| File: Rename\Renamer.SyncNamespaceDocumentAction.cs | Web Access |
| Project: src\roslyn\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. using System.Collections.Generic; using System.Globalization; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ChangeNamespace; using Microsoft.CodeAnalysis.LanguageService; using Microsoft.CodeAnalysis.Shared.Extensions; using Microsoft.CodeAnalysis.Shared.Utilities; namespace Microsoft.CodeAnalysis.Rename; public static partial class Renamer { /// <summary> /// Action that will sync the namespace of the document to match the folders property /// of that document, similar to if a user performed the "Sync Namespace" code refactoring. /// /// For example, if a document is moved from "Bat/Bar/Baz" folder structure to "Bat/Bar/Baz/Bat" and contains /// a namespace definition of Bat.Bar.Baz in the document, then it would update that definition to /// Bat.Bar.Baz.Bat and update the solution to reflect these changes. Uses <see cref="IChangeNamespaceService"/> /// </summary> internal sealed class SyncNamespaceDocumentAction : RenameDocumentAction { private readonly AnalysisResult _analysis; private SyncNamespaceDocumentAction(AnalysisResult analysis) : base([]) { _analysis = analysis; } public override string GetDescription(CultureInfo? culture) => WorkspacesResources.ResourceManager.GetString("Sync_namespace_to_folder_structure", culture ?? WorkspacesResources.Culture)!; internal override async Task<Solution> GetModifiedSolutionAsync(Document document, DocumentRenameOptions options, CancellationToken cancellationToken) { var changeNamespaceService = document.GetRequiredLanguageService<IChangeNamespaceService>(); var solution = await changeNamespaceService.TryChangeTopLevelNamespacesAsync(document, _analysis.TargetNamespace, cancellationToken).ConfigureAwait(false); // If the solution fails to update fail silently. The user will see no large // negative impact from not doing this modification, and it's possible the document // was too malformed to update any namespaces. return solution ?? document.Project.Solution; } public static SyncNamespaceDocumentAction? TryCreate(Document document, IReadOnlyList<string> newFolders) { var analysisResult = Analyze(document, newFolders); if (analysisResult.HasValue) { return new SyncNamespaceDocumentAction(analysisResult.Value); } return null; } private static AnalysisResult? Analyze(Document document, IReadOnlyCollection<string> newFolders) { // https://github.com/dotnet/roslyn/issues/41841 // VB implementation is incomplete for sync namespace if (document.Project.Language == LanguageNames.CSharp) { var syntaxFacts = document.GetRequiredLanguageService<ISyntaxFactsService>(); var targetNamespace = PathMetadataUtilities.TryBuildNamespaceFromFolders(newFolders, syntaxFacts, document.Project.DefaultNamespace); if (targetNamespace is null) { return null; } return new AnalysisResult(targetNamespace); } else { return null; } } private readonly struct AnalysisResult(string targetNamespace) { public string TargetNamespace { get; } = targetNamespace; } } }