ts-analyzer 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +356 -0
- package/bin/cli.js +4 -0
- package/bin/cli.ts +241 -0
- package/dist/bin/cli.d.ts +2 -0
- package/dist/bin/cli.js +215 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/src/code-complexity.d.ts +24 -0
- package/dist/src/code-complexity.js +338 -0
- package/dist/src/code-complexity.js.map +1 -0
- package/dist/src/index.d.ts +47 -0
- package/dist/src/index.js +115 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/table-formatter.d.ts +6 -0
- package/dist/src/table-formatter.js +82 -0
- package/dist/src/table-formatter.js.map +1 -0
- package/dist/src/typescript-safety.d.ts +27 -0
- package/dist/src/typescript-safety.js +287 -0
- package/dist/src/typescript-safety.js.map +1 -0
- package/package.json +51 -0
- package/src/code-complexity.ts +431 -0
- package/src/index.ts +180 -0
- package/src/table-formatter.ts +94 -0
- package/src/typescript-safety.ts +346 -0
- package/tsconfig.json +18 -0
package/dist/bin/cli.js
ADDED
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// bin/cli.ts
|
|
3
|
+
import { Command } from 'commander';
|
|
4
|
+
import chalk from 'chalk';
|
|
5
|
+
import ora from 'ora';
|
|
6
|
+
import { analyzeProject } from '../src/index.js';
|
|
7
|
+
import { formatTable } from '../src/table-formatter.js';
|
|
8
|
+
const program = new Command();
|
|
9
|
+
program
|
|
10
|
+
.name('ts-analyzer')
|
|
11
|
+
.description('Comprehensive TypeScript code analyzer with type safety and complexity metrics')
|
|
12
|
+
.version('1.1.2')
|
|
13
|
+
.argument('[dir]', 'project directory to analyze', '.')
|
|
14
|
+
.option('-e, --exclude <patterns>', 'additional patterns to exclude (comma-separated)')
|
|
15
|
+
.option('-i, --include <extensions>', 'additional file extensions to include (comma-separated)')
|
|
16
|
+
.option('--no-color', 'disable colored output')
|
|
17
|
+
.option('--no-safety', 'disable TypeScript safety analysis')
|
|
18
|
+
.option('--no-complexity', 'disable code complexity analysis')
|
|
19
|
+
.action(async (dir, options) => {
|
|
20
|
+
const spinner = ora('Analyzing React project...').start();
|
|
21
|
+
const useColors = options.color !== false;
|
|
22
|
+
try {
|
|
23
|
+
const extraExcludes = options.exclude ? options.exclude.split(',') : [];
|
|
24
|
+
const extraExtensions = options.include ? options.include.split(',').map(ext => ext.startsWith('.') ? ext : `.${ext}`) : [];
|
|
25
|
+
const stats = await analyzeProject(dir, {
|
|
26
|
+
excludePatterns: extraExcludes,
|
|
27
|
+
additionalExtensions: extraExtensions,
|
|
28
|
+
analyzeSafety: options.safety !== false,
|
|
29
|
+
analyzeComplexity: options.complexity !== false
|
|
30
|
+
});
|
|
31
|
+
spinner.succeed('Analysis complete!');
|
|
32
|
+
// Print summary table
|
|
33
|
+
console.log('\n' + (useColors ? chalk.bold.green('Project Summary:') : 'Project Summary:'));
|
|
34
|
+
formatTable([
|
|
35
|
+
{ metric: 'Total Files', value: stats.formatNumber(stats.files) },
|
|
36
|
+
{ metric: 'Total Lines', value: stats.formatNumber(stats.totalLines) },
|
|
37
|
+
{ metric: 'Code Lines', value: stats.formatNumber(stats.codeLines) },
|
|
38
|
+
{ metric: 'Comment Lines', value: stats.formatNumber(stats.commentLines) },
|
|
39
|
+
{ metric: 'Empty Lines', value: stats.formatNumber(stats.emptyLines) }
|
|
40
|
+
]);
|
|
41
|
+
// Print file types table
|
|
42
|
+
console.log('\n' + (useColors ? chalk.bold.green('Files by Type:') : 'Files by Type:'));
|
|
43
|
+
formatTable(stats.formattedFileTypes);
|
|
44
|
+
// Print TypeScript safety metrics if available
|
|
45
|
+
if (stats.typescriptSafety) {
|
|
46
|
+
console.log('\n' + (useColors ? chalk.bold.green('TypeScript Safety:') : 'TypeScript Safety:'));
|
|
47
|
+
// Prepare safety indicators
|
|
48
|
+
let safetyIndicator;
|
|
49
|
+
if (stats.typescriptSafety.avgTypeSafetyScore >= 80) {
|
|
50
|
+
safetyIndicator = useColors ? chalk.green('Good ✓') : 'Good ✓';
|
|
51
|
+
}
|
|
52
|
+
else if (stats.typescriptSafety.avgTypeSafetyScore >= 50) {
|
|
53
|
+
safetyIndicator = useColors ? chalk.yellow('Moderate ⚠') : 'Moderate ⚠';
|
|
54
|
+
}
|
|
55
|
+
else {
|
|
56
|
+
safetyIndicator = useColors ? chalk.red('Poor ✗') : 'Poor ✗';
|
|
57
|
+
}
|
|
58
|
+
let safetyRating;
|
|
59
|
+
if (stats.typescriptSafety.overallComplexity === 'Low') {
|
|
60
|
+
safetyRating = useColors ? chalk.green('Low') : 'Low';
|
|
61
|
+
}
|
|
62
|
+
else if (stats.typescriptSafety.overallComplexity === 'Medium') {
|
|
63
|
+
safetyRating = useColors ? chalk.yellow('Medium') : 'Medium';
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
safetyRating = useColors ? chalk.red('High') : 'High';
|
|
67
|
+
}
|
|
68
|
+
// Create coverage evaluation
|
|
69
|
+
let coverageEvaluation;
|
|
70
|
+
const typeCoverage = parseFloat(stats.typescriptSafety.avgTypeCoverage);
|
|
71
|
+
if (typeCoverage >= 95) {
|
|
72
|
+
coverageEvaluation = useColors ? chalk.green('(Excellent)') : '(Excellent)';
|
|
73
|
+
}
|
|
74
|
+
else if (typeCoverage >= 85) {
|
|
75
|
+
coverageEvaluation = useColors ? chalk.green('(Good)') : '(Good)';
|
|
76
|
+
}
|
|
77
|
+
else if (typeCoverage >= 70) {
|
|
78
|
+
coverageEvaluation = useColors ? chalk.yellow('(Moderate)') : '(Moderate)';
|
|
79
|
+
}
|
|
80
|
+
else {
|
|
81
|
+
coverageEvaluation = useColors ? chalk.red('(Needs Improvement)') : '(Needs Improvement)';
|
|
82
|
+
}
|
|
83
|
+
formatTable([
|
|
84
|
+
{ metric: 'TypeScript Files', value: `${stats.formatNumber(stats.typescriptSafety.tsFileCount)} (${stats.typescriptSafety.tsPercentage}% of codebase)` },
|
|
85
|
+
{ metric: 'Type Coverage', value: `${stats.typescriptSafety.avgTypeCoverage}% ${coverageEvaluation}` },
|
|
86
|
+
{ metric: 'Any Type Usage', value: stats.formatNumber(stats.typescriptSafety.totalAnyCount) },
|
|
87
|
+
{ metric: 'Type Assertions', value: stats.formatNumber(stats.typescriptSafety.totalAssertions) },
|
|
88
|
+
{ metric: 'Non-Null Assertions', value: stats.formatNumber(stats.typescriptSafety.totalNonNullAssertions) },
|
|
89
|
+
{ metric: 'Type Safety Score', value: `${stats.typescriptSafety.avgTypeSafetyScore}/100 (${safetyIndicator})` },
|
|
90
|
+
{ metric: 'Type Safety Rating', value: safetyRating }
|
|
91
|
+
]);
|
|
92
|
+
// Add explanation about TypeScript metrics
|
|
93
|
+
console.log('\n' + (useColors ? chalk.italic('Type Coverage:') : 'Type Coverage:'));
|
|
94
|
+
console.log(useColors
|
|
95
|
+
? chalk.italic('• Measures the percentage of code elements that have proper type information')
|
|
96
|
+
: '• Measures the percentage of code elements that have proper type information');
|
|
97
|
+
console.log(useColors
|
|
98
|
+
? chalk.italic('• Includes both explicit type annotations and TypeScript\'s type inference')
|
|
99
|
+
: '• Includes both explicit type annotations and TypeScript\'s type inference');
|
|
100
|
+
console.log(useColors
|
|
101
|
+
? chalk.italic('• Industry standard for production TypeScript is 85-95% coverage')
|
|
102
|
+
: '• Industry standard for production TypeScript is 85-95% coverage');
|
|
103
|
+
console.log('\n' + (useColors ? chalk.italic('Type Safety Score:') : 'Type Safety Score:'));
|
|
104
|
+
console.log(useColors
|
|
105
|
+
? chalk.italic('• Comprehensive evaluation that considers type coverage, "any" usage, and type assertions')
|
|
106
|
+
: '• Comprehensive evaluation that considers type coverage, "any" usage, and type assertions');
|
|
107
|
+
console.log(useColors
|
|
108
|
+
? chalk.italic('• Also accounts for TypeScript configuration in tsconfig.json')
|
|
109
|
+
: '• Also accounts for TypeScript configuration in tsconfig.json');
|
|
110
|
+
}
|
|
111
|
+
// Print code complexity metrics if available
|
|
112
|
+
if (stats.codeComplexity) {
|
|
113
|
+
console.log('\n' + (useColors ? chalk.bold.green('Code Complexity:') : 'Code Complexity:'));
|
|
114
|
+
// Prepare complexity indicator
|
|
115
|
+
let complexityIndicator;
|
|
116
|
+
if (stats.codeComplexity.overallComplexity === 'Low') {
|
|
117
|
+
complexityIndicator = useColors ? chalk.green('Simple ✓') : 'Simple ✓';
|
|
118
|
+
}
|
|
119
|
+
else if (stats.codeComplexity.overallComplexity === 'Medium') {
|
|
120
|
+
complexityIndicator = useColors ? chalk.yellow('Moderate ⚠') : 'Moderate ⚠';
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
complexityIndicator = useColors ? chalk.red('Complex ✗') : 'Complex ✗';
|
|
124
|
+
}
|
|
125
|
+
formatTable([
|
|
126
|
+
{ metric: 'Analyzed Files', value: stats.formatNumber(stats.codeComplexity.analyzedFiles) },
|
|
127
|
+
{ metric: 'Total Functions', value: stats.formatNumber(stats.codeComplexity.totalFunctions) },
|
|
128
|
+
{ metric: 'Avg Cyclomatic Complexity', value: stats.codeComplexity.avgComplexity },
|
|
129
|
+
{ metric: 'Max Cyclomatic Complexity', value: stats.formatNumber(stats.codeComplexity.maxComplexity) },
|
|
130
|
+
{ metric: 'Avg Nesting Depth', value: stats.codeComplexity.avgNestingDepth },
|
|
131
|
+
{ metric: 'Max Nesting Depth', value: stats.formatNumber(stats.codeComplexity.maxNestingDepth) },
|
|
132
|
+
{ metric: 'Avg Function Size', value: `${stats.codeComplexity.avgFunctionSize} lines` },
|
|
133
|
+
{ metric: 'Complex Files', value: stats.formatNumber(stats.codeComplexity.complexFiles) },
|
|
134
|
+
{ metric: 'Overall Complexity', value: complexityIndicator }
|
|
135
|
+
]);
|
|
136
|
+
}
|
|
137
|
+
// Add code quality recommendations
|
|
138
|
+
if (stats.typescriptSafety || stats.codeComplexity) {
|
|
139
|
+
console.log('\n' + (useColors ? chalk.bold.blue('📝 Code Quality Recommendations:') : '📝 Code Quality Recommendations:'));
|
|
140
|
+
const recommendations = [];
|
|
141
|
+
if (stats.typescriptSafety) {
|
|
142
|
+
const typeCoverage = parseFloat(stats.typescriptSafety.avgTypeCoverage);
|
|
143
|
+
// Type safety recommendations - with more specific thresholds
|
|
144
|
+
if (typeCoverage < 85) {
|
|
145
|
+
recommendations.push(useColors
|
|
146
|
+
? chalk.yellow('• Improve type coverage by adding more explicit type annotations')
|
|
147
|
+
: '• Improve type coverage by adding more explicit type annotations');
|
|
148
|
+
}
|
|
149
|
+
else if (typeCoverage < 95) {
|
|
150
|
+
recommendations.push(useColors
|
|
151
|
+
? chalk.yellow('• Consider adding explicit type annotations to remaining untyped areas')
|
|
152
|
+
: '• Consider adding explicit type annotations to remaining untyped areas');
|
|
153
|
+
}
|
|
154
|
+
if (stats.typescriptSafety.totalAnyCount > 10) {
|
|
155
|
+
recommendations.push(useColors
|
|
156
|
+
? chalk.yellow(`• Reduce usage of 'any' type (found ${stats.typescriptSafety.totalAnyCount} instances) by using more specific types`)
|
|
157
|
+
: `• Reduce usage of 'any' type (found ${stats.typescriptSafety.totalAnyCount} instances) by using more specific types`);
|
|
158
|
+
}
|
|
159
|
+
else if (stats.typescriptSafety.totalAnyCount > 0) {
|
|
160
|
+
recommendations.push(useColors
|
|
161
|
+
? chalk.yellow(`• Consider replacing the ${stats.typescriptSafety.totalAnyCount} 'any' type usage(s) with more specific types`)
|
|
162
|
+
: `• Consider replacing the ${stats.typescriptSafety.totalAnyCount} 'any' type usage(s) with more specific types`);
|
|
163
|
+
}
|
|
164
|
+
if (stats.typescriptSafety.totalAssertions > 5) {
|
|
165
|
+
recommendations.push(useColors
|
|
166
|
+
? chalk.yellow(`• Reduce type assertions (${stats.typescriptSafety.totalAssertions} instances) by improving type declarations`)
|
|
167
|
+
: `• Reduce type assertions (${stats.typescriptSafety.totalAssertions} instances) by improving type declarations`);
|
|
168
|
+
}
|
|
169
|
+
if (stats.typescriptSafety.totalNonNullAssertions > 5) {
|
|
170
|
+
recommendations.push(useColors
|
|
171
|
+
? chalk.yellow(`• Replace non-null assertions (${stats.typescriptSafety.totalNonNullAssertions} instances) with proper null checks`)
|
|
172
|
+
: `• Replace non-null assertions (${stats.typescriptSafety.totalNonNullAssertions} instances) with proper null checks`);
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
if (stats.codeComplexity) {
|
|
176
|
+
// Code complexity recommendations
|
|
177
|
+
if (parseFloat(stats.codeComplexity.avgComplexity) > 6) {
|
|
178
|
+
recommendations.push(useColors
|
|
179
|
+
? chalk.yellow('• Reduce function complexity by breaking down complex functions into smaller, more focused ones')
|
|
180
|
+
: '• Reduce function complexity by breaking down complex functions into smaller, more focused ones');
|
|
181
|
+
}
|
|
182
|
+
if (parseFloat(stats.codeComplexity.avgNestingDepth) > 3) {
|
|
183
|
+
recommendations.push(useColors
|
|
184
|
+
? chalk.yellow('• Reduce nesting depth by extracting deeply nested code into separate functions')
|
|
185
|
+
: '• Reduce nesting depth by extracting deeply nested code into separate functions');
|
|
186
|
+
}
|
|
187
|
+
if (parseFloat(stats.codeComplexity.avgFunctionSize) > 15) {
|
|
188
|
+
recommendations.push(useColors
|
|
189
|
+
? chalk.yellow('• Consider refactoring large functions to improve readability and maintainability')
|
|
190
|
+
: '• Consider refactoring large functions to improve readability and maintainability');
|
|
191
|
+
}
|
|
192
|
+
if (stats.codeComplexity.complexFiles > 0) {
|
|
193
|
+
recommendations.push(useColors
|
|
194
|
+
? chalk.yellow(`• Address high complexity in ${stats.codeComplexity.complexFiles} files with potential technical debt`)
|
|
195
|
+
: `• Address high complexity in ${stats.codeComplexity.complexFiles} files with potential technical debt`);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
if (recommendations.length > 0) {
|
|
199
|
+
console.log(recommendations.join('\n'));
|
|
200
|
+
}
|
|
201
|
+
else {
|
|
202
|
+
console.log(useColors
|
|
203
|
+
? chalk.green('✓ Your code looks well structured! Keep up the good work.')
|
|
204
|
+
: '✓ Your code looks well structured! Keep up the good work.');
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
catch (error) {
|
|
209
|
+
spinner.fail('Analysis failed');
|
|
210
|
+
console.error(useColors ? chalk.red('Error:') : 'Error:', error.message);
|
|
211
|
+
process.exit(1);
|
|
212
|
+
}
|
|
213
|
+
});
|
|
214
|
+
program.parse();
|
|
215
|
+
//# sourceMappingURL=cli.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"cli.js","sourceRoot":"","sources":["../../bin/cli.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export interface FileComplexityMetrics {
|
|
2
|
+
avgComplexity: string;
|
|
3
|
+
maxComplexity: number;
|
|
4
|
+
avgNestingDepth: string;
|
|
5
|
+
maxNestingDepth: number;
|
|
6
|
+
avgFunctionSize: string;
|
|
7
|
+
avgParams: string;
|
|
8
|
+
functionCount: number;
|
|
9
|
+
complexityScore: number;
|
|
10
|
+
complexityRating: string;
|
|
11
|
+
}
|
|
12
|
+
export interface CodeComplexityMetrics {
|
|
13
|
+
analyzedFiles: number;
|
|
14
|
+
avgComplexity: string;
|
|
15
|
+
maxComplexity: number;
|
|
16
|
+
avgNestingDepth: string;
|
|
17
|
+
maxNestingDepth: number;
|
|
18
|
+
avgFunctionSize: string;
|
|
19
|
+
totalFunctions: number;
|
|
20
|
+
complexFiles: number;
|
|
21
|
+
overallComplexity: string;
|
|
22
|
+
}
|
|
23
|
+
export declare function analyzeFileComplexity(filePath: string): Promise<FileComplexityMetrics>;
|
|
24
|
+
export declare function calculateProjectComplexity(projectPath: string, fileList: string[]): Promise<CodeComplexityMetrics>;
|
|
@@ -0,0 +1,338 @@
|
|
|
1
|
+
// src/code-complexity.ts
|
|
2
|
+
import fs from 'fs/promises';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import * as espree from 'espree';
|
|
5
|
+
import * as estraverse from 'estraverse';
|
|
6
|
+
import * as ts from 'typescript';
|
|
7
|
+
// Calculate cyclomatic complexity
|
|
8
|
+
function calculateCyclomaticComplexity(ast) {
|
|
9
|
+
let complexity = 1; // Start with 1 (one path through the function)
|
|
10
|
+
estraverse.traverse(ast, {
|
|
11
|
+
enter(node) {
|
|
12
|
+
// Count conditional statements and operators that create new paths
|
|
13
|
+
switch (node.type) {
|
|
14
|
+
case 'IfStatement':
|
|
15
|
+
case 'ConditionalExpression':
|
|
16
|
+
case 'SwitchCase':
|
|
17
|
+
case 'ForStatement':
|
|
18
|
+
case 'ForInStatement':
|
|
19
|
+
case 'ForOfStatement':
|
|
20
|
+
case 'WhileStatement':
|
|
21
|
+
case 'DoWhileStatement':
|
|
22
|
+
complexity++;
|
|
23
|
+
break;
|
|
24
|
+
case 'LogicalExpression':
|
|
25
|
+
if (node.operator === '&&' || node.operator === '||') {
|
|
26
|
+
complexity++;
|
|
27
|
+
}
|
|
28
|
+
break;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
return complexity;
|
|
33
|
+
}
|
|
34
|
+
// Calculate nesting depth
|
|
35
|
+
function calculateNestingDepth(ast) {
|
|
36
|
+
let maxDepth = 0;
|
|
37
|
+
let currentDepth = 0;
|
|
38
|
+
estraverse.traverse(ast, {
|
|
39
|
+
enter(node) {
|
|
40
|
+
// Count nesting for blocks and control structures
|
|
41
|
+
switch (node.type) {
|
|
42
|
+
case 'BlockStatement':
|
|
43
|
+
case 'IfStatement':
|
|
44
|
+
case 'SwitchStatement':
|
|
45
|
+
case 'ForStatement':
|
|
46
|
+
case 'ForInStatement':
|
|
47
|
+
case 'ForOfStatement':
|
|
48
|
+
case 'WhileStatement':
|
|
49
|
+
case 'DoWhileStatement':
|
|
50
|
+
case 'TryStatement':
|
|
51
|
+
currentDepth++;
|
|
52
|
+
maxDepth = Math.max(maxDepth, currentDepth);
|
|
53
|
+
break;
|
|
54
|
+
}
|
|
55
|
+
},
|
|
56
|
+
leave(node) {
|
|
57
|
+
// Decrement depth when leaving a block
|
|
58
|
+
switch (node.type) {
|
|
59
|
+
case 'BlockStatement':
|
|
60
|
+
case 'IfStatement':
|
|
61
|
+
case 'SwitchStatement':
|
|
62
|
+
case 'ForStatement':
|
|
63
|
+
case 'ForInStatement':
|
|
64
|
+
case 'ForOfStatement':
|
|
65
|
+
case 'WhileStatement':
|
|
66
|
+
case 'DoWhileStatement':
|
|
67
|
+
case 'TryStatement':
|
|
68
|
+
currentDepth--;
|
|
69
|
+
break;
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
return maxDepth;
|
|
74
|
+
}
|
|
75
|
+
// Find function declarations and calculate their metrics
|
|
76
|
+
function analyzeFunctions(ast) {
|
|
77
|
+
const functions = [];
|
|
78
|
+
estraverse.traverse(ast, {
|
|
79
|
+
enter(node) {
|
|
80
|
+
if (node.type === 'FunctionDeclaration' ||
|
|
81
|
+
node.type === 'FunctionExpression' ||
|
|
82
|
+
node.type === 'ArrowFunctionExpression') {
|
|
83
|
+
// Skip functions without a body
|
|
84
|
+
if (!node.body)
|
|
85
|
+
return;
|
|
86
|
+
// Get the function's source code
|
|
87
|
+
let functionAst = node;
|
|
88
|
+
if (node.type === 'ArrowFunctionExpression' && node.body.type !== 'BlockStatement') {
|
|
89
|
+
functionAst = {
|
|
90
|
+
type: 'ArrowFunctionExpression',
|
|
91
|
+
body: {
|
|
92
|
+
type: 'BlockStatement',
|
|
93
|
+
body: [{ type: 'ReturnStatement', argument: node.body }]
|
|
94
|
+
}
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
// Calculate complexity
|
|
98
|
+
const complexity = calculateCyclomaticComplexity(functionAst);
|
|
99
|
+
// Calculate nesting
|
|
100
|
+
const nestingDepth = calculateNestingDepth(functionAst);
|
|
101
|
+
// Count function parameters
|
|
102
|
+
const paramCount = node.params ? node.params.length : 0;
|
|
103
|
+
// Estimate function size (lines)
|
|
104
|
+
let lineCount = 0;
|
|
105
|
+
if (node.loc) {
|
|
106
|
+
lineCount = node.loc.end.line - node.loc.start.line + 1;
|
|
107
|
+
}
|
|
108
|
+
functions.push({
|
|
109
|
+
type: node.type,
|
|
110
|
+
name: node.id ? node.id.name : 'anonymous',
|
|
111
|
+
complexity,
|
|
112
|
+
nestingDepth,
|
|
113
|
+
paramCount,
|
|
114
|
+
lineCount
|
|
115
|
+
});
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
});
|
|
119
|
+
return functions;
|
|
120
|
+
}
|
|
121
|
+
// Parse a TypeScript file using the TypeScript compiler
|
|
122
|
+
function parseTypeScriptFile(content) {
|
|
123
|
+
try {
|
|
124
|
+
// Create a source file
|
|
125
|
+
const sourceFile = ts.createSourceFile('temp.ts', content, ts.ScriptTarget.Latest, true);
|
|
126
|
+
// Create a simplified program AST structure
|
|
127
|
+
const simplifiedAst = {
|
|
128
|
+
type: 'Program',
|
|
129
|
+
body: []
|
|
130
|
+
};
|
|
131
|
+
// Function to visit TypeScript nodes and extract function information
|
|
132
|
+
function visit(node) {
|
|
133
|
+
if (ts.isFunctionDeclaration(node) ||
|
|
134
|
+
ts.isMethodDeclaration(node) ||
|
|
135
|
+
ts.isArrowFunction(node) ||
|
|
136
|
+
ts.isFunctionExpression(node)) {
|
|
137
|
+
const startLine = sourceFile.getLineAndCharacterOfPosition(node.getStart()).line + 1;
|
|
138
|
+
const endLine = sourceFile.getLineAndCharacterOfPosition(node.getEnd()).line + 1;
|
|
139
|
+
const functionNode = {
|
|
140
|
+
type: ts.isFunctionDeclaration(node) ? 'FunctionDeclaration' :
|
|
141
|
+
ts.isArrowFunction(node) ? 'ArrowFunctionExpression' : 'FunctionExpression',
|
|
142
|
+
id: ts.isFunctionDeclaration(node) && node.name ? { name: node.name.text } : undefined,
|
|
143
|
+
params: node.parameters ? node.parameters.map(() => ({})) : [],
|
|
144
|
+
body: { type: 'BlockStatement', body: [] },
|
|
145
|
+
loc: {
|
|
146
|
+
start: { line: startLine },
|
|
147
|
+
end: { line: endLine }
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
simplifiedAst.body.push(functionNode);
|
|
151
|
+
}
|
|
152
|
+
ts.forEachChild(node, visit);
|
|
153
|
+
}
|
|
154
|
+
visit(sourceFile);
|
|
155
|
+
return simplifiedAst;
|
|
156
|
+
}
|
|
157
|
+
catch (error) {
|
|
158
|
+
console.error('Error parsing TypeScript file:', error);
|
|
159
|
+
return { type: 'Program', body: [] };
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
export async function analyzeFileComplexity(filePath) {
|
|
163
|
+
try {
|
|
164
|
+
const content = await fs.readFile(filePath, 'utf8');
|
|
165
|
+
const extension = path.extname(filePath);
|
|
166
|
+
// Choose the appropriate parser based on file extension
|
|
167
|
+
let ast;
|
|
168
|
+
if (extension === '.ts' || extension === '.tsx') {
|
|
169
|
+
// Use TypeScript parser for .ts and .tsx files
|
|
170
|
+
ast = parseTypeScriptFile(content);
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
// Use espree for JavaScript files
|
|
174
|
+
try {
|
|
175
|
+
const parserOptions = {
|
|
176
|
+
ecmaVersion: 2022,
|
|
177
|
+
sourceType: 'module',
|
|
178
|
+
ecmaFeatures: {
|
|
179
|
+
jsx: extension === '.jsx'
|
|
180
|
+
}
|
|
181
|
+
};
|
|
182
|
+
ast = espree.parse(content, parserOptions);
|
|
183
|
+
}
|
|
184
|
+
catch (parseError) {
|
|
185
|
+
console.error(`Parsing error in ${filePath}: ${parseError.message}`);
|
|
186
|
+
return {
|
|
187
|
+
avgComplexity: '0',
|
|
188
|
+
maxComplexity: 0,
|
|
189
|
+
avgNestingDepth: '0',
|
|
190
|
+
maxNestingDepth: 0,
|
|
191
|
+
avgFunctionSize: '0',
|
|
192
|
+
avgParams: '0',
|
|
193
|
+
functionCount: 0,
|
|
194
|
+
complexityScore: 0,
|
|
195
|
+
complexityRating: 'N/A'
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
// Analyze the functions in the file
|
|
200
|
+
const functions = analyzeFunctions(ast);
|
|
201
|
+
if (functions.length === 0) {
|
|
202
|
+
return {
|
|
203
|
+
avgComplexity: '0',
|
|
204
|
+
maxComplexity: 0,
|
|
205
|
+
avgNestingDepth: '0',
|
|
206
|
+
maxNestingDepth: 0,
|
|
207
|
+
avgFunctionSize: '0',
|
|
208
|
+
avgParams: '0',
|
|
209
|
+
functionCount: 0,
|
|
210
|
+
complexityScore: 0,
|
|
211
|
+
complexityRating: 'N/A'
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
// Calculate average and maximum values
|
|
215
|
+
const totalComplexity = functions.reduce((sum, fn) => sum + fn.complexity, 0);
|
|
216
|
+
const maxComplexity = Math.max(...functions.map(fn => fn.complexity));
|
|
217
|
+
const totalNestingDepth = functions.reduce((sum, fn) => sum + fn.nestingDepth, 0);
|
|
218
|
+
const maxNestingDepth = Math.max(...functions.map(fn => fn.nestingDepth));
|
|
219
|
+
const totalLineCount = functions.reduce((sum, fn) => sum + fn.lineCount, 0);
|
|
220
|
+
const totalParams = functions.reduce((sum, fn) => sum + fn.paramCount, 0);
|
|
221
|
+
const avgComplexity = totalComplexity / functions.length;
|
|
222
|
+
const avgNestingDepth = totalNestingDepth / functions.length;
|
|
223
|
+
const avgFunctionSize = totalLineCount / functions.length;
|
|
224
|
+
const avgParams = totalParams / functions.length;
|
|
225
|
+
// Calculate a complexity score (0-100, higher means more complex)
|
|
226
|
+
const complexityWeight = 0.4;
|
|
227
|
+
const nestingWeight = 0.3;
|
|
228
|
+
const sizeWeight = 0.2;
|
|
229
|
+
const paramsWeight = 0.1;
|
|
230
|
+
// Normalized scores (0-100)
|
|
231
|
+
const complexityScore = Math.min((avgComplexity / 10) * 100, 100);
|
|
232
|
+
const nestingScore = Math.min((avgNestingDepth / 5) * 100, 100);
|
|
233
|
+
const sizeScore = Math.min((avgFunctionSize / 30) * 100, 100);
|
|
234
|
+
const paramsScore = Math.min((avgParams / 6) * 100, 100);
|
|
235
|
+
const totalScore = (complexityScore * complexityWeight) +
|
|
236
|
+
(nestingScore * nestingWeight) +
|
|
237
|
+
(sizeScore * sizeWeight) +
|
|
238
|
+
(paramsScore * paramsWeight);
|
|
239
|
+
// Define complexity rating
|
|
240
|
+
let complexityRating;
|
|
241
|
+
if (totalScore < 30)
|
|
242
|
+
complexityRating = 'Low';
|
|
243
|
+
else if (totalScore < 60)
|
|
244
|
+
complexityRating = 'Medium';
|
|
245
|
+
else
|
|
246
|
+
complexityRating = 'High';
|
|
247
|
+
return {
|
|
248
|
+
avgComplexity: avgComplexity.toFixed(1),
|
|
249
|
+
maxComplexity,
|
|
250
|
+
avgNestingDepth: avgNestingDepth.toFixed(1),
|
|
251
|
+
maxNestingDepth,
|
|
252
|
+
avgFunctionSize: avgFunctionSize.toFixed(1),
|
|
253
|
+
avgParams: avgParams.toFixed(1),
|
|
254
|
+
functionCount: functions.length,
|
|
255
|
+
complexityScore: Math.round(totalScore),
|
|
256
|
+
complexityRating
|
|
257
|
+
};
|
|
258
|
+
}
|
|
259
|
+
catch (error) {
|
|
260
|
+
console.error(`Error analyzing file complexity for ${filePath}:`, error);
|
|
261
|
+
return {
|
|
262
|
+
avgComplexity: '0',
|
|
263
|
+
maxComplexity: 0,
|
|
264
|
+
avgNestingDepth: '0',
|
|
265
|
+
maxNestingDepth: 0,
|
|
266
|
+
avgFunctionSize: '0',
|
|
267
|
+
avgParams: '0',
|
|
268
|
+
functionCount: 0,
|
|
269
|
+
complexityScore: 0,
|
|
270
|
+
complexityRating: 'N/A'
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
export async function calculateProjectComplexity(projectPath, fileList) {
|
|
275
|
+
const jsExtensions = ['.js', '.jsx', '.ts', '.tsx'];
|
|
276
|
+
const jsFiles = fileList.filter(file => jsExtensions.includes(path.extname(file)));
|
|
277
|
+
if (jsFiles.length === 0) {
|
|
278
|
+
return {
|
|
279
|
+
analyzedFiles: 0,
|
|
280
|
+
avgComplexity: '0.0',
|
|
281
|
+
maxComplexity: 0,
|
|
282
|
+
avgNestingDepth: '0.0',
|
|
283
|
+
maxNestingDepth: 0,
|
|
284
|
+
avgFunctionSize: '0.0',
|
|
285
|
+
totalFunctions: 0,
|
|
286
|
+
complexFiles: 0,
|
|
287
|
+
overallComplexity: 'N/A'
|
|
288
|
+
};
|
|
289
|
+
}
|
|
290
|
+
let totalComplexity = 0;
|
|
291
|
+
let totalNestingDepth = 0;
|
|
292
|
+
let totalFunctionSize = 0;
|
|
293
|
+
let maxComplexityGlobal = 0;
|
|
294
|
+
let maxNestingDepthGlobal = 0;
|
|
295
|
+
let totalFunctions = 0;
|
|
296
|
+
let complexFiles = 0;
|
|
297
|
+
for (const file of jsFiles) {
|
|
298
|
+
const filePath = path.join(projectPath, file);
|
|
299
|
+
const metrics = await analyzeFileComplexity(filePath);
|
|
300
|
+
totalComplexity += parseFloat(metrics.avgComplexity) * metrics.functionCount;
|
|
301
|
+
totalNestingDepth += parseFloat(metrics.avgNestingDepth) * metrics.functionCount;
|
|
302
|
+
totalFunctionSize += parseFloat(metrics.avgFunctionSize) * metrics.functionCount;
|
|
303
|
+
maxComplexityGlobal = Math.max(maxComplexityGlobal, metrics.maxComplexity);
|
|
304
|
+
maxNestingDepthGlobal = Math.max(maxNestingDepthGlobal, metrics.maxNestingDepth);
|
|
305
|
+
totalFunctions += metrics.functionCount;
|
|
306
|
+
if (metrics.complexityRating === 'High') {
|
|
307
|
+
complexFiles++;
|
|
308
|
+
}
|
|
309
|
+
}
|
|
310
|
+
// Calculate project averages
|
|
311
|
+
const avgComplexity = totalFunctions > 0 ? (totalComplexity / totalFunctions).toFixed(1) : '0.0';
|
|
312
|
+
const avgNestingDepth = totalFunctions > 0 ? (totalNestingDepth / totalFunctions).toFixed(1) : '0.0';
|
|
313
|
+
const avgFunctionSize = totalFunctions > 0 ? (totalFunctionSize / totalFunctions).toFixed(1) : '0.0';
|
|
314
|
+
// Determine overall complexity
|
|
315
|
+
let overallComplexity;
|
|
316
|
+
const complexFilesPercentage = (complexFiles / jsFiles.length) * 100;
|
|
317
|
+
if (parseFloat(avgComplexity) < 4 && complexFilesPercentage < 10) {
|
|
318
|
+
overallComplexity = 'Low';
|
|
319
|
+
}
|
|
320
|
+
else if (parseFloat(avgComplexity) < 8 && complexFilesPercentage < 25) {
|
|
321
|
+
overallComplexity = 'Medium';
|
|
322
|
+
}
|
|
323
|
+
else {
|
|
324
|
+
overallComplexity = 'High';
|
|
325
|
+
}
|
|
326
|
+
return {
|
|
327
|
+
analyzedFiles: jsFiles.length,
|
|
328
|
+
avgComplexity,
|
|
329
|
+
maxComplexity: maxComplexityGlobal,
|
|
330
|
+
avgNestingDepth,
|
|
331
|
+
maxNestingDepth: maxNestingDepthGlobal,
|
|
332
|
+
avgFunctionSize,
|
|
333
|
+
totalFunctions,
|
|
334
|
+
complexFiles,
|
|
335
|
+
overallComplexity
|
|
336
|
+
};
|
|
337
|
+
}
|
|
338
|
+
//# sourceMappingURL=code-complexity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-complexity.js","sourceRoot":"","sources":["../../src/code-complexity.ts"],"names":[],"mappings":"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"}
|