summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--package.json64
-rw-r--r--src/CodeParser/CParser.ts46
-rw-r--r--src/CodeParser/CodeParserController.ts44
-rw-r--r--src/Config.ts14
-rw-r--r--src/DocGen/CGen.ts203
-rw-r--r--src/DocGen/DocGen.ts18
6 files changed, 240 insertions, 149 deletions
diff --git a/package.json b/package.json
index 4ea2631..c288cd6 100644
--- a/package.json
+++ b/package.json
@@ -18,19 +18,65 @@
"type": "object",
"title": "Doxygen Documentation Generator Settings",
"properties": {
- "doxdocgen.generic.commentStart": {
- "description": "Doxygen comment start indicator. Default ist /** but Qt style with /*! is also valid.",
+ "doxdocgen.generic.triggerSequence": {
+ "description": "Doxygen comment trigger. This character sequence triggers generation of DoxyGen comments.",
"type": "string",
- "default": "/**",
- "enum": [
- "/**",
- "/*!"
- ]
+ "default": "/**"
},
- "doxdocgen.generic.generateReturnType": {
- "description": "Insert return type into generated documentation",
+ "doxdocgen.generic.firstLine": {
+ "description": "The first line of the comment that gets generated. If empty it won't get generated at all.",
+ "type": "string",
+ "default": "/**"
+ },
+ "doxdocgen.generic.commentPrefix": {
+ "description": "The prefix that is used for each comment line.",
+ "type": "string",
+ "default": " * "
+ },
+ "doxdocgen.generic.lastLine": {
+ "description": "The last line of the comment that gets generated. If empty it won't get generated at all.",
+ "type": "string",
+ "default": " */"
+ },
+ "doxdocgen.generic.newLineAfterBrief": {
+ "description": "Whether to insert a newline after a brief.",
"type": "boolean",
"default": true
+ },
+ "doxdocgen.generic.newLineAfterParams": {
+ "description": "Whether to insert a newline after the params.",
+ "type": "boolean",
+ "default": false
+ },
+ "doxdocgen.generic.newLineAfterTParams": {
+ "description": "Whether to insert a newline after the template params.",
+ "type": "boolean",
+ "default": false
+ },
+ "doxdocgen.generic.includeTypeAtReturn": {
+ "description": "Whether include type information at return.",
+ "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",
+ "default": "@brief "
+ },
+ "doxdocgen.generic.paramTemplate": {
+ "description": "The template of the param DoxyGen line(s) that are generated. If empty it won't get generated at all.",
+ "type": "string",
+ "default": "@param {param} "
+ },
+ "doxdocgen.generic.tparamTemplate": {
+ "description": "The template of the template parameter DoxyGen line(s) that are generated. If empty it won't get generated at all.",
+ "type": "string",
+ "default": "@tparam {param} "
+ },
+ "doxdocgen.generic.returnTemplate": {
+ "description": "The template of the return DoxyGen line that is generated. If empty it won't get generated at all.",
+ "type": "string",
+ "default": "@return {type} "
}
}
}
diff --git a/src/CodeParser/CParser.ts b/src/CodeParser/CParser.ts
index 4889de6..8b0bfe1 100644
--- a/src/CodeParser/CParser.ts
+++ b/src/CodeParser/CParser.ts
@@ -25,27 +25,33 @@ export default class CParser implements ICodeParser {
const activeLine: TextLine = this.activeEditor.document.lineAt(this.activeEditor.selection.active.line);
- const method: string = this.getMethodText();
+ const line: string = this.getLogicalLine();
// Not a method
- if (method.length === 0) {
+ if (line.length === 0) {
return null;
}
- const returnValue: string[] = this.getReturn(method);
+ const returnValue: string[] = this.getReturn(line);
- const params: string[] = this.getParams(method);
+ const params: string[] = this.getParams(line);
+ const tparams: string[] = this.getTemplateParams(line);
- const cppGenerator: IDocGen = new Generator(this.activeEditor, this.activeSelection, params, returnValue);
+ const cppGenerator: IDocGen = new Generator(
+ this.activeEditor,
+ this.activeSelection,
+ params,
+ tparams,
+ returnValue,
+ );
return cppGenerator;
}
/***************************************************************************
Implementation
***************************************************************************/
-
- protected getMethodText(): string {
- let method: string = "";
+ protected getLogicalLine(): string {
+ let logicalLine: string = "";
let nextLine: Position = new Position(this.activeSelection.line + 1, this.activeSelection.character);
@@ -61,7 +67,7 @@ export default class CParser implements ICodeParser {
nextLineTxt = this.activeEditor.document.lineAt(nextLine.line).text.trim();
}
- method += nextLineTxt;
+ logicalLine += nextLineTxt;
// Get method end line
while (nextLineTxt.indexOf(")") === -1 &&
@@ -69,22 +75,22 @@ export default class CParser implements ICodeParser {
nextLine = new Position(nextLine.line + 1, nextLine.character);
nextLineTxt = this.activeEditor.document.lineAt(nextLine.line).text.trim();
- method += " " + nextLineTxt;
+ logicalLine += " " + nextLineTxt;
}
// Not a method but some code in the file
- if (method.indexOf(")") === -1) {
+ if (logicalLine.indexOf(")") === -1) {
return "";
}
- return method;
+ return logicalLine;
}
protected getReturn(method: string): string[] {
const retVals: string[] = [];
// Remove the compiler keywords from the signature
- const sign: string = method.replace(/(static)|(inline)|(friend)|(virtual)|(extern)|(explicit)/g, "");
+ const sign: string = method.replace(/(static)|(inline)|(friend)|(virtual)|(extern)|(explicit)|(const)/g, "");
// Remove the parameters from the signature
const returnSignature = sign.slice(0, sign.indexOf("(")).trim();
@@ -106,14 +112,6 @@ export default class CParser implements ICodeParser {
break;
}
- // Don't generate return type if the user doesn't wish to do it
- if (!workspace.getConfiguration(ConfigType.generic).get<boolean>(Config.generateReturnType, true) &&
- retVals.length > 0) {
- retVals.length = 0;
- retVals.push(" ");
- return retVals;
- }
-
return retVals;
}
@@ -139,4 +137,10 @@ export default class CParser implements ICodeParser {
return paramArr;
}
+
+ protected getTemplateParams(method: string): string[] {
+ // Todo implement parsing of template parameters.
+ const tparams: string[] = [];
+ return tparams;
+ }
}
diff --git a/src/CodeParser/CodeParserController.ts b/src/CodeParser/CodeParserController.ts
index 49d4082..70941d0 100644
--- a/src/CodeParser/CodeParserController.ts
+++ b/src/CodeParser/CodeParserController.ts
@@ -1,4 +1,13 @@
-import { Disposable, Position, TextDocumentContentChangeEvent, TextEditor, TextLine, window, workspace } from "vscode";
+import {
+ Disposable,
+ Position,
+ Range,
+ TextDocumentContentChangeEvent,
+ TextEditor,
+ TextLine,
+ window,
+ workspace,
+} from "vscode";
import { Config, ConfigType } from "../Config";
import CodeParser from "./CodeParser";
import CParser from "./CParser";
@@ -13,7 +22,7 @@ import CppParser from "./CppParser";
*/
export default class CodeParserController {
private disposable: Disposable;
- private indicators: string[] = [];
+ private triggerSequence: string;
/**
* Creates an instance of CodeParserController
@@ -51,8 +60,9 @@ export default class CodeParserController {
***************************************************************************/
private readConfig() {
- this.indicators.pop();
- this.indicators.push(workspace.getConfiguration(ConfigType.generic).get<string>(Config.commentStart, "/**"));
+ this.triggerSequence = workspace
+ .getConfiguration(ConfigType.generic)
+ .get<string>(Config.triggerSequence, "/**");
}
private check(activeEditor: TextEditor, event: TextDocumentContentChangeEvent): boolean {
@@ -70,16 +80,8 @@ export default class CodeParserController {
}
const cont: string = activeLine.text.trim();
- let found: boolean = false;
- this.indicators.forEach((element: string) => {
- if (element === cont) { // Compare the content from the line with the valid indicators
- found = true;
- return;
- }
- });
-
- return found;
+ return this.triggerSequence === cont;
}
private onEvent(activeEditor: TextEditor, event: TextDocumentContentChangeEvent) {
@@ -102,6 +104,20 @@ export default class CodeParserController {
console.log("No comments can be generated for language: " + lang);
return null;
}
- parser.Parse(activeEditor, event).GenerateDoc();
+
+ const currentPos: Position = window.activeTextEditor.selection.active;
+ const startReplace: Position = new Position(
+ currentPos.line,
+ currentPos.character - this.triggerSequence.length,
+ );
+
+ let endReplace: Position = new Position(currentPos.line, currentPos.character);
+ const nextLineText: string = window.activeTextEditor.document.lineAt(endReplace.line + 1).text;
+ // VSCode may enter a * on itself, we don't want that in our comment.
+ if (nextLineText.trim() === "*") {
+ endReplace = new Position(currentPos.line + 1, nextLineText.length);
+ }
+
+ parser.Parse(activeEditor, event).GenerateDoc(new Range(startReplace, endReplace));
}
}
diff --git a/src/Config.ts b/src/Config.ts
index 2e449cf..3cc78fb 100644
--- a/src/Config.ts
+++ b/src/Config.ts
@@ -3,6 +3,16 @@ export enum ConfigType {
}
export enum Config {
- commentStart = "commentStart",
- generateReturnType = "generateReturnType",
+ triggerSequence = "triggerSequence",
+ firstLine = "firstLine",
+ commentPrefix = "commentPrefix",
+ lastLine = "lastLine",
+ newLineAfterBrief = "newLineAfterBrief",
+ newLineAfterParams = "newLineAfterParams",
+ newLineAfterTParams = "newLineAfterTParams",
+ includeTypeAtReturn = "includeTypeAtReturn",
+ briefTemplate = "briefTemplate",
+ paramTemplate = "paramTemplate",
+ tparamTemplate = "tparamTemplate",
+ returnTemplate = "returnTemplate",
}
diff --git a/src/DocGen/CGen.ts b/src/DocGen/CGen.ts
index 426bb26..c2750ee 100644
--- a/src/DocGen/CGen.ts
+++ b/src/DocGen/CGen.ts
@@ -1,52 +1,64 @@
-import { Position, Range, Selection, TextEditor, TextLine, WorkspaceEdit } from "vscode";
-import { DoxygenCommands, IDocGen } from "./DocGen";
+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 lineStart: string;
- protected endComment: string;
- protected commandIndicator: string;
- protected spaceAfterCommand: string;
+ 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 position: Position;
- protected comment: string;
+
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[]} param 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, param: string[], returnVals: string[]) {
+ public constructor(
+ actEdit: TextEditor,
+ cursorPosition: Position,
+ param: string[],
+ tparam: string[],
+ returnVals: string[],
+ ) {
this.activeEditor = actEdit;
- this.position = cursorPosition;
- this.comment = "\n"; // Add the new line after the comment indicator
+ this.templateParamReplace = "{param}";
+ this.templateTypeReplace = "{type}";
this.params = param;
+ this.tparams = tparam;
this.retVals = returnVals;
}
/**
* @inheritdoc
*/
- public GenerateDoc() {
+ public GenerateDoc(rangeToReplace: Range) {
this.readConfig();
- this.generateComment();
-
- const oldPos: Position = this.position;
+ const comment: string = this.generateComment();
- const active: Position = this.activeEditor.selection.active;
- const anchor: Position = new Position(active.line + 1, active.character); // Start at the next line
- const replaceSelection = new Selection(anchor, active);
this.activeEditor.edit((editBuilder) => {
- editBuilder.replace(replaceSelection, this.comment); // Insert the comment
+ editBuilder.replace(rangeToReplace, comment); // Insert the comment
});
- // Set cursor after brief command
- this.setCursor(oldPos.line + 3, oldPos.character);
- const newSelectActive = new Position(oldPos.line + 3, oldPos.character + DoxygenCommands.detailed.length);
- const newSelectPos = new Position(oldPos.line + 3, oldPos.character);
- this.activeEditor.selection = new Selection(newSelectPos, newSelectActive);
+ // Set cursor to first DoxyGen command.
+ this.moveCursurToFirstDoxyCommand(comment, rangeToReplace.start.line, rangeToReplace.start.character);
}
/***************************************************************************
@@ -54,13 +66,22 @@ export default class CGen implements IDocGen {
***************************************************************************/
protected readConfig() {
- this.lineStart = " * "; // TODO: make this customizable
- this.endComment = "*/"; // TODO: make this customizable
- this.commandIndicator = "@"; // TODO: make this customizable
- this.spaceAfterCommand = " "; // TODO: make this customizable
+ 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 indentLine(commentLine: string): string {
+ protected getIndentation(): string {
const line: TextLine = this.activeEditor.document.lineAt(this.activeEditor.selection.start.line);
const lineTxt: string = line.text;
let stringToIndent: string = "";
@@ -72,86 +93,90 @@ export default class CGen implements IDocGen {
stringToIndent = stringToIndent + " ";
}
}
- const textToInsert = stringToIndent + commentLine;
- return textToInsert;
+ return stringToIndent;
}
- protected generateBrief() {
- let line: string = "";
- line += this.lineStart;
- line += this.commandIndicator;
- line += DoxygenCommands.brief;
- line += this.spaceAfterCommand;
- this.comment += this.indentLine(line);
+ protected getTemplatedString(replace: string, template: string, param: string): string {
+ return template.replace(replace, param);
}
- protected generateDetailed() {
- let line: string = "";
- line += this.lineStart;
- line += "\n";
- this.comment += this.indentLine(line);
- line = this.lineStart;
- line += DoxygenCommands.detailed + "\n";
- this.comment += this.indentLine(line);
- line = this.lineStart;
- this.comment += this.indentLine(line);
+ protected generateBrief(lines: string[]) {
+ lines.push(this.commentPrefix + this.briefTemplate);
}
- protected generateParams() {
+ protected generateFromTemplate(lines: string[], replace: string, template: string, templateWith: string[]) {
let line: string = "";
- this.params.forEach((element: string) => {
- line = this.lineStart;
- line += this.commandIndicator;
- line += DoxygenCommands.param + " "; // TODO: Make this customizable
- line += element + "\n";
- this.comment += this.indentLine(line);
+ templateWith.forEach((element: string) => {
+ line = this.commentPrefix;
+ line += this.getTemplatedString(replace, template, element);
+ lines.push(line);
});
}
- protected generateReturn() {
- if (this.retVals.length === 0) {
- return;
+ protected generateComment(): string {
+ const lines: string[] = [];
+
+ if (this.firstLine.trim().length !== 0) {
+ lines.push(this.firstLine);
}
- let line: string = "";
- if (this.params.length !== 0) {
- line = this.lineStart + "\n";
- this.comment += this.indentLine(line);
+ if (this.briefTemplate.trim().length !== 0) {
+ this.generateBrief(lines);
+ if (this.newLineAfterBrief === true) {
+ lines.push(this.commentPrefix);
+ }
}
- this.retVals.forEach((element: string) => {
- line = this.lineStart;
- line += this.commandIndicator;
- line += DoxygenCommands.return + " "; // TODO: Make this customizable
- line += element.trim() + "\n";
- this.comment += this.indentLine(line);
- });
- }
+ 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);
+ }
+ }
- protected generateEnd() {
- let line: string = " "; // TODO: Make this customizable
- line += this.endComment;
- this.comment += this.indentLine(line);
- }
+ 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);
+ }
+ }
- protected generateComment() {
- this.generateBrief();
- this.comment += "\n";
- this.generateDetailed();
- this.comment += "\n";
- if (this.params.length !== 0) { // Only if we have parameters
- this.generateParams();
+ 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 : "");
+ }
+
+ this.generateFromTemplate(lines, this.templateTypeReplace, this.returnTemplate, this.retVals);
}
- if (this.retVals.length !== 0) { // Only if we have return values
- this.generateReturn();
+
+ if (this.lastLine.trim().length !== 0) {
+ lines.push(this.lastLine);
}
- this.generateEnd();
+
+ const comment: string = lines.join("\n" + this.getIndentation());
+ return comment;
}
- protected setCursor(line: number, character: number) {
- const indentLen: number = this.indentLine("").length;
- const move: Selection = new Selection(line, character, line, character);
- this.activeEditor.selection = move;
+ 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/DocGen.ts b/src/DocGen/DocGen.ts
index 9de9d41..1b5b1e1 100644
--- a/src/DocGen/DocGen.ts
+++ b/src/DocGen/DocGen.ts
@@ -1,19 +1,9 @@
-/**
- * Contains the supported doxygen commands
- *
- * @export
- * @enum {number}
- */
-export enum DoxygenCommands {
- brief = "brief",
- return = "return",
- param = "param",
- detailed = "(Detailed description)",
-}
+import { Range } from "vscode";
export interface IDocGen {
/**
- * Generate documentation string and write it to the active editor
+ * @brief Generate documentation string and write it to the active editor
+ * @param {Range} rangeToReplace Range to replace with the generated comment.
*/
- GenerateDoc();
+ GenerateDoc(rangeToReplace: Range);
}