diff options
| author | Christoph Schlosser <christophschlosser@users.noreply.github.com> | 2017-10-15 20:12:01 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-10-15 20:12:01 +0200 |
| commit | c7ebe707bbfbe52c75646a111600986d6c584d03 (patch) | |
| tree | f5435eda43b5d9bd22348f4400028c07b4a446c8 | |
| parent | 140229888a0e4a120c11ecaae81132d07cc69e5b (diff) | |
| parent | 32baa67d95609fc2b0f20c582fe152eeee98ff35 (diff) | |
| download | doxdocgen-c7ebe707bbfbe52c75646a111600986d6c584d03.tar.gz | |
Merge pull request #16 from rowanG077/master
-- Added extensive templating the be able to generated different type…
| -rw-r--r-- | package.json | 64 | ||||
| -rw-r--r-- | src/CodeParser/CParser.ts | 46 | ||||
| -rw-r--r-- | src/CodeParser/CodeParserController.ts | 44 | ||||
| -rw-r--r-- | src/Config.ts | 14 | ||||
| -rw-r--r-- | src/DocGen/CGen.ts | 203 | ||||
| -rw-r--r-- | src/DocGen/DocGen.ts | 18 |
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); } |