@girardelli/architect-core 8.1.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/dist/src/core/analyzer.d.ts +42 -0
- package/dist/src/core/analyzer.js +431 -0
- package/dist/src/core/analyzer.js.map +1 -0
- package/dist/src/core/analyzers/forecast.d.ts +84 -0
- package/dist/src/core/analyzers/forecast.js +338 -0
- package/dist/src/core/analyzers/forecast.js.map +1 -0
- package/dist/src/core/analyzers/index.d.ts +9 -0
- package/dist/src/core/analyzers/index.js +7 -0
- package/dist/src/core/analyzers/index.js.map +1 -0
- package/dist/src/core/analyzers/temporal-scorer.d.ts +71 -0
- package/dist/src/core/analyzers/temporal-scorer.js +141 -0
- package/dist/src/core/analyzers/temporal-scorer.js.map +1 -0
- package/dist/src/core/anti-patterns.d.ts +28 -0
- package/dist/src/core/anti-patterns.js +264 -0
- package/dist/src/core/anti-patterns.js.map +1 -0
- package/dist/src/core/ast/ast-parser.interface.d.ts +20 -0
- package/dist/src/core/ast/ast-parser.interface.js +2 -0
- package/dist/src/core/ast/ast-parser.interface.js.map +1 -0
- package/dist/src/core/ast/path-resolver.d.ts +13 -0
- package/dist/src/core/ast/path-resolver.js +54 -0
- package/dist/src/core/ast/path-resolver.js.map +1 -0
- package/dist/src/core/ast/tree-sitter-parser.d.ts +10 -0
- package/dist/src/core/ast/tree-sitter-parser.js +142 -0
- package/dist/src/core/ast/tree-sitter-parser.js.map +1 -0
- package/dist/src/core/config.d.ts +11 -0
- package/dist/src/core/config.js +112 -0
- package/dist/src/core/config.js.map +1 -0
- package/dist/src/core/diagram.d.ts +9 -0
- package/dist/src/core/diagram.js +101 -0
- package/dist/src/core/diagram.js.map +1 -0
- package/dist/src/core/i18n.d.ts +14 -0
- package/dist/src/core/i18n.js +54 -0
- package/dist/src/core/i18n.js.map +1 -0
- package/dist/src/core/locales/en.d.ts +2 -0
- package/dist/src/core/locales/en.js +337 -0
- package/dist/src/core/locales/en.js.map +1 -0
- package/dist/src/core/locales/pt-BR.d.ts +172 -0
- package/dist/src/core/locales/pt-BR.js +337 -0
- package/dist/src/core/locales/pt-BR.js.map +1 -0
- package/dist/src/core/locales/types.d.ts +86 -0
- package/dist/src/core/locales/types.js +2 -0
- package/dist/src/core/locales/types.js.map +1 -0
- package/dist/src/core/plugin-loader.d.ts +11 -0
- package/dist/src/core/plugin-loader.js +67 -0
- package/dist/src/core/plugin-loader.js.map +1 -0
- package/dist/src/core/project-summarizer.d.ts +16 -0
- package/dist/src/core/project-summarizer.js +37 -0
- package/dist/src/core/project-summarizer.js.map +1 -0
- package/dist/src/core/refactor-engine.d.ts +18 -0
- package/dist/src/core/refactor-engine.js +87 -0
- package/dist/src/core/refactor-engine.js.map +1 -0
- package/dist/src/core/rules/barrel-optimizer.d.ts +13 -0
- package/dist/src/core/rules/barrel-optimizer.js +76 -0
- package/dist/src/core/rules/barrel-optimizer.js.map +1 -0
- package/dist/src/core/rules/dead-code-detector.d.ts +21 -0
- package/dist/src/core/rules/dead-code-detector.js +116 -0
- package/dist/src/core/rules/dead-code-detector.js.map +1 -0
- package/dist/src/core/rules/hub-splitter.d.ts +13 -0
- package/dist/src/core/rules/hub-splitter.js +117 -0
- package/dist/src/core/rules/hub-splitter.js.map +1 -0
- package/dist/src/core/rules/import-organizer.d.ts +13 -0
- package/dist/src/core/rules/import-organizer.js +84 -0
- package/dist/src/core/rules/import-organizer.js.map +1 -0
- package/dist/src/core/rules/module-grouper.d.ts +13 -0
- package/dist/src/core/rules/module-grouper.js +116 -0
- package/dist/src/core/rules/module-grouper.js.map +1 -0
- package/dist/src/core/rules-engine.d.ts +7 -0
- package/dist/src/core/rules-engine.js +89 -0
- package/dist/src/core/rules-engine.js.map +1 -0
- package/dist/src/core/scorer.d.ts +15 -0
- package/dist/src/core/scorer.js +165 -0
- package/dist/src/core/scorer.js.map +1 -0
- package/dist/src/core/summarizer/keyword-extractor.d.ts +6 -0
- package/dist/src/core/summarizer/keyword-extractor.js +38 -0
- package/dist/src/core/summarizer/keyword-extractor.js.map +1 -0
- package/dist/src/core/summarizer/module-inferrer.d.ts +11 -0
- package/dist/src/core/summarizer/module-inferrer.js +171 -0
- package/dist/src/core/summarizer/module-inferrer.js.map +1 -0
- package/dist/src/core/summarizer/package-reader.d.ts +3 -0
- package/dist/src/core/summarizer/package-reader.js +33 -0
- package/dist/src/core/summarizer/package-reader.js.map +1 -0
- package/dist/src/core/summarizer/purpose-inferrer.d.ts +8 -0
- package/dist/src/core/summarizer/purpose-inferrer.js +179 -0
- package/dist/src/core/summarizer/purpose-inferrer.js.map +1 -0
- package/dist/src/core/summarizer/readme-reader.d.ts +3 -0
- package/dist/src/core/summarizer/readme-reader.js +24 -0
- package/dist/src/core/summarizer/readme-reader.js.map +1 -0
- package/dist/src/core/types/architect-rules.d.ts +27 -0
- package/dist/src/core/types/architect-rules.js +2 -0
- package/dist/src/core/types/architect-rules.js.map +1 -0
- package/dist/src/core/types/core.d.ts +87 -0
- package/dist/src/core/types/core.js +2 -0
- package/dist/src/core/types/core.js.map +1 -0
- package/dist/src/core/types/infrastructure.d.ts +38 -0
- package/dist/src/core/types/infrastructure.js +2 -0
- package/dist/src/core/types/infrastructure.js.map +1 -0
- package/dist/src/core/types/plugin.d.ts +12 -0
- package/dist/src/core/types/plugin.js +2 -0
- package/dist/src/core/types/plugin.js.map +1 -0
- package/dist/src/core/types/rules.d.ts +53 -0
- package/dist/src/core/types/rules.js +2 -0
- package/dist/src/core/types/rules.js.map +1 -0
- package/dist/src/core/types/summarizer.d.ts +12 -0
- package/dist/src/core/types/summarizer.js +2 -0
- package/dist/src/core/types/summarizer.js.map +1 -0
- package/dist/src/infrastructure/git-cache.d.ts +6 -0
- package/dist/src/infrastructure/git-cache.js +41 -0
- package/dist/src/infrastructure/git-cache.js.map +1 -0
- package/dist/src/infrastructure/git-history.d.ts +112 -0
- package/dist/src/infrastructure/git-history.js +340 -0
- package/dist/src/infrastructure/git-history.js.map +1 -0
- package/dist/src/infrastructure/logger.d.ts +20 -0
- package/dist/src/infrastructure/logger.js +57 -0
- package/dist/src/infrastructure/logger.js.map +1 -0
- package/dist/src/infrastructure/scanner.d.ts +31 -0
- package/dist/src/infrastructure/scanner.js +334 -0
- package/dist/src/infrastructure/scanner.js.map +1 -0
- package/dist/tests/analyzers-integration.test.d.ts +7 -0
- package/dist/tests/analyzers-integration.test.js +140 -0
- package/dist/tests/analyzers-integration.test.js.map +1 -0
- package/dist/tests/anti-patterns.test.d.ts +1 -0
- package/dist/tests/anti-patterns.test.js +81 -0
- package/dist/tests/anti-patterns.test.js.map +1 -0
- package/dist/tests/ast-parser.test.d.ts +1 -0
- package/dist/tests/ast-parser.test.js +94 -0
- package/dist/tests/ast-parser.test.js.map +1 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.d.ts +1 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.js +9 -0
- package/dist/tests/fixtures/monorepo/packages/app/src/index.js.map +1 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.d.ts +2 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.js +11 -0
- package/dist/tests/fixtures/monorepo/packages/core/src/index.js.map +1 -0
- package/dist/tests/forecast.test.d.ts +7 -0
- package/dist/tests/forecast.test.js +380 -0
- package/dist/tests/forecast.test.js.map +1 -0
- package/dist/tests/git-history.test.d.ts +7 -0
- package/dist/tests/git-history.test.js +193 -0
- package/dist/tests/git-history.test.js.map +1 -0
- package/dist/tests/i18n.test.d.ts +1 -0
- package/dist/tests/i18n.test.js +39 -0
- package/dist/tests/i18n.test.js.map +1 -0
- package/dist/tests/monorepo-scan.test.d.ts +11 -0
- package/dist/tests/monorepo-scan.test.js +143 -0
- package/dist/tests/monorepo-scan.test.js.map +1 -0
- package/dist/tests/plugin-loader.test.d.ts +1 -0
- package/dist/tests/plugin-loader.test.js +31 -0
- package/dist/tests/plugin-loader.test.js.map +1 -0
- package/dist/tests/rules-engine.test.d.ts +1 -0
- package/dist/tests/rules-engine.test.js +112 -0
- package/dist/tests/rules-engine.test.js.map +1 -0
- package/dist/tests/scanner.test.d.ts +1 -0
- package/dist/tests/scanner.test.js +44 -0
- package/dist/tests/scanner.test.js.map +1 -0
- package/dist/tests/scorer.test.d.ts +1 -0
- package/dist/tests/scorer.test.js +610 -0
- package/dist/tests/scorer.test.js.map +1 -0
- package/dist/tests/temporal-scorer.test.d.ts +7 -0
- package/dist/tests/temporal-scorer.test.js +239 -0
- package/dist/tests/temporal-scorer.test.js.map +1 -0
- package/package.json +29 -0
- package/src/core/analyzer.ts +499 -0
- package/src/core/analyzers/forecast.ts +497 -0
- package/src/core/analyzers/index.ts +33 -0
- package/src/core/analyzers/temporal-scorer.ts +227 -0
- package/src/core/anti-patterns.ts +324 -0
- package/src/core/ast/ast-parser.interface.ts +21 -0
- package/src/core/ast/path-resolver.ts +61 -0
- package/src/core/ast/tree-sitter-parser.ts +158 -0
- package/src/core/config.ts +125 -0
- package/src/core/diagram.ts +129 -0
- package/src/core/i18n.ts +64 -0
- package/src/core/locales/en.ts +340 -0
- package/src/core/locales/pt-BR.ts +341 -0
- package/src/core/locales/types.ts +95 -0
- package/src/core/plugin-loader.ts +80 -0
- package/src/core/project-summarizer.ts +42 -0
- package/src/core/refactor-engine.ts +112 -0
- package/src/core/rules/barrel-optimizer.ts +99 -0
- package/src/core/rules/dead-code-detector.ts +134 -0
- package/src/core/rules/hub-splitter.ts +135 -0
- package/src/core/rules/import-organizer.ts +100 -0
- package/src/core/rules/module-grouper.ts +133 -0
- package/src/core/rules-engine.ts +100 -0
- package/src/core/scorer.ts +181 -0
- package/src/core/summarizer/keyword-extractor.ts +53 -0
- package/src/core/summarizer/module-inferrer.ts +194 -0
- package/src/core/summarizer/package-reader.ts +34 -0
- package/src/core/summarizer/purpose-inferrer.ts +197 -0
- package/src/core/summarizer/readme-reader.ts +24 -0
- package/src/core/types/architect-rules.ts +29 -0
- package/src/core/types/core.ts +94 -0
- package/src/core/types/infrastructure.ts +41 -0
- package/src/core/types/plugin.ts +19 -0
- package/src/core/types/rules.ts +51 -0
- package/src/core/types/summarizer.ts +8 -0
- package/src/infrastructure/git-cache.ts +52 -0
- package/src/infrastructure/git-history.ts +496 -0
- package/src/infrastructure/logger.ts +68 -0
- package/src/infrastructure/scanner.ts +349 -0
- package/tests/analyzers-integration.test.ts +174 -0
- package/tests/anti-patterns.test.ts +95 -0
- package/tests/ast-parser.test.ts +102 -0
- package/tests/fixtures/monorepo/package.json +6 -0
- package/tests/fixtures/monorepo/packages/app/package.json +12 -0
- package/tests/fixtures/monorepo/packages/app/src/index.ts +6 -0
- package/tests/fixtures/monorepo/packages/core/package.json +7 -0
- package/tests/fixtures/monorepo/packages/core/src/index.ts +7 -0
- package/tests/forecast.test.ts +504 -0
- package/tests/git-history.test.ts +254 -0
- package/tests/i18n.test.ts +47 -0
- package/tests/monorepo-scan.test.ts +170 -0
- package/tests/plugin-loader.test.ts +40 -0
- package/tests/rules-engine.test.ts +131 -0
- package/tests/scanner.test.ts +54 -0
- package/tests/scorer.test.ts +675 -0
- package/tests/temporal-scorer.test.ts +306 -0
- package/tsconfig.json +9 -0
|
@@ -0,0 +1,264 @@
|
|
|
1
|
+
import { readFileSync } from 'fs';
|
|
2
|
+
import { logger } from '../infrastructure/logger.js';
|
|
3
|
+
export class AntiPatternDetector {
|
|
4
|
+
config;
|
|
5
|
+
dependencyGraph;
|
|
6
|
+
/** Paths that indicate third-party or build artifacts — never report anti-patterns here */
|
|
7
|
+
static EXCLUDED_PATH_SEGMENTS = [
|
|
8
|
+
'node_modules', '/dist/', '/build/', '/coverage/',
|
|
9
|
+
'/.next/', '/venv/', '/__pycache__/', '/target/',
|
|
10
|
+
];
|
|
11
|
+
customDetectors = [];
|
|
12
|
+
pluginContext;
|
|
13
|
+
constructor(config) {
|
|
14
|
+
this.config = config;
|
|
15
|
+
this.dependencyGraph = new Map();
|
|
16
|
+
}
|
|
17
|
+
setCustomDetectors(detectors) {
|
|
18
|
+
this.customDetectors = detectors;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Check if a file path belongs to the project's own source code.
|
|
22
|
+
* Returns false for node_modules, dist, build artifacts, etc.
|
|
23
|
+
*/
|
|
24
|
+
isProjectFile(filePath) {
|
|
25
|
+
const normalized = filePath.replace(/\\/g, '/');
|
|
26
|
+
return !AntiPatternDetector.EXCLUDED_PATH_SEGMENTS.some(seg => normalized.includes(seg));
|
|
27
|
+
}
|
|
28
|
+
async detect(fileTree, dependencies) {
|
|
29
|
+
this.dependencyGraph = dependencies;
|
|
30
|
+
const patterns = [];
|
|
31
|
+
patterns.push(...this.detectGodClasses(fileTree));
|
|
32
|
+
patterns.push(...this.detectCircularDependencies());
|
|
33
|
+
patterns.push(...this.detectLeakyAbstractions(fileTree));
|
|
34
|
+
patterns.push(...this.detectFeatureEnvy(fileTree, dependencies));
|
|
35
|
+
patterns.push(...this.detectShotgunSurgery(dependencies));
|
|
36
|
+
// Execute Enterprise Custom Plugin Detectors
|
|
37
|
+
const context = this.pluginContext || {
|
|
38
|
+
config: this.config,
|
|
39
|
+
projectPath: process.cwd() // Fallback if not injected explicitly
|
|
40
|
+
};
|
|
41
|
+
for (const detector of this.customDetectors) {
|
|
42
|
+
try {
|
|
43
|
+
const customPatterns = await detector(fileTree, dependencies, context);
|
|
44
|
+
if (Array.isArray(customPatterns)) {
|
|
45
|
+
patterns.push(...customPatterns);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
logger.warn(`[Architect Plugin] A custom rule engine failed during detection: ${err.message}`);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
return patterns.sort((a, b) => {
|
|
53
|
+
const severityOrder = {
|
|
54
|
+
CRITICAL: 0,
|
|
55
|
+
HIGH: 1,
|
|
56
|
+
MEDIUM: 2,
|
|
57
|
+
LOW: 3,
|
|
58
|
+
};
|
|
59
|
+
return severityOrder[a.severity] - severityOrder[b.severity];
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
detectGodClasses(node) {
|
|
63
|
+
const patterns = [];
|
|
64
|
+
const threshold = this.config.antiPatterns?.godClass?.linesThreshold || 800; // Increased to 800 for OSS realities
|
|
65
|
+
const methodThreshold = this.config.antiPatterns?.godClass?.methodsThreshold || 20; // Increased to 20
|
|
66
|
+
this.walkFileTree(node, (file) => {
|
|
67
|
+
if (file.type === 'file' && (file.lines || 0) > threshold && this.isProjectFile(file.path)) {
|
|
68
|
+
const methods = this.countMethods(file.path);
|
|
69
|
+
if (methods > methodThreshold) {
|
|
70
|
+
patterns.push({
|
|
71
|
+
name: 'God Class',
|
|
72
|
+
severity: 'CRITICAL',
|
|
73
|
+
location: file.path,
|
|
74
|
+
description: `Class with ${file.lines} lines and ${methods} methods violates single responsibility principle`,
|
|
75
|
+
suggestion: 'Consider splitting into smaller, focused classes with specific responsibilities',
|
|
76
|
+
metrics: {
|
|
77
|
+
lines: file.lines || 0,
|
|
78
|
+
methods,
|
|
79
|
+
},
|
|
80
|
+
});
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
return patterns;
|
|
85
|
+
}
|
|
86
|
+
detectCircularDependencies() {
|
|
87
|
+
const patterns = [];
|
|
88
|
+
const visited = new Set();
|
|
89
|
+
const recursionStack = new Set();
|
|
90
|
+
for (const file of this.dependencyGraph.keys()) {
|
|
91
|
+
// Only check cycles starting from project files
|
|
92
|
+
if (!this.isProjectFile(file))
|
|
93
|
+
continue;
|
|
94
|
+
if (!visited.has(file)) {
|
|
95
|
+
const cycle = this.findCycle(file, visited, recursionStack);
|
|
96
|
+
if (cycle && cycle.every(f => this.isProjectFile(f))) {
|
|
97
|
+
patterns.push({
|
|
98
|
+
name: 'Circular Dependency',
|
|
99
|
+
severity: 'HIGH',
|
|
100
|
+
location: cycle.join(' -> '),
|
|
101
|
+
description: `Circular dependency detected: ${cycle.join(' -> ')}`,
|
|
102
|
+
suggestion: 'Refactor code to break the circular dependency using dependency injection or intermediate abstractions',
|
|
103
|
+
affectedFiles: cycle,
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
return patterns;
|
|
109
|
+
}
|
|
110
|
+
findCycle(node, visited, recursionStack) {
|
|
111
|
+
visited.add(node);
|
|
112
|
+
recursionStack.add(node);
|
|
113
|
+
const neighbors = this.dependencyGraph.get(node) || new Set();
|
|
114
|
+
for (const neighbor of neighbors) {
|
|
115
|
+
if (!visited.has(neighbor)) {
|
|
116
|
+
const cycle = this.findCycle(neighbor, visited, recursionStack);
|
|
117
|
+
if (cycle) {
|
|
118
|
+
cycle.unshift(node);
|
|
119
|
+
return cycle;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (recursionStack.has(neighbor)) {
|
|
123
|
+
return [node, neighbor];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
recursionStack.delete(node);
|
|
127
|
+
return null;
|
|
128
|
+
}
|
|
129
|
+
detectLeakyAbstractions(node) {
|
|
130
|
+
const patterns = [];
|
|
131
|
+
this.walkFileTree(node, (file) => {
|
|
132
|
+
if (file.type === 'file' && this.isProjectFile(file.path)) {
|
|
133
|
+
const internalExports = this.countInternalExports(file.path);
|
|
134
|
+
if (internalExports > 5) {
|
|
135
|
+
patterns.push({
|
|
136
|
+
name: 'Leaky Abstraction',
|
|
137
|
+
severity: 'MEDIUM',
|
|
138
|
+
location: file.path,
|
|
139
|
+
description: `Exports ${internalExports} internal types that should be private`,
|
|
140
|
+
suggestion: 'Use private/internal access modifiers and facade patterns to hide implementation details',
|
|
141
|
+
metrics: {
|
|
142
|
+
exportedInternalTypes: internalExports,
|
|
143
|
+
},
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
return patterns;
|
|
149
|
+
}
|
|
150
|
+
detectFeatureEnvy(node, dependencies) {
|
|
151
|
+
const patterns = [];
|
|
152
|
+
this.walkFileTree(node, (file) => {
|
|
153
|
+
if (file.type === 'file' && this.isProjectFile(file.path)) {
|
|
154
|
+
const externalMethodCalls = (dependencies.get(file.path) || new Set())
|
|
155
|
+
.size;
|
|
156
|
+
const internalMethods = this.countMethods(file.path);
|
|
157
|
+
const name = file.name.toLowerCase();
|
|
158
|
+
// Skip infrastructure files where external deps are by design
|
|
159
|
+
const isInfraFile = name.endsWith('.module.ts') ||
|
|
160
|
+
name.endsWith('.dto.ts') ||
|
|
161
|
+
name.endsWith('.entity.ts') ||
|
|
162
|
+
name.endsWith('.guard.ts') ||
|
|
163
|
+
name.endsWith('.pipe.ts') ||
|
|
164
|
+
name.endsWith('.interceptor.ts') ||
|
|
165
|
+
name.endsWith('.filter.ts') ||
|
|
166
|
+
name.endsWith('.decorator.ts') ||
|
|
167
|
+
name.endsWith('.spec.ts') ||
|
|
168
|
+
name.endsWith('.test.ts') ||
|
|
169
|
+
name.endsWith('-engine.ts') ||
|
|
170
|
+
name.endsWith('-enricher.ts') ||
|
|
171
|
+
name.endsWith('-detector.ts') ||
|
|
172
|
+
file.path.includes('/scripts/');
|
|
173
|
+
if (!isInfraFile && internalMethods > 0 && externalMethodCalls > internalMethods * 3) {
|
|
174
|
+
patterns.push({
|
|
175
|
+
name: 'Feature Envy',
|
|
176
|
+
severity: 'MEDIUM',
|
|
177
|
+
location: file.path,
|
|
178
|
+
description: `Uses more external methods (${externalMethodCalls}) than internal methods (${internalMethods})`,
|
|
179
|
+
suggestion: 'Move functionality closer to where it is used or extract to shared utility',
|
|
180
|
+
metrics: {
|
|
181
|
+
externalMethodCalls,
|
|
182
|
+
internalMethods,
|
|
183
|
+
},
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
return patterns;
|
|
189
|
+
}
|
|
190
|
+
detectShotgunSurgery(dependencies) {
|
|
191
|
+
const patterns = [];
|
|
192
|
+
const threshold = this.config.antiPatterns?.shotgunSurgery?.changePropagationThreshold ||
|
|
193
|
+
Math.max(15, Math.ceil(this.dependencyGraph.size * 0.02));
|
|
194
|
+
for (const [file, dependents] of dependencies) {
|
|
195
|
+
// Only report for project files
|
|
196
|
+
if (!this.isProjectFile(file))
|
|
197
|
+
continue;
|
|
198
|
+
const fileName = file.split('/').pop() || '';
|
|
199
|
+
const isBaseFile = ['index.ts', 'index.js', 'types.ts', 'logger.ts', 'config.ts', 'architect.ts', 'constants.ts', 'interfaces.ts', 'globals.ts'].includes(fileName) ||
|
|
200
|
+
fileName.endsWith('.interface.ts') || fileName.endsWith('.constants.ts') || fileName.endsWith('.type.ts') || fileName.endsWith('.model.ts') || fileName.endsWith('.enum.ts');
|
|
201
|
+
const isExcludedDir = file.includes('tests/') || file.includes('scripts/') || file.includes('adapters/') || file.includes('agent-generator/');
|
|
202
|
+
if (isBaseFile || isExcludedDir)
|
|
203
|
+
continue;
|
|
204
|
+
if (dependents.size >= threshold) {
|
|
205
|
+
patterns.push({
|
|
206
|
+
name: 'Shotgun Surgery',
|
|
207
|
+
severity: 'HIGH',
|
|
208
|
+
location: file,
|
|
209
|
+
description: `Changes to this file likely require modifications in ${dependents.size} other files`,
|
|
210
|
+
suggestion: 'Refactor to reduce coupling and consolidate related functionality into modules',
|
|
211
|
+
affectedFiles: Array.from(dependents).filter(f => this.isProjectFile(f)),
|
|
212
|
+
metrics: {
|
|
213
|
+
dependentFileCount: dependents.size,
|
|
214
|
+
},
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
return patterns;
|
|
219
|
+
}
|
|
220
|
+
countMethods(filePath) {
|
|
221
|
+
try {
|
|
222
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
223
|
+
const methodRegex = /(?:async\s+)?(?:function|public|private|protected|static)\s+\w+\s*\(/g;
|
|
224
|
+
const arrowMethodRegex = /(?:readonly\s+)?\w+\s*=\s*(?:async\s+)?\(/g;
|
|
225
|
+
const matches = content.match(methodRegex);
|
|
226
|
+
const arrowMatches = content.match(arrowMethodRegex);
|
|
227
|
+
return (matches ? matches.length : 0) + (arrowMatches ? arrowMatches.length : 0);
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
return 0;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
countInternalExports(filePath) {
|
|
234
|
+
try {
|
|
235
|
+
const content = readFileSync(filePath, 'utf-8');
|
|
236
|
+
const internalTypes = [
|
|
237
|
+
'_',
|
|
238
|
+
'Internal',
|
|
239
|
+
'Private',
|
|
240
|
+
'Impl',
|
|
241
|
+
'Detail',
|
|
242
|
+
];
|
|
243
|
+
let count = 0;
|
|
244
|
+
for (const type of internalTypes) {
|
|
245
|
+
const regex = new RegExp(`export\\s+\\w*${type}\\w*`, 'g');
|
|
246
|
+
const matches = content.match(regex);
|
|
247
|
+
count += matches ? matches.length : 0;
|
|
248
|
+
}
|
|
249
|
+
return count;
|
|
250
|
+
}
|
|
251
|
+
catch {
|
|
252
|
+
return 0;
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
walkFileTree(node, callback) {
|
|
256
|
+
callback(node);
|
|
257
|
+
if (node.children) {
|
|
258
|
+
for (const child of node.children) {
|
|
259
|
+
this.walkFileTree(child, callback);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
//# sourceMappingURL=anti-patterns.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"anti-patterns.js","sourceRoot":"","sources":["../../../src/core/anti-patterns.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Interface for Abstract Syntax Tree-based code parsers.
|
|
3
|
+
* Replaces regex-based static analysis to improve deterministic import resolution
|
|
4
|
+
* without compiling the project.
|
|
5
|
+
*/
|
|
6
|
+
export interface ASTParser {
|
|
7
|
+
/**
|
|
8
|
+
* Initializes the parser engine and loads required language parsers.
|
|
9
|
+
* Can throw an error if the native bindings fail.
|
|
10
|
+
*/
|
|
11
|
+
initialize(): Promise<void>;
|
|
12
|
+
/**
|
|
13
|
+
* Parses the file content and extracts the imported/required module paths.
|
|
14
|
+
*
|
|
15
|
+
* @param content Raw file string content
|
|
16
|
+
* @param filePath Absolute path to the file
|
|
17
|
+
* @returns List of internal dependencies (import paths)
|
|
18
|
+
*/
|
|
19
|
+
parseImports(content: string, filePath: string): string[];
|
|
20
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ast-parser.interface.js","sourceRoot":"","sources":["../../../../src/core/ast/ast-parser.interface.ts"],"names":[],"mappings":""}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare class PathResolver {
|
|
2
|
+
private projectRoot;
|
|
3
|
+
private tsconfigPaths;
|
|
4
|
+
private initialized;
|
|
5
|
+
constructor(projectRoot: string);
|
|
6
|
+
initialize(): void;
|
|
7
|
+
private loadTsConfig;
|
|
8
|
+
/**
|
|
9
|
+
* Resolve `importPath` baseando-se no dicionário de Aliases.
|
|
10
|
+
* Ex: "@/" mapeia para "src/"
|
|
11
|
+
*/
|
|
12
|
+
resolveAlias(importPath: string): string;
|
|
13
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
export class PathResolver {
|
|
4
|
+
projectRoot;
|
|
5
|
+
tsconfigPaths = {};
|
|
6
|
+
initialized = false;
|
|
7
|
+
constructor(projectRoot) {
|
|
8
|
+
this.projectRoot = projectRoot;
|
|
9
|
+
}
|
|
10
|
+
initialize() {
|
|
11
|
+
if (this.initialized)
|
|
12
|
+
return;
|
|
13
|
+
try {
|
|
14
|
+
this.loadTsConfig();
|
|
15
|
+
// Em futuruos iteratives, carregar pyproject.toml e go.mod aliases
|
|
16
|
+
this.initialized = true;
|
|
17
|
+
}
|
|
18
|
+
catch {
|
|
19
|
+
// Falhas na leitura de config não devem quebrar o parser
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
loadTsConfig() {
|
|
23
|
+
const tsconfigPath = path.join(this.projectRoot, 'tsconfig.json');
|
|
24
|
+
if (fs.existsSync(tsconfigPath)) {
|
|
25
|
+
const content = fs.readFileSync(tsconfigPath, 'utf8');
|
|
26
|
+
// Limpeza brutal de comentários JS/TS do JSON
|
|
27
|
+
const cleanContent = content.replace(new RegExp('//.*$', 'gm'), '').replace(new RegExp('/\\\\*[\\\\s\\\\S]*?\\\\*/', 'g'), '');
|
|
28
|
+
const parsed = JSON.parse(cleanContent);
|
|
29
|
+
if (parsed?.compilerOptions?.paths) {
|
|
30
|
+
this.tsconfigPaths = parsed.compilerOptions.paths;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Resolve `importPath` baseando-se no dicionário de Aliases.
|
|
36
|
+
* Ex: "@/" mapeia para "src/"
|
|
37
|
+
*/
|
|
38
|
+
resolveAlias(importPath) {
|
|
39
|
+
this.initialize();
|
|
40
|
+
for (const alias in this.tsconfigPaths) {
|
|
41
|
+
// Ex: alias = "@/components/*", targets = ["src/components/*"]
|
|
42
|
+
const cleanAlias = alias.replace('/*', '');
|
|
43
|
+
if (importPath.startsWith(cleanAlias)) {
|
|
44
|
+
const targets = this.tsconfigPaths[alias];
|
|
45
|
+
if (targets && targets.length > 0) {
|
|
46
|
+
const cleanTarget = targets[0].replace('/*', '');
|
|
47
|
+
return importPath.replace(cleanAlias, cleanTarget);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return importPath;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=path-resolver.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"path-resolver.js","sourceRoot":"","sources":["../../../../src/core/ast/path-resolver.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,IAAI,CAAC;AACpB,OAAO,IAAI,MAAM,MAAM,CAAC;AAExB,MAAM,OAAO,YAAY;IACf,WAAW,CAAS;IACpB,aAAa,GAA6B,EAAE,CAAC;IAC7C,WAAW,GAAG,KAAK,CAAC;IAE5B,YAAY,WAAmB;QAC7B,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;IACjC,CAAC;IAED,UAAU;QACR,IAAI,IAAI,CAAC,WAAW;YAAE,OAAO;QAC7B,IAAI,CAAC;YACH,IAAI,CAAC,YAAY,EAAE,CAAC;YACpB,mEAAmE;YACnE,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,yDAAyD;QAC3D,CAAC;IACH,CAAC;IAEO,YAAY;QAClB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;QAClE,IAAI,EAAE,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;YAChC,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;YAEtD,8CAA8C;YAC9C,MAAM,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,IAAI,MAAM,CAAC,4BAA4B,EAAE,GAAG,CAAC,EAAE,EAAE,CAAC,CAAC;YAC/H,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,CAAC;YAExC,IAAI,MAAM,EAAE,eAAe,EAAE,KAAK,EAAE,CAAC;gBACnC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,eAAe,CAAC,KAAK,CAAC;YACpD,CAAC;QACH,CAAC;IACH,CAAC;IAED;;;OAGG;IACH,YAAY,CAAC,UAAkB;QAC7B,IAAI,CAAC,UAAU,EAAE,CAAC;QAElB,KAAK,MAAM,KAAK,IAAI,IAAI,CAAC,aAAa,EAAE,CAAC;YACvC,+DAA+D;YAC/D,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;YAE3C,IAAI,UAAU,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;gBACtC,MAAM,OAAO,GAAG,IAAI,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC;gBAC1C,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAClC,MAAM,WAAW,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;oBACjD,OAAO,UAAU,CAAC,OAAO,CAAC,UAAU,EAAE,WAAW,CAAC,CAAC;gBACrD,CAAC;YACH,CAAC;QACH,CAAC;QAED,OAAO,UAAU,CAAC;IACpB,CAAC;CACF"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { ASTParser } from './ast-parser.interface.js';
|
|
2
|
+
export declare class TreeSitterParser implements ASTParser {
|
|
3
|
+
private parsers;
|
|
4
|
+
private queries;
|
|
5
|
+
private ParserClass;
|
|
6
|
+
private QueryClass;
|
|
7
|
+
initialize(): Promise<void>;
|
|
8
|
+
private initParser;
|
|
9
|
+
parseImports(content: string, filePath: string): string[];
|
|
10
|
+
}
|
|
@@ -0,0 +1,142 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
export class TreeSitterParser {
|
|
3
|
+
parsers = new Map();
|
|
4
|
+
queries = new Map();
|
|
5
|
+
// Store the classes dynamically to avoid static C++ addon evaluation leaks in Jest ESM VMs
|
|
6
|
+
ParserClass = null;
|
|
7
|
+
QueryClass = null;
|
|
8
|
+
async initialize() {
|
|
9
|
+
try {
|
|
10
|
+
// Defer loading the native C++ bindings until absolutely needed.
|
|
11
|
+
// This prevents "Cannot read properties of undefined (reading 'tree')"
|
|
12
|
+
// when Jest loads the file across multiple test suites concurrently.
|
|
13
|
+
const treeSitterCore = await import('tree-sitter');
|
|
14
|
+
this.ParserClass = treeSitterCore.default;
|
|
15
|
+
this.QueryClass = treeSitterCore.Query;
|
|
16
|
+
// Dynamic ESM imports to handle native bindings gracefully
|
|
17
|
+
const tsMod = await import('tree-sitter-typescript').catch(() => null);
|
|
18
|
+
const jsMod = await import('tree-sitter-javascript').catch(() => null);
|
|
19
|
+
const pyMod = await import('tree-sitter-python').catch(() => null);
|
|
20
|
+
const goMod = await import('tree-sitter-go').catch(() => null);
|
|
21
|
+
const javaMod = await import('tree-sitter-java').catch(() => null);
|
|
22
|
+
const rustMod = await import('tree-sitter-rust').catch(() => null);
|
|
23
|
+
if (tsMod) {
|
|
24
|
+
// Handle CJS vs ESM interop structures
|
|
25
|
+
const tsLang = tsMod.default?.typescript || tsMod.typescript || tsMod;
|
|
26
|
+
const tsxLang = tsMod.default?.tsx || tsMod.tsx;
|
|
27
|
+
this.initParser('.ts', tsLang);
|
|
28
|
+
this.initParser('.tsx', tsxLang);
|
|
29
|
+
}
|
|
30
|
+
if (jsMod) {
|
|
31
|
+
const jsLang = jsMod.default || jsMod;
|
|
32
|
+
this.initParser('.js', jsLang);
|
|
33
|
+
this.initParser('.jsx', jsLang);
|
|
34
|
+
}
|
|
35
|
+
if (pyMod) {
|
|
36
|
+
this.initParser('.py', pyMod.default || pyMod);
|
|
37
|
+
}
|
|
38
|
+
if (goMod) {
|
|
39
|
+
this.initParser('.go', goMod.default || goMod);
|
|
40
|
+
}
|
|
41
|
+
if (javaMod) {
|
|
42
|
+
this.initParser('.java', javaMod.default || javaMod);
|
|
43
|
+
}
|
|
44
|
+
if (rustMod) {
|
|
45
|
+
this.initParser('.rs', rustMod.default || rustMod);
|
|
46
|
+
}
|
|
47
|
+
if (this.parsers.size === 0) {
|
|
48
|
+
throw new Error('No Tree-Sitter grammars were successfully loaded.');
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
throw new Error(`AST Parsers failed to initialize: ${err.message}`);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
initParser(ext, languageOption) {
|
|
56
|
+
if (!languageOption || !this.ParserClass)
|
|
57
|
+
return;
|
|
58
|
+
try {
|
|
59
|
+
const parser = new this.ParserClass();
|
|
60
|
+
parser.setLanguage(languageOption);
|
|
61
|
+
this.parsers.set(ext, parser);
|
|
62
|
+
// Pre-compile queries for performance based on language
|
|
63
|
+
let queryStr = '';
|
|
64
|
+
if (ext === '.ts' || ext === '.tsx' || ext === '.js' || ext === '.jsx') {
|
|
65
|
+
// Matches "import X from 'path'", "import('path')", "require('path')", "export * from 'path'"
|
|
66
|
+
queryStr = `
|
|
67
|
+
(import_statement source: (string) @path)
|
|
68
|
+
(export_statement source: (string) @path)
|
|
69
|
+
(call_expression
|
|
70
|
+
function: [(identifier) (import)] @fn
|
|
71
|
+
arguments: (arguments (string) @path)
|
|
72
|
+
(#match? @fn "^(require|import)$")
|
|
73
|
+
)
|
|
74
|
+
`;
|
|
75
|
+
}
|
|
76
|
+
else if (ext === '.py') {
|
|
77
|
+
// python imports
|
|
78
|
+
queryStr = `
|
|
79
|
+
(import_from_statement module_name: (_) @module)
|
|
80
|
+
(import_statement name: (_) @module)
|
|
81
|
+
`;
|
|
82
|
+
}
|
|
83
|
+
else if (ext === '.go') {
|
|
84
|
+
queryStr = `
|
|
85
|
+
(import_spec path: (interpreted_string_literal) @path)
|
|
86
|
+
`;
|
|
87
|
+
}
|
|
88
|
+
else if (ext === '.java') {
|
|
89
|
+
queryStr = `
|
|
90
|
+
(import_declaration (scoped_identifier) @path)
|
|
91
|
+
`;
|
|
92
|
+
}
|
|
93
|
+
else if (ext === '.rs') {
|
|
94
|
+
queryStr = `
|
|
95
|
+
(use_declaration argument: (scoped_identifier) @path)
|
|
96
|
+
`;
|
|
97
|
+
}
|
|
98
|
+
if (queryStr) {
|
|
99
|
+
const query = new this.QueryClass(languageOption, queryStr);
|
|
100
|
+
this.queries.set(ext, query);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
catch (e) {
|
|
104
|
+
console.error(`[TreeSitter] Query compilation failed for ${ext}:`, e);
|
|
105
|
+
// Ignore parser failure for a specific extension silently, letting fallback take over
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
parseImports(content, filePath) {
|
|
109
|
+
const ext = path.extname(filePath);
|
|
110
|
+
const parser = this.parsers.get(ext);
|
|
111
|
+
const query = this.queries.get(ext);
|
|
112
|
+
if (!parser || !query) {
|
|
113
|
+
throw new Error(`Tree-Sitter parser not mapped/loaded for extension ${ext}`);
|
|
114
|
+
}
|
|
115
|
+
const tree = parser.parse(content);
|
|
116
|
+
const matches = query.matches(tree.rootNode);
|
|
117
|
+
const imports = [];
|
|
118
|
+
for (const match of matches) {
|
|
119
|
+
// Extract the captured module paths/names
|
|
120
|
+
for (const capture of match.captures) {
|
|
121
|
+
if (capture.name === 'path' || capture.name === 'module') {
|
|
122
|
+
// Remove quotes around literal strings (e.g., "'./module'" -> "./module")
|
|
123
|
+
let value = capture.node.text.replace(/['"]/g, '');
|
|
124
|
+
if (ext === '.py') {
|
|
125
|
+
value = value.split(' as ')[0].trim();
|
|
126
|
+
}
|
|
127
|
+
imports.push(value);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
// Anti-GC trick for V8 + node-tree-sitter:
|
|
132
|
+
// If the 'tree' object is not referenced after 'query.matches()', V8's aggressive GC
|
|
133
|
+
// might destroy the Tree before 'query.matches' fully executes its C++ bindings,
|
|
134
|
+
// resulting in "Cannot read properties of undefined (reading 'tree')" inside marshalNode.
|
|
135
|
+
// Calling tree.delete() explicitly fixes memory leaks AND keeps the reference alive.
|
|
136
|
+
if (typeof tree.delete === 'function') {
|
|
137
|
+
tree.delete();
|
|
138
|
+
}
|
|
139
|
+
return imports;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
//# sourceMappingURL=tree-sitter-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"tree-sitter-parser.js","sourceRoot":"","sources":["../../../../src/core/ast/tree-sitter-parser.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { ArchitectConfig } from './types/core.js';
|
|
2
|
+
/**
|
|
3
|
+
* Normalize ignore patterns to use proper glob syntax.
|
|
4
|
+
* Simple names like "node_modules" are expanded to cover nested directories:
|
|
5
|
+
* "node_modules" → ["node_modules", "node_modules/**", "** /node_modules", "** /node_modules/**"]
|
|
6
|
+
*/
|
|
7
|
+
export declare function normalizeIgnorePatterns(patterns: string[]): string[];
|
|
8
|
+
export declare class ConfigLoader {
|
|
9
|
+
static loadConfig(projectPath: string): ArchitectConfig;
|
|
10
|
+
private static mergeConfigs;
|
|
11
|
+
}
|