public override string OutputOf(IList <Topic> topics) { if (topics == null || topics.Count == 0) { return("(No topics found)"); } StringBuilder output = new StringBuilder(); for (int topicIndex = 0; topicIndex < topics.Count; topicIndex++) { if (topicIndex != 0) { output.AppendLine(); output.AppendLine("------------------------------"); output.AppendLine(); } if (topics[topicIndex].Prototype == null) { output.AppendLine("(No prototype detected)"); continue; } var parsedPrototype = topics[topicIndex].ParsedPrototype; for (int sectionIndex = 0; sectionIndex < parsedPrototype.Sections.Count; sectionIndex++) { if (sectionIndex != 0) { output.AppendLine(); } if (parsedPrototype.Sections[sectionIndex] is Prototypes.ParameterSection) { Prototypes.ParameterSection section = (parsedPrototype.Sections[sectionIndex] as Prototypes.ParameterSection); output.AppendLine("- Parameter Section:"); TokenIterator start, end; section.GetBeforeParameters(out start, out end); output.AppendLine(" - Before Parameters: " + start.TextBetween(end)); output.AppendLine(" - Access Level: " + section.GetAccessLevel()); output.Append(" - Link Candidates: "); AppendLinkCandidates(start, end, output); output.AppendLine(); for (int paramIndex = 0; paramIndex < section.NumberOfParameters; paramIndex++) { output.AppendLine(); section.GetParameterBounds(paramIndex, out start, out end); output.AppendLine(" - Parameter " + (paramIndex + 1) + ": " + start.TextBetween(end)); if (section.GetParameterName(paramIndex, out start, out end)) { output.AppendLine(" - Name: " + start.TextBetween(end)); } else { output.AppendLine(" - Name: (not detected)"); } string fullType = null; if (section.BuildFullParameterType(paramIndex, out start, out end, false)) { fullType = start.TextBetween(end); } string impliedType = null; if (section.BuildFullParameterType(paramIndex, out start, out end, true)) { impliedType = start.TextBetween(end); } if (fullType != null) { output.AppendLine(" - Full Type: " + fullType); } if (impliedType != null) { if (fullType == null) { output.AppendLine(" - Full Type (implied): " + impliedType); } else if (impliedType != fullType) { output.AppendLine(" - Full Type (plus implied): " + impliedType); } } if (fullType == null && impliedType == null) { output.AppendLine(" - Full Type: (not detected)"); } if (section.GetBaseParameterType(paramIndex, out start, out end, false)) { output.AppendLine(" - Base Type: " + start.TextBetween(end)); } else if (section.GetBaseParameterType(paramIndex, out start, out end, true)) { output.AppendLine(" - Base Type (implied): " + start.TextBetween(end)); } else { output.AppendLine(" - Base Type: (not detected)"); } section.GetParameterBounds(paramIndex, out start, out end); output.Append(" - Link Candidates: "); AppendLinkCandidates(start, end, output); output.AppendLine(); if (section.GetParameterDefaultValue(paramIndex, out start, out end)) { output.AppendLine(" - Default Value: " + start.TextBetween(end)); } else { output.AppendLine(" - Default Value: (not detected)"); } } if (section.GetAfterParameters(out start, out end)) { output.AppendLine(); output.AppendLine(" - After Parameters: " + start.TextBetween(end)); output.Append(" - Link Candidates: "); AppendLinkCandidates(start, end, output); output.AppendLine(); } } else // Plain section { Prototypes.Section section = parsedPrototype.Sections[sectionIndex]; output.AppendLine("- Plain Section: " + section.Start.TextBetween(section.End)); output.AppendLine(" - Access Level: " + section.GetAccessLevel()); output.Append(" - Link Candidates: "); AppendLinkCandidates(section.Start, section.End, output); output.AppendLine(); } } } return(output.ToString()); }
// 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; } } } } }