mirror of
https://github.com/langgenius/dify.git
synced 2025-12-19 22:28:46 +00:00
129 lines
3.6 KiB
JavaScript
129 lines
3.6 KiB
JavaScript
// https://www.sonarsource.com/blog/5-clean-code-tips-for-reducing-cognitive-complexity/
|
|
const fs = require('fs');
|
|
const path = require('path');
|
|
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,
|
|
maxComplexityInfo: functionComplexities[maxFileComplexityIndex],
|
|
details: functionComplexities
|
|
};
|
|
|
|
} catch (error) {
|
|
console.error(`Error processing file ${filePath}:`, error);
|
|
return null;
|
|
}
|
|
}
|
|
|
|
function collectTsxFiles(baseDir) {
|
|
const entries = fs.readdirSync(baseDir, { withFileTypes: true });
|
|
const files = [];
|
|
|
|
entries.forEach((entry) => {
|
|
const fullPath = path.join(baseDir, entry.name);
|
|
|
|
if (entry.isDirectory()) {
|
|
if (
|
|
entry.name === 'node_modules' ||
|
|
entry.name.startsWith('.') ||
|
|
entry.name === '__test__' ||
|
|
entry.name === '__tests__'
|
|
) {
|
|
return;
|
|
}
|
|
files.push(...collectTsxFiles(fullPath));
|
|
} else if (
|
|
entry.isFile() &&
|
|
entry.name.endsWith('.tsx') &&
|
|
!entry.name.endsWith('.spec.tsx') &&
|
|
!entry.name.endsWith('.test.tsx')
|
|
) {
|
|
files.push(fullPath);
|
|
}
|
|
});
|
|
|
|
return files;
|
|
}
|
|
|
|
function writeCsv(results, outputPath) {
|
|
const header = 'File,Total Complexity,Max Complexity,Max Complexity Line';
|
|
const rows = results.map(({ file, totalComplexity, maxComplexityInfo }) => {
|
|
const maxScore = maxComplexityInfo?.score ?? 0;
|
|
const maxLine = maxComplexityInfo?.line ?? '';
|
|
const targetFile = JSON.stringify(path.relative(process.cwd(), file));
|
|
return `${targetFile},${totalComplexity},${maxScore},${maxLine}`;
|
|
});
|
|
|
|
fs.writeFileSync(outputPath, [header, ...rows].join('\n'), 'utf8');
|
|
}
|
|
|
|
function main() {
|
|
const projectRoot = process.cwd();
|
|
const tsxFiles = collectTsxFiles(projectRoot);
|
|
const results = tsxFiles
|
|
.map(getFileComplexity)
|
|
.filter((item) => item && item.totalComplexity > 0)
|
|
.sort((a, b) => b.maxComplexityInfo?.score - a.maxComplexityInfo?.score);
|
|
|
|
const outputPath = path.join(projectRoot, 'complexity-report.csv');
|
|
writeCsv(results, outputPath);
|
|
console.log(`CSV report written to ${outputPath}`);
|
|
}
|
|
|
|
main();
|