Exemplo n.º 1
0
            public TagSource(
                ITextView textViewOpt,
                ITextBuffer subjectBuffer,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener,
                IForegroundNotificationService notificationService)
            {
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _subjectBuffer       = subjectBuffer;
                _textViewOpt         = textViewOpt;
                _dataSource          = dataSource;
                _asyncListener       = asyncListener;
                _notificationService = notificationService;
                _tagSpanComparer     = new TagSpanComparer(_dataSource.TagComparer);

                DebugRecordInitialStackTrace();

                _workQueue          = new AsynchronousSerialWorkQueue(asyncListener);
                this.CachedTagTrees = ImmutableDictionary.Create <ITextBuffer, TagSpanIntervalTree <TTag> >();

                _eventSource = CreateEventSource();

                Connect();

                // Kick off a task to compute the initial set of tags.
                RecalculateTagsOnChanged(new TaggerEventArgs(TaggerDelay.Short));
            }
Exemplo n.º 2
0
            public TagSource(
                ITextView textViewOpt,
                ITextBuffer subjectBuffer,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener,
                IForegroundNotificationService notificationService)
                : base(dataSource.ThreadingContext)
            {
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _subjectBuffer       = subjectBuffer;
                _textViewOpt         = textViewOpt;
                _dataSource          = dataSource;
                _asyncListener       = asyncListener;
                _notificationService = notificationService;
                _tagSpanComparer     = new TagSpanComparer(_dataSource.TagComparer);

                DebugRecordInitialStackTrace();

                _workQueue          = new AsynchronousSerialWorkQueue(ThreadingContext, asyncListener);
                this.CachedTagTrees = ImmutableDictionary.Create <ITextBuffer, TagSpanIntervalTree <TTag> >();

                _eventSource = CreateEventSource();

                Connect();

                // Start computing the initial set of tags immediately.  We want to get the UI
                // to a complete state as soon as possible.
                ComputeInitialTags();
            }
            public TagSource(
                ITextView textViewOpt,
                ITextBuffer subjectBuffer,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener,
                IForegroundNotificationService notificationService)
            {
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _subjectBuffer       = subjectBuffer;
                _textViewOpt         = textViewOpt;
                _dataSource          = dataSource;
                _asyncListener       = asyncListener;
                _notificationService = notificationService;
                _tagSpanComparer     = new TagSpanComparer(_dataSource.TagComparer);

                DebugRecordInitialStackTrace();

                _workQueue          = new AsynchronousSerialWorkQueue(asyncListener);
                this.CachedTagTrees = ImmutableDictionary.Create <ITextBuffer, TagSpanIntervalTree <TTag> >();

                _eventSource = CreateEventSource();

                Connect();

                // Kick off a task to immediately compute the initial set of tags. This work should
                // not be cancellable (except if we get completely released), even if more events come
                // in.  That way we can get the initial set of results for the buffer as quickly as
                // possible, without kicking the work  down the road.
                var initialTagsCancellationToken = _initialComputationCancellationTokenSource.Token;

                // Note: we always kick this off to the new UI pump instead of computing tags right
                // on this thread.  The reason for that is that we may be getting created at a time
                // when the view itself is initializing.  As such the view is not in a state where
                // we want code touching it.
                RegisterNotification(
                    () => RecomputeTagsForeground(cancellationTokenOpt: initialTagsCancellationToken),
                    delay: 0,
                    cancellationToken: initialTagsCancellationToken);
            }
Exemplo n.º 4
0
            public TagSource(
                ITextView textViewOpt,
                ITextBuffer subjectBuffer,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener)
                : base(dataSource.ThreadingContext)
            {
                this.AssertIsForeground();
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _subjectBuffer = subjectBuffer;
                _textViewOpt   = textViewOpt;
                _dataSource    = dataSource;
                _asyncListener = asyncListener;

                _highPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                    TaggerDelay.NearImmediate.ComputeTimeDelay(),
                    ProcessTagsChangedAsync,
                    equalityComparer: null,
                    asyncListener,
                    _tagSourceState.Target.DisposalToken);

                if (_dataSource.AddedTagNotificationDelay == TaggerDelay.NearImmediate)
                {
                    // if the tagger wants "added tags" to be reported "NearImmediate"ly, then just reuse
                    // the "high pri" queue as that already reports things at that cadence.
                    _normalPriTagsChangedQueue = _highPriTagsChangedQueue;
                }
                else
                {
                    _normalPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                        _dataSource.AddedTagNotificationDelay.ComputeTimeDelay(),
                        ProcessTagsChangedAsync,
                        equalityComparer: null,
                        asyncListener,
                        _tagSourceState.Target.DisposalToken);
                }

                DebugRecordInitialStackTrace();

                _eventSource = CreateEventSource();
                Connect();

                // Start computing the initial set of tags immediately.  We want to get the UI
                // to a complete state as soon as possible.
                EnqueueWork(initialTags: true);

                return;

                void Connect()
                {
                    this.AssertIsForeground();

                    _eventSource.Changed += OnEventSourceChanged;

                    if (_dataSource.TextChangeBehavior.HasFlag(TaggerTextChangeBehavior.TrackTextChanges))
                    {
                        _subjectBuffer.Changed += OnSubjectBufferChanged;
                    }

                    if (_dataSource.CaretChangeBehavior.HasFlag(TaggerCaretChangeBehavior.RemoveAllTagsOnCaretMoveOutsideOfTag))
                    {
                        if (_textViewOpt == null)
                        {
                            throw new ArgumentException(
                                      nameof(_dataSource.CaretChangeBehavior) + " can only be specified for an " + nameof(IViewTaggerProvider));
                        }

                        _textViewOpt.Caret.PositionChanged += OnCaretPositionChanged;
                    }

                    // Tell the interaction object to start issuing events.
                    _eventSource.Connect();
                }
            }
 public TestAccessor(AbstractAsynchronousTaggerProvider <TTag> provider)
 => _provider = provider;
Exemplo n.º 6
0
            public TagSource(
                ITextView?textView,
                ITextBuffer subjectBuffer,
                ITextBufferVisibilityTracker?visibilityTracker,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener)
            {
                dataSource.ThreadingContext.ThrowIfNotOnUIThread();
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _textView          = textView;
                _subjectBuffer     = subjectBuffer;
                _visibilityTracker = visibilityTracker;
                _dataSource        = dataSource;
                _asyncListener     = asyncListener;

                _workspaceRegistration = Workspace.GetWorkspaceRegistration(subjectBuffer.AsTextContainer());

                // Collapse all booleans added to just a max of two ('true' or 'false') representing if we're being
                // asked for initial tags or not
                _eventChangeQueue = new AsyncBatchingWorkQueue <bool>(
                    dataSource.EventChangeDelay.ComputeTimeDelay(),
                    ProcessEventChangeAsync,
                    EqualityComparer <bool> .Default,
                    asyncListener,
                    _disposalTokenSource.Token);

                _highPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                    TaggerDelay.NearImmediate.ComputeTimeDelay(),
                    ProcessTagsChangedAsync,
                    equalityComparer: null,
                    asyncListener,
                    _disposalTokenSource.Token);

                if (_dataSource.AddedTagNotificationDelay == TaggerDelay.NearImmediate)
                {
                    // if the tagger wants "added tags" to be reported "NearImmediate"ly, then just reuse
                    // the "high pri" queue as that already reports things at that cadence.
                    _normalPriTagsChangedQueue = _highPriTagsChangedQueue;
                }
                else
                {
                    _normalPriTagsChangedQueue = new AsyncBatchingWorkQueue <NormalizedSnapshotSpanCollection>(
                        _dataSource.AddedTagNotificationDelay.ComputeTimeDelay(),
                        ProcessTagsChangedAsync,
                        equalityComparer: null,
                        asyncListener,
                        _disposalTokenSource.Token);
                }

                DebugRecordInitialStackTrace();

                // Create the tagger-specific events that will cause the tagger to refresh.
                _eventSource = CreateEventSource();

                // any time visibility changes, resume tagging on all taggers.  Any non-visible taggers will pause
                // themselves immediately afterwards.
                _onVisibilityChanged = () => ResumeIfVisible();

                // Now hook up this tagger to all interesting events.
                Connect();

                // Now that we're all hooked up to the events we care about, start computing the initial set of tags at
                // high priority.  We want to get the UI to a complete state as soon as possible.
                EnqueueWork(highPriority: true);

                return;

                // Represented as a local function just so we can keep this in sync with Dispose.Disconnect below.
                void Connect()
                {
                    _dataSource.ThreadingContext.ThrowIfNotOnUIThread();

                    // Register to hear about visibility changes so we can pause/resume this tagger.
                    _visibilityTracker?.RegisterForVisibilityChanges(subjectBuffer, _onVisibilityChanged);

                    _eventSource.Changed += OnEventSourceChanged;

                    if (_dataSource.TextChangeBehavior.HasFlag(TaggerTextChangeBehavior.TrackTextChanges))
                    {
                        _subjectBuffer.Changed += OnSubjectBufferChanged;
                    }

                    if (_dataSource.CaretChangeBehavior.HasFlag(TaggerCaretChangeBehavior.RemoveAllTagsOnCaretMoveOutsideOfTag))
                    {
                        if (_textView == null)
                        {
                            throw new ArgumentException(
                                      nameof(_dataSource.CaretChangeBehavior) + " can only be specified for an " + nameof(IViewTaggerProvider));
                        }

                        _textView.Caret.PositionChanged += OnCaretPositionChanged;
                    }

                    // Tell the interaction object to start issuing events.
                    _eventSource.Connect();
                }
            }
Exemplo n.º 7
0
            public TagSource(
                ITextView textViewOpt,
                ITextBuffer subjectBuffer,
                AbstractAsynchronousTaggerProvider <TTag> dataSource,
                IAsynchronousOperationListener asyncListener,
                IForegroundNotificationService notificationService)
                : base(dataSource.ThreadingContext)
            {
                this.AssertIsForeground();
                if (dataSource.SpanTrackingMode == SpanTrackingMode.Custom)
                {
                    throw new ArgumentException("SpanTrackingMode.Custom not allowed.", "spanTrackingMode");
                }

                _subjectBuffer       = subjectBuffer;
                _textViewOpt         = textViewOpt;
                _dataSource          = dataSource;
                _asyncListener       = asyncListener;
                _notificationService = notificationService;

                _batchChangeTokenSource = new CancellationTokenSource();

                _batchChangeNotifier = new BatchChangeNotifier(
                    dataSource.ThreadingContext,
                    subjectBuffer, asyncListener, notificationService, NotifyEditorNow, _batchChangeTokenSource.Token);

                DebugRecordInitialStackTrace();

                _workQueue          = new AsynchronousSerialWorkQueue(ThreadingContext, asyncListener);
                this.CachedTagTrees = ImmutableDictionary.Create <ITextBuffer, TagSpanIntervalTree <TTag> >();

                _eventSource = CreateEventSource();

                Connect();

                // Start computing the initial set of tags immediately.  We want to get the UI
                // to a complete state as soon as possible.
                ComputeInitialTags();

                return;

                void Connect()
                {
                    this.AssertIsForeground();

                    _eventSource.Changed += OnEventSourceChanged;

                    if (_dataSource.TextChangeBehavior.HasFlag(TaggerTextChangeBehavior.TrackTextChanges))
                    {
                        _subjectBuffer.Changed += OnSubjectBufferChanged;
                    }

                    if (_dataSource.CaretChangeBehavior.HasFlag(TaggerCaretChangeBehavior.RemoveAllTagsOnCaretMoveOutsideOfTag))
                    {
                        if (_textViewOpt == null)
                        {
                            throw new ArgumentException(
                                      nameof(_dataSource.CaretChangeBehavior) + " can only be specified for an " + nameof(IViewTaggerProvider));
                        }

                        _textViewOpt.Caret.PositionChanged += OnCaretPositionChanged;
                    }

                    // Tell the interaction object to start issuing events.
                    _eventSource.Connect();
                }
            }