File: Completion\Providers\ImportCompletionProvider\ImportCompletionProviderHelpers.cs
Web Access
Project: src\src\Features\Core\Portable\Microsoft.CodeAnalysis.Features.csproj (Microsoft.CodeAnalysis.Features)
// 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.Immutable;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.AddImport;
using Microsoft.CodeAnalysis.Editing;
using Microsoft.CodeAnalysis.Formatting;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
 
namespace Microsoft.CodeAnalysis.Completion.Providers;
 
internal static class ImportCompletionProviderHelpers
{
    /// <summary>
    /// Gets the changes needed to add a particular import for <paramref name="namespaceName"/> to the supplied document.
    /// </summary>
    public static async Task<ImmutableArray<TextChange>> GetAddImportTextChangesAsync(
        Document document, int completionItemPosition, string namespaceName, CancellationToken cancellationToken)
    {
        // Find context node so we can use it to decide where to insert using/imports.
        var tree = await document.GetRequiredSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);
        var root = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false);
        var addImportContextNode = root.FindToken(completionItemPosition, findInsideTrivia: true).Parent;
 
        // Add required using/imports directive.
        var addImportService = document.GetRequiredLanguageService<IAddImportsService>();
        var generator = document.GetRequiredLanguageService<SyntaxGenerator>();
 
        var addImportsOptions = await document.GetAddImportPlacementOptionsAsync(cancellationToken).ConfigureAwait(false);
        var formattingOptions = await document.GetSyntaxFormattingOptionsAsync(cancellationToken).ConfigureAwait(false);
 
        var syntaxGenerator = SyntaxGenerator.GetGenerator(document);
        var importNode = syntaxGenerator.NamespaceImportDeclaration(namespaceName).WithAdditionalAnnotations(Formatter.Annotation);
 
        var compilation = await document.Project.GetRequiredCompilationAsync(cancellationToken).ConfigureAwait(false);
        if (addImportService.HasExistingImport(compilation, root, addImportContextNode, importNode, syntaxGenerator))
            return [];
 
        var rootWithImport = addImportService.AddImport(compilation, root, addImportContextNode!, importNode, generator, addImportsOptions, cancellationToken);
        var documentWithImport = document.WithSyntaxRoot(rootWithImport);
 
        // This only formats the annotated import we just added, not the entire document.
        var formattedDocumentWithImport = await Formatter.FormatAsync(documentWithImport, Formatter.Annotation, formattingOptions, cancellationToken).ConfigureAwait(false);
        var importChanges = await formattedDocumentWithImport.GetTextChangesAsync(document, cancellationToken).ConfigureAwait(false);
        return [.. importChanges];
    }
}