Repository navigation
Releases: rodri-oliveira-dev/complexity-analyzers
Release list
v1.6.0
Complexity Analyzers v1.6.0 — Explainable Analysis, Regression Detection & MCP Integration
Version 1.6.0 introduces Complexity Analysis vNext, a significant expansion of Complexity Analyzers beyond traditional Roslyn diagnostics.
This release focuses on making algorithmic complexity analysis more reliable, explainable, reproducible, and suitable for integration into development workflows, CI pipelines, and AI-assisted engineering tools.
The existing Roslyn analyzer remains backward compatible, while new capabilities are delivered through a separate .NET CLI and a local MCP server.
Highlights
1. More Reliable Complexity Analysis
Improved static analysis provides more conservative and explicit complexity estimates.
Expanded analysis of loops, recursion, collections, and LINQ operations.
Improved handling of loop-bound mutations and unstable conditions.
Recognition of supported deferred LINQ execution and collection operation costs.
Explicit complexity guarantees and assumptions, including worst-case, expected, amortized, and conditional estimates.
Conservative
Unknownclassification when available evidence is insufficient.
Why it matters: Complexity estimates should reflect what static analysis can actually establish, rather than presenting uncertain conclusions as facts.
2. Explainable Complexity Results
Complexity analysis now supports structured evidence explaining how an estimate was derived.
Deterministic evidence traces with source locations.
Explicit assumptions and uncertainty reasons.
Bounded evidence collection to preserve analysis performance.
Optional evidence exposure through CLI JSON reports.
Why it matters: Developers can investigate why a method received a particular complexity classification instead of relying on an opaque diagnostic.
3. Complexity Regression Detection
This release introduces deterministic snapshots and comparison capabilities for tracking complexity changes over time.
Versioned JSON snapshots with stable member identities.
Baseline-versus-current complexity comparisons.
Classification of regressions, improvements, equivalent results, and inconclusive comparisons.
Explicit handling of added, removed, and ambiguously matched members.
Optional quality gates using
--fail-on-regression.
Why it matters: Teams can identify proven asymptotic complexity regressions during code review and CI without treating uncertain comparisons as failures.
4. New .NET CLI and SARIF Reporting
ComplexityAnalysis.Tool is available as a separately packaged local .NET Tool.
Capabilities include:
Project and solution analysis (
.csproj,.sln,.slnx).Console and deterministic JSON reporting.
Evidence-rich complexity snapshots.
Baseline comparison.
SARIF 2.1.0 export with stable fingerprints.
Optional regression quality gates.
Why it matters: Complexity analysis can extend beyond IDE diagnostics into automated validation, reporting, and engineering quality workflows.
5. Local MCP Server for AI-Assisted Engineering
A new ComplexityAnalysis.Mcp project exposes complexity analysis through the Model Context Protocol (MCP).
The local, read-only server provides three tools:
MCP Tool | Capability -- | -- analyze_project | Analyze a project or solution and return complexity results with evidence query_member_evidence | Retrieve evidence for a specific analyzed member compare_snapshots | Compare complexity snapshots and identify changesThe server uses standard input/output (stdio) and includes security controls for allowed filesystem roots, symbolic links, workload limits, timeouts, and cancellation.
Why it matters: AI-assisted development tools can consume deterministic complexity evidence instead of relying exclusively on language-model reasoning about algorithmic behavior.
The MCP server performs local analysis only. It does not modify source files, execute arbitrary commands, or require external services.
6. CI Integration and Software Supply Chain Security
This release also strengthens engineering quality and release integrity.
Opt-in GitHub Actions complexity regression checks.
Reviewed sample baseline and retained JSON comparison artifacts.
CodeQL security scanning and dependency review.
Release provenance and SPDX Software Bill of Materials (SBOM).
Updated dependencies, SDK tooling, and GitHub Actions.
Linux CI runner migration to Ubuntu 26.04.
Refactoring to reduce internal cognitive complexity and improve maintainability.
These changes make complexity analysis easier to adopt in existing CI processes while reinforcing software supply chain transparency.
Compatibility
The release preserves compatibility with existing analyzer consumers.
Existing diagnostic IDs, default severities, and configuration behavior remain unchanged.
The Roslyn analyzer continues targeting
netstandard2.0.CLI and MCP dependencies remain isolated from the analyzer package.
Existing projects can continue using the analyzer without adopting the new tooling.
The additional capabilities are optional and can be introduced incrementally.
Validation
The Complexity Analysis vNext implementation was validated through:
1,239 passing automated tests in the integration PR.
Analyzer and CLI package contract tests.
Consumer validation on .NET 8, .NET 9, and .NET 10.
Structural and performance contract tests.
Deterministic snapshot and regression comparison tests.
MCP server security and functionality tests.
Successful CI, SonarQube, release, and CodeQL workflows.
Known Limitations
Complexity Analyzers intentionally favors conservative conclusions.
Analysis may return
Unknownwhen sufficient semantic evidence is unavailable.Snapshot matching does not infer renames when identity correspondence is ambiguous.
MCP integration is local and read-only, not a hosted remote service.
Regression checks are opt-in; teams must establish representative baselines for their projects.
These boundaries are intentional and help maintain trustworthy results.
Full Changelog
Major implementation: Complexity Analysis vNext — PR #114
All changes: Compare v1.5.0...v1.6.0
Complexity Analyzers v1.6.0 moves algorithmic complexity analysis beyond diagnostics toward explainable, reproducible, and automation-ready engineering workflows.
# Complexity Analyzers v1.6.0 — Explainable Analysis, Regression Detection & MCP IntegrationVersion 1.6.0 introduces Complexity Analysis vNext, a significant expansion of Complexity Analyzers beyond traditional Roslyn diagnostics.
This release focuses on making algorithmic complexity analysis more reliable, explainable, reproducible, and suitable for integration into development workflows, CI pipelines, and AI-assisted engineering tools.
The existing Roslyn analyzer remains backward compatible, while new capabilities are delivered through a separate .NET CLI and a local MCP server.
Highlights
1. More Reliable Complexity Analysis
Improved static analysis provides more conservative and explicit complexity estimates.
- Expanded analysis o...
tool-v1.0.0
ComplexityAnalysis.Tool v1.0.0 — First Stable Release
The first stable release of ComplexityAnalysis.Tool introduces a standalone .NET command-line tool for analyzing algorithmic and structural complexity across C# projects and solutions.
Built on the same analysis engine as ComplexityAnalysis.Analyzers, the CLI brings complexity metrics, deterministic reports, and configurable quality gates to local development and CI pipelines, without requiring integration into the compiler.
Highlights
Code Complexity Analysis
Analyze .csproj, .sln, and .slnx files with support for:
- Algorithmic complexity (Big-O) with conservative
Unknownresults when complexity cannot be reliably determined. - Cyclomatic and Cognitive Complexity to assess control-flow complexity and code comprehensibility.
- Nesting depth and method-size metrics, including NLOC, statements, tokens, and parameter counts.
- Halstead metrics for additional code complexity measurements.
- Duplicate code detection using C#-aware token normalization.
Reports and Quality Gates
- Generate deterministic reports in console, JSON, or SARIF 2.1.0 formats.
- Configure quality thresholds for use in local development and CI.
- Create versioned complexity snapshots with supporting evidence.
- Compare snapshots to identify regressions and improvements.
- Fail CI builds on explicitly configured quality violations or proven complexity regressions.
- Use predictable exit codes for automation.
Quality gates are opt-in. No default thresholds are enforced.
Developer Experience
- Install as a global or repository-local .NET Tool.
- Use the
complexity-analysiscommand without cloning the repository. - Access built-in
--helpand--versioncommands. - Follow dedicated documentation in English and Portuguese.
- Keep tooling versions reproducible with local .NET tool manifests.
Getting Started
Requirements: .NET 10 runtime.
Install from NuGet.org:
dotnet tool install --global ComplexityAnalysis.Tool --version 1.0.0Analyze a C# solution:
complexity-analysis analyze MySolution.slnxGenerate a SARIF report:
complexity-analysis analyze MyProject.csproj --format sarif --output complexity.sarifApply a quality gate:
complexity-analysis analyze MyProject.csproj --max-cyclomatic-complexity 10Explore the available commands:
complexity-analysis --helpIndependent Versioning and Distribution
ComplexityAnalysis.Tool now has its own release lifecycle, independently versioned from the ComplexityAnalysis.Analyzers NuGet package.
This release introduces:
- Dedicated NuGet.org and GitHub Packages distribution workflows.
- Manual, controlled releases using GitHub Actions and Trusted Publishing.
- Package installation and execution validation.
- An SPDX 2.3 Software Bill of Materials (SBOM).
- GitHub release provenance and supply-chain attestations.
- A dedicated
tool-v*tag namespace.
The Roslyn Analyzer package and its existing release process remain unchanged.
Documentation
- [CLI documentation](https://github.com/rodri-oliveira-dev/complexity-analyzers/blob/main/docs/en/project-tooling.md)
- [Documentação em português](https://github.com/rodri-oliveira-dev/complexity-analyzers/blob/main/docs/pt-BR/project-tooling.md)
- [Source code and repository](https://github.com/rodri-oliveira-dev/complexity-analyzers)
- [NuGet package](https://www.nuget.org/packages/ComplexityAnalysis.Tool/1.0.0)
Release Details
This release includes the documentation, packaging, testing, and distribution improvements delivered in [PR #115](#115).
Release tag: tool-v1.0.0
Package: ComplexityAnalysis.Tool
Target framework: .NET 10
License: MIT
This release establishes a standalone CLI distribution for complexity analysis, making existing analysis capabilities easier to integrate into development workflows and automated quality checks.
ComplexityAnalysis.Mcp 1.0.0
ComplexityAnalysis.Mcp 1.0.0
The first stable release of ComplexityAnalysis.Mcp makes the repository's
deterministic C# complexity analysis available to compatible local agents as an
independently installed .NET 10 tool.
Highlights
- Install
ComplexityAnalysis.Mcpand run thecomplexity-mcpcommand without
a repository checkout or separate CLI installation. - Analyze
.csproj,.sln, and.slnxinputs, query exact member evidence by
StableId, and compare deterministic complexity snapshots through three
read-only MCP tools. - Choose the backward-compatible full response or an explicitly bounded summary
response for lower context usage. - Reuse an exact analyzed snapshot through
analysisId, avoiding duplicate
analysis without treating cached data as current filesystem state. - Preserve conservative
Unknownresults and typed evidence; comparisons never
convert inconclusive estimates into proven regressions. - Enforce an allowed root, extension checks, symbolic-link/reparse-point
protection, per-request file/byte limits, timeout, cancellation, and strict
stdout/stderr separation. - Configure the installed command with VS Code / GitHub Copilot, Codex, and
Claude Desktop using documented local stdio formats. - Discover the release as
io.github.rodri-oliveira-dev/complexity-analysisin the Official MCP
Registry, backed by the same installable package on NuGet.org.
Install
dotnet tool install --global ComplexityAnalysis.Mcp --version 1.0.0
complexity-mcp --root /absolute/path/to/projectThis release requires the .NET 10 runtime. The server is local, stdio-only, and
read-only. It does not provide HTTP transport, network access, telemetry, shell
execution, or source mutation.
Release artifacts include the NuGet package and its SPDX 2.3 SBOM. GitHub build
provenance and SBOM attestations are generated by the protected release
workflow. After those artifacts are available, the workflow publishes the
version-synchronized Registry manifest with GitHub OIDC and verifies the
resulting entry.
v1.5.0
What's Changed
This release completes Phase 11 — Project-level Tooling, expanding ComplexityAnalysis.Analyzers beyond compiler-time diagnostics with a dedicated project-level analysis surface.
The new ComplexityAnalysis.Tool CLI can analyze complete C# projects and solutions, produce deterministic aggregate reports, apply explicit CI quality gates, and detect normalized duplicate code across files — all while keeping project-wide work completely outside Roslyn analyzer hot paths.
This release also updates the project's test and analysis infrastructure dependencies.
Phase 11 — Project-level Tooling
Project-level complexity CLI
The repository now includes a dedicated ComplexityAnalysis.Tool project for whole-project analysis.
The CLI supports:
.csprojprojects;.slnsolutions;.slnxsolutions;- deterministic console reporting;
- machine-readable JSON reporting;
- opt-in quality gates;
- cooperative cancellation;
- generated-code exclusion;
- build-output exclusion;
- normalized duplicate-code detection.
The CLI is intentionally architecturally separated from the packaged Roslyn analyzer.
No filesystem scanning, project traversal, duplicate detection, or other whole-project operations have been introduced into DiagnosticAnalyzer.Initialize or analyzer callbacks.
Consumer applications using ComplexityAnalysis.Analyzers therefore remain independent from the CLI and its project-level responsibilities.
Aggregate complexity reports
Project-level reports aggregate complexity information across projects, files, and executable members.
Reports can include:
- Big-O Complexity;
- Cyclomatic Complexity;
- Maximum Control-Flow Nesting Depth;
- NLOC;
- Statement Count;
- Token Count;
- Parameter Count;
- Cognitive Complexity;
- Halstead Metrics;
- source identity and location;
- duplicate-code summaries and clone groups;
- quality-gate results.
Metrics that cannot be determined safely remain explicitly represented as unavailable or Unknown rather than being coerced into artificial values.
This preserves the conservative analysis philosophy established by previous releases.
Deterministic console and JSON output
Two report formats are available.
Console
The console report provides a human-readable representation suitable for local development and CI logs.
Projects, files, members, and duplicate groups are ordered deterministically so equivalent inputs produce stable output.
JSON
The JSON report exposes machine-readable project, file, member, location, metric, quality-gate, and duplicate information.
It is designed to support CI pipelines and future integrations without coupling consumers to analyzer internals.
The reporting architecture also introduces a format-independent writer boundary that can support additional exporters, such as SARIF, in future releases.
SARIF itself is intentionally not implemented in this release.
CI quality gates
Project-level quality gates are now supported.
All gates are explicitly opt-in.
The CLI does not introduce arbitrary default thresholds that could unexpectedly break existing builds.
Documented exit codes are:
0— analysis completed successfully;1— execution or configuration error;2— an explicitly configured quality gate was exceeded;130— operation cancelled.
Quality gates can evaluate project-level metric thresholds and duplicate-code limits while keeping policy separate from metric calculation.
Generated code and build-output exclusions
Whole-project analysis excludes generated and build-generated content by default.
Common exclusions include directories such as:
bin;obj;artifacts;TestResults;packages;- other known tooling/build output locations.
Generated-code and build-output behavior can be overridden explicitly when required.
This prevents project reports from being polluted by files that are not part of the authored source being evaluated.
Cross-file duplicate-code detection
Phase 11 also introduces normalized C# duplicate-code detection.
Duplicate detection runs exclusively in the project-level tooling layer and supports:
- duplicates within the same file;
- duplicates across different files;
- configurable minimum clone size;
- token-based thresholds;
- logical-line thresholds;
- deterministic clone grouping;
- precise source ranges;
- duplicate token counts;
- occurrence counts;
- project/file duplication information;
- optional duplicate-code quality gates.
Small fragments below the configured thresholds are ignored to reduce noise.
C#-aware normalization
Duplicate detection uses Roslyn tokenization and C#-specific normalization rather than plain textual comparison.
The normalization model understands constructs including:
- parameters;
- local variables;
- member, type, and namespace identifiers by role;
- numeric literals;
- string literals;
- character literals;
- interpolated strings;
- pattern variables;
- generic type arguments;
- member access;
- modern C# syntax supported by the configured parser.
Harmless renaming or literal substitutions can therefore be recognized as structurally equivalent where appropriate.
At the same time, material differences remain preserved.
Unary and binary operators, control-flow structure, and other behaviorally meaningful syntax are not collapsed into generic tokens merely to increase clone matches.
This reduces false positives between implementations that may look superficially similar but express different behavior.
Bounded duplicate-detection algorithm
Duplicate detection deliberately avoids naive all-pairs substring comparison.
The implementation uses token-window indexing with rolling/fingerprint-style hashing to identify candidate regions efficiently.
Candidate hashes are only used to narrow the search space.
A matching hash is never considered proof of duplication.
Every candidate is verified using the actual normalized token sequence before a clone is reported, preventing hash collisions from directly producing false-positive findings.
The expected behavior is approximately linear with the number of normalized token windows, plus verification of candidate buckets, with memory proportional to the indexed windows.
This keeps project-level duplicate detection suitable for real repositories while avoiding pathological unbounded comparison strategies.
Deterministic overlap suppression
Duplicate-code analysis also performs deterministic de-noising.
Overlapping or fully contained clone ranges are suppressed using stable rules that prioritize longer matches and deterministic source ordering.
This avoids overwhelming reports with multiple representations of effectively the same duplicate region.
Equivalent source inputs therefore produce equivalent clone groups regardless of filesystem enumeration order.
Architecture
The new project-level functionality preserves the separation between compiler analysis and repository analysis.
The dependency direction remains explicit:
ComplexityAnalysis.Tool → shared analyzer/metric infrastructure
The Roslyn analyzer does not depend on the CLI.
The project-level loader uses Roslyn syntax and compilation APIs directly without introducing Microsoft.CodeAnalysis.Workspaces.
No network calls, telemetry, databases, external clone-detection services, or runtime services are required.
This architecture allows project-wide analysis to evolve without compromising the bounded execution requirements of IDE and compiler analyzer hosts.
Documentation
Project-level tooling is documented in both English and Brazilian Portuguese.
The documentation now covers:
- CLI usage;
.csproj,.sln, and.slnxinputs;- console reports;
- JSON reports;
- aggregate metric semantics;
- quality gates;
- exit codes;
- generated/build-output exclusions;
- duplicate detection;
- C# normalization rules;
- clone thresholds;
- architecture and dependency boundaries;
- performance characteristics.
The Phase 11 behavior is also formally described in a dedicated specification, following the project's Specification-Driven Development approach.
Validation
The Phase 11 implementation was validated against the existing engineering baseline.
Validation included:
- Release restore and build;
- 1,088 automated tests passing;
- project-tool integration tests;
- analyzer characterization tests;
- package contract tests;
- consumer contract tests;
- performance synthetic-corpus tests;
- analyzer performance-budget tests;
- Roslyn host-compatibility tests;
- deterministic console and JSON reporting;
- duplicate detection against representative multi-file fixtures;
- quality-gate behavior;
- cancellation;
- generated/build-output exclusions;
- local NuGet packaging;
- manual CLI execution with JSON, duplicate detection, and duplicate quality gates.
The Release build completed with no new build warnings or errors.
Existing analyzer diagnostic behavior, package contracts, performance characteristics, diagnostic IDs, severity defaults, and configuration semantics remain unchanged.
Dependency updates
This release also includes maintenance updates to the development infrastructure:
dotnet-sonarscannerupdated from11.2.1to11.3.0;Microsoft.NET.Test.Sdkupdated from18.9.0to18.10.0.
These updates affect the repository's analysis/test infrastructure and do not change the public analyzer behavior.
Why this release matters
Previous releases progressively established a set of deterministic and independently explainable C# complexity measurements.
With v1.5.0, those measurements are no longer limited to compiler-time diagnostics.
`ComplexityAnalysis....
v1.4.0
This release introduces deterministic, C#-specific Halstead Metrics and continues the project's focus on maintainable, reproducible static-analysis infrastructure.
Halstead analysis complements the existing complexity dimensions by measuring the vocabulary and usage of operators and operands within supported C# executable members.
Rather than attempting to collapse these measurements into another generic maintainability score, ComplexityAnalysis.Analyzers exposes a well-defined internal metric model that can support future diagnostics, reporting, and higher-level analysis while preserving the project's conservative diagnostic philosophy.
Phase 10 — Halstead Metrics
10.1 — C#-specific Halstead Metrics
The analyzer now provides a deterministic C#-specific implementation of Halstead Metrics based on Roslyn syntax rather than generic C-like token heuristics.
The analysis collects the four primitive Halstead measurements:
n1— distinct operators;n2— distinct operands;N1— total operators;N2— total operands.
From these primitive values, the analyzer derives:
- vocabulary;
- program length;
- calculated length;
- volume;
- difficulty;
- effort;
- estimated implementation time;
- estimated delivered bugs.
The implementation explicitly protects empty and trivial executable members from invalid floating-point results such as NaN or infinity.
C#-specific classification
The operator and operand model is deliberately defined for modern C# and documented as part of the project's compatibility contract.
Supported syntax includes representative constructs such as:
- arithmetic, comparison, logical, and assignment operators;
- compound assignments;
- null-related operators such as
?.,??, and??=; - lambdas and expression-bodied members using
=>; - pattern-matching constructs;
- identifiers and literals;
- interpolated strings;
- member access;
- range and index syntax;
- collection expressions;
- supported control-flow and expression constructs.
Comments and trivia do not contribute to the metrics.
Nested executable members such as local functions, lambdas, and anonymous methods retain independent ownership and therefore do not incorrectly inflate their lexical parent's Halstead measurements.
Independent complexity dimensions
Halstead Metrics remain independent from the analyzer's existing measurements:
- Big-O complexity;
- Cyclomatic Complexity;
- Maximum Control-Flow Nesting Depth;
- NLOC;
- Statement Count;
- Token Count;
- Parameter Count;
- Cognitive Complexity.
Each metric answers a different question about source code.
Halstead Metrics focus on the vocabulary and frequency of the operators and operands required to express an implementation, while the existing metrics describe computational growth, execution paths, structural depth, source size, API shape, or cognitive control-flow burden.
Keeping these dimensions separate avoids introducing a speculative composite maintainability score.
No Halstead threshold diagnostic
This release intentionally does not introduce a new BIG2xxx diagnostic or public Halstead threshold configuration.
Although Halstead measurements can provide useful information about code characteristics, there is currently no single Halstead-derived value with a sufficiently universal and evidence-backed threshold to justify a maintainability diagnostic across different C# codebases.
This follows the project's established principle that diagnostics should be actionable, deterministic, and defensible rather than being introduced simply because a metric can be calculated.
The Halstead implementation therefore establishes the measurement foundation without prematurely defining policy around acceptable values.
Maintainability hardening
This release also addresses a SonarQube maintainability finding in MethodSizeMetricsAnalyzer.
The affected analysis logic is refactored to reduce its Cognitive Complexity while preserving the existing behavior and contracts of the NLOC, Statement Count, and Token Count metrics.
The change is structural rather than behavioral: existing diagnostic semantics, configuration, executable-member boundaries, and metric calculations remain unchanged.
This keeps the analyzer's own implementation aligned with the maintainability principles it is designed to help enforce.
Documentation
The Halstead classification convention is documented in both English and Brazilian Portuguese.
The documentation defines:
- operator and operand classification;
- primitive-count semantics;
- derived formulas;
- modern C# syntax handling;
- nested executable-member ownership;
- comments and trivia exclusion;
- numeric stability requirements;
- the relationship between Halstead and the analyzer's other complexity dimensions.
The goal is to make Halstead values reproducible across future versions rather than dependent on undocumented token-classification behavior.
Validation
The implementation was validated against the engineering baseline established by previous releases, including:
- primitive Halstead count tests;
- derived-formula tests;
- numeric safety and deterministic formatting;
- modern C# operator and operand classification;
- null operators;
- pattern matching;
- lambdas and expression-bodied members;
- interpolated strings;
- range, index, and collection syntax;
- comments and trivia exclusion;
- identifier-renaming behavior;
- nested executable-member isolation;
- supported executable-member kinds;
- regression coverage for existing complexity metrics;
- analyzer performance budgets;
- Roslyn host compatibility;
- NuGet package and consumer contracts.
The existing analyzer behavior remains unchanged outside the new Halstead analysis capability and the internal maintainability refactoring.
Why this release matters
Complexity is multidimensional.
Big-O describes how computational cost grows. Cyclomatic Complexity measures independent execution paths. Maximum Nesting Depth describes structural depth. Cognitive Complexity focuses on how difficult control flow is to mentally follow.
Halstead Metrics add another perspective: the vocabulary and operational structure used to express an implementation.
With Phase 10 beginning, ComplexityAnalysis.Analyzers can reason about an increasingly broad set of code characteristics while keeping every measurement deterministic, independently explainable, and free from arbitrary composite scoring.
At the same time, the maintainability refactoring included in this release reinforces an important principle of the project: the analyzer itself should meet the same engineering standards it encourages in the code it evaluates.
See the canonical execution roadmap in #36 — Execution order for analyzer hardening and capability expansion.
What's Changed
- feat: add C#-specific Halstead Metrics — #60
- refactor: reduce Cognitive Complexity in
MethodSizeMetricsAnalyzer— #61 - closes #15 —
[10.1] Add C#-specific Halstead Metrics - closes #61 —
[Sonar][HIGH][MAINTAINABILITY] Cognitive Complexity of methods should not be too high
Full Changelog: v1.3.0...v1.4.0
v1.3.0
The analyzer can now calculate Cognitive Complexity for supported C# executable members using a documented, deterministic scoring convention.
Unlike Cyclomatic Complexity, which primarily measures independent execution paths, Cognitive Complexity focuses on the structural burden placed on a developer reading the code.
The metric accounts for control-flow structures and the additional cognitive cost introduced by nesting.
Supported constructs include:
if,else if, andelse;for,foreach,while, anddo;switchstatements and switch expressions;catchclauses;- conditional (
?:) expressions; - boolean condition sequences;
- pattern matching and
whenguards; - nested control flow;
- direct recursion where it can be resolved safely.
Straight-line code starts with a Cognitive Complexity score of 0, while structural control-flow breaks and nesting progressively increase the score.
Nested executable members such as local functions, lambdas, and anonymous methods are analyzed independently and do not incorrectly inflate the score of their lexical parent.
New diagnostic
This release introduces:
BIG2007— Cognitive complexity exceeds configured threshold
The diagnostic remains opt-in and is emitted only when a Cognitive Complexity threshold has explicitly been configured and the calculated value exceeds it.
Example:
complexity_analyzers.maximum_cognitive_complexity = 15
dotnet_diagnostic.BIG2007.severity = warningInvalid or missing configuration does not cause analysis failures and simply leaves the Cognitive Complexity threshold disabled.
Independent complexity dimensions
Cognitive Complexity is intentionally independent from the existing metrics.
A member may therefore have:
- low Cyclomatic Complexity but high Cognitive Complexity because of deep nesting;
- high Cyclomatic Complexity but comparatively low Cognitive Complexity when branches remain flat;
- high algorithmic complexity while remaining structurally simple to understand;
- low Big-O complexity while still being difficult for humans to reason about.
This distinction allows the analyzer to evaluate different dimensions of complexity without attempting to collapse them into a single maintainability score.
Reuse of the Phase 08 analysis foundation
The implementation reuses the executable-member and control-flow foundations introduced during Phase 08 rather than establishing a parallel analysis pipeline.
This keeps executable-member boundaries consistent across metrics and ensures constructs such as:
- methods;
- constructors;
- accessors;
- operators;
- conversion operators;
- local functions;
- lambdas;
- anonymous methods;
- supported expression-bodied members
continue to follow the same analysis model.
Direct recursion detection also covers supported semantic forms such as operators, conversions, and property or event accessors where Roslyn can reliably resolve the invoked symbol.
Documented scoring convention
The project's Cognitive Complexity convention is now documented in both English and Brazilian Portuguese.
The specification explicitly defines how supported C# constructs contribute to the score, including nesting behavior, boolean conditions, modern switch and pattern constructs, and executable-member isolation.
The implementation intentionally describes itself as the ComplexityAnalysis.Analyzers Cognitive Complexity convention rather than claiming equivalence with another analyzer's proprietary implementation.
This makes the metric reproducible and keeps its behavior under the project's own compatibility contract.
Validation
Phase 09 was validated against the engineering baseline established in previous releases, including:
- dedicated Cognitive Complexity unit and integration tests;
- flat versus deeply nested control-flow scenarios;
- threshold boundary behavior;
- invalid configuration handling;
- modern C# switch and pattern constructs;
- boolean-expression behavior;
- recursion scenarios;
- supported executable-member kinds;
- generated-code exclusion;
- regression coverage for Big-O, Cyclomatic Complexity, nesting depth, method-size metrics, and Parameter Count;
- analyzer performance budgets;
- Roslyn host compatibility;
- NuGet package and consumer contracts.
The SonarQube Cloud Quality Gate for the implementation also passed, including the required coverage, reliability, security, maintainability, duplication, and security-hotspot checks.
Why this release matters
Complexity is not a single-dimensional property.
Cyclomatic Complexity can tell us how many independent paths exist through a member, while Maximum Nesting Depth exposes structural depth and Big-O describes algorithmic growth. None of those metrics alone fully captures how difficult code may be for another developer to mentally follow.
Cognitive Complexity adds that missing perspective.
With Phase 09 complete, ComplexityAnalysis.Analyzers can now distinguish between computational complexity, control-flow complexity, structural depth, source size, API shape, and cognitive burden while keeping each metric independently configurable and explainable.
This continues the project's approach of preferring deterministic, evidence-based diagnostics over composite or speculative maintainability scores.
See the canonical execution roadmap in #36 — Execution order for analyzer hardening and capability expansion.
What's Changed
- feat: add Cognitive Complexity analysis for C# — #58
- closes #14 —
[09.1] Add Cognitive Complexity analysis for C#
Full Changelog: v1.2.0...v1.3.0
v1.2.0
This release evolves the analyzer from a method-centric Big-O analysis pipeline into a reusable executable-member analysis foundation and introduces a new family of deterministic structural metrics for C#.
Existing algorithmic-complexity behavior remains conservative, while analysis coverage and maintainability diagnostics are significantly expanded.
What's new
08.1 — Shared executable-member foundation
The analysis pipeline now uses a reusable internal executable-member abstraction instead of being centered exclusively on MethodDeclarationSyntax.
This foundation provides consistent access to:
- Roslyn syntax and symbols;
- executable bodies and expression bodies;
- diagnostic locations;
- analyzer configuration;
- cancellation;
- interprocedural context.
Existing ordinary-method Big-O, recursion, recurrence, known-operation and interprocedural behavior was migrated to this shared foundation without intentionally changing its semantics.
Implemented in #49.
Closes #8.
08.2 — Expanded C# executable-member coverage
Analysis is no longer limited to ordinary methods.
Supported executable roots now include, where applicable:
- ordinary methods;
- constructors and static constructors;
- property accessors;
- event accessors;
- operators;
- conversion operators;
- local functions;
- simple and parenthesized lambdas;
- anonymous methods;
- expression-bodied properties and other supported expression-bodied members.
Nested executable members are analyzed independently so their complexity does not incorrectly inflate the lexical parent.
Unsupported or unsafe scenarios continue to fail conservatively rather than forcing an estimate.
Implemented in #50.
Closes #9.
08.3 — Cyclomatic Complexity and Modified McCabe
This release introduces deterministic Cyclomatic Complexity analysis independently from Big-O estimation.
New diagnostic:
BIG2001— Cyclomatic complexity exceeds configured threshold
New configuration:
complexity_analyzers.maximum_cyclomatic_complexity = 10
complexity_analyzers.cyclomatic_complexity_mode = standardv1.1.0
With that foundation in place, v1.1.0 completes Phase 07 — Hardening baseline.
Rather than introducing additional complexity metrics, this release focuses on making the existing analyzer safer to maintain, validate, and evolve. It establishes explicit engineering guarantees around correctness, performance, Roslyn compatibility, diagnostic experience, and release quality before the architecture expands further.
Phase 07 — Hardening baseline
07.1 — Analyzer correctness and characterization baseline
Established automated characterization and regression coverage for the behavior delivered by the existing analyzer.
This creates a stable behavioral reference for future development and helps detect accidental changes in:
- diagnostic triggering;
- diagnostic IDs;
- severity and enablement;
- configuration behavior;
- supported and unsupported complexity classifications.
The objective is to preserve existing semantics unless a future change explicitly intends to modify them.
07.2 — Performance budgets and regression gates
Defined explicit performance expectations for analyzer execution and introduced regression gates around performance-sensitive paths.
Because Roslyn analyzers execute inside compiler and IDE hosts, performance is treated as part of functional behavior rather than as an optional optimization concern.
The baseline helps ensure future metrics do not introduce:
- unbounded traversal;
- excessive allocations;
- unnecessary repeated analysis;
- compiler or IDE responsiveness regressions.
07.3 — Roslyn host and package compatibility
Formalized the supported Roslyn host scenarios and analyzer package contract.
Compatibility expectations are now explicit and testable, reducing the risk that dependency, packaging, or compiler-host changes unexpectedly affect consumers.
This includes clearer expectations around:
- Roslyn dependencies;
- package layout;
- analyzer loading;
- supported compiler and SDK scenarios;
- consumer-facing dependency behavior.
07.4 — Diagnostic explainability and developer guidance
Improved the way diagnostics communicate their findings.
Analyzer messages and guidance now follow clearer conventions designed to remain:
- deterministic;
- evidence-based;
- actionable;
- conservative when remediation cannot be proven safe.
The analyzer should explain what it can establish from the source code without presenting speculative recommendations as definitive fixes.
07.5 — Release-quality governance
Established a canonical Definition of Done for analyzer changes.
Future work now follows explicit quality expectations covering:
- correctness;
- analyzer safety;
- performance;
- Roslyn compatibility;
- package compatibility;
- diagnostic UX;
- documentation;
- automated testing;
- release validation.
This provides a repeatable engineering gate for subsequent roadmap phases.
Why this release matters
v1.0.0 already provided meaningful complexity-analysis capabilities.
The purpose of v1.1.0 is not to replace or rebuild that foundation, but to place stronger engineering guarantees around it.
Before introducing additional metrics and broader executable-member analysis, the project now has explicit mechanisms to answer critical questions:
- Did existing analyzer behavior change?
- Did a new feature introduce false positives?
- Did analyzer execution become materially slower?
- Does the package still load correctly across supported Roslyn hosts?
- Are diagnostics explaining only what the analyzer can prove?
- Is the change ready to be released safely?
See the canonical execution roadmap in [#36 — Execution order for analyzer hardening and capability expansion](#36).
Additional repository improvements
This release also includes supporting repository and developer-experience improvements:
- Copilot repository instructions — #28
- Complexity Analyzer Architect custom agent — #29
- NuGet and release badges — #30
What's Changed
- test: establish analyzer correctness baseline — #37
- perf: define analyzer performance budgets and regression gates — #38
- test: formalize Roslyn host and package compatibility — #39
- feat: improve diagnostic explainability — #40
- docs: establish release-quality governance for analyzer changes — #41
Full Changelog: v1.0.0...v1.1.0
v1.0.0
v1.0.0 marks the first production-ready release of ComplexityAnalysis.Analyzers.
This version establishes the core analyzer architecture and delivers the complexity-analysis roadmap through Phase 06, providing the functional baseline on top of which future metrics and structural analysis capabilities will evolve.
The focus of this release is deterministic static analysis, conservative complexity estimation, bounded interprocedural reasoning, and a stable analyzer package suitable for use in compiler and IDE environments.
Core analyzer foundation
The initial architecture establishes the execution model, diagnostic infrastructure, analysis boundaries, configuration mechanisms, and packaging required for the analyzer to evolve safely.
The implementation favors conservative results over speculative estimates: whenever complexity cannot be proven reliably, the analyzer should prefer an Unknown result rather than report misleading information.
Analysis capabilities through Phase 06
BCL-aware diagnostics
Expanded complexity analysis to understand relevant .NET Base Class Library operations and incorporate their known computational behavior where deterministic evidence is available.
This allows diagnostics to account for common framework operations without relying exclusively on local syntax.
Interprocedural analysis
Introduced bounded analysis across source-code method calls.
The analyzer can propagate complexity information through relevant call chains while preserving explicit limits that prevent uncontrolled traversal or excessive compiler-host work.
Source-call argument evaluation
Improved source-call analysis by accounting for the complexity required to evaluate method arguments before the invoked member itself executes.
This closes an important gap in interprocedural estimation and produces a more faithful representation of the actual computational work performed by a call expression.
Recurrence solving
Added support for recognizing and solving supported recurrence patterns.
This enables the analyzer to reason about recursive complexity in deterministic cases while remaining conservative when a recurrence cannot be safely classified.
Engineering and repository improvements
Alongside the analyzer capabilities, this release establishes the repository and delivery infrastructure required for continued development:
- isolated analyzer CI;
- migration to the modern
.slnxsolution format; - analyzer configuration and performance safeguards;
- NuGet packaging;
- GitHub Packages support;
- automated release workflow;
- Dependabot configuration;
- repository restructuring;
- project status badges;
- community health files;
- security reporting guidance;
- product-oriented documentation.
These capabilities form the stable functional baseline that subsequent releases can harden and extend.
Roadmap position
With v1.0.0, the analyzer reaches the end of Phase 06 of its functional evolution.
The next milestone focuses on hardening this existing behavior before expanding the architecture with additional structural complexity metrics.
That work is delivered in v1.1.0 — Phase 07: Hardening baseline.
What's Changed
- ci(analyzer): add isolated CI and migrate solution to slnx — #1
- chore: complete BCL diagnostics — #2
- chore: complete interprocedural analysis — #3
- fix: account for source call argument evaluation — #4
- chore: complete recurrence solving — #5
- configuration, performance and packaging improvements — #6
- refactor: promote analyzer project to repository root — #7
- configure Dependabot for multiple package ecosystems — #18
- docs: add project status badges — #23
- docs: reframe product documentation around analyzer capabilities — #24
- docs: add community health files — #25
- docs: add private security reporting fallback — #26
- ci: add NuGet and GitHub Packages release workflow — #27
Full Changelog: v1.0.0