@defai.digital/ax-cli 3.2.0 → 3.4.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/.ax-cli/memory.json +8 -1
- package/README.md +118 -2
- package/config/models.yaml +13 -0
- package/config/settings.yaml +6 -0
- package/dist/agent/context-manager.d.ts +5 -5
- package/dist/agent/context-manager.js +19 -9
- package/dist/agent/context-manager.js.map +1 -1
- package/dist/agent/dependency-resolver.js +2 -1
- package/dist/agent/dependency-resolver.js.map +1 -1
- package/dist/agent/llm-agent.d.ts +3 -2
- package/dist/agent/llm-agent.js +64 -58
- package/dist/agent/llm-agent.js.map +1 -1
- package/dist/agent/subagent.js +2 -1
- package/dist/agent/subagent.js.map +1 -1
- package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.d.ts +29 -0
- package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js +103 -0
- package/dist/analyzers/architecture/anti-pattern-detectors/god-object-detector.js.map +1 -0
- package/dist/analyzers/architecture/architecture-analyzer.d.ts +58 -0
- package/dist/analyzers/architecture/architecture-analyzer.js +276 -0
- package/dist/analyzers/architecture/architecture-analyzer.js.map +1 -0
- package/dist/analyzers/architecture/index.d.ts +12 -0
- package/dist/analyzers/architecture/index.js +14 -0
- package/dist/analyzers/architecture/index.js.map +1 -0
- package/dist/analyzers/architecture/pattern-detectors/base-detector.d.ts +27 -0
- package/dist/analyzers/architecture/pattern-detectors/base-detector.js +31 -0
- package/dist/analyzers/architecture/pattern-detectors/base-detector.js.map +1 -0
- package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.d.ts +11 -0
- package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js +57 -0
- package/dist/analyzers/architecture/pattern-detectors/clean-architecture-detector.js.map +1 -0
- package/dist/analyzers/architecture/pattern-detectors/mvc-detector.d.ts +11 -0
- package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js +43 -0
- package/dist/analyzers/architecture/pattern-detectors/mvc-detector.js.map +1 -0
- package/dist/analyzers/architecture/pattern-detectors/repository-detector.d.ts +11 -0
- package/dist/analyzers/architecture/pattern-detectors/repository-detector.js +49 -0
- package/dist/analyzers/architecture/pattern-detectors/repository-detector.js.map +1 -0
- package/dist/analyzers/architecture/project-structure-scanner.d.ts +54 -0
- package/dist/analyzers/architecture/project-structure-scanner.js +200 -0
- package/dist/analyzers/architecture/project-structure-scanner.js.map +1 -0
- package/dist/analyzers/best-practices/base-rule.d.ts +45 -0
- package/dist/analyzers/best-practices/base-rule.js +45 -0
- package/dist/analyzers/best-practices/base-rule.js.map +1 -0
- package/dist/analyzers/best-practices/best-practice-validator.d.ts +35 -0
- package/dist/analyzers/best-practices/best-practice-validator.js +181 -0
- package/dist/analyzers/best-practices/best-practice-validator.js.map +1 -0
- package/dist/analyzers/best-practices/rules/index.d.ts +7 -0
- package/dist/analyzers/best-practices/rules/index.js +56 -0
- package/dist/analyzers/best-practices/rules/index.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/consistent-naming.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js +41 -0
- package/dist/analyzers/best-practices/rules/typescript/consistent-naming.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/function-complexity.d.ts +27 -0
- package/dist/analyzers/best-practices/rules/typescript/function-complexity.js +76 -0
- package/dist/analyzers/best-practices/rules/typescript/function-complexity.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/index.d.ts +15 -0
- package/dist/analyzers/best-practices/rules/typescript/index.js +16 -0
- package/dist/analyzers/best-practices/rules/typescript/index.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/max-file-length.d.ts +18 -0
- package/dist/analyzers/best-practices/rules/typescript/max-file-length.js +25 -0
- package/dist/analyzers/best-practices/rules/typescript/max-file-length.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/no-any-type.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/no-any-type.js +27 -0
- package/dist/analyzers/best-practices/rules/typescript/no-any-type.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.d.ts +18 -0
- package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js +39 -0
- package/dist/analyzers/best-practices/rules/typescript/no-implicit-any.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js +32 -0
- package/dist/analyzers/best-practices/rules/typescript/no-magic-numbers.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js +36 -0
- package/dist/analyzers/best-practices/rules/typescript/no-unused-vars.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-const.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-const.js +33 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-const.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js +34 -0
- package/dist/analyzers/best-practices/rules/typescript/prefer-readonly.js.map +1 -0
- package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.d.ts +17 -0
- package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js +27 -0
- package/dist/analyzers/best-practices/rules/typescript/proper-error-handling.js.map +1 -0
- package/dist/analyzers/best-practices/types.d.ts +86 -0
- package/dist/analyzers/best-practices/types.js +7 -0
- package/dist/analyzers/best-practices/types.js.map +1 -0
- package/dist/analyzers/cache/analysis-cache.d.ts +41 -0
- package/dist/analyzers/cache/analysis-cache.js +84 -0
- package/dist/analyzers/cache/analysis-cache.js.map +1 -0
- package/dist/analyzers/errors.d.ts +51 -0
- package/dist/analyzers/errors.js +79 -0
- package/dist/analyzers/errors.js.map +1 -0
- package/dist/commands/doctor.js +3 -2
- package/dist/commands/doctor.js.map +1 -1
- package/dist/commands/frontend.d.ts +9 -0
- package/dist/commands/frontend.js +645 -0
- package/dist/commands/frontend.js.map +1 -0
- package/dist/commands/mcp.js +652 -3
- package/dist/commands/mcp.js.map +1 -1
- package/dist/commands/models.js +2 -2
- package/dist/commands/models.js.map +1 -1
- package/dist/commands/setup.js +100 -41
- package/dist/commands/setup.js.map +1 -1
- package/dist/constants.d.ts +4 -0
- package/dist/constants.js +4 -0
- package/dist/constants.js.map +1 -1
- package/dist/hooks/use-enhanced-input.js +16 -3
- package/dist/hooks/use-enhanced-input.js.map +1 -1
- package/dist/hooks/use-input-handler.js +9 -4
- package/dist/hooks/use-input-handler.js.map +1 -1
- package/dist/index.js +5 -2
- package/dist/index.js.map +1 -1
- package/dist/llm/client.d.ts +1 -0
- package/dist/llm/tools.js +86 -0
- package/dist/llm/tools.js.map +1 -1
- package/dist/llm/types.d.ts +49 -22
- package/dist/llm/types.js +12 -8
- package/dist/llm/types.js.map +1 -1
- package/dist/mcp/client.d.ts +5 -0
- package/dist/mcp/client.js +55 -0
- package/dist/mcp/client.js.map +1 -1
- package/dist/mcp/config.d.ts +1 -1
- package/dist/mcp/config.js +2 -2
- package/dist/mcp/config.js.map +1 -1
- package/dist/mcp/health.d.ts +120 -0
- package/dist/mcp/health.js +267 -0
- package/dist/mcp/health.js.map +1 -0
- package/dist/mcp/reconnection.d.ts +93 -0
- package/dist/mcp/reconnection.js +216 -0
- package/dist/mcp/reconnection.js.map +1 -0
- package/dist/mcp/registry.d.ts +71 -0
- package/dist/mcp/registry.js +257 -0
- package/dist/mcp/registry.js.map +1 -0
- package/dist/mcp/resources.d.ts +53 -0
- package/dist/mcp/resources.js +135 -0
- package/dist/mcp/resources.js.map +1 -0
- package/dist/mcp/templates.d.ts +52 -0
- package/dist/mcp/templates.js +624 -0
- package/dist/mcp/templates.js.map +1 -0
- package/dist/mcp/validation.d.ts +25 -0
- package/dist/mcp/validation.js +209 -0
- package/dist/mcp/validation.js.map +1 -0
- package/dist/memory/context-generator.js +1 -2
- package/dist/memory/context-generator.js.map +1 -1
- package/dist/planner/types.d.ts +2 -2
- package/dist/schemas/api-schemas.d.ts +2 -1
- package/dist/schemas/api-schemas.js +6 -4
- package/dist/schemas/api-schemas.js.map +1 -1
- package/dist/schemas/index.d.ts +4 -4
- package/dist/schemas/tool-schemas.d.ts +2 -2
- package/dist/schemas/yaml-schemas.d.ts +15 -0
- package/dist/schemas/yaml-schemas.js +3 -0
- package/dist/schemas/yaml-schemas.js.map +1 -1
- package/dist/sdk/index.d.ts +138 -0
- package/dist/sdk/index.js +173 -0
- package/dist/sdk/index.js.map +1 -0
- package/dist/sdk/types.d.ts +53 -0
- package/dist/sdk/types.js +8 -0
- package/dist/sdk/types.js.map +1 -0
- package/dist/tools/analysis-tools/architecture-tool.d.ts +46 -0
- package/dist/tools/analysis-tools/architecture-tool.js +124 -0
- package/dist/tools/analysis-tools/architecture-tool.js.map +1 -0
- package/dist/tools/analysis-tools/validation-tool.d.ts +51 -0
- package/dist/tools/analysis-tools/validation-tool.js +121 -0
- package/dist/tools/analysis-tools/validation-tool.js.map +1 -0
- package/dist/tools/bash.js +25 -10
- package/dist/tools/bash.js.map +1 -1
- package/dist/tools/web-search/cache.d.ts +62 -0
- package/dist/tools/web-search/cache.js +105 -0
- package/dist/tools/web-search/cache.js.map +1 -0
- package/dist/tools/web-search/engines/brave.d.ts +16 -0
- package/dist/tools/web-search/engines/brave.js +99 -0
- package/dist/tools/web-search/engines/brave.js.map +1 -0
- package/dist/tools/web-search/engines/crates.d.ts +19 -0
- package/dist/tools/web-search/engines/crates.js +87 -0
- package/dist/tools/web-search/engines/crates.js.map +1 -0
- package/dist/tools/web-search/engines/npm.d.ts +18 -0
- package/dist/tools/web-search/engines/npm.js +86 -0
- package/dist/tools/web-search/engines/npm.js.map +1 -0
- package/dist/tools/web-search/engines/pypi.d.ts +18 -0
- package/dist/tools/web-search/engines/pypi.js +75 -0
- package/dist/tools/web-search/engines/pypi.js.map +1 -0
- package/dist/tools/web-search/engines/tavily.d.ts +17 -0
- package/dist/tools/web-search/engines/tavily.js +73 -0
- package/dist/tools/web-search/engines/tavily.js.map +1 -0
- package/dist/tools/web-search/index.d.ts +13 -0
- package/dist/tools/web-search/index.js +13 -0
- package/dist/tools/web-search/index.js.map +1 -0
- package/dist/tools/web-search/router.d.ts +36 -0
- package/dist/tools/web-search/router.js +280 -0
- package/dist/tools/web-search/router.js.map +1 -0
- package/dist/tools/web-search/types.d.ts +45 -0
- package/dist/tools/web-search/types.js +6 -0
- package/dist/tools/web-search/types.js.map +1 -0
- package/dist/tools/web-search/web-search-tool.d.ts +51 -0
- package/dist/tools/web-search/web-search-tool.js +256 -0
- package/dist/tools/web-search/web-search-tool.js.map +1 -0
- package/dist/types/analysis.d.ts +177 -0
- package/dist/types/analysis.js +8 -0
- package/dist/types/analysis.js.map +1 -0
- package/dist/ui/components/api-key-input.js +2 -2
- package/dist/ui/components/api-key-input.js.map +1 -1
- package/dist/ui/components/chat-history.js +14 -7
- package/dist/ui/components/chat-history.js.map +1 -1
- package/dist/ui/components/chat-input.js +12 -7
- package/dist/ui/components/chat-input.js.map +1 -1
- package/dist/ui/components/chat-interface.js +75 -54
- package/dist/ui/components/chat-interface.js.map +1 -1
- package/dist/ui/components/keyboard-hints.js +5 -4
- package/dist/ui/components/keyboard-hints.js.map +1 -1
- package/dist/ui/components/quick-actions.js +1 -0
- package/dist/ui/components/quick-actions.js.map +1 -1
- package/dist/ui/components/reasoning-display.js +14 -4
- package/dist/ui/components/reasoning-display.js.map +1 -1
- package/dist/ui/components/status-bar.d.ts +1 -0
- package/dist/ui/components/status-bar.js +37 -39
- package/dist/ui/components/status-bar.js.map +1 -1
- package/dist/ui/components/toast-notification.d.ts +29 -0
- package/dist/ui/components/toast-notification.js +17 -3
- package/dist/ui/components/toast-notification.js.map +1 -1
- package/dist/ui/components/welcome-panel.d.ts +1 -0
- package/dist/ui/components/welcome-panel.js +106 -4
- package/dist/ui/components/welcome-panel.js.map +1 -1
- package/dist/utils/analysis-logger.d.ts +47 -0
- package/dist/utils/analysis-logger.js +70 -0
- package/dist/utils/analysis-logger.js.map +1 -0
- package/dist/utils/automatosx-detector.d.ts +19 -0
- package/dist/utils/automatosx-detector.js +52 -0
- package/dist/utils/automatosx-detector.js.map +1 -0
- package/dist/utils/config-loader.d.ts +4 -0
- package/dist/utils/config-loader.js.map +1 -1
- package/dist/utils/confirmation-service.js +1 -1
- package/dist/utils/confirmation-service.js.map +1 -1
- package/dist/utils/init-previewer.js +26 -4
- package/dist/utils/init-previewer.js.map +1 -1
- package/dist/utils/setup-validator.js +1 -0
- package/dist/utils/setup-validator.js.map +1 -1
- package/dist/utils/text-utils.d.ts +1 -0
- package/dist/utils/text-utils.js +12 -0
- package/dist/utils/text-utils.js.map +1 -1
- package/package.json +19 -4
- package/vitest.config.ts +1 -0
|
@@ -0,0 +1,181 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Best Practice Validator
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator for validation operations
|
|
5
|
+
*/
|
|
6
|
+
import { getRuleRegistry } from './rules/index.js';
|
|
7
|
+
import { createLogger } from '../../utils/analysis-logger.js';
|
|
8
|
+
import { promises as fs } from 'fs';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
export class BestPracticeValidator {
|
|
11
|
+
logger;
|
|
12
|
+
constructor(logger) {
|
|
13
|
+
this.logger = logger || createLogger();
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Validate a single file
|
|
17
|
+
*/
|
|
18
|
+
async validateFile(filePath, options) {
|
|
19
|
+
const startTime = Date.now();
|
|
20
|
+
try {
|
|
21
|
+
// Read file
|
|
22
|
+
const content = await fs.readFile(filePath, 'utf-8');
|
|
23
|
+
// Detect language from extension
|
|
24
|
+
const language = this.detectLanguage(filePath);
|
|
25
|
+
// Get applicable rules
|
|
26
|
+
const registry = getRuleRegistry();
|
|
27
|
+
const allRules = registry.getAll();
|
|
28
|
+
const enabledRules = allRules.filter(rule => {
|
|
29
|
+
const config = options?.rules?.[rule.id];
|
|
30
|
+
return config?.enabled !== false; // Enabled by default
|
|
31
|
+
});
|
|
32
|
+
this.logger.debug('Validating file', {
|
|
33
|
+
file: filePath,
|
|
34
|
+
language,
|
|
35
|
+
ruleCount: enabledRules.length,
|
|
36
|
+
});
|
|
37
|
+
// Run all rules in parallel
|
|
38
|
+
const violationArrays = await Promise.all(enabledRules.map(async (rule) => {
|
|
39
|
+
try {
|
|
40
|
+
const violations = await rule.check(filePath, content);
|
|
41
|
+
return violations;
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
this.logger.warn(`Rule ${rule.id} failed`, {
|
|
45
|
+
error: error.message,
|
|
46
|
+
});
|
|
47
|
+
return [];
|
|
48
|
+
}
|
|
49
|
+
}));
|
|
50
|
+
// Flatten violations
|
|
51
|
+
const violations = violationArrays.flat();
|
|
52
|
+
// Calculate score (0-100)
|
|
53
|
+
const score = this.calculateScore(violations);
|
|
54
|
+
const result = Object.freeze({
|
|
55
|
+
timestamp: Date.now(),
|
|
56
|
+
durationMs: Date.now() - startTime,
|
|
57
|
+
projectPath: path.dirname(filePath),
|
|
58
|
+
file: filePath,
|
|
59
|
+
language,
|
|
60
|
+
violations: Object.freeze(violations),
|
|
61
|
+
score,
|
|
62
|
+
summary: this.generateSummary(violations, score),
|
|
63
|
+
});
|
|
64
|
+
return result;
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw new Error(`Failed to validate file ${filePath}: ${error.message}`);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Validate multiple files in batch
|
|
72
|
+
*/
|
|
73
|
+
async validateBatch(filePaths, options) {
|
|
74
|
+
const startTime = Date.now();
|
|
75
|
+
this.logger.info('Starting batch validation', { fileCount: filePaths.length });
|
|
76
|
+
// Validate all files in parallel (with concurrency limit)
|
|
77
|
+
const CONCURRENCY = 5;
|
|
78
|
+
const results = [];
|
|
79
|
+
for (let i = 0; i < filePaths.length; i += CONCURRENCY) {
|
|
80
|
+
const batch = filePaths.slice(i, i + CONCURRENCY);
|
|
81
|
+
const batchResults = await Promise.all(batch.map(async (filePath) => {
|
|
82
|
+
try {
|
|
83
|
+
return await this.validateFile(filePath, options);
|
|
84
|
+
}
|
|
85
|
+
catch (error) {
|
|
86
|
+
this.logger.warn(`Failed to validate ${filePath}`, {
|
|
87
|
+
error: error.message,
|
|
88
|
+
});
|
|
89
|
+
return null;
|
|
90
|
+
}
|
|
91
|
+
}));
|
|
92
|
+
results.push(...batchResults.filter((r) => r !== null));
|
|
93
|
+
}
|
|
94
|
+
// Calculate aggregate metrics
|
|
95
|
+
const allViolations = results.flatMap(r => Array.from(r.violations));
|
|
96
|
+
const criticalCount = allViolations.filter(v => v.severity === 'critical').length;
|
|
97
|
+
const highCount = allViolations.filter(v => v.severity === 'high').length;
|
|
98
|
+
const averageScore = results.reduce((sum, r) => sum + r.score, 0) / (results.length || 1);
|
|
99
|
+
const result = Object.freeze({
|
|
100
|
+
timestamp: Date.now(),
|
|
101
|
+
durationMs: Date.now() - startTime,
|
|
102
|
+
projectPath: path.dirname(filePaths[0] || process.cwd()),
|
|
103
|
+
files: Object.freeze(results),
|
|
104
|
+
totalViolations: allViolations.length,
|
|
105
|
+
criticalCount,
|
|
106
|
+
highCount,
|
|
107
|
+
averageScore: Math.round(averageScore),
|
|
108
|
+
summary: this.generateBatchSummary(results, allViolations.length),
|
|
109
|
+
});
|
|
110
|
+
this.logger.info('Batch validation completed', {
|
|
111
|
+
fileCount: results.length,
|
|
112
|
+
violations: allViolations.length,
|
|
113
|
+
averageScore: result.averageScore,
|
|
114
|
+
});
|
|
115
|
+
return result;
|
|
116
|
+
}
|
|
117
|
+
/**
|
|
118
|
+
* Detect language from file extension
|
|
119
|
+
*/
|
|
120
|
+
detectLanguage(filePath) {
|
|
121
|
+
const ext = path.extname(filePath).toLowerCase();
|
|
122
|
+
if (ext === '.ts' || ext === '.tsx') {
|
|
123
|
+
return 'typescript';
|
|
124
|
+
}
|
|
125
|
+
return 'javascript';
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Calculate quality score (0-100)
|
|
129
|
+
*/
|
|
130
|
+
calculateScore(violations) {
|
|
131
|
+
let score = 100;
|
|
132
|
+
const severityPenalty = {
|
|
133
|
+
critical: 10,
|
|
134
|
+
high: 5,
|
|
135
|
+
medium: 2,
|
|
136
|
+
low: 1,
|
|
137
|
+
info: 0,
|
|
138
|
+
};
|
|
139
|
+
for (const violation of violations) {
|
|
140
|
+
score -= severityPenalty[violation.severity] || 0;
|
|
141
|
+
}
|
|
142
|
+
// Bonus for clean code
|
|
143
|
+
if (violations.length === 0) {
|
|
144
|
+
score = 100;
|
|
145
|
+
}
|
|
146
|
+
return Math.max(0, Math.min(100, score));
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* Generate summary text
|
|
150
|
+
*/
|
|
151
|
+
generateSummary(violations, score) {
|
|
152
|
+
if (violations.length === 0) {
|
|
153
|
+
return `Perfect score! No violations found. (Score: ${score}/100)`;
|
|
154
|
+
}
|
|
155
|
+
const bySeverity = {
|
|
156
|
+
critical: violations.filter(v => v.severity === 'critical').length,
|
|
157
|
+
high: violations.filter(v => v.severity === 'high').length,
|
|
158
|
+
medium: violations.filter(v => v.severity === 'medium').length,
|
|
159
|
+
low: violations.filter(v => v.severity === 'low').length,
|
|
160
|
+
};
|
|
161
|
+
const parts = [`Found ${violations.length} violation(s)`];
|
|
162
|
+
if (bySeverity.critical > 0)
|
|
163
|
+
parts.push(`${bySeverity.critical} critical`);
|
|
164
|
+
if (bySeverity.high > 0)
|
|
165
|
+
parts.push(`${bySeverity.high} high`);
|
|
166
|
+
if (bySeverity.medium > 0)
|
|
167
|
+
parts.push(`${bySeverity.medium} medium`);
|
|
168
|
+
if (bySeverity.low > 0)
|
|
169
|
+
parts.push(`${bySeverity.low} low`);
|
|
170
|
+
parts.push(`Score: ${score}/100`);
|
|
171
|
+
return parts.join(', ');
|
|
172
|
+
}
|
|
173
|
+
/**
|
|
174
|
+
* Generate batch summary
|
|
175
|
+
*/
|
|
176
|
+
generateBatchSummary(results, totalViolations) {
|
|
177
|
+
const avgScore = results.reduce((sum, r) => sum + r.score, 0) / (results.length || 1);
|
|
178
|
+
return `Validated ${results.length} file(s). Found ${totalViolations} violation(s). Average score: ${Math.round(avgScore)}/100`;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
//# sourceMappingURL=best-practice-validator.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"best-practice-validator.js","sourceRoot":"","sources":["../../../src/analyzers/best-practices/best-practice-validator.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAQH,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,OAAO,EAAE,YAAY,EAAE,MAAM,gCAAgC,CAAC;AAC9D,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AACpC,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,OAAO,qBAAqB;IACf,MAAM,CAAS;IAEhC,YAAY,MAAe;QACzB,IAAI,CAAC,MAAM,GAAG,MAAM,IAAI,YAAY,EAAE,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,YAAY,CAChB,QAAgB,EAChB,OAA2B;QAE3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC;YACH,YAAY;YACZ,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;YAErD,iCAAiC;YACjC,MAAM,QAAQ,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;YAE/C,uBAAuB;YACvB,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;YACnC,MAAM,QAAQ,GAAG,QAAQ,CAAC,MAAM,EAAE,CAAC;YACnC,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE;gBAC1C,MAAM,MAAM,GAAG,OAAO,EAAE,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;gBACzC,OAAO,MAAM,EAAE,OAAO,KAAK,KAAK,CAAC,CAAC,qBAAqB;YACzD,CAAC,CAAC,CAAC;YAEH,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,iBAAiB,EAAE;gBACnC,IAAI,EAAE,QAAQ;gBACd,QAAQ;gBACR,SAAS,EAAE,YAAY,CAAC,MAAM;aAC/B,CAAC,CAAC;YAEH,4BAA4B;YAC5B,MAAM,eAAe,GAAG,MAAM,OAAO,CAAC,GAAG,CACvC,YAAY,CAAC,GAAG,CAAC,KAAK,EAAC,IAAI,EAAC,EAAE;gBAC5B,IAAI,CAAC;oBACH,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;oBACvD,OAAO,UAAU,CAAC;gBACpB,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,SAAS,EAAE;wBACzC,KAAK,EAAG,KAAe,CAAC,OAAO;qBAChC,CAAC,CAAC;oBACH,OAAO,EAAE,CAAC;gBACZ,CAAC;YACH,CAAC,CAAC,CACH,CAAC;YAEF,qBAAqB;YACrB,MAAM,UAAU,GAAG,eAAe,CAAC,IAAI,EAAE,CAAC;YAE1C,0BAA0B;YAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,UAAU,CAAC,CAAC;YAE9C,MAAM,MAAM,GAAqB,MAAM,CAAC,MAAM,CAAC;gBAC7C,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;gBACrB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;gBAClC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC;gBACnC,IAAI,EAAE,QAAQ;gBACd,QAAQ;gBACR,UAAU,EAAE,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC;gBACrC,KAAK;gBACL,OAAO,EAAE,IAAI,CAAC,eAAe,CAAC,UAAU,EAAE,KAAK,CAAC;aACjD,CAAC,CAAC;YAEH,OAAO,MAAM,CAAC;QAChB,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,IAAI,KAAK,CACb,2BAA2B,QAAQ,KAAM,KAAe,CAAC,OAAO,EAAE,CACnE,CAAC;QACJ,CAAC;IACH,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CACjB,SAAmB,EACnB,OAA2B;QAE3B,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,CAAC;QAE7B,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,2BAA2B,EAAE,EAAE,SAAS,EAAE,SAAS,CAAC,MAAM,EAAE,CAAC,CAAC;QAE/E,0DAA0D;QAC1D,MAAM,WAAW,GAAG,CAAC,CAAC;QACtB,MAAM,OAAO,GAAuB,EAAE,CAAC;QAEvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,CAAC,MAAM,EAAE,CAAC,IAAI,WAAW,EAAE,CAAC;YACvD,MAAM,KAAK,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,GAAG,WAAW,CAAC,CAAC;YAClD,MAAM,YAAY,GAAG,MAAM,OAAO,CAAC,GAAG,CACpC,KAAK,CAAC,GAAG,CAAC,KAAK,EAAC,QAAQ,EAAC,EAAE;gBACzB,IAAI,CAAC;oBACH,OAAO,MAAM,IAAI,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;gBACpD,CAAC;gBAAC,OAAO,KAAK,EAAE,CAAC;oBACf,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,sBAAsB,QAAQ,EAAE,EAAE;wBACjD,KAAK,EAAG,KAAe,CAAC,OAAO;qBAChC,CAAC,CAAC;oBACH,OAAO,IAAI,CAAC;gBACd,CAAC;YACH,CAAC,CAAC,CACH,CAAC;YACF,OAAO,CAAC,IAAI,CAAC,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,EAAyB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC;QACjF,CAAC;QAED,8BAA8B;QAC9B,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC;QACrE,MAAM,aAAa,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM,CAAC;QAClF,MAAM,SAAS,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM,CAAC;QAC1E,MAAM,YAAY,GAChB,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAEvE,MAAM,MAAM,GAA0B,MAAM,CAAC,MAAM,CAAC;YAClD,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE;YACrB,UAAU,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,SAAS;YAClC,WAAW,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;YACxD,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,OAAO,CAAC;YAC7B,eAAe,EAAE,aAAa,CAAC,MAAM;YACrC,aAAa;YACb,SAAS;YACT,YAAY,EAAE,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC;YACtC,OAAO,EAAE,IAAI,CAAC,oBAAoB,CAAC,OAAO,EAAE,aAAa,CAAC,MAAM,CAAC;SAClE,CAAC,CAAC;QAEH,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,4BAA4B,EAAE;YAC7C,SAAS,EAAE,OAAO,CAAC,MAAM;YACzB,UAAU,EAAE,aAAa,CAAC,MAAM;YAChC,YAAY,EAAE,MAAM,CAAC,YAAY;SAClC,CAAC,CAAC;QAEH,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,QAAgB;QACrC,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,EAAE,CAAC;QACjD,IAAI,GAAG,KAAK,KAAK,IAAI,GAAG,KAAK,MAAM,EAAE,CAAC;YACpC,OAAO,YAAY,CAAC;QACtB,CAAC;QACD,OAAO,YAAY,CAAC;IACtB,CAAC;IAED;;OAEG;IACK,cAAc,CAAC,UAAgC;QACrD,IAAI,KAAK,GAAG,GAAG,CAAC;QAEhB,MAAM,eAAe,GAA2B;YAC9C,QAAQ,EAAE,EAAE;YACZ,IAAI,EAAE,CAAC;YACP,MAAM,EAAE,CAAC;YACT,GAAG,EAAE,CAAC;YACN,IAAI,EAAE,CAAC;SACR,CAAC;QAEF,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACnC,KAAK,IAAI,eAAe,CAAC,SAAS,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpD,CAAC;QAED,uBAAuB;QACvB,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,KAAK,GAAG,GAAG,CAAC;QACd,CAAC;QAED,OAAO,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC,CAAC;IAC3C,CAAC;IAED;;OAEG;IACK,eAAe,CAAC,UAAgC,EAAE,KAAa;QACrE,IAAI,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5B,OAAO,+CAA+C,KAAK,OAAO,CAAC;QACrE,CAAC;QAED,MAAM,UAAU,GAAG;YACjB,QAAQ,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;YAClE,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM;YAC1D,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CAAC,MAAM;YAC9D,GAAG,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,KAAK,CAAC,CAAC,MAAM;SACzD,CAAC;QAEF,MAAM,KAAK,GAAa,CAAC,SAAS,UAAU,CAAC,MAAM,eAAe,CAAC,CAAC;QAEpE,IAAI,UAAU,CAAC,QAAQ,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,QAAQ,WAAW,CAAC,CAAC;QAC3E,IAAI,UAAU,CAAC,IAAI,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,IAAI,OAAO,CAAC,CAAC;QAC/D,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,MAAM,SAAS,CAAC,CAAC;QACrE,IAAI,UAAU,CAAC,GAAG,GAAG,CAAC;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,UAAU,CAAC,GAAG,MAAM,CAAC,CAAC;QAE5D,KAAK,CAAC,IAAI,CAAC,UAAU,KAAK,MAAM,CAAC,CAAC;QAElC,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,CAAC;IAED;;OAEG;IACK,oBAAoB,CAC1B,OAAoC,EACpC,eAAuB;QAEvB,MAAM,QAAQ,GACZ,OAAO,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC,CAAC;QAEvE,OAAO,aAAa,OAAO,CAAC,MAAM,mBAAmB,eAAe,iCAAiC,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC;IAClI,CAAC;CACF"}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Validation Rule Registry
|
|
3
|
+
*
|
|
4
|
+
* Singleton registry managing all validation rules
|
|
5
|
+
*/
|
|
6
|
+
/**
|
|
7
|
+
* Singleton rule registry
|
|
8
|
+
* Manages all validation rules
|
|
9
|
+
*/
|
|
10
|
+
class ValidationRuleRegistry {
|
|
11
|
+
static instance;
|
|
12
|
+
rules = new Map();
|
|
13
|
+
constructor() { }
|
|
14
|
+
static getInstance() {
|
|
15
|
+
if (!ValidationRuleRegistry.instance) {
|
|
16
|
+
ValidationRuleRegistry.instance = new ValidationRuleRegistry();
|
|
17
|
+
}
|
|
18
|
+
return ValidationRuleRegistry.instance;
|
|
19
|
+
}
|
|
20
|
+
register(rule) {
|
|
21
|
+
if (this.rules.has(rule.id)) {
|
|
22
|
+
console.warn(`Rule ${rule.id} is already registered, overwriting`);
|
|
23
|
+
}
|
|
24
|
+
this.rules.set(rule.id, rule);
|
|
25
|
+
}
|
|
26
|
+
get(id) {
|
|
27
|
+
return this.rules.get(id);
|
|
28
|
+
}
|
|
29
|
+
getAll() {
|
|
30
|
+
return Object.freeze(Array.from(this.rules.values()));
|
|
31
|
+
}
|
|
32
|
+
getByCategory(category) {
|
|
33
|
+
return Object.freeze(Array.from(this.rules.values()).filter(r => r.category === category));
|
|
34
|
+
}
|
|
35
|
+
clear() {
|
|
36
|
+
this.rules.clear();
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
export function getRuleRegistry() {
|
|
40
|
+
return ValidationRuleRegistry.getInstance();
|
|
41
|
+
}
|
|
42
|
+
// Auto-register all TypeScript rules
|
|
43
|
+
import { NoAnyTypeRule, PreferConstRule, NoImplicitAnyRule, ProperErrorHandlingRule, ConsistentNamingRule, NoUnusedVarsRule, FunctionComplexityRule, MaxFileLengthRule, NoMagicNumbersRule, PreferReadonlyRule, } from './typescript/index.js';
|
|
44
|
+
// Register TypeScript rules on module load
|
|
45
|
+
const registry = getRuleRegistry();
|
|
46
|
+
registry.register(new NoAnyTypeRule());
|
|
47
|
+
registry.register(new PreferConstRule());
|
|
48
|
+
registry.register(new NoImplicitAnyRule());
|
|
49
|
+
registry.register(new ProperErrorHandlingRule());
|
|
50
|
+
registry.register(new ConsistentNamingRule());
|
|
51
|
+
registry.register(new NoUnusedVarsRule());
|
|
52
|
+
registry.register(new FunctionComplexityRule());
|
|
53
|
+
registry.register(new MaxFileLengthRule());
|
|
54
|
+
registry.register(new NoMagicNumbersRule());
|
|
55
|
+
registry.register(new PreferReadonlyRule());
|
|
56
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/analyzers/best-practices/rules/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,MAAM,sBAAsB;IAClB,MAAM,CAAC,QAAQ,CAAyB;IACxC,KAAK,GAAG,IAAI,GAAG,EAA0B,CAAC;IAElD,gBAAuB,CAAC;IAExB,MAAM,CAAC,WAAW;QAChB,IAAI,CAAC,sBAAsB,CAAC,QAAQ,EAAE,CAAC;YACrC,sBAAsB,CAAC,QAAQ,GAAG,IAAI,sBAAsB,EAAE,CAAC;QACjE,CAAC;QACD,OAAO,sBAAsB,CAAC,QAAQ,CAAC;IACzC,CAAC;IAED,QAAQ,CAAC,IAAoB;QAC3B,IAAI,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC,EAAE,CAAC;YAC5B,OAAO,CAAC,IAAI,CAAC,QAAQ,IAAI,CAAC,EAAE,qCAAqC,CAAC,CAAC;QACrE,CAAC;QACD,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,EAAE,IAAI,CAAC,CAAC;IAChC,CAAC;IAED,GAAG,CAAC,EAAU;QACZ,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5B,CAAC;IAED,MAAM;QACJ,OAAO,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC;IACxD,CAAC;IAED,aAAa,CAAC,QAAsB;QAClC,OAAO,MAAM,CAAC,MAAM,CAClB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,QAAQ,CAAC,CACrE,CAAC;IACJ,CAAC;IAED,KAAK;QACH,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;IACrB,CAAC;CACF;AAED,MAAM,UAAU,eAAe;IAC7B,OAAO,sBAAsB,CAAC,WAAW,EAAE,CAAC;AAC9C,CAAC;AAED,qCAAqC;AACrC,OAAO,EACL,aAAa,EACb,eAAe,EACf,iBAAiB,EACjB,uBAAuB,EACvB,oBAAoB,EACpB,gBAAgB,EAChB,sBAAsB,EACtB,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,GACnB,MAAM,uBAAuB,CAAC;AAE/B,2CAA2C;AAC3C,MAAM,QAAQ,GAAG,eAAe,EAAE,CAAC;AACnC,QAAQ,CAAC,QAAQ,CAAC,IAAI,aAAa,EAAE,CAAC,CAAC;AACvC,QAAQ,CAAC,QAAQ,CAAC,IAAI,eAAe,EAAE,CAAC,CAAC;AACzC,QAAQ,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;AAC3C,QAAQ,CAAC,QAAQ,CAAC,IAAI,uBAAuB,EAAE,CAAC,CAAC;AACjD,QAAQ,CAAC,QAAQ,CAAC,IAAI,oBAAoB,EAAE,CAAC,CAAC;AAC9C,QAAQ,CAAC,QAAQ,CAAC,IAAI,gBAAgB,EAAE,CAAC,CAAC;AAC1C,QAAQ,CAAC,QAAQ,CAAC,IAAI,sBAAsB,EAAE,CAAC,CAAC;AAChD,QAAQ,CAAC,QAAQ,CAAC,IAAI,iBAAiB,EAAE,CAAC,CAAC;AAC3C,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC;AAC5C,QAAQ,CAAC,QAAQ,CAAC,IAAI,kBAAkB,EAAE,CAAC,CAAC"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistent Naming Rule
|
|
3
|
+
*
|
|
4
|
+
* Use consistent naming conventions: camelCase for variables/functions, PascalCase for classes/interfaces
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
import type { Violation, Severity } from '../../../../types/analysis.js';
|
|
8
|
+
import type { RuleCategory } from '../../types.js';
|
|
9
|
+
export declare class ConsistentNamingRule extends BaseValidationRule {
|
|
10
|
+
readonly id = "consistent-naming";
|
|
11
|
+
readonly name = "Consistent Naming";
|
|
12
|
+
readonly description = "Use consistent naming conventions: camelCase for variables/functions, PascalCase for classes/interfaces";
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly category: RuleCategory;
|
|
15
|
+
readonly autoFixable = false;
|
|
16
|
+
check(filePath: string, content: string): Promise<Violation[]>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consistent Naming Rule
|
|
3
|
+
*
|
|
4
|
+
* Use consistent naming conventions: camelCase for variables/functions, PascalCase for classes/interfaces
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
export class ConsistentNamingRule extends BaseValidationRule {
|
|
8
|
+
id = 'consistent-naming';
|
|
9
|
+
name = 'Consistent Naming';
|
|
10
|
+
description = 'Use consistent naming conventions: camelCase for variables/functions, PascalCase for classes/interfaces';
|
|
11
|
+
severity = 'low';
|
|
12
|
+
category = 'best-practices';
|
|
13
|
+
autoFixable = false;
|
|
14
|
+
async check(filePath, content) {
|
|
15
|
+
const violations = [];
|
|
16
|
+
// Check class names (should be PascalCase)
|
|
17
|
+
const classPattern = /class\s+([a-z][a-zA-Z0-9]*)/g;
|
|
18
|
+
let match;
|
|
19
|
+
while ((match = classPattern.exec(content)) !== null) {
|
|
20
|
+
const className = match[1];
|
|
21
|
+
const pos = this.getPosition(content, match.index);
|
|
22
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, `Class name "${className}" should be in PascalCase (start with uppercase).`, `Rename to "${className.charAt(0).toUpperCase() + className.slice(1)}"`));
|
|
23
|
+
}
|
|
24
|
+
// Check interface names (should be PascalCase)
|
|
25
|
+
const interfacePattern = /interface\s+([a-z][a-zA-Z0-9]*)/g;
|
|
26
|
+
while ((match = interfacePattern.exec(content)) !== null) {
|
|
27
|
+
const interfaceName = match[1];
|
|
28
|
+
const pos = this.getPosition(content, match.index);
|
|
29
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, `Interface name "${interfaceName}" should be in PascalCase (start with uppercase).`, `Rename to "${interfaceName.charAt(0).toUpperCase() + interfaceName.slice(1)}"`));
|
|
30
|
+
}
|
|
31
|
+
// Check function names (should be camelCase, not PascalCase)
|
|
32
|
+
const functionPattern = /function\s+([A-Z][a-zA-Z0-9]*)/g;
|
|
33
|
+
while ((match = functionPattern.exec(content)) !== null) {
|
|
34
|
+
const functionName = match[1];
|
|
35
|
+
const pos = this.getPosition(content, match.index);
|
|
36
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, `Function name "${functionName}" should be in camelCase (start with lowercase).`, `Rename to "${functionName.charAt(0).toLowerCase() + functionName.slice(1)}"`));
|
|
37
|
+
}
|
|
38
|
+
return violations;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=consistent-naming.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"consistent-naming.js","sourceRoot":"","sources":["../../../../../src/analyzers/best-practices/rules/typescript/consistent-naming.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,OAAO,oBAAqB,SAAQ,kBAAkB;IACjD,EAAE,GAAG,mBAAmB,CAAC;IACzB,IAAI,GAAG,mBAAmB,CAAC;IAC3B,WAAW,GAClB,yGAAyG,CAAC;IACnG,QAAQ,GAAa,KAAK,CAAC;IAC3B,QAAQ,GAAiB,gBAAgB,CAAC;IAC1C,WAAW,GAAG,KAAK,CAAC;IAE7B,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAe;QAC3C,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,2CAA2C;QAC3C,MAAM,YAAY,GAAG,8BAA8B,CAAC;QACpD,IAAI,KAA6B,CAAC;QAElC,OAAO,CAAC,KAAK,GAAG,YAAY,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACrD,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEnD,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,QAAQ,EACR,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,EACV,eAAe,SAAS,mDAAmD,EAC3E,cAAc,SAAS,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CACxE,CACF,CAAC;QACJ,CAAC;QAED,+CAA+C;QAC/C,MAAM,gBAAgB,GAAG,kCAAkC,CAAC;QAE5D,OAAO,CAAC,KAAK,GAAG,gBAAgB,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACzD,MAAM,aAAa,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC/B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEnD,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,QAAQ,EACR,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,EACV,mBAAmB,aAAa,mDAAmD,EACnF,cAAc,aAAa,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAChF,CACF,CAAC;QACJ,CAAC;QAED,6DAA6D;QAC7D,MAAM,eAAe,GAAG,iCAAiC,CAAC;QAE1D,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACxD,MAAM,YAAY,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEnD,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,QAAQ,EACR,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,EACV,kBAAkB,YAAY,kDAAkD,EAChF,cAAc,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC,CAAC,GAAG,CAC9E,CACF,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function Complexity Rule
|
|
3
|
+
*
|
|
4
|
+
* Functions should have low cyclomatic complexity (max 10)
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
import type { Violation, Severity } from '../../../../types/analysis.js';
|
|
8
|
+
import type { RuleCategory } from '../../types.js';
|
|
9
|
+
export declare class FunctionComplexityRule extends BaseValidationRule {
|
|
10
|
+
readonly id = "function-complexity";
|
|
11
|
+
readonly name = "Function Complexity";
|
|
12
|
+
readonly description = "Functions should have low cyclomatic complexity (max 10)";
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly category: RuleCategory;
|
|
15
|
+
readonly autoFixable = false;
|
|
16
|
+
private readonly MAX_COMPLEXITY;
|
|
17
|
+
check(filePath: string, content: string): Promise<Violation[]>;
|
|
18
|
+
/**
|
|
19
|
+
* Extract function body (simplified version)
|
|
20
|
+
*/
|
|
21
|
+
private extractFunctionBody;
|
|
22
|
+
/**
|
|
23
|
+
* Calculate cyclomatic complexity
|
|
24
|
+
* Complexity = 1 + number of decision points (if, for, while, case, &&, ||, ?, catch)
|
|
25
|
+
*/
|
|
26
|
+
private calculateComplexity;
|
|
27
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Function Complexity Rule
|
|
3
|
+
*
|
|
4
|
+
* Functions should have low cyclomatic complexity (max 10)
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
export class FunctionComplexityRule extends BaseValidationRule {
|
|
8
|
+
id = 'function-complexity';
|
|
9
|
+
name = 'Function Complexity';
|
|
10
|
+
description = 'Functions should have low cyclomatic complexity (max 10)';
|
|
11
|
+
severity = 'medium';
|
|
12
|
+
category = 'maintainability';
|
|
13
|
+
autoFixable = false;
|
|
14
|
+
MAX_COMPLEXITY = 10;
|
|
15
|
+
async check(filePath, content) {
|
|
16
|
+
const violations = [];
|
|
17
|
+
// Find all function definitions
|
|
18
|
+
const functionPattern = /function\s+(\w+)\s*\([^)]*\)\s*\{/g;
|
|
19
|
+
let match;
|
|
20
|
+
while ((match = functionPattern.exec(content)) !== null) {
|
|
21
|
+
const functionName = match[1];
|
|
22
|
+
// Extract function body (simplified - finds next closing brace)
|
|
23
|
+
const startIndex = match.index + match[0].length;
|
|
24
|
+
const functionBody = this.extractFunctionBody(content, startIndex);
|
|
25
|
+
// Calculate cyclomatic complexity
|
|
26
|
+
const complexity = this.calculateComplexity(functionBody);
|
|
27
|
+
if (complexity > this.MAX_COMPLEXITY) {
|
|
28
|
+
const pos = this.getPosition(content, match.index);
|
|
29
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, `Function "${functionName}" has complexity of ${complexity}, exceeds maximum of ${this.MAX_COMPLEXITY}.`, 'Break down the function into smaller, focused functions', { complexity, limit: this.MAX_COMPLEXITY }));
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return violations;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Extract function body (simplified version)
|
|
36
|
+
*/
|
|
37
|
+
extractFunctionBody(content, startIndex) {
|
|
38
|
+
let braceCount = 1;
|
|
39
|
+
let endIndex = startIndex;
|
|
40
|
+
for (let i = startIndex; i < content.length && braceCount > 0; i++) {
|
|
41
|
+
if (content[i] === '{')
|
|
42
|
+
braceCount++;
|
|
43
|
+
if (content[i] === '}')
|
|
44
|
+
braceCount--;
|
|
45
|
+
endIndex = i;
|
|
46
|
+
}
|
|
47
|
+
return content.substring(startIndex, endIndex);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Calculate cyclomatic complexity
|
|
51
|
+
* Complexity = 1 + number of decision points (if, for, while, case, &&, ||, ?, catch)
|
|
52
|
+
*/
|
|
53
|
+
calculateComplexity(code) {
|
|
54
|
+
let complexity = 1;
|
|
55
|
+
// Count decision points
|
|
56
|
+
const decisionKeywords = [
|
|
57
|
+
/\bif\b/g,
|
|
58
|
+
/\belse\s+if\b/g,
|
|
59
|
+
/\bfor\b/g,
|
|
60
|
+
/\bwhile\b/g,
|
|
61
|
+
/\bcase\b/g,
|
|
62
|
+
/\bcatch\b/g,
|
|
63
|
+
/&&/g,
|
|
64
|
+
/\|\|/g,
|
|
65
|
+
/\?/g,
|
|
66
|
+
];
|
|
67
|
+
for (const pattern of decisionKeywords) {
|
|
68
|
+
const matches = code.match(pattern);
|
|
69
|
+
if (matches) {
|
|
70
|
+
complexity += matches.length;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
return complexity;
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
//# sourceMappingURL=function-complexity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"function-complexity.js","sourceRoot":"","sources":["../../../../../src/analyzers/best-practices/rules/typescript/function-complexity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript Validation Rules
|
|
3
|
+
*
|
|
4
|
+
* Exports all TypeScript-specific validation rules
|
|
5
|
+
*/
|
|
6
|
+
export { NoAnyTypeRule } from './no-any-type.js';
|
|
7
|
+
export { PreferConstRule } from './prefer-const.js';
|
|
8
|
+
export { NoImplicitAnyRule } from './no-implicit-any.js';
|
|
9
|
+
export { ProperErrorHandlingRule } from './proper-error-handling.js';
|
|
10
|
+
export { ConsistentNamingRule } from './consistent-naming.js';
|
|
11
|
+
export { NoUnusedVarsRule } from './no-unused-vars.js';
|
|
12
|
+
export { FunctionComplexityRule } from './function-complexity.js';
|
|
13
|
+
export { MaxFileLengthRule } from './max-file-length.js';
|
|
14
|
+
export { NoMagicNumbersRule } from './no-magic-numbers.js';
|
|
15
|
+
export { PreferReadonlyRule } from './prefer-readonly.js';
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* TypeScript Validation Rules
|
|
3
|
+
*
|
|
4
|
+
* Exports all TypeScript-specific validation rules
|
|
5
|
+
*/
|
|
6
|
+
export { NoAnyTypeRule } from './no-any-type.js';
|
|
7
|
+
export { PreferConstRule } from './prefer-const.js';
|
|
8
|
+
export { NoImplicitAnyRule } from './no-implicit-any.js';
|
|
9
|
+
export { ProperErrorHandlingRule } from './proper-error-handling.js';
|
|
10
|
+
export { ConsistentNamingRule } from './consistent-naming.js';
|
|
11
|
+
export { NoUnusedVarsRule } from './no-unused-vars.js';
|
|
12
|
+
export { FunctionComplexityRule } from './function-complexity.js';
|
|
13
|
+
export { MaxFileLengthRule } from './max-file-length.js';
|
|
14
|
+
export { NoMagicNumbersRule } from './no-magic-numbers.js';
|
|
15
|
+
export { PreferReadonlyRule } from './prefer-readonly.js';
|
|
16
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../../src/analyzers/best-practices/rules/typescript/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,uBAAuB,EAAE,MAAM,4BAA4B,CAAC;AACrE,OAAO,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AACvD,OAAO,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,MAAM,sBAAsB,CAAC;AACzD,OAAO,EAAE,kBAAkB,EAAE,MAAM,uBAAuB,CAAC;AAC3D,OAAO,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Max File Length Rule
|
|
3
|
+
*
|
|
4
|
+
* Files should not exceed 300 lines for better maintainability
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
import type { Violation, Severity } from '../../../../types/analysis.js';
|
|
8
|
+
import type { RuleCategory } from '../../types.js';
|
|
9
|
+
export declare class MaxFileLengthRule extends BaseValidationRule {
|
|
10
|
+
readonly id = "max-file-length";
|
|
11
|
+
readonly name = "Max File Length";
|
|
12
|
+
readonly description = "Files should not exceed 300 lines for better maintainability";
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly category: RuleCategory;
|
|
15
|
+
readonly autoFixable = false;
|
|
16
|
+
private readonly MAX_LINES;
|
|
17
|
+
check(filePath: string, content: string): Promise<Violation[]>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Max File Length Rule
|
|
3
|
+
*
|
|
4
|
+
* Files should not exceed 300 lines for better maintainability
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
export class MaxFileLengthRule extends BaseValidationRule {
|
|
8
|
+
id = 'max-file-length';
|
|
9
|
+
name = 'Max File Length';
|
|
10
|
+
description = 'Files should not exceed 300 lines for better maintainability';
|
|
11
|
+
severity = 'low';
|
|
12
|
+
category = 'maintainability';
|
|
13
|
+
autoFixable = false;
|
|
14
|
+
MAX_LINES = 300;
|
|
15
|
+
async check(filePath, content) {
|
|
16
|
+
const violations = [];
|
|
17
|
+
const lines = content.split('\n');
|
|
18
|
+
const lineCount = lines.length;
|
|
19
|
+
if (lineCount > this.MAX_LINES) {
|
|
20
|
+
violations.push(this.createViolation(filePath, 1, 1, `File has ${lineCount} lines, exceeds maximum of ${this.MAX_LINES}.`, 'Consider splitting this file into smaller, focused modules', { lineCount, limit: this.MAX_LINES }));
|
|
21
|
+
}
|
|
22
|
+
return violations;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
//# sourceMappingURL=max-file-length.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"max-file-length.js","sourceRoot":"","sources":["../../../../../src/analyzers/best-practices/rules/typescript/max-file-length.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,OAAO,iBAAkB,SAAQ,kBAAkB;IAC9C,EAAE,GAAG,iBAAiB,CAAC;IACvB,IAAI,GAAG,iBAAiB,CAAC;IACzB,WAAW,GAAG,8DAA8D,CAAC;IAC7E,QAAQ,GAAa,KAAK,CAAC;IAC3B,QAAQ,GAAiB,iBAAiB,CAAC;IAC3C,WAAW,GAAG,KAAK,CAAC;IAEZ,SAAS,GAAG,GAAG,CAAC;IAEjC,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAe;QAC3C,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAClC,MAAM,SAAS,GAAG,KAAK,CAAC,MAAM,CAAC;QAE/B,IAAI,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,CAAC;YAC/B,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,QAAQ,EACR,CAAC,EACD,CAAC,EACD,YAAY,SAAS,8BAA8B,IAAI,CAAC,SAAS,GAAG,EACpE,4DAA4D,EAC5D,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,CACrC,CACF,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No Any Type Rule
|
|
3
|
+
*
|
|
4
|
+
* Detect usage of the 'any' type which defeats TypeScript's type safety
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
import type { Violation, Severity } from '../../../../types/analysis.js';
|
|
8
|
+
import type { RuleCategory } from '../../types.js';
|
|
9
|
+
export declare class NoAnyTypeRule extends BaseValidationRule {
|
|
10
|
+
readonly id = "no-any-type";
|
|
11
|
+
readonly name = "No Any Type";
|
|
12
|
+
readonly description = "Avoid using the \"any\" type - use specific types instead";
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly category: RuleCategory;
|
|
15
|
+
readonly autoFixable = false;
|
|
16
|
+
check(filePath: string, content: string): Promise<Violation[]>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No Any Type Rule
|
|
3
|
+
*
|
|
4
|
+
* Detect usage of the 'any' type which defeats TypeScript's type safety
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
export class NoAnyTypeRule extends BaseValidationRule {
|
|
8
|
+
id = 'no-any-type';
|
|
9
|
+
name = 'No Any Type';
|
|
10
|
+
description = 'Avoid using the "any" type - use specific types instead';
|
|
11
|
+
severity = 'high';
|
|
12
|
+
category = 'type-safety';
|
|
13
|
+
autoFixable = false;
|
|
14
|
+
async check(filePath, content) {
|
|
15
|
+
const violations = [];
|
|
16
|
+
// Pattern to match: any type annotations
|
|
17
|
+
// Matches: ': any', '<any>', 'Array<any>', etc.
|
|
18
|
+
const anyTypePattern = /:\s*any\b|<any>|Array<any>/g;
|
|
19
|
+
let match;
|
|
20
|
+
while ((match = anyTypePattern.exec(content)) !== null) {
|
|
21
|
+
const pos = this.getPosition(content, match.index);
|
|
22
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, 'Avoid using "any" type. Use specific types for better type safety.', 'Replace "any" with a specific type (e.g., string, number, SomeInterface)'));
|
|
23
|
+
}
|
|
24
|
+
return violations;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
//# sourceMappingURL=no-any-type.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"no-any-type.js","sourceRoot":"","sources":["../../../../../src/analyzers/best-practices/rules/typescript/no-any-type.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAIxD,MAAM,OAAO,aAAc,SAAQ,kBAAkB;IAC1C,EAAE,GAAG,aAAa,CAAC;IACnB,IAAI,GAAG,aAAa,CAAC;IACrB,WAAW,GAAG,yDAAyD,CAAC;IACxE,QAAQ,GAAa,MAAM,CAAC;IAC5B,QAAQ,GAAiB,aAAa,CAAC;IACvC,WAAW,GAAG,KAAK,CAAC;IAE7B,KAAK,CAAC,KAAK,CAAC,QAAgB,EAAE,OAAe;QAC3C,MAAM,UAAU,GAAgB,EAAE,CAAC;QAEnC,yCAAyC;QACzC,gDAAgD;QAChD,MAAM,cAAc,GAAG,6BAA6B,CAAC;QAErD,IAAI,KAA6B,CAAC;QAClC,OAAO,CAAC,KAAK,GAAG,cAAc,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;YACvD,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC;YAEnD,UAAU,CAAC,IAAI,CACb,IAAI,CAAC,eAAe,CAClB,QAAQ,EACR,GAAG,CAAC,IAAI,EACR,GAAG,CAAC,MAAM,EACV,oEAAoE,EACpE,0EAA0E,CAC3E,CACF,CAAC;QACJ,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No Implicit Any Rule
|
|
3
|
+
*
|
|
4
|
+
* Function parameters and variables should have explicit types
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
import type { Violation, Severity } from '../../../../types/analysis.js';
|
|
8
|
+
import type { RuleCategory } from '../../types.js';
|
|
9
|
+
export declare class NoImplicitAnyRule extends BaseValidationRule {
|
|
10
|
+
readonly id = "no-implicit-any";
|
|
11
|
+
readonly name = "No Implicit Any";
|
|
12
|
+
readonly description = "Function parameters and variables should have explicit types";
|
|
13
|
+
readonly severity: Severity;
|
|
14
|
+
readonly category: RuleCategory;
|
|
15
|
+
readonly autoFixable = false;
|
|
16
|
+
check(filePath: string, content: string): Promise<Violation[]>;
|
|
17
|
+
private checkPattern;
|
|
18
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* No Implicit Any Rule
|
|
3
|
+
*
|
|
4
|
+
* Function parameters and variables should have explicit types
|
|
5
|
+
*/
|
|
6
|
+
import { BaseValidationRule } from '../../base-rule.js';
|
|
7
|
+
export class NoImplicitAnyRule extends BaseValidationRule {
|
|
8
|
+
id = 'no-implicit-any';
|
|
9
|
+
name = 'No Implicit Any';
|
|
10
|
+
description = 'Function parameters and variables should have explicit types';
|
|
11
|
+
severity = 'medium';
|
|
12
|
+
category = 'type-safety';
|
|
13
|
+
autoFixable = false;
|
|
14
|
+
async check(filePath, content) {
|
|
15
|
+
const violations = [];
|
|
16
|
+
// Pattern: function parameters without type annotations
|
|
17
|
+
const functionPattern = /function\s+\w+\s*\(([^)]+)\)/g;
|
|
18
|
+
const arrowFunctionPattern = /\(([^)]+)\)\s*=>/g;
|
|
19
|
+
this.checkPattern(content, filePath, functionPattern, violations);
|
|
20
|
+
this.checkPattern(content, filePath, arrowFunctionPattern, violations);
|
|
21
|
+
return violations;
|
|
22
|
+
}
|
|
23
|
+
checkPattern(content, filePath, pattern, violations) {
|
|
24
|
+
let match;
|
|
25
|
+
while ((match = pattern.exec(content)) !== null) {
|
|
26
|
+
const params = match[1];
|
|
27
|
+
// Check each parameter
|
|
28
|
+
const paramList = params.split(',').map(p => p.trim());
|
|
29
|
+
for (const param of paramList) {
|
|
30
|
+
// If parameter doesn't have a type annotation (no ':')
|
|
31
|
+
if (param && !param.includes(':') && param !== '...args') {
|
|
32
|
+
const pos = this.getPosition(content, match.index);
|
|
33
|
+
violations.push(this.createViolation(filePath, pos.line, pos.column, `Parameter "${param}" has implicit "any" type. Add explicit type annotation.`, `Add type annotation: "${param}: SomeType"`));
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=no-implicit-any.js.map
|