Skip to content

feature: Tier 3 custom Roslyn analyzers CX001–CX004 (#49, #46) - #95

Merged
mcpolo99 merged 4 commits into
developfrom
49-tier3-custom-roslyn-analyzers
Jul 4, 2026
Merged

feature: Tier 3 custom Roslyn analyzers CX001–CX004 (#49, #46)#95
mcpolo99 merged 4 commits into
developfrom
49-tier3-custom-roslyn-analyzers

Conversation

@mcpolo99

@mcpolo99 mcpolo99 commented Jul 4, 2026

Copy link
Copy Markdown
Owner

Implements the Tier 3 ConfuserEx-specific analyzers — all four rules — completing #49. With #46's Tier 1 (built-in analyzers) and Tier 2 (Roslynator) already wired, this also finishes #46.

Closes #49
Closes #46

New: Confuser.Analyzers project

A netstandard2.0 Roslyn analyzer assembly wired into every project via ConfuserEx.Common.targets (SkipGetTargetFrameworkProperties + UndefineProperties so it attaches even to the net20 runtime).

The four rules

ID Rule Severity Violations fixed
CX004 Assembly/Module.GetTypes() without ReflectionTypeLoadException handling Warning 2 (PluginDiscovery, ComponentDiscovery)
CX003 Resolve...Throw audit Info 0 (awareness; ~34 intentional uses, no build noise)
CX002 ResolveTypeDef()/ResolveMethodDef() result dereferenced without a null check Warning 0 (pure prevention)
CX001 Import(Type.GetMethod/GetConstructor/...) — host-reflection import (wrong-corlib) Warning 1 (Utils.cs fallback, documented + suppressed)

Design notes (the issue was partly stale — verified against current code)

  • CX004 resolves the invocation symbol so it only fires for System.Reflection types — dnlib's ModuleDef.GetTypes() (returns TypeDef, never throws) is correctly ignored.
  • CX002 flags only genuine dereferences. The VTableAnalyzer sites the issue listed pass results to dnlib's null-tolerant SigComparer.Equals — not a crash — so they are correctly not flagged (no false positive).
  • CX001 was redesigned: the issue's three call sites were already refactored to a context-aware Import(context, Type, method) helper. The only remaining host-reflection path is that helper's last-resort fallback, which CX001 now targets; it's isolated and suppressed with a documented pragma.

Tests & verification

  • 17 analyzer unit tests (Microsoft.CodeAnalysis.Testing) covering fire/no-fire for every rule.
  • Full solution builds clean with all analyzers wired — zero CX diagnostics (violations fixed/suppressed).

Develop PRs are gated, so nothing runs automatically; validated locally.

RandomCrocodile added 3 commits July 4, 2026 14:43
First increment of the Tier 3 custom analyzers (#49, parent #46). Establishes the
Confuser.Analyzers project (netstandard2.0 Roslyn analyzer) and wires it into every
project via ConfuserEx.Common.targets as an analyzer reference.

CX004 — flags Assembly.GetTypes()/Module.GetTypes() that are not guarded against
ReflectionTypeLoadException (the cause of packer/plugin startup crashes). The
analyzer resolves the invocation symbol and only fires for System.Reflection types,
so dnlib's ModuleDef.GetTypes() (which returns TypeDef and never throws) is ignored.

- Fixed the two real CX004 violations: PluginDiscovery.AddPlugins and
  ComponentDiscovery.LoadComponents now catch ReflectionTypeLoadException and keep
  the types that loaded.
- Analyzer wired with SkipGetTargetFrameworkProperties + UndefineProperties so the
  netstandard2.0 analyzer attaches to all targets including net20.
- 4 analyzer unit tests (fires on unguarded; silent when guarded by RTLE/Exception
  or on unrelated GetTypes()). Full solution builds clean with zero CX004 warnings.

Remaining under #49 (follow-up): CX002 (unguarded Resolve*Def), CX003 (ResolveThrow
audit). CX001's premise is stale — the listed call sites were refactored to a
context-aware Import helper; the only host-reflection path left is that helper's
fallback (Confuser.Protections/Utils.cs).
CX003 surfaces every call to a dnlib Resolve...Throw helper (ResolveThrow,
ResolveTypeDefThrow, ResolveMethodDefThrow, ResolveFieldThrow) at Info severity —
an awareness rule for spots that crash on unresolvable references. Info severity
means no build noise (the ~34 existing intentional uses are not reported as
warnings). 5 tests.
Completes the four Tier 3 analyzers.

CX002 — flags a non-throwing ResolveTypeDef()/ResolveMethodDef() result that is
dereferenced immediately with no null check (crashes on external/unresolvable
references). Only genuine dereferences are flagged (x.ResolveTypeDef().Member /
[i]); null-conditional access, assignment, return, and passing the result as an
argument (e.g. to dnlib's null-tolerant SigComparer.Equals, as VTableAnalyzer
does) are correctly not reported. No existing violations — pure prevention.

CX001 — redesigned against the current code. The issue's original call sites were
already refactored to a context-aware Import(context, Type, method) helper; the
only remaining host-reflection path is that helper's last-resort fallback. CX001
now flags Import(...) whose argument is Type.GetMethod/GetConstructor/GetField/
GetProperty (host reflection → wrong-corlib reference). The single intentional
fallback in Confuser.Protections/Utils.cs is isolated and suppressed with a
documented pragma; new occurrences are flagged.

8 new analyzer tests (17 total). Full solution builds clean — zero CX
diagnostics.
@mcpolo99 mcpolo99 changed the title feature: Tier 3 analyzers — CX004 + CX003 (#49) feature: Tier 3 custom Roslyn analyzers CX001–CX004 (#49, #46) Jul 4, 2026
…slyn-analyzers

# Conflicts:
#	Confuser2.sln
@mcpolo99
mcpolo99 merged commit 44e6f29 into develop Jul 4, 2026
3 checks passed
@mcpolo99
mcpolo99 deleted the 49-tier3-custom-roslyn-analyzers branch July 4, 2026 13:49
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