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); }
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); }
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); }
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 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))); } }
// 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; } }
public void PushState(FormatterState value) { m_stateStack.Push(value); }
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 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); }