Example #1
0
        internal AsyncTagger(IAsyncTaggerSource <TData, TTag> asyncTaggerSource)
        {
            _asyncTaggerSource          = asyncTaggerSource;
            _asyncTaggerSource.Changed += OnAsyncTaggerSourceChanged;

            // If there is an ITextView associated with the IAsyncTaggerSource then we want to
            // listen to LayoutChanges.  If the layout changes while we are getting tags we want
            // to prioritize the visible lines
            if (_asyncTaggerSource.TextViewOptional != null)
            {
                _asyncTaggerSource.TextViewOptional.LayoutChanged += OnLayoutChanged;
            }
        }
 protected void Create(params string[] lines)
 {
     _textView                       = CreateTextView(lines);
     _textBuffer                     = _textView.TextBuffer;
     _globalSettings                 = new GlobalSettings();
     _globalSettings.IgnoreCase      = true;
     _globalSettings.HighlightSearch = true;
     _vimData = Vim.VimData;
     _asyncTaggerSourceRaw = new HighlightSearchTaggerSource(
         _textView,
         _globalSettings,
         _vimData,
         Vim.VimHost);
     _asyncTaggerSource = _asyncTaggerSourceRaw;
 }
 protected void Create(params string[] lines)
 {
     _textView = CreateTextView(lines);
     _textBuffer = _textView.TextBuffer;
     _globalSettings = Vim.GlobalSettings;
     _globalSettings.IgnoreCase = true;
     _globalSettings.HighlightSearch = true;
     _vimData = Vim.VimData;
     _asyncTaggerSourceRaw = new HighlightSearchTaggerSource(
         _textView,
         _globalSettings,
         _vimData,
         Vim.VimHost);
     _asyncTaggerSource = _asyncTaggerSourceRaw;
 }
 private void Create(params string[] lines)
 {
     _textView                       = CreateTextView(lines);
     _textBuffer                     = _textView.TextBuffer;
     _globalSettings                 = new GlobalSettings();
     _globalSettings.IgnoreCase      = true;
     _globalSettings.HighlightSearch = true;
     _searchService                  = VimUtil.CreateSearchService();
     _vimData = Vim.VimData;
     _asyncTaggerSourceRaw = new HighlightSearchTaggerSource(
         _textView,
         _globalSettings,
         VimUtil.CreateTextStructureNavigator(_textBuffer, WordKind.NormalWord),
         _searchService,
         _vimData,
         Vim.VimHost);
     _asyncTaggerSource = _asyncTaggerSourceRaw;
 }
 private void Create(params string[] lines)
 {
     _textView = CreateTextView(lines);
     _textBuffer = _textView.TextBuffer;
     _globalSettings = new GlobalSettings();
     _globalSettings.IgnoreCase = true;
     _globalSettings.HighlightSearch = true;
     _searchService = Vim.SearchService;
     _vimData = Vim.VimData;
     _asyncTaggerSourceRaw = new HighlightSearchTaggerSource(
         _textView,
         _globalSettings,
         CreateTextStructureNavigator(_textBuffer, WordKind.NormalWord),
         _searchService,
         _vimData,
         Vim.VimHost);
     _asyncTaggerSource = _asyncTaggerSourceRaw;
 }
Example #6
0
 public static IClassifier CreateClassifierRaw <TData>(IAsyncTaggerSource <TData, IClassificationTag> asyncTaggerSource)
 {
     return(new Classifier(CreateTaggerRaw(asyncTaggerSource)));
 }
Example #7
0
 /// <summary>
 /// Create an ITagger implementation for the IAsyncTaggerSource.
 /// </summary>
 public static ITagger <TTag> CreateTaggerRaw <TData, TTag>(IAsyncTaggerSource <TData, TTag> asyncTaggerSource)
     where TTag : ITag
 {
     return(new AsyncTagger <TData, TTag>(asyncTaggerSource));
 }
Example #8
0
        private static void GetTagsInBackgroundCore(
            IAsyncTaggerSource <TData, TTag> asyncTaggerSource,
            TData data,
            int chunkCount,
            Channel channel,
            NormalizedLineRangeCollection visited,
            CancellationToken cancellationToken,
            Action <CompleteReason> onComplete,
            Action <SnapshotLineRange, ReadOnlyCollection <ITagSpan <TTag> > > onProgress)
        {
            CompleteReason completeReason;

            try
            {
                // Keep track of the LineRange values which we've already provided tags for.  Don't
                // duplicate the work
                var toProcess = new Queue <SnapshotLineRange>();

                // *** This value can be wrong ***
                // This is the version number we expect the Channel to have.  It's used
                // as a hueristic to determine if we should prioritize a value off of the stack or our
                // local stack.  If it's wrong it means we prioritize the wrong value.  Not a bug it
                // just changes the order in which values will appear
                var versionNumber = channel.CurrentVersion;

                // Take one value off of the threadedLineRangeStack value.  If the value is bigger than
                // our chunking increment then we will add the value in chunks to the toProcess queue
                Action popOne =
                    () =>
                {
                    var value = channel.Read();
                    if (!value.HasValue)
                    {
                        return;
                    }

                    var lineRange = value.Value;
                    if (lineRange.Count <= chunkCount)
                    {
                        toProcess.Enqueue(lineRange);
                        return;
                    }

                    var snapshot        = lineRange.Snapshot;
                    var startLineNumber = lineRange.StartLineNumber;
                    while (startLineNumber <= lineRange.LastLineNumber)
                    {
                        var startLine  = snapshot.GetLineFromLineNumber(startLineNumber);
                        var localRange = SnapshotLineRange.CreateForLineAndMaxCount(startLine, chunkCount);
                        toProcess.Enqueue(localRange);
                        startLineNumber += chunkCount;
                    }
                };

                // Get the tags for the specified SnapshotLineRange and return the results.  No chunking is done here,
                // the data is just directly processed
                Action <SnapshotLineRange> getTags =
                    tagLineRange =>
                {
                    var unvisited = visited.GetUnvisited(tagLineRange.LineRange);
                    if (unvisited.HasValue)
                    {
                        var tagList = EmptyTagList;
                        try
                        {
                            tagLineRange = SnapshotLineRange.CreateForLineNumberRange(tagLineRange.Snapshot, unvisited.Value.StartLineNumber, unvisited.Value.LastLineNumber).Value;
                            tagList      = asyncTaggerSource.GetTagsInBackground(data, tagLineRange.ExtentIncludingLineBreak, cancellationToken);
                        }
                        catch (Exception e)
                        {
                            // Ignore exceptions that are thrown by IAsyncTaggerSource.  If the tagger threw then we consider
                            // the tags to be nothing for this span.
                            //
                            // It's important that we register some value here.  If we register nothing then the foreground will
                            // never see this slot as fulfilled and later requests for this span will eventually queue up another
                            // background request
                            EditorUtilsTrace.TraceInfo("AsyncTagger source exception in background processing {0}", e);
                        }
                        visited.Add(tagLineRange.LineRange);
                        onProgress(tagLineRange, tagList);
                    }
                };

                do
                {
                    versionNumber = channel.CurrentVersion;
                    popOne();

                    // We've drained both of the sources of input hence we are done
                    if (0 == toProcess.Count)
                    {
                        break;
                    }

                    while (0 != toProcess.Count)
                    {
                        // If at any point the threadLineRangeStack value changes we consider the new values to have
                        // priority over the old ones
                        if (versionNumber != channel.CurrentVersion)
                        {
                            break;
                        }

                        cancellationToken.ThrowIfCancellationRequested();

                        var lineRange = toProcess.Dequeue();
                        getTags(lineRange);
                    }
                } while (!cancellationToken.IsCancellationRequested);

                completeReason = cancellationToken.IsCancellationRequested
                    ? CompleteReason.Cancelled
                    : CompleteReason.Finished;
            }
            catch (OperationCanceledException)
            {
                // Don't report cancellation exceptions.  These are thrown during cancellation for fast
                // break from the operation.  It's really a control flow mechanism
                completeReason = CompleteReason.Cancelled;
            }
            catch (Exception e)
            {
                // Handle cancellation exceptions and everything else.  Don't want an errant
                // exception thrown by the IAsyncTaggerSource to crash the process
                EditorUtilsTrace.TraceInfo("AsyncTagger Exception in background processing {0}", e);
                completeReason = CompleteReason.Error;
            }

            onComplete(completeReason);
        }