protected sealed override async Task ProduceTagsAsync(
            TaggerContext <TRegionTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            try
            {
                var document = documentSnapshotSpan.Document;
                if (document == null)
                {
                    return;
                }

                // Let LSP handle producing tags in the cloud scenario
                if (documentSnapshotSpan.Document.IsInCloudEnvironmentClientContext())
                {
                    return;
                }

                var outliningService = BlockStructureService.GetService(document);
                if (outliningService == null)
                {
                    return;
                }

                var blockStructure = await outliningService.GetBlockStructureAsync(
                    documentSnapshotSpan.Document, context.CancellationToken).ConfigureAwait(false);

                ProcessSpans(
                    context, documentSnapshotSpan.SnapshotSpan, outliningService,
                    blockStructure.Spans);
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        /// <summary>
        /// Keep this in sync with <see cref="ProduceTagsAsync"/>
        /// </summary>
        protected sealed override void ProduceTagsSynchronously(
            TaggerContext <IStructureTag> context, DocumentSnapshotSpan documentSnapshotSpan, int?caretPosition)
        {
            try
            {
                var document = documentSnapshotSpan.Document;
                if (document == null)
                {
                    return;
                }

                // Let LSP handle producing tags in the cloud scenario
                if (documentSnapshotSpan.SnapshotSpan.Snapshot.TextBuffer.IsInLspEditorContext())
                {
                    return;
                }

                var outliningService = BlockStructureService.GetService(document);
                if (outliningService == null)
                {
                    return;
                }

                var blockStructure = outliningService.GetBlockStructure(document, context.CancellationToken);
                ProcessSpans(
                    context, documentSnapshotSpan.SnapshotSpan, outliningService,
                    blockStructure.Spans);
            }
            catch (Exception e) when(FatalError.ReportAndPropagateUnlessCanceled(e))
            {
                throw ExceptionUtilities.Unreachable;
            }
        }
        void DocumentContext_DocumentParsed(object sender, EventArgs e)
        {
            CancelDocumentParsedUpdate();
            var analysisDocument = DocumentContext.AnalysisDocument;
            var editor           = Editor;

            if (analysisDocument == null || !editor.Options.ShowFoldMargin)
            {
                return;
            }

            var outliningService = BlockStructureService.GetService(analysisDocument);

            if (outliningService == null)
            {
                return;
            }

            var snapshot      = editor.CreateDocumentSnapshot();
            var caretLocation = editor.CaretOffset;
            var token         = src.Token;

            Task.Run(async() => {
                var blockStructure = await outliningService.GetBlockStructureAsync(analysisDocument, token).ConfigureAwait(false);
                return(UpdateFoldings(snapshot, blockStructure.Spans, caretLocation, (start, length) => editor.CreateFoldSegment(start, length), token));
            }).ContinueWith(t => {
                if (!token.IsCancellationRequested)
                {
                    editor.SetFoldings(t.Result);
                }
            }, Runtime.MainTaskScheduler);
        }
        private void ProcessSpansWorker(
            TaggerContext <TRegionTag> context,
            SnapshotSpan snapshotSpan,
            BlockStructureService outliningService,
            ImmutableArray <BlockSpan> spans)
        {
            if (spans != null)
            {
                var snapshot = snapshotSpan.Snapshot;
                spans = GetMultiLineRegions(outliningService, spans, snapshot);

                // Create the outlining tags.
                var tagSpanStack = new Stack <TagSpan <TRegionTag> >();

                foreach (var region in spans)
                {
                    var spanToCollapse = new SnapshotSpan(snapshot, region.TextSpan.ToSpan());

                    while (tagSpanStack.Count > 0 &&
                           tagSpanStack.Peek().Span.End <= spanToCollapse.Span.Start)
                    {
                        tagSpanStack.Pop();
                    }

                    var parentTag = tagSpanStack.Count > 0 ? tagSpanStack.Peek() : null;
                    var tag       = CreateTag(parentTag?.Tag, snapshot, region);

                    var tagSpan = new TagSpan <TRegionTag>(spanToCollapse, tag);

                    context.AddTag(tagSpan);
                    tagSpanStack.Push(tagSpan);
                }
            }
        }
示例#5
0
 public InvalidOutliningRegionException(BlockStructureService service, ITextSnapshot snapshot, Span snapshotSpan, Span regionSpan)
     : base(GetExceptionMessage(service, snapshot, snapshotSpan, regionSpan))
 {
     _service      = service;
     _snapshot     = snapshot;
     _snapshotSpan = snapshotSpan;
     _regionSpan   = regionSpan;
 }
        private static ImmutableArray <BlockSpan> GetMultiLineRegions(
            BlockStructureService service,
            ImmutableArray <BlockSpan> regions,
            ITextSnapshot snapshot
            )
        {
            // Remove any spans that aren't multiline.
            var multiLineRegions = ArrayBuilder <BlockSpan> .GetInstance();

            foreach (var region in regions)
            {
                if (region.TextSpan.Length > 0)
                {
                    // Check if any clients produced an invalid OutliningSpan.  If so, filter them
                    // out and report a non-fatal watson so we can attempt to determine the source
                    // of the issue.
                    var snapshotSpan = snapshot.GetFullSpan().Span;
                    var regionSpan   = region.TextSpan.ToSpan();
                    if (!snapshotSpan.Contains(regionSpan))
                    {
                        if (!s_exceptionReported)
                        {
                            s_exceptionReported = true;
                            try
                            {
                                throw new InvalidOutliningRegionException(
                                          service,
                                          snapshot,
                                          snapshotSpan,
                                          regionSpan
                                          );
                            }
                            catch (InvalidOutliningRegionException e)
                                when(FatalError.ReportAndCatch(e))
                                {
                                }
                        }
                        continue;
                    }

                    var startLine = snapshot.GetLineNumberFromPosition(region.TextSpan.Start);
                    var endLine   = snapshot.GetLineNumberFromPosition(region.TextSpan.End);
                    if (startLine != endLine)
                    {
                        multiLineRegions.Add(region);
                    }
                }
            }

            return(multiLineRegions.ToImmutableAndFree());
        }
        private static ImmutableArray <BlockSpan> GetMultiLineRegions(
            BlockStructureService service,
            ImmutableArray <BlockSpan> regions, ITextSnapshot snapshot)
        {
            // Remove any spans that aren't multiline.
            var multiLineRegions = ArrayBuilder <BlockSpan> .GetInstance();

            foreach (var region in regions)
            {
                if (region.TextSpan.Length > 0)
                {
                    // Check if any clients produced an invalid OutliningSpan.  If so, filter them
                    // out and report a non-fatal watson so we can attempt to determine the source
                    // of the issue.
                    var snapshotSpan = snapshot.GetFullSpan().Span;
                    var regionSpan   = region.TextSpan.ToSpan();
                    if (!snapshotSpan.Contains(regionSpan))
                    {
                        if (!s_exceptionReported)
                        {
                            s_exceptionReported = true;
                            try
                            {
                                throw new InvalidOutliningRegionException(service, snapshot, snapshotSpan, regionSpan);
                            }
                            catch (InvalidOutliningRegionException e) when(FatalError.ReportAndCatch(e))
                            {
                            }
                        }
                        continue;
                    }

                    var startLine = snapshot.GetLineNumberFromPosition(region.TextSpan.Start);
                    var endLine   = snapshot.GetLineNumberFromPosition(region.TextSpan.End);
                    if (startLine != endLine)
                    {
                        multiLineRegions.Add(region);
                    }
                }
            }

            // Make sure the regions are lexicographically sorted.  This is needed
            // so we can appropriately parent them for BlockTags.
            //
            // Note we pass a IComparer instead of a Comparison to work around this
            // issue in ImmutableArray.Builder: https://github.com/dotnet/corefx/issues/11173
            multiLineRegions.Sort(s_blockSpanComparer);
            return(multiLineRegions.ToImmutableAndFree());
        }
        private void ProcessSpans(
            TaggerContext <IStructureTag> context,
            SnapshotSpan snapshotSpan,
            BlockStructureService outliningService,
            ImmutableArray <BlockSpan> spans)
        {
            var snapshot = snapshotSpan.Snapshot;

            spans = GetMultiLineRegions(outliningService, spans, snapshot);

            foreach (var span in spans)
            {
                var tag = new StructureTag(this, span, snapshot);
                context.AddTag(new TagSpan <IStructureTag>(span.TextSpan.ToSnapshotSpan(snapshot), tag));
            }
        }
        private BlockStructureService TryGetService(
            TaggerContext <TRegionTag> context,
            DocumentSnapshotSpan documentSnapshotSpan)
        {
            var cancellationToken = context.CancellationToken;

            using (Logger.LogBlock(FunctionId.Tagger_Outlining_TagProducer_ProduceTags, cancellationToken))
            {
                var document = documentSnapshotSpan.Document;
                if (document != null)
                {
                    return(BlockStructureService.GetService(document));
                }
            }

            return(null);
        }
 private void ProcessSpans(
     TaggerContext <TRegionTag> context,
     SnapshotSpan snapshotSpan,
     BlockStructureService outliningService,
     ImmutableArray <BlockSpan> spans)
 {
     try
     {
         ProcessSpansWorker(context, snapshotSpan, outliningService, spans);
     }
     catch (TypeLoadException)
     {
         // We're targeting a version of the BlockTagging infrastructure in
         // VS that may not match the version that the user is currently
         // developing against.  Be resilient to this until everything moves
         // forward to the right VS version.
     }
 }
        async void DocumentContext_DocumentParsed(object sender, EventArgs e)
        {
            CancelDocumentParsedUpdate();
            var analysisDocument = DocumentContext.AnalysisDocument;

            if (analysisDocument == null || !Editor.Options.ShowFoldMargin)
            {
                return;
            }
            var caretLocation = Editor.CaretOffset;

            var outliningService = BlockStructureService.GetService(analysisDocument);

            if (outliningService == null)
            {
                return;
            }
            var token          = src.Token;
            var blockStructure = await outliningService.GetBlockStructureAsync(analysisDocument, token).ConfigureAwait(false);

            UpdateFoldings(Editor, blockStructure.Spans, caretLocation, token);
        }
示例#12
0
 private static string GetExceptionMessage(BlockStructureService service, ITextSnapshot snapshot, Span snapshotSpan, Span regionSpan)
 {
     return($"OutliningService({service.GetType()}) produced an invalid region.  ITextSnapshot span is {snapshotSpan}. OutliningSpan is {regionSpan}.");
 }