diff --git a/CHANGELOG.md b/CHANGELOG.md index 20c027a..8405298 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,12 @@ All notable changes to the "turbo-file-header" extension will be documented in this file. +# [0.2.5] + +## 新增功能 🌱 + +- feat: 函数注释支持 python + # [0.2.4] ## 新增功能 🌱 diff --git a/README.md b/README.md index f03df7d..26bd346 100644 --- a/README.md +++ b/README.md @@ -3,7 +3,7 @@ [![Visual Studio Marketplace Version](https://img.shields.io/visual-studio-marketplace/v/ygqygq2.turbo-file-header.svg?color=07c160&label=turbo-file-header&logo=visual-studio-code)](https://marketplace.visualstudio.com/items?itemName=ygqygq2.turbo-file-header) ![Visual Studio Marketplace Installs](https://img.shields.io/visual-studio-marketplace/i/ygqygq2.turbo-file-header) -[中文](README.zh-CN.md) +[中文](README.zh-CN.md) | [Wiki](https://github.com/ygqygq2/turbo-file-header/wiki) Turbo file header, sets file header information globally or for a project. diff --git a/README.zh-CN.md b/README.zh-CN.md index 698090c..1c2c89f 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -45,7 +45,7 @@ Properties: | 配置 `tags` 在明亮主题 | 明亮主题中的 `tags` 配置 | tagsLight | `[]` | | 配置 `tags` 在暗黑主题 | 暗黑主题中的 `tags` 配置 | tagsDark | `[]` | -**注意e**: +**注意**: - `include` 和 `exclude` 是为了控制文件头影响范围,`addFileheader` 命令不受它们影响。 - `author` 包含用户名/邮箱,如果文件被 VCS 追踪,将从 VCS 中获取用户信息,否则将使用备用用户名/邮箱. diff --git a/package.json b/package.json index d93108f..1517832 100644 --- a/package.json +++ b/package.json @@ -2,7 +2,7 @@ "name": "turbo-file-header", "displayName": "Turbo File Header", "description": "%description%", - "version": "0.2.4", + "version": "0.2.5", "icon": "resources/icons/icon.png", "repository": { "type": "git", diff --git a/sampleWorkspace/function-comment-for-python/function-none-params-with-return.py b/sampleWorkspace/function-comment-for-python/function-none-params-with-return.py new file mode 100644 index 0000000..252beab --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-none-params-with-return.py @@ -0,0 +1,2 @@ +def funcName () -> str: + return "test" diff --git a/sampleWorkspace/function-comment-for-python/function-none-params-with-return.result.py b/sampleWorkspace/function-comment-for-python/function-none-params-with-return.result.py new file mode 100644 index 0000000..36e343b --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-none-params-with-return.result.py @@ -0,0 +1,6 @@ +""" + * @description + * @return default {str} +""" +def funcName () -> str: + return "test" diff --git a/sampleWorkspace/function-comment-for-python/function-none-params-without-return.py b/sampleWorkspace/function-comment-for-python/function-none-params-without-return.py new file mode 100644 index 0000000..32a8b81 --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-none-params-without-return.py @@ -0,0 +1,2 @@ +def funcName (): + return "test" diff --git a/sampleWorkspace/function-comment-for-python/function-none-params-without-return.result.py b/sampleWorkspace/function-comment-for-python/function-none-params-without-return.result.py new file mode 100644 index 0000000..1bfd285 --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-none-params-without-return.result.py @@ -0,0 +1,6 @@ +""" + * @description + * @return default {auto} +""" +def funcName (): + return "test" diff --git a/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.py b/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.py new file mode 100644 index 0000000..ed56959 --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.py @@ -0,0 +1,2 @@ +def add(a='a', **kwargs) -> Union[int, float]: + return a + b diff --git a/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.result.py b/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.result.py new file mode 100644 index 0000000..b98817e --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-optional-params-with-return.result.py @@ -0,0 +1,8 @@ +""" + * @description + * @return default {Union[int, float]} + * @param [a='a'] {any} + * @param [kwargs] {any} +""" +def add(a='a', **kwargs) -> Union[int, float]: + return a + b diff --git a/sampleWorkspace/function-comment-for-python/function-with-params-with-return.result.py b/sampleWorkspace/function-comment-for-python/function-with-params-with-return.result.py new file mode 100644 index 0000000..cc1e219 --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-with-params-with-return.result.py @@ -0,0 +1,10 @@ +/** + * @description + * @return default {int} + * @param String {a} + * @param int {b} + */ +public int func(String a, int b) { + System.out.println("test"); + return 1; +} diff --git a/sampleWorkspace/function-comment-for-python/function-with-params-without-return.py b/sampleWorkspace/function-comment-for-python/function-with-params-without-return.py new file mode 100644 index 0000000..7683944 --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-with-params-without-return.py @@ -0,0 +1,2 @@ +def add(a: Union[int, float], b: Union[int, float]) -> Union[int, float]: + return a + b diff --git a/sampleWorkspace/function-comment-for-python/function-with-params-without-return.result.py b/sampleWorkspace/function-comment-for-python/function-with-params-without-return.result.py new file mode 100644 index 0000000..abfa53e --- /dev/null +++ b/sampleWorkspace/function-comment-for-python/function-with-params-without-return.result.py @@ -0,0 +1,8 @@ +""" + * @description + * @return default {Union[int, float]} + * @param a {Union[int, float]} + * @param b {Union[int, float]} +""" +def add(a: Union[int, float], b: Union[int, float]) -> Union[int, float]: + return a + b diff --git a/sampleWorkspace/test.code-workspace b/sampleWorkspace/test.code-workspace index bb53c1c..46361bd 100644 --- a/sampleWorkspace/test.code-workspace +++ b/sampleWorkspace/test.code-workspace @@ -5,6 +5,7 @@ { "path": "function-comment-for-ts" }, { "path": "function-comment-for-go" }, { "path": "function-comment-for-java" }, + { "path": "function-comment-for-python" }, { "path": "workspace" }, ], "settings": {}, diff --git a/src/fileheader/FileheaderManager.ts b/src/fileheader/FileheaderManager.ts index 402127f..f66e9d7 100644 --- a/src/fileheader/FileheaderManager.ts +++ b/src/fileheader/FileheaderManager.ts @@ -187,8 +187,8 @@ export class FileheaderManager { ); if (functionCommentInfo) { - const originFunctionComment = generateFunctionComment(originFunctionInfo, true); - const functionComment = generateFunctionComment(functionCommentInfo); + const originFunctionComment = generateFunctionComment(comments, originFunctionInfo, true); + const functionComment = generateFunctionComment(comments, functionCommentInfo); // 函数注释没有变化 if (originFunctionComment === functionComment) { logger.info('Not need update function comment:', document.uri.fsPath); diff --git a/src/function-params-parser/FunctionParserLoader.ts b/src/function-params-parser/FunctionParserLoader.ts index cf08ed2..fc44d8e 100644 --- a/src/function-params-parser/FunctionParserLoader.ts +++ b/src/function-params-parser/FunctionParserLoader.ts @@ -6,6 +6,7 @@ import { FunctionParamsParser } from './FunctionParamsParser'; import { GoParser } from './GoProvider'; import { JavaParser } from './JavaProvider'; import { JavascriptParser } from './JavascriptProvider'; +import { PythonParser } from './PythonProvider'; import { TypescriptParser } from './TypescriptProvider'; export class FunctionParserLoader { @@ -29,6 +30,7 @@ export class FunctionParserLoader { javascriptreact: JavascriptParser, go: GoParser, java: JavaParser, + python: PythonParser, }; public async loadParser(languageId: string): Promise { diff --git a/src/function-params-parser/GoProvider.ts b/src/function-params-parser/GoProvider.ts index 3bd75d5..553c5fc 100644 --- a/src/function-params-parser/GoProvider.ts +++ b/src/function-params-parser/GoProvider.ts @@ -157,10 +157,6 @@ export class GoParser extends FunctionParamsParser { const line = document.lineAt(i); functionDefinition += line.text + '\n'; - if (line.text.includes('=>') && !line.text.match(/=>\s*{/)) { - break; - } - for (const char of line.text) { if (char === '(') { parenthesisCount++; diff --git a/src/function-params-parser/JavaProvider.ts b/src/function-params-parser/JavaProvider.ts index 9e45eb8..acad7e3 100644 --- a/src/function-params-parser/JavaProvider.ts +++ b/src/function-params-parser/JavaProvider.ts @@ -7,7 +7,7 @@ import { escapeRegexString } from '@/utils/str'; import { extractFunctionParamsString } from './extractFunctionParamsString'; import { FunctionParamsParser } from './FunctionParamsParser'; -import { splitParams } from './go-splitParams'; +import { splitParams } from './java-splitParams'; import { FunctionParamsInfo, ParamsInfo, ReturnInfo } from './types'; function matchNormalFunction( @@ -113,10 +113,6 @@ export class JavaParser extends FunctionParamsParser { const line = document.lineAt(i); functionDefinition += line.text + '\n'; - if (line.text.includes('=>') && !line.text.match(/=>\s*{/)) { - break; - } - for (const char of line.text) { if (char === '(') { parenthesisCount++; diff --git a/src/function-params-parser/PythonProvider.ts b/src/function-params-parser/PythonProvider.ts new file mode 100644 index 0000000..e704b50 --- /dev/null +++ b/src/function-params-parser/PythonProvider.ts @@ -0,0 +1,157 @@ +import * as vscode from 'vscode'; + +import { ConfigManager } from '@/configuration/ConfigManager'; +import { logger } from '@/extension'; +import { LanguageFunctionCommentSettings } from '@/typings/types'; +import { escapeRegexString } from '@/utils/str'; + +import { extractFunctionParamsString } from './extractFunctionParamsString'; +import { FunctionParamsParser } from './FunctionParamsParser'; +import { splitParams } from './python-splitParams'; +import { FunctionParamsInfo, ParamsInfo, ReturnInfo } from './types'; + +function matchNormalFunction( + functionDefinition: string, + languageSettings: LanguageFunctionCommentSettings, +): { + matched: boolean; + returnType: ReturnInfo; + params: ParamsInfo; +} { + const { defaultReturnName = 'default', defaultReturnType = 'Any' } = languageSettings; + const returnType: ReturnInfo = {}; + let matched = false; + let params: ParamsInfo = {}; + + // 提取参数括号里的字符串 + const functionParamsStr = extractFunctionParamsString(functionDefinition); + const functionParamsRegStr = escapeRegexString(functionParamsStr); + const functionPattern = new RegExp( + `def\\s+([a-zA-Z0-9_]+)\\s*\\(${functionParamsRegStr}\\)\\s*(->\\s*(.*))?\\s*:`, + 'm', + ); + + const match = functionPattern.exec(functionDefinition); + + if (match) { + matched = true; + const returnTypeStr = match[3] ? match[3].trim() : defaultReturnType; + + returnType[defaultReturnName] = { + type: returnTypeStr, + description: '', + }; + + params = splitParams(functionParamsStr, languageSettings); + } + + return { matched, returnType, params }; +} + +/** + * @description + * @return default {auto} + */ +function matchFunction( + functionDefinition: string, + languageSettings: LanguageFunctionCommentSettings, +): { matched: boolean; returnType: ReturnInfo; params: ParamsInfo } { + const { defaultReturnName = 'default', defaultReturnType = 'Any' } = languageSettings; + let returnType: ReturnInfo = { + [defaultReturnName]: { type: defaultReturnType, description: '' }, + }; + let matched = false; + let params: ParamsInfo = {}; + + const matchers = [matchNormalFunction]; + + for (const matcher of matchers) { + const result = matcher(functionDefinition, languageSettings); + if (result.matched) { + matched = result.matched; + params = result.params; + returnType = result.returnType; + break; + } + } + + return { matched, returnType, params }; +} + +export class PythonParser extends FunctionParamsParser { + constructor(configManager: ConfigManager, languageId: string) { + super(configManager, languageId); + } + + private getFunctionString(document: vscode.TextDocument, startLine: number) { + let functionDefinition = ''; + let bracketCount = 0; // 大括号计数 + let parenthesisCount = 0; // 小括号计数 + let colonDetected = false; // 函数冒号检测 + + for (let i = startLine; i < document.lineCount; i++) { + const line = document.lineAt(i); + functionDefinition += line.text + '\n'; + + for (const char of line.text) { + if (char === '(') { + parenthesisCount++; + } else if (char === ')') { + parenthesisCount--; + } else if (char === '{') { + bracketCount++; + } else if (char === '}') { + bracketCount--; + } else if (char === ':' && parenthesisCount === 0) { + colonDetected = true; + } + } + + if (bracketCount === 0 && parenthesisCount === 0 && colonDetected) { + break; + } + } + + return functionDefinition; + } + + public getFunctionParamsAtCursor( + activeEditor: vscode.TextEditor, + languageSettings: LanguageFunctionCommentSettings = this.languageSettings, + ): FunctionParamsInfo { + let functionParams: ParamsInfo = {}; + let matchedFunction = false; + let returnType: ReturnInfo = {}; + const document = activeEditor.document; + const cursorLine = activeEditor.selection.start.line; + let startLine = cursorLine; + // 如果光标所在行为空行或者注释,则从下一行开始 + const cursorLineText = document.lineAt(cursorLine).text.trim(); + if (cursorLineText === '' || cursorLineText === '//' || cursorLineText === '*/') { + startLine = cursorLine + 1; + } + + const functionDefinition = this.getFunctionString(document, startLine); + const { + matched, + returnType: returnTypeTmp, + params, + } = matchFunction(functionDefinition, languageSettings); + if (matched) { + matchedFunction = true; + returnType = returnTypeTmp; + functionParams = params; + } + + if (!matchFunction) { + logger.info(vscode.l10n.t('No function found at the cursor')); + } + + return { + matchedFunction, + returnType, + params: functionParams, + insertPosition: new vscode.Position(startLine, 0), + }; + } +} diff --git a/src/function-params-parser/go-splitParams.ts b/src/function-params-parser/go-splitParams.ts index 55c0f4b..69edb92 100644 --- a/src/function-params-parser/go-splitParams.ts +++ b/src/function-params-parser/go-splitParams.ts @@ -17,7 +17,9 @@ export function splitParams( bracketCount++; } else if (char === ')' || char === ']' || char === '}' || char === '>') { bracketCount--; - } else if ( + } + + if ( (char === ',' && bracketCount === 0) || (i === paramsStr.length - 1 && bracketCount === 0) ) { diff --git a/src/function-params-parser/java-splitParams.ts b/src/function-params-parser/java-splitParams.ts index e1b89a8..c7a8720 100644 --- a/src/function-params-parser/java-splitParams.ts +++ b/src/function-params-parser/java-splitParams.ts @@ -17,7 +17,9 @@ export function splitParams( bracketCount++; } else if (char === ')' || char === ']' || char === '}' || char === '>') { bracketCount--; - } else if ( + } + + if ( (char === ',' && bracketCount === 0) || (i === paramsStr.length - 1 && bracketCount === 0) ) { diff --git a/src/function-params-parser/python-splitParams.ts b/src/function-params-parser/python-splitParams.ts new file mode 100644 index 0000000..6867ee7 --- /dev/null +++ b/src/function-params-parser/python-splitParams.ts @@ -0,0 +1,47 @@ +import { LanguageFunctionCommentSettings } from '@/typings/types'; + +import { ParamsInfo } from './types'; + +export function splitParams( + paramsStr: string, + languageSettings: LanguageFunctionCommentSettings, +): ParamsInfo { + const { defaultParamType = 'Any', defaultReturnName = 'default' } = languageSettings; + let bracketCount = 0; + let paramStartIndex = 0; + let defaultCount = 0; + const params: ParamsInfo = {}; + for (let i = 0; i < paramsStr?.length; i++) { + const char = paramsStr[i]; + if (char === '(' || char === '[' || char === '{' || char === '<') { + bracketCount++; + } else if (char === ')' || char === ']' || char === '}' || char === '>') { + bracketCount--; + } + + if ( + (char === ',' && bracketCount === 0) || + (i === paramsStr.length - 1 && bracketCount === 0) + ) { + const paramStr = paramsStr + .slice(paramStartIndex, i === paramsStr.length - 1 ? i + 1 : i) + .trim(); + + const paramPattern = /^(\*\*|\*)?(\w+)?\s*(:\s*(.*?))?(=\s*(.*))?$/; + const match = paramPattern.exec(paramStr); + if (match) { + const name = + match[2] || + (defaultCount > 0 ? `${defaultReturnName}${defaultCount++}` : defaultReturnName); + const type = match[4] || defaultParamType; + const optional = match[1] || match[6] ? { optional: true } : {}; + const defaultValue = match[6] ? { defaultValue: match[6] } : {}; + + params[name] = { type, description: '', ...optional, ...defaultValue }; + } + paramStartIndex = i + 1; + } + } + + return params; +} diff --git a/src/function-params-parser/ts-splitParams.ts b/src/function-params-parser/ts-splitParams.ts index 9601d59..e46e7d2 100644 --- a/src/function-params-parser/ts-splitParams.ts +++ b/src/function-params-parser/ts-splitParams.ts @@ -16,7 +16,9 @@ export function splitParams( bracketCount++; } else if (char === ')' || char === ']' || char === '}' || char === '>') { bracketCount--; - } else if ( + } + + if ( (char === ',' && bracketCount === 0) || (i === paramsStr.length - 1 && bracketCount === 0) ) { diff --git a/src/test/suite/python-functionComment.test.ts b/src/test/suite/python-functionComment.test.ts new file mode 100644 index 0000000..f8c33fa --- /dev/null +++ b/src/test/suite/python-functionComment.test.ts @@ -0,0 +1,17 @@ +import { functionCommentTester } from './common/functionCommentTester'; +import { TestInfo } from './types'; + +const testInfo: TestInfo = [ + { + testName: 'python-function', + workspaceName: 'function-comment-for-python', + files: [ + { fileName: 'function-none-params-with-return.py', cursorLine: 0 }, + { fileName: 'function-none-params-without-return.py', cursorLine: 0 }, + { fileName: 'function-optional-params-with-return.py', cursorLine: 0 }, + { fileName: 'function-with-params-without-return.py', cursorLine: 0 }, + ], + }, +]; + +functionCommentTester(testInfo); diff --git a/src/test/unit/utils/str.spec.ts b/src/test/unit/utils/str.spec.ts new file mode 100644 index 0000000..aa6110a --- /dev/null +++ b/src/test/unit/utils/str.spec.ts @@ -0,0 +1,121 @@ +import { describe, expect, it, test } from 'vitest'; + +import { escapeRegexString, removeSpecialString, trim, trimLeft, trimRight } from '@/utils/str'; + +test('escapeRegexString', () => { + const input = '.*+?^${}()|[\\/'; + const expected = '\\.\\*\\+\\?\\^\\$\\{\\}\\(\\)\\|\\[\\\\\\/'; + + const result = escapeRegexString(input); + + expect(result).toBe(expected); +}); + +describe('trim', () => { + it('should trim leading and trailing whitespace by default', () => { + const str = ' Hello, World! '; + const expected = 'Hello, World!'; + + const result = trim(str); + + expect(result).toBe(expected); + }); + + it('should trim leading and trailing specified character', () => { + const str = '***Hello, World!***'; + const char = '*'; + const expected = 'Hello, World!'; + + const result = trim(str, char); + + expect(result).toBe(expected); + }); + + it('should trim leading and trailing whitespace when no character is specified', () => { + const str = ' Hello, World! '; + const expected = 'Hello, World!'; + + const result = trim(str); + + expect(result).toBe(expected); + }); +}); + +describe('trimLeft', () => { + it('trimLeft', () => { + const input = ' Hello, World! '; + const expected = 'Hello, World! '; + + const result = trimLeft(input); + + expect(result).toBe(expected); + }); + + it('trimLeft with specific character', () => { + const input = '---Hello, World!---'; + const expected = 'Hello, World!---'; + + const result = trimLeft(input, '-'); + + expect(result).toBe(expected); + }); +}); + +describe('trimRight', () => { + it('should trim trailing whitespace by default', () => { + const str = 'Hello, World! '; + const expected = 'Hello, World!'; + + const result = trimRight(str); + + expect(result).toBe(expected); + }); + + it('should trim trailing specified character', () => { + const str = 'Hello, World!***'; + const char = '*'; + const expected = 'Hello, World!'; + + const result = trimRight(str, char); + + expect(result).toBe(expected); + }); + + it('should trim trailing whitespace when no character is specified', () => { + const str = 'Hello, World! '; + const expected = 'Hello, World!'; + + const result = trimRight(str); + + expect(result).toBe(expected); + }); +}); + +describe('removeSpecialString', () => { + it('should remove special string when regex is a single regular expression', () => { + const fileHeaderContent = 'Hello, /* World */!'; + const regex = /\/\*.*\*\//g; + + const result = removeSpecialString(fileHeaderContent, regex); + + expect(result).toBe('Hello, !'); + }); + + it('should remove special strings when regex is an array of regular expressions', () => { + const fileHeaderContent = 'Hello, /* World */! /* Goodbye */'; + const regex = [/\/\*.*?\*\//g, /\/\/.*/g]; + + const result = removeSpecialString(fileHeaderContent, regex); + + expect(result).toBe('Hello, ! '); + }); + + it('should return the same string when no special string is found', () => { + const fileHeaderContent = 'Hello, World!'; + const regex = /\/\*.*\*\//g; + + const result = removeSpecialString(fileHeaderContent, regex); + + expect(result).toBe(fileHeaderContent); + }); +}); diff --git a/src/test/unit/utils/utils.spec.ts b/src/test/unit/utils/utils.spec.ts new file mode 100644 index 0000000..a206626 --- /dev/null +++ b/src/test/unit/utils/utils.spec.ts @@ -0,0 +1,31 @@ +import { describe, expect, it } from 'vitest'; + +import { TEMPLATE_SYMBOL_KEY } from '@/constants'; +import { getTaggedTemplateInputs, hasShebang } from '@/utils/utils'; + +describe('hasShebang', () => { + it('should return true if the text has a shebang', () => { + const text = '#!/usr/bin/env node'; + const result = hasShebang(text); + expect(result).toBe(true); + }); + + it('should return false if the text does not have a shebang', () => { + const text = 'console.log("Hello, world!");'; + const result = hasShebang(text); + expect(result).toBe(false); + }); +}); + +describe('getTaggedTemplateInputs', () => { + it('should return the tagged template inputs', () => { + const strings = ['Hello', 'World'] as unknown as TemplateStringsArray; + const interpolations = [1, 2]; + const result = getTaggedTemplateInputs(strings, ...interpolations); + expect(result).toEqual({ + [TEMPLATE_SYMBOL_KEY]: true, + strings, + interpolations, + }); + }); +}); diff --git a/src/utils/log.ts b/src/utils/log.ts deleted file mode 100644 index ae5e5e7..0000000 --- a/src/utils/log.ts +++ /dev/null @@ -1,5 +0,0 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const log = (...args: any[]) => { - const line = args.map((obj) => (typeof obj === 'object' ? JSON.stringify(obj) : obj)).join(' '); - return line; -}; diff --git a/src/utils/vscode-utils.ts b/src/utils/vscode-utils.ts index 86447ca..d20fd90 100644 --- a/src/utils/vscode-utils.ts +++ b/src/utils/vscode-utils.ts @@ -274,10 +274,12 @@ export function updateBlockCommentState( } export function generateFunctionComment( + comments: vscode.CommentRule, functionCommentInfo: FunctionCommentInfo, isOrigin: boolean = false, ): string { const { paramsInfo, returnInfo, descriptionInfo } = functionCommentInfo; + const { blockCommentStart, blockCommentEnd } = getBlockComment(comments); if (isOrigin) { if ( @@ -289,24 +291,34 @@ export function generateFunctionComment( } } - let functionComment = '/**\n'; - functionComment += ` * @description ${descriptionInfo}\n`; + let functionComment = ''; + let lineStart = ''; + if (comments && comments?.blockComment && comments?.blockComment.length) { + lineStart = ` `; + } else { + lineStart = `${blockCommentStart} `; + } + + functionComment += `${blockCommentStart === '/*' ? '/**' : blockCommentStart}\n`; + functionComment += `${lineStart}* @description ${descriptionInfo}\n`; for (const returnKey in returnInfo) { - functionComment += ` * @return ${returnKey} {${returnInfo[returnKey].type}} ${returnInfo[returnKey].description}\n`; + functionComment += `${lineStart}* @return ${returnKey} {${returnInfo[returnKey].type}} ${returnInfo[returnKey].description}\n`; } for (const paramName in paramsInfo) { if (paramsInfo[paramName]?.defaultValue) { - functionComment += ` * @param [${paramName}=${paramsInfo[paramName].defaultValue}] {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description} \n`; + functionComment += `${lineStart}* @param [${paramName}=${paramsInfo[paramName].defaultValue}] {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description} \n`; } else if (paramsInfo[paramName]?.optional) { - functionComment += ` * @param [${paramName}] {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description}\n`; + functionComment += `${lineStart}* @param [${paramName}] {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description}\n`; } else { - functionComment += ` * @param ${paramName} {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description}\n`; + functionComment += `${lineStart}* @param ${paramName} {${paramsInfo[paramName].type}} ${paramsInfo[paramName].description}\n`; } } - functionComment += ' */'; + functionComment += + blockCommentEnd === '*/' ? `${lineStart}${blockCommentEnd}` : `${blockCommentEnd}`; + return functionComment; }