Example #1
0
        /// <summary>
        /// Returns true when the current position is inside user code (e.g. not strings) and the closing token
        /// matches the expected closing token for this brace completion service.
        /// Helper method used by <see cref="AllowOverType(BraceCompletionContext, CancellationToken)"/> implementations.
        /// </summary>
        protected bool AllowOverTypeInUserCodeWithValidClosingToken(BraceCompletionContext context, CancellationToken cancellationToken)
        {
            var tree = context.Document.SyntaxTree;
            var syntaxFactsService = context.Document.LanguageServices.GetRequiredService <ISyntaxFactsService>();

            return(!syntaxFactsService.IsInNonUserCode(tree, context.CaretLocation, cancellationToken) &&
                   CheckClosingTokenKind(context.Document, context.ClosingPoint));
        }
Example #2
0
 /// <summary>
 /// Returns true when the closing token matches the expected closing token for this brace completion service.
 /// Used by <see cref="AllowOverTypeAsync(BraceCompletionContext, CancellationToken)"/> implementations
 /// when the over type could be triggered from outside of user code (e.g. overtyping end quotes in a string).
 /// </summary>
 protected Task <bool> AllowOverTypeWithValidClosingTokenAsync(
     BraceCompletionContext context,
     CancellationToken cancellationToken
     )
 {
     return(CheckClosingTokenKindAsync(
                context.Document,
                context.ClosingPoint,
                cancellationToken
                ));
 }
Example #3
0
        public async Task <BraceCompletionResult?> GetBraceCompletionAsync(
            BraceCompletionContext braceCompletionContext,
            CancellationToken cancellationToken
            )
        {
            var closingPoint = braceCompletionContext.ClosingPoint;

            if (closingPoint < 1)
            {
                return(null);
            }

            var openingPoint = braceCompletionContext.OpeningPoint;
            var document     = braceCompletionContext.Document;

            var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            if (sourceText[openingPoint] != OpeningBrace)
            {
                return(null);
            }

            var root = await document
                       .GetRequiredSyntaxRootAsync(cancellationToken)
                       .ConfigureAwait(false);

            var token             = root.FindToken(openingPoint, findInsideTrivia: true);
            var validOpeningPoint = await IsValidOpenBraceTokenAtPositionAsync(
                token,
                openingPoint,
                document,
                cancellationToken
                )
                                    .ConfigureAwait(false);

            if (!validOpeningPoint)
            {
                return(null);
            }

            var braceTextEdit = new TextChange(
                TextSpan.FromBounds(closingPoint, closingPoint),
                ClosingBrace.ToString()
                );
            // The caret location should be in between the braces.
            var originalOpeningLinePosition = sourceText.Lines.GetLinePosition(openingPoint);
            var caretLocation = new LinePosition(
                originalOpeningLinePosition.Line,
                originalOpeningLinePosition.Character + 1
                );

            return(new BraceCompletionResult(ImmutableArray.Create(braceTextEdit), caretLocation));
        }
        public async Task <BraceCompletionResult?> GetBraceCompletionAsync(BraceCompletionContext braceCompletionContext, CancellationToken cancellationToken)
        {
            var closingPoint = braceCompletionContext.ClosingPoint;

            if (closingPoint < 1)
            {
                return(null);
            }

            var openingPoint = braceCompletionContext.OpeningPoint;
            var document     = braceCompletionContext.Document;

            var sourceText = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);

            if (sourceText[openingPoint] != OpeningBrace)
            {
                return(null);
            }

            var root = await document.GetRequiredSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            var token = root.FindToken(openingPoint, findInsideTrivia: true);

            if (NeedsSemantics)
            {
                // Pass along a document with frozen partial semantics.  Brace completion is a highly latency sensitive
                // operation.  We don't want to wait on things like source generators to figure things out.
                var validOpeningPoint = await IsValidOpenBraceTokenAtPositionAsync(
                    document.WithFrozenPartialSemantics(cancellationToken), token, openingPoint, cancellationToken).ConfigureAwait(false);

                if (!validOpeningPoint)
                {
                    return(null);
                }
            }
            else
            {
                var validOpeningPoint = IsValidOpenBraceTokenAtPosition(sourceText, token, openingPoint);
                if (!validOpeningPoint)
                {
                    return(null);
                }
            }

            var braceTextEdit = new TextChange(TextSpan.FromBounds(closingPoint, closingPoint), ClosingBrace.ToString());

            // The caret location should be in between the braces.
            var originalOpeningLinePosition = sourceText.Lines.GetLinePosition(openingPoint);
            var caretLocation = new LinePosition(originalOpeningLinePosition.Line, originalOpeningLinePosition.Character + 1);

            return(new BraceCompletionResult(ImmutableArray.Create(braceTextEdit), caretLocation));
        }
Example #5
0
        public BraceCompletionResult GetBraceCompletion(BraceCompletionContext context)
        {
            Debug.Assert(context.HasCompletionForOpeningBrace(OpeningBrace));

            var closingPoint  = context.ClosingPoint;
            var braceTextEdit = new TextChange(TextSpan.FromBounds(closingPoint, closingPoint), ClosingBrace.ToString());

            // The caret location should be in between the braces.
            var originalOpeningLinePosition = context.Document.Text.Lines.GetLinePosition(context.OpeningPoint);
            var caretLocation = new LinePosition(originalOpeningLinePosition.Line, originalOpeningLinePosition.Character + 1);

            return(new BraceCompletionResult(ImmutableArray.Create(braceTextEdit), caretLocation));
        }
Example #6
0
        public Task <bool> HasBraceCompletionAsync(BraceCompletionContext context, Document document, CancellationToken cancellationToken)
        {
            if (!context.HasCompletionForOpeningBrace(OpeningBrace))
            {
                return(Task.FromResult(false));
            }

            var openingToken = context.GetOpeningToken();

            if (!NeedsSemantics)
            {
                return(Task.FromResult(IsValidOpenBraceTokenAtPosition(context.Document.Text, openingToken, context.OpeningPoint)));
            }

            // Pass along a document with frozen partial semantics.  Brace completion is a highly latency sensitive
            // operation.  We don't want to wait on things like source generators to figure things out.
            return(IsValidOpenBraceTokenAtPositionAsync(document.WithFrozenPartialSemantics(cancellationToken), openingToken, context.OpeningPoint, cancellationToken));
        }
Example #7
0
        /// <summary>
        /// Returns true when the current position is inside user code (e.g. not strings) and the closing token
        /// matches the expected closing token for this brace completion service.
        /// Helper method used by <see cref="AllowOverTypeAsync(BraceCompletionContext, CancellationToken)"/> implementations.
        /// </summary>
        protected async Task <bool> AllowOverTypeInUserCodeWithValidClosingTokenAsync(
            BraceCompletionContext context,
            CancellationToken cancellationToken
            )
        {
            var tree = await context.Document
                       .GetRequiredSyntaxTreeAsync(cancellationToken)
                       .ConfigureAwait(false);

            var syntaxFactsService =
                context.Document.GetRequiredLanguageService <ISyntaxFactsService>();

            return(!syntaxFactsService.IsInNonUserCode(
                       tree,
                       context.CaretLocation,
                       cancellationToken
                       ) &&
                   await CheckClosingTokenKindAsync(
                       context.Document,
                       context.ClosingPoint,
                       cancellationToken
                       )
                   .ConfigureAwait(false));
        }
 public virtual Task <BraceCompletionResult?> GetTextChangeAfterReturnAsync(BraceCompletionContext braceCompletionContext, IndentationOptions options, CancellationToken cancellationToken)
 => SpecializedTasks.Default <BraceCompletionResult?>();
 public abstract Task <bool> AllowOverTypeAsync(BraceCompletionContext braceCompletionContext, CancellationToken cancellationToken);
Example #10
0
 public virtual Task <BraceCompletionResult?> GetTextChangesAfterCompletionAsync(
     BraceCompletionContext braceCompletionContext,
     CancellationToken cancellationToken
     ) => SpecializedTasks.Default <BraceCompletionResult?>();
Example #11
0
 public virtual BraceCompletionResult?GetTextChangeAfterReturn(BraceCompletionContext braceCompletionContext, IndentationOptions options, CancellationToken cancellationToken)
 => null;
Example #12
0
 public abstract bool AllowOverType(BraceCompletionContext braceCompletionContext, CancellationToken cancellationToken);
Example #13
0
 /// <summary>
 /// Returns true when the closing token matches the expected closing token for this brace completion service.
 /// Used by <see cref="AllowOverType(BraceCompletionContext, CancellationToken)"/> implementations
 /// when the over type could be triggered from outside of user code (e.g. overtyping end quotes in a string).
 /// </summary>
 protected bool AllowOverTypeWithValidClosingToken(BraceCompletionContext context)
 {
     return(CheckClosingTokenKind(context.Document, context.ClosingPoint));
 }