Skip to content

feat: NE0001 — one top-level type per file with matching file name - #8

Merged
samtrion merged 2 commits into
mainfrom
feature/ne0001-one-type-per-file
Aug 3, 2026
Merged

feat: NE0001 — one top-level type per file with matching file name#8
samtrion merged 2 commits into
mainfrom
feature/ne0001-one-type-per-file

Conversation

@samtrion

@samtrion samtrion commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

Closes #3 · part of epic #6

What

Adds NE0001 (Maintainability, Warning): reports a file that declares more than one top-level type, or
whose single top-level type does not match the file name.

  • Top-level class/struct/record/record struct/interface/enum/delegate; nested types ignored.
  • Generic overloads are arity-encoded by default (Result.cs, Result{T}.cs, Result{T1,T2}.cs), or
    may share a base-named file when NetEvolveAnalyzerGroupGenericOverloads=true.
  • partial parts of the same type count as one type; namespace-scoped identity so two same-named types
    in different namespaces are each evaluated.
  • Disabled automatically for single-file publish (PublishSingleFile) and via
    NetEvolveAnalyzerDisableFileOrganizationRules.

Includes

  • Analyzer + DiagnosticIds.NE0001 + AnalyzerReleases.Unshipped.md entry + docs/rules/NE0001.md
  • Consumer build/NetEvolve.Analyzer.props exposing the CompilerVisibleProperty values the rule reads
  • Test infrastructure for file-name/path- and build-property-sensitive rules (reused by NE0002/NE0003):
    named-source unit verifier + AnalyzerCompiler with tree path and AnalyzerConfigOptions
  • 29 unit + 8 integration tests
  • Fixes a stray line in AnalyzerReleases.Shipped.md that failed RS2007

Quality

  • Release build clean (0 warnings, warnings-as-errors)
  • Coverage over src/: unit 98.9% · integration 88.2% · project 100% (gates 75/80/90/95)
  • Reviewed via a multi-dimension adversarial pass; one confirmed false-negative (namespace collision) fixed
    with regression tests

Not in this PR

🤖 Generated with Claude Code

… name)

Implements #3. Reports files that declare more than one top-level type or
whose single type does not match the file name. Generic overloads are
arity-encoded by default (Result{T}.cs) or may share a base-named file when
NetEvolveAnalyzerGroupGenericOverloads is set. The rule disables itself for
single-file publish (PublishSingleFile) and via
NetEvolveAnalyzerDisableFileOrganizationRules.

- Analyzer + NE0001 registration + release-tracking entry + docs
- Consumer build props expose the CompilerVisibleProperty values it reads
- Namespace-scoped type identity, so distinct same-named types in different
  namespaces are each evaluated (adversarial-review finding)
- File-name-aware unit verifier (named sources + build-property injection)
  and an integration harness with tree path + AnalyzerConfigOptions
- 29 unit + 8 integration tests; src coverage: unit 98.9%, integration 88.2%,
  project 100%

Also removes a stray line in AnalyzerReleases.Shipped.md that failed RS2007.

Refs #3 #6

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Aug 3, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are limited based on label configuration.

🏷️ Required labels (at least one) (1)
  • state:ready for merge

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro Plus

Run ID: 96cbba5d-d7f6-4591-9c7c-fcae48cad8c9

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

The test-tree .editorconfig that disabled IDE0058 for TUnit's awaited
assertions is git-ignored (.gitignore rule **/.editorconfig, keeping only the
root .editorconfig), so it never reached CI. There, code-style enforcement
failed on every `await Assert.That(...)` expression statement — including the
pre-existing seed tests. The root .editorconfig is template-managed
("DO NOT CHANGE SETTINGS IN THIS FILE").

Add a committed test/Directory.Build.props that chains to the root props and
sets NoWarn=IDE0058 for all test projects (current and future).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@codecov

codecov Bot commented Aug 3, 2026

Copy link
Copy Markdown

Welcome to Codecov 🎉

Once you merge this PR into your default branch, you're all set! Codecov will compare coverage reports and display results in all future pull requests.

Thanks for integrating Codecov - We've got you covered ☂️

@samtrion
samtrion merged commit ec14219 into main Aug 3, 2026
9 checks 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.

analyzer: NE0001 — one top-level type per file, file name equals type name

1 participant