protected virtual int GetLineExpectedIndent(ITextSnapshotLine line, XmlBackgroundParser parser, int indentSize)
        {
            //create a lightweight tree parser, which will actually close nodes
            var spineParser = parser.GetSpineParser(line.Start);
            var startNodes  = spineParser.Spine.ToList();
            var startState  = spineParser.CurrentState;

            startNodes.Reverse();

            //advance the parser to the end of the line
            for (int i = line.Start.Position; i < line.End.Position; i++)
            {
                spineParser.Push(line.Snapshot[i]);
            }

            var endNodes = spineParser.Spine.ToList();

            endNodes.Reverse();

            //count the number of elements in the stack at the start of the line
            //which were not closed by the end of the line
            int depth = 0;

            //first node is the xdocument, skip it
            for (int i = 1; i < startNodes.Count; i++)
            {
                if (i == endNodes.Count || !(startNodes[i] is XElement) || startNodes[i] != endNodes[i])
                {
                    break;
                }
                depth++;
            }

            //if inside a tag state, indent a level further
            while (startState != null)
            {
                if (startState is XmlTagState)
                {
                    depth++;
                }
                startState = startState.Parent;
            }

            int indent = indentSize * depth;

            return(indent);
        }
예제 #2
0
        protected virtual int GetLineExpectedIndent(ITextSnapshotLine line, XmlBackgroundParser parser, int indentSize)
        {
            var snapshot = line.Snapshot;

            //create a lightweight tree parser, which will actually close nodes
            var spineParser = parser.GetSpineParser(line.Start);
            var startNodes  = spineParser.Spine.ToList();
            var startState  = spineParser.CurrentState;

            startNodes.Reverse();

            //advance the parser to the end of the line
            for (int i = line.Start.Position; i < line.End.Position; i++)
            {
                spineParser.Push(snapshot[i]);
            }

            var endNodes = spineParser.Spine.ToList();

            endNodes.Reverse();

            //count the number of elements in the stack at the start of the line
            //which were not closed by the end of the line
            int depth = 0;

            //special case if the line starts with something else than a closing tag,
            //treat it as content and don't take the remaining closing tags on the
            //current line into account
            bool startsWithClosingTag       = false;
            var  firstNonWhitespacePosition = line.GetFirstNonWhitespacePosition();

            if (firstNonWhitespacePosition is int first &&
                line.End > first + 1 &&
                snapshot[first] == '<' &&
                snapshot[first + 1] == '/')
            {
                startsWithClosingTag = true;
            }

            //first node is the xdocument, skip it
            for (int i = 1; i < startNodes.Count; i++)
            {
                if (!(startNodes[i] is XElement))
                {
                    continue;
                }

                if (startsWithClosingTag)
                {
                    if (i == endNodes.Count || startNodes[i] != endNodes[i])
                    {
                        break;
                    }
                }

                depth++;
            }

            //if inside a tag state, indent a level further
            while (startState != null)
            {
                if (startState is XmlTagState)
                {
                    depth++;
                }
                startState = startState.Parent;
            }

            int indent = indentSize * depth;

            return(indent);
        }