FileConstraintScope
A DSL receiver a constraint can be written on: a role block, and every block inside a layout { }.
Where it is written decides what it covers. Directly on a role it covers the union of every layout { } that role declares; inside a directory block it covers that block's own subtree and nothing else — or, with scope = FileConstraintRange.DirectOnly, only the files that block declares directly, leaving out what its nested directories declare. That is the whole of the scoping rule, and it is why this is an interface shared by the two receivers rather than one function on each of them.
ArchitectureScope and GroupScope deliberately do not get it: a group holds roles, not files, so there would be no set of files for a constraint written there to be about.
Example 1: constrain one directory, and the whole role
"UseCase" {
fileConstraint("has an invoke function") { subject -> /* every place below */emptyList() }
layout {
"core/domain" {
fileConstraint("is usable from outside") { subject -> /* core/domain only */emptyList() }
mainSourceSet / kotlin / "useCase" / "*UseCase".ktFile()
}
}
}Example 2: a parent directory whose rule does not reach its children
"Util" {
layout {
"util" {
fileConstraint("uses the stdlib only", scope = FileConstraintRange.DirectOnly) { subject -> /* util/ only */emptyList() }
"*".ktFile()
"ksp" { "*".ktFile() } // not covered: util/ksp/ may use the KSP API
}
}
}Inheritors
Functions
Declares a constraint over the files the block around it matched.