// Internal for testing
        internal static bool IsAcceptableInsertion(SourceChange change)
        {
            if (!change.IsInsert)
            {
                return(false);
            }

            if (ContainsInvalidContent(change))
            {
                return(false);
            }

            return(true);
        }
        public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, TagHelperDocumentContext tagHelperDocumentContext, SourceSpan location)
        {
            if (syntaxTree is null)
            {
                throw new ArgumentNullException(nameof(syntaxTree));
            }

            if (tagHelperDocumentContext is null)
            {
                throw new ArgumentNullException(nameof(tagHelperDocumentContext));
            }

            if (!FileKinds.IsComponent(syntaxTree.Options.FileKind))
            {
                // Directive attributes are only supported in components
                return(Array.Empty <RazorCompletionItem>());
            }

            var change = new SourceChange(location, string.Empty);
            var owner  = syntaxTree.Root.LocateOwner(change);

            if (owner == null)
            {
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!TryGetAttributeInfo(owner, out var attributeName, out var attributeNameLocation, out _, out _))
            {
                // Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions.
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!attributeNameLocation.IntersectsWith(location.AbsoluteIndex))
            {
                // We're trying to retrieve completions on a portion of the name that is not supported (such as a parameter).
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes))
            {
                // This should never be the case, it means that we're operating on an attribute that doesn't have a tag.
                return(Array.Empty <RazorCompletionItem>());
            }

            // At this point we've determined that completions have been requested for the name portion of the selected attribute.

            var completionItems = GetAttributeCompletions(attributeName, containingTagName, attributes, tagHelperDocumentContext);

            return(completionItems);
        }
Esempio n. 3
0
 public override IEnumerable <IModelChange> Invert()
 {
     for (int i = NestedChanges.Count - 1; i >= 0; i--)
     {
         foreach (var inverted in NestedChanges[i].Invert())
         {
             yield return(inverted);
         }
     }
     foreach (var invertedSource in SourceChange.Invert())
     {
         yield return(invertedSource);
     }
 }
        public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, TagHelperDocumentContext tagHelperDocumentContext, SourceSpan location)
        {
            if (syntaxTree is null)
            {
                throw new ArgumentNullException(nameof(syntaxTree));
            }

            if (tagHelperDocumentContext is null)
            {
                throw new ArgumentNullException(nameof(tagHelperDocumentContext));
            }

            var change = new SourceChange(location, string.Empty);
            var owner  = syntaxTree.Root.LocateOwner(change);

            if (owner == null)
            {
                Debug.Fail("Owner should never be null.");
                return(Array.Empty <RazorCompletionItem>());
            }

            var parent = owner.Parent;

            if (_htmlFactsService.TryGetElementInfo(parent, out var containingTagNameToken, out var attributes) &&
                containingTagNameToken.Span.IntersectsWith(location.AbsoluteIndex))
            {
                var stringifiedAttributes = _tagHelperFactsService.StringifyAttributes(attributes);
                var elementCompletions    = GetElementCompletions(parent, containingTagNameToken.Content, stringifiedAttributes, tagHelperDocumentContext);
                return(elementCompletions);
            }

            if (_htmlFactsService.TryGetAttributeInfo(
                    parent,
                    out containingTagNameToken,
                    out var prefixLocation,
                    out var selectedAttributeName,
                    out var selectedAttributeNameLocation,
                    out attributes) &&
                (selectedAttributeName == null ||
                 selectedAttributeNameLocation?.IntersectsWith(location.AbsoluteIndex) == true ||
                 (prefixLocation?.IntersectsWith(location.AbsoluteIndex) ?? false)))
            {
                var stringifiedAttributes = _tagHelperFactsService.StringifyAttributes(attributes);
                var attributeCompletions  = GetAttributeCompletions(parent, containingTagNameToken.Content, selectedAttributeName, stringifiedAttributes, tagHelperDocumentContext);
                return(attributeCompletions);
            }

            // Invalid location for TagHelper completions.
            return(Array.Empty <RazorCompletionItem>());
        }
        // Internal for testing
        internal static bool IsAcceptableDeletion(SyntaxNode target, SourceChange change)
        {
            if (!change.IsDelete)
            {
                return(false);
            }

            if (ModifiesInvalidContent(target, change))
            {
                return(false);
            }

            return(true);
        }
Esempio n. 6
0
        public static SyntaxNode LocateOwner(this SyntaxNode node, SourceChange change)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            if (change.Span.AbsoluteIndex < node.Position)
            {
                // Early escape for cases where changes overlap multiple spans
                // In those cases, the span will return false, and we don't want to search the whole tree
                // So if the current span starts after the change, we know we've searched as far as we need to
                return(null);
            }

            if (IsSpanKind(node))
            {
                var editHandler = node.GetSpanContext()?.EditHandler ?? SpanEditHandler.CreateDefault();
                return(editHandler.OwnsChange(node, change) ? node : null);
            }

            SyntaxNode owner = null;
            IEnumerable <SyntaxNode> children = null;

            if (node is MarkupStartTagSyntax startTag)
            {
                children = startTag.Children;
            }
            else if (node is MarkupEndTagSyntax endTag)
            {
                children = endTag.Children;
            }
            else
            {
                children = node.ChildNodes();
            }

            foreach (var child in children)
            {
                owner = LocateOwner(child, change);
                if (owner != null)
                {
                    break;
                }
            }

            return(owner);
        }
        private void TextBuffer_OnChanged(object sender, TextContentChangedEventArgs args)
        {
            _dispatcher.AssertForegroundThread();

            if (args.Changes.Count > 0)
            {
                // Idle timers are used to track provisional changes. Provisional changes only last for a single text change. After that normal
                // partial parsing rules apply (stop the timer).
                StopIdleTimer();
            }

            var snapshot = args.After;

            if (!args.TextChangeOccurred(out var changeInformation))
            {
                // Ensure we get a parse for latest snapshot.
                QueueChange(null, snapshot);
                return;
            }

            var             change = new SourceChange(changeInformation.firstChange.OldPosition, changeInformation.oldText.Length, changeInformation.newText);
            var             result = PartialParseResultInternal.Rejected;
            RazorSyntaxTree partialParseSyntaxTree = null;

            using (_parser.SynchronizeMainThreadState())
            {
                // Check if we can partial-parse
                if (_partialParser != null && _parser.IsIdle)
                {
                    (result, partialParseSyntaxTree) = _partialParser.Parse(change);
                }
            }

            // If partial parsing failed or there were outstanding parser tasks, start a full reparse
            if ((result & PartialParseResultInternal.Rejected) == PartialParseResultInternal.Rejected)
            {
                QueueChange(change, snapshot);
            }
            else
            {
                TryUpdateLatestParsedSyntaxTreeSnapshot(partialParseSyntaxTree, snapshot);
            }

            if ((result & PartialParseResultInternal.Provisional) == PartialParseResultInternal.Provisional)
            {
                StartIdleTimer();
            }
        }
Esempio n. 8
0
        public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorCompletionContext context, SourceSpan location)
        {
            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (context.TagHelperDocumentContext is null)
            {
                throw new ArgumentNullException(nameof(context.TagHelperDocumentContext));
            }

            if (!FileKinds.IsComponent(context.SyntaxTree.Options.FileKind))
            {
                // Directive attribute parameters are only supported in components
                return(Array.Empty <RazorCompletionItem>());
            }

            var change = new SourceChange(location, string.Empty);
            var owner  = context.SyntaxTree.Root.LocateOwner(change);

            if (owner is null)
            {
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!TryGetAttributeInfo(owner, out _, out var attributeName, out _, out var parameterName, out var parameterNameLocation))
            {
                // Either we're not in an attribute or the attribute is so malformed that we can't provide proper completions.
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!parameterNameLocation.IntersectsWith(location.AbsoluteIndex))
            {
                // We're trying to retrieve completions on a portion of the name that is not supported (such as the name, i.e., |@bind|:format).
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!TryGetElementInfo(owner.Parent.Parent, out var containingTagName, out var attributes))
            {
                // This should never be the case, it means that we're operating on an attribute that doesn't have a tag.
                return(Array.Empty <RazorCompletionItem>());
            }

            var completions = GetAttributeParameterCompletions(attributeName, parameterName, containingTagName, attributes, context.TagHelperDocumentContext);

            return(completions);
        }
Esempio n. 9
0
    Document GetChangedDocument(Document originalDocument, SourceChangeList changes)
    {
        string        originalString = originalDocument.Text.Source;
        StringBuilder sb             = new StringBuilder();
        int           lastPos        = 0;

        for (int i = 0, n = changes.Count; i < n; i++)
        {
            SourceChange sc = changes[i];
            sb.Append(originalString, lastPos, sc.SourceContext.StartPos - lastPos);
            sb.Append(sc.ChangedText);
            lastPos = sc.SourceContext.EndPos;
        }
        sb.Append(originalString, lastPos, originalString.Length - lastPos);
        return(this.compiler.CreateDocument(this.compilationUnit.SourceContext.Document.Name, 1, sb.ToString()));
    }
Esempio n. 10
0
 private PartialParseResult HandleInsertion(Span target, char previousChar, SourceChange change)
 {
     // What are we inserting after?
     if (previousChar == '.')
     {
         return(HandleInsertionAfterDot(target, change));
     }
     else if (ParserHelpers.IsIdentifierPart(previousChar) || previousChar == ')' || previousChar == ']')
     {
         return(HandleInsertionAfterIdPart(target, change));
     }
     else
     {
         return(PartialParseResult.Rejected);
     }
 }
Esempio n. 11
0
 private PartialParseResult HandleDeletion(Span target, char previousChar, SourceChange change)
 {
     // What's left after deleting?
     if (previousChar == '.')
     {
         return(TryAcceptChange(target, change, PartialParseResult.Accepted | PartialParseResult.Provisional));
     }
     else if (ParserHelpers.IsIdentifierPart(previousChar))
     {
         return(TryAcceptChange(target, change));
     }
     else
     {
         return(PartialParseResult.Rejected);
     }
 }
Esempio n. 12
0
        public virtual EditResult ApplyChange(SyntaxNode target, SourceChange change, bool force)
        {
            var result = PartialParseResultInternal.Accepted;

            if (!force)
            {
                result = CanAcceptChange(target, change);
            }

            // If the change is accepted then apply the change
            if ((result & PartialParseResultInternal.Accepted) == PartialParseResultInternal.Accepted)
            {
                return(new EditResult(result, UpdateSpan(target, change)));
            }
            return(new EditResult(result, target));
        }
        [InlineData(9, 5, " Space")] // "Some Name Space"
        public void CanAcceptChange_RejectsWhitespaceChanges(int index, int length, string newText)
        {
            // Arrange
            var factory = new SpanFactory();
            var directiveTokenHandler = new TestDirectiveTokenEditHandler();
            var target = factory.Span(SpanKindInternal.Code, "Some Namespace", markup: false)
                         .With(directiveTokenHandler)
                         .Accepts(AcceptedCharactersInternal.NonWhiteSpace);
            var sourceChange = new SourceChange(index, length, newText);

            // Act
            var result = directiveTokenHandler.CanAcceptChange(target, sourceChange);

            // Assert
            Assert.Equal(PartialParseResult.Rejected, result);
        }
        public override bool TryResolveInsertion(Position position, FormattingContext context, out TextEdit edit, out InsertTextFormat format)
        {
            if (position is null)
            {
                throw new ArgumentNullException(nameof(position));
            }

            if (context is null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            var syntaxTree = context.CodeDocument.GetSyntaxTree();

            var absoluteIndex = position.GetAbsoluteIndex(context.SourceText);
            var change        = new SourceChange(absoluteIndex, 0, string.Empty);
            var owner         = syntaxTree.Root.LocateOwner(change);

            if (!IsAtEnterRuleLocation(owner))
            {
                format = default;
                edit   = default;
                return(false);
            }

            // We're currently at:
            // <someTag>
            // |</someTag>

            context.SourceText.GetLineAndOffset(owner.SpanStart, out var lineNumber, out _);

            var existingIndentation        = context.Indentations[lineNumber].ExistingIndentation;
            var existingIndentationString  = context.GetIndentationString(existingIndentation);
            var increasedIndentationString = context.GetIndentationLevelString(indentationLevel: 1);
            var innerIndentationString     = string.Concat(increasedIndentationString, existingIndentationString);

            // We mark start position at the beginning of the line in order to remove any pre-existing whitespace.
            var startPosition = new Position(position.Line, 0);

            format = InsertTextFormat.Snippet;
            edit   = new TextEdit()
            {
                NewText = $"{innerIndentationString}$0{Environment.NewLine}{existingIndentationString}",
                Range   = new Range(startPosition, position)
            };
            return(true);
        }
Esempio n. 15
0
        protected virtual SpanBuilder UpdateSpan(Span target, SourceChange change)
        {
            var newContent = change.GetEditedContent(target);
            var newSpan    = new SpanBuilder(target);

            newSpan.ClearTokens();
            foreach (var token in Tokenizer(newContent))
            {
                newSpan.Accept(token);
            }
            if (target.Next != null)
            {
                var newEnd = SourceLocationTracker.CalculateNewLocation(target.Start, newContent);
                target.Next.ChangeStart(newEnd);
            }
            return(newSpan);
        }
        [InlineData(9, 5, " Space")] // "Some Name Space"
        public void CanAcceptChange_RejectsWhitespaceChanges(int index, int length, string newText)
        {
            // Arrange
            var directiveTokenHandler = new TestDirectiveTokenEditHandler();

            directiveTokenHandler.AcceptedCharacters = AcceptedCharactersInternal.NonWhitespace;

            var target = GetSyntaxNode(directiveTokenHandler, "Some Namespace");

            var sourceChange = new SourceChange(index, length, newText);

            // Act
            var result = directiveTokenHandler.CanAcceptChange(target, sourceChange);

            // Assert
            Assert.Equal(PartialParseResultInternal.Rejected, result);
        }
Esempio n. 17
0
        /// <summary>
        /// Make generic change to running assembly using EnC.
        /// </summary>
        /// <param name="change">Description of change.</param>
        public void MakeChange(SourceChange change)
        {
            switch (change.MemberKind)
            {
            case SourceChangeMember.Method:
                if (change.MemberAction == SourceChangeAction.BodyChanged)
                {
                    ChangeMethod((IMethod)change.OldEntity);
                }
                else if (change.MemberAction == SourceChangeAction.Created &&
                         change.NewEntity.IsPrivate && !change.NewEntity.IsVirtual)
                {
                    AddMethod((IMethod)change.NewEntity);
                }
                else
                {
                    throw new TranslatingException("This kind of change is not supported by this version of EnC.");
                }
                break;

            case SourceChangeMember.Property:
                if (change.MemberAction == SourceChangeAction.BodyChanged)
                {
                    ChangeProperty((IProperty)change.OldEntity, ((BodyChange)change).isGetter);
                }
                else
                {
                    throw new TranslatingException("This kind of change is not supported by this version of EnC.");
                }
                break;

            case SourceChangeMember.Field:
                if (change.MemberAction == SourceChangeAction.Created)
                {
                    addField((IField)change.NewEntity);
                }
                else
                {
                    throw new TranslatingException("This kind of change is not supported by this version of EnC.");
                }
                break;

            default:
                throw new TranslatingException("This kind of change is not supported by this version of EnC.");
            }
        }
    protected override PartialParseResultInternal CanAcceptChange(SyntaxNode target, SourceChange change)
    {
        if (AcceptedCharacters == AcceptedCharactersInternal.NonWhitespace)
        {
            var originalText  = change.GetOriginalText(target);
            var editedContent = change.GetEditedContent(target);

            if (!ContainsWhitespace(originalText) && !ContainsWhitespace(editedContent))
            {
                // Did not modify whitespace, directive format should be the same.
                // Return provisional so extensible IR/code gen pieces can see the full directive text
                // once the user stops editing the document.
                return(PartialParseResultInternal.Accepted | PartialParseResultInternal.Provisional);
            }
        }

        return(PartialParseResultInternal.Rejected);
    }
Esempio n. 19
0
    public void GetOrigninalText_SpanIsOwner_ReturnsContent_ZeroLengthSpan()
    {
        // Arrange
        var builder = SyntaxListBuilder <SyntaxToken> .Create();

        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "Hello, "));
        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "World"));

        var node = SyntaxFactory.MarkupTextLiteral(builder.ToList()).CreateRed(null, 13);

        var change = new SourceChange(15, 0, "heyo");

        // Act
        var result = change.GetOriginalText(node);

        // Act
        Assert.Equal(string.Empty, result);
    }
Esempio n. 20
0
    public void GetOffSet_SpanIsOwner_ReturnsOffset()
    {
        // Arrange
        var builder = SyntaxListBuilder <SyntaxToken> .Create();

        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "Hello, "));
        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "World"));

        var node = SyntaxFactory.MarkupTextLiteral(builder.ToList()).CreateRed(null, 13);

        var change = new SourceChange(15, 2, "heyo");

        // Act
        var result = change.GetOffset(node);

        // Act
        Assert.Equal(2, result);
    }
Esempio n. 21
0
    public void GetEditedContent_SyntaxNode_ReturnsNewContent()
    {
        // Arrange
        var builder = SyntaxListBuilder <SyntaxToken> .Create();

        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "Hello, "));
        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "World"));

        var node = SyntaxFactory.MarkupTextLiteral(builder.ToList()).CreateRed();

        var change = new SourceChange(2, 2, "heyo");

        // Act
        var result = change.GetEditedContent(node);

        // Act
        Assert.Equal("Heheyoo, World", result);
    }
Esempio n. 22
0
        public override IReadOnlyList <RazorCompletionItem> GetCompletionItems(RazorSyntaxTree syntaxTree, TagHelperDocumentContext tagHelperDocumentContext, SourceSpan location)
        {
            if (!FileKinds.IsComponent(syntaxTree.Options.FileKind))
            {
                // Directive attributes are only supported in components
                return(Array.Empty <RazorCompletionItem>());
            }

            var change = new SourceChange(location, string.Empty);
            var owner  = syntaxTree.Root.LocateOwner(change);

            if (owner == null)
            {
                return(Array.Empty <RazorCompletionItem>());
            }

            var attribute = owner.Parent;

            if (attribute is MarkupMiscAttributeContentSyntax)
            {
                // This represents a tag when there's no attribute content <InputText | />.
                return(Completions);
            }

            if (!TryGetAttributeInfo(owner, out var prefixLocation, out var attributeName, out var attributeNameLocation, out _, out _))
            {
                return(Array.Empty <RazorCompletionItem>());
            }

            if (attributeNameLocation.IntersectsWith(location.AbsoluteIndex) && attributeName.StartsWith("@", StringComparison.Ordinal))
            {
                // The transition is already provided for the attribute name
                return(Array.Empty <RazorCompletionItem>());
            }

            if (!IsValidCompletionPoint(location, prefixLocation, attributeNameLocation))
            {
                // Not operating in the attribute name area
                return(Array.Empty <RazorCompletionItem>());
            }

            // This represents a tag when there's no attribute content <InputText | />.
            return(Completions);
        }
Esempio n. 23
0
    public void GetOffSet_SpanIsNotOwnerOfChange_ThrowsException()
    {
        // Arrange
        var builder = SyntaxListBuilder <SyntaxToken> .Create();

        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "Hello, "));
        builder.Add(SyntaxFactory.Token(SyntaxKind.Marker, "World"));

        var node = SyntaxFactory.MarkupTextLiteral(builder.ToList()).CreateRed(null, 13);

        var change = new SourceChange(12, 2, "heyo");

        var expected = $"The node '{node}' is not the owner of change '{change}'.";

        // Act & Assert
        var exception = Assert.Throws <InvalidOperationException>(() => { change.GetOffset(node); });

        Assert.Equal(expected, exception.Message);
    }
Esempio n. 24
0
        protected override PartialParseResultInternal CanAcceptChange(Span target, SourceChange change)
        {
            if (IsAcceptableDeletion(target, change))
            {
                return(PartialParseResultInternal.Accepted);
            }

            if (IsAcceptableReplacement(target, change))
            {
                return(PartialParseResultInternal.Accepted);
            }

            if (IsAcceptableInsertion(change))
            {
                return(PartialParseResultInternal.Accepted);
            }

            return(PartialParseResultInternal.Rejected);
        }
Esempio n. 25
0
        private bool AtDirectiveCompletionPoint(RazorSyntaxTree syntaxTree, CompletionContext context)
        {
            if (TryGetRazorSnapshotPoint(context, out var razorSnapshotPoint))
            {
                var change = new SourceChange(razorSnapshotPoint.Position, 0, string.Empty);
                var owner  = syntaxTree.Root.LocateOwner(change);
                if (owner.ChunkGenerator is ExpressionChunkGenerator &&
                    owner.Symbols.All(IsDirectiveCompletableSymbol) &&
                    // Do not provide IntelliSense for explicit expressions. Explicit expressions will usually look like:
                    // [@] [(] [DateTime.Now] [)]
                    owner.Parent?.Children.Count > 1 &&
                    owner.Parent.Children[1] == owner)
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 26
0
        // Internal for testing
        internal static bool IsAcceptableReplacement(SyntaxNode target, SourceChange change)
        {
            if (!change.IsReplace)
            {
                return(false);
            }

            if (ContainsInvalidContent(change))
            {
                return(false);
            }

            if (ModifiesInvalidContent(target, change))
            {
                return(false);
            }

            return(true);
        }
Esempio n. 27
0
        private static bool IsPartOfHtmlTag(FormattingContext context, int position)
        {
            var syntaxTree = context.CodeDocument.GetSyntaxTree();
            var change     = new SourceChange(position, 0, string.Empty);
            var owner      = syntaxTree.Root.LocateOwner(change);

            if (owner == null)
            {
                // Can't determine owner of this position.
                return(false);
            }

            // E.g, (| is position)
            //
            // `<p csharpattr="|Variable">` - true
            //
            return(owner.AncestorsAndSelf().Any(
                       n => n is MarkupStartTagSyntax || n is MarkupTagHelperStartTagSyntax || n is MarkupEndTagSyntax || n is MarkupTagHelperEndTagSyntax));
        }
        private PartialParseResultInternal GetPartialParseResult(SourceChange change)
        {
            var result = PartialParseResultInternal.Rejected;

            // Try the last change owner
            if (_lastChangeOwner != null)
            {
                var editHandler = _lastChangeOwner.GetSpanContext()?.EditHandler ?? SpanEditHandler.CreateDefault();
                if (editHandler.OwnsChange(_lastChangeOwner, change))
                {
                    var editResult = editHandler.ApplyChange(_lastChangeOwner, change);
                    result = editResult.Result;
                    if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
                    {
                        ReplaceLastChangeOwner(editResult.EditedNode);
                    }
                }

                return(result);
            }

            // Locate the span responsible for this change
            _lastChangeOwner = ModifiedSyntaxTreeRoot.LocateOwner(change);

            if (_lastResultProvisional)
            {
                // Last change owner couldn't accept this, so we must do a full reparse
                result = PartialParseResultInternal.Rejected;
            }
            else if (_lastChangeOwner != null)
            {
                var editHandler = _lastChangeOwner.GetSpanContext()?.EditHandler ?? SpanEditHandler.CreateDefault();
                var editResult  = editHandler.ApplyChange(_lastChangeOwner, change);
                result = editResult.Result;
                if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
                {
                    ReplaceLastChangeOwner(editResult.EditedNode);
                }
            }

            return(result);
        }
Esempio n. 29
0
        private async Task <TagHelperBinding> GetOriginTagHelperBindingAsync(DocumentSnapshot documentSnapshot, RazorCodeDocument codeDocument, Position position)
        {
            var sourceText = await documentSnapshot.GetTextAsync().ConfigureAwait(false);

            var linePosition      = new LinePosition((int)position.Line, (int)position.Character);
            var hostDocumentIndex = sourceText.Lines.GetPosition(linePosition);
            var location          = new SourceLocation(hostDocumentIndex, (int)position.Line, (int)position.Character);

            var change     = new SourceChange(location.AbsoluteIndex, length: 0, newText: string.Empty);
            var syntaxTree = codeDocument.GetSyntaxTree();

            if (syntaxTree?.Root is null)
            {
                return(null);
            }

            var owner = syntaxTree.Root.LocateOwner(change);

            if (owner is null)
            {
                return(null);
            }

            var node = owner.Ancestors().FirstOrDefault(n => n.Kind == SyntaxKind.MarkupTagHelperStartTag);

            if (node == null || !(node is MarkupTagHelperStartTagSyntax tagHelperStartTag))
            {
                return(null);
            }

            if (!tagHelperStartTag.Name.Span.Contains(location.AbsoluteIndex))
            {
                return(null);
            }

            if (!(tagHelperStartTag?.Parent is MarkupTagHelperElementSyntax tagHelperElement))
            {
                return(null);
            }

            return(tagHelperElement.TagHelperInfo.BindingResult);
        }
        // Internal for testing
        internal static bool IsAcceptableInsertionInBalancedParenthesis(Span target, SourceChange change)
        {
            if (!change.IsInsert)
            {
                return(false);
            }

            if (change.NewText.IndexOfAny(new[] { '(', ')' }) >= 0)
            {
                // Insertions of parenthesis aren't handled by us. If someone else wants to accept it, they can.
                return(false);
            }

            if (IsInsideParenthesis(change.Span.AbsoluteIndex, target.Tokens))
            {
                return(true);
            }

            return(false);
        }
Esempio n. 31
0
 SourceChangeList ConstructSourceChangeList(){
   SourceChangeList result = new SourceChangeList();
   int lastPos = 0;
   do{
     int beforeLine = this.lineCounter;
     string beforeText = this.ReadString();
     if (this.inputLine != "after") 
       throw new MalformedSuiteException("Line "+this.lineCounter+": Expected an 'after' line");
     string afterText = this.ReadString();
     SourceChange sc = new SourceChange();
     sc.ChangedText = afterText;
     sc.SourceContext = this.compilationUnit.SourceContext;
     int beforePos = this.currentDocument.Text.Source.IndexOf(beforeText, lastPos);
     if (beforePos < 0) 
       throw new MalformedSuiteException("Line "+beforeLine+": before text not found");
     sc.SourceContext.StartPos = beforePos;
     sc.SourceContext.EndPos = lastPos = beforePos + beforeText.Length;
     result.Add(sc);
   }while (this.inputLine == "before");
   return result;
 }