private static CharacterSpan GetCharacterSpan(LocationSpan locationSpan, CharacterPositionFinder finder)
        {
            var startPos = finder.GetCharacterPosition(locationSpan.Start);
            var endPos   = finder.GetCharacterPosition(locationSpan.End);

            return(new CharacterSpan(startPos, endPos));
        }
        private static int AdjustBegin(Container parent, IList <ContainerOrTerminalNode> parentChildren, int indexInParentChildren, CharacterPositionFinder finder)
        {
            var node = parentChildren[indexInParentChildren];

            int newStartPos;

            var first = node == parentChildren.First();

            if (first)
            {
                // first child, so adjust parent's header span and terminal node's line start and span begin
                newStartPos = parent.HeaderSpan.End + 1;

                var parentHeaderSpanEnd = finder.GetLineInfo(parent.HeaderSpan.End);
                if (parentHeaderSpanEnd.LineNumber < node.LocationSpan.Start.LineNumber)
                {
                    // different lines, so adjust line end of parent
                    newStartPos = AdjustHeaderToLineEnd(parent, finder);
                }
            }
            else
            {
                var siblingBefore = parentChildren.ElementAt(indexInParentChildren - 1);
                newStartPos = siblingBefore.GetTotalSpan().End + 1;

                var siblingBeforeEndLineNumber = siblingBefore.LocationSpan.End.LineNumber;
                if (siblingBeforeEndLineNumber != node.LocationSpan.Start.LineNumber)
                {
                    newStartPos = finder.GetCharacterPosition(new LineInfo(siblingBeforeEndLineNumber + 1, 1));
                }
            }

            return(newStartPos);
        }
        private static int AdjustParentFooter(Container parent, CharacterPositionFinder finder, LineInfo position)
        {
            var characterPosition = finder.GetCharacterPosition(position);

            parent.FooterSpan = new CharacterSpan(characterPosition, parent.FooterSpan.End);

            return(characterPosition - 1);
        }
        private static int AdjustHeaderEnd(Container node, CharacterPositionFinder finder, LineInfo position)
        {
            var characterPosition = finder.GetCharacterPosition(position);

            node.HeaderSpan = new CharacterSpan(node.HeaderSpan.Start, characterPosition);

            return(characterPosition + 1);
        }
        private static void AdjustNode(Container parent, IList <ContainerOrTerminalNode> parentChildren, int indexInParentChildren, CharacterPositionFinder finder)
        {
            var newStartPos = AdjustBegin(parent, parentChildren, indexInParentChildren, finder);
            var newEndPos   = AdjustEnd(parent, parentChildren, indexInParentChildren, finder);

            // somewhere in the middle, so adjust only node span and location, as well as that from the siblings
            var newStartLine = finder.GetLineInfo(newStartPos);
            var newEndLine   = finder.GetLineInfo(newEndPos);

            var node = parentChildren[indexInParentChildren];

            node.LocationSpan = new LocationSpan(newStartLine, newEndLine);

            // now adjust terminal node's start position
            if (node is Container c)
            {
                // only adjust child nodes that are no attributes
                var children = c.Children.Where(IsNoAttribute).ToList();
                if (children.Any())
                {
                    c.HeaderSpan = new CharacterSpan(newStartPos, c.HeaderSpan.End);

                    for (var index = 0; index < children.Count; index++)
                    {
                        AdjustNode(c, children, index, finder);
                    }

                    c.FooterSpan = new CharacterSpan(c.FooterSpan.Start, newEndPos);
                }
                else
                {
                    var headerEndLine   = finder.GetLineInfo(c.HeaderSpan.End).LineNumber;
                    var footerStartLine = finder.GetLineInfo(c.FooterSpan.Start).LineNumber;

                    if (headerEndLine != footerStartLine)
                    {
                        var endPos       = finder.GetLineLength(headerEndLine);
                        var headerEndPos = finder.GetCharacterPosition(headerEndLine, endPos);

                        c.HeaderSpan = new CharacterSpan(newStartPos, headerEndPos);
                        c.FooterSpan = new CharacterSpan(headerEndPos + 1, newEndPos);
                    }
                    else
                    {
                        c.HeaderSpan = new CharacterSpan(newStartPos, c.FooterSpan.Start - 1);
                        c.FooterSpan = new CharacterSpan(c.FooterSpan.Start, newEndPos);
                    }
                }
            }
            else if (node is TerminalNode t)
            {
                t.Span = new CharacterSpan(newStartPos, newEndPos);
            }
        }
        private static void ParseAttribute(XmlTextReader reader, Container parent, CharacterPositionFinder finder, IXmlFlavor flavor)
        {
            var attributeStartPos = new LineInfo(reader.LineNumber, reader.LinePosition);

            var name = flavor.GetName(reader);
            var type = flavor.GetType(reader);

            // important call to be able to read the attribute value
            reader.ReadAttributeValue();

            var content = flavor.GetContent(reader);

            var attributeEndPos = new LineInfo(reader.LineNumber, reader.LinePosition + content.Length);

            var startPos = finder.GetCharacterPosition(attributeStartPos);
            var endPos   = finder.GetCharacterPosition(attributeEndPos);

            var locationSpan = new LocationSpan(attributeStartPos, attributeEndPos);
            var span         = new CharacterSpan(startPos, endPos);

            var child = AddTerminalNode(parent, type, name, content, locationSpan, span);

            flavor.FinalAdjustAfterParsingComplete(child);
        }
        private static int AdjustEnd(Container parent, IList <ContainerOrTerminalNode> parentChildren, int indexInParentChildren, CharacterPositionFinder finder)
        {
            var node = parentChildren[indexInParentChildren];

            int newEndPos;

            var last = node == parentChildren.Last();

            if (last)
            {
                // last child, so adjust parent's footer span and terminal node's end start and span end
                newEndPos = parent.FooterSpan.Start - 1;

                var parentFooterLocation = finder.GetLineInfo(parent.FooterSpan.Start);
                if (parentFooterLocation.LineNumber != node.LocationSpan.End.LineNumber)
                {
                    var startPosition = new LineInfo(parentFooterLocation.LineNumber, 1);
                    newEndPos = AdjustParentFooter(parent, finder, startPosition);
                }
            }
            else
            {
                var siblingAfter = parentChildren.ElementAt(indexInParentChildren + 1);
                newEndPos = siblingAfter.GetTotalSpan().Start - 1;

                var startLine = siblingAfter.LocationSpan.Start.LineNumber;
                if (startLine != node.LocationSpan.End.LineNumber)
                {
                    var lineLength = finder.GetLineLength(node.LocationSpan.End);
                    var lineInfo   = new LineInfo(node.LocationSpan.End.LineNumber, lineLength);
                    newEndPos = finder.GetCharacterPosition(lineInfo);
                }
            }

            return(newEndPos);
        }
예제 #8
0
 public int GetCharacterPosition(int lineNumber, int linePosition) => _objectUnderTest.GetCharacterPosition(new LineInfo(lineNumber, linePosition));