Skip to content

Fade unused directives, add "Remove unnecessary" code action and support Remove and Sort commands#12831

Merged
davidwengier merged 49 commits intomainfrom
dev/dawengie/RemoveUnusuedUsingsCodeAction
Feb 26, 2026
Merged

Fade unused directives, add "Remove unnecessary" code action and support Remove and Sort commands#12831
davidwengier merged 49 commits intomainfrom
dev/dawengie/RemoveUnusuedUsingsCodeAction

Conversation

@davidwengier
Copy link
Copy Markdown
Member

Fixes a very large portion of #8548

This adds diagnostics and fading of unnecessary @using directives in Razor and MVC, and unnecessary @addTagHelper directives in Legacy. Also adds a "Remove unnecessary directives" code action whenever the cursor is in the block of directives. Looks like this:
image

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)

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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>
Comment thread eng/Version.Details.props Outdated
Comment thread eng/Version.Details.xml Outdated
Comment thread eng/Version.Details.xml Outdated
@davidwengier
Copy link
Copy Markdown
Member Author

Have pushed changes for each comment. Ready for round 2.

@davidwengier davidwengier added the feature request Large improvement request label Feb 26, 2026
Copy link
Copy Markdown
Contributor

@ToddGrun ToddGrun left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

:shipit:

@davidwengier
Copy link
Copy Markdown
Member Author

@chsienki would be good to get your sign-off on the compiler changes, just in case.

davidwengier and others added 2 commits February 27, 2026 08:00
…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"
/>


![a3859981-6778-4aae-a0eb-6d522a5e8e26](https://github.com/user-attachments/assets/22b9d3e9-92d0-4573-9405-5b8fa4634700)
@davidwengier davidwengier changed the title Fade unused directives, and add code action to remove Fade unused directives, add "Remove unnecessary" code action and support Remove and Sort commands Feb 26, 2026
@davidwengier davidwengier merged commit 7f0dced into main Feb 26, 2026
10 checks passed
@davidwengier davidwengier deleted the dev/dawengie/RemoveUnusuedUsingsCodeAction branch February 26, 2026 23:14
@dotnet-policy-service dotnet-policy-service Bot added this to the Next milestone Feb 26, 2026
@jjonescz jjonescz modified the milestones: Next, 18.6 Mar 31, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature request Large improvement request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants