summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.json10
-rw-r--r--src/CodeParser/CParser/Argument.ts6
-rw-r--r--src/CodeParser/CParser/CppParser.ts16
-rw-r--r--src/CodeParser/CParser/ParseTree.ts121
-rw-r--r--src/CodeParserController.ts (renamed from src/CodeParser/CodeParserController.ts)27
-rw-r--r--src/Common/ICodeParser.ts (renamed from src/CodeParser/CodeParser.ts)6
-rw-r--r--src/Common/IDocGen.ts (renamed from src/DocGen/DocGen.ts)0
-rw-r--r--src/Config.ts57
-rw-r--r--src/DocGen/CGen.ts185
-rw-r--r--src/DocGen/CppGen.ts6
-rw-r--r--src/Lang/C/CArgument.ts6
-rw-r--r--src/Lang/C/CDocGen.ts183
-rw-r--r--src/Lang/C/CParseTree.ts121
-rw-r--r--src/Lang/C/CParser.ts (renamed from src/CodeParser/CParser/CParser.ts)293
-rw-r--r--src/Lang/C/CToken.ts (renamed from src/CodeParser/CParser/Token.ts)15
-rw-r--r--src/extension.ts2
-rw-r--r--src/test/CTests/Attributes.test.ts (renamed from src/test/Attributes.test.ts)15
-rw-r--r--src/test/CTests/FunctionPointer.test.ts (renamed from src/test/FunctionPointer.test.ts)10
-rw-r--r--src/test/CTests/Operators.test.ts256
-rw-r--r--src/test/CTests/ReturnTypes.test.ts (renamed from src/test/ReturnTypes.test.ts)14
-rw-r--r--src/test/CTests/Templates.test.ts (renamed from src/test/Templates.test.ts)17
-rw-r--r--src/test/CTests/TestSetup.ts (renamed from src/test/tools/TestSetup.ts)24
-rw-r--r--src/test/CTests/TrailingReturns.test.ts (renamed from src/test/TrailingReturns.test.ts)2
-rw-r--r--src/test/Operators.test.ts38
-rw-r--r--src/test/Variadic.test.ts38
25 files changed, 819 insertions, 649 deletions
diff --git a/package.json b/package.json
index 041abf3..67b83b8 100644
--- a/package.json
+++ b/package.json
@@ -59,6 +59,16 @@
"type": "boolean",
"default": true
},
+ "doxdocgen.generic.boolReturnsTrueFalse": {
+ "description": "If this is enabled a bool return value will be split into true and false return param.",
+ "type": "boolean",
+ "default": true
+ },
+ "doxdocgen.generic.boolPointerReturnsNull": {
+ "description": "If this is enabled a pointer to a bool return value will include a null return param.",
+ "type": "boolean",
+ "default": true
+ },
"doxdocgen.generic.briefTemplate": {
"description": "The template of the brief DoxyGen line that is generated. If empty it won't get generated at all.",
"type": "string",
diff --git a/src/CodeParser/CParser/Argument.ts b/src/CodeParser/CParser/Argument.ts
deleted file mode 100644
index 4cd793d..0000000
--- a/src/CodeParser/CParser/Argument.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { ParseTree } from "./ParseTree";
-
-export class Argument {
- public Name: string = undefined;
- public Type: ParseTree = new ParseTree();
-}
diff --git a/src/CodeParser/CParser/CppParser.ts b/src/CodeParser/CParser/CppParser.ts
deleted file mode 100644
index b3279c6..0000000
--- a/src/CodeParser/CParser/CppParser.ts
+++ /dev/null
@@ -1,16 +0,0 @@
-import { Position, TextDocumentContentChangeEvent, TextEditor, TextLine } from "vscode";
-import Generator from "../../DocGen/CGen";
-import { IDocGen } from "../../DocGen/DocGen";
-import CParser from "./CParser";
-
-/**
- *
- * Parses C++ code for methods and signatures
- *
- * @export
- * @class CppParser
- * @implements {ICodeParser}
- */
-export default class CppParser extends CParser {
- // For now C++ is the same as C
-}
diff --git a/src/CodeParser/CParser/ParseTree.ts b/src/CodeParser/CParser/ParseTree.ts
deleted file mode 100644
index bec5b91..0000000
--- a/src/CodeParser/CParser/ParseTree.ts
+++ /dev/null
@@ -1,121 +0,0 @@
-import { Token, TokenType } from "./Token";
-
-export class ParseTree {
-
- /**
- * Create a tree from tokens. This consumes the tokens.
- * @param tokens The tokens to create a tree for.
- * @param inNested If currently allready nesting.
- */
- public static CreateTree(tokens: Token[], inNested: boolean = false): ParseTree {
- const tree: ParseTree = new ParseTree();
-
- while (tokens.length > 0) {
- const token: Token = tokens.shift();
- switch (token.Type) {
- case TokenType.OpenParenthesis:
- tree.nodes.push(this.CreateTree(tokens, true));
- break;
- case TokenType.CloseParenthesis:
- if (inNested === false) {
- throw new Error("Unmatched closing parenthesis.");
- }
- return tree;
- default:
- tree.nodes.push(token);
- break;
- }
- }
-
- if (inNested === true) {
- throw new Error("No match found for an opening parenthesis.");
- }
-
- return tree;
- }
-
- public nodes: Array<Token | ParseTree> = [];
-
- /**
- * Compact empty branches. Example ((foo))(((bar))) will become (foo)(bar)
- * @param tree The ParseTree to compact. Defaults to the current tree.
- */
- public Compact(tree: ParseTree = this): ParseTree {
- const newTree: ParseTree = new ParseTree();
- newTree.nodes = tree.nodes.map((n) => n);
- const isNotCompact = (n) => n instanceof ParseTree && n.nodes.length === 1 && n.nodes[0] instanceof ParseTree;
-
- // Compact current level of nodes to the maximum amount.
- while (newTree.nodes.some((n) => isNotCompact(n))) {
- newTree.nodes = newTree.nodes
- .map((n) => n instanceof ParseTree && isNotCompact(n) ? n.nodes[0] : n);
- }
-
- // Compact all nested parsetrees.
- newTree.nodes = newTree.nodes
- .map((n) => n instanceof ParseTree ? this.Compact(n) : n);
-
- return newTree;
- }
-
- /**
- * Copy parsetree.
- * @param tree The ParseTree to compact. Defaults to the current tree.
- */
- public Copy(tree: ParseTree = this): ParseTree {
- const newTree: ParseTree = new ParseTree();
- newTree.nodes = tree.nodes
- .map((n) => n instanceof Token ? n : this.Copy(n));
- return newTree;
- }
-
- /**
- * Create string from the parsetree which is a representation of the original code.
- * @param tree The ParseTree to compact. Defaults to the current tree.
- */
- public Yield(tree: ParseTree = this): string {
- let code: string = "";
-
- for (const node of tree.nodes) {
- if (node instanceof ParseTree) {
- code += "(" + this.Yield(node) + ")";
- continue;
- }
-
- switch (node.Type) {
- case TokenType.Symbol:
- code += code === "" ? node.Value : " " + node.Value;
- break;
- case TokenType.Pointer:
- code += node.Value;
- break;
- case TokenType.Reference:
- code += node.Value;
- break;
- case TokenType.ArraySubscript:
- code += node.Value;
- break;
- case TokenType.CurlyBlock:
- code += node.Value;
- break;
- case TokenType.Assignment:
- code += " " + node.Value;
- break;
- case TokenType.Comma:
- code += node.Value;
- break;
- case TokenType.Arrow:
- code += " " + node.Value;
- break;
- case TokenType.Ellipsis:
- code += node.Value;
- break;
- case TokenType.Attribute:
- code += code === "" ? node.Value : " " + node.Value;
- break;
- }
- }
-
- return code;
- }
-}
diff --git a/src/CodeParser/CodeParserController.ts b/src/CodeParserController.ts
index 7eae9c0..32d1d75 100644
--- a/src/CodeParser/CodeParserController.ts
+++ b/src/CodeParserController.ts
@@ -8,11 +8,9 @@ import {
window,
workspace,
} from "vscode";
-import { Config, ConfigType } from "../Config";
-import CodeParser from "./CodeParser";
-import CParser from "./CParser/CParser";
-import CppParser from "./CParser/CppParser";
-
+import CodeParser from "./Common/ICodeParser";
+import { Config } from "./Config";
+import CParser from "./Lang/C/CParser";
/**
*
* Checks if the event matches the specified guidelines and if a parser exists for this language
@@ -22,7 +20,7 @@ import CppParser from "./CParser/CppParser";
*/
export default class CodeParserController {
private disposable: Disposable;
- private triggerSequence: string;
+ private cfg: Config;
/**
* Creates an instance of CodeParserController
@@ -36,8 +34,7 @@ export default class CodeParserController {
workspace.onDidChangeTextDocument((event) => {
const activeEditor: TextEditor = window.activeTextEditor;
if (activeEditor && event.document === activeEditor.document) {
- this.readConfig();
-
+ this.cfg = Config.ImportFromSettings();
this.onEvent(activeEditor, event.contentChanges[0]);
}
}, this, subscriptions);
@@ -59,12 +56,6 @@ export default class CodeParserController {
Implementation
***************************************************************************/
- private readConfig() {
- this.triggerSequence = workspace
- .getConfiguration(ConfigType.generic)
- .get<string>(Config.triggerSequence, "/**");
- }
-
private check(activeEditor: TextEditor, event: TextDocumentContentChangeEvent): boolean {
if (activeEditor == null || event.text == null) {
return false;
@@ -81,7 +72,7 @@ export default class CodeParserController {
const cont: string = activeLine.text.trim();
- return this.triggerSequence === cont;
+ return this.cfg.triggerSequence === cont;
}
private onEvent(activeEditor: TextEditor, event: TextDocumentContentChangeEvent) {
@@ -94,10 +85,8 @@ export default class CodeParserController {
switch (lang) {
case "c":
- parser = new CParser();
- break;
case "cpp":
- parser = new CppParser();
+ parser = new CParser(this.cfg);
break;
default:
// tslint:disable-next-line:no-console
@@ -108,7 +97,7 @@ export default class CodeParserController {
const currentPos: Position = window.activeTextEditor.selection.active;
const startReplace: Position = new Position(
currentPos.line,
- currentPos.character - this.triggerSequence.length,
+ currentPos.character - this.cfg.triggerSequence.length,
);
const nextLineText: string = window.activeTextEditor.document.lineAt(startReplace.line + 1).text;
diff --git a/src/CodeParser/CodeParser.ts b/src/Common/ICodeParser.ts
index cc2c709..afe2967 100644
--- a/src/CodeParser/CodeParser.ts
+++ b/src/Common/ICodeParser.ts
@@ -1,9 +1,9 @@
-import { Position, TextDocumentContentChangeEvent, TextEditor } from "vscode";
+import { TextEditor } from "vscode";
+import { IDocGen } from "./IDocGen";
export default interface ICodeParser {
-
/**
* @param {TextEditor} activeEditor The open active Editor where the event came from
*/
- Parse(activeEditor: TextEditor);
+ Parse(activeEditor: TextEditor): IDocGen;
}
diff --git a/src/DocGen/DocGen.ts b/src/Common/IDocGen.ts
index 1b5b1e1..1b5b1e1 100644
--- a/src/DocGen/DocGen.ts
+++ b/src/Common/IDocGen.ts
diff --git a/src/Config.ts b/src/Config.ts
index 3cc78fb..6297a66 100644
--- a/src/Config.ts
+++ b/src/Config.ts
@@ -1,18 +1,43 @@
-export enum ConfigType {
- generic = "doxdocgen.generic",
-}
+import { workspace } from "vscode";
+
+export class Config {
+ public static ImportFromSettings(): Config {
+ const values: Config = new Config();
+
+ const cfg = workspace.getConfiguration("doxdocgen.generic");
+
+ values.firstLine = cfg.get<string>("firstLine", values.firstLine);
+ values.commentPrefix = cfg.get<string>("commentPrefix", values.commentPrefix);
+ values.lastLine = cfg.get<string>("lastLine", values.lastLine);
+ values.newLineAfterBrief = cfg.get<boolean>("newLineAfterBrief", values.newLineAfterBrief);
+ values.newLineAfterParams = cfg.get<boolean>("newLineAfterParams", values.newLineAfterParams);
+ values.newLineAfterTParams = cfg.get<boolean>("newLineAfterTParams", values.newLineAfterTParams);
+ values.includeTypeAtReturn = cfg.get<boolean>("includeTypeAtReturn", values.includeTypeAtReturn);
+ values.boolReturnsTrueFalse = cfg.get<boolean>("boolReturnsTrueFalse", values.boolReturnsTrueFalse);
+ values.boolPointerReturnsNull = cfg.get<boolean>("boolPointerReturnsNull", values.boolPointerReturnsNull);
+ values.briefTemplate = cfg.get<string>("briefTemplate", values.briefTemplate);
+ values.paramTemplate = cfg.get<string>("paramTemplate", values.paramTemplate);
+ values.tparamTemplate = cfg.get<string>("tparamTemplate", values.tparamTemplate);
+ values.returnTemplate = cfg.get<string>("returnTemplate", values.returnTemplate);
+
+ return values;
+ }
+
+ public readonly paramTemplateReplace: string = "{param}";
+ public readonly typeTemplateReplace: string = "{type}";
-export enum Config {
- triggerSequence = "triggerSequence",
- firstLine = "firstLine",
- commentPrefix = "commentPrefix",
- lastLine = "lastLine",
- newLineAfterBrief = "newLineAfterBrief",
- newLineAfterParams = "newLineAfterParams",
- newLineAfterTParams = "newLineAfterTParams",
- includeTypeAtReturn = "includeTypeAtReturn",
- briefTemplate = "briefTemplate",
- paramTemplate = "paramTemplate",
- tparamTemplate = "tparamTemplate",
- returnTemplate = "returnTemplate",
+ public triggerSequence: string = "/**";
+ public firstLine: string = "/**";
+ public commentPrefix: string = " * ";
+ public lastLine: string = " */";
+ public newLineAfterBrief: boolean = true;
+ public newLineAfterParams: boolean = false;
+ public newLineAfterTParams: boolean = false;
+ public includeTypeAtReturn: boolean = true;
+ public boolReturnsTrueFalse: boolean = true;
+ public boolPointerReturnsNull: boolean = true;
+ public briefTemplate: string = "@brief ";
+ public paramTemplate: string = "@param {param} ";
+ public tparamTemplate: string = "@tparam {param} ";
+ public returnTemplate: string = "@return {type} ";
}
diff --git a/src/DocGen/CGen.ts b/src/DocGen/CGen.ts
deleted file mode 100644
index 13ecbf1..0000000
--- a/src/DocGen/CGen.ts
+++ /dev/null
@@ -1,185 +0,0 @@
-import { Position, Range, Selection, TextEditor, TextLine, workspace, WorkspaceEdit } from "vscode";
-import { Config, ConfigType } from "../Config";
-import { IDocGen } from "./DocGen";
-
-export default class CGen implements IDocGen {
- protected firstLine: string;
- protected commentPrefix: string;
- protected lastLine: string;
- protected newLineAfterBrief: boolean;
- protected newLineAfterParams: boolean;
- protected newLineAfterTParams: boolean;
- protected includeTypeAtReturn: boolean;
- protected briefTemplate: string;
- protected paramTemplate: string;
- protected tparamTemplate: string;
- protected returnTemplate: string;
-
- protected templateParamReplace: string;
- protected templateTypeReplace: string;
-
- protected activeEditor: TextEditor;
-
- protected retVals: string[];
- protected params: string[];
- protected tparams: string[];
-
- /**
- * @param {TextEditor} actEdit Active editor window
- * @param {Position} cursorPosition Where the cursor of the user currently is
- * @param {string[]} params The parameter names of the method extracted by the parser
- * @param {string[]} tparam The template parameter names of the method extracted by the parser.
- * @param {string[]} returnVals The return values extracted by the parser
- */
- public constructor(
- actEdit: TextEditor,
- cursorPosition: Position,
- params: string[],
- tparam: string[],
- returnVals: string[],
- ) {
- this.activeEditor = actEdit;
- this.templateParamReplace = "{param}";
- this.templateTypeReplace = "{type}";
- this.params = params;
- this.tparams = tparam;
- this.retVals = returnVals;
- }
-
- /**
- * @inheritdoc
- */
- public GenerateDoc(rangeToReplace: Range) {
- this.readConfig();
- const comment: string = this.generateComment();
-
- this.activeEditor.edit((editBuilder) => {
- editBuilder.replace(rangeToReplace, comment); // Insert the comment
- });
-
- // Set cursor to first DoxyGen command.
- this.moveCursurToFirstDoxyCommand(comment, rangeToReplace.start.line, rangeToReplace.start.character);
- }
-
- /***************************************************************************
- Implementation
- ***************************************************************************/
-
- protected readConfig() {
- const getCfg = workspace.getConfiguration;
-
- this.firstLine = getCfg(ConfigType.generic).get<string>(Config.firstLine, "/**");
- this.commentPrefix = getCfg(ConfigType.generic).get<string>(Config.commentPrefix, " * ");
- this.lastLine = getCfg(ConfigType.generic).get<string>(Config.lastLine, " */");
- this.newLineAfterBrief = getCfg(ConfigType.generic).get<boolean>(Config.newLineAfterBrief, true);
- this.newLineAfterParams = getCfg(ConfigType.generic).get<boolean>(Config.newLineAfterParams, false);
- this.newLineAfterTParams = getCfg(ConfigType.generic).get<boolean>(Config.newLineAfterTParams, false);
- this.includeTypeAtReturn = getCfg(ConfigType.generic).get<boolean>(Config.includeTypeAtReturn, false);
- this.briefTemplate = getCfg(ConfigType.generic).get<string>(Config.briefTemplate, "@brief ");
- this.paramTemplate = getCfg(ConfigType.generic).get<string>(Config.paramTemplate, "@param {param} ");
- this.tparamTemplate = getCfg(ConfigType.generic).get<string>(Config.tparamTemplate, "@tparam {param} ");
- this.returnTemplate = getCfg(ConfigType.generic).get<string>(Config.returnTemplate, "@return {type} ");
- }
-
- protected getIndentation(): string {
- const line: TextLine = this.activeEditor.document.lineAt(this.activeEditor.selection.start.line);
- const lineTxt: string = line.text;
- let stringToIndent: string = "";
- // Find indentation from previous line
- for (let i = 0; i < line.firstNonWhitespaceCharacterIndex; i++) {
- if (lineTxt.charAt(i) === "\t") {
- stringToIndent = stringToIndent + "\t";
- } else if (lineTxt.charAt(i) === " ") {
- stringToIndent = stringToIndent + " ";
- }
- }
- return stringToIndent;
- }
-
- protected getTemplatedString(replace: string, template: string, param: string): string {
- return template.replace(replace, param);
- }
-
- protected generateBrief(lines: string[]) {
- lines.push(this.commentPrefix + this.briefTemplate);
- }
-
- protected generateFromTemplate(lines: string[], replace: string, template: string, templateWith: string[]) {
- let line: string = "";
-
- templateWith.forEach((element: string) => {
- // Ignore null values
- if (element !== null) {
- line = this.commentPrefix;
- line += this.getTemplatedString(replace, template, element);
- lines.push(line);
- }
- });
- }
-
- protected generateComment(): string {
- const lines: string[] = [];
-
- if (this.firstLine.trim().length !== 0) {
- lines.push(this.firstLine);
- }
-
- if (this.briefTemplate.trim().length !== 0) {
- this.generateBrief(lines);
- if (this.newLineAfterBrief === true) {
- lines.push(this.commentPrefix);
- }
- }
-
- if (this.tparamTemplate.trim().length !== 0 && this.tparams.length > 0) {
- this.generateFromTemplate(lines, this.templateParamReplace, this.tparamTemplate, this.tparams);
- if (this.newLineAfterTParams === true) {
- lines.push(this.commentPrefix);
- }
- }
-
- if (this.paramTemplate.trim().length !== 0 && this.params.length > 0) {
- this.generateFromTemplate(lines, this.templateParamReplace, this.paramTemplate, this.params);
- if (this.newLineAfterParams === true) {
- lines.push(this.commentPrefix);
- }
- }
-
- if (this.returnTemplate.trim().length !== 0 && this.retVals.length > 0) {
- if (this.includeTypeAtReturn === false) {
- this.retVals = this.retVals.map((t) => t === "true" || t === "false" || t === "null" ? t : "");
- }
-
- this.generateFromTemplate(lines, this.templateTypeReplace, this.returnTemplate, this.retVals);
- }
-
- if (this.lastLine.trim().length !== 0) {
- lines.push(this.lastLine);
- }
-
- const comment: string = lines.join("\n" + this.getIndentation());
- return comment;
- }
-
- protected moveCursurToFirstDoxyCommand(comment: string, baseLine: number, baseCharacter) {
- // Find first offset of a new line in the comment. Since that's when the line where the first param starts.
- let line: number = baseLine;
- let character: number = comment.indexOf("\n");
-
- // If a first line is included find the 2nd line with a newline.
- if (this.firstLine.trim().length !== 0) {
- line++;
- const oldCharacter: number = character;
- character = comment.indexOf("\n", oldCharacter + 1) - oldCharacter;
- }
-
- // If newline is not found means no first param was found so Set to base line before the newline.
- if (character < 0) {
- line = baseLine;
- character = baseCharacter;
- }
-
- const moveTo: Position = new Position(line, character);
- this.activeEditor.selection = new Selection(moveTo, moveTo);
- }
-}
diff --git a/src/DocGen/CppGen.ts b/src/DocGen/CppGen.ts
deleted file mode 100644
index c13d194..0000000
--- a/src/DocGen/CppGen.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-import { Position, Range, Selection, TextEditor, TextLine, WorkspaceEdit } from "vscode";
-import CGen from "./CGen";
-
-export default class CppGen extends CGen {
- // For now C++ is the same as C
-}
diff --git a/src/Lang/C/CArgument.ts b/src/Lang/C/CArgument.ts
new file mode 100644
index 0000000..46f180c
--- /dev/null
+++ b/src/Lang/C/CArgument.ts
@@ -0,0 +1,6 @@
+import { CParseTree } from "./CParseTree";
+
+export class CArgument {
+ public name: string = null;
+ public type: CParseTree = new CParseTree();
+}
diff --git a/src/Lang/C/CDocGen.ts b/src/Lang/C/CDocGen.ts
new file mode 100644
index 0000000..87d59fb
--- /dev/null
+++ b/src/Lang/C/CDocGen.ts
@@ -0,0 +1,183 @@
+import { Position, Range, Selection, TextEditor, TextLine, WorkspaceEdit } from "vscode";
+import { IDocGen } from "../../Common/IDocGen";
+import { Config } from "../../Config";
+import { CArgument } from "./CArgument";
+import { CParseTree } from "./CParseTree";
+import { CToken, CTokenType } from "./CToken";
+
+export default class CDocGen implements IDocGen {
+ protected activeEditor: TextEditor;
+
+ protected readonly cfg: Config;
+
+ protected func: CArgument;
+ protected templateParams: string[];
+ protected params: CArgument[];
+
+ /**
+ * @param {TextEditor} actEdit Active editor window
+ * @param {Position} cursorPosition Where the cursor of the user currently is
+ * @param {string[]} templateParams The template parameters of the declaration.
+ * @param {CArgument} func The type and name of the function to generate doxygen.
+ * Doesn't contain anything if it is not a function.
+ * @param {CArgument[]} params The parameters of the function. Doesn't contain anything if it is not a function.
+ */
+ public constructor(
+ actEdit: TextEditor,
+ cursorPosition: Position,
+ cfg: Config,
+ templateParams: string[],
+ func: CArgument,
+ params: CArgument[],
+ ) {
+ this.activeEditor = actEdit;
+ this.cfg = cfg;
+ this.func = func;
+ this.templateParams = templateParams;
+ this.params = params;
+ }
+
+ /**
+ * @inheritdoc
+ */
+ public GenerateDoc(rangeToReplace: Range) {
+ const comment: string = this.generateComment();
+
+ this.activeEditor.edit((editBuilder) => {
+ editBuilder.replace(rangeToReplace, comment); // Insert the comment
+ });
+
+ // Set cursor to first DoxyGen command.
+ this.moveCursurToFirstDoxyCommand(comment, rangeToReplace.start.line, rangeToReplace.start.character);
+ }
+
+ /***************************************************************************
+ Implementation
+ ***************************************************************************/
+ protected getIndentation(): string {
+ const line: TextLine = this.activeEditor.document.lineAt(this.activeEditor.selection.start.line);
+ return line.text.slice(0, line.firstNonWhitespaceCharacterIndex);
+ }
+
+ protected getTemplatedString(replace: string, template: string, param: string): string {
+ return template.replace(replace, param);
+ }
+
+ protected generateBrief(lines: string[]) {
+ lines.push(this.cfg.commentPrefix + this.cfg.briefTemplate);
+ }
+
+ protected generateFromTemplate(lines: string[], replace: string, template: string, templateWith: string[]) {
+ let line: string = "";
+
+ templateWith.forEach((element: string) => {
+ // Ignore null values
+ if (element !== null && element !== undefined && element !== "") {
+ line = this.cfg.commentPrefix;
+ line += this.getTemplatedString(replace, template, element);
+ lines.push(line);
+ }
+ });
+ }
+
+ protected generateReturnParams(): string[] {
+ const params: string[] = [];
+
+ // Check if return type is a pointer
+ const ptrReturnIndex = this.func.type.nodes
+ .findIndex((n) => n instanceof CToken && n.type === CTokenType.Pointer);
+
+ // Special case for void functions.
+ const voidReturnIndex = this.func.type.nodes
+ .findIndex((n) => n instanceof CToken && n.type === CTokenType.Symbol && n.value === "void");
+
+ // Special case for bool return type.
+ const boolReturnIndex: number = this.func.type.nodes
+ .findIndex((n) => n instanceof CToken && n.type === CTokenType.Symbol && n.value === "bool");
+
+ if (boolReturnIndex !== -1) {
+ if (this.cfg.boolReturnsTrueFalse === true) {
+ params.push("true");
+ params.push("false");
+ }
+ if (ptrReturnIndex !== -1 && this.cfg.boolPointerReturnsNull === true) {
+ params.push("null");
+ }
+ } else if (voidReturnIndex !== -1 && ptrReturnIndex !== -1) {
+ params.push(this.cfg.includeTypeAtReturn === true ? this.func.type.Yield() : "");
+ } else if (voidReturnIndex === -1 && this.func.type.nodes.length > 0) {
+ params.push(this.cfg.includeTypeAtReturn === true ? this.func.type.Yield() : "");
+ }
+
+ return params;
+ }
+
+ protected generateComment(): string {
+ const lines: string[] = [];
+
+ if (this.cfg.firstLine.trim().length !== 0) {
+ lines.push(this.cfg.firstLine);
+ }
+
+ if (this.cfg.briefTemplate.trim().length !== 0) {
+ this.generateBrief(lines);
+ if (this.cfg.newLineAfterBrief === true) {
+ lines.push(this.cfg.commentPrefix);
+ }
+ }
+
+ if (this.cfg.tparamTemplate.trim().length !== 0 && this.templateParams.length > 0) {
+ this.generateFromTemplate(
+ lines,
+ this.cfg.paramTemplateReplace,
+ this.cfg.paramTemplate,
+ this.templateParams,
+ );
+ if (this.cfg.newLineAfterTParams === true) {
+ lines.push(this.cfg.commentPrefix);
+ }
+ }
+
+ if (this.cfg.paramTemplate.trim().length !== 0 && this.params.length > 0) {
+ const paramNames: string[] = this.params.map((p) => p.name);
+ this.generateFromTemplate(lines, this.cfg.paramTemplateReplace, this.cfg.paramTemplate, paramNames);
+ if (this.cfg.newLineAfterParams === true) {
+ lines.push(this.cfg.commentPrefix);
+ }
+ }
+
+ if (this.cfg.returnTemplate.trim().length !== 0 && this.func.type !== null) {
+ const returnParams = this.generateReturnParams();
+ this.generateFromTemplate(lines, this.cfg.typeTemplateReplace, this.cfg.returnTemplate, returnParams);
+ }
+
+ if (this.cfg.lastLine.trim().length !== 0) {
+ lines.push(this.cfg.lastLine);
+ }
+
+ const comment: string = lines.join("\n" + this.getIndentation());
+ return comment;
+ }
+
+ protected moveCursurToFirstDoxyCommand(comment: string, baseLine: number, baseCharacter) {
+ // Find first offset of a new line in the comment. Since that's when the line where the first param starts.
+ let line: number = baseLine;
+ let character: number = comment.indexOf("\n");
+
+ // If a first line is included find the 2nd line with a newline.
+ if (this.cfg.firstLine.trim().length !== 0) {
+ line++;
+ const oldCharacter: number = character;
+ character = comment.indexOf("\n", oldCharacter + 1) - oldCharacter;
+ }
+
+ // If newline is not found means no first param was found so Set to base line before the newline.
+ if (character < 0) {
+ line = baseLine;
+ character = baseCharacter;
+ }
+
+ const moveTo: Position = new Position(line, character);
+ this.activeEditor.selection = new Selection(moveTo, moveTo