AGENTS.md
Build & Test Commands
# Build
dotnet build dotnet-project-file-analyzers.slnx -c Release
# Test (must filter out Generators category — CI does this too)
dotnet test dotnet-project-file-analyzers.slnx -c Release --no-build --filter TestCategory!=Generators
# Pack (version passed via -p:PackageVersion=)
dotnet pack src/DotNetProjectFile.Analyzers/DotNetProjectFile.Analyzers.csproj -c Release -p:PackageVersion=1.15.2
No separate lint/typecheck step — EnforceCodeStyleInBuild=true in props/common.props means code style rules run during dotnet build. Fix build warnings to satisfy style.
SDK & Toolchain
- .NET SDK 10.0.300 pinned in
global.json(rollForward: latestPatch). - Solution format:
dotnet-project-file-analyzers.slnx(new XML-based SLNX, not legacy .sln). - C# 14.0, nullable enabled,
netstandard2.0for the analyzer itself,net10.0for tests.
Architecture
This is a Roslyn analyzer package (160+ diagnostics) for .NET project files (.csproj, .vbproj, .resx, NuGet.config, .editorconfig, .slnx, INI).
| Path | Purpose | |
|---|---|---|
.net.csproj |
SDK | Allows DotNetProjectFile.Analyzers to run Roslyn Analyzers on MSBuild files. Ignore it. |
src/DotNetProjectFile.Analyzers/ |
Main analyzer library (netstandard2.0) |
|
src/DotNetProjectFile.RuleCatalog/ |
Rule metadata collection & NuGet package introspection (net10.0) |
|
src/.../Analyzers/ |
Analyzer implementations (MsBuild, Resx, Ini, NuGetConfig, Slnx, Generic) | |
src/.../Rule.cs (+ partials) |
All DiagnosticDescriptor definitions |
|
src/.../build/ |
MSBuild .props/.targets shipped in the NuGet package |
|
specs/Specs/ |
Unit tests (NUnit) | |
specs/TestData/ |
Shared test data (embedded files) | |
specs/Bench/ |
Benchmarks (BenchmarkDotNet) | |
projects/ |
120+ fixture projects used as test input data | |
props/common.props |
Shared MSBuild properties for all projects |
Rule numbering: Proj00xx general, Proj02xx packaging, Proj03xx NuGet config, Proj05xx licensing, Proj08xx CPM, Proj17xx formatting, Proj2xxx RESX, Proj3xxx generic, Proj4xxx INI/EditorConfig, Proj5xxx SLNX.
Testing Quirks
- Tests use NUnit 4 + Verify (snapshot testing) + CodeAnalysis.TestTools.
- Verify snapshots:
.verified.txtis the baseline;.received.txtis generated on failure. Accept by replacing verified with received. specs/TestData/is a separate project embedding files fromspecs/TestData/Files/.- Fixture projects in
projects/are linked into the Specs project as<None>items. - Windows-specific tests use
DefineConstants: Is_Windowsconditional compilation. - CI always runs with
--filter TestCategory!=Generators.
Code Style
.editorconfig: 4-space indent for.cs; 2-space indent for.csproj/.props/.targets/.slnx.- Expression-bodied members preferred for methods, properties, constructors, accessors, indexers, operators.
- Multiple Roslyn analyzer packages enforce style: StyleCop, SonarAnalyzer, Qowaiv, AsyncFixer.
RestoreLockedModeenforced in CI — after changing dependencies, rundotnet restore --force-evaluateto updatepackages.lock.json.
CI
- Build workflow (
build-publish.yml): build → test (withTestCategory!=Generatorsfilter) → pack on tag → publish to NuGet.org. - Dependabot: weekly NuGet + GitHub Actions updates.
- Spell/grammar checks on
docs/**via LanguageTool and Misspell reviewdog workflows.
Adding a New Diagnostic
- Add a
DiagnosticDescriptorproperty inRule.cs(or the relevant partial:Rule.Ini.cs,Rule.NuGet.cs,Rule.RESX.cs,Rule.SLNX.cs). - Implement the analyzer in the appropriate
Analyzers/subdirectory. - Add test fixture projects under
projects/if needed. - Add tests under
specs/Specs/matching the source structure. - Update
docs/with the new rule documentation:- Identify the category of the rule (e.g.,
SLNX,MSBuild,Packaging,Publishing,Test projects,Licensing,Central Package Management,Resource file rules,Generic,NuGet configuration,INI,.globalconfig,.editorconfig,JSON,Analyzers,Other,Design,Formatting). - Create
docs/rules/ProjXXXX.mdwhereProjXXXXis the rule ID:- Use the exact Jekyll front matter template:
--- parent: <CategoryName> ancestor: Rules permalink: /rules/ProjXXXX --- - Use a title of the format
# ProjXXXX: Rule Name. - Provide a clear explanation of why the rule exists and how to address it.
- Include
## Non-compliantand## Compliantcode blocks showing examples of the bad practice and its fix.
- Use the exact Jekyll front matter template:
- Update
docs/README.md:- Locate the correct category header in the document.
- Add the new rule link in sequential/numerical order:
* [**ProjXXXX** Rule Name](rules/ProjXXXX.md)
- Update
src/DotNetProjectFile.Analyzers/README.md:- Locate the correct category header in the document.
- Add the new rule link in sequential/numerical order:
* [**ProjXXXX** Rule Name](https://dotnet-project-file-analyzers.github.io/rules/ProjXXXX.html)
- Identify the category of the rule (e.g.,
Gotchas
- Do not modify
.net.csproj: This file is exclusively for running Roslyn Analyzers. Agents must completely ignore and skip this file during development. - Do not modify or read
src/DotNetProjectFile.RuleCatalog/Data/DiagnosticCollection.json: This file is huge, and is data about analyzers. - Do not commit, any change, or check the GIT history of this repo unless explictly asked.
- Only run related tests, and never if you only changed documentation.