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); } } }
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); }
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}."); }