Rules File Format - grzesiek-galezowski/nscan GitHub Wiki
-
Rules file syntax:
- Independent of rule for projects
- Has correct namespaces rule for projects
- Has no circular usings rule for projects
- Has methods decorated with attributes rule for projects
- Has property rule for projects
- Has target framework rule for projects (Deprecated - use the hasProperty rule)
- Specifying exclusions
The rules file can be placed anywhere and called anyhow. The only requirements for the file are:
-
The path to the rule file must be passed to NScan.
-
The file must be written according to syntax specified below.
Each rule is described by a single line using a format depending on rule type:
<<project assembly name glob>> independentOf <<dependency type>>:<<dependency name glob>>
where:
-
<<project assembly name glob>> is a depending project assembly name pattern in glob format
-
<<dependency type>> is either "project", "assembly" or "package"
-
<<dependency name glob>> is a dependency name pattern in glob format
Two things worth remembering:
-
The glob matching is case-sensitive.
-
Splitting a single rule definition into several lines is not supported, so you can’t write something like:
*Domain*
independentOf
project:*Persistence*
"Every project with the word Domain in its assembly name must not depend on any project with the word Persistence in its assembly name":
*Domain* independentOf project:*Persistence*
It is important to note that the dependency pattern describes project’s assembly name, not project name.
"Every project with the word Domain in its assembly name must not depend on any package with the word xunit in its package name":
*Domain* independentOf package:*xunit*
NScan supports a rule for checking whether all project files contain correct namespace. This rule can be enables by writing:
<<project assembly name glob>> hasCorrectNamespaces
To apply this rule to all projects in a solution, simply write:
* hasCorrectNamespaces
This rule allows to check whether there are circular dependencies between namespaces in a scope of a project. Several things have to be pointed in using this rule:
-
It is highly advised to use this rule together with hasCorrectNamespaces, otherwise the results will be hard to interpret or make sense of.
-
The rule assumes a convention where there is a single namespace per file and that all usings in this file are dependencies of that namespace. This is important, as C# by itself does not enforce any such convention.
-
As C# does not mandate using parent namespace from a child namespace, circular references between those will typically not be found by NScan.
This rule can be enables by writing:
<<project assembly name glob>> hasNoCircularUsings
To apply this rule to all projects in a solution, simply write:
* hasNoCircularUsings
Note that while the rule can be applied to many projects, it scopes the cycle detection only to the processed projects (i.e. it does not find any cycles across projects).
NScan supports a rule for checking whether specified methods are decorated with attributes. This can be useful to e.g. check whether all test methods are decorated with test runner attributes. The syntax is:
<<project assembly name glob>> hasAttributesOn <<class inclusion glob>>:<<method inclusion glob>>
To apply this rule to all projects in a solution, simply use *
in place of <<project assembly name glob>>
.
Example:
*Tests hasAttributesOn *Tests:Test*
Which says: In every project ending with the word "Test", in every class which name ends with "Tests", each method which name starts with "Test" must be decorated with an attribute.
You can enforce your csproj property value (a member of a property group) using the following syntax:
<<project assembly name glob>> hasProperty <<property name>>:<<property value>>
Example:
* hasProperty Nullable:enable
* hasProperty WarningsAsErrors:nullable
You can enforce target framework (useful e.g. if your solution is a collection of standalone projects):
<<project assembly name glob>> hasTargetFramework <<framework moniker>>
For a list of monikers, see https://docs.microsoft.com/en-us/dotnet/standard/frameworks
Example:
* except *Tests hasTargetFramework netstandard.2.1
*Tests hasTargetFramework net5.0
NScan syntax also supports pattern exclusions in addition to the <<project assembly name glob>>. The syntax is:
<<project assembly name glob>> except <<excluded assembly name glob>> independentOf <<dependency type>>:<<dependency name glob>>
The exclusion syntax allows saying things like: "I want all except test projects independent of composition root project". In NScan syntax, this can be written as:
* except *Tests* independentOf *CompositionRoot*