Exemple #1
0
        /// <summary>
        /// The same as
        /// <see cref="LocalContextStateExtensions.ActiveNodeAs{T}(LocalContextState)"/>
        /// but for getting the virtual node.
        /// </summary>
        /// <typeparam name="T">The type of virtual node to get.</typeparam>
        /// <param name="state">
        /// The state from which the <see cref="LocalContextState.ActiveNode"/>
        /// should be retrieved and casted.
        /// </param>
        /// <returns>
        /// The casted <see cref="LocalContextState.ActiveNode"/> to the specified type.
        /// </returns>
        /// <exception cref="InvalidOperationException">
        /// Thrown when active node of the <see cref="LocalContextState"/>
        /// is not initialized or isn't virtual.
        /// </exception>
        /// <exception cref="InvalidCastException">
        /// Thrown when the <see cref="LocalContextState.ActiveNode"/> cannot be
        /// casted to the specified type.
        /// </exception>
        public static T ActiveNodeAsVirtual <T>(this LocalContextState state)
            where T : IVirtualSyntaxNode
        {
            _ = state ?? throw new ArgumentNullException(nameof(state));

            if (state.ActiveNode == null)
            {
                throw new InvalidOperationException(
                          "The active node is missing on the provided state.");
            }

            if (!state.ActiveNode.Value.IsVirtual)
            {
                throw new InvalidOperationException(
                          "The active node of the provided state is not a virtual node.");
            }

            if (!(state.ActiveNode.Value.MixedNode is T castedValue))
            {
                throw new InvalidCastException(
                          "The active node type doesn't match the requested one. " +
                          $"The actual type: {state.ActiveNode.Value.MixedNode.GetType()}. " +
                          $"The expected type: {typeof(T)}.");
            }

            return(castedValue);
        }
Exemple #2
0
        /// <summary>
        /// Retrieves the <see cref="LocalContextState.ActiveNode"/>
        /// for the specified <see cref="LocalContextState"/> and cast it
        /// to the specified type.
        /// </summary>
        /// <typeparam name="T">
        /// The type to which <see cref="LocalContextState.ActiveNode"/>
        /// should be casted.
        /// </typeparam>
        /// <param name="state">
        /// The state from which the <see cref="LocalContextState.ActiveNode"/>
        /// should be retrieved and casted.
        /// </param>
        /// <returns>
        /// The casted <see cref="LocalContextState.ActiveNode"/> to the specified type.
        /// </returns>
        /// <exception cref="InvalidCastException">
        /// Thrown when the <see cref="LocalContextState.ActiveNode"/> cannot be
        /// casted to the specified type.
        /// </exception>
        public static T ActiveNodeAs <T>(this LocalContextState state)
            where T : SyntaxNode
        {
            _ = state ?? throw new ArgumentNullException(nameof(state));

            if (!(state.ActiveNode?.BaseNode is T castedValue))
            {
                throw new InvalidCastException("Unable to cast the target node.");
            }

            return(castedValue);
        }
        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();
            }
        }