Skip to content

Initial implementation of ComplexityRipper#1

Merged
Treit merged 34 commits intomainfrom
initial-setup
Mar 30, 2026
Merged

Initial implementation of ComplexityRipper#1
Treit merged 34 commits intomainfrom
initial-setup

Conversation

@Treit
Copy link
Copy Markdown
Owner

@Treit Treit commented Mar 23, 2026

ComplexityRipper

Roslyn-based code complexity analyzer for C#. Scans repos for long functions, high cyclomatic complexity, and deep nesting. Generates self-contained HTML reports with hyperlinks to source files in Azure DevOps and GitHub.

Features

Analysis: Uses Roslyn syntax tree parsing for accurate cyclomatic complexity, line count, nesting depth, and parameter count. Finds methods, constructors, property accessors, and local functions. Resolves the nearest .csproj for a Project column.

Report: Self-contained HTML with theme switcher (light, dark, high-contrast, ink). Repos ranked by concern score (worst first), with per-repo detail sections containing Combined Risk, Long Functions, and High Complexity tables. All columns hyperlinked to source in ADO or GitHub. Sortable and filterable tables with distribution charts.

Concern Score: Weighted composite per repo -- 10 pts per combined-risk function, 3 pts per complex-only, 2 pts per long-only, plus bonus for extreme values. Repos with score 0 are listed as clean.

Filtering: \--include\ and \--exclude\ regex options filter by repo name (use \|\ for OR). Non-matching repos are skipped entirely.

CLI: Three commands -- \
un\ (analyze + report), \�nalyze\ (JSON only), \
eport\ (HTML from JSON). Configurable thresholds, themes, and output paths. Packaged as a dotnet global tool.

Project structure (ToListinator conventions)

\Directory.Build.props\ for centralized versioning, \Directory.Packages.props\ for package management, CI + release GitHub Actions workflows, \.editorconfig\, MIT license, modern \.slnx\ solution format. 41 xUnit tests.

Mike Treit (from Dev Box) and others added 30 commits March 22, 2026 17:34
Roslyn-based code complexity analyzer that scans C# repos for long functions,
high cyclomatic complexity, and deep nesting. Supports other languages via
Lizard integration. Generates self-contained HTML reports with ADO hyperlinks.

Features:
- Roslyn syntax tree analysis for C# (accurate, in-process parallel)
- Lizard CLI integration for Python, TypeScript, Go, JavaScript
- Configurable thresholds (line count, cyclomatic complexity)
- HTML report with dark theme, sortable/filterable tables, distribution charts
- ADO hyperlinks parsed from git remotes
- Published as dotnet global tool (complexityripper)

Project structure follows ToListinator conventions:
- Directory.Build.props for centralized versioning
- Directory.Packages.props for centralized package management
- CI workflow (build + test on push/PR)
- Release workflow (tag-triggered NuGet publish)
- 33 xUnit tests for ComplexityCalculator, AdoUrlHelper, CSharpAnalyzer

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When --root points to a directory that is itself a git repo (has a .git
subdirectory), treat it as a single repo instead of treating each
subdirectory as a separate repo.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
All four columns in the function tables (Repo, File, Class, Function)
are now hyperlinked:
- Repo links to the repository root
- File links to the file at the exact line range
- Class links to the file (for context)
- Function links to the file at the exact line range

Also adds GitHub remote URL support alongside existing ADO support.
GitHub URLs use the blob/branch/path#L1-L10 format. The default
branch is auto-detected via git symbolic-ref.

Repo breakdown table also hyperlinks repo names.

Fixes the single-repo case where the repo name column was blank.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repos with legacy visualstudio.com remotes (e.g.,
msdata.visualstudio.com/DefaultCollection/Project/_git/Repo)
are now correctly parsed and converted to dev.azure.com URLs
for hyperlink generation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Path.GetFileName returns empty string when the path ends with a
directory separator (e.g., C:\src\PerfBenchInfra\). This caused
the repo column to be blank in the HTML report.

Added a regression test that confirms the bug (fails before fix,
passes after).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Added per-command option tables, single-repo vs multi-repo examples,
two-step workflow (analyze once, adjust thresholds), custom output
paths, and hyperlink/remote URL documentation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Resolves the nearest .csproj/.fsproj/.vbproj for each source file
by walking up the directory tree. Results are cached per directory
for performance. The column is blank for non-.NET languages (Python,
TypeScript, etc.) where project boundaries are less well-defined.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Report order is now: summary cards, per-repo breakdown, language
breakdown, distribution charts, then the detail tables (combined
risk, long functions, high complexity). Summary data comes first,
details as you scroll down.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each function table (combined risk, long functions, high complexity)
now has a repo dropdown alongside the text filter. Both filters work
together -- selecting a repo narrows the rows, and typing further
filters within that repo. The dropdown only appears when there are
multiple repos.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Themes available via --theme CLI option and an in-page dropdown:
- dark: original dark GitHub-like theme
- light: clean light theme
- colorblind: blue/orange/brown palette, no red-green reliance
- high-contrast: pure black background, maximum contrast
- ink: minimal color, print-friendly

All color semantics use CSS variables (--severity-ok, --severity-medium,
--severity-high, --severity-critical, --bar-1 through --bar-5) so
every theme can define its own accessible palette. The theme switcher
in the page header allows instant switching without regeneration.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Lizard CSV output has 11 columns (not 10): the parser was reading
the 'long name' field as the start line, which failed int parsing
and caused every line to be silently skipped. Fixed by using
parts[^2] and parts[^1] for start/end line numbers.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Changed table container from overflow:hidden to overflow-x:auto so
wide tables scroll horizontally instead of clipping. Widened max
container to 1600px, tightened cell padding and font size slightly
to fit more columns, and added white-space:nowrap on td to prevent
mid-cell wrapping.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Function tables now group rows by repo with a separator heading
row instead of repeating the repo name in every row. This drops
a column (9 instead of 10) and makes the tables easier to scan.
The repo heading spans all columns, is styled distinctly, includes
a count badge, and links to the repo root. The repo dropdown
filter works with the data-repo attribute on both separator and
data rows.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each repo gets a concern score based on the number and severity of
flagged functions:
- Combined risk (both thresholds): 10 points each
- Complex only: 3 points each
- Long only: 2 points each
- Bonus points for extreme values (2x threshold)

Report structure is now:
1. Summary cards
2. Repository Ranking table (sorted by concern score, worst first)
   with clickable links to each repo's detail section
3. Language breakdown and distribution charts
4. Per-repo detail sections (only for repos with issues), each with
   its own Combined Risk, Long Functions, and High Complexity tables
5. Clean repos listed at the bottom

This makes the report much easier to read with 50+ repos since
you see the worst offenders first and can drill into each repo
independently.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Both options accept a regex pattern (use | for OR) and are applied
to file paths (normalized with forward slashes) during scanning.
--include keeps only matching paths; --exclude skips matching paths.
Filters apply to both Roslyn C# analysis and Lizard results.

Examples:
  --include "src/dev"
  --exclude "Tests?|Generated|\.Designer\."
  --include "ProjectA|ProjectB"

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Filters now match against repo/folder names rather than individual
file paths. Non-matching repos are skipped entirely (with a
'Skipping ... (filtered)' message) and excluded from all totals.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Deleted LizardRunner.cs and removed all Lizard references from
Program.cs, README, and csproj. The --csharp-only flag is no longer
needed. Multi-language support may be added later with a different
tool.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Bar chart text is now white for readability on all colored bars.
Concern score badges use severity colors with bold weight instead
of muted text. Combined Risk heading clarified to 'Combined Risk
(Long + Complex)'.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Critical/high/medium scores get colored backgrounds (red/orange/
yellow) with white text. Low scores stay subtle with green text.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Swap the tile/card grid for a single-row table showing key stats
inline: '57 repos  7,630 files  36,469 functions  89 long  479
complex  24 combined risk'. Flagged counts are color-coded by
severity. Compact, readable, no visual clutter.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Each repo with flagged functions now gets its own length and
complexity distribution charts. The global distribution section
is removed. Also updated complexity buckets to align with the
new default threshold of 25.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Mike Treit (from Dev Box) and others added 4 commits March 23, 2026 13:50
Projects ending in 'Tests' or 'Test' are excluded from analysis
by default. Use --include-tests to include them. File counts in
the report reflect only non-test files.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Repository names in the ranking table now anchor-link to the
repo's detail section within the report. The per-repo detail
heading still links to the actual external repo URL.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
When the root directory contains subdirectories that are not git repos
(organizational folders like babylon/ and sentinel_graph/), descend one
level to find actual repos. Direct child repos are still handled as before.

Repo names now use the relative path from root (e.g., babylon/RepoName)
to disambiguate repos with the same name across org folders. Lifecycle
metadata lookup falls back to the leaf name for backward compatibility.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Update default threshold-complexity from 15 to 25 to match code.
Rewrite HTML Report section to reflect actual structure: summary
table, repository ranking, and per-repo details with distribution
charts and function tables. Add missing CLI options (--include-tests,
--repo-metadata, --theme on report command). Rename AppendSummaryCards
to AppendSummaryTable and remove unused .cards CSS class.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@Treit Treit merged commit c1bf290 into main Mar 30, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant