/// <summary> /// Writes comments for function parameters. /// </summary> /// <param name="sb">String builder to write comments into.</param> /// <param name="spaces">Indentation spaces.</param> /// <param name="codeElement">Function code element.</param> /// <param name="parsedComment">Parsed existing comment, if any.</param> private void WriteTemplateParamComments(StringBuilder sb, string spaces, CodeElement codeElement, ParsedComment parsedComment) { ThreadHelper.ThrowIfNotOnUIThread(); // Parse template parameters from the full function name. string[] tparams = ParseTemplateParams(codeElement.FullName); if (tparams.Length == 0) { return; } // Calculate maximum template parameter name length. int maxParamNameLength = 0; foreach (string tparamName in tparams) { maxParamNameLength = Math.Max(maxParamNameLength, tparamName.Length); } // Create doxygen lines for each parameter. sb.Append("\r\n" + spaces + " *"); foreach (string tparamName in tparams) { // Check if the existing comment contained this parameter. ParsedParam parsedParam = null; if (parsedComment.TemplateParameters.ContainsKey(tparamName)) { parsedParam = parsedComment.TemplateParameters[tparamName]; } string paramAlignSpaces = new string(' ', maxParamNameLength - tparamName.Length + 1); string tagLine = m_indentString + Config.TagChar + "tparam " + tparamName + paramAlignSpaces; sb.Append("\r\n" + spaces + " * " + tagLine); // Add existing comments. if (parsedParam != null) { AppendComments(sb, parsedParam.Comments, spaces, tagLine.Length); } // TODO: Any smart comments possible? } }
/// <summary> /// Determines parameter direction based on the code element and the previously parsed parameter comment line. /// </summary> /// <param name="function">Parent function.</param> /// <param name="param">Code element for the parameter.</param> /// <param name="parsedParam">Existing parsed parameter info, if available.</param> /// <returns>The parameter direction.</returns> private ParamDirection GetParamDirection(CodeFunction function, CodeParameter param, ParsedParam parsedParam) { ThreadHelper.ThrowIfNotOnUIThread(); ParamDirection direction = ParamDirection.In; bool isConstructor = (function.FunctionKind & vsCMFunction.vsCMFunctionConstructor) != 0; // By default trust the user if an existing direction is found. if (parsedParam != null) { direction = parsedParam.Direction; } // Constructor assumes inputs only. Otherwise we check the parameter data type to try to determine // the appropriate direction. else if (!isConstructor && !IsInput(param)) { direction = Config.DefaultNonConstReferenceDirection; } return(direction); }
/// <summary> /// Parses the given Doxygen comment. /// </summary> /// <param name="comment">The comment to parse.</param> /// <returns>Parsed comment structure.</returns> private ParsedComment ParseComment(string comment) { ParsedComment parsedComment = new ParsedComment(); if (comment.Length > 0) { string[] lines = comment.Split("\r\n".ToCharArray(), StringSplitOptions.RemoveEmptyEntries); // Trim leading and trailing whitespace before any parsing. for (int i = 0; i < lines.Length; ++i) { lines[i] = lines[i].Trim(); } for (int i = 0; i < lines.Length; ++i) { // Skip empty lines and comment start/end lines. string line = lines[i]; if (line.Length == 0 || line == "*" || line == "/*!" || line == "*/") { continue; } // Check if this is a template parameter line. Match tparamMatch = m_regexTParam.Match(line); if (tparamMatch.Success) { string name = tparamMatch.Groups[1].Value; string firstComment = tparamMatch.Groups[2].Value; if (!parsedComment.TemplateParameters.ContainsKey(name) && firstComment.Length > 0) { ParsedParam param = new ParsedParam(); param.Name = name; param.Comments.Add(firstComment); i = ParseExtraComments(lines, i + 1, param.Comments); parsedComment.TemplateParameters.Add(param.Name, param); } } else { // Check if this is a parameter line. Match paramMatch = m_regexParam.Match(line); if (paramMatch.Success) { string name = paramMatch.Groups[2].Value; string firstComment = paramMatch.Groups[3].Value; if (!parsedComment.Parameters.ContainsKey(name) && firstComment.Length > 0) { ParsedParam param = new ParsedParam(); param.Name = name; param.Direction = ToDirection(paramMatch.Groups[1].Value); param.Comments.Add(firstComment); i = ParseExtraComments(lines, i + 1, param.Comments); parsedComment.Parameters.Add(param.Name, param); } } else { // Otherwise check if it is some other tag. Match sectionMatch = m_regexTagSection.Match(line); if (sectionMatch.Success) { string tagName = sectionMatch.Groups[1].Value; string firstComment = sectionMatch.Groups[2].Value; if (firstComment.Length > 0) { ParsedSection section = new ParsedSection(); section.TagName = tagName; section.Comments.Add(firstComment); i = ParseExtraComments(lines, i + 1, section.Comments); if (section.TagName == "return" || section.TagName == "returns") { parsedComment.Returns = section; } else { parsedComment.TagSections.Add(section); } } } else { // If the line doesn't contain any tag, we try to extract text out of it. Match textMatch = m_regexText.Match(line); if (textMatch.Success) { parsedComment.BriefComments.Add(textMatch.Groups[1].Value); } } } } } } return(parsedComment); }
/// <summary> /// Writes comments for function parameters. /// </summary> /// <param name="sb">String builder to write comments into.</param> /// <param name="spaces">Indentation spaces.</param> /// <param name="codeElement">Function code element.</param> /// <param name="parsedComment">Parsed existing comment, if any.</param> private void WriteParamComments(StringBuilder sb, string spaces, CodeFunction function, ParsedComment parsedComment) { ThreadHelper.ThrowIfNotOnUIThread(); int maxTypeDirectionLength = 0; int maxParamNameLength = 0; foreach (CodeElement child in function.Children) { CodeParameter param = child as CodeParameter; if (param != null) { // Check if the existing comment contained this parameter. ParsedParam parsedParam = null; if (parsedComment.Parameters.ContainsKey(param.Name)) { parsedParam = parsedComment.Parameters[param.Name]; } string typeDirName = DirectionToString(GetParamDirection(function, param, parsedParam)); maxTypeDirectionLength = Math.Max(maxTypeDirectionLength, typeDirName.Length); maxParamNameLength = Math.Max(maxParamNameLength, param.Name.Length); } } // Create doxygen lines for each parameter. if (function.Children.Count > 0) { sb.Append("\r\n" + spaces + " *"); foreach (CodeElement child in function.Children) { CodeParameter param = child as CodeParameter; if (param != null) { // Check if the existing comment contained this parameter. ParsedParam parsedParam = null; if (parsedComment.Parameters.ContainsKey(param.Name)) { parsedParam = parsedComment.Parameters[param.Name]; } // Determine type of parameter (in, out or inout). string typeDirName = DirectionToString(GetParamDirection(function, param, parsedParam)); string paramAlignSpaces = new string(' ', maxParamNameLength - param.Name.Length + 1); string typeAlignSpaces = new string(' ', maxTypeDirectionLength - typeDirName.Length + 1); string tagLine = m_indentString + Config.TagChar + "param " + typeDirName + typeAlignSpaces + param.Name + paramAlignSpaces; sb.Append("\r\n" + spaces + " * " + tagLine); // Add existing comments. if (parsedParam != null) { AppendComments(sb, parsedParam.Comments, spaces, tagLine.Length); } else if (Config.SmartComments && function.Children.Count == 1) { sb.Append(TryGenerateParamDesc(function, param)); } } } } }