/* 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) { if (HasAnyTag(sourceComment.Start.FirstToken(LineBoundsMode.CommentContent), sourceComment.End.FirstToken(LineBoundsMode.Everything)) == false) { return(false); } LineIterator firstBlockLine = sourceComment.Start; while (firstBlockLine < sourceComment.End && IsFirstBlockLine(firstBlockLine) == false) { firstBlockLine.Next(); } JavadocComment parsedComment = new JavadocComment(); if (sourceComment.Start < firstBlockLine) { parsedComment.Description = GetText(sourceComment.Start, firstBlockLine); } while (firstBlockLine < sourceComment.End) { // There may be unrecognized blocks so we have to manually advance if GetBlockTag() fails. if (!TryToGetBlock(ref firstBlockLine, sourceComment.End, parsedComment)) { firstBlockLine.Next(); } } Topic topic = GenerateTopic(parsedComment); if (topic != null) { topic.CommentLineNumber = sourceComment.Start.LineNumber; topics.Add(topic); } return(true); }
/* Function: TryToGetBlock * If the iterator is on a line that starts with one of the <BlockTags>, parses it, adds its content to the comment, * moves the iterator past it, and returns true. If it is not at the start of a tag block it will return false and change * nothing. */ protected bool TryToGetBlock(ref LineIterator lineIterator, LineIterator limit, JavadocComment comment) { if (lineIterator >= limit) { return(false); } // Get the complete content across multiple lines. string tag; TokenIterator startOfContent; if (TryToGetFirstBlockLine(lineIterator, out tag, out startOfContent) == false) { return(false); } for (;;) { lineIterator.Next(); if (lineIterator >= limit || IsFirstBlockLine(lineIterator)) { break; } } TokenIterator endOfContent = lineIterator.FirstToken(LineBoundsMode.Everything); // Any "@tag item description", possibly in a list if (tag == "exception" || tag == "param" || tag == "throws") { TokenIterator iterator = startOfContent; string symbol = null; TryToGetBlockSymbol(ref iterator, endOfContent, out symbol); iterator.NextPastWhitespace(); string description = GetText(iterator, endOfContent); description = Normalize(description); if (symbol == null || symbol == "" || description == null || description == "") { return(false); } var commentBlock = comment.GetListBlock(tag); commentBlock.Add(symbol, description); return(true); } // Any "@tag description", possibly in a list else if (tag == "author" || tag == "deprecated" || tag == "since" || tag == "version") { string description = GetText(startOfContent, endOfContent); description = Normalize(description); if (description == null || description == "") { return(false); } if (tag == "deprecated") { if (comment.Deprecated == null) { comment.Deprecated = description; } else { comment.Deprecated += description; } } else { var commentBlock = comment.GetListBlock(tag); commentBlock.Add(null, description); } return(true); } // Any "@tag description" that can't be in a list else if (tag == "return") { string description = GetText(startOfContent, endOfContent); description = Normalize(description); if (description == null || description == "") { return(false); } var commentBlock = comment.GetTextBlock(tag); commentBlock.Text.Append(description); return(true); } else if (tag == "see") { string description = null; TokenIterator iterator = startOfContent; // @see "Description" // @see <a href="link">Description</a> if (iterator.Character == '"' || iterator.Character == '<') { // There's not symbol so interpret the whole thing as the description. We'll let GetText() handle the HTML link. description = GetText(iterator, endOfContent); description = Normalize(description); } // @see Class.Class#Member // @see Class.Class#Member Description else { string symbol = GetJavadocLinkSymbol(ref iterator); iterator.NextPastWhitespace(); description = GetSimpleText(iterator, endOfContent); description = Normalize(description); if (description == null || description == "") { description = "<p><link type=\"naturaldocs\" originaltext=\"" + symbol.EntityEncode() + "\"></p>"; } else { description = "<p><link type=\"naturaldocs\" originaltext=\"" + description.EntityEncode() + " at " + symbol.EntityEncode() + "\"></p>"; } } if (description == null || description == "") { return(false); } var commentBlock = comment.GetListBlock(tag); commentBlock.Add(null, description); return(true); } // Ignored blocks // - serial // - serialField // - serialData else { return(true); } }
/* Function: GenerateTopic * Creates and returns a <Topic> from the <JavadocComment> and returns it. If the comment contains no useful content * it will return null. */ protected Topic GenerateTopic(JavadocComment comment) { StringBuilder body = new StringBuilder(); if (comment.Deprecated != null) { string deprecatedNote = comment.Deprecated; deprecatedNote = deprecatedNote.Replace("<p>", "<p><i>"); deprecatedNote = deprecatedNote.Replace("</p>", "</i></p>"); string deprecatedTitle = Locale.Get("NaturalDocs.Engine", "Javadoc.Heading.deprecated"); if (deprecatedNote.StartsWith("<p><i>")) { body.Append("<p><i><b>" + deprecatedTitle + ":</b> "); body.Append(deprecatedNote, 6, deprecatedNote.Length - 6); } else { body.Append("<p><i><b>" + deprecatedTitle + ":</b></i></p>"); body.Append(deprecatedNote); } } if (comment.Description != null) { body.Append(Normalize(comment.Description.ToString())); } foreach (var block in comment.Blocks) { if (block is BlockComment.TextBlock) { BlockComment.TextBlock textBlock = (BlockComment.TextBlock)block; string heading = Locale.SafeGet("NaturalDocs.Engine", "Javadoc.Heading." + textBlock.Type, null); if (heading != null) { body.Append("<h>"); body.EntityEncodeAndAppend(heading); body.Append("</h>"); } body.Append(textBlock.Text); } else { BlockComment.ListBlock listBlock = (BlockComment.ListBlock)block; if (listBlock.Count > 0) { string heading = Engine.Locale.SafeGet("NaturalDocs.Engine", "Javadoc.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 == "throws"); if (useDefinitionList) { body.Append("<dl>"); } else if (listBlock.Count != 1) { body.Append("<ul>"); } foreach (var listItem in listBlock.List) { if (useDefinitionList) { body.Append("<de>"); } else if (listBlock.Count != 1) { body.Append("<li>"); } if (listItem.Name != null) { if (addLinks) { body.Append("<link type=\"naturaldocs\" originaltext=\""); } body.EntityEncodeAndAppend(listItem.Name); if (addLinks) { body.Append("\">"); } } if (useDefinitionList) { body.Append("</de><dd>"); } if (listItem.Description != null) { body.Append(Normalize(listItem.Description)); // Should already be in NDMarkup } if (useDefinitionList) { body.Append("</dd>"); } else if (listBlock.Count != 1) { body.Append("</li>"); } } if (useDefinitionList) { body.Append("</dl>"); } else if (listBlock.Count != 1) { body.Append("</ul>"); } } } } Topic topic = null; if (body.Length > 0) { topic = new Topic(EngineInstance.CommentTypes); topic.Body = body.ToString(); MakeSummaryFromBody(topic); } return(topic); }