summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHO-COOH <42881734+HO-COOH@users.noreply.github.com>2021-05-15 00:14:36 +0800
committerGitHub <noreply@github.com>2021-05-14 18:14:36 +0200
commitaf70cf95d9d010f27da1c1c8987c807ee3255a10 (patch)
tree9d6de559ea072c684f690d32816f7fe3ae1a88d3
parentbe07386c572fe8258a3b4c101b85dd900867bb13 (diff)
downloaddoxdocgen-af70cf95d9d010f27da1c1c8987c807ee3255a10.tar.gz
Refactor, add {file} template (#221)
* Refactor, add {file} template * Add test for {file} expansion
-rw-r--r--README.md4
-rw-r--r--package.json4
-rw-r--r--src/CodeParserController.ts17
-rw-r--r--src/Lang/Cpp/CppDocGen.ts134
-rw-r--r--src/templatedString.ts84
-rw-r--r--src/test/CppTests/Config.test.ts8
-rw-r--r--src/test/CppTests/FileDescription.test.ts4
-rw-r--r--src/util.ts54
8 files changed, 182 insertions, 127 deletions
diff --git a/README.md b/README.md
index 4a023dc..decc8f2 100644
--- a/README.md
+++ b/README.md
@@ -148,7 +148,7 @@ Each of them can be configured with its own custom text and you can decide if th
"@copyright Copyright (c) {year}"
],
- // Additional file documentation. Array of strings will be converted to one line per element. Can template {year}, {date}, {author}, and {email}.
+ // Additional file documentation. One tag per line will be added. Can template `{year}`, `{date}`, `{author}`, `{email}` and `{file}`. You have to specify the prefix.
"doxdocgen.file.customTag": [],
// The order to use for the file comment. Values can be used multiple times. Valid values are shown in default setting.
@@ -210,7 +210,7 @@ Each of them can be configured with its own custom text and you can decide if th
"custom"
],
- // Custom tags to be added to the generic order. One tag per line will be added. You have to specify the prefix yourself.
+ // Custom tags to be added to the generic order. One tag per line will be added. Can template `{year}`, `{date}`, `{author}`, `{email}` and `{file}`. You have to specify the prefix.
"doxdocgen.generic.customTags": [],
// The template of the param Doxygen line(s) that are generated. If empty it won't get generated at all.
diff --git a/package.json b/package.json
index c065138..a0bf1d3 100644
--- a/package.json
+++ b/package.json
@@ -108,7 +108,7 @@
"default": "@version 0.1"
},
"doxdocgen.file.customTag": {
- "markdownDescription": "Additional file documentation. Array of strings will be converted to one line per element. Can template `{year}`, `{date}`, `{author}` and `{email}`.",
+ "markdownDescription": "Additional file documentation. Array of strings will be converted to one line per element. Can template `{year}`, `{date}`, `{author}`, `{email}` and `{file}`. You have to specify the prefix.",
"type": [
"array",
"string"
@@ -214,7 +214,7 @@
]
},
"doxdocgen.generic.customTags": {
- "description": "Custom tags to be added to the generic order. One tag per line will be added. You have to specify the prefix yourself.",
+ "description": "Custom tags to be added to the generic order. One tag per line will be added. Can template `{year}`, `{date}`, `{author}`, `{email}` and `{file}`. You have to specify the prefix.",
"type": [
"array",
"string"
diff --git a/src/CodeParserController.ts b/src/CodeParserController.ts
index f87e221..3b6348a 100644
--- a/src/CodeParserController.ts
+++ b/src/CodeParserController.ts
@@ -12,6 +12,7 @@ import CodeParser from "./Common/ICodeParser";
import { Config } from "./Config";
import GitConfig from "./GitConfig";
import CppParser from "./Lang/Cpp/CppParser";
+import { inComment } from "./util";
/**
*
* Checks if the event matches the specified guidelines and if a parser exists for this language
@@ -75,7 +76,7 @@ export default class CodeParserController {
}
// Check if currently in a comment block
- if (this.inComment(activeEditor, activeSelection.line)) {
+ if (inComment(activeEditor, activeSelection.line)) {
return false;
}
@@ -92,20 +93,6 @@ export default class CodeParserController {
}
}
- private inComment(activeEditor: TextEditor, activeLine: number): boolean {
- if (activeLine === 0) {
- return false;
- }
-
- const txt: string = activeEditor.document.lineAt(activeLine - 1).text.trim();
- if (!txt.startsWith("///") && !txt.startsWith("*") &&
- !txt.startsWith("/**") && !txt.startsWith("/*!")) {
- return false;
- } else {
- return true;
- }
- }
-
private onEvent(activeEditor: TextEditor, event: TextDocumentContentChangeEvent) {
if (!this.check(activeEditor, event)) {
return null;
diff --git a/src/Lang/Cpp/CppDocGen.ts b/src/Lang/Cpp/CppDocGen.ts
index 05c8883..c0113ad 100644
--- a/src/Lang/Cpp/CppDocGen.ts
+++ b/src/Lang/Cpp/CppDocGen.ts
@@ -1,9 +1,10 @@
-import * as env from "env-var";
import * as moment from "moment";
import { Position, Range, Selection, TextEditor } from "vscode";
import { IDocGen } from "../../Common/IDocGen";
import { Config } from "../../Config";
import GitConfig from "../../GitConfig";
+import * as templates from "../../templatedString";
+import { getIndentation } from "../../util";
import { CppArgument } from "./CppArgument";
import * as CppParser from "./CppParser";
import { CppToken, CppTokenType } from "./CppToken";
@@ -111,79 +112,16 @@ export class CppDocGen implements IDocGen {
});
// Set cursor to first DoxyGen command.
- this.moveCursurToFirstDoxyCommand(comment,
- modifiedRangeToReplace.start.line,
- modifiedRangeToReplace.start.character);
+ this.moveCursurToFirstDoxyCommand(
+ comment,
+ modifiedRangeToReplace.start.line,
+ modifiedRangeToReplace.start.character,
+ );
}
/***************************************************************************
Implementation
***************************************************************************/
- protected getIndentation(): string {
- return this.activeEditor.document.lineAt(this.activeEditor.selection.start.line).text.match("^\\s*")[0];
- }
-
- protected getIndentedTemplate(replace: string): string {
- if (replace === undefined || replace === null || replace === "") {
- return "";
- }
- const snippets = replace.split(/({indent:\d+})/);
-
- let indentedString: string = "";
- let indentWidth: number = 0;
-
- // tslint:disable-next-line:prefer-for-of
- snippets.forEach((element) => {
- if (element.match(/{indent:\d+}/)) {
- const indents = parseInt(element.match(/{indent:(\d+)}/)[1], 10);
- indentWidth = indents;
- const numSpaces = Math.max(indentWidth - indentedString.length, 0);
- indentedString += " ".repeat(numSpaces);
- } else {
- // just some text
- indentedString += element;
- }
- });
-
- return indentedString;
- }
-
- protected getEnvVars(replace: string): string {
- let replacement = replace;
- const regex = /\$\{env\:([\w|\d|_]+)\}/m;
- let match: RegExpExecArray;
-
- // tslint:disable-next-line:no-conditional-assignment
- while ((match = regex.exec(replacement)) !== null) {
- if (match.index === regex.lastIndex) {
- regex.lastIndex++;
- }
-
- const m = match[1];
-
- const envVar: string = env.get(m, m).asString();
-
- replacement = replacement.replace("${env:" + m + "}", envVar);
- }
-
- return replacement;
- }
-
- protected getTemplatedString(replace: string, template: string, param: string): string {
- const replacedTemplate = template.replace(replace, param);
- const replacedWithEnv = this.getEnvVars(replacedTemplate);
- return this.getIndentedTemplate(replacedWithEnv);
- }
-
- protected getMultiTemplatedString(replace: string[], template: string, param: string[]): string {
- // For each replace entry, attempt to replace it with the corresponding param in the template
- for (let i = 0; i < replace.length; i++) {
- if (i < param.length) {
- template = template.replace(replace[i], param[i]);
- }
- }
- return this.getEnvVars(template);
- }
protected getSmartText(): string {
if (!this.cfg.Generic.generateSmartText) {
@@ -234,35 +172,20 @@ export class CppDocGen implements IDocGen {
return "";
}
}
- const str = this.getTemplatedString(this.cfg.nameTemplateReplace,
- text,
- val);
+ const str = templates.getTemplatedString(text, { toReplace: this.cfg.nameTemplateReplace, with: val });
this.smartTextLength = str.length;
return str;
}
protected generateBrief(lines: string[]) {
lines.push(
- ...this.getTemplatedString(
- this.cfg.textTemplateReplace,
+ ...templates.getTemplatedString(
this.cfg.Generic.briefTemplate,
- this.getSmartText(),
+ { toReplace: this.cfg.textTemplateReplace, with: this.getSmartText() },
).split("\n"),
);
}
- protected generateFromTemplate(lines: string[],
- replace: string,
- template: string,
- templateWith: string[]) {
- templateWith.forEach((element: string) => {
- // Ignore null values
- if (element !== null) {
- lines.push(...this.getTemplatedString(replace, template, element).split("\n"));
- }
- });
- }
-
protected generateReturnParams(): string[] {
const params: string[] = [];
@@ -303,10 +226,12 @@ export class CppDocGen implements IDocGen {
const authorInfo = this.getAuthorInfo();
// Allow substitution of {author} and {email} only
lines.push(
- ...this.getMultiTemplatedString(
- [this.cfg.authorTemplateReplace, this.cfg.emailTemplateReplace],
+ ...templates.getMultiTemplatedString(
this.cfg.Generic.authorTag,
- [authorInfo.authorName, authorInfo.authorEmail],
+ [
+ { toReplace: this.cfg.authorTemplateReplace, with: authorInfo.authorName },
+ { toReplace: this.cfg.emailTemplateReplace, with: authorInfo.authorEmail },
+ ],
).split("\n"),
);
}
@@ -314,7 +239,7 @@ export class CppDocGen implements IDocGen {
protected generateFilenameFromTemplate(lines: string[]) {
if (this.cfg.File.fileTemplate.trim().length !== 0) {
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.nameTemplateReplace,
this.cfg.File.fileTemplate,
@@ -332,7 +257,7 @@ export class CppDocGen implements IDocGen {
protected generateCopyrightTag(lines: string[]) {
// This currently only supports year substitution
this.cfg.File.copyrightTag.forEach((element) => {
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.yearTemplateReplace,
element,
@@ -392,14 +317,17 @@ export class CppDocGen implements IDocGen {
if (element !== "custom") { // Prevent recursive expansion
// Allow any of date, year, author, email to be replaced
lines.push(
- ...this.getMultiTemplatedString(
- [this.cfg.authorTemplateReplace, this.cfg.emailTemplateReplace,
- this.cfg.dateTemplateReplace, this.cfg.yearTemplateReplace],
+ ...templates.getMultiTemplatedString(
element,
- [authorInfo.authorName, authorInfo.authorEmail,
- moment().format(dateFormat), moment().format("YYYY")],
+ [
+ { toReplace: this.cfg.authorTemplateReplace, with: authorInfo.authorName },
+ { toReplace: this.cfg.emailTemplateReplace, with: authorInfo.authorEmail },
+ { toReplace: this.cfg.dateTemplateReplace, with: moment().format(dateFormat) },
+ { toReplace: this.cfg.yearTemplateReplace, with: moment().format("YYYY") },
+ { toReplace: "{file}", with: this.activeEditor.document.fileName.replace(/^.*[\\\/]/, "")},
+ ],
).split("\n"),
- ); // TODO: clean up this
+ );
}
});
}
@@ -407,7 +335,7 @@ export class CppDocGen implements IDocGen {
protected generateDateFromTemplate(lines: string[]) {
if (this.cfg.Generic.dateTemplate.trim().length !== 0 &&
this.cfg.Generic.dateFormat.trim().length !== 0) {
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.dateTemplateReplace,
this.cfg.Generic.dateTemplate,
@@ -467,7 +395,7 @@ export class CppDocGen implements IDocGen {
switch (element) {
case "tparam": {
if (this.cfg.Cpp.tparamTemplate.trim().length !== 0 && this.templateParams.length > 0) {
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.paramTemplateReplace,
this.cfg.Cpp.tparamTemplate,
@@ -479,7 +407,7 @@ export class CppDocGen implements IDocGen {
case "param": {
if (this.cfg.Generic.paramTemplate.trim().length !== 0 && this.params.length > 0) {
const paramNames: string[] = this.params.map((p) => p.name);
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.paramTemplateReplace,
this.cfg.Generic.paramTemplate,
@@ -491,7 +419,7 @@ export class CppDocGen implements IDocGen {
case "return": {
if (this.cfg.Generic.returnTemplate.trim().length !== 0 && this.func.type !== null) {
const returnParams = this.generateReturnParams();
- this.generateFromTemplate(
+ templates.generateFromTemplate(
lines,
this.cfg.typeTemplateReplace,
this.cfg.Generic.returnTemplate,
@@ -514,7 +442,7 @@ export class CppDocGen implements IDocGen {
this.insertFirstLine(lines);
this.insertLastLine(lines);
- return lines.join(`\n${this.getIndentation()}`);
+ return lines.join(`\n${getIndentation(this.activeEditor)}`);
}
protected moveCursurToFirstDoxyCommand(comment: string, baseLine: number, baseCharacter) {
diff --git a/src/templatedString.ts b/src/templatedString.ts
new file mode 100644
index 0000000..c397ad9
--- /dev/null
+++ b/src/templatedString.ts
@@ -0,0 +1,84 @@
+import { getEnvVars } from "./util";
+
+/**
+ * Represent a templated variable in string
+ */
+export interface ITemplate {
+ toReplace: string; // The template to be replaced in string
+ with: string; // The value to replace with
+}
+
+export function getIndentedTemplate(replace: string): string {
+ if (replace === "") {
+ return "";
+ }
+ const snippets = replace.split(/({indent:\d+})/);
+
+ let indentedString: string = "";
+ let indentWidth: number = 0;
+
+ // tslint:disable-next-line:prefer-for-of
+ snippets.forEach((element) => {
+ if (element.match(/{indent:\d+}/)) {
+ const indents = parseInt(element.match(/{indent:(\d+)}/)[1], 10);
+ indentWidth = indents;
+ const numSpaces = Math.max(indentWidth - indentedString.length, 0);
+ indentedString += " ".repeat(numSpaces);
+ } else {
+ // just some text
+ indentedString += element;
+ }
+ });
+
+ return indentedString;
+}
+
+/**
+ * Expand variable template in the string
+ * @param original the original string
+ * @param template variable template to be expanded
+ * @returns new string with expanded template
+ */
+export function getTemplatedString(original: string, template: ITemplate): string {
+ const replacedTemplate = original.replace(template.toReplace, template.with);
+ const replacedWithEnv = getEnvVars(replacedTemplate);
+ return getIndentedTemplate(replacedWithEnv);
+}
+
+/**
+ * Generate lines of doxygen comments from template
+ * @param lines Arrays to store lines of comments
+ * @param replace Variable template to be expanded
+ * @param template Original string that contains variable templates
+ * @param templateWith Arrays of values to replace in the original template string
+ */
+export function generateFromTemplate(
+ lines: string[],
+ replace: string,
+ template: string,
+ templateWith: string[],
+) {
+ templateWith.forEach((element: string) => {
+ // Ignore null values
+ if (element !== null) {
+ lines.push(...getTemplatedString(template, { toReplace: replace, with: element }).split("\n"));
+ }
+ });
+}
+
+/**
+ * Expand multiple variable templates in the string
+ * @param original string containing multiple variables to be expanded
+ * @param templates variable templates to be expanded
+ * @returns new string with expanded templates
+ */
+export function getMultiTemplatedString(
+ original: string,
+ templates: ITemplate[],
+): string {
+ // For each replace entry, attempt to replace it with the corresponding param in the template
+ for (const template of templates) {
+ original = original.replace(template.toReplace, template.with);
+ }
+ return getEnvVars(original);
+}
diff --git a/src/test/CppTests/Config.test.ts b/src/test/CppTests/Config.test.ts
index 1afbef3..f6ec573 100644
--- a/src/test/CppTests/Config.test.ts
+++ b/src/test/CppTests/Config.test.ts
@@ -11,6 +11,7 @@ import * as assert from "assert";
import * as moment from "moment";
import * as vscode from "vscode";
import { Config } from "../../Config";
+import GitConfig from "../../GitConfig";
import TestSetup from "./TestSetup";
// Defines a Mocha test suite to group tests of similar kind together
@@ -242,11 +243,12 @@ suite("C++ - Configuration Tests", () => {
"@author {author}",
"@date {date}",
"@note {email}",
+ "@file {file}",
];
- testSetup.cfg.Generic.useGitUserName = true;
- testSetup.cfg.Generic.useGitUserEmail = true;
const result = testSetup.SetLine("void foo();").GetResult();
- assert.notStrictEqual(result, "/**\n * @author {author}\n * @date {date}\n * @note {email}\n */");
+ const date = moment().format("YYYY-MM-DD");
+ assert.strictEqual(result, `/**\n * @author your name\n * @date ${date}\n * @note you@domain.com\n` +
+ ` * @file MockDocument.h\n */`);
});
test("Env variable", () => {
diff --git a/src/test/CppTests/FileDescription.test.ts b/src/test/CppTests/FileDescription.test.ts
index 2e0bb7e..ec0034d 100644
--- a/src/test/CppTests/FileDescription.test.ts
+++ b/src/test/CppTests/FileDescription.test.ts
@@ -78,9 +78,9 @@ suite("File Description Tests", () => {
test("custom block", () => {
testSetup.cfg.File.fileOrder = ["custom"];
testSetup.cfg.File.customTag = ["First Line", "{year} Year Line", "{date} Date Line",
- "{author} Author Line", "{email} Email Line"];
+ "{author} Author Line", "{email} Email Line", "{file} File Line"];
const result = testSetup.SetLine("").GetResult();
assert.strictEqual(result, "/**\n * First Line\n * " + year + " Year Line\n * " + date + " Date Line\n" +
- " * your name Author Line\n * you@domain.com Email Line\n */");
+ " * your name Author Line\n * you@domain.com Email Line\n" + " * MockDocument.h File Line\n */");
});
});
diff --git a/src/util.ts b/src/util.ts
new file mode 100644
index 0000000..f2068e7
--- /dev/null
+++ b/src/util.ts
@@ -0,0 +1,54 @@
+import * as env from "env-var";
+import * as vscode from "vscode";
+
+/**
+ * Check if a specific line is inside a comment block
+ * @param activeEditor the active editor
+ * @param activeLine the line number to be checked
+ */
+export function inComment(activeEditor: vscode.TextEditor, activeLine: number): boolean {
+ if (activeLine === 0) {
+ return false;
+ }
+
+ const txt: string = activeEditor.document.lineAt(activeLine - 1).text.trim();
+ if (!txt.startsWith("///") && !txt.startsWith("*") &&
+ !txt.startsWith("/**") && !txt.startsWith("/*!")) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+/**
+ * Get the indentation string for the current line (line at the current cursor position)
+ */
+export function getIndentation(editor: vscode.TextEditor = vscode.window.activeTextEditor): string {
+ return editor.document.lineAt(editor.selection.start.line).text.match("^\\s*")[0];
+}
+
+/**
+ * Expand enviroment variables in the string
+ * @param replace string containing environment variables
+ * @returns new string with expanded enviroment variables
+ */
+export function getEnvVars(replace: string): string {
+ let replacement = replace;
+ const regex = /\$\{env\:([\w|\d|_]+)\}/m;
+ let match: RegExpExecArray;
+
+ // tslint:disable-next-line:no-conditional-assignment
+ while ((match = regex.exec(replacement)) !== null) {
+ if (match.index === regex.lastIndex) {
+ regex.lastIndex++;
+ }
+
+ const m = match[1];
+
+ const envVar: string = env.get(m, m).asString();
+
+ replacement = replacement.replace("${env:" + m + "}", envVar);
+ }
+
+ return replacement;
+}