File: Services\SemanticClassification\RemoteSemanticClassificationService.cs
Web Access
Project: src\src\Workspaces\Remote\ServiceHub\Microsoft.CodeAnalysis.Remote.ServiceHub.csproj (Microsoft.CodeAnalysis.Remote.ServiceHub)
// 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.Classification;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.Remote;
 
internal sealed partial class RemoteSemanticClassificationService : BrokeredServiceBase, IRemoteSemanticClassificationService
{
    internal sealed class Factory : FactoryBase<IRemoteSemanticClassificationService>
    {
        protected override IRemoteSemanticClassificationService CreateService(in ServiceConstructionArguments arguments)
            => new RemoteSemanticClassificationService(arguments);
    }
 
    public ValueTask<SerializableClassifiedSpans> GetClassificationsAsync(
        Checksum solutionChecksum,
        DocumentId documentId,
        ImmutableArray<TextSpan> spans,
        ClassificationType type,
        ClassificationOptions options,
        bool isFullyLoaded,
        CancellationToken cancellationToken)
    {
        return RunServiceAsync(solutionChecksum, async solution =>
        {
            var document = solution.GetDocument(documentId) ?? await solution.GetSourceGeneratedDocumentAsync(documentId, cancellationToken).ConfigureAwait(false);
            Contract.ThrowIfNull(document);
 
            // Frozen partial semantics is not automatically passed to OOP, so enable it explicitly when desired
            document = options.FrozenPartialSemantics ? document.WithFrozenPartialSemantics(cancellationToken) : document;
            solution = document.Project.Solution;
 
            using var _ = Classifier.GetPooledList(out var temp);
 
            // Safe to do this.  The remote classification service only runs for C#/VB.  So we know we'll always
            // have this service and it will always be this type.
            var classificationService = (AbstractClassificationService)document.GetRequiredLanguageService<IClassificationService>();
            await classificationService.AddClassificationsAsync(
                document, spans, options, type, temp, cancellationToken).ConfigureAwait(false);
 
            if (isFullyLoaded)
            {
                // Once fully loaded, there's no need for us to keep around any of the data we cached in-memory
                // during the time the solution was loading.
                lock (_cachedData)
                    _cachedData.Clear();
 
                // Enqueue this document into our work queue to fully classify and cache.
                _workQueue.AddWork((document, type, options));
            }
 
            return SerializableClassifiedSpans.Dehydrate([.. temp]);
        }, cancellationToken);
    }
}