Exemplo n.º 1
0
        public void IsUnlinkedSpan_NullOwner_ReturnsTrue()
        {
            // Arrange
            Span owner = null;

            // Act
            var result = BraceSmartIndenter.IsUnlinkedSpan(owner);

            // Assert
            Assert.True(result);
        }
Exemplo n.º 2
0
        // Internal for testing
        internal static bool ContainsInvalidContent(Span owner)
        {
            // We only support whitespace based content. Any non-whitespace content is an unkonwn to us
            // in regards to indentation.
            for (var i = 0; i < owner.Tokens.Count; i++)
            {
                if (!string.IsNullOrWhiteSpace(owner.Tokens[i].Content))
                {
                    return(true);
                }
            }

            return(false);
        }
        private List <Span> Flatten(RazorSyntaxTree syntaxTree)
        {
            var result = new List <Span>();

            AppendFlattenedSpans(syntaxTree.Root, result);
            return(result);

            void AppendFlattenedSpans(SyntaxTreeNode node, List <Span> foundSpans)
            {
                Span spanNode = node as Span;

                if (spanNode != null)
                {
                    foundSpans.Add(spanNode);
                }
                else
                {
                    TagHelperBlock tagHelperNode = node as TagHelperBlock;
                    if (tagHelperNode != null)
                    {
                        // These aren't in document order, sort them first and then dig in
                        List <SyntaxTreeNode> attributeNodes = tagHelperNode.Attributes.Select(kvp => kvp.Value).Where(att => att != null).ToList();
                        attributeNodes.Sort((x, y) => x.Start.AbsoluteIndex.CompareTo(y.Start.AbsoluteIndex));

                        foreach (SyntaxTreeNode curNode in attributeNodes)
                        {
                            AppendFlattenedSpans(curNode, foundSpans);
                        }
                    }

                    Block blockNode = node as Block;
                    if (blockNode != null)
                    {
                        foreach (SyntaxTreeNode curNode in blockNode.Children)
                        {
                            AppendFlattenedSpans(curNode, foundSpans);
                        }
                    }
                }
            }
        }
        private PartialParseResultInternal GetPartialParseResult(SourceChange change)
        {
            var result = PartialParseResultInternal.Rejected;

            // Try the last change owner
            if (_lastChangeOwner != null && _lastChangeOwner.EditHandler.OwnsChange(_lastChangeOwner, change))
            {
                var editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
                result = editResult.Result;
                if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
                {
                    _lastChangeOwner.ReplaceWith(editResult.EditedSpan);
                }

                return(result);
            }

            // Locate the span responsible for this change
            _lastChangeOwner = SyntaxTreeRoot.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 editResult = _lastChangeOwner.EditHandler.ApplyChange(_lastChangeOwner, change);
                result = editResult.Result;
                if ((editResult.Result & PartialParseResultInternal.Rejected) != PartialParseResultInternal.Rejected)
                {
                    _lastChangeOwner.ReplaceWith(editResult.EditedSpan);
                }
            }

            return(result);
        }
        private Span LocateOwner(Block root, SourceChange change)
        {
            // Ask each child recursively
            Span owner = null;

            foreach (SyntaxTreeNode element in root.Children)
            {
                if (element.Start.AbsoluteIndex > change.Span.AbsoluteIndex)
                {
                    // too far
                    break;
                }

                int elementLen = element.Length;
                if (element.Start.AbsoluteIndex + elementLen < change.Span.AbsoluteIndex)
                {
                    // not far enough
                    continue;
                }

                if (element.IsBlock)
                {
                    Block block = element as Block;

                    if (element.Start.AbsoluteIndex + elementLen == change.Span.AbsoluteIndex)
                    {
                        Span lastDescendant = block.FindLastDescendentSpan();
                        if ((lastDescendant == null) && (block is TagHelperBlock))
                        {
                            TagHelperBlock tagHelperBlock = (TagHelperBlock)block;
                            if (tagHelperBlock.SourceEndTag != null)
                            {
                                lastDescendant = tagHelperBlock.SourceEndTag.FindLastDescendentSpan();
                            }
                            else if (tagHelperBlock.SourceStartTag != null)
                            {
                                lastDescendant = tagHelperBlock.SourceStartTag.FindLastDescendentSpan();
                            }
                        }

                        // Conceptually, lastDescendant should always be non-null, but runtime errs on some
                        //   cases and makes empty blocks. Runtime will fix these issues as we find them, but make
                        //   no guarantee that they catch them all.
                        if (lastDescendant == null)
                        {
                            owner = LocateOwner(block, change);
                            if (owner != null)
                            {
                                break;
                            }
                        }
                        else if (lastDescendant.EditHandler.OwnsChange(lastDescendant, change))
                        {
                            owner = lastDescendant;
                            break;
                        }
                    }
                    else
                    {
                        owner = LocateOwner(block, change);
                        if (owner != null)
                        {
                            break;
                        }
                    }
                }
                else
                {
                    Span span = element as Span;
                    if (span.EditHandler.OwnsChange(span, change))
                    {
                        owner = span;
                        break;
                    }
                }
            }

            if (owner == null)
            {
                TagHelperBlock tagHelperNode = root as TagHelperBlock;
                if (tagHelperNode != null)
                {
                    Block sourceStartTag = tagHelperNode.SourceStartTag;
                    Block sourceEndTag   = tagHelperNode.SourceEndTag;
                    if ((sourceStartTag.Start.AbsoluteIndex <= change.Span.AbsoluteIndex) &&
                        (sourceStartTag.Start.AbsoluteIndex + sourceStartTag.Length >= change.Span.AbsoluteIndex))
                    {
                        // intersects the start tag
                        return(LocateOwner(sourceStartTag, change));
                    }
                    else if ((sourceEndTag.Start.AbsoluteIndex <= change.Span.AbsoluteIndex) &&
                             (sourceEndTag.Start.AbsoluteIndex + sourceEndTag.Length >= change.Span.AbsoluteIndex))
                    {
                        // intersects the end tag
                        return(LocateOwner(sourceEndTag, change));
                    }
                }
            }

            return(owner);
        }
        public override int?GetDesiredIndentation(RazorSyntaxTree syntaxTree, ITextSnapshot syntaxTreeSnapshot, ITextSnapshotLine line, int indentSize, int tabSize)
        {
            if (syntaxTree == null)
            {
                throw new ArgumentNullException(nameof(syntaxTree));
            }

            if (syntaxTreeSnapshot == null)
            {
                throw new ArgumentNullException(nameof(syntaxTreeSnapshot));
            }

            if (line == null)
            {
                throw new ArgumentNullException(nameof(line));
            }

            if (indentSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(indentSize));
            }

            if (tabSize < 0)
            {
                throw new ArgumentOutOfRangeException(nameof(tabSize));
            }

            // The tricky thing here is that line.Snapshot is very likely newer
            var previousLine    = line.Snapshot.GetLineFromLineNumber(line.LineNumber - 1);
            var trackingPoint   = line.Snapshot.CreateTrackingPoint(line.End, PointTrackingMode.Negative);
            var previousLineEnd = trackingPoint.GetPosition(syntaxTreeSnapshot);

            var simulatedChange = new SourceChange(previousLineEnd, 0, string.Empty);
            var owningSpan      = LocateOwner(syntaxTree.Root, simulatedChange);

            int?desiredIndentation = null;

            if (owningSpan.Kind != SpanKindInternal.Code)
            {
                SyntaxTreeNode owningChild = owningSpan;
                while ((owningChild.Parent != null) && !desiredIndentation.HasValue)
                {
                    Block owningParent             = owningChild.Parent;
                    List <SyntaxTreeNode> children = new List <SyntaxTreeNode>(owningParent.Children);
                    for (int i = 0; i < children.Count; i++)
                    {
                        SyntaxTreeNode curChild = children[i];
                        if (!curChild.IsBlock)
                        {
                            Span curSpan = curChild as Span;
                            if (curSpan.Kind == SpanKindInternal.MetaCode)
                            {
                                // yay! We want to use the start of this span to determine the indent level.
                                var startLine   = line.Snapshot.GetLineFromLineNumber(curSpan.Start.LineIndex);
                                var extraIndent = 0;

                                // Dev11 337312: Only indent one level deeper if the item after the metacode is a markup block
                                if (i < children.Count - 1)
                                {
                                    SyntaxTreeNode nextChild = children[i + 1];
                                    if (nextChild.IsBlock && ((nextChild as Block).Type == BlockKindInternal.Markup))
                                    {
                                        extraIndent = indentSize;
                                    }
                                }

                                desiredIndentation = GetIndentLevelOfLine(startLine, tabSize) + indentSize;
                            }
                        }

                        if (curChild == owningChild)
                        {
                            break;
                        }
                    }

                    owningChild = owningParent;
                }
            }

            return(desiredIndentation);
        }
Exemplo n.º 7
0
 // Internal for testing
 internal static bool SurroundedByInvalidContent(Span owner)
 {
     return(owner.Next.Kind != SpanKindInternal.MetaCode ||
            owner.Previous.Kind != SpanKindInternal.MetaCode);
 }
Exemplo n.º 8
0
 // Internal for testing
 internal static bool IsUnlinkedSpan(Span owner)
 {
     return(owner == null ||
            owner.Next == null ||
            owner.Previous == null);
 }