예제 #1
0
        string GenerateHtmlFragmentCore(NormalizedSnapshotSpanCollection spans, ITextView?textView, string delimiter, CancellationToken cancellationToken)
        {
            ISynchronousClassifier?classifier = null;

            try {
                int tabSize;
                IClassificationFormatMap classificationFormatMap;
                if (!(textView is null))
                {
                    classifier = synchronousViewClassifierAggregatorService.GetSynchronousClassifier(textView);
                    classificationFormatMap = classificationFormatMapService.GetClassificationFormatMap(textView);
                    tabSize = textView.Options.GetTabSize();
                }
                else
                {
                    classifier = spans.Count == 0 ? null : synchronousClassifierAggregatorService.GetSynchronousClassifier(spans[0].Snapshot.TextBuffer);
                    classificationFormatMap = classificationFormatMapService.GetClassificationFormatMap(AppearanceCategoryConstants.TextEditor);
                    tabSize = defaultTabSize;
                }
                tabSize = OptionsHelpers.FilterTabSize(tabSize);

                var builder = new HtmlBuilder(classificationFormatMap, delimiter, tabSize);
                if (spans.Count != 0)
                {
                    builder.Add(classifier !, spans, cancellationToken);
                }
                return(builder.Create());
            }
예제 #2
0
 protected override ITaggerEventSource CreateEventSource(
     ITextView?textView, ITextBuffer subjectBuffer)
 {
     return(TaggerEventSources.Compose(
                new EditorFormatMapChangedEventSource(_editorFormatMap),
                TaggerEventSources.OnTextChanged(subjectBuffer)));
 }
예제 #3
0
        protected override ITaggerEventSource CreateEventSource(ITextView?textView, ITextBuffer subjectBuffer)
        {
            this.ThreadingContext.ThrowIfNotOnUIThread();

            return(TaggerEventSources.Compose(
                       new EventSource(subjectBuffer),
                       TaggerEventSources.OnTextChanged(subjectBuffer),
                       TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer)));
        }
예제 #4
0
        protected override IEnumerable <SnapshotSpan> GetSpansToTag(ITextView?textView, ITextBuffer subjectBuffer)
        {
            this.ThreadingContext.ThrowIfNotOnUIThread();
            Contract.ThrowIfNull(textView);

            var visibleSpan = textView.GetVisibleLinesSpan(subjectBuffer, extraLines: 100);

            if (visibleSpan == null)
            {
                return(base.GetSpansToTag(textView, subjectBuffer));
            }

            return(SpecializedCollections.SingletonEnumerable(visibleSpan.Value));
        }
        protected sealed override IEnumerable <SnapshotSpan> GetSpansToTag(ITextView?textView, ITextBuffer subjectBuffer)
        {
            this.ThreadingContext.ThrowIfNotOnUIThread();
            Contract.ThrowIfNull(textView);

            // Find the visible span some 100 lines +/- what's actually in view.  This way
            // if the user scrolls up/down, we'll already have the results.
            var visibleSpanOpt = textView.GetVisibleLinesSpan(subjectBuffer, extraLines: 100);

            if (visibleSpanOpt == null)
            {
                // Couldn't find anything visible, just fall back to classifying everything.
                return(base.GetSpansToTag(textView, subjectBuffer));
            }

            return(SpecializedCollections.SingletonEnumerable(visibleSpanOpt.Value));
        }
예제 #6
0
 protected override ITaggerEventSource CreateEventSource(ITextView?textView, ITextBuffer subjectBuffer)
 {
     Contract.ThrowIfNull(textView);
     // Because we use frozen-partial documents for semantic classification, we may end up with incomplete
     // semantics (esp. during solution load).  Because of this, we also register to hear when the full
     // compilation is available so that reclassify and bring ourselves up to date.
     // Note: Also generate tags when FeatureOnOffOptions.InheritanceMarginCombinedWithIndicatorMargin is changed,
     // because we want to refresh the glyphs in indicator margin.
     return(new CompilationAvailableTaggerEventSource(
                subjectBuffer,
                AsyncListener,
                TaggerEventSources.OnWorkspaceChanged(subjectBuffer, AsyncListener),
                TaggerEventSources.OnViewSpanChanged(ThreadingContext, textView),
                TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer),
                TaggerEventSources.OnOptionChanged(subjectBuffer, FeatureOnOffOptions.ShowInheritanceMargin),
                TaggerEventSources.OnOptionChanged(subjectBuffer, FeatureOnOffOptions.InheritanceMarginCombinedWithIndicatorMargin)));
 }
        protected sealed override ITaggerEventSource CreateEventSource(ITextView?textView, ITextBuffer subjectBuffer)
        {
            this.ThreadingContext.ThrowIfNotOnUIThread();
            Contract.ThrowIfNull(textView);

            // Note: we don't listen for OnTextChanged.  They'll get reported by the ViewSpan changing and also the
            // SemanticChange notification.
            //
            // Note: because we use frozen-partial documents for semantic classification, we may end up with incomplete
            // semantics (esp. during solution load).  Because of this, we also register to hear when the full
            // compilation is available so that reclassify and bring ourselves up to date.
            return(new CompilationAvailableTaggerEventSource(
                       subjectBuffer,
                       AsyncListener,
                       TaggerEventSources.OnViewSpanChanged(ThreadingContext, textView),
                       TaggerEventSources.OnWorkspaceChanged(subjectBuffer, AsyncListener),
                       TaggerEventSources.OnDocumentActiveContextChanged(subjectBuffer),
                       TaggerEventSources.OnGlobalOptionChanged(_globalOptions, ClassificationOptionsStorage.ClassifyReassignedVariables)));
        }
 protected override ITaggerEventSource CreateEventSource(ITextView?textView, ITextBuffer subjectBuffer)
 {
     Contract.ThrowIfNull(textView);
     return(TaggerEventSources.Compose(
                TaggerEventSources.OnViewSpanChanged(this.ThreadingContext, textView),
                TaggerEventSources.OnWorkspaceChanged(subjectBuffer, _listener),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsGlobalStateOption.DisplayAllOverride),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.EnabledForParameters),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForLiteralParameters),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForIndexerParameters),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForObjectCreationParameters),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForOtherParameters),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.SuppressForParametersThatMatchMethodIntent),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.SuppressForParametersThatDifferOnlyBySuffix),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.SuppressForParametersThatMatchArgumentName),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.EnabledForTypes),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForImplicitVariableTypes),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForLambdaParameterTypes),
                TaggerEventSources.OnOptionChanged(subjectBuffer, InlineHintsOptionsStorage.ForImplicitObjectCreation)));
 }
 // Need to override this from AbstractDiagnosticsTaggerProvider because the location option needs to be added
 // to the TaggerEventSource, otherwise it does not get updated until there is a change in the editor.
 protected override ITaggerEventSource CreateEventSource(ITextView?textView, ITextBuffer subjectBuffer)
 {
     return(TaggerEventSources.Compose(
                base.CreateEventSource(textView, subjectBuffer),
                TaggerEventSources.OnGlobalOptionChanged(GlobalOptions, InlineDiagnosticsOptions.Location)));
 }
예제 #10
0
        private void UpdateContextAndJump(Action <LocalContextState> jumpAction)
        {
            this.operationSemaphorSlim.Wait();

            try
            {
                IWpfTextView?view = this.viewAccessor?.ActiveView;

                if (view == null && this.lastView != null)
                {
                    this.lastView.LayoutChanged -= this.View_LayoutChanged;
                    this.lastView     = null;
                    this.lastSnapshot = null;
                }

                if (view != null && this.lastActiveView != view)
                {
                    if (this.adornment != null)
                    {
                        this.adornment.Remove();
                    }

                    this.adornment      = new TextHighlightAdornment(view);
                    this.lastActiveView = view;

                    string     text = view.TextSnapshot.GetText();
                    SyntaxTree tree = CSharpSyntaxTree.ParseText(text);
                    this.localContext = new LocalContext(tree);

                    view.LayoutChanged += View_LayoutChanged;
                    this.lastView       = view;
                }

                if (this.adornment != null && view != null)
                {
                    _ = this.localContext ?? throw new NullReferenceException(
                                  "The local context should be initialized first.");

                    this.adornment.Remove();

                    SnapshotPoint    caret        = view.Caret.Position.BufferPosition;
                    IWpfTextViewLine textViewLine = view.GetTextViewLineContainingBufferPosition(caret);
                    int line      = caret.GetContainingLine().LineNumber;
                    int startChar = textViewLine.Start.Difference(caret);

                    Debug.WriteLine(
                        "The state before cursor update:\t" +
                        $"{this.localContext.State.GetType().Name}");

                    this.localContext.TransitionTo(line, startChar);

                    Debug.WriteLine(
                        "The state after cursor update:\t" +
                        $"{this.localContext.State.GetType().Name}");

                    jumpAction(this.localContext.State);

                    LocalContextState state = this.localContext.State;

                    Debug.WriteLine(
                        "The state after jump:\t\t\t" +
                        $"{this.localContext.State.GetType().Name}");

                    if (state.IsJumpTargetSet)
                    {
                        this.adornment.EndorseTextBounds(
                            state.JumpTargetStartLine,
                            state.JumpTargetEndLine,
                            state.JumpTargetStartChar,
                            state.JumpTargetEndChar);

                        ITextSnapshotLine jumpTargetLine = view.TextSnapshot
                                                           .GetLineFromLineNumber(state.JumpTargetStartLine);
                        SnapshotPoint jumpPoint = jumpTargetLine.Start.Add(state.JumpTargetStartChar);

                        view.Caret.MoveTo(new SnapshotPoint(view.TextSnapshot, jumpPoint));

                        if (!view.TextViewLines.ContainsBufferPosition(jumpPoint))
                        {
                            var span = new SnapshotSpan(
                                view.TextSnapshot,
                                Span.FromBounds(jumpTargetLine.Start, jumpTargetLine.End));

                            view.ViewScroller.EnsureSpanVisible(
                                span,
                                EnsureSpanVisibleOptions.AlwaysCenter);
                        }

                        view.Caret.EnsureVisible();
                    }
                }
            }
            finally
            {
                this.operationSemaphorSlim.Release();
            }
        }
예제 #11
0
 /// <summary>
 /// Initializes a new instance of the <see cref="RenderExceptionEventArgs"/> class.
 /// </summary>
 /// <param name="exception">The exception.</param>
 /// <param name="textView">The text view.</param>
 public RenderExceptionEventArgs(Exception exception, ITextView?textView)
 {
     this.Exception = exception;
     this.TextView  = textView;
 }
예제 #12
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();
                }
            }