dotnet/roslyn

Sync Namespaces at folder level

Open

#79,185 创建于 2025年6月28日

在 GitHub 查看
 (1 评论) (0 反应) (0 负责人)C# (4,257 fork)batch import
Area-IDEhelp wanted

仓库指标

Star
 (20,414 star)
PR 合并指标
 (平均合并 6天 17小时) (30 天内合并 256 个 PR)

描述

#74777 #61479 comment

Currently the context menu can only be used for solution or single project.

TBD

Is sync just for the selected folder / folders or should there be multiple options Directory Directory and descendants Directory and ascendants

Solution - for single directory

  1. Add to commands.vsct

<CommandPlacement guid="guidRoslynGrpId" id="cmdidSyncNamespaces" priority="0xF200"> <Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_FOLDER_ADD" /> </CommandPlacement>

  1. Change the VisualStudioCommandHandlerHelpers to look for C# code files Look for single in OnSyncNamespacesForSelectedProjectStatus Look for multiple in OnSyncNamespacesForSelectedProject More on this later

  2. SyncNamespacesCommandHandler changes In adition to the new folder functionality it addresses shared folders that do not work and allows working in a .Net Framework non sdk style project. The CollectFolderCSharpFiles enumeration allows for DirectoryAndDescendants ....

    private void OnSyncNamespacesForSelectedProjectStatus(object sender, EventArgs e)
    {
        var command = (OleMenuCommand)sender;

        var visible = false;

        if (VisualStudioCommandHandlerHelpers.TryGetSelectedProjectHierarchyWithSelectionDetails(_serviceProvider, CollectFolderCSharpFiles.Directory, out var projectHierarchy, out var projectOrFolderWithCSharpFiles))
        {
            var isShared = projectHierarchy.TryGetProjectFilePath()?.EndsWith(".shproj") == true;
            if (!isShared)
            {
                visible = projectOrFolderWithCSharpFiles && projectHierarchy.IsCapabilityMatch("CSharp");
            }
        }

The code files are then passed to the service as a new argument.

    private void OnSyncNamespacesForSelectedProject(object sender, EventArgs args)
    {
        if (VisualStudioCommandHandlerHelpers.TryGetSelectedProjectHierarchyWithCSharpFilePaths(_serviceProvider, CollectFolderCSharpFiles.Directory, out var projectHierarchy, out var cSharpFilePaths))
        {
            var projects = GetProjectsForHierarchy(projectHierarchy);

            SyncNamespaces(projects, cSharpFilePaths);
        }
internal interface ISyncNamespacesService : ILanguageService
{
    Task<Solution> SyncNamespacesAsync(
        ImmutableArray<Project> projects, ImmutableArray<string>? codeFilePaths, IProgress<CodeAnalysisProgress> progressTracker, CancellationToken cancellationToken);
}

The AbstractSyncNamespacesService will use GetAnalysisResultAsync for the SyntaxTree of each code file if code files are passed (using FileUtilities.TryNormalizeAbsolutePath ) otherwise will continue to use GetAnalyzerDiagnosticsAsync.

How I have implemented 2.

Created a VisualStudioFolderWalker helper that uses IVsHierarchy and __VSHPROPID.VSHPROPID_FirstChild, __VSHPROPID.VSHPROPID_NextSibling __VSHPROPID.VSHPROPID_TypeGuid

to walk and has predicates for descending directories and completion.

The VisualStudioCommandHandlerHelpers determines when to descend based on the CollectFolderCSharpFiles enumeration parameter and collects the C# code files from the walker predicate ( returning early when presence of a code file is all that is required). If multi select then IVsMultiItemSelect.GetSelectedItems is used for walking each folder.

贡献者指南