File: AddFileBanner\AddFileBannerHelpers.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;
using System.Collections.Immutable;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.LanguageService;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.Utilities;
 
namespace Microsoft.CodeAnalysis.AddFileBanner;
 
internal static class AddFileBannerHelpers
{
    public static async Task<Document> CopyBannerAsync(
        Document destinationDocument,
        string? destinationFilePath,
        Document sourceDocument,
        CancellationToken cancellationToken)
    {
        var bannerService = destinationDocument.GetRequiredLanguageService<IFileBannerFactsService>();
 
        var fromRoot = await sourceDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
        var sourceBanner = bannerService.GetFileBanner(fromRoot);
 
        sourceBanner = UpdateEmbeddedFileNames(
            sourceDocument, destinationFilePath, sourceBanner, bannerService.CreateTrivia);
 
        var destinationRoot = await destinationDocument.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);
        var destinationBanner = bannerService.GetFileBanner(destinationRoot);
 
        var firstToken = destinationRoot.GetFirstToken();
        var newRoot = destinationRoot.ReplaceToken(
            firstToken,
            firstToken.WithLeadingTrivia(
                sourceBanner.Concat(firstToken.LeadingTrivia.Skip(destinationBanner.Length))));
        return destinationDocument.WithSyntaxRoot(newRoot);
    }
 
    /// <summary>
    /// Looks at <paramref name="banner"/> to see if it contains the name of <paramref name="sourceDocument"/>
    /// in it.  If so, those names will be replaced with <paramref name="destinationFilePath"/>.
    /// </summary>
    private static ImmutableArray<SyntaxTrivia> UpdateEmbeddedFileNames(
        Document sourceDocument,
        string? destinationFilePath,
        ImmutableArray<SyntaxTrivia> banner,
        Func<SyntaxTrivia, string, SyntaxTrivia> createTrivia)
    {
        var sourceName = IOUtilities.PerformIO(() => Path.GetFileName(sourceDocument.FilePath));
        var destinationName = IOUtilities.PerformIO(() => Path.GetFileName(destinationFilePath));
        if (string.IsNullOrEmpty(sourceName) || string.IsNullOrEmpty(destinationName))
            return banner;
 
        var result = new FixedSizeArrayBuilder<SyntaxTrivia>(banner.Length);
        foreach (var trivia in banner)
        {
            var updated = createTrivia(trivia, trivia.ToFullString().Replace(sourceName, destinationName));
            result.Add(updated);
        }
 
        return result.MoveToImmutable();
    }
}