示例#1
0
        /// <summary>
        ///     Determine whether the element lies after the specified position.
        /// </summary>
        /// <param name="element">
        ///     The element.
        /// </param>
        /// <param name="position">
        ///     The target position.
        /// </param>
        /// <param name="xmlPositions">
        ///     The XML position lookup.
        /// </param>
        /// <returns>
        ///     <c>true</c>, if the element's opening tag ("&lt;") lies after the specified position; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsAfter(this XmlElementSyntaxBase element, Position position, TextPositions xmlPositions)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

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

            Range startTokenRange;

            if (element is XmlEmptyElementSyntax emptyElement)
            {
                startTokenRange = emptyElement.LessThanToken.Span.ToNative(xmlPositions);
            }
            else if (element is XmlElementSyntax elementWithContent)
            {
                startTokenRange = elementWithContent.StartTag.LessThanToken.Span.ToNative(xmlPositions);
            }
            else
            {
                throw new ArgumentException($"Unexpected element kind '{element.Kind}'.", nameof(element));
            }

            return(position <= startTokenRange); // We're still before the element when the element "at" the position is the opening tag.
        }
示例#2
0
        /// <summary>
        ///     Determine whether the element lies before the specified position.
        /// </summary>
        /// <param name="element">
        ///     The element.
        /// </param>
        /// <param name="position">
        ///     The target position.
        /// </param>
        /// <param name="xmlPositions">
        ///     The XML position lookup.
        /// </param>
        /// <returns>
        ///     <c>true</c>, if the element's final closing tag ("/&gt;" or "&gt;") lies after the specified position; otherwise, <c>false</c>.
        /// </returns>
        public static bool IsAfterPosition(this XmlElementSyntaxBase element, Position position, TextPositions xmlPositions)
        {
            if (element == null)
            {
                throw new ArgumentNullException(nameof(element));
            }

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

            Range endTokenRange;

            if (element is XmlEmptyElementSyntax emptyElement)
            {
                endTokenRange = emptyElement.SlashGreaterThanToken.Span.ToNative(xmlPositions);
            }
            else if (element is XmlElementSyntax elementWithContent)
            {
                endTokenRange = elementWithContent.EndTag.GreaterThanToken.Span.ToNative(xmlPositions);
            }
            else
            {
                throw new ArgumentException($"Unexpected element kind '{element.Kind}'.", nameof(element));
            }

            return(position >= endTokenRange);
        }
示例#3
0
        /// <summary>
        ///     Create a new <see cref="XSInvalidElement"/>.
        /// </summary>
        /// <param name="element">
        ///     The <see cref="XmlElementSyntaxBase"/> represented by the <see cref="XSInvalidElement"/>.
        /// </param>
        /// <param name="range">
        ///     The <see cref="Range"/>, within the source text, spanned by the element.
        /// </param>
        /// <param name="nameRange">
        ///     The range, within the source text, spanned by the element's name.
        /// </param>
        /// <param name="attributesRange">
        ///     The range, within the source text, spanned by the element's attributes.
        /// </param>
        /// <param name="parent">
        ///     The <see cref="XSInvalidElement"/>'s parent element (if any).
        /// </param>
        /// <param name="hasContent">
        ///     Does the <see cref="XSInvalidElement"/> have any content (besides attributes)?
        /// </param>
        public XSInvalidElement(XmlElementSyntaxBase element, Range range, Range nameRange, Range attributesRange, XSElement parent, bool hasContent)
            : base(element, range, nameRange, attributesRange, parent)
        {
            if (parent == null)
            {
                System.Diagnostics.Debugger.Break();
            }

            HasContent = hasContent;
        }
示例#4
0
            /// <summary>
            ///     Visit an <see cref="XmlDocumentSyntax"/>.
            /// </summary>
            /// <param name="document">
            ///     The <see cref="XmlDocumentSyntax"/>.
            /// </param>
            /// <returns>
            ///     The <see cref="XmlDocumentSyntax"/> (unchanged).
            /// </returns>
            public override SyntaxNode VisitXmlDocument(XmlDocumentSyntax document)
            {
                XmlElementSyntaxBase root = document.Root as XmlElementSyntaxBase;

                if (root == null)
                {
                    return(document);
                }

                if (root is XmlElementSyntax rootElement && rootElement.StartTag == null)
                {
                    root = rootElement.Elements.FirstOrDefault() as XmlElementSyntaxBase;
                }

                if (root != null)
                {
                    Visit(root);
                }

                return(document);
            }
        /// <summary>
        ///     Determine <see cref="XmlLocationFlags"/> for the current position.
        /// </summary>
        /// <returns>
        ///     <see cref="XmlLocationFlags"/> describing the position.
        /// </returns>
        XmlLocationFlags ComputeLocationFlags(XSNode node, int absolutePosition)
        {
            if (node == null)
            {
                throw new ArgumentNullException(nameof(node));
            }

            XmlLocationFlags flags = XmlLocationFlags.None;

            if (!node.IsValid)
            {
                flags |= XmlLocationFlags.Invalid;
            }

            switch (node)
            {
            case XSEmptyElement element:
            {
                flags |= XmlLocationFlags.Element | XmlLocationFlags.Empty;

                XmlEmptyElementSyntax syntaxNode = element.ElementNode;

                TextSpan nameSpan = syntaxNode.NameNode?.Span ?? new TextSpan();
                if (nameSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Name;
                }

                TextSpan attributesSpan = new TextSpan();
                if (syntaxNode.SlashGreaterThanToken != null)     // This is the most accurate way to measure the span of text where the element's attributes can be located.
                {
                    attributesSpan = new TextSpan(start: syntaxNode.NameNode.Span.End, length: syntaxNode.SlashGreaterThanToken.Span.Start - syntaxNode.NameNode.Span.End);
                }
                else if (syntaxNode.AttributesNode != null)
                {
                    attributesSpan = syntaxNode.AttributesNode.FullSpan;     // We don't rely on the span of the syntaxNode.AttributesNode unless we have to, because it's often less accurate than the measurement above.
                }
                if (attributesSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Attributes;
                }

                break;
            }

            case XSElementWithContent elementWithContent:
            {
                flags |= XmlLocationFlags.Element;

                XmlElementSyntax syntaxNode = elementWithContent.ElementNode;

                TextSpan nameSpan = syntaxNode.NameNode?.Span ?? new TextSpan();
                if (nameSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Name;
                }

                TextSpan startTagSpan = syntaxNode.StartTag?.Span ?? new TextSpan();
                if (startTagSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.OpeningTag;
                }

                TextSpan attributesSpan = new TextSpan();
                if (syntaxNode.StartTag?.GreaterThanToken != null)     // This is the most accurate way to measure the span of text where the element's attributes can be located.
                {
                    attributesSpan = new TextSpan(start: syntaxNode.NameNode.Span.End, length: syntaxNode.StartTag.GreaterThanToken.Span.Start - syntaxNode.NameNode.Span.End);
                }
                else if (syntaxNode.AttributesNode != null)
                {
                    attributesSpan = syntaxNode.AttributesNode.FullSpan;                                 // We don't rely on the span of the syntaxNode.AttributesNode unless we have to, because it's often less accurate than the measurement above.
                }
                if (attributesSpan.Contains(absolutePosition) || absolutePosition == attributesSpan.End) // In this particular case, we need an inclusive comparison.
                {
                    flags |= XmlLocationFlags.Attributes;
                }

                TextSpan endTagSpan = syntaxNode.EndTag?.Span ?? new TextSpan();
                if (endTagSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.ClosingTag;
                }

                if (absolutePosition >= startTagSpan.End && absolutePosition <= endTagSpan.Start)
                {
                    flags |= XmlLocationFlags.Value;
                }

                break;
            }

            case XSInvalidElement invalidElement:
            {
                flags |= XmlLocationFlags.Element;

                XmlElementSyntaxBase syntaxNode = invalidElement.ElementNode;

                TextSpan nameSpan = syntaxNode.NameNode?.Span ?? new TextSpan();
                if (nameSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Name;
                }

                TextSpan attributesSpan = syntaxNode.AttributesNode?.FullSpan ?? new TextSpan();
                if (attributesSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Attributes;
                }

                break;
            }

            case XSAttribute attribute:
            {
                flags |= XmlLocationFlags.Attribute;

                XmlAttributeSyntax syntaxNode = attribute.AttributeNode;

                TextSpan nameSpan = syntaxNode.NameNode?.Span ?? new TextSpan();
                if (nameSpan.Contains(absolutePosition))
                {
                    flags |= XmlLocationFlags.Name;
                }

                TextSpan valueSpan = syntaxNode.ValueNode?.Span ?? new TextSpan();
                if (absolutePosition >= valueSpan.Start + 1 && absolutePosition <= valueSpan.End - 1)
                {
                    flags |= XmlLocationFlags.Value;
                }

                break;
            }

            case XSElementText text:
            {
                flags |= XmlLocationFlags.Text | XmlLocationFlags.Element | XmlLocationFlags.Value;

                break;
            }

            case XSWhitespace whitespace:
            {
                flags |= XmlLocationFlags.Whitespace | XmlLocationFlags.Element | XmlLocationFlags.Value;

                break;
            }
            }

            return(flags);
        }