Roslyn analysers for enforcing architectural rules in C# projects.
dotnet add package ArchonAnalysersArchonAnalysers provides Roslyn analysers that enforce namespace-based architectural rules:
Ensures that all types within namespaces containing .Internal are properly restricted with internal or private access modifiers. This prevents accidental exposure of internal implementation details.
- Severity: Error
- Namespace Pattern:
*.Internal*(e.g.,MyApp.Internal,MyApp.Services.Internal) - Allowed Modifiers:
internal,private,private protected - Special Handling: Nested types are exempt if their containing type is already
internalorprivate
Ensures that top-level types within namespaces containing .Public are appropriately exposed with public or protected access modifiers. This enforces discoverability of your public API surface.
- Severity: Warning
- Namespace Pattern:
*.Public*(e.g.,MyApp.Public,MyApp.Api.Public) - Required Modifiers:
public,protected,protected internal - Scope: Only applies to top-level types (nested types are exempt)
Prevents specified projects from referencing forbidden assemblies at compile time, enforcing architectural layering rules.
- Severity: Error
- Configuration:
archon_003.forbidden_references(directional rules:Source->Target) - Matching: Simple assembly name, case-insensitive, .dll extension optional
- Scope: Global configuration in single EditorConfig
ARCHON003 provides a code fix that automatically removes forbidden <ProjectReference> entries from .csproj files.
Limitations:
- Only works for SDK-style projects (
.csprojwith<Project Sdk="...">) - Only removes
<ProjectReference>elements (not<PackageReference>or<Reference>) - Assumes project name matches assembly name
- Fix available from Error List window (not in-editor, due to compilation-level diagnostics)
- Requires project reload in IDE after applying fix
To use: Right-click the diagnostic in the Error List and select "Remove project reference to [AssemblyName]"
Once installed, the analysers will automatically run during compilation and highlight violations in your IDE.
Both analysers support customising which namespace patterns trigger the rules via .editorconfig:
[*.cs]
# Single namespace slug (default: Internal)
archon_001.internal_namespace_slugs = Internal
# Multiple namespace slugs
archon_001.internal_namespace_slugs = Internal, Private, Hidden, ImplTypes in namespaces matching *.Internal.*, *.Private.*, *.Hidden.*, or *.Impl.* must be internal, private, or private protected.
[*.cs]
# Single namespace slug (default: Public)
archon_002.public_namespace_slugs = Public
# Multiple namespace slugs
archon_002.public_namespace_slugs = Public, Api, Exposed, ContractTop-level types in namespaces matching *.Public.*, *.Api.*, *.Exposed.*, or *.Contract.* must be public, protected, or protected internal.
Notes:
- Slugs are comma-separated with automatic whitespace trimming
- Empty or missing configuration uses defaults ("Internal" for ARCHON001, "Public" for ARCHON002)
- Slugs match complete namespace segments (e.g., "Internal" matches
App.Internal.Servicesbut notApp.InternalStuff) - Special regex characters are automatically escaped
Configure directional rules in a single global EditorConfig file:
# Single global .editorconfig at solution root
[*.cs]
archon_003.forbidden_references = Contracts->Domain, Contracts->Application, Domain->ApplicationThis enforces:
- Contracts → Domain: ❌ Forbidden
- Contracts → Application: ❌ Forbidden
- Domain → Application: ❌ Forbidden
- Domain → Contracts: ✅ Allowed
- Application → Domain: ✅ Allowed
- Application → Contracts: ✅ Allowed
Directional format:
archon_003.forbidden_references = Source->Target, AnotherSource->AnotherTargetNotes:
- Assembly names are matched without version, culture, or public key token
- Matching is case-insensitive for both source and target
- The
.dllextension is optional in configuration - Whitespace around
->is automatically trimmed - Empty or missing configuration means no restrictions
- Rules must use the
Source->Targetformat
Configure severity levels in your .editorconfig:
[*.cs]
# Enforce internal types in configured namespaces (default: error)
dotnet_diagnostic.ARCHON001.severity = error
# Enforce public types in configured namespaces (default: warning)
dotnet_diagnostic.ARCHON002.severity = warning
# Enforce forbidden assembly references (default: error)
dotnet_diagnostic.ARCHON003.severity = errornamespace MyApp.Internal
{
// ✅ Correct - internal type in .Internal namespace
internal class InternalService { }
// ❌ ARCHON001 violation - public type in .Internal namespace
public class PublicService { }
}
namespace MyApp.Public
{
// ✅ Correct - public type in .Public namespace
public class PublicApi { }
// ❌ ARCHON002 violation - internal type in .Public namespace
internal class InternalApi { }
}- .NET 10.0 SDK or later
- (Optional)
actfor local CI/CD testing
cd src
dotnet restore Archon.slnx
dotnet build Archon.slnxcd src/ArchonAnalysers.Tests.Unit/bin/Release/net10.0
dotnet ArchonAnalysers.Tests.Unit.dllTest the CI pipeline locally:
./scripts/test-ci.shTest the CD pipeline locally:
./scripts/test-cd.shThis project is licensed under the MIT Licence - see the LICENSE file for details.
Contributions are welcome! Please feel free to submit a Pull Request.