From c269b044c3bb24f26a618252504f00760c3784a2 Mon Sep 17 00:00:00 2001 From: Joel Date: Tue, 2 Dec 2025 15:43:33 +0800 Subject: [PATCH] feat: detect the cognitive-complexity of file --- web/calculate-complexity.js | 79 ++++++++++++++++++++++++++ web/package.json | 1 + web/pnpm-lock.yaml | 107 ++++++++++++++++++++++++++++++------ 3 files changed, 170 insertions(+), 17 deletions(-) create mode 100644 web/calculate-complexity.js diff --git a/web/calculate-complexity.js b/web/calculate-complexity.js new file mode 100644 index 0000000000..3d7666e286 --- /dev/null +++ b/web/calculate-complexity.js @@ -0,0 +1,79 @@ +// https://www.sonarsource.com/blog/5-clean-code-tips-for-reducing-cognitive-complexity/ +const fs = require('fs'); +const { Linter } = require('eslint'); +const sonarPlugin = require('eslint-plugin-sonarjs'); +const tsParser = require('@typescript-eslint/parser'); + +const linter = new Linter(); + +const config = { + languageOptions: { + parser: tsParser, + parserOptions: { + ecmaVersion: 'latest', + sourceType: 'module', + ecmaFeatures: { + jsx: true + } + } + }, + plugins: { + sonarjs: sonarPlugin, + }, + rules: { + 'sonarjs/cognitive-complexity': ['error', 0], // always show error + }, +}; + +function getFileComplexity(filePath) { + try { + const code = fs.readFileSync(filePath, 'utf8'); + + const messages = linter.verify(code, config); + + let totalFileComplexity = 0; + let maxFileComplexityIndex = 0; + const functionComplexities = []; + + messages.forEach((msg) => { + // console.log(msg); + if (msg.ruleId === 'sonarjs/cognitive-complexity') { + const match = msg.message.match(/reduce its Cognitive Complexity from (\d+)/); + if (match && match[1]) { + const score = parseInt(match[1], 10); + totalFileComplexity += score; + if (score > functionComplexities[maxFileComplexityIndex]?.score || functionComplexities.length === 0) { + maxFileComplexityIndex = functionComplexities.length; + } + + functionComplexities.push({ + line: msg.line, + // functionName: extractFunctionName(code, msg.line), // 可选:尝试获取函数名 + score: score, + // message: msg.message + }); + } + } + }); + + return { + file: filePath, + totalComplexity: totalFileComplexity, + maxFileComplexity: functionComplexities[maxFileComplexityIndex], + details: functionComplexities + }; + + } catch (error) { + console.error(`Error processing file ${filePath}:`, error); + return null; + } +} + +// const targetFile = './app/components/share/text-generation/run-once/index.tsx'; // "totalComplexity": 22 +const targetFile = './app/components/share/text-generation/index.tsx'; // 90, max: 41 +// const targetFile = './app/components/workflow/nodes/_base/components/workflow-panel/index.tsx'; // 33 +// const targetFile = './app/components/app/configuration/index.tsx'; // 111, max: 26 + + +const result = getFileComplexity(targetFile); +console.log(JSON.stringify(result, null, 2)); diff --git a/web/package.json b/web/package.json index 11a8763566..3d91ba4250 100644 --- a/web/package.json +++ b/web/package.json @@ -179,6 +179,7 @@ "@types/semver": "^7.7.1", "@types/sortablejs": "^1.15.8", "@types/uuid": "^10.0.0", + "@typescript-eslint/parser": "^8.48.0", "autoprefixer": "^10.4.21", "babel-loader": "^10.0.0", "bing-translate-api": "^4.1.0", diff --git a/web/pnpm-lock.yaml b/web/pnpm-lock.yaml index 6038ec0153..e76f6ec4fb 100644 --- a/web/pnpm-lock.yaml +++ b/web/pnpm-lock.yaml @@ -457,6 +457,9 @@ importers: '@types/uuid': specifier: ^10.0.0 version: 10.0.0 + '@typescript-eslint/parser': + specifier: ^8.48.0 + version: 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) autoprefixer: specifier: ^10.4.21 version: 10.4.21(postcss@8.5.6) @@ -3386,8 +3389,8 @@ packages: eslint: ^8.57.0 || ^9.0.0 typescript: '>=4.8.4 <6.0.0' - '@typescript-eslint/parser@8.46.2': - resolution: {integrity: sha512-BnOroVl1SgrPLywqxyqdJ4l3S2MsKVLDVxZvjI1Eoe8ev2r3kGDo+PcMihNmDE+6/KjkTubSJnmqGZZjQSBq/g==} + '@typescript-eslint/parser@8.48.0': + resolution: {integrity: sha512-jCzKdm/QK0Kg4V4IK/oMlRZlY+QOcdjv89U2NgKHZk1CYTj82/RVSx1mV/0gqCVMJ/DA+Zf/S4NBWNF8GQ+eqQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 @@ -3399,16 +3402,32 @@ packages: peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/project-service@8.48.0': + resolution: {integrity: sha512-Ne4CTZyRh1BecBf84siv42wv5vQvVmgtk8AuiEffKTUo3DrBaGYZueJSxxBZ8fjk/N3DrgChH4TOdIOwOwiqqw==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/scope-manager@8.46.2': resolution: {integrity: sha512-LF4b/NmGvdWEHD2H4MsHD8ny6JpiVNDzrSZr3CsckEgCbAGZbYM4Cqxvi9L+WqDMT+51Ozy7lt2M+d0JLEuBqA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/scope-manager@8.48.0': + resolution: {integrity: sha512-uGSSsbrtJrLduti0Q1Q9+BF1/iFKaxGoQwjWOIVNJv0o6omrdyR8ct37m4xIl5Zzpkp69Kkmvom7QFTtue89YQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/tsconfig-utils@8.46.2': resolution: {integrity: sha512-a7QH6fw4S57+F5y2FIxxSDyi5M4UfGF+Jl1bCGd7+L4KsaUY80GsiF/t0UoRFDHAguKlBaACWJRmdrc6Xfkkag==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/tsconfig-utils@8.48.0': + resolution: {integrity: sha512-WNebjBdFdyu10sR1M4OXTt2OkMd5KWIL+LLfeH9KhgP+jzfDV/LI3eXzwJ1s9+Yc0Kzo2fQCdY/OpdusCMmh6w==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/type-utils@8.46.2': resolution: {integrity: sha512-HbPM4LbaAAt/DjxXaG9yiS9brOOz6fabal4uvUmaUYe6l3K1phQDMQKBRUrr06BQkxkvIZVVHttqiybM9nJsLA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3420,12 +3439,22 @@ packages: resolution: {integrity: sha512-lNCWCbq7rpg7qDsQrd3D6NyWYu+gkTENkG5IKYhUIcxSb59SQC/hEQ+MrG4sTgBVghTonNWq42bA/d4yYumldQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/types@8.48.0': + resolution: {integrity: sha512-cQMcGQQH7kwKoVswD1xdOytxQR60MWKM1di26xSUtxehaDs/32Zpqsu5WJlXTtTTqyAVK8R7hvsUnIXRS+bjvA==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/typescript-estree@8.46.2': resolution: {integrity: sha512-f7rW7LJ2b7Uh2EiQ+7sza6RDZnajbNbemn54Ob6fRwQbgcIn+GWfyuHDHRYgRoZu1P4AayVScrRW+YfbTvPQoQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/typescript-estree@8.48.0': + resolution: {integrity: sha512-ljHab1CSO4rGrQIAyizUS6UGHHCiAYhbfcIZ1zVJr5nMryxlXMVWS3duFPSKvSUbFPwkXMFk1k0EMIjub4sRRQ==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + peerDependencies: + typescript: '>=4.8.4 <6.0.0' + '@typescript-eslint/utils@8.46.2': resolution: {integrity: sha512-sExxzucx0Tud5tE0XqR0lT0psBQvEpnpiul9XbGUB1QwpWJJAps1O/Z7hJxLGiZLBKMCutjTzDgmd1muEhBnVg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3437,6 +3466,10 @@ packages: resolution: {integrity: sha512-tUFMXI4gxzzMXt4xpGJEsBsTox0XbNQ1y94EwlD/CuZwFcQP79xfQqMhau9HsRc/J0cAPA/HZt1dZPtGn9V/7w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@typescript-eslint/visitor-keys@8.48.0': + resolution: {integrity: sha512-T0XJMaRPOH3+LBbAfzR2jalckP1MSG/L9eUtY0DEzUyVaXJ/t6zN0nR7co5kz0Jko/nkSYCBRkz1djvjajVTTg==} + engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} + '@ungap/structured-clone@1.3.0': resolution: {integrity: sha512-WmoN8qaIAo7WTYWbAZuG8PYEhn5fkz7dZrqTBZ7dtt//lL2Gwms1IcnQ5yHqjDfX8Ft5j4YzDM23f87zBfDe9g==} @@ -8503,8 +8536,8 @@ snapshots: '@eslint-community/eslint-plugin-eslint-comments': 4.5.0(eslint@9.38.0(jiti@1.21.7)) '@eslint/markdown': 7.4.1 '@stylistic/eslint-plugin': 5.5.0(eslint@9.38.0(jiti@1.21.7)) - '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) '@vitest/eslint-plugin': 1.3.23(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) ansis: 4.2.0 cac: 6.7.14 @@ -8524,8 +8557,8 @@ snapshots: eslint-plugin-regexp: 2.10.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-toml: 0.12.0(eslint@9.38.0(jiti@1.21.7)) eslint-plugin-unicorn: 61.0.2(eslint@9.38.0(jiti@1.21.7)) - eslint-plugin-unused-imports: 4.3.0(@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7)) - eslint-plugin-vue: 10.5.1(@stylistic/eslint-plugin@5.5.0(eslint@9.38.0(jiti@1.21.7)))(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@1.21.7))) + eslint-plugin-unused-imports: 4.3.0(@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7)) + eslint-plugin-vue: 10.5.1(@stylistic/eslint-plugin@5.5.0(eslint@9.38.0(jiti@1.21.7)))(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@1.21.7))) eslint-plugin-yml: 1.19.0(eslint@9.38.0(jiti@1.21.7)) eslint-processor-vue-blocks: 2.0.0(@vue/compiler-sfc@3.5.22)(eslint@9.38.0(jiti@1.21.7)) globals: 16.4.0 @@ -11831,10 +11864,10 @@ snapshots: dependencies: '@types/yargs-parser': 21.0.3 - '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/regexpp': 4.12.1 - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/scope-manager': 8.46.2 '@typescript-eslint/type-utils': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) '@typescript-eslint/utils': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) @@ -11848,12 +11881,12 @@ snapshots: transitivePeerDependencies: - supports-color - '@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': + '@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: - '@typescript-eslint/scope-manager': 8.46.2 - '@typescript-eslint/types': 8.46.2 - '@typescript-eslint/typescript-estree': 8.46.2(typescript@5.9.3) - '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/scope-manager': 8.48.0 + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/typescript-estree': 8.48.0(typescript@5.9.3) + '@typescript-eslint/visitor-keys': 8.48.0 debug: 4.4.3 eslint: 9.38.0(jiti@1.21.7) typescript: 5.9.3 @@ -11869,15 +11902,33 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/project-service@8.48.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3) + '@typescript-eslint/types': 8.48.0 + debug: 4.4.3 + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/scope-manager@8.46.2': dependencies: '@typescript-eslint/types': 8.46.2 '@typescript-eslint/visitor-keys': 8.46.2 + '@typescript-eslint/scope-manager@8.48.0': + dependencies: + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 + '@typescript-eslint/tsconfig-utils@8.46.2(typescript@5.9.3)': dependencies: typescript: 5.9.3 + '@typescript-eslint/tsconfig-utils@8.48.0(typescript@5.9.3)': + dependencies: + typescript: 5.9.3 + '@typescript-eslint/type-utils@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@typescript-eslint/types': 8.46.2 @@ -11892,6 +11943,8 @@ snapshots: '@typescript-eslint/types@8.46.2': {} + '@typescript-eslint/types@8.48.0': {} + '@typescript-eslint/typescript-estree@8.46.2(typescript@5.9.3)': dependencies: '@typescript-eslint/project-service': 8.46.2(typescript@5.9.3) @@ -11908,6 +11961,21 @@ snapshots: transitivePeerDependencies: - supports-color + '@typescript-eslint/typescript-estree@8.48.0(typescript@5.9.3)': + dependencies: + '@typescript-eslint/project-service': 8.48.0(typescript@5.9.3) + '@typescript-eslint/tsconfig-utils': 8.48.0(typescript@5.9.3) + '@typescript-eslint/types': 8.48.0 + '@typescript-eslint/visitor-keys': 8.48.0 + debug: 4.4.3 + minimatch: 9.0.5 + semver: 7.7.3 + tinyglobby: 0.2.15 + ts-api-utils: 2.1.0(typescript@5.9.3) + typescript: 5.9.3 + transitivePeerDependencies: + - supports-color + '@typescript-eslint/utils@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@1.21.7)) @@ -11924,6 +11992,11 @@ snapshots: '@typescript-eslint/types': 8.46.2 eslint-visitor-keys: 4.2.1 + '@typescript-eslint/visitor-keys@8.48.0': + dependencies: + '@typescript-eslint/types': 8.48.0 + eslint-visitor-keys: 4.2.1 + '@ungap/structured-clone@1.3.0': {} '@vitest/eslint-plugin@1.3.23(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3)': @@ -13651,13 +13724,13 @@ snapshots: semver: 7.7.3 strip-indent: 4.1.1 - eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7)): + eslint-plugin-unused-imports@4.3.0(@typescript-eslint/eslint-plugin@8.46.2(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7)): dependencies: eslint: 9.38.0(jiti@1.21.7) optionalDependencies: - '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/eslint-plugin': 8.46.2(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) - eslint-plugin-vue@10.5.1(@stylistic/eslint-plugin@5.5.0(eslint@9.38.0(jiti@1.21.7)))(@typescript-eslint/parser@8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@1.21.7))): + eslint-plugin-vue@10.5.1(@stylistic/eslint-plugin@5.5.0(eslint@9.38.0(jiti@1.21.7)))(@typescript-eslint/parser@8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3))(eslint@9.38.0(jiti@1.21.7))(vue-eslint-parser@10.2.0(eslint@9.38.0(jiti@1.21.7))): dependencies: '@eslint-community/eslint-utils': 4.9.0(eslint@9.38.0(jiti@1.21.7)) eslint: 9.38.0(jiti@1.21.7) @@ -13669,7 +13742,7 @@ snapshots: xml-name-validator: 4.0.0 optionalDependencies: '@stylistic/eslint-plugin': 5.5.0(eslint@9.38.0(jiti@1.21.7)) - '@typescript-eslint/parser': 8.46.2(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) + '@typescript-eslint/parser': 8.48.0(eslint@9.38.0(jiti@1.21.7))(typescript@5.9.3) eslint-plugin-yml@1.19.0(eslint@9.38.0(jiti@1.21.7)): dependencies: