private static void AppendTextFromNode(FormatterState state, XNode node, Compilation compilation)
        {
            if (node.NodeType == XmlNodeType.Text)
            {
                AppendTextFromTextNode(state, (XText)node);
            }

            if (node.NodeType != XmlNodeType.Element)
            {
                return;
            }

            var element = (XElement)node;

            var name = element.Name.LocalName;

            if (name == DocumentationCommentXmlNames.SeeElementName ||
                name == DocumentationCommentXmlNames.SeeAlsoElementName)
            {
                if (element.IsEmpty || element.FirstNode == null)
                {
                    foreach (var attribute in element.Attributes())
                    {
                        AppendTextFromAttribute(state, element, attribute, attributeNameToParse: DocumentationCommentXmlNames.CrefAttributeName, SymbolDisplayPartKind.Text);
                    }

                    return;
                }
            }
            else if (name == DocumentationCommentXmlNames.ParameterReferenceElementName ||
                     name == DocumentationCommentXmlNames.TypeParameterReferenceElementName)
            {
                var kind = name == DocumentationCommentXmlNames.ParameterReferenceElementName ? SymbolDisplayPartKind.ParameterName : SymbolDisplayPartKind.TypeParameterName;
                foreach (var attribute in element.Attributes())
                {
                    AppendTextFromAttribute(state, element, attribute, attributeNameToParse: DocumentationCommentXmlNames.NameAttributeName, kind);
                }

                return;
            }

            if (name == DocumentationCommentXmlNames.ParaElementName)
            {
                state.MarkBeginOrEndPara();
            }
            else if (name == "br")
            {
                state.MarkLineBreak();
            }

            foreach (var childNode in element.Nodes())
            {
                AppendTextFromNode(state, childNode, compilation);
            }

            if (name == DocumentationCommentXmlNames.ParaElementName)
            {
                state.MarkBeginOrEndPara();
            }
        }
 public override bool ShouldNestState(FormatterState other)
 {
     SimpleBlockFormatterState blockFormatterState = (SimpleBlockFormatterState)other;
     return (blockFormatterState.m_tag != m_tag ||
             blockFormatterState.m_alignNfo != m_alignNfo ||
             blockFormatterState.m_attNfo != m_attNfo);
 }
Example #3
0
        public override bool ShouldNestState(FormatterState other)
        {
            var blockFormatterState = (SimpleBlockFormatterState)other;

            return(blockFormatterState.Tag != Tag ||
                   blockFormatterState.AlignInfo != AlignInfo ||
                   blockFormatterState.AttInfo != AttInfo);
        }
        public override bool ShouldNestState(FormatterState other)
        {
            SimpleBlockFormatterState blockFormatterState = (SimpleBlockFormatterState)other;

            return(blockFormatterState.m_tag != m_tag ||
                   blockFormatterState.m_alignNfo != m_alignNfo ||
                   blockFormatterState.m_attNfo != m_attNfo);
        }
Example #5
0
        private static void AppendTextFromAttribute(FormatterState state, XElement element, string attributeName)
        {
            var attribute = element.Attribute(attributeName);

            if (attribute == null)
            {
                return;
            }

            state.AppendParts(CrefToSymbolDisplayParts(attribute.Value, state.Position, state.SemanticModel, state.Format));
        }
        private static void AppendTextFromTextNode(FormatterState state, XText element)
        {
            var rawText = element.Value;
            var builder = new StringBuilder(rawText.Length);

            // Normalize the whitespace.
            var pendingWhitespace   = false;
            var hadAnyNonWhitespace = false;

            for (int i = 0; i < rawText.Length; i++)
            {
                if (char.IsWhiteSpace(rawText[i]))
                {
                    // Whitespace. If it occurs at the beginning of the text we don't append it
                    // at all; otherwise, we reduce it to a single space.
                    if (!state.AtBeginning || hadAnyNonWhitespace)
                    {
                        pendingWhitespace = true;
                    }
                }
                else
                {
                    // Some other character...
                    if (pendingWhitespace)
                    {
                        if (builder.Length == 0)
                        {
                            state.AppendSingleSpace();
                        }
                        else
                        {
                            builder.Append(' ');
                        }

                        pendingWhitespace = false;
                    }

                    builder.Append(rawText[i]);
                    hadAnyNonWhitespace = true;
                }
            }

            if (builder.Length > 0)
            {
                state.AppendString(builder.ToString());
            }

            if (pendingWhitespace)
            {
                state.AppendSingleSpace();
            }
        }
        private static void AppendTextFromNode(FormatterState state, XNode node, Compilation compilation)
        {
            if (node.NodeType == XmlNodeType.Text)
            {
                AppendTextFromTextNode(state, (XText)node);
            }

            if (node.NodeType != XmlNodeType.Element)
            {
                return;
            }

            var element = (XElement)node;

            var name = element.Name.LocalName;

            if (name == "see" ||
                name == "seealso")
            {
                foreach (var attribute in element.Attributes())
                {
                    AppendTextFromAttribute(state, element, attribute, attributeNameToParse: "cref");
                }

                return;
            }
            else if (name == "paramref" ||
                     name == "typeparamref")
            {
                foreach (var attribute in element.Attributes())
                {
                    AppendTextFromAttribute(state, element, attribute, attributeNameToParse: "name");
                }

                return;
            }

            if (name == "para")
            {
                state.MarkBeginOrEndPara();
            }

            foreach (var childNode in element.Nodes())
            {
                AppendTextFromNode(state, childNode, compilation);
            }

            if (name == "para")
            {
                state.MarkBeginOrEndPara();
            }
        }
        private static void AppendTextFromAttribute(FormatterState state, XElement element, XAttribute attribute, string attributeNameToParse)
        {
            var attributeName = attribute.Name.LocalName;

            if (attributeNameToParse == attributeName)
            {
                state.AppendParts(CrefToSymbolDisplayParts(attribute.Value, state.Position, state.SemanticModel, state.Format));
            }
            else
            {
                var displayKind = attributeName == "langword"
                    ? SymbolDisplayPartKind.Keyword
                    : SymbolDisplayPartKind.Text;
                state.AppendParts(SpecializedCollections.SingletonEnumerable(new SymbolDisplayPart(kind: displayKind, symbol: null, text: attribute.Value)));
            }
        }
        private static void AppendTextFromAttribute(FormatterState state, XElement element, XAttribute attribute, string attributeNameToParse, SymbolDisplayPartKind kind)
        {
            var attributeName = attribute.Name.LocalName;

            if (attributeNameToParse == attributeName)
            {
                state.AppendParts(
                    CrefToSymbolDisplayParts(attribute.Value, state.Position, state.SemanticModel, state.Format, kind).ToTaggedText());
            }
            else
            {
                var displayKind = attributeName == DocumentationCommentXmlNames.LangwordAttributeName
                    ? TextTags.Keyword
                    : TextTags.Text;
                state.AppendParts(SpecializedCollections.SingletonEnumerable(new TaggedText(displayKind, attribute.Value)));
            }
        }
        private static void AppendTextFromTagWithNameAttribute(FormatterState state, XElement element, Compilation compilation)
        {
            var nameAttribute = element.Attribute("name");

            if (nameAttribute == null)
            {
                return;
            }

            if (compilation != null && state.TryAppendSymbol(DocumentationCommentId.GetFirstSymbolForDeclarationId(nameAttribute.Value, compilation)))
            {
                return;
            }
            else
            {
                state.AppendString(TrimCrefPrefix(nameAttribute.Value));
            }
        }
        public string Format(string rawXmlText, Compilation compilation = null)
        {
            if (rawXmlText == null)
            {
                return(null);
            }

            var state = new FormatterState();

            // In case the XML is a fragment (that is, a series of elements without a parent)
            // wrap it up in a single tag. This makes parsing it much, much easier.
            var inputString = "<tag>" + rawXmlText + "</tag>";

            var summaryElement = XElement.Parse(inputString, LoadOptions.PreserveWhitespace);

            AppendTextFromNode(state, summaryElement, compilation);

            return(state.GetText());
        }
        private static void AppendTextFromSeeTag(FormatterState state, XElement element, Compilation compilation)
        {
            var crefAttribute = element.Attribute("cref");

            if (crefAttribute == null)
            {
                return;
            }

            var crefValue = crefAttribute.Value;

            if (compilation != null && state.TryAppendSymbol(DocumentationCommentId.GetFirstSymbolForDeclarationId(crefValue, compilation)))
            {
                return;
            }
            else
            {
                state.AppendString(TrimCrefPrefix(crefValue));
            }
        }
        public IEnumerable <SymbolDisplayPart> Format(string rawXmlText, SemanticModel semanticModel, int position, SymbolDisplayFormat format = null)
        {
            if (rawXmlText == null)
            {
                return(null);
            }

            var state = new FormatterState()
            {
                SemanticModel = semanticModel, Position = position, Format = format
            };

            // In case the XML is a fragment (that is, a series of elements without a parent)
            // wrap it up in a single tag. This makes parsing it much, much easier.
            var inputString = "<tag>" + rawXmlText + "</tag>";

            var summaryElement = XElement.Parse(inputString, LoadOptions.PreserveWhitespace);

            AppendTextFromNode(state, summaryElement, state.SemanticModel.Compilation);

            return(state.Builder);
        }
        private static void AppendTextFromAttribute(FormatterState state, XElement element, string attributeName)
        {
            var attribute = element.Attribute(attributeName);
            if (attribute == null)
            {
                return;
            }

            state.AppendParts(CrefToSymbolDisplayParts(attribute.Value, state.Position, state.SemanticModel, state.Format));
        }
 public override bool ShouldNestState(FormatterState other)
 {
     return(false);
 }
 public override bool ShouldNestState(FormatterState other)
 {
     return false;
 }
        public string Format(string rawXmlText, Compilation compilation = null)
        {
            if (rawXmlText == null)
            {
                return null;
            }

            var state = new FormatterState();

            // In case the XML is a fragment (that is, a series of elements without a parent)
            // wrap it up in a single tag. This makes parsing it much, much easier.
            var inputString = "<tag>" + rawXmlText + "</tag>";

            var summaryElement = XElement.Parse(inputString, LoadOptions.PreserveWhitespace);

            AppendTextFromNode(state, summaryElement, compilation);

            return state.GetText();
        }
        private static void AppendTextFromTextNode(FormatterState state, XText element)
        {
            var rawText = element.Value;
            var builder = new StringBuilder(rawText.Length);

            // Normalize the whitespace.
            var pendingWhitespace = false;
            var hadAnyNonWhitespace = false;
            for (int i = 0; i < rawText.Length; i++)
            {
                if (char.IsWhiteSpace(rawText[i]))
                {
                    // Whitespace. If it occurs at the beginning of the text we don't append it
                    // at all; otherwise, we reduce it to a single space.
                    if (!state.AtBeginning || hadAnyNonWhitespace)
                    {
                        pendingWhitespace = true;
                    }
                }
                else
                {
                    // Some other character...
                    if (pendingWhitespace)
                    {
                        if (builder.Length == 0)
                        {
                            state.AppendSingleSpace();
                        }
                        else
                        {
                            builder.Append(' ');
                        }

                        pendingWhitespace = false;
                    }

                    builder.Append(rawText[i]);
                    hadAnyNonWhitespace = true;
                }
            }

            if (builder.Length > 0)
            {
                state.AppendString(builder.ToString());
            }

            if (pendingWhitespace)
            {
                state.AppendSingleSpace();
            }
        }
 private static void AppendTextFromAttribute(FormatterState state, XElement element, XAttribute attribute, string attributeNameToParse)
 {
     var attributeName = attribute.Name.LocalName;
     if (attributeNameToParse == attributeName)
     {
         state.AppendParts(
             CrefToSymbolDisplayParts(attribute.Value, state.Position, state.SemanticModel, state.Format).ToTaggedText());
     }
     else
     {
         var displayKind = attributeName == "langword"
             ? TextTags.Keyword
             : TextTags.Text;
         state.AppendParts(SpecializedCollections.SingletonEnumerable(new TaggedText(displayKind, attribute.Value)));
     }
 }
        private static void AppendTextFromNode(FormatterState state, XNode node, Compilation compilation)
        {
            if (node.NodeType == XmlNodeType.Text)
            {
                AppendTextFromTextNode(state, (XText)node);
            }

            if (node.NodeType != XmlNodeType.Element)
            {
                return;
            }

            var element = (XElement)node;

            var name = element.Name.LocalName;

            if (name == "see" ||
                name == "seealso")
            {
                foreach (var attribute in element.Attributes())
                {
                    AppendTextFromAttribute(state, element, attribute, attributeNameToParse: "cref");
                }

                return;
            }
            else if (name == "paramref" ||
                     name == "typeparamref")
            {
                foreach (var attribute in element.Attributes())
                {
                    AppendTextFromAttribute(state, element, attribute, attributeNameToParse: "name");
                }

                return;
            }

            if (name == "para")
            {
                state.MarkBeginOrEndPara();
            }

            foreach (var childNode in element.Nodes())
            {
                AppendTextFromNode(state, childNode, compilation);
            }

            if (name == "para")
            {
                state.MarkBeginOrEndPara();
            }
        }
Example #21
0
            // This is where the real work is done - work out what colour to use based on the current state
            // and the string value being written. XmlTextWriter has an AutoComplete() function, so often
            // we may be writing a value that SHOULD have been written in the previous state. This makes it
            // necessary to check for "xmlns" for the previous element when writing the start of the next one,
            // for example.

            // There is one method for a char value and one for a string value. This improves performance
            // as it avoids unnecessary conversion from char to string.

            private void PrepareToWrite(char value)
            {
                FormatterState state = PeekState();

                switch (state)
                {
                case FormatterState.StartElement:
                    SetColour(value == '<' || value == '>' ? m_colourBlue : m_colourMaroon);
                    break;

                case FormatterState.EndElement:
                    SetColour(value == '<' || value == '>' || value == '/' ? m_colourBlue : m_colourMaroon);
                    break;

                case FormatterState.ElementBody:
                    SetColour(value == '>' ? m_colourBlue : m_colourBlack);
                    break;

                case FormatterState.StartAttribute:
                    if (value == ':')
                    {
                        Debug.Assert(m_attributeBuffer != null, "m_attributeBuffer != null");

                        // The buffer was a prefix - write it now.

                        SetColour(m_colourMaroon);
                        WriteEncoded(m_attributeBuffer);
                        m_attributeBuffer = null;
                        SetColour(m_colourPink);

                        // The attribute name should follow.

                        PopState();
                        PushState(FormatterState.AttributeName);
                    }
                    else if (value == '=')
                    {
                        // The buffer was a name - write it now.

                        SetColour(m_colourRed);
                        WriteEncoded(m_attributeBuffer);
                        m_attributeBuffer = null;

                        // The body should follow.

                        SetColour(m_colourBlue);
                        PopState();
                        PushState(FormatterState.AttributeBody);
                    }
                    else
                    {
                        Debug.Assert(value == ' ', "Unexpected character value in StartAttribute state: '"
                                     + value.ToString() + "'");
                    }
                    break;

                case FormatterState.AttributeName:
                    if (value == '=')
                    {
                        SetColour(m_colourBlue);
                        PopState();
                        PushState(FormatterState.AttributeBody);
                    }
                    else
                    {
                        SetColour(m_colourRed);
                    }
                    break;

                case FormatterState.AttributeBody:
                    SetColour(m_colourBlue);
                    if (value == '>')
                    {
                        PopState();
                    }
                    break;

                case FormatterState.EndAttribute:
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.Text:
                    SetColour(m_colourBlack);
                    break;

                case FormatterState.StartCDATA:
                    if (value == '>')
                    {
                        SetColour(m_colourBlue);                                 // The > ending the start of the element
                    }
                    else
                    {
                        Debug.Fail("Unexpected text in StartCDATA state: '" + value.ToString() + "'");
                    }
                    break;

                case FormatterState.CDATABody:
                    SetColour(m_colourBlack);
                    break;

                case FormatterState.Comment:
                    SetColour(m_colourGreen);
                    break;

                case FormatterState.StartInstruction:
                    // No character values for this state.
                    break;

                case FormatterState.InstructionName:
                    if (value == '=')
                    {
                        SetColour(m_colourBlue);
                        PushState(FormatterState.InstructionBody);
                    }
                    else
                    {
                        SetColour(m_colourRed);
                    }
                    break;

                case FormatterState.InstructionBody:
                    if (value == ' ')
                    {
                        PopState();
                    }
                    else
                    {
                        // This may actually be the end of the processing instruction, but the colour is blue
                        // either way.
                        SetColour(m_colourBlue);
                    }
                    break;

                case FormatterState.StartDocType:
                    SetColour(m_colourBlue);
                    PushState(FormatterState.DocTypeName);
                    break;

                case FormatterState.DocTypeName:
                    if (value == '>')
                    {
                        SetColour(m_colourBlue);
                    }
                    else if (value == '[')
                    {
                        SetColour(m_colourBlue);
                        PushState(FormatterState.DocTypeBody);
                    }
                    else if (value == '\"')
                    {
                        SetColour(m_colourBlue);
                        PushState(FormatterState.DocTypeReference);
                    }
                    else
                    {
                        SetColour(m_colourRed);
                    }
                    break;

                case FormatterState.DocTypeBody:
                    SetColour(value == ']' || value == '>' ? m_colourBlue : m_colourPink);
                    break;

                case FormatterState.DocTypeReference:
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.QualifiedName:
                    // Nothing to do for a qualified name - it should be part of an attribute or
                    // element value and will have the same formatting as any other value.
                    break;

                case FormatterState.None:
                    // This case occurs when the XML ends abruptly (ie. it's invalid), but we still
                    // to auto-complete the last element.
                    SetColour(value == '>' ? m_colourBlue : m_colourBlack);
                    break;

                default:
                    Debug.Fail("Unexpected formatter state: " + state.ToString());
                    break;
                }
            }
Example #22
0
 public void PushState(FormatterState value)
 {
     m_stateStack.Push(value);
 }
        private static void AppendTextFromSeeTag(FormatterState state, XElement element, Compilation compilation)
        {
            var crefAttribute = element.Attribute("cref");

            if (crefAttribute == null)
            {
                return;
            }

            var crefValue = crefAttribute.Value;

            if (compilation != null && state.TryAppendSymbol(DocumentationCommentId.GetFirstSymbolForDeclarationId(crefValue, compilation)))
            {
                return;
            }
            else
            {
                state.AppendString(TrimCrefPrefix(crefValue));
            }
        }
Example #24
0
 public override bool ShouldNestState(FormatterState other) => false;
        public sealed override bool ShouldNestState(FormatterState other)
        {
            ListFormatterState listState = (ListFormatterState)other;

            return(listState.NestingDepth > NestingDepth);
        }
 public sealed override bool ShouldNestState(FormatterState other)
 {
     ListFormatterState listState = (ListFormatterState)other;
     return (listState.NestingDepth > NestingDepth);
 }
        public IEnumerable<TaggedText> Format(string rawXmlText, SemanticModel semanticModel, int position, SymbolDisplayFormat format = null)
        {
            if (rawXmlText == null)
            {
                return null;
            }

            var state = new FormatterState() { SemanticModel = semanticModel, Position = position, Format = format };

            // In case the XML is a fragment (that is, a series of elements without a parent)
            // wrap it up in a single tag. This makes parsing it much, much easier.
            var inputString = "<tag>" + rawXmlText + "</tag>";

            var summaryElement = XElement.Parse(inputString, LoadOptions.PreserveWhitespace);

            AppendTextFromNode(state, summaryElement, state.SemanticModel.Compilation);

            return state.Builder;
        }
        private static void AppendTextFromTagWithNameAttribute(FormatterState state, XElement element, Compilation compilation)
        {
            var nameAttribute = element.Attribute("name");

            if (nameAttribute == null)
            {
                return;
            }

            if (compilation != null && state.TryAppendSymbol(DocumentationCommentId.GetFirstSymbolForDeclarationId(nameAttribute.Value, compilation)))
            {
                return;
            }
            else
            {
                state.AppendString(TrimCrefPrefix(nameAttribute.Value));
            }
        }
Example #29
0
            private bool PrepareToWrite(string value)
            {
                FormatterState state = PeekState();

                switch (state)
                {
                case FormatterState.StartElement:
                    if (value == " xmlns")
                    {
                        PushState(FormatterState.StartAttribute);
                        return(PrepareToWrite(value));
                    }
                    else
                    {
                        SetColour(m_colourMaroon);
                    }
                    break;

                case FormatterState.EndElement:
                    SetColour(value == " /" ? m_colourBlue : m_colourMaroon);
                    break;

                case FormatterState.ElementBody:
                    if (value == " xmlns")
                    {
                        PushState(FormatterState.StartAttribute);
                        return(PrepareToWrite(value));
                    }
                    else
                    {
                        SetColour(m_colourBlack);
                    }
                    break;

                case FormatterState.StartAttribute:
                    // We don't know at this stage whether this is the attribute prefix or the attribute
                    // name, so don't write it yet, just buffer it.

                    Debug.Assert(m_attributeBuffer == null, "m_attributeBuffer == null");
                    m_attributeBuffer = value;
                    return(false);

                case FormatterState.AttributeName:
                    SetColour(m_colourRed);
                    break;

                case FormatterState.AttributeBody:
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.EndAttribute:
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.Text:
                    SetColour(m_colourBlack);
                    break;

                case FormatterState.StartCDATA:
                    Debug.Assert(value == "<![CDATA[", "Unexpected text in StartCDATA state: '" + value + "'");
                    SetColour(m_colourPink);
                    PushState(FormatterState.CDATABody);
                    break;

                case FormatterState.CDATABody:
                    SetColour(value == "]]>" ? m_colourPink : m_colourBlack);
                    break;

                case FormatterState.Comment:
                    SetColour(value == "<!--" || value == "-->" ? m_colourBlue : m_colourGreen);
                    break;

                case FormatterState.StartInstruction:
                    if (value == "<?")
                    {
                        SetColour(m_colourBlue);
                    }
                    else if (value == "xml")
                    {
                        SetColour(m_colourMaroon);
                        PushState(FormatterState.InstructionName);
                    }
                    break;

                case FormatterState.InstructionName:
                    if (value == "?>")
                    {
                        SetColour(m_colourBlue);
                    }
                    else
                    {
                        WriteXmlInstructions(value);
                        return(false);
                    }
                    break;

                case FormatterState.InstructionBody:
                    // This may actually be the end of the processing instruction, but the colour is blue
                    // either way.
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.StartDocType:
                    SetColour(m_colourBlue);
                    PushState(FormatterState.DocTypeName);
                    break;

                case FormatterState.DocTypeName:
                    SetColour(m_colourRed);
                    break;

                case FormatterState.DocTypeBody:
                    SetColour(m_colourPink);
                    break;

                case FormatterState.DocTypeReference:
                    SetColour(m_colourBlue);
                    break;

                case FormatterState.QualifiedName:
                    // Nothing to do for a qualified name - it should be part of an attribute or
                    // element value and will have the same formatting as any other value.
                    break;

                default:
                    Debug.Fail("Unexpected formatter state: " + state.ToString());
                    break;
                }

                return(true);
            }