コード例 #1
0
        /* Function: TryToGetLineComment
         * If the iterator is on a line that starts with a line comment symbol, this function moves the iterator past the entire
         * comment and returns true.  If the comment is a candidate for documentation it will also return it as a
         * <PossibleDocumentationComment>.  If the line does not start with a line comment symbol it will return false and
         * leave the iterator where it is.
         */
        protected bool TryToGetLineComment(ref LineIterator lineIterator, string commentSymbol,
                                           out PossibleDocumentationComment comment)
        {
            TokenIterator firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

            if (firstToken.MatchesAcrossTokens(commentSymbol) == false)
            {
                comment = null;
                return(false);
            }

            comment       = new PossibleDocumentationComment();
            comment.Start = lineIterator;
            lineIterator.Next();

            // Since we're definitely returning a comment we can mark the comment symbols as we go rather than waiting until
            // the end.
            firstToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, commentSymbol.Length);

            while (lineIterator.IsInBounds)
            {
                firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

                if (firstToken.MatchesAcrossTokens(commentSymbol) == false)
                {
                    break;
                }

                firstToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, commentSymbol.Length);
                lineIterator.Next();
            }

            comment.End = lineIterator;
            return(true);
        }
コード例 #2
0
        /* Function: TryToGetFirstBlockLine
         * If the iterator is on a line that starts with one of the <BlockTags>, extracts the components and returns true.
         * Use <GetBlockTag()> to get the complete block since it may span multiple lines.
         */
        protected bool TryToGetFirstBlockLine(LineIterator lineIterator, out string tag, out TokenIterator startOfContent)
        {
            tag            = null;
            startOfContent = default(TokenIterator);

            TokenIterator tokenIterator = lineIterator.FirstToken(LineBoundsMode.CommentContent);

            if (tokenIterator.Character != '@')
            {
                return(false);
            }

            tokenIterator.Next();

            if (tokenIterator.FundamentalType != FundamentalType.Text)
            {
                return(false);
            }

            string possibleTag = tokenIterator.String;

            if (BlockTags.Contains(possibleTag) == false)
            {
                return(false);
            }

            tokenIterator.Next();
            tokenIterator.NextPastWhitespace();

            tag            = possibleTag;
            startOfContent = tokenIterator;
            return(true);
        }
コード例 #3
0
ファイル: CommentFinder.cs プロジェクト: ws-tools/NaturalDocs
        /* Function: TryToGetPDLineComment
         *
         * If the line iterator is on a line comment, return it and all connected line comments as a
         * <PossibleDocumentationComment> and mark the symbols as <CommentParsingType.CommentSymbol>.  Returns
         * null otherwise.
         *
         * This function takes a separate comment symbol for the first line and all remaining lines, allowing you to detect
         * Javadoc line comments that start with ## and the remaining lines use #.  Both symbols can be the same if this isn't
         * required.  If openingMustBeAlone is set, no symbol can appear immediately after the first line symbol for this
         * function to succeed.  This allows you to specifically detect something like ## without also matching #######.
         */
        protected PossibleDocumentationComment TryToGetPDLineComment(LineIterator lineIterator,
                                                                     string firstSymbol, string remainderSymbol,
                                                                     bool openingMustBeAlone)
        {
            TokenIterator firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

            if (firstToken.MatchesAcrossTokens(firstSymbol) == false)
            {
                return(null);
            }

            if (openingMustBeAlone)
            {
                TokenIterator nextToken = firstToken;
                nextToken.NextByCharacters(firstSymbol.Length);
                if (nextToken.FundamentalType == FundamentalType.Symbol)
                {
                    return(null);
                }
            }

            PossibleDocumentationComment comment = new PossibleDocumentationComment();

            comment.Start = lineIterator;
            lineIterator.Next();

            // Since we're definitely returning a comment (barring the operation being cancelled) we can mark the comment
            // symbols as we go rather than waiting until the end.
            firstToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, firstSymbol.Length);

            while (lineIterator.IsInBounds)
            {
                firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

                if (firstToken.MatchesAcrossTokens(remainderSymbol) == false)
                {
                    break;
                }

                firstToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, remainderSymbol.Length);
                lineIterator.Next();
            }

            comment.End = lineIterator;
            return(comment);
        }
コード例 #4
0
        // Function: GetPossibleDocumentationComments
        //
        // Goes through the file looking for comments that could possibly contain documentation and returns them as a list.  These
        // comments are not guaranteed to have documentation in them, just to be acceptable candidates for them.  If there are no
        // comments it will return an empty list.
        //
        // All the comments in the returned list will have their comment symbols marked as <CommentParsingType.CommentSymbol>
        // in the tokenizer.  This allows further operations to be done on them in a language independent manner.  If you want to also
        // filter out text boxes and lines, use <Comments.LineFinder>.
        //
        override public List <PossibleDocumentationComment> GetPossibleDocumentationComments(Tokenizer source)
        {
            List <PossibleDocumentationComment> comments = new List <PossibleDocumentationComment>();
            LineIterator lineIterator = source.FirstLine;

            PODLineType podLineType;

            while (lineIterator.IsInBounds)
            {
                TokenIterator tokenIterator = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);


                // Hash comments

                if (tokenIterator.Character == '#')
                {
                    PossibleDocumentationComment comment = new PossibleDocumentationComment();
                    comment.Start = lineIterator;


                    // First line

                    if (tokenIterator.MatchesAcrossTokens("###"))
                    {
                        comment.Javadoc = false;
                        comment.XML     = true;
                    }
                    else if (tokenIterator.MatchesAcrossTokens("##"))
                    {
                        comment.Javadoc = true;
                        comment.XML     = false;
                    }
                    else                     // just "#"
                    {
                        comment.Javadoc = false;
                        comment.XML     = false;
                    }

                    lineIterator.Next();


                    // Subsequent lines

                    while (lineIterator.IsInBounds)
                    {
                        tokenIterator = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

                        if (tokenIterator.Character != '#')
                        {
                            break;
                        }

                        if (tokenIterator.MatchesAcrossTokens("###"))
                        {
                            comment.Javadoc = false;
                            // XML is still possible
                        }
                        else if (tokenIterator.MatchesAcrossTokens("##"))
                        {
                            comment.Javadoc = false;
                            comment.XML     = false;
                        }
                        else                         // just "#"
                        {
                            // Javadoc is still possible
                            comment.XML = false;
                        }

                        lineIterator.Next();
                    }

                    comment.End = lineIterator;
                    comments.Add(comment);


                    // Go back and mark the tokens

                    int firstLineCount, subsequentLineCount;

                    if (comment.XML)
                    {
                        firstLineCount      = 3;
                        subsequentLineCount = 3;
                    }
                    else if (comment.Javadoc)
                    {
                        firstLineCount      = 2;
                        subsequentLineCount = 1;
                    }
                    else                     // plain
                    {
                        firstLineCount      = 1;
                        subsequentLineCount = 1;
                    }

                    LineIterator temp = comment.Start;
                    tokenIterator = temp.FirstToken(LineBoundsMode.ExcludeWhitespace);

                    tokenIterator.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, firstLineCount);
                    temp.Next();

                    while (temp < comment.End)
                    {
                        tokenIterator = temp.FirstToken(LineBoundsMode.ExcludeWhitespace);
                        tokenIterator.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, subsequentLineCount);
                        temp.Next();
                    }


                    // XML can actually appear in Javadoc comments

                    if (comment.Javadoc)
                    {
                        comment.XML = true;
                    }
                }


                // POD comments

                else if (TryToSkipPODLine(ref tokenIterator, out podLineType))
                {
                    TokenIterator podLineStart, podLineEnd;
                    lineIterator.GetBounds(LineBoundsMode.CommentContent, out podLineStart, out podLineEnd);

                    lineIterator.Tokenizer.SetCommentParsingTypeBetween(podLineStart, podLineEnd, CommentParsingType.CommentSymbol);

                    if (podLineType == PODLineType.StartNaturalDocs ||
                        podLineType == PODLineType.StartJavadoc)
                    {
                        PossibleDocumentationComment comment = new PossibleDocumentationComment();
                        comment.Start = lineIterator;

                        if (podLineType == PODLineType.StartJavadoc)
                        {
                            comment.Javadoc = true;
                        }

                        for (;;)
                        {
                            lineIterator.Next();

                            if (lineIterator.IsInBounds == false)
                            {
                                break;
                            }

                            tokenIterator = lineIterator.FirstToken(LineBoundsMode.CommentContent);

                            if (TryToSkipPODLine(ref tokenIterator, out podLineType) == true)
                            {
                                if (podLineType == PODLineType.End)
                                {
                                    lineIterator.GetBounds(LineBoundsMode.CommentContent, out podLineStart, out podLineEnd);
                                    lineIterator.Tokenizer.SetCommentParsingTypeBetween(podLineStart, podLineEnd, CommentParsingType.CommentSymbol);

                                    lineIterator.Next();
                                }

                                break;
                            }
                        }

                        comment.End = lineIterator;
                        comments.Add(comment);
                    }
                    else
                    {
                        lineIterator.Next();
                    }
                }

                else
                {
                    lineIterator.Next();
                }
            }

            return(comments);
        }
コード例 #5
0
 /* Function: GetText
  */
 protected string GetText(LineIterator start, LineIterator end)
 {
     return(GetText(start.FirstToken(LineBoundsMode.Everything), end.FirstToken(LineBoundsMode.Everything)));
 }
コード例 #6
0
        /* 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);
            }
        }
コード例 #7
0
ファイル: CommentFinder.cs プロジェクト: ws-tools/NaturalDocs
        // Group: Support Functions
        // __________________________________________________________________________


        /* Function: TryToGetPDBlockComment
         *
         * If the line iterator is on the starting symbol of a block comment, return it as a <PossibleDocumentationComment>
         * and mark the symbols as <CommentParsingType.CommentSymbol>.  If the iterator is not on the opening comment
         * symbol or there is content after the closing comment symbol making it unsuitable as a documentation comment,
         * returns null.
         *
         * If openingMustBeAlone is set, that means no symbol can appear immediately after the opening symbol for this
         * function to succeed.  This allows you to specifically detect something like /** without also matching /******.
         */
        protected PossibleDocumentationComment TryToGetPDBlockComment(LineIterator lineIterator,
                                                                      string openingSymbol, string closingSymbol,
                                                                      bool openingMustBeAlone)
        {
            TokenIterator firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);

            if (firstToken.MatchesAcrossTokens(openingSymbol) == false)
            {
                return(null);
            }

            if (openingMustBeAlone)
            {
                TokenIterator nextToken = firstToken;
                nextToken.NextByCharacters(openingSymbol.Length);
                if (nextToken.FundamentalType == FundamentalType.Symbol)
                {
                    return(null);
                }
            }

            PossibleDocumentationComment comment = new PossibleDocumentationComment();

            comment.Start = lineIterator;

            for (;;)
            {
                if (!lineIterator.IsInBounds)
                {
                    return(null);
                }

                TokenIterator closingSymbolIterator;

                if (lineIterator.FindAcrossTokens(closingSymbol, false, LineBoundsMode.Everything, out closingSymbolIterator) == true)
                {
                    closingSymbolIterator.NextByCharacters(closingSymbol.Length);

                    closingSymbolIterator.NextPastWhitespace();

                    if (closingSymbolIterator.FundamentalType != FundamentalType.LineBreak &&
                        closingSymbolIterator.FundamentalType != FundamentalType.Null)
                    {
                        return(null);
                    }

                    lineIterator.Next();
                    comment.End = lineIterator;
                    break;
                }

                lineIterator.Next();
            }

            // Success.  Mark the symbols before returning.
            firstToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, openingSymbol.Length);

            TokenIterator lastToken;

            lineIterator.Previous();
            lineIterator.GetBounds(LineBoundsMode.ExcludeWhitespace, out firstToken, out lastToken);
            lastToken.PreviousByCharacters(closingSymbol.Length);
            lastToken.SetCommentParsingTypeByCharacters(CommentParsingType.CommentSymbol, closingSymbol.Length);

            return(comment);
        }
コード例 #8
0
ファイル: Lua.cs プロジェクト: loafbrad/NaturalDocs
        /* Function: TryToGetLineComment
         *
         * If the iterator is on a line that starts with a line comment symbol, this function moves the iterator past the entire
         * comment and returns true.  If the comment is a candidate for documentation it will also return it as a
         * <PossibleDocumentationComment> and mark the symbols as <CommentParsingType.CommentSymbol>.  If the
         * line does not start with a line comment symbol it will return false and leave the iterator where it is.
         */
        protected bool TryToGetLineComment(ref LineIterator lineIterator, out PossibleDocumentationComment comment)
        {
            TokenIterator firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);
            TokenIterator lookahead  = firstToken;


            // Are we on a line comment?

            if (TryToSkipLineCommentSymbol(ref lookahead) == false)
            {
                comment = null;
                return(false);
            }


            // We are.  Create a possible documentation comment.

            comment       = new PossibleDocumentationComment();
            comment.Start = lineIterator;


            // Check if we're a Javadoc/XML comment.  We can't tell the difference from just the first line.

            TokenIterator endOfCommentSymbol = lookahead;

            if (lookahead.Character == '-')
            {
                lookahead.Next();

                if (lookahead.FundamentalType != FundamentalType.Symbol)
                {
                    endOfCommentSymbol = lookahead;
                    comment.Javadoc    = true;
                    comment.XML        = true;
                }
            }


            // Mark it.

            firstToken.SetCommentParsingTypeBetween(endOfCommentSymbol, CommentParsingType.CommentSymbol);


            // Continue to find the rest of the comment

            lineIterator.Next();
            bool hasXMLishLines    = false;
            bool hasNonXMLishLines = false;
            bool hasMultipleLines  = false;

            while (lineIterator.IsInBounds)
            {
                firstToken = lineIterator.FirstToken(LineBoundsMode.ExcludeWhitespace);
                lookahead  = firstToken;

                if (TryToSkipLineCommentSymbol(ref lookahead) == false)
                {
                    break;
                }

                hasMultipleLines   = true;
                endOfCommentSymbol = lookahead;

                if (lookahead.Character == '-')
                {
                    lookahead.Next();

                    if (lookahead.FundamentalType != FundamentalType.Symbol)
                    {
                        hasXMLishLines     = true;
                        endOfCommentSymbol = lookahead;
                    }
                    else
                    {
                        hasNonXMLishLines = true;
                    }
                }
                else
                {
                    hasNonXMLishLines = true;
                }

                firstToken.SetCommentParsingTypeBetween(endOfCommentSymbol, CommentParsingType.CommentSymbol);
                lineIterator.Next();
            }

            comment.End = lineIterator;

            if (hasMultipleLines && comment.Javadoc)
            {
                if (hasXMLishLines && !hasNonXMLishLines)
                {
                    comment.Javadoc = false;
                }
                else if (hasNonXMLishLines)
                {
                    comment.XML = false;
                }
            }

            return(true);
        }