Fade unused directives, add "Remove unnecessary" code action and support Remove and Sort commands#12831
Merged
davidwengier merged 49 commits intomainfrom Feb 26, 2026
Merged
Conversation
…s produced the data
Contributor
There was a problem hiding this comment.
Pull request overview
Adds end-to-end support for detecting and fading unused Razor directives and offering a “Remove unnecessary directives” code action, leveraging Roslyn’s unused-imports diagnostics where possible and adding legacy @addTagHelper coverage.
Changes:
- Introduces unused-directive diagnostics plumbing (including caching) to power fading + removal code actions.
- Tracks directive → tag helper contributions during compilation to distinguish “unused in C#” vs “used for component/tag helper binding”.
- Adds cohost code action + diagnostics tests, updates resources, and bumps Roslyn dependency versions.
Reviewed changes
Copilot reviewed 43 out of 43 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CohostDocumentPullDiagnosticsTest.cs | Adds cohost diagnostics tests for unused @using and legacy @addTagHelper. |
| src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CodeActions/RemoveUnnecessaryDirectiveTests.cs | New tests validating the “Remove unnecessary directives” code action behavior. |
| src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/Shared/CodeActions/CohostCodeActionsEndpointTestBase.cs | Extends code action test harness to optionally fetch real diagnostics before requesting code actions. |
| src/Razor/test/Microsoft.VisualStudioCode.RazorExtension.Test/Endpoints/CohostDocumentPullDiagnosticsTest.cs | Refactors diagnostics test helper and exposes a shared diagnostics-request helper for code action tests. |
| src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/CohostDocumentPullDiagnosticsTest.cs | Mirrors diagnostics helper refactor for VS cohost tests and adds shared diagnostics-request helper. |
| src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/CSharpTestLspServer.cs | Adjusts reflection invocation for Roslyn language server lifecycle calls after dependency/API changes. |
| src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Diagnostics/RemoteDiagnosticsService.cs | Normalizes unused-import diagnostics to Razor’s RZ0005, sets unnecessary tags, caches unused directive line info, and adds legacy @addTagHelper unused diagnostics. |
| src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/RemoteServices.cs | Exports new OOP provider/resolver for remove-unnecessary-directives code action. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hant.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.zh-Hans.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.tr.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ru.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pt-BR.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.pl.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ko.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.ja.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.it.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.fr.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.es.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.de.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/xlf/SR.cs.xlf | Adds localized string entry for “Remove unnecessary directives”. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Resources/SR.resx | Adds the new resource key/value for the code action title. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/LanguageServerConstants.cs | Adds RemoveUnnecessaryDirectives code action name constant. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/UsingDirectiveHelper.cs | Extracts reusable helper to compute the text edit for removing a directive line/span. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/RazorSyntaxTreeExtensions.cs | Adds helper to enumerate @addTagHelper directives. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Extensions/RazorSyntaxNodeExtensions.cs | Adds directive identification helper and span-trimming utility for directive ranges. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/UnusedDirectiveCache.cs | New cache for unused-directive line numbers keyed to a RazorCodeDocument. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Diagnostics/RazorTranslateDiagnosticsService.cs | Updates C# diagnostic filtering to handle unused-using diagnostics with Razor-specific usage semantics. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/RemoveUnnecessaryDirectivesCodeActionResolver.cs | New resolver that applies removal edits for all unused directive spans. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/RemoveUnnecessaryDirectivesCodeActionProvider.cs | New provider that offers the removal code action when selection is on a directive and cached unused directives exist. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Razor/RazorCodeActionFactory.cs | Adds code action factory method, localized title, telemetry id, and ordering for the new action. |
| src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/CodeActions/Models/RemoveUnnecessaryDirectivesCodeActionParams.cs | New model carrying the unused directive spans to the resolver. |
| src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/RazorLifeCycleManager.cs | Updates lifecycle API surface (Shutdown signature change) for updated protocol/framework APIs. |
| src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeDocumentExtensions.cs | Adds imports-file detection and directive usage evaluation based on recorded contributions and referenced tag helpers. |
| src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/RazorCodeDocument.cs | Stores directive tag helper contribution data on the code document. |
| src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DirectiveTagHelperContribution.cs | New record representing a directive’s contributed tag helpers. |
| src/Compiler/Microsoft.CodeAnalysis.Razor.Compiler/src/Language/DefaultRazorTagHelperContextDiscoveryPhase.cs | Records per-directive contributions while discovering tag helpers/components. |
| src/Compiler/Microsoft.AspNetCore.Razor.Language/test/RazorCodeDocumentExtensionsTest.cs | Adds unit tests for directive contribution storage and directive usage evaluation. |
| src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/TagHelpersIntegrationTest.cs | Adds integration tests validating @addTagHelper directive usage tracking. |
| src/Compiler/Microsoft.AspNetCore.Razor.Language/test/IntegrationTests/ComponentDiscoveryIntegrationTest.cs | Adds integration tests validating @using directive usage tracking for components and fully-qualified tags. |
| eng/Version.Details.xml | Bumps Roslyn dependency versions/SHA and updates Arcade SDK toolset dependency. |
| eng/Version.Details.props | Updates Roslyn package version properties and Arcade SDK version property. |
| .github/skills/update-roslyn-version/SKILL.md | Adds a repo skill guide for performing Roslyn version bumps consistently. |
Comments suppressed due to low confidence (2)
.github/skills/update-roslyn-version/SKILL.md:24
- The skill text is machine-specific (‘D:\NugetCache on this machine’). Since this lives in the repo and should be reusable, consider rewording step 5 to refer to the user’s NuGet cache generically (and keep the platform-specific paths in the Notes section).
5. **Get the commit hash**: After restore, find a `.nuspec` file for one of the restored Roslyn packages in the NuGet cache (`D:\NugetCache` on this machine). For example:
D:\NugetCache\microsoft.codeanalysis.common<NEW_VERSION>\microsoft.codeanalysis.common.nuspec
Parse the `<repository commit="...">` element from the nuspec to extract the commit SHA. All Roslyn packages share the same commit.
eng/Version.Details.xml:105
- This PR description calls out a Roslyn bump, but these changes also modify the Microsoft.DotNet.Arcade.Sdk toolset dependency (and appear to downgrade it from 10.0.0-beta.26123.2 to 10.0.0-beta.26110.1). If this isn’t intentional/required for the Roslyn update, consider reverting it or updating the PR description to explain why Arcade needs to change too.
<Dependency Name="Microsoft.DotNet.Arcade.Sdk" Version="10.0.0-beta.26110.1">
<Uri>https://github.com/dotnet/arcade</Uri>
<Sha>4bf37ce670528cf2aef4d9b1cd892554b1b02d9d</Sha>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
davidwengier
commented
Feb 25, 2026
davidwengier
commented
Feb 25, 2026
davidwengier
commented
Feb 25, 2026
Member
Author
|
Have pushed changes for each comment. Ready for round 2. |
…gsCodeAction' into dev/dawengie/RemoveAndSortUsingsCommands
Member
Author
|
@chsienki would be good to get your sign-off on the compiler changes, just in case. |
chsienki
approved these changes
Feb 26, 2026
…e/RazorCodeDocumentExtensions.cs Co-authored-by: Chris Sienkiewicz <chsienki@microsoft.com>
Fixes #8548 This is the final piece of the puzzle, makes the menu items and keyboard shortcuts work. This was really just putting the pieces of lego from the two previous PRs together, plus VS commanding nonsense. <img width="425" height="83" alt="image" src="https://github.com/user-attachments/assets/e49c3946-4350-447c-b156-f1853eb59759" /> 
This was referenced Feb 27, 2026
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.
Fixes a very large portion of #8548
This adds diagnostics and fading of unnecessary

@usingdirectives in Razor and MVC, and unnecessary@addTagHelperdirectives in Legacy. Also adds a "Remove unnecessary directives" code action whenever the cursor is in the block of directives. Looks like this:Also needed a Roslyn bump so a couple of slight changes due to API differences, and I added a copilot skill so we can just ask copilot to do Roslyn bumps for us in future.
(redo of #12804 so I can keep working on the next phase)