Esempio n. 1
0
        /* Function: BuildCurrentClass
         */
        protected void BuildCurrentClass()
        {
            htmlOutput.Append("<div class=\"CPEntry T" + EngineInstance.CommentTypes.FromID(topic.CommentTypeID).SimpleIdentifier + " Current\">");


            // Pre-prototype lines

            int           lineCount = parsedPrototype.NumberOfPrePrototypeLines;
            TokenIterator start, end;

            for (int i = 0; i < lineCount; i++)
            {
                parsedPrototype.GetPrePrototypeLine(i, out start, out end);

                htmlOutput.Append("<div class=\"CPPrePrototypeLine\">");
                BuildSyntaxHighlightedText(start, end);
                htmlOutput.Append("</div>");
            }


            // Keyword and modifiers.  We only show the keyword if it's not "class".

            TokenIterator startKeyword, endKeyword;

            topic.ParsedClassPrototype.GetKeyword(out startKeyword, out endKeyword);
            string keyword = startKeyword.String;

            TokenIterator startModifiers, endModifiers;
            bool          hasModifiers = topic.ParsedClassPrototype.GetModifiers(out startModifiers, out endModifiers);

            if (hasModifiers || keyword != "class")
            {
                StringBuilder modifiersOutput = new StringBuilder();
                TokenIterator partial;

                bool hasPartial = startModifiers.Tokenizer.FindTokenBetween("partial", EngineInstance.Languages.FromID(topic.LanguageID).CaseSensitive,
                                                                            startModifiers, endModifiers, out partial);

                if (hasPartial)
                {
                    TokenIterator lookahead = partial;
                    lookahead.Next();

                    if (lookahead < endModifiers &&
                        (lookahead.FundamentalType == FundamentalType.Text ||
                         lookahead.Character == '_'))
                    {
                        hasPartial = false;
                    }

                    TokenIterator lookbehind = partial;
                    lookbehind.Previous();

                    if (lookbehind >= startModifiers &&
                        (lookbehind.FundamentalType == FundamentalType.Text ||
                         lookbehind.Character == '_'))
                    {
                        hasPartial = false;
                    }
                }

                if (hasModifiers && hasPartial)
                {
                    if (partial > startModifiers)
                    {
                        TokenIterator lookbehind = partial;
                        lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

                        BuildSyntaxHighlightedText(startModifiers, lookbehind, modifiersOutput);
                    }

                    partial.Next();
                    partial.NextPastWhitespace();

                    if (partial < endModifiers)
                    {
                        if (modifiersOutput.Length > 0)
                        {
                            modifiersOutput.Append(' ');
                        }

                        BuildSyntaxHighlightedText(partial, endModifiers, modifiersOutput);
                    }
                }
                else if (hasModifiers)
                {
                    BuildSyntaxHighlightedText(startModifiers, endModifiers, modifiersOutput);
                }

                if (keyword != "class")
                {
                    if (modifiersOutput.Length > 0)
                    {
                        modifiersOutput.Append(' ');
                    }

                    BuildSyntaxHighlightedText(startKeyword, endKeyword, modifiersOutput);
                }

                if (modifiersOutput.Length > 0)
                {
                    htmlOutput.Append("<div class=\"CPModifiers\">");
                    htmlOutput.Append(modifiersOutput.ToString());
                    htmlOutput.Append("</div>");
                }
            }


            // Name.  We use the fully resolved name in the symbol instead of the prototype name, which may just be the last segment.

            htmlOutput.Append("<div class=\"CPName\">");

            BuildWrappedTitle(topic.Symbol.FormatWithSeparator(this.language.MemberOperator), topic.CommentTypeID, htmlOutput);

            TokenIterator startTemplate, endTemplate;

            if (topic.ParsedClassPrototype.GetTemplateSuffix(out startTemplate, out endTemplate))
            {
                // Include a zero-width space for wrapping
                htmlOutput.Append("&#8203;<span class=\"TemplateSignature\">");
                htmlOutput.EntityEncodeAndAppend(startTemplate.Tokenizer.TextBetween(startTemplate, endTemplate));
                htmlOutput.Append("</span>");
            }

            htmlOutput.Append("</div>");


            // Post-prototype lines

            lineCount = parsedPrototype.NumberOfPostPrototypeLines;

            for (int i = 0; i < lineCount; i++)
            {
                parsedPrototype.GetPostPrototypeLine(i, out start, out end);

                htmlOutput.Append("<div class=\"CPPostPrototypeLine\">");
                BuildSyntaxHighlightedText(start, end);
                htmlOutput.Append("</div>");
            }

            htmlOutput.Append("</div>");
        }
Esempio n. 2
0
        /* Function: TryToSkipAnnotationParameters
         *
         * Tries to move the iterator past an annotation parameter section, such as "("String")" in "@Copynight("String")".
         *
         * Supported Modes:
         *
         *		- <ParseMode.IterateOnly>
         *		- <ParseMode.SyntaxHighlight>
         *		- <ParseMode.ParsePrototype>
         *			- The contents will be marked with parameter tokens.
         *		- Everything else is treated as <ParseMode.IterateOnly>.
         */
        protected bool TryToSkipAnnotationParameters(ref TokenIterator iterator, ParseMode mode = ParseMode.IterateOnly)
        {
            if (iterator.Character != '(')
            {
                return(false);
            }

            TokenIterator lookahead = iterator;

            if (!TryToSkipBlock(ref lookahead, false))
            {
                return(false);
            }

            TokenIterator end = lookahead;

            if (mode == ParseMode.SyntaxHighlight)
            {
                iterator.SetSyntaxHighlightingTypeBetween(end, SyntaxHighlightingType.Metadata);
            }

            else if (mode == ParseMode.ParsePrototype)
            {
                TokenIterator openingParen = iterator;

                TokenIterator closingParen = lookahead;
                closingParen.Previous();

                openingParen.PrototypeParsingType = PrototypeParsingType.StartOfParams;
                closingParen.PrototypeParsingType = PrototypeParsingType.EndOfParams;

                lookahead = openingParen;
                lookahead.Next();

                TokenIterator startOfParam = lookahead;

                while (lookahead < closingParen)
                {
                    if (lookahead.Character == ',')
                    {
                        MarkAnnotationParameter(startOfParam, lookahead, mode);

                        lookahead.PrototypeParsingType = PrototypeParsingType.ParamSeparator;
                        lookahead.Next();

                        startOfParam = lookahead;
                    }

                    else if (TryToSkipComment(ref lookahead) ||
                             TryToSkipString(ref lookahead) ||
                             TryToSkipBlock(ref lookahead, true))
                    {
                    }

                    else
                    {
                        lookahead.Next();
                    }
                }

                MarkAnnotationParameter(startOfParam, lookahead, mode);
            }

            iterator = end;
            return(true);
        }
Esempio n. 3
0
        // Group: Support Functions
        // __________________________________________________________________________


        /* Function: CalculateParameterTable
         * Fills in <parameterTableTokenIndexes>, <parameterTableColumnUsed>, and <symbolColumnWidth> for the
         * passed section.
         */
        protected void CalculateParameterTable(Prototypes.ParameterSection section)
        {
            //
            // Check if this is a raw section with nothing other than parameter separators, meaning no name, type, etc. tokens
            //

            TokenIterator iterator     = section.Start;
            TokenIterator endOfSection = section.End;
            bool          isRaw        = true;

            while (iterator < endOfSection)
            {
                var type = iterator.PrototypeParsingType;

                if (type != PrototypeParsingType.Null &&
                    type != PrototypeParsingType.StartOfPrototypeSection &&
                    type != PrototypeParsingType.StartOfParams &&
                    type != PrototypeParsingType.ParamSeparator &&
                    type != PrototypeParsingType.EndOfParams &&
                    type != PrototypeParsingType.EndOfPrototypeSection)
                {
                    isRaw = false;
                    break;
                }

                iterator.Next();
            }


            //
            // Now fill in parameterTableTokenIndexes
            //

            parameterTableTokenIndexes = new int[section.NumberOfParameters, NumberOfColumns + 1];

            for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++)
            {
                TokenIterator startOfParam, endOfParam;
                section.GetParameterBounds(parameterIndex, out startOfParam, out endOfParam);

                iterator = startOfParam;
                iterator.NextPastWhitespace(endOfParam);


                // C-Style Parameters

                if (section.ParameterStyle == ParsedPrototype.ParameterStyle.C)
                {
                    while (iterator < endOfParam &&
                           iterator.PrototypeParsingType == PrototypeParsingType.Null &&
                           iterator.FundamentalType == FundamentalType.Whitespace)
                    {
                        iterator.Next();
                    }


                    // ModifierQualifier

                    int currentColumn = 0;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    TokenIterator startOfType = iterator;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            // Null covers whitespace and any random symbols we encountered that went unmarked.
                            if (type == PrototypeParsingType.TypeModifier ||
                                type == PrototypeParsingType.TypeQualifier ||
                                type == PrototypeParsingType.ParamModifier ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                     type == PrototypeParsingType.OpeningParamModifier)
                            {
                                SkipModifierBlock(ref iterator, endOfParam);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // Type

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    // Allow this column to claim the contents of a raw prototype.  They should all be null tokens.
                    // We use the type column instead of the name column because the name column isn't fully syntax highlighted.
                    while (iterator < endOfParam)
                    {
                        PrototypeParsingType type = iterator.PrototypeParsingType;

                        // The previous loop already got any modifiers before the type, so this will only cover the type
                        // plus any modifiers following it.
                        if (type == PrototypeParsingType.Type ||
                            type == PrototypeParsingType.TypeModifier ||
                            type == PrototypeParsingType.ParamModifier ||
                            (isRaw && type == PrototypeParsingType.ParamSeparator) ||
                            type == PrototypeParsingType.Null)
                        {
                            iterator.Next();
                        }
                        else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                 type == PrototypeParsingType.OpeningParamModifier)
                        {
                            SkipModifierBlock(ref iterator, endOfParam);
                        }
                        else
                        {
                            break;
                        }
                    }


                    // Symbols

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        // All symbols are part of the type column right now because they're marked as type or param
                        // modifiers.  Walk backwards to claim the symbols from the type column.

                        if (iterator > startOfType)
                        {
                            TokenIterator lookbehind = iterator;
                            lookbehind.Previous();

                            if (lookbehind.FundamentalType == FundamentalType.Symbol &&
                                lookbehind.Character != '_' &&
                                lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingTypeModifier &&
                                lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingParamModifier)
                            {
                                parameterTableTokenIndexes[parameterIndex, currentColumn] = lookbehind.TokenIndex;
                                lookbehind.Previous();

                                while (lookbehind >= startOfType)
                                {
                                    if (lookbehind.FundamentalType == FundamentalType.Symbol &&
                                        lookbehind.Character != '_' &&
                                        lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingTypeModifier &&
                                        lookbehind.PrototypeParsingType != PrototypeParsingType.ClosingParamModifier)
                                    {
                                        parameterTableTokenIndexes[parameterIndex, currentColumn] = lookbehind.TokenIndex;
                                        lookbehind.Previous();
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }

                                // Fix up any columns we stole from
                                for (int i = 0; i < currentColumn; i++)
                                {
                                    if (parameterTableTokenIndexes[parameterIndex, i] > parameterTableTokenIndexes[parameterIndex, currentColumn])
                                    {
                                        parameterTableTokenIndexes[parameterIndex, i] = parameterTableTokenIndexes[parameterIndex, currentColumn];
                                    }
                                }
                            }
                        }
                    }


                    // Name

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            // Include the parameter separator because there may not be a default value.
                            // Include modifiers because there still may be some after the name.
                            if (type == PrototypeParsingType.Name ||
                                type == PrototypeParsingType.TypeModifier ||
                                type == PrototypeParsingType.ParamModifier ||
                                type == PrototypeParsingType.ParamSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                     type == PrototypeParsingType.OpeningParamModifier)
                            {
                                SkipModifierBlock(ref iterator, endOfParam);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // PropertyValueSeparator

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.PropertyValueSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // PropertyValue

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.PropertyValue ||
                                type == PrototypeParsingType.ParamSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // DefaultValueSeparator

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.DefaultValueSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // DefaultValue

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;


                    // End of param

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = endOfParam.TokenIndex;
                }


                // Pascal-Style Parameters

                else if (section.ParameterStyle == ParsedPrototype.ParameterStyle.Pascal)
                {
                    while (iterator < endOfParam &&
                           iterator.PrototypeParsingType == PrototypeParsingType.Null &&
                           iterator.FundamentalType == FundamentalType.Whitespace)
                    {
                        iterator.Next();
                    }


                    // ModifierQualifier

                    int currentColumn = 0;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.TypeModifier ||
                                type == PrototypeParsingType.ParamModifier ||
                                type == PrototypeParsingType.ParamSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                     type == PrototypeParsingType.OpeningParamModifier)
                            {
                                SkipModifierBlock(ref iterator, endOfParam);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // Do we have a name-type separator?  We may not, such as for SQL.

                    bool          hasNameTypeSeparator = false;
                    TokenIterator lookahead            = iterator;

                    if (!isRaw)
                    {
                        while (lookahead < endOfParam)
                        {
                            if (lookahead.PrototypeParsingType == PrototypeParsingType.NameTypeSeparator)
                            {
                                hasNameTypeSeparator = true;
                                break;
                            }

                            lookahead.Next();
                        }
                    }


                    // Name

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            // Include the parameter separator because there may not be a type.
                            if (type == PrototypeParsingType.Name ||
                                type == PrototypeParsingType.ParamSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            // Include modifiers because there still may be some after the name, but only if there's a name-type separator.
                            else if (hasNameTypeSeparator &&
                                     (type == PrototypeParsingType.TypeModifier ||
                                      type == PrototypeParsingType.ParamModifier))
                            {
                                iterator.Next();
                            }
                            else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                     type == PrototypeParsingType.OpeningParamModifier)
                            {
                                SkipModifierBlock(ref iterator, endOfParam);
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // TypeNameSeparator

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.NameTypeSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // Symbols

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        if (iterator < endOfParam &&
                            iterator.FundamentalType == FundamentalType.Symbol &&
                            iterator.Character != '_')
                        {
                            while (iterator < endOfParam)
                            {
                                PrototypeParsingType type = iterator.PrototypeParsingType;

                                if ((
                                        (iterator.FundamentalType == FundamentalType.Symbol && iterator.Character != '_') ||
                                        (iterator.FundamentalType == FundamentalType.Whitespace)
                                        ) &&
                                    (type == PrototypeParsingType.TypeModifier ||
                                     type == PrototypeParsingType.ParamModifier ||
                                     type == PrototypeParsingType.Null))
                                {
                                    iterator.Next();
                                }
                                else
                                {
                                    break;
                                }
                            }
                        }
                    }


                    // Type

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    // Allow this column to claim the contents of a raw prototype.  They should all be null tokens.
                    // We use the type column instead of the name column because the name column isn't syntax highlighted.
                    while (iterator < endOfParam)
                    {
                        PrototypeParsingType type = iterator.PrototypeParsingType;

                        // Include the parameter separator because there may not be a default value.
                        if (type == PrototypeParsingType.Type ||
                            type == PrototypeParsingType.TypeModifier ||
                            type == PrototypeParsingType.TypeQualifier ||
                            type == PrototypeParsingType.ParamModifier ||
                            type == PrototypeParsingType.ParamSeparator ||
                            type == PrototypeParsingType.Null)
                        {
                            iterator.Next();
                        }
                        else if (type == PrototypeParsingType.OpeningTypeModifier ||
                                 type == PrototypeParsingType.OpeningParamModifier)
                        {
                            SkipModifierBlock(ref iterator, endOfParam);
                        }
                        else
                        {
                            break;
                        }
                    }


                    // PropertyValueSeparator

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.PropertyValueSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // PropertyValue

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.PropertyValue ||
                                type == PrototypeParsingType.ParamSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // DefaultValueSeparator

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;

                    if (!isRaw)
                    {
                        while (iterator < endOfParam)
                        {
                            PrototypeParsingType type = iterator.PrototypeParsingType;

                            if (type == PrototypeParsingType.DefaultValueSeparator ||
                                type == PrototypeParsingType.Null)
                            {
                                iterator.Next();
                            }
                            else
                            {
                                break;
                            }
                        }
                    }


                    // DefaultValue

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = iterator.TokenIndex;


                    // End of param

                    currentColumn++;
                    parameterTableTokenIndexes[parameterIndex, currentColumn] = endOfParam.TokenIndex;
                }
            }



            //
            // Next fill in parameterTableColumnsUsed
            //

            // There's a very high likelihood of this array always being the same length so it's worth it to try to reuse the
            // memory and avoid a reallocation.
            if (parameterTableColumnsUsed != null &&
                parameterTableColumnsUsed.Length == NumberOfColumns)
            {
                Array.Clear(parameterTableColumnsUsed, 0, NumberOfColumns);
            }
            else
            {
                parameterTableColumnsUsed = new bool[NumberOfColumns];
            }

            for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++)
            {
                for (int columnIndex = 0; columnIndex < NumberOfColumns; columnIndex++)
                {
                    if (parameterTableTokenIndexes[parameterIndex, columnIndex] !=
                        parameterTableTokenIndexes[parameterIndex, columnIndex + 1])
                    {
                        parameterTableColumnsUsed[columnIndex] = true;
                    }
                }
            }



            //
            // Next determine the symbol column's width
            //

            symbolColumnWidth = 0;

            if (parameterTableColumnsUsed[SymbolsColumnIndex])
            {
                for (int parameterIndex = 0; parameterIndex < section.NumberOfParameters; parameterIndex++)
                {
                    int startTokenIndex = parameterTableTokenIndexes[parameterIndex, SymbolsColumnIndex];
                    int endTokenIndex   = parameterTableTokenIndexes[parameterIndex, SymbolsColumnIndex + 1];

                    if (endTokenIndex > startTokenIndex)
                    {
                        TokenIterator start, end;
                        section.GetParameterBounds(parameterIndex, out start, out end);

                        start.Next(startTokenIndex - start.TokenIndex);
                        end.Previous(end.TokenIndex - endTokenIndex);

                        int paramColumnWidth = end.RawTextIndex - start.RawTextIndex;

                        if (paramColumnWidth > symbolColumnWidth)
                        {
                            symbolColumnWidth = paramColumnWidth;
                        }
                    }
                }
            }
        }
Esempio n. 4
0
        // Group: Parsing Functions
        // __________________________________________________________________________


        /* Function: TryToSkipPODLine
         * If the iterator is on a POD line such as "=pod", moves the iterator past it and returns true and the type.  If the iterator
         * isn't on a POD line it will return false and leave the iterator alone.
         */
        protected bool TryToSkipPODLine(ref TokenIterator iterator, out PODLineType type)
        {
            type = 0;

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

            TokenIterator lookbehind = iterator;

            for (;;)
            {
                lookbehind.Previous();

                if (lookbehind.IsInBounds == false ||
                    lookbehind.FundamentalType == FundamentalType.LineBreak)
                {
                    break;
                }
                else if (lookbehind.FundamentalType != FundamentalType.Whitespace)
                {
                    return(false);
                }
            }

            TokenIterator endOfLine = iterator;

            endOfLine.Next();

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

            do
            {
                endOfLine.Next();
            }while (endOfLine.IsInBounds &&
                    endOfLine.FundamentalType != FundamentalType.LineBreak);

            TokenIterator endOfContent = endOfLine;

            endOfContent.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

            // ND and Javadoc lines may also match PODBeginLineRegex so test them first.
            if (iterator.Tokenizer.MatchTextBetween(PODBeginNDLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartNaturalDocs;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODBeginJavadocLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartJavadoc;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODBeginLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.StartPOD;
            }
            else if (iterator.Tokenizer.MatchTextBetween(PODEndLineRegex, iterator, endOfContent).Success)
            {
                type = PODLineType.End;
            }
            else
            {
                return(false);
            }

            iterator = endOfLine;

            if (iterator.FundamentalType == FundamentalType.LineBreak)
            {
                iterator.Next();
            }

            return(true);
        }
Esempio n. 5
0
        /* Function: AppendCurrentClassPrototype
         */
        protected void AppendCurrentClassPrototype(StringBuilder output)
        {
            // Main tag

            string simpleTypeIdentifier = EngineInstance.CommentTypes.FromID(context.Topic.CommentTypeID).SimpleIdentifier;

            output.Append("<div class=\"CPEntry T" + simpleTypeIdentifier + " Current\">");


            // Pre-prototype lines

            int           lineCount = parsedClassPrototype.NumberOfPrePrototypeLines;
            TokenIterator start, end;

            for (int i = 0; i < lineCount; i++)
            {
                parsedClassPrototype.GetPrePrototypeLine(i, out start, out end);

                output.Append("<div class=\"CPPrePrototypeLine\">");
                AppendSyntaxHighlightedText(start, end, output);
                output.Append("</div>");
            }


            // Keyword and modifiers.  We only show the keyword if it's not "class", and we exclude "partial" from the list of modifiers.

            TokenIterator startKeyword, endKeyword;

            parsedClassPrototype.GetKeyword(out startKeyword, out endKeyword);
            string keyword = startKeyword.String;

            TokenIterator startModifiers, endModifiers;
            bool          hasModifiers = parsedClassPrototype.GetModifiers(out startModifiers, out endModifiers);

            if (hasModifiers || keyword != "class")
            {
                StringBuilder modifiersOutput = new StringBuilder();
                TokenIterator partial;

                bool hasPartial = startModifiers.Tokenizer.FindTokenBetween("partial", language.CaseSensitive, startModifiers, endModifiers,
                                                                            out partial);

                // Make sure "partial" is a keyword and not part of a longer identifier
                if (hasPartial)
                {
                    TokenIterator lookahead = partial;
                    lookahead.Next();

                    if (lookahead < endModifiers &&
                        (lookahead.FundamentalType == FundamentalType.Text ||
                         lookahead.Character == '_'))
                    {
                        hasPartial = false;
                    }

                    TokenIterator lookbehind = partial;
                    lookbehind.Previous();

                    if (lookbehind >= startModifiers &&
                        (lookbehind.FundamentalType == FundamentalType.Text ||
                         lookbehind.Character == '_'))
                    {
                        hasPartial = false;
                    }
                }

                // Add the modifiers sans-"partial"
                if (hasModifiers && hasPartial)
                {
                    if (partial > startModifiers)
                    {
                        TokenIterator lookbehind = partial;
                        lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds);

                        AppendSyntaxHighlightedText(startModifiers, lookbehind, modifiersOutput);
                    }

                    partial.Next();
                    partial.NextPastWhitespace();

                    if (partial < endModifiers)
                    {
                        if (modifiersOutput.Length > 0)
                        {
                            modifiersOutput.Append(' ');
                        }

                        AppendSyntaxHighlightedText(partial, endModifiers, modifiersOutput);
                    }
                }
                else if (hasModifiers)
                {
                    AppendSyntaxHighlightedText(startModifiers, endModifiers, modifiersOutput);
                }

                // Add the keyword if it isn't "class"
                if (keyword != "class")
                {
                    if (modifiersOutput.Length > 0)
                    {
                        modifiersOutput.Append(' ');
                    }

                    AppendSyntaxHighlightedText(startKeyword, endKeyword, modifiersOutput);
                }

                if (modifiersOutput.Length > 0)
                {
                    output.Append("<div class=\"CPModifiers\">");
                    output.Append(modifiersOutput.ToString());
                    output.Append("</div>");
                }
            }


            // Name.  We use the fully resolved name in the symbol instead of the prototype name, which may just be the last segment.

            output.Append("<div class=\"CPName\">");

            AppendWrappedTitle(context.Topic.Symbol.FormatWithSeparator(language.MemberOperator), WrappedTitleMode.Code, output);

            TokenIterator startTemplate, endTemplate;

            if (parsedClassPrototype.GetTemplateSuffix(out startTemplate, out endTemplate))
            {
                // Include preceding whitespace if present, or a zero-width space for wrapping if not
                if (!startTemplate.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds))
                {
                    output.Append("&#8203;");
                }

                output.Append("<span class=\"TemplateSignature\">");
                AppendSyntaxHighlightedText(startTemplate, endTemplate, output);
                output.Append("</span>");
            }

            output.Append("</div>");


            // Post-prototype lines

            lineCount = parsedClassPrototype.NumberOfPostPrototypeLines;

            for (int i = 0; i < lineCount; i++)
            {
                parsedClassPrototype.GetPostPrototypeLine(i, out start, out end);

                output.Append("<div class=\"CPPostPrototypeLine\">");
                AppendSyntaxHighlightedText(start, end, output);
                output.Append("</div>");
            }

            output.Append("</div>");
        }
Esempio n. 6
0
        /* Function: AppendSyntaxHighlightedTextWithTypeLinks
         *
         * Formats the text between the iterators with syntax highlighting and links for any tokens marked with
         * <PrototypeParsingType.Type> and <PrototypeParsingType.TypeQualifier>.  Appends the result to the passed StringBuilder.
         *
         * Parameters:
         *
         *		start - The first token of the text to convert.
         *		end - The end of the text to convert, which is one token past the last one included.
         *		output - The StringBuilder to append the output to.
         *
         *		links - A list of <Links> that should  contain any appearing in the code.
         *		linkTargets - A list of topics that should contain any used as targets in the list of links.
         *
         *		extendTypeSearch - If true, it will search beyond the bounds of the iterators to get the complete type.  This allows you to
         *									 format only a portion of the link with this function yet still have the link go to the complete destination.
         *
         * Requirements:
         *
         *		- The <Context>'s topic and page must be set.
         */
        public void AppendSyntaxHighlightedTextWithTypeLinks(TokenIterator start, TokenIterator end, StringBuilder output,
                                                             IList <Link> links, IList <Topics.Topic> linkTargets,
                                                             bool extendTypeSearch = false)
        {
                        #if DEBUG
            if (Context.Topic == null)
            {
                throw new Exception("Tried to call AppendSyntaxtHighlightedTextWithTypeLinks without setting the context's topic.");
            }
            if (Context.Page.IsNull)
            {
                throw new Exception("Tried to call AppendSyntaxtHighlightedTextWithTypeLinks without setting the context's page.");
            }
            if (links == null)
            {
                throw new Exception("Tried to call AppendSyntaxtHighlightedTextWithTypeLinks without setting the links variable.");
            }
            if (linkTargets == null)
            {
                throw new Exception("Tried to call AppendSyntaxtHighlightedTextWithTypeLinks without setting the linkTargets variable.");
            }
                        #endif

            Language language = EngineInstance.Languages.FromID(Context.Topic.LanguageID);


            // Find each Type/TypeQualifier stretch in the text

            TokenIterator iterator = start;

            while (iterator < end)
            {
                if (iterator.PrototypeParsingType == PrototypeParsingType.Type ||
                    iterator.PrototypeParsingType == PrototypeParsingType.TypeQualifier)
                {
                    TokenIterator textStart = iterator;
                    TokenIterator textEnd   = iterator;

                    do
                    {
                        textEnd.Next();
                    }while (textEnd < end &&
                            (textEnd.PrototypeParsingType == PrototypeParsingType.Type ||
                             textEnd.PrototypeParsingType == PrototypeParsingType.TypeQualifier));

                    TokenIterator symbolStart = textStart;
                    TokenIterator symbolEnd   = textEnd;


                    // Extend past start and end if the flag is set

                    if (extendTypeSearch && symbolStart == start)
                    {
                        TokenIterator temp = symbolStart;
                        temp.Previous();

                        while (temp.IsInBounds &&
                               (temp.PrototypeParsingType == PrototypeParsingType.Type ||
                                temp.PrototypeParsingType == PrototypeParsingType.TypeQualifier))
                        {
                            symbolStart = temp;
                            temp.Previous();
                        }
                    }

                    if (extendTypeSearch && symbolEnd == end)
                    {
                        while (symbolEnd.IsInBounds &&
                               (symbolEnd.PrototypeParsingType == PrototypeParsingType.Type ||
                                symbolEnd.PrototypeParsingType == PrototypeParsingType.TypeQualifier))
                        {
                            symbolEnd.Next();
                        }
                    }


                    // Built in types don't get links

                    if (language.IsBuiltInType(symbolStart, symbolEnd))
                    {
                        AppendSyntaxHighlightedText(textStart, textEnd, output);
                    }

                    else
                    {
                        // Create a link object with the identifying properties needed to look it up in the list of links.

                        Link linkStub = new Link();
                        linkStub.Type        = LinkType.Type;
                        linkStub.Symbol      = SymbolString.FromPlainText_NoParameters(symbolStart.TextBetween(symbolEnd));
                        linkStub.Context     = Context.Topic.PrototypeContext;
                        linkStub.ContextID   = Context.Topic.PrototypeContextID;
                        linkStub.FileID      = Context.Topic.FileID;
                        linkStub.ClassString = Context.Topic.ClassString;
                        linkStub.ClassID     = Context.Topic.ClassID;
                        linkStub.LanguageID  = Context.Topic.LanguageID;


                        // Find the actual link so we know if it resolved to anything.

                        Link fullLink = null;

                        foreach (Link link in links)
                        {
                            if (link.SameIdentifyingPropertiesAs(linkStub))
                            {
                                fullLink = link;
                                break;
                            }
                        }

                                                #if DEBUG
                        if (fullLink == null)
                        {
                            throw new Exception("All links in a topic must be in the list passed to AppendSyntaxtHighlightedTextWithTypeLinks.");
                        }
                                                #endif


                        // If it didn't resolve, we just output the original text.

                        if (!fullLink.IsResolved)
                        {
                            AppendSyntaxHighlightedText(textStart, textEnd, output);
                        }

                        else
                        {
                            // If it did resolve, find Topic it resolved to.

                            Topics.Topic targetTopic = null;

                            foreach (var linkTarget in linkTargets)
                            {
                                if (linkTarget.TopicID == fullLink.TargetTopicID)
                                {
                                    targetTopic = linkTarget;
                                    break;
                                }
                            }

                                                        #if DEBUG
                            if (targetTopic == null)
                            {
                                throw new Exception("All links targets for a topic must be in the list passed to AppendSyntaxtHighlightedTextWithTypeLinks.");
                            }
                                                        #endif

                            AppendOpeningLinkTag(targetTopic, output);
                            AppendSyntaxHighlightedText(textStart, textEnd, output);
                            output.Append("</a>");
                        }
                    }

                    iterator = textEnd;
                }

                else                 // not on a type
                {
                    TokenIterator startText = iterator;

                    do
                    {
                        iterator.Next();
                    }while (iterator < end &&
                            iterator.PrototypeParsingType != PrototypeParsingType.Type &&
                            iterator.PrototypeParsingType != PrototypeParsingType.TypeQualifier);

                    AppendSyntaxHighlightedText(startText, iterator, output);
                }
            }
        }
Esempio n. 7
0
        // Group: Parameter Functions
        // __________________________________________________________________________


        /* Function: RecalculateParameters
         * Scans this section for <PrototypeParsingType.StartOfParams>, <PrototypeParsingType.EndOfParams>, and
         * <PrototypeParsingTypes.ParamSeparator> tokens to determine how many parameters there are and allow easy access to them
         * individually.  This is automatically called by the constructor so you only need to call this manually if you made changes to these
         * token types after creating this object.
         */
        public void RecalculateParameters()
        {
            TokenIterator iterator = start;


            // Before parameters

            while (iterator < end &&
                   iterator.PrototypeParsingType != PrototypeParsingType.StartOfParams)
            {
                iterator.Next();
            }

            if (iterator.PrototypeParsingType == PrototypeParsingType.StartOfParams)
            {
                iterator.Next();
            }

            beforeParameters = new Section(start, iterator);

            // Only trim whitespace if it's insignificant
            if (iterator.FundamentalType == FundamentalType.Whitespace &&
                iterator.PrototypeParsingType == PrototypeParsingType.Null)
            {
                iterator.Next();
            }


            // Count the parameters so we don't allocate more memory than we need for the list.  Also, there may not be any parameters
            // at all since it could be a pair of empty parentheses.

            if (iterator < end &&
                iterator.PrototypeParsingType != PrototypeParsingType.EndOfParams)
            {
                TokenIterator startOfFirstParam = iterator;
                int           paramCount        = 1;

                do
                {
                    if (iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                    {
                        paramCount++;
                    }

                    iterator.Next();
                }while (iterator < end &&
                        iterator.PrototypeParsingType != PrototypeParsingType.EndOfParams);


                // Get the actual parameters

                parameters = new List <Section>(paramCount);

                iterator = startOfFirstParam;
                TokenIterator startOfParam = iterator;

                for (;;)
                {
                    if (iterator >= end ||
                        iterator.PrototypeParsingType == PrototypeParsingType.EndOfParams)
                    {
                        TokenIterator lookbehind = iterator;
                        lookbehind.Previous();

                        if (lookbehind.FundamentalType == FundamentalType.Whitespace &&
                            lookbehind.PrototypeParsingType == PrototypeParsingType.Null &&
                            lookbehind >= startOfParam)
                        {
                            parameters.Add(new Section(startOfParam, lookbehind));
                        }
                        else
                        {
                            parameters.Add(new Section(startOfParam, iterator));
                        }

                        break;
                    }
                    else if (iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                    {
                        iterator.Next();
                        parameters.Add(new Section(startOfParam, iterator));

                        if (iterator.FundamentalType == FundamentalType.Whitespace &&
                            iterator.PrototypeParsingType == PrototypeParsingType.Null)
                        {
                            iterator.Next();
                        }

                        startOfParam = iterator;
                    }
                    else
                    {
                        iterator.Next();
                    }
                }
            }


            // After parameters

            if (iterator < end)
            {
                afterParameters = new Section(iterator, end);
            }


            // Parameter style

            // Set to null so it recalculates on next use rather than doing it preemptively
            parameterStyle = null;
        }
Esempio n. 8
0
        /* Function: GetJavadocLinkSymbol
         * Returns the symbol part of a @see or {@link} tag and moves the iterator past it.
         */
        protected string GetJavadocLinkSymbol(ref TokenIterator iterator)
        {
            StringBuilder symbol = new StringBuilder();

            // In Javadoc, spaces are only allowed in parentheses.  We're going to go further and allow them in any braces to support
            // templates and other languages.  However, for angle brackets they must be preceded by a comma.  This allows
            // "Template<A, B>" to be supported while not getting tripped on "operator<".

            // Most symbols won't have braces so create this on demand.
            SafeStack <char> braceStack = null;

            while (iterator.IsInBounds)
            {
                if (iterator.Character == '(' ||
                    iterator.Character == '[' ||
                    iterator.Character == '{' ||
                    iterator.Character == '<')
                {
                    if (braceStack == null)
                    {
                        braceStack = new SafeStack <char>();
                    }

                    braceStack.Push(iterator.Character);
                    symbol.Append(iterator.Character);
                }

                else if ((iterator.Character == ')' && braceStack != null && braceStack.Peek() == '(') ||
                         (iterator.Character == ']' && braceStack != null && braceStack.Peek() == '[') ||
                         (iterator.Character == '}' && braceStack != null && braceStack.Peek() == '{') ||
                         (iterator.Character == '>' && braceStack != null && braceStack.Peek() == '<'))
                {
                    braceStack.Pop();
                    symbol.Append(iterator.Character);
                }
                else if (iterator.Character == '}' && (braceStack == null || braceStack.Contains('{') == false))
                {
                    // If we're at an unopened closing brace we're probably at the end of a {@link}.  We check if the stack contains an
                    // opening brace instead of checking whether it's empty to ignore any possible opening angle brackets that could
                    // screw us up like "operator<".
                    break;
                }
                else if (iterator.FundamentalType == FundamentalType.Text ||
                         iterator.FundamentalType == FundamentalType.Symbol)
                {
                    iterator.AppendTokenTo(symbol);
                }
                else if (iterator.FundamentalType == FundamentalType.Whitespace)
                {
                    if (braceStack == null || braceStack.Count == 0)
                    {
                        break;
                    }
                    else if (braceStack.Peek() == '<')
                    {
                        TokenIterator lookbehind = iterator;
                        lookbehind.Previous();

                        if (lookbehind.Character == ',')
                        {
                            iterator.AppendTokenTo(symbol);
                        }
                        else
                        {
                            break;
                        }
                    }
                    else
                    {
                        iterator.AppendTokenTo(symbol);
                    }
                }
                else                 // line break
                {
                    break;
                }

                iterator.Next();
            }

            // Javadoc uses Class.Class#Member.  First remove leading hashes to handle just #Member
            while (symbol.Length > 0 && symbol[0] == '#')
            {
                symbol.Remove(0, 1);
            }

            // Convert any remaining hashes to dots.  Ideally we would use the language's native member operator but it's not
            // easy to get it here.
            return(symbol.ToString().Replace('#', '.'));
        }
Esempio n. 9
0
        /* Function: ParsePrototype
         * Converts a raw text prototype into a <ParsedPrototype>.
         */
        override public ParsedPrototype ParsePrototype(string stringPrototype, int commentTypeID)
        {
            Tokenizer       tokenizedPrototype = new Tokenizer(stringPrototype, tabWidth: EngineInstance.Config.TabWidth);
            ParsedPrototype parsedPrototype;


            // Mark any leading decorators.

            TokenIterator iterator = tokenizedPrototype.FirstToken;

            TryToSkipWhitespace(ref iterator, true, ParseMode.ParsePrototype);

            if (TryToSkipDecorators(ref iterator, ParseMode.ParsePrototype))
            {
                TryToSkipWhitespace(ref iterator, true, ParseMode.ParsePrototype);
            }


            // Search for the first opening bracket or brace.

            char closingBracket = '\0';

            while (iterator.IsInBounds)
            {
                if (iterator.Character == '(')
                {
                    closingBracket = ')';
                    break;
                }
                else if (iterator.Character == '[')
                {
                    // Only treat brackets as parameters if it's following "this", meaning it's an iterator.  Ignore all others so we
                    // don't get tripped up on metadata or array brackets on return values.

                    TokenIterator lookbehind = iterator;
                    lookbehind.Previous();
                    lookbehind.PreviousPastWhitespace(PreviousPastWhitespaceMode.Iterator);

                    if (lookbehind.MatchesToken("this"))
                    {
                        closingBracket = ']';
                        break;
                    }
                    else
                    {
                        iterator.Next();
                    }
                }
                else if (iterator.Character == '{')
                {
                    closingBracket = '}';
                    break;
                }
                else if (TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator))
                {
                }
                else
                {
                    iterator.Next();
                }
            }


            // If we found brackets, it's either a function prototype or a class prototype that includes members.
            // Mark the delimiters.

            if (closingBracket != '\0')
            {
                iterator.PrototypeParsingType = PrototypeParsingType.StartOfParams;
                iterator.Next();

                while (iterator.IsInBounds)
                {
                    if (iterator.Character == ',')
                    {
                        iterator.PrototypeParsingType = PrototypeParsingType.ParamSeparator;
                        iterator.Next();
                    }

                    else if (iterator.Character == closingBracket)
                    {
                        iterator.PrototypeParsingType = PrototypeParsingType.EndOfParams;
                        break;
                    }

                    // Unlike prototype detection, here we treat < as an opening bracket.  Since we're already in the parameter list
                    // we shouldn't run into it as part of an operator overload, and we need it to not treat the comma in "template<a,b>"
                    // as a parameter divider.
                    else if (TryToSkipComment(ref iterator) ||
                             TryToSkipString(ref iterator) ||
                             TryToSkipBlock(ref iterator, true))
                    {
                    }

                    else
                    {
                        iterator.Next();
                    }
                }


                // We have enough tokens marked to create the parsed prototype.  This will also let us iterate through the parameters
                // easily.

                parsedPrototype = new ParsedPrototype(tokenizedPrototype, supportsImpliedTypes: false);


                // Set the main section to the last one, since any decorators present will each be in their own section.  Some can have
                // parameter lists and we don't want those confused for the actual parameter list.

                parsedPrototype.MainSectionIndex = parsedPrototype.Sections.Count - 1;


                // Mark the part before the parameters, which includes the name and return value.

                TokenIterator start, end;
                parsedPrototype.GetBeforeParameters(out start, out end);

                // Exclude the opening bracket
                end.Previous();
                end.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, start);

                if (start < end)
                {
                    MarkPascalParameter(start, end);
                }


                // If there are any parameters, mark the tokens in them.

                if (parsedPrototype.NumberOfParameters > 0)
                {
                    for (int i = 0; i < parsedPrototype.NumberOfParameters; i++)
                    {
                        parsedPrototype.GetParameter(i, out start, out end);
                        MarkPascalParameter(start, end);
                    }
                }
            }


            // If there's no brackets, it's a variable, property, or class.

            else
            {
                parsedPrototype = new ParsedPrototype(tokenizedPrototype);
                TokenIterator start = tokenizedPrototype.FirstToken;
                TokenIterator end   = tokenizedPrototype.LastToken;

                MarkPascalParameter(start, end);
            }

            return(parsedPrototype);
        }
Esempio n. 10
0
        /* Function: TryToGetBlockComment
         *
         * If the iterator is on a line that starts with the opening symbol of a block comment, 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 an opening comment symbol it will return false and leave the iterator where it is.
         */
        protected bool TryToGetBlockComment(ref LineIterator lineIterator, out PossibleDocumentationComment comment)
        {
            TokenIterator firstToken, endOfLine;

            lineIterator.GetBounds(LineBoundsMode.ExcludeWhitespace, out firstToken, out endOfLine);


            // Are we on a block comment?

            TokenIterator lookahead = firstToken;
            string        closingSymbol;

            if (TryToSkipOpeningBlockCommentSymbol(ref lookahead, out closingSymbol) == false)
            {
                comment = null;
                return(false);
            }


            // We are.  Create a possible documentation comment.

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


            // Check if we're on a Javadoc comment, which will be an extra [.

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

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


            // Find the end of the comment, which could be on the same line as the start.

            var  tokenizer         = lineIterator.Tokenizer;
            var  lineLookahead     = lineIterator;
            bool hadTrailingDashes = false;

            for (;;)
            {
                TokenIterator closingSymbolIterator;

                if (tokenizer.FindTokensBetween(closingSymbol, false, firstToken, endOfLine, out closingSymbolIterator) == true)
                {
                    // Move past the end of the comment regardless of whether it's acceptable for documentation or not
                    lineLookahead.Next();

                    // Make sure nothing appears after the closing symbol on the line
                    closingSymbolIterator.NextByCharacters(closingSymbol.Length);

                    // We'll allow -- though since some people use --[[ and ]]-- for balance even though the latter is actually the
                    // closing comment symbol followed by a line comment.
                    if (closingSymbolIterator.MatchesAcrossTokens("--"))
                    {
                        hadTrailingDashes = true;
                        closingSymbolIterator.Next(2);
                    }

                    closingSymbolIterator.NextPastWhitespace();

                    if (closingSymbolIterator.FundamentalType != FundamentalType.LineBreak &&
                        closingSymbolIterator.FundamentalType != FundamentalType.Null)
                    {
                        comment = null;
                    }
                    else
                    {
                        comment.End = lineLookahead;
                    }

                    break;
                }

                lineLookahead.Next();

                // If we're not in bounds that means there was an unclosed comment at the end of the file.  Skip it but don't treat
                // it as a documentation candidate.
                if (!lookahead.IsInBounds)
                {
                    comment = null;
                    break;
                }

                lineLookahead.GetBounds(LineBoundsMode.ExcludeWhitespace, out firstToken, out endOfLine);
            }


            if (comment != null)
            {
                // Mark the symbols before returning

                firstToken = comment.Start.FirstToken(LineBoundsMode.ExcludeWhitespace);
                lookahead  = firstToken;
                TryToSkipOpeningBlockCommentSymbol(ref lookahead, out closingSymbol);

                if (comment.Javadoc)
                {
                    lookahead.Next();
                }

                firstToken.SetCommentParsingTypeBetween(lookahead, CommentParsingType.CommentSymbol);

                LineIterator lastLine = comment.End;
                lastLine.Previous();
                lastLine.GetBounds(LineBoundsMode.ExcludeWhitespace, out firstToken, out endOfLine);

                lookahead = endOfLine;

                if (hadTrailingDashes)
                {
                    lookahead.Previous(2);
                }

                lookahead.PreviousByCharacters(closingSymbol.Length);

                lookahead.SetCommentParsingTypeBetween(endOfLine, CommentParsingType.CommentSymbol);
            }

            // If we made it this far that means we found a comment and can move the line iterator and return true.  Whether
            // that comment was suitable for documentation will be determined by the comment variable, but we are moving the
            // iterator and returning true either way.
            lineIterator = lineLookahead;
            return(true);
        }
Esempio n. 11
0
        /* Function: MarkParameter
         * Marks the tokens in the parameter specified by the bounds with <PrototypeParsingTypes>.
         */
        protected void MarkParameter(TokenIterator start, TokenIterator end)
        {
            // Pass 1: Count the number of "words" in the parameter prior to the default value and mark the default value
            // separator.  We'll figure out how to interpret the words in the second pass.

            int           words    = 0;
            TokenIterator iterator = start;

            while (iterator < end)
            {
                // Default values

                if (iterator.Character == '=')
                {
                    iterator.PrototypeParsingType = PrototypeParsingType.DefaultValueSeparator;
                    iterator.Next();

                    iterator.NextPastWhitespace(end);
                    TokenIterator endOfDefaultValue = end;

                    TokenIterator lookbehind = endOfDefaultValue;
                    lookbehind.Previous();

                    while (lookbehind >= iterator && lookbehind.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                    {
                        endOfDefaultValue = lookbehind;
                        lookbehind.Previous();
                    }

                    endOfDefaultValue.PreviousPastWhitespace(PreviousPastWhitespaceMode.EndingBounds, iterator);

                    if (iterator < endOfDefaultValue)
                    {
                        iterator.SetPrototypeParsingTypeBetween(endOfDefaultValue, PrototypeParsingType.DefaultValue);
                    }

                    break;
                }


                // Param separator

                else if (iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                {
                    break;
                }


                // "Words" we're interested in

                else if (TryToSkipTypeOrVarName(ref iterator, end) ||
                         TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator) ||
                         TryToSkipBlock(ref iterator, true))
                {
                    // If there was a comment in the prototype, that means it specifically wasn't filtered out because it was something
                    // significant like a Splint comment or /*out*/.  Treat it like a modifier.

                    // Strings don't really make sense in the prototype until the default value, but we need the parser to handle it anyway
                    // just so it doesn't lose its mind if one occurs.

                    // If we come across a block that doesn't immediately follow an identifier, it may be something like a C# property so
                    // treat it as a modifier.

                    words++;
                }


                // Whitespace and any unexpected random symbols

                else
                {
                    iterator.Next();
                }
            }


            // Pass 2: Mark the "words" we counted from the first pass.  The order of words goes [modifier] [modifier] [type] [name],
            // starting from the right.  Typeless languages that only have one word will have it correctly interpreted as the name.

            iterator = start;
            TokenIterator wordStart, wordEnd;

            while (iterator < end)
            {
                wordStart = iterator;
                bool foundWord  = false;
                bool foundBlock = false;

                if (iterator.PrototypeParsingType == PrototypeParsingType.DefaultValueSeparator ||
                    iterator.PrototypeParsingType == PrototypeParsingType.ParamSeparator)
                {
                    break;
                }
                else if (TryToSkipTypeOrVarName(ref iterator, end))
                {
                    foundWord = true;
                }
                else if (TryToSkipComment(ref iterator) ||
                         TryToSkipString(ref iterator) ||
                         TryToSkipBlock(ref iterator, true))
                {
                    foundWord  = true;
                    foundBlock = true;
                }
                else
                {
                    iterator.Next();
                }

                // Process the word we found
                if (foundWord)
                {
                    wordEnd = iterator;

                    if (words >= 3)
                    {
                        if (foundBlock && wordEnd.TokenIndex - wordStart.TokenIndex >= 2)
                        {
                            wordStart.PrototypeParsingType = PrototypeParsingType.OpeningTypeModifier;

                            TokenIterator lookbehind = wordEnd;
                            lookbehind.Previous();
                            lookbehind.PrototypeParsingType = PrototypeParsingType.ClosingTypeModifier;
                        }
                        else
                        {
                            wordStart.SetPrototypeParsingTypeBetween(wordEnd, PrototypeParsingType.TypeModifier);
                        }
                    }
                    else if (words == 2)
                    {
                        MarkType(wordStart, wordEnd);
                    }
                    else if (words == 1)
                    {
                        MarkName(wordStart, wordEnd);

                        // Change the $ at the beginning of the name from a param modifier to part of the name
                        if (wordStart.Character == '$')
                        {
                            wordStart.PrototypeParsingType = PrototypeParsingType.Name;
                        }
                    }

                    words--;
                }
            }
        }