Cover type forwarding and other gaps#138
Merged
dfederm merged 3 commits intodfederm:dfederm/symbol-based-usage-detectionfrom Apr 20, 2026
Merged
Conversation
dfederm
added a commit
that referenced
this pull request
Apr 24, 2026
* Add experimental symbol-based usage detection (opt-in) Replace the GetUsedAssemblyReferences approach with a Roslyn analyzer that tracks symbol usage at finer granularity, behind the ReferenceTrimmerUseSymbolAnalysis MSBuild property (opt-in, defaults to false). The new approach uses RegisterSymbolAction and RegisterOperationAction to track which assemblies contain symbols that the code actually references, rather than relying on the compiler's broader 'used assembly' heuristic which over-reports usage by treating transitive assembly dependencies as used. Key design decisions: - RT0001 (bare Reference): always uses conservative transitive closure to avoid breaking runtime dependencies that lack automatic transitive resolution - RT0002 (ProjectReference): uses transitive closure only when DisableTransitiveProjectReferences is set; otherwise uses precise detection - RT0003 (PackageReference): always uses precise symbol-based detection since NuGet handles transitive package deps automatically - Attribute constructor/named arguments (including typeof) are tracked - Early exit optimization when all reference assemblies are already tracked The legacy GetUsedAssemblyReferences code path is preserved as the default. All E2E tests run in both modes via DataRow parameterization (91 pass). Version bumped from 3.4 to 3.5. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Cover type forwarding and other gaps (#138) * type forwarding * Fill out the gaps * Add tests * Improve symbol-based analysis coverage, perf, and testing - Fill operation coverage gaps: switch patterns (statement + expression), default expressions, user-defined operators (binary/unary/compound/ increment-decrement), function pointer types, and conversion operand types - Performance: replace ConcurrentDictionary.Count (acquires all stripe locks on .NET Framework) with a monotonic int flag on the hot path; skip tracking for the compilation's own assembly via ReferenceEquals - Platform-aware path comparers: case-insensitive on Windows/macOS, case-sensitive on Linux (addresses PR review feedback) - Rename legacy -> default for the GetUsedAssemblyReferences analysis path - Add analyzer unit tests (19 tests, ~6s) using CompilationWithAnalyzers for fast, targeted coverage of symbol tracking logic - Replace E2E edge-case tests with unit tests to reduce test data bloat - Add Microsoft.CodeAnalysis.CSharp.Workspaces package reference for tests Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * Improve symbol analysis: fix perf, track local vars, add 17 tests - Replace ConcurrentDictionary.Count with Interlocked.Increment counter to avoid acquiring all stripe locks on .NET Framework - Simplify allTracked flag to just trackedCount >= totalReferenceCount - Track local variable types via IVariableDeclaratorOperation - Add 17 new analyzer tests (19 -> 36 total): - nameof, XML doc cref (with doc mode on/off), type forwarding - local variables, lambdas, local functions, arrays, attributes - recursive patterns, events - PackageReference (RT0003): unused, used, multi-assembly aggregation - Bare Reference (RT0001): unused with transitive closure - Fix test isolation: lambda and local function tests now use the specific handler as the sole tracking path Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --------- Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> Co-authored-by: olstakh <45368758+olstakh@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This pull request enhances the ReferenceTrimmer analyzer to more accurately detect used project references in C# code, especially in cases that previously required syntax-level analysis. The changes add support for tracking references used only in
nameof()expressions, XML documentation<cref>attributes, and advanced pattern-matching constructs. Comprehensive tests are included to verify these scenarios.Analyzer improvements:
nameof()expressions and XML doc<cref>references, ensuring references used only in these contexts are not incorrectly reported as unused. This is implemented via a newRegisterCSharpSyntaxTrackingmethod and corresponding registration in the analyzer. [1] [2] [3]sizeofoperations, improving accuracy for modern C# code. [1] [2]Test coverage:
nameof(), XML doc<cref>, and advanced switch patterns, with corresponding test projects and source files. [1] [2] [3] [4] [5] [6] [7] [8] [9]These improvements ensure that the analyzer correctly identifies all used references, even in subtle or modern C# usage patterns.