private void ClassifyXmlAttribute(XmlAttributeSyntax attribute)
        {
            ClassifyXmlName(attribute.Name);
            AddXmlClassification(
                attribute.EqualsToken,
                ClassificationTypeNames.XmlDocCommentDelimiter
                );
            AddXmlClassification(
                attribute.StartQuoteToken,
                ClassificationTypeNames.XmlDocCommentAttributeQuotes
                );

            switch (attribute.Kind())
            {
            case SyntaxKind.XmlTextAttribute:
                ClassifyXmlTextTokens(((XmlTextAttributeSyntax)attribute).TextTokens);
                break;

            case SyntaxKind.XmlCrefAttribute:
                ClassifyNode(((XmlCrefAttributeSyntax)attribute).Cref);
                break;

            case SyntaxKind.XmlNameAttribute:
                ClassifyNode(((XmlNameAttributeSyntax)attribute).Identifier);
                break;
            }

            AddXmlClassification(
                attribute.EndQuoteToken,
                ClassificationTypeNames.XmlDocCommentAttributeQuotes
                );
        }
Example #2
0
        private bool IsAttributeValueContext(SyntaxToken token, out string tagName, out string attributeName)
        {
            XmlAttributeSyntax attributeSyntax = null;

            if (token.Parent.IsKind(SyntaxKind.IdentifierName) &&
                token.Parent.IsParentKind(SyntaxKind.XmlNameAttribute, out XmlNameAttributeSyntax xmlName))
            {
                // Handle the special 'name' attributes: name="bar$$
                attributeSyntax = xmlName;
            }
            else if (token.IsKind(SyntaxKind.XmlTextLiteralToken) &&
                     token.Parent.IsKind(SyntaxKind.XmlTextAttribute, out XmlTextAttributeSyntax xmlText))
            {
                // Handle the other general text attributes: foo="bar$$
                attributeSyntax = xmlText;
            }
            else if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute, out attributeSyntax) ||
                     token.Parent.IsKind(SyntaxKind.XmlTextAttribute, out attributeSyntax))
            {
                // When there's no attribute value yet, the parent attribute is returned:
                //     name="$$
                //     foo="$$
                if (token != attributeSyntax.StartQuoteToken)
                {
                    attributeSyntax = null;
                }
            }

            if (attributeSyntax != null)
            {
                attributeName = attributeSyntax.Name.LocalName.ValueText;

                var emptyElement = attributeSyntax.GetAncestor <XmlEmptyElementSyntax>();
                if (emptyElement != null)
                {
                    // Empty element tags: <tag attr=... />
                    tagName = emptyElement.Name.LocalName.Text;
                    return(true);
                }

                var startTagSyntax = token.GetAncestor <XmlElementStartTagSyntax>();
                if (startTagSyntax != null)
                {
                    // Non-empty element start tags: <tag attr=... >
                    tagName = startTagSyntax.Name.LocalName.Text;
                    return(true);
                }
            }

            attributeName = null;
            tagName       = null;
            return(false);
        }
        public static void AddAttributeValueReferences(
            this BoundSourceFileBuilder binder,
            XmlAttributeSyntax attribute,
            params ReferenceSymbol[] references)
        {
            var node = attribute?.ValueNode.As <XmlStringSyntax>()?.TextTokens.Node;

            if (node != null)
            {
                binder.AnnotateReferences(node.Start, node.FullWidth, references);
            }
        }
        public static void AddAttributeNameReferences(
            this BoundSourceFileBuilder binder,
            XmlAttributeSyntax attribute,
            params ReferenceSymbol[] references)
        {
            var node = attribute?.NameNode;

            if (node != null)
            {
                binder.AnnotateReferences(node.Start, node.FullWidth, references);
            }
        }
        public static void AddAttributeValueDefinition(
            this BoundSourceFileBuilder binder,
            XmlAttributeSyntax attribute,
            DefinitionSymbol definition)
        {
            var node = attribute?.ValueNode.As <XmlStringSyntax>()?.TextTokens.Node;

            if (node != null)
            {
                binder.AnnotateDefinition(node.Start, node.FullWidth, definition);
            }
        }
 public static DocumentationCommentAttribute FromXmlAttributeSyntax(XmlAttributeSyntax syntax)
 {
     if (syntax is XmlCrefAttributeSyntax)
     {
         return(FromXmlCref(syntax));
     }
     if (syntax is XmlNameAttributeSyntax)
     {
         return(FromXmlName(syntax));
     }
     return(FromXmlText(syntax as XmlTextAttributeSyntax));
 }
Example #7
0
        public static IEnumerable <ReferenceSpan> GetAttributeValueExpressionSpans(this XmlAttributeSyntax element,
                                                                                   ExpressionProcessor customStringProcessor = null,
                                                                                   string referencingItemName = null)
        {
            var valueNode = element?.ValueNode.As <XmlStringSyntax>()?.TextTokens.Node;

            if (valueNode == null)
            {
                return(Enumerable.Empty <ReferenceSpan>());
            }

            return(ProcessExpressions(valueNode.Start, valueNode.ToFullString(), customStringProcessor, referencingItemName));
        }
 private static DocumentationCommentAttribute FromXmlName(XmlAttributeSyntax syntax)
 => new DocumentationCommentAttribute
 {
     Identifier = new Identifier {
         Name = new AsciiStringReference {
             Value = "name"
         }
     },
     Value = new Identifier {
         Name = new AsciiStringReference {
             Value = (syntax as XmlNameAttributeSyntax).Identifier.ToString()
         }
     }
 };
Example #9
0
        private string GetAttributeValue(XmlAttributeSyntax attribute)
        {
            switch (attribute)
            {
            case XmlTextAttributeSyntax textAttribute:
                // Decode any XML enities and concatentate the results
                return(textAttribute.TextTokens.GetValueText());

            case XmlNameAttributeSyntax nameAttribute:
                return(nameAttribute.Identifier.Identifier.ValueText);

            default:
                return(null);
            }
        }
Example #10
0
        /// <summary>
        /// This is used to determine whether or not the current caret location is in an attribute value context
        /// </summary>
        /// <param name="token">The token to check</param>
        /// <param name="elementName">On return, this will contain the element name if it is an attribute value
        /// context, null if not.</param>
        /// <param name="attributeName">On return, this will contain the attribute name if it is an attribute
        /// value context, null if not.</param>
        /// <returns>True if it is within the attribute value context, false if not.</returns>
        private static bool IsAttributeValueContext(SyntaxToken token, out string elementName, out string attributeName)
        {
            XmlAttributeSyntax attributeSyntax = null;

            if (token.IsKind(SyntaxKind.XmlTextLiteralToken) && token.Parent.IsKind(SyntaxKind.XmlTextAttribute))
            {
                // General attribute: attr="value|
                attributeSyntax = (XmlTextAttributeSyntax)token.Parent;
            }
            else
            if (token.Parent.IsKind(SyntaxKind.XmlNameAttribute) || token.Parent.IsKind(SyntaxKind.XmlTextAttribute))
            {
                // Return the parent attribute if there is no value yet: attr="|
                attributeSyntax = (XmlAttributeSyntax)token.Parent;

                if (token != attributeSyntax.StartQuoteToken)
                {
                    attributeSyntax = null;
                }
            }

            if (attributeSyntax != null)
            {
                attributeName = attributeSyntax.Name.LocalName.ValueText;

                var emptyElement = attributeSyntax.GetAncestor <XmlEmptyElementSyntax>();

                if (emptyElement != null)
                {
                    // Self-closing or incomplete element: <elem attr="|" /> or <elem attr="|"
                    elementName = emptyElement.Name.LocalName.Text;
                    return(true);
                }

                var startTag = token.Parent?.FirstAncestorOrSelf <XmlElementStartTagSyntax>();

                if (startTag != null)
                {
                    // Start tag: <elem attr="|">
                    elementName = startTag.Name.LocalName.Text;
                    return(true);
                }
            }

            attributeName = elementName = null;
            return(false);
        }
Example #11
0
        /// <summary>
        ///     Get a <see cref="Range"/> representing the attribute's span (without quotes) in the XML.
        /// </summary>
        /// <param name="attribute">
        ///     The attribute.
        /// </param>
        /// <param name="xmlPositions">
        ///     The XML position lookup.
        /// </param>
        /// <returns>
        ///     The <see cref="Range"/>.
        /// </returns>
        public static Range GetValueRange(this XmlAttributeSyntax attribute, TextPositions xmlPositions)
        {
            if (attribute == null)
            {
                throw new ArgumentNullException(nameof(attribute));
            }

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

            Range valueRange = attribute.ValueNode.Span.ToNative(xmlPositions);

            // Trim off leading and trailing quotes.
            return(valueRange.Transform(moveStartColumns: 1, moveEndColumns: -1));
        }
Example #12
0
        private void FormatTagAttribute(XmlAttributeSyntax node)
        {
            FormatTagName(node.Name);

            EnqueueTrailingTriviaChange(node.Name, string.Empty);

            EnqueueLeadingTriviaChange(node.EqualsToken, string.Empty);

            AddWord(node.EqualsToken.Span);

            EnqueueTrailingTriviaChange(node.EqualsToken, string.Empty);

            EnqueueLeadingTriviaChange(node.StartQuoteToken, string.Empty);

            AddWord(node.StartQuoteToken.Span);

            switch (node.Kind())
            {
            case SyntaxKind.XmlCrefAttribute:
                FormatTagCrefAttribute((XmlCrefAttributeSyntax)node);
                break;

            case SyntaxKind.XmlNameAttribute:
                FormatTagNameAttribute((XmlNameAttributeSyntax)node);
                break;

            case SyntaxKind.XmlTextAttribute:
                FormatTagTextAttribute((XmlTextAttributeSyntax)node);
                break;

            default:
                FormatTagUnknownAttribute(node);
                break;
            }

            AddWord(node.EndQuoteToken.Span);
        }
Example #13
0
            /// <summary>
            ///     Visit an <see cref="XmlAttributeSyntax"/>.
            /// </summary>
            /// <param name="attribute">
            ///     The <see cref="XmlAttributeSyntax"/>.
            /// </param>
            /// <returns>
            ///     The <see cref="XmlAttributeSyntax"/> (unchanged).
            /// </returns>
            public override SyntaxNode VisitXmlAttribute(XmlAttributeSyntax attribute)
            {
                if (!HaveCurrentElement)
                {
                    return(attribute);
                }

                Range attributeRange = attribute.Span.ToNative(_textPositions);
                Range nameRange      = attribute.NameNode?.Span.ToNative(_textPositions) ?? attributeRange;
                Range valueRange     = attribute.ValueNode?.Span.ToNative(_textPositions) ?? Range.Zero;

                if (valueRange != Range.Zero && valueRange.End.ColumnNumber - valueRange.Start.ColumnNumber >= 2)
                {
                    valueRange = valueRange.Transform(moveStartColumns: 1, moveEndColumns: -1); // Trim off quotes.
                }
                else
                {
                    valueRange = nameRange;
                }

                XSAttribute xsAttribute;

                if (String.IsNullOrWhiteSpace(attribute.Name) || nameRange == attributeRange || valueRange == attributeRange)
                {
                    xsAttribute = new XSInvalidAttribute(attribute, CurrentElement, attributeRange, nameRange, valueRange);
                }
                else
                {
                    xsAttribute = new XSAttribute(attribute, CurrentElement, attributeRange, nameRange, valueRange);
                }

                CurrentElement.Attributes = CurrentElement.Attributes.Add(xsAttribute);
                DiscoveredNodes.Add(xsAttribute);

                return(attribute);
            }
Example #14
0
 internal static string GetName(this XmlAttributeSyntax value) => value?.Name.LocalName.ValueText;
        private void ClassifyXmlAttribute(XmlAttributeSyntax attribute)
        {
            ClassifyXmlName(attribute.Name);
            AddXmlClassification(attribute.EqualsToken, ClassificationTypeNames.XmlDocCommentDelimiter);
            AddXmlClassification(attribute.StartQuoteToken, ClassificationTypeNames.XmlDocCommentAttributeQuotes);

            switch (attribute.Kind())
            {
                case SyntaxKind.XmlTextAttribute:
                    ClassifyXmlTextTokens(((XmlTextAttributeSyntax)attribute).TextTokens);
                    break;
                case SyntaxKind.XmlCrefAttribute:
                    ClassifyNode(((XmlCrefAttributeSyntax)attribute).Cref);
                    break;
                case SyntaxKind.XmlNameAttribute:
                    ClassifyNode(((XmlNameAttributeSyntax)attribute).Identifier);
                    break;
            }

            AddXmlClassification(attribute.EndQuoteToken, ClassificationTypeNames.XmlDocCommentAttributeQuotes);
        }
Example #16
0
        private void FormatTagUnknownAttribute(XmlAttributeSyntax node)
        {
            Debug.Assert(false);

            AddWord(TextSpan.FromBounds(node.StartQuoteToken.Span.End, node.EndQuoteToken.Span.Start));
        }
        /// <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);
        }
 public TameXmlAttributeSyntax(XmlAttributeSyntax node)
 {
     Node = node;
     AddChildren();
 }
Example #19
0
 private string GetAttributeName(XmlAttributeSyntax attribute) => attribute.Name.LocalName.ValueText;
Example #20
0
 internal static bool IsInXmlAttributeValue(int position, XmlAttributeSyntax attribute)
 {
     return IsBetweenTokens(position, attribute.StartQuoteToken, attribute.EndQuoteToken);
 }
Example #21
0
 internal static bool IsInXmlAttributeValue(int position, XmlAttributeSyntax attribute)
 {
     return(IsBetweenTokens(position, attribute.StartQuoteToken, attribute.EndQuoteToken));
 }
Example #22
0
 /// <summary>
 ///     Create a new <see cref="XSInvalidAttribute"/>.
 /// </summary>
 /// <param name="attribute">
 ///     The <see cref="XmlAttributeSyntax"/> represented by the <see cref="XSInvalidAttribute"/>.
 /// </param>
 /// <param name="element">
 ///     The element that contains the attribute.
 /// </param>
 /// <param name="range">
 ///     The <see cref="Range"/>, within the source text, spanned by the attribute.
 /// </param>
 /// <param name="nameRange">
 ///     The <see cref="Range"/>, within the source text, spanned by the attribute's name.
 /// </param>
 /// <param name="valueRange">
 ///     The <see cref="Range"/>, within the source text, spanned by the attribute's value.
 /// </param>
 public XSInvalidAttribute(XmlAttributeSyntax attribute, XSElement element, Range range, Range nameRange, Range valueRange)
     : base(attribute, element, range, nameRange, valueRange)
 {
 }