/* Function: Parse * * Attempts to parse the passed comment into <Topics>. Returns whether it was successful, and if so, adds them * to the list. These fields will be set: * * - CommentLineNumber * - Body, if present * - Summary, if available */ public bool Parse(PossibleDocumentationComment sourceComment, List <Topic> topics) { XMLIterator iterator = new XMLIterator(sourceComment.Start.FirstToken(Tokenization.LineBoundsMode.Everything), sourceComment.End.FirstToken(Tokenization.LineBoundsMode.Everything)); while (iterator.Type == XMLElementType.Indent || iterator.Type == XMLElementType.LineBreak) { iterator.Next(); } if (iterator.Type != XMLElementType.Tag) { return(false); } XMLComment xmlComment = new XMLComment(); while (iterator.IsInBounds) { if (TryToGetTopLevelTextBlock(ref iterator, xmlComment) || TryToGetTopLevelListItem(ref iterator, xmlComment)) { } else if (iterator.IsOnTag(TagForm.Opening)) { SkipBlock(ref iterator); } else { iterator.Next(); } } Topic topic = GenerateTopic(xmlComment); if (topic != null) { topic.CommentLineNumber = sourceComment.Start.LineNumber; topics.Add(topic); } return(true); }
/* Function: TryToGetTopLevelTextBlock * If the iterator is on a summary, remark, returns, or top-level example tag it will convert it to NDMarkup, add it to the comment * in a text block, move the iterator past it, and return true. Otherwise it returns false and nothing is changed. */ protected bool TryToGetTopLevelTextBlock(ref XMLIterator iterator, XMLComment comment) { if (iterator.IsOnTag("summary", TagForm.Opening) == false && iterator.IsOnTag("remark", TagForm.Opening) == false && iterator.IsOnTag("remarks", TagForm.Opening) == false && iterator.IsOnTag("example", TagForm.Opening) == false && iterator.IsOnTag("returns", TagForm.Opening) == false && iterator.IsOnTag("value", TagForm.Opening) == false) { return(false); } string keyword = iterator.TagType; string blockType = keyword; if (keyword == "remarks") { blockType = "remark"; } XMLComment.TextBlock block = comment.GetTextBlock(blockType); TagStack tagStack = new TagStack(); tagStack.OpenTag(keyword); iterator.Next(); GetText(ref iterator, block.Text, tagStack); tagStack.CloseAllTags(block.Text); if (iterator.IsOnTag(keyword, TagForm.Closing)) { iterator.Next(); } return(true); }
public virtual void AddComment(int line, XMLComment c) { }
/* Function: GenerateTopic * Creates and returns a <Topic> from the <XMLComment> and returns it. If the comment contains no useful content * it will return null. */ protected Topic GenerateTopic(XMLComment comment) { StringBuilder body = new StringBuilder(); // For the first pass just add summary and similar blocks to the body without a heading. We want them to always // come first. foreach (var block in comment.Blocks) { if (block.Type == "summary" || block.Type == "remark" || block.Type == "value") { string text = (block as XMLComment.TextBlock).Text.ToString(); text = Normalize(text); if (text != null && text.Length > 0) { body.Append(text); } } } // The rest of the blocks can be added afterwards with headings. foreach (var block in comment.Blocks) { if (block.Type == "summary" || block.Type == "remark" || block.Type == "value") { continue; } else if (block is BlockComment.TextBlock) { BlockComment.TextBlock textBlock = (BlockComment.TextBlock)block; string text = textBlock.Text.ToString(); text = Normalize(text); if (text != null && text.Length > 0) { string heading = Engine.Locale.SafeGet("NaturalDocs.Engine", "XML.Heading." + textBlock.Type, null); if (heading != null) { body.Append("<h>"); body.EntityEncodeAndAppend(heading); body.Append("</h>"); } body.Append(text); } } else // BlockComment.ListBlock { BlockComment.ListBlock listBlock = (BlockComment.ListBlock)block; if (listBlock.Count > 0) { string heading = Engine.Locale.SafeGet("NaturalDocs.Engine", "XML.Heading." + listBlock.Type + "(count)", null, listBlock.Count); if (heading != null) { if (listBlock.Type == "param") { body.Append("<h type=\"parameters\">"); } else { body.Append("<h>"); } body.EntityEncodeAndAppend(heading); body.Append("</h>"); } // Parameters always get definition lists even if they don't have descriptions so that the type information can appear with // them in HTML. bool useDefinitionList = (listBlock.Type == "param" || (listBlock.HasNames && listBlock.HasDescriptions)); bool addLinks = (listBlock.Type == "exception" || listBlock.Type == "permission" || listBlock.Type == "seealso"); if (useDefinitionList) { body.Append("<dl>"); } else { body.Append("<ul>"); } foreach (var listItem in listBlock.List) { if (useDefinitionList) { body.Append("<de>"); } else { body.Append("<li><p>"); } if (addLinks) { body.Append("<link type=\"naturaldocs\" originaltext=\""); } body.EntityEncodeAndAppend(listItem.Name); if (addLinks) { body.Append("\">"); } if (useDefinitionList) { body.Append("</de><dd>"); body.Append(listItem.Description); // Should already be in NDMarkup body.Append("</dd>"); } else { body.Append("</p></li>"); } } if (useDefinitionList) { body.Append("</dl>"); } else { body.Append("</ul>"); } } } } Topic topic = null; if (body.Length > 0) { topic = new Topic(EngineInstance.CommentTypes); topic.Body = body.ToString(); MakeSummaryFromBody(topic); } return(topic); }
/* Function: TryToGetTopLevelListItem * If the iterator is on a param, typeparam, exception, or permission tag it will convert it to NDMarkup, add it to the * comment in a list block, move the iterator past it, and return true. Otherwise it returns false and nothing is changed. */ protected bool TryToGetTopLevelListItem(ref XMLIterator iterator, XMLComment comment) { if (iterator.IsOnTag("param", TagForm.Opening) == false && iterator.IsOnTag("exception", TagForm.Opening) == false && iterator.IsOnTag("permission", TagForm.Opening) == false && iterator.IsOnTag("typeparam", TagForm.Opening) == false && iterator.IsOnTag("see", TagForm.Opening) == false && iterator.IsOnTag("see", TagForm.Standalone) == false && iterator.IsOnTag("seealso", TagForm.Opening) == false && iterator.IsOnTag("seealso", TagForm.Standalone) == false) { return(false); } string keyword = iterator.TagType; if (keyword == "see") { keyword = "seealso"; } XMLComment.ListBlock block = comment.GetListBlock(keyword); string name = null; string description = null; if (keyword == "param" || keyword == "typeparam") { name = iterator.TagProperty("name"); } else { name = iterator.TagProperty("cref") ?? iterator.TagProperty("langword"); } if (iterator.TagForm == TagForm.Opening) { TagStack tagStack = new TagStack(); tagStack.OpenTag(keyword); iterator.Next(); StringBuilder descriptionBuilder = new StringBuilder(); GetText(ref iterator, descriptionBuilder, tagStack); tagStack.CloseAllTags(descriptionBuilder); description = Normalize(descriptionBuilder.ToString()); if (iterator.IsOnTag(keyword, TagForm.Closing)) { iterator.Next(); } } else { iterator.Next(); } if (name != null) { block.Add(name, description); } return(true); }