Example #1
0
        private static async Task ClassifySpansAsync(
            TaggerContext <IClassificationTag> context,
            DocumentSnapshotSpan spanToTag,
            IClassificationService classificationService,
            ClassificationTypeMap typeMap)
        {
            try
            {
                var document     = spanToTag.Document;
                var snapshotSpan = spanToTag.SnapshotSpan;
                var snapshot     = snapshotSpan.Snapshot;

                var cancellationToken = context.CancellationToken;
                using (Logger.LogBlock(FunctionId.Tagger_SemanticClassification_TagProducer_ProduceTags, cancellationToken))
                {
                    var classifiedSpans = ClassificationUtilities.GetOrCreateClassifiedSpanList();

                    await classificationService.AddSemanticClassificationsAsync(
                        document, snapshotSpan.Span.ToTextSpan(), classifiedSpans, cancellationToken : cancellationToken).ConfigureAwait(false);

                    ClassificationUtilities.Convert(typeMap, snapshotSpan.Snapshot, classifiedSpans, context.AddTag);
                    ClassificationUtilities.ReturnClassifiedSpanList(classifiedSpans);

                    var version = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                    // Let the context know that this was the span we actually tried to tag.
                    context.SetSpansTagged(SpecializedCollections.SingletonEnumerable(spanToTag));
                    context.State = version;
                }
            }
            catch (Exception e) when(FatalError.ReportUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private static async Task AddSemanticClassificationsAsync(
            Document document,
            TextSpan textSpan,
            IClassificationService classificationService,
            ArrayBuilder <ClassifiedSpan> classifiedSpans,
            CancellationToken cancellationToken)
        {
            var workspaceStatusService = document.Project.Solution.Workspace.Services.GetRequiredService <IWorkspaceStatusService>();

            // Importantly, we do not await/wait on the fullyLoadedStateTask.  We do not want to ever be waiting on work
            // that may end up touching the UI thread (As we can deadlock if GetTagsSynchronous waits on us).  Instead,
            // we only check if the Task is completed.  Prior to that we will assume we are still loading.  Once this
            // task is completed, we know that the WaitUntilFullyLoadedAsync call will have actually finished and we're
            // fully loaded.
            var isFullyLoadedTask = workspaceStatusService.IsFullyLoadedAsync(cancellationToken);
            var isFullyLoaded     = isFullyLoadedTask.IsCompleted && isFullyLoadedTask.GetAwaiter().GetResult();

            // If we're not fully loaded try to read from the cache instead so that classifications appear up to date.
            // New code will not be semantically classified, but will eventually when the project fully loads.
            if (await TryAddSemanticClassificationsFromCacheAsync(document, textSpan, classifiedSpans, isFullyLoaded, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            await classificationService.AddSemanticClassificationsAsync(
                document, textSpan, classifiedSpans, cancellationToken).ConfigureAwait(false);
        }
Example #3
0
        private static async Task ClassifySpansAsync(
            TaggerContext <IClassificationTag> context,
            DocumentSnapshotSpan spanToTag,
            IClassificationService classificationService,
            ClassificationTypeMap typeMap,
            ClassificationOptions options,
            CancellationToken cancellationToken)
        {
            try
            {
                var document     = spanToTag.Document;
                var snapshotSpan = spanToTag.SnapshotSpan;
                var snapshot     = snapshotSpan.Snapshot;

                using (Logger.LogBlock(FunctionId.Tagger_SemanticClassification_TagProducer_ProduceTags, cancellationToken))
                {
                    using var _ = ArrayBuilder <ClassifiedSpan> .GetInstance(out var classifiedSpans);

                    await classificationService.AddSemanticClassificationsAsync(
                        document,
                        snapshotSpan.Span.ToTextSpan(),
                        options,
                        classifiedSpans,
                        cancellationToken).ConfigureAwait(false);

                    foreach (var span in classifiedSpans)
                    {
                        context.AddTag(ClassificationUtilities.Convert(typeMap, snapshotSpan.Snapshot, span));
                    }

                    var version = await document.Project.GetDependentSemanticVersionAsync(cancellationToken).ConfigureAwait(false);

                    // Let the context know that this was the span we actually tried to tag.
                    context.SetSpansTagged(SpecializedCollections.SingletonEnumerable(spanToTag));
                    context.State = version;
                }
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e, cancellationToken))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        private static async Task AddSemanticClassificationsAsync(
            Document document,
            TextSpan textSpan,
            IClassificationService classificationService,
            List <ClassifiedSpan> classifiedSpans,
            CancellationToken cancellationToken)
        {
            // Note: we do this work in a Task.Run to ensure that nothing we do (sync or async) ends up causing blocking
            // on the UI thread inside of IWorkspaceStatusService.  This is necessary as synchronous tagging will cause
            // us to make an explicit .Wait call on the tagging tasks.  If this thread in any way ended up blocking on
            // the UI thread, we would deadlock.
            var fullyLoadedStateTask = s_workspaceToFullyLoadedStateTask.GetValue(
                document.Project.Solution.Workspace,
                w => Task.Run(async() =>
            {
                var workspaceLoadedService = w.Services.GetRequiredService <IWorkspaceStatusService>();
                await workspaceLoadedService.WaitUntilFullyLoadedAsync(CancellationToken.None).ConfigureAwait(false);
            }));

            // If we're not fully loaded try to read from the cache instead so that classifications appear up to date.
            // New code will not be semantically classified, but will eventually when the project fully loads.
            //
            // Importantly, we do not await/wait on the fullyLoadedStateTask.  We do not want to ever be waiting on work
            // that may end up touching the UI thread (As we can deadlock if GetTagsSynchronous waits on us).  Instead,
            // we only check if the Task is completed.  Prior to that we will assume we are still loading.  Once this
            // task is completed, we know that the WaitUntilFullyLoadedAsync call will have actually finished and we're
            // fully loaded.
            var isFullyLoaded = fullyLoadedStateTask.IsCompleted;

            if (await TryAddSemanticClassificationsFromCacheAsync(document, textSpan, classifiedSpans, isFullyLoaded, cancellationToken).ConfigureAwait(false))
            {
                return;
            }

            await classificationService.AddSemanticClassificationsAsync(
                document, textSpan, classifiedSpans, cancellationToken).ConfigureAwait(false);
        }
Example #5
0
 private static async Task AddClassificationsAsync(
     IClassificationService classificationService,
     ClassificationOptions options,
     Document document,
     SnapshotSpan snapshotSpan,
     ArrayBuilder <ClassifiedSpan> classifiedSpans,
     ClassificationType type,
     CancellationToken cancellationToken)
 {
     if (type == ClassificationType.Semantic)
     {
         await classificationService.AddSemanticClassificationsAsync(
             document, snapshotSpan.Span.ToTextSpan(), options, classifiedSpans, cancellationToken).ConfigureAwait(false);
     }
     else if (type == ClassificationType.EmbeddedLanguage)
     {
         await classificationService.AddEmbeddedLanguageClassificationsAsync(
             document, snapshotSpan.Span.ToTextSpan(), options, classifiedSpans, cancellationToken).ConfigureAwait(false);
     }
     else
     {
         throw ExceptionUtilities.UnexpectedValue(type);
     }
 }
Example #6
0
 public async Task AddSemanticClassificationsAsync(Document document, TextSpan textSpan, List <ClassifiedSpan> result, CancellationToken cancellationToken)
 => await _originalService.AddSemanticClassificationsAsync(document, textSpan, result, cancellationToken).ConfigureAwait(false);
Example #7
0
 protected override async Task AddClassificationsAsync(IClassificationService classificationService, Document document, TextSpan textSpan, List <ClassifiedSpan> spans, CancellationToken cancellationToken)
 => await classificationService.AddSemanticClassificationsAsync(document, textSpan, spans, cancellationToken).ConfigureAwait(false);