This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
NsDepCop is a Roslyn-based static analysis tool for C# that enforces namespace and assembly dependency rules. It ships as a NuGet package that integrates into the build process, reporting violations as compiler warnings/errors.
Solution-level dotnet build/test fails due to a self-referencing NuGet cycle (NsDepCop.Analyzer depends on the NsDepCop NuGet package, which is produced by NsDepCop.NuGet in the same solution). CI (GitHub Actions) avoids this by building/testing/packing the individual projects rather than the solution; VS IDE handles it internally. From the command line, target individual projects:
# Build the analyzer (restores and builds dependencies automatically)
dotnet build source/NsDepCop.Analyzer/NsDepCop.Analyzer.csproj
# Run unit tests
dotnet test source/NsDepCop.Test/NsDepCop.Test.csproj
# Run source-based integration tests
dotnet test source/NsDepCop.SourceTest/NsDepCop.SourceTest.csproj
# Run a single test by name
dotnet test source/NsDepCop.Test/NsDepCop.Test.csproj --filter "FullyQualifiedName~TestMethodName"Prerequisites: Visual Studio 2022 with Visual Studio extension development workload (includes the .NET SDK).
All source code lives under source/. The solution is source/NsDepCop.sln.
| Project | Target | Purpose |
|---|---|---|
NsDepCop.Analyzer |
netstandard2.0 | Core analyzer — the main product code |
NsDepCop.Test |
net8.0 | Unit tests (xUnit, FluentAssertions, Moq) |
NsDepCop.SourceTest |
net8.0 | Integration tests — verifies analyzer against C# source files |
NsDepCop.NuGet |
netstandard2.0 | NuGet package packaging |
NsDepCop.Benchmarks |
— | Performance benchmarks |
NsDepCop.Vsix |
— | Visual Studio Extension wrapper |
Root namespace: Codartis.NsDepCop. Internal module dependencies are enforced by config.nsdepcop in the project itself.
- RoslynAnalyzer/ — Entry point.
NsDepCopAnalyzerextends RoslynDiagnosticAnalyzer, registered forIdentifierName,GenericName, andDefaultLiteralExpressionsyntax kinds. Wires together config and analysis. Must only depend on other modules via interfaces (not.Implementationnamespaces). - Config/ — XML config file parsing and rule model.
DependencyRule,Domain,WildcardDomain,RegexDomainrepresent rules.MultiLevelXmlFileConfigProviderhandles config inheritance (project → parent directories). Factory pattern separates creation from implementation. - Analysis/ — Dependency validation logic.
DependencyAnalyzerorchestrates type-level and assembly-level validation.TypeDependencyValidatorchecks namespace rules;AssemblyDependencyValidatorchecks assembly rules. - ParserAdapter/Roslyn/ — Extracts type dependencies from Roslyn syntax trees.
- Util/ — Shared helpers.
RoslynAnalyzer → Config (interfaces only), Analysis (interfaces only), ParserAdapter
ParserAdapter → Analysis
Analysis → Config
Config.Factory → Config.Implementation
The RoslynAnalyzer layer is explicitly disallowed from depending on *.Implementation namespaces.
Unit tests (NsDepCop.Test): Standard xUnit tests for config parsing, validation logic, and analyzer behavior. Test data files (.nsdepcop configs) are in subdirectories named after their test class, copied to output via CopyToOutputDirectory.
Source tests (NsDepCop.SourceTest): Each test case is a folder containing a .cs source file and a config.nsdepcop file. The .cs files are excluded from compilation (<Compile Remove>) and instead copied to output as test data. Tests verify the analyzer produces expected diagnostics for various C# syntax patterns (C# 6, 7, 7.1, 7.2, 7.3, top-level statements).
The project references the latest published version of its own NuGet package (the NsDepCop PackageReference in NsDepCop.Analyzer.csproj) and enforces dependency rules on its own code. After each release is published to NuGet, the reference is bumped to the new version in a separate "Dogfooding vX.Y.Z" commit. Directory.Build.targets contains a workaround (AvoidCycleErrorOnSelfReference) that renames PackageId to NsDepCop_temp during build to break the cycle, restoring it before pack. Solution-level dotnet restore / msbuild /t:Restore still detect the cycle; only building the individual projects (CI) and VS IDE's internal restore avoid the error. This is why command-line builds must target individual projects rather than the solution.
TreatWarningsAsErrorsis enabled on all projects- Root namespace is
Codartis.NsDepCop(with project-specific suffixes like.Test) config.nsdepcopis the XML configuration file format — both the product config and test fixtures- CI runs on GitHub Actions (
.github/workflows/build.yml,ubuntu-latest), Release configuration, using per-projectdotnet test/dotnet pack(not a solution build, to avoid the self-reference cycle) - Version is managed via MSBuild properties:
VersionPrefixinsource/Directory.Build.propsis the single source of truth (with sharedCompany/Product/Copyright); CI sets aVersionSuffixprerelease tag for non-release builds.AssemblyVersionis pinned stable per major.
Diagnostic IDs: NSDEPCOP01 (illegal namespace dependency), NSDEPCOP02 (too many issues), NSDEPCOP03 (no config), NSDEPCOP04 (config disabled), NSDEPCOP05 (config error), NSDEPCOP06 (tool disabled), NSDEPCOP07 (illegal assembly dependency). Definitions are in DiagnosticDefinitions.cs.