Configuration¶
Configuration is optional. This is all of it.
defaults:
unexported: private # package | private
rules:
naming:
qualify: never # always | never | ondemand
exported: false # true | false
vocabulary:
mouse: [wheel]
boundary: on # off | on
surplus: loose # off | loose | strict
filter:
only: [] # nothing outside these, when set
omit:
- "**/mock_*.go" # and not these
baseline: .declscope-baseline.yaml
| Key | Values | Default | Effect |
|---|---|---|---|
defaults.unexported |
package, private |
private |
Scope of a declaration that carries no directive and inherits none |
rules.naming.qualify |
always, never, ondemand |
never |
When a name must carry its namespace. See the naming rule |
rules.naming.exported |
true, false |
false |
Whether the naming rule also reaches exported declarations. The rename is never offered there |
rules.naming.vocabulary |
Namespace to a list of words | None | Extra words that carry a namespace. See what carries a namespace |
rules.boundary |
off, on |
on |
Whether the boundary rule reports. See reach without a boundary |
rules.surplus |
off, loose, strict |
loose |
How much the surplus rule reports. See strict |
filter.only |
Path globs | None | When set, no file outside them is read. Empty places no restriction |
filter.omit |
Path globs | None | Files taken back out, whether or not only let them through |
baseline |
A path relative to the config file | The nearest .declscope-baseline.yaml |
The baseline to consult |
- The file is
.declscope.yamlor.declscope.yml. An empty one changes nothing. -confignames one file, and reads no other.- An unknown key is an error, and so is a value a key does not accept. The message names what the section does take, so a typo never leaves a rule at its default in silence.
defaults takes only unexported, because an exported declaration has no scope to default.
How two config files compose¶
Every .declscope.yaml between the analyzed package and the module root is read, outermost first. A nearer file does not replace the one above it. Each key composes on its own.
| Key | Down the chain |
|---|---|
defaults.*, rules.* except vocabulary, baseline |
The nearest file that states the key wins. A key no file states takes the built-in default |
rules.naming.vocabulary |
Merged per namespace. The nearer file wins the namespaces it states |
filter.only |
Intersected. A file is read when it matches every stating file's list |
filter.omit |
Unioned. A file matching any level's list is not read |
Important
A config file can only ever shrink what is read. An omit written at the root holds everywhere below it, and no nested file can undo it. filter has no negation, so nothing like .gitignore's ! can put a path back.
The filter rule¶
filter decides which files are read at all. A file matches a list when it matches any pattern in it.
| Written | Read |
|---|---|
| Neither | Every file |
only alone |
Nothing outside the patterns |
omit alone |
Everything except the patterns |
| Both | What only admits, minus what omit names |
An empty only places no restriction, which is why a repository with no config is read whole.
A pattern is read against the directory of the config file that states it. Anchoring follows the rules of .gitignore.
| Pattern | Matches |
|---|---|
gen.go |
A file of that name at any depth |
/gen.go |
The one beside this config file |
gen/** |
That directory beside this config file, and no other |
**/gen/** |
That directory at any depth |
*, ? |
Within one path segment |
Why patterns are anchored where they are
- A pattern holding a separator is anchored whether or not it starts with one, so
/gen/**andgen/**are the same rule. The leading/matters only on a bare name, which would otherwise match at any depth. - The same line means different things in different files.
internal/tui/**in the root config reachesinternal/tui. Ininternal/.declscope.yamlit reachesinternal/internal/tui. - A
..in a pattern is an error. A pattern cannot leave its own directory. - The origin is the config file's directory, not the module root. A config governs only the packages below it. A pattern anchored higher than that could only name files that never read this config.
One report comes from the configuration rather than from the code. It fires when a file's only matches files, but an only above it removes them all, so the package is read as empty.
sub/a.go:1:1: filter.only stated in /repo/sub matches 1 file(s) here, but an only above it removes them all, so this package is read as empty
The report is that narrow on purpose. A package that reads nothing is usually the point, as with a root only naming one subtree, or an omit naming a directory.