Nota's code style, StyleCop and code analysis rules, as one package. Install it and a project gets the same rules as every other project here, enforced at build time rather than agreed in a wiki.
The package lives on Nota's GitHub Packages feed, so a NuGet.config needs the source:
<add key="notalib" value="https://nuget.pkg.github.com/Notalib/index.json" />Then reference it once per project, or once in a Directory.Build.props for a whole solution:
<PackageReference Include="Nota.CodeAnalysis" Version="2.2.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>PrivateAssets matters: without it the rules flow to anything that references your library, and
whether your code uses var is nobody else's build error.
Four properties are switched on, in build/Nota.CodeAnalysis.props:
| Property | Why |
|---|---|
EnforceCodeStyleInBuild |
without it the IDE#### rules never run, whatever their severity says |
EnableNETAnalyzers |
the CA#### rules |
GenerateDocumentationFile |
load-bearing, and not obviously so: severity is a filter, and this is the switch that produces the diagnostics being filtered. Remove it and IDE0005 silently stops reporting |
ImplicitUsings |
disabled - usings are stated, not inherited |
Four analyser packages come as dependencies: StyleCop.Analyzers, Microsoft.VisualStudio.Threading.Analyzers,
SerilogAnalyzer, and UsingLayoutAnalyser. Around 400 rule severities are set in
content/Nota.CodeAnalysis.globalconfig.
Nothing is required. The one setting most likely to need changing is which namespaces count as
yours, for the using layout - it defaults to Nota, which is right for almost everything here.
If your code is called something else, say so in your own .editorconfig:
[*.cs]
usinglayout.first_party_prefixes = Contoso, FabrikamComma-separated for several roots. Getting it wrong is not fatal - your namespaces are simply sorted as one more vendor rather than last.
Most of this is unsurprising. These are the ones that catch people out:
IDE0008is an error.varis banned outright; write the type.VSTHRD100is an error. Noasync void.NOTA0001fails the build on a source file that is not valid UTF-8. It is an MSBuild task rather than an analyser because it has to see the bytes: a file saved as Windows-1252 compiles with no warning at all and reaches the assembly as U+FFFD replacement characters. UTF-16 with a byte order mark passes, since the compiler reads it correctly - and such a file must keep its BOM, which is the only record of its encoding.UA1000andUA1001enforce the using layout: System, then third party, then yours, as blocks separated by a blank line, one run per vendor. An existing repository is converted in one pass withdotnet format analyzers --diagnostics UA1000 UA1001 --severity warn.
Any rule can be overridden in the consuming repository's own .editorconfig. An .editorconfig
entry beats a global analyzer config entry for the same key, so nothing this package sets is a
decision you are stuck with:
dotnet_diagnostic.IDE0008.severity = suggestionThe encoding check is a build task rather than a diagnostic, so it has its own switch:
<NotaValidateSourceEncoding>false</NotaValidateSourceEncoding>The product here is configuration, and configuration fails silently: a rule that cannot report looks
exactly like a rule being obeyed, because the build is quiet either way. dotnet_diagnostic.CS8019
asked for unused usings to be reported and reported nothing for years, with forty-five of them
collected behind it in one consuming solution.
Nota.CodeAnalysis.Verification exists to make that noisy. It is a consumer built against files that
break the rules on purpose, and a script that fails if any of them stayed quiet. Read its README
before changing rules.
./Nota.CodeAnalysis.Verification/verify.sh # the rules report
./Nota.CodeAnalysis.Verification/verify-encoding.sh # source is valid UTF-8Both run on pull requests as well as on main.
Releases are cut by tagging:
git tag -a v2.3.0 -m "Nota.CodeAnalysis 2.3.0" && git push origin v2.3.0The tag is the version, so nothing in the repository can disagree with what shipped. <Version> in
the csproj is only a local default, for anyone packing by hand.
Merging to main builds and verifies but does not publish, and neither do pull requests - releasing
is a separate act from merging.