Herimanitra.Architecture.Analyzer
1.1.0
dotnet add package Herimanitra.Architecture.Analyzer --version 1.1.0
NuGet\Install-Package Herimanitra.Architecture.Analyzer -Version 1.1.0
<PackageReference Include="Herimanitra.Architecture.Analyzer" Version="1.1.0" />
<PackageVersion Include="Herimanitra.Architecture.Analyzer" Version="1.1.0" />
<PackageReference Include="Herimanitra.Architecture.Analyzer" />
paket add Herimanitra.Architecture.Analyzer --version 1.1.0
#r "nuget: Herimanitra.Architecture.Analyzer, 1.1.0"
#:package Herimanitra.Architecture.Analyzer@1.1.0
#addin nuget:?package=Herimanitra.Architecture.Analyzer&version=1.1.0
#tool nuget:?package=Herimanitra.Architecture.Analyzer&version=1.1.0
Herimanitra.Architecture.Analyzer
Roslyn analyzers for enforcing architecture, naming conventions as well as limiting LOCs generated by AI coding agents in .NET solutions.
Installation
dotnet add package Herimanitra.Architecture.Analyzer
Adding the package drops a default .editorconfig at the consumer project root (via contentFiles). It ships sensible defaults; the sections below explain how to override each rule from your own .editorconfig.
Rules at a glance
| ID | Rule | Configured by |
|---|---|---|
ARCH001 |
Model type is placed in the folder expected by its suffix | architecture_analyzer.model_suffix / architecture_analyzer.model_folder / architecture_analyzer.model_conventions |
ARCH002 |
The file name matches the type name | (no configuration) |
ARCH003 |
Only whitelisted suffixes are allowed inside a given folder / a module carries provider contracts | architecture_analyzer.model_folder_allowed_suffixes |
ARCH004 |
A module project does not implement its own provider interfaces | (auto — a project counts as a module when its assembly name ends with .Module) |
ARCH005 |
DTO properties are alphabetically ordered (identifier-like properties excluded) | (no configuration) |
ARCH006 |
Class body stays within its LOC ceiling | architecture_analyzer.loc_max_lines_per_class |
ARCH007 |
Method body stays within its LOC ceiling | architecture_analyzer.loc_max_lines_per_method |
ARCH008 |
Solution respects the global "% of code added per prompt" budget | architecture_analyzer.loc_budget_percent_global + shipped MSBuild target |
ARCH009 |
Project respects the per-project "% of code added per prompt" budget | architecture_analyzer.loc_budget_percent_project + shipped MSBuild target |
ARCH010 |
Project contains the folder(s) required by its own convention (e.g. HR.Infrastructure must have Models/Entities) |
architecture_analyzer.required_project_folders |
ARCH011 |
Class methods are alphabetically ordered | (no configuration) |
Configuring the rules
Overriding severity (works for every rule)
Every diagnostic is emitted as an error by default. Downgrade or silence one from any .editorconfig:
[*.cs]
# error | warning | suggestion | silent | none
dotnet_diagnostic.ARCH006.severity = warning
dotnet_diagnostic.ARCH008.severity = suggestion
dotnet_diagnostic.ARCH009.severity = none
Localization: the analyzer ships a French neutral catalog and an English satellite (en/Architecture.Analyzer.resources.dll). The message rendered follows Roslyn's UI culture — no .editorconfig knob is needed.
ARCH001 — Model type in the expected folder
Both suffix and folder can be tuned. Folder separators accept /, \, or > (> is handy in .editorconfig where / can be significant).
Single convention (default: BusinessModel → Models/Business)
[*.cs]
architecture_analyzer.model_suffix = ViewModel
architecture_analyzer.model_folder = Presentation/ViewModels
Multiple conventions in one line — this key, when present and non-empty, replaces the two above:
[*.cs]
architecture_analyzer.model_conventions = BusinessModel=Models/Business;DataModel=Models/Data;ViewModel=Presentation/ViewModels
The matching convention is the one with the longest suffix that matches the type name (so CustomerBusinessModel matches BusinessModel, not a shorter Model).
ARCH002 — File name matches type name
No configuration. public class CustomerBusinessModel must live in CustomerBusinessModel.cs. Fix by renaming either the file or the type.
ARCH003 — Whitelist of suffixes per folder
Restrict which suffixes are allowed inside specific folders. Same folder separator flexibility as ARCH001; commas separate multiple suffixes for the same folder; semicolons separate the folder rules.
[*.cs]
architecture_analyzer.model_folder_allowed_suffixes = \
Models/Business=BusinessModel;\
Models/Data=DataModel,DataProvider;\
Presentation/ViewModels=ViewModel
With the config above, a CustomerDataModel under Models/Business/ reports ARCH003 because Models/Business only allows BusinessModel. When several folder rules match, the deepest wins (so Models/Business/Sub overrides Models). Types under a folder that has no rule are ignored.
Note: ARCH003 is reused by the ModuleProviderAnalyzer for "module projects must ship at least one provider interface under Models/Data/Providers/" — no .editorconfig needed there (see next section).
ARCH004 — Providers must not be implemented inside a module project
Fires automatically when:
- the compiled project's assembly name ends with
.Module, and - a class in that project implements an interface declared under
Models/Data/Providers/of the same module.
To fix, either move the implementation to an infrastructure project outside the module, or remove the .Module suffix from the project.
ARCH005 — DTO properties ordered alphabetically
Applies to types whose name ends with BusinessModel, DataModel, or ViewModel. Identifier-like properties (containing Id) are ignored in the ordering check. No configuration; just reorder the properties.
ARCH011 — Methods ordered alphabetically
Applies to every class. Methods must be declared in alphabetical order (ordinal comparison). No configuration; just reorder the methods.
ARCH006 / ARCH007 — Class / method size ceiling
Both default to 20 lines. Override them per project or per folder:
# Project-wide
[*.cs]
architecture_analyzer.loc_max_lines_per_class = 60
architecture_analyzer.loc_max_lines_per_method = 25
# Loosen a specific folder that hosts generated code
[src/Generated/**.cs]
architecture_analyzer.loc_max_lines_per_class = 200
architecture_analyzer.loc_max_lines_per_method = 200
Set the value to a positive integer; anything else falls back to the default (20).
ARCH008 / ARCH009 — LOC budget "% of code added since HEAD"
These two rules cap the cumulative lines of code added since HEAD — per project (ARCH009) and per solution (ARCH008) — as a percentage of the existing tracked C# code base. The percentages are read from .editorconfig; the actual line counts are computed by the MSBuild target shipped with the package (build/Architecture.Analyzer.targets), which shells out to git at build time and forwards the values through CompilerVisibleProperty.
Enable the budgets in .editorconfig:
[*.cs]
# Per-project budget: any project that grows by more than 3% of its current size errors out.
architecture_analyzer.loc_budget_percent_project = 3
# Solution-wide budget: any single prompt that grows the whole solution by more than 2% errors out.
architecture_analyzer.loc_budget_percent_global = 2
Both are integers. Omitting a key disables the corresponding rule. The budget itself is ceil(baseline * percent / 100), so a 1000-line project with a 3% budget rejects any change that adds more than 30 lines.
Prerequisites for the MSBuild target:
gitmust be onPATHat build time (the target no-ops silently if it isn't, so budgets stay quiet in odd environments).- The build must run from inside a git working tree.
Manual override (useful in tests or CI without git): feed the four inputs directly as MSBuild properties. They're already declared CompilerVisibleProperty, so setting them from the command line or from Directory.Build.props is enough to bypass the git task:
dotnet build /p:ArchitectureLocProjectBaselineLines=1000 \
/p:ArchitectureLocProjectAddedLines=15 \
/p:ArchitectureLocSolutionBaselineLines=50000 \
/p:ArchitectureLocSolutionAddedLines=120
ARCH010 — Required folder per project
Enforce that a given project (matched by assembly name) contains at least one file under a specific folder. Same folder separator flexibility as ARCH001; commas separate multiple required folders for the same project; semicolons separate the project rules.
[*.cs]
architecture_analyzer.required_project_folders = \
HR.Infrastructure=Models/Entities;\
HR.Module=Models/Data,Presentation/ViewModels
With the config above, the HR.Infrastructure project reports ARCH010 (once, at compilation end) unless at least one .cs file lives under Models/Entities. Projects with no matching rule are ignored.
Full worked example
A typical monolith .editorconfig layered on top of the shipped defaults:
root = true
[*.cs]
# ARCH001: model conventions used by this codebase.
architecture_analyzer.model_conventions = \
BusinessModel=Models/Business;\
DataModel=Models/Data;\
ViewModel=Presentation/ViewModels
# ARCH003: guard each folder against foreign suffixes.
architecture_analyzer.model_folder_allowed_suffixes = \
Models/Business=BusinessModel;\
Models/Data=DataModel;\
Presentation/ViewModels=ViewModel
# ARCH006/ARCH007: keep files small so prompt-diffs stay reviewable.
architecture_analyzer.loc_max_lines_per_class = 60
architecture_analyzer.loc_max_lines_per_method = 25
# ARCH008/ARCH009: hard cap on code volume added per prompt.
architecture_analyzer.loc_budget_percent_project = 3
architecture_analyzer.loc_budget_percent_global = 2
# Downgrade a rule for legacy folders.
[legacy/**.cs]
dotnet_diagnostic.ARCH005.severity = suggestion
dotnet_diagnostic.ARCH006.severity = none
License
See LICENSE.txt.
Learn more about Target Frameworks and .NET Standard.
-
.NETStandard 2.0
- No dependencies.
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.