private async Task <SnapshotSpan> GetChangedSpanAsync(
                Document currentDocument, ITextSnapshot currentSnapshot, CancellationToken cancellationToken)
            {
                // We don't need to grab _lastProcessedDocument in a lock.  We don't care which version of the previous
                // doc we grab, just that we grab some prior version.  This is only used to narrow down the changed range we
                // specify, so it's ok if it's slightly larger because we read in a change from a couple of edits ago.
                var previousDocument = _lastProcessedDocument;

                if (previousDocument != null)
                {
                    var service = TryGetClassificationService(currentSnapshot);
                    if (service != null)
                    {
                        var changeRange = await service.ComputeSyntacticChangeRangeAsync(
                            previousDocument, currentDocument, _diffTimeout, cancellationToken).ConfigureAwait(false);

                        if (changeRange != null)
                        {
                            return(currentSnapshot.GetSpan(changeRange.Value.Span.Start, changeRange.Value.NewLength));
                        }
                    }
                }

                // Couldn't compute a narrower range.  Just the mark the entire file as changed.
                return(currentSnapshot.GetFullSpan());
            }
Exemple #2
0
        public static NormalizedSnapshotSpanCollection GetSnapshotSpanCollection(
            this ITextSnapshot snapshot
            )
        {
            Contract.ThrowIfNull(snapshot);

            return(new NormalizedSnapshotSpanCollection(snapshot.GetFullSpan()));
        }
Exemple #3
0
 // For testing only.
 internal TaggerContext(
     Document document, ITextSnapshot snapshot,
     SnapshotPoint?caretPosition         = null,
     TextChangeRange?textChangeRange     = null,
     CancellationToken cancellationToken = default)
     : this(null, ImmutableArray.Create(new DocumentSnapshotSpan(document, snapshot.GetFullSpan())),
            caretPosition, textChangeRange, null, cancellationToken)
 {
 }
Exemple #4
0
 // For testing only.
 internal TaggerContext(
     Document document, ITextSnapshot snapshot,
     SnapshotPoint?caretPosition         = null,
     TextChangeRange?textChangeRange     = null,
     CancellationToken cancellationToken = default(CancellationToken))
     : this(null, new[] { new DocumentSnapshotSpan(document, snapshot.GetFullSpan()) },
            caretPosition, textChangeRange, null, cancellationToken)
 {
 }
        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 static ITextSnapshot CreateSnapshot(ITextSnapshot editorSnapshot)
            {
                var factory = TextBufferFactory;

                // We might not have a factory if there is no primary workspace (for example, under the unit test harness,
                // or in CodeSense where they are just using the parsers by themselves). In that case, just use the editor
                // snapshot as-is.
                //
                // Creating a buffer off a given snapshot should be cheap, so it should be okay to create a dummy buffer here
                // just to host the snapshot we want.
                var roslynSnapshot = factory != null
                                        ? factory.Clone(editorSnapshot.GetFullSpan()).CurrentSnapshot
                                        : editorSnapshot;

                // put reverse entry that won't hold onto anything
                var weakEditorSnapshot = new WeakReference<ITextSnapshot>(editorSnapshot);
                s_roslynToEditorSnapshotMap.GetValue(roslynSnapshot, _ => weakEditorSnapshot);

                return roslynSnapshot;
            }
Exemple #8
0
        private IList <OutliningSpan> GetMultiLineRegions(IOutliningService service, IList <OutliningSpan> regions, ITextSnapshot snapshot)
        {
            // Remove any spans that aren't multiline.
            var multiLineRegions = new List <OutliningSpan>(regions.Count);

            foreach (var region in regions)
            {
                if (region != null && 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 (!exceptionReported)
                        {
                            exceptionReported = true;
                            try
                            {
                                throw new InvalidOutliningRegionException(service, snapshot, snapshotSpan, regionSpan);
                            }
                            catch (InvalidOutliningRegionException e) when(FatalError.ReportWithoutCrash(e))
                            {
                            }
                        }
                        continue;
                    }

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

            return(multiLineRegions);
        }
            private static ITextSnapshot CreateSnapshot(ITextSnapshot editorSnapshot)
            {
                var factory = TextBufferFactory;

                // We might not have a factory if there is no primary workspace (for example, under the unit test harness,
                // or in CodeSense where they are just using the parsers by themselves). In that case, just use the editor
                // snapshot as-is.
                //
                // Creating a buffer off a given snapshot should be cheap, so it should be okay to create a dummy buffer here
                // just to host the snapshot we want.
                var roslynSnapshot = factory != null
                                        ? factory.Clone(editorSnapshot.GetFullSpan()).CurrentSnapshot
                                        : editorSnapshot;

                // put reverse entry that won't hold onto anything
                var weakEditorSnapshot = new WeakReference <ITextSnapshot>(editorSnapshot);

                s_roslynToEditorSnapshotMap.GetValue(roslynSnapshot, _ => weakEditorSnapshot);

                return(roslynSnapshot);
            }
Exemple #10
0
            private async Task EnqueueParseSnapshotWorkerAsync(Document document, ITextSnapshot snapshot, CancellationToken cancellationToken)
            {
                // preemptively parse file in background so that when we are called from tagger from UI thread, we have tree ready.
                var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                lock (_gate)
                {
                    _lastParsedSnapshot = snapshot;
                    _lastParsedDocument = document;
                }

                _reportChangeCancellationSource = new CancellationTokenSource();
                _notificationService.RegisterNotification(() =>
                {
                    _workQueue.AssertIsForeground();
                    ReportChangedSpan(snapshot.GetFullSpan());
                },
                                                          ReportChangeDelayInMilliseconds,
                                                          _listener.BeginAsyncOperation("ReportEntireFileChanged"),
                                                          _reportChangeCancellationSource.Token);
            }
            public override SourceText WithChanges(IEnumerable <TextChange> changes)
            {
                if (changes == null)
                {
                    throw new ArgumentNullException(nameof(changes));
                }

                if (!changes.Any())
                {
                    return(this);
                }

                // check whether we can use text buffer factory
                var factory = TextBufferFactory;

                if (factory == null)
                {
                    // if we can't get the factory, use the default implementation
                    return(base.WithChanges(changes));
                }

                // otherwise, create a new cloned snapshot
                var buffer       = factory.Clone(EditorSnapshot.GetFullSpan());
                var baseSnapshot = buffer.CurrentSnapshot;

                // apply the change to the buffer
                using (var edit = buffer.CreateEdit())
                {
                    foreach (var change in changes)
                    {
                        edit.Replace(change.Span.ToSpan(), change.NewText);
                    }

                    edit.Apply();
                }

                return(new ChangedSourceText(this, baseSnapshot, buffer.CurrentSnapshot));
            }
Exemple #12
0
 internal TaggerContext(
     Document document, ITextSnapshot snapshot,
     SnapshotPoint?caretPosition     = null,
     TextChangeRange?textChangeRange = null)
     : this(state : null, ImmutableArray.Create(new DocumentSnapshotSpan(document, snapshot.GetFullSpan())),
            caretPosition, textChangeRange, existingTags : null)
 {
 }
            private async Task EnqueueParseSnapshotWorkerAsync(Document document, ITextSnapshot snapshot, CancellationToken cancellationToken)
            {
                // preemptively parse file in background so that when we are called from tagger from UI thread, we have tree ready.
                var syntaxTree = await document.GetSyntaxTreeAsync(cancellationToken).ConfigureAwait(false);

                lock (_gate)
                {
                    _lastParsedSnapshot = snapshot;
                    _lastParsedDocument = document;
                }

                _reportChangeCancellationSource = new CancellationTokenSource();
                _notificationService.RegisterNotification(() =>
                    {
                        _workQueue.AssertIsForeground();
                        ReportChangedSpan(snapshot.GetFullSpan());
                    },
                    ReportChangeDelayInMilliseconds,
                    _listener.BeginAsyncOperation("ReportEntireFileChanged"),
                    _reportChangeCancellationSource.Token);
            }