vibecodingmachine-core 2026.2.26-1739 → 2026.3.9-850
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/package.json +1 -1
- package/src/agents/AgentCheckDiscoveryService.js +180 -0
- package/src/agents/AgentCheckService.js +18 -261
- package/src/agents/AgentCheckStatisticsService.js +195 -0
- package/src/agents/EnvironmentConfigurationManager.js +31 -380
- package/src/agents/InstallationType.js +19 -6
- package/src/agents/SimpleAgentCheckService.js +472 -0
- package/src/agents/config-managers/ConfigUtils.js +72 -0
- package/src/agents/config-managers/DefaultConfig.js +58 -0
- package/src/agents/config-managers/EnvVarLoader.js +66 -0
- package/src/agents/config-managers/FileConfigLoader.js +124 -0
- package/src/agents/config-managers/TypeConverters.js +61 -0
- package/src/agents/config-managers/VariableMappings.js +92 -0
- package/src/agents/discovery/AgentDiscoveryService-refactored.js +272 -0
- package/src/agents/discovery/AgentDiscoveryService.js +29 -403
- package/src/agents/discovery/agent-validator.js +262 -0
- package/src/agents/discovery/discovery-results.js +176 -0
- package/src/agents/discovery/discovery-scanner.js +268 -0
- package/src/agents/discovery/discovery-utils.js +161 -0
- package/src/agents/discovery/executable-analyzer.js +290 -0
- package/src/agents/discovery/history-manager.js +310 -0
- package/src/agents/verification/ResultAnalyzer-refactored.js +341 -0
- package/src/agents/verification/ResultAnalyzer.js +30 -431
- package/src/agents/verification/analysis-utils.js +310 -0
- package/src/agents/verification/batch-analyzer.js +440 -0
- package/src/agents/verification/pattern-recognizer.js +369 -0
- package/src/agents/verification/report-generator.js +320 -0
- package/src/agents/verification/test-analyzer.js +290 -0
- package/src/agents/windows/InstallerFactory.js +4 -0
- package/src/agents/windows/VSCodeExtensionInstaller.js +404 -0
- package/src/analysis/analysis-engine.js +314 -0
- package/src/analysis/ast-analyzer.js +342 -0
- package/src/analysis/boundary-detector-refactored.js +378 -0
- package/src/analysis/boundary-detector.js +200 -603
- package/src/analysis/boundary-scanner.js +609 -0
- package/src/analysis/boundary-types.js +118 -0
- package/src/analysis/boundary-utils.js +293 -0
- package/src/analysis/deadline-priority-calculator.js +18 -0
- package/src/analysis/detection-methods.js +347 -0
- package/src/analysis/importance-priority-calculator.js +18 -0
- package/src/analysis/priority/factor-calculators.js +204 -0
- package/src/analysis/priority/factor-helpers.js +71 -0
- package/src/analysis/priority/priority-constants.js +73 -0
- package/src/analysis/priority/priority-factor-calculators.js +301 -0
- package/src/analysis/priority/reasons-generator.js +44 -0
- package/src/analysis/priority-calculator.js +15 -580
- package/src/analysis/strategy-generator.js +16 -66
- package/src/analysis/type-priority-calculator.js +18 -0
- package/src/analysis/urgency-priority-calculator.js +18 -0
- package/src/auto-mode/AutoModeBusinessLogic.js +2 -40
- package/src/commands/disable-requirement.js +60 -0
- package/src/commands/disable-spec.js +60 -0
- package/src/commands/enable-requirement.js +60 -0
- package/src/commands/enable-spec.js +60 -0
- package/src/commands/registry.js +1 -6
- package/src/commands/requirements.js +8 -2
- package/src/ide-integration/applescript-manager.cjs +9 -24
- package/src/ide-integration/cdp-handlers/chat-reader.js +44 -0
- package/src/ide-integration/cdp-handlers/connection-handler.js +88 -0
- package/src/ide-integration/cdp-handlers/continuation-handler.js +314 -0
- package/src/ide-integration/cdp-handlers/message-submitter.js +75 -0
- package/src/ide-integration/cdp-handlers/text-sender.js +138 -0
- package/src/ide-integration/cdp-manager.js +28 -573
- package/src/ide-integration/claude-code-cli-manager.cjs +48 -12
- package/src/ide-integration/ide-openers/claude-opener.js +171 -0
- package/src/ide-integration/ide-openers/cursor-opener.js +53 -0
- package/src/ide-integration/ide-openers/other-ides-opener.js +230 -0
- package/src/ide-integration/ide-openers/vscode-opener.js +147 -0
- package/src/ide-integration/macos-ide-manager.js +20 -582
- package/src/ide-integration/macos-quota-checker.js +164 -0
- package/src/ide-integration/macos-text-sender.js +19 -38
- package/src/ide-integration/provider-manager.cjs +52 -7
- package/src/index.cjs +6 -0
- package/src/index.js +10 -0
- package/src/llm/direct-llm-manager.cjs +501 -0
- package/src/localization/translations/en-part1.js +363 -0
- package/src/localization/translations/en-part2.js +320 -0
- package/src/localization/translations/en.js +4 -687
- package/src/localization/translations/es-part1.js +363 -0
- package/src/localization/translations/es-part2.js +320 -0
- package/src/localization/translations/es.js +4 -688
- package/src/models/file-analysis-collection.js +139 -0
- package/src/models/file-analysis-metrics.js +50 -0
- package/src/models/file-analysis.js +15 -262
- package/src/models/plan-manager.js +410 -0
- package/src/models/refactoring-models.js +380 -0
- package/src/models/refactoring-plan-refactored.js +81 -0
- package/src/models/refactoring-plan.js +2 -663
- package/src/monitoring/alert-system.js +4 -45
- package/src/monitoring/continuous-scan-notifications.js +37 -191
- package/src/monitoring/notification-handlers/base-handler.js +58 -0
- package/src/monitoring/notification-handlers/error-handler.js +36 -0
- package/src/monitoring/notification-handlers/index.js +21 -0
- package/src/monitoring/notification-handlers/new-violation-handler.js +91 -0
- package/src/monitoring/notification-handlers/progress-handler.js +48 -0
- package/src/monitoring/notification-handlers/resolved-violation-handler.js +54 -0
- package/src/monitoring/notification-handlers/threshold-handler.js +36 -0
- package/src/provider-registry.js +8 -0
- package/src/refactoring/boundary/boundary-detector-refactored.js +58 -0
- package/src/refactoring/boundary/boundary-detector.js +26 -596
- package/src/refactoring/boundary/detectors/boundary-analyzers.js +281 -0
- package/src/refactoring/boundary/detectors/boundary-core.js +167 -0
- package/src/refactoring/boundary/detectors/class-detector.js +247 -0
- package/src/refactoring/boundary/detectors/config-detector.js +270 -0
- package/src/refactoring/boundary/detectors/constant-detector.js +269 -0
- package/src/refactoring/boundary/detectors/function-detector.js +248 -0
- package/src/refactoring/boundary/detectors/module-detector.js +249 -0
- package/src/refactoring/boundary/detectors/object-detector.js +247 -0
- package/src/refactoring/boundary/detectors/type-detectors.js +338 -0
- package/src/refactoring/boundary/detectors/utility-detector.js +270 -0
- package/src/refactoring/circular-dependency-resolver-original.js +16 -76
- package/src/refactoring/code-mover-refactored.js +309 -0
- package/src/refactoring/code-mover.js +48 -355
- package/src/refactoring/execution-status.js +18 -0
- package/src/refactoring/execution-strategies.js +172 -0
- package/src/refactoring/file-splitter-core.js +568 -0
- package/src/refactoring/file-splitter-types.js +136 -0
- package/src/refactoring/file-splitter.js +2 -682
- package/src/refactoring/functionality-validator.js +11 -51
- package/src/refactoring/import-manager-refactored.js +385 -0
- package/src/refactoring/import-manager.js +112 -487
- package/src/refactoring/import-models.js +189 -0
- package/src/refactoring/import-parser.js +306 -0
- package/src/refactoring/move-executor.js +431 -0
- package/src/refactoring/move-utils.js +368 -0
- package/src/refactoring/operation-executor.js +76 -0
- package/src/refactoring/plan-creator.js +36 -0
- package/src/refactoring/plan-executor.js +143 -0
- package/src/refactoring/plan-validator.js +68 -0
- package/src/refactoring/refactoring-executor-result.js +70 -0
- package/src/refactoring/refactoring-executor.js +34 -569
- package/src/refactoring/refactoring-operation.js +94 -0
- package/src/refactoring/refactoring-plan.js +69 -0
- package/src/refactoring/refactoring-rollback.js +22 -527
- package/src/refactoring/rollback-handlers/RollbackExecutor.js +107 -0
- package/src/refactoring/rollback-handlers/RollbackManager.js +265 -0
- package/src/refactoring/rollback-handlers/RollbackOperation.js +105 -0
- package/src/refactoring/rollback-handlers/RollbackResult.js +109 -0
- package/src/refactoring/rollback-handlers/RollbackStatistics.js +77 -0
- package/src/refactoring/test-validator.js +32 -448
- package/src/refactoring/validation/baseline-runner.js +71 -0
- package/src/refactoring/validation/report-generator.js +136 -0
- package/src/refactoring/validation/result-comparator.js +92 -0
- package/src/refactoring/validation/test-suite.js +59 -0
- package/src/refactoring/validation/test-validation-result.js +83 -0
- package/src/refactoring/validation/validation-runner.js +95 -0
- package/src/refactoring/validation/validation-status.js +18 -0
- package/src/rui/commands/AgentCommandParser.js +60 -369
- package/src/rui/commands/AgentResponseFormatter.js +7 -47
- package/src/rui/commands/parsers/CommandMapper.js +148 -0
- package/src/rui/commands/parsers/CommandValidator.js +228 -0
- package/src/rui/commands/parsers/ComponentExtractor.js +100 -0
- package/src/rui/commands/parsers/TokenParser.js +69 -0
- package/src/rui/commands/parsers/tokenizer.js +153 -0
- package/src/utils/current-requirement-operations.js +50 -1
- package/src/utils/report-generator.js +18 -514
- package/src/utils/report-generators/analysis-generator.js +115 -0
- package/src/utils/report-generators/base-generator.js +141 -0
- package/src/utils/report-generators/compliance-generator.js +41 -0
- package/src/utils/report-generators/format-handlers.js +185 -0
- package/src/utils/report-generators/refactoring-generator.js +46 -0
- package/src/utils/report-generators/validation-generator.js +63 -0
- package/src/utils/requirement-enable-disable.js +265 -0
- package/src/utils/requirement-helpers/requirement-file-ops.js +69 -1
- package/src/utils/requirement-helpers/requirement-mover.js +88 -1
- package/src/utils/requirement-helpers.js +5 -2
- package/src/utils/smoke-test-cli.js +45 -8
- package/src/utils/specification-enable-disable.js +122 -0
- package/src/utils/specification-helpers.js +30 -4
- package/src/utils/specification-migration.js +5 -5
- package/src/utils/test-comparator.js +118 -0
- package/src/utils/test-config.js +54 -0
- package/src/utils/test-executor.js +133 -0
- package/src/utils/test-parser.js +215 -0
- package/src/utils/test-runner-baseline.js +63 -0
- package/src/utils/test-runner-core.js +98 -0
- package/src/utils/test-runner-report.js +39 -0
- package/src/utils/test-runner-validation.js +71 -0
- package/src/utils/test-runner.js +11 -535
- package/src/validation/comparison-analyzer.js +333 -0
- package/src/validation/compliance-reporter-new.js +282 -0
- package/src/validation/compliance-reporter-refactored.js +344 -0
- package/src/validation/compliance-reporter.js +278 -591
- package/src/validation/compliance-utils.js +278 -0
- package/src/validation/html-generator.js +446 -0
- package/src/validation/metrics/category-calculator.js +137 -0
- package/src/validation/metrics/metrics-helpers.js +155 -0
- package/src/validation/metrics/overview-calculator.js +85 -0
- package/src/validation/metrics/overview-metrics.js +41 -0
- package/src/validation/metrics/quality-calculator.js +166 -0
- package/src/validation/metrics/size-calculator.js +69 -0
- package/src/validation/metrics-calculator.js +27 -551
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority factor calculation functions.
|
|
3
|
+
* Each function adds one factor to the PriorityResult.
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const { PRIORITY_FACTORS } = require('./priority-constants');
|
|
7
|
+
const { calculateComplexityScore, assessCouplingRisk, findTestFile } = require('./factor-helpers');
|
|
8
|
+
|
|
9
|
+
function calculateSizeViolationFactor(fileAnalysis, result, weights, config) {
|
|
10
|
+
const limits = config.limits;
|
|
11
|
+
let score = 0;
|
|
12
|
+
const details = {};
|
|
13
|
+
if (fileAnalysis.lineCount > limits.criticalThreshold) {
|
|
14
|
+
score = 1.0;
|
|
15
|
+
details.violation = 'critical';
|
|
16
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
17
|
+
details.severity = 'critical';
|
|
18
|
+
} else if (fileAnalysis.lineCount > limits.maxFileSize) {
|
|
19
|
+
score = 0.8;
|
|
20
|
+
details.violation = 'major';
|
|
21
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
22
|
+
details.severity = 'major';
|
|
23
|
+
} else if (fileAnalysis.lineCount > limits.warningThreshold) {
|
|
24
|
+
score = 0.6;
|
|
25
|
+
details.violation = 'minor';
|
|
26
|
+
details.excessLines = fileAnalysis.lineCount - limits.warningThreshold;
|
|
27
|
+
details.severity = 'minor';
|
|
28
|
+
} else if (fileAnalysis.lineCount > limits.mediumFileMax) {
|
|
29
|
+
score = 0.3;
|
|
30
|
+
details.violation = 'approaching';
|
|
31
|
+
details.excessLines = 0;
|
|
32
|
+
details.severity = 'low';
|
|
33
|
+
} else {
|
|
34
|
+
details.violation = 'none';
|
|
35
|
+
details.excessLines = 0;
|
|
36
|
+
details.severity = 'none';
|
|
37
|
+
}
|
|
38
|
+
details.lineCount = fileAnalysis.lineCount;
|
|
39
|
+
details.limit = limits.maxFileSize;
|
|
40
|
+
details.warningThreshold = limits.warningThreshold;
|
|
41
|
+
result.addFactor(PRIORITY_FACTORS.SIZE_VIOLATION, score, weights[PRIORITY_FACTORS.SIZE_VIOLATION], details);
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function calculateComplexityFactor(fileAnalysis, result, weights, _config) {
|
|
45
|
+
const complexityScore = fileAnalysis.getComplexityScore
|
|
46
|
+
? fileAnalysis.getComplexityScore()
|
|
47
|
+
: calculateComplexityScore(fileAnalysis);
|
|
48
|
+
let score = 0;
|
|
49
|
+
let level = 'very_low';
|
|
50
|
+
if (complexityScore >= 80) {
|
|
51
|
+
score = 1.0;
|
|
52
|
+
level = 'very_high';
|
|
53
|
+
} else if (complexityScore >= 60) {
|
|
54
|
+
score = 0.8;
|
|
55
|
+
level = 'high';
|
|
56
|
+
} else if (complexityScore >= 40) {
|
|
57
|
+
score = 0.6;
|
|
58
|
+
level = 'medium';
|
|
59
|
+
} else if (complexityScore >= 20) {
|
|
60
|
+
score = 0.3;
|
|
61
|
+
level = 'low';
|
|
62
|
+
}
|
|
63
|
+
const details = {
|
|
64
|
+
complexityScore,
|
|
65
|
+
cyclomaticComplexity: fileAnalysis.cyclomaticComplexity || 0,
|
|
66
|
+
nestingDepth: fileAnalysis.nestingDepth || 0,
|
|
67
|
+
functionCount: fileAnalysis.functionCount || 0,
|
|
68
|
+
classCount: fileAnalysis.classCount || 0,
|
|
69
|
+
level
|
|
70
|
+
};
|
|
71
|
+
result.addFactor(PRIORITY_FACTORS.COMPLEXITY, score, weights[PRIORITY_FACTORS.COMPLEXITY], details);
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
function calculateDependencyFactor(fileAnalysis, result, weights, _config) {
|
|
75
|
+
const dependencyCount = fileAnalysis.dependencyCount || fileAnalysis.imports?.length || 0;
|
|
76
|
+
const dependentCount = fileAnalysis.dependents?.length || 0;
|
|
77
|
+
const totalDependencies = dependencyCount + dependentCount;
|
|
78
|
+
let score = 0;
|
|
79
|
+
let level = 'very_low';
|
|
80
|
+
if (totalDependencies > 20) {
|
|
81
|
+
score = 1.0;
|
|
82
|
+
level = 'very_high';
|
|
83
|
+
} else if (totalDependencies > 15) {
|
|
84
|
+
score = 0.8;
|
|
85
|
+
level = 'high';
|
|
86
|
+
} else if (totalDependencies > 10) {
|
|
87
|
+
score = 0.6;
|
|
88
|
+
level = 'medium';
|
|
89
|
+
} else if (totalDependencies > 5) {
|
|
90
|
+
score = 0.3;
|
|
91
|
+
level = 'low';
|
|
92
|
+
}
|
|
93
|
+
const details = {
|
|
94
|
+
dependencyCount,
|
|
95
|
+
dependentCount,
|
|
96
|
+
totalDependencies,
|
|
97
|
+
couplingRisk: assessCouplingRisk(totalDependencies),
|
|
98
|
+
level
|
|
99
|
+
};
|
|
100
|
+
result.addFactor(PRIORITY_FACTORS.DEPENDENCY_COUNT, score, weights[PRIORITY_FACTORS.DEPENDENCY_COUNT], details);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function calculatePackageImportanceFactor(fileAnalysis, result, weights, _config) {
|
|
104
|
+
const packageName = fileAnalysis.package || 'root';
|
|
105
|
+
const packageImportance = {
|
|
106
|
+
core: 1.0, cli: 0.8, 'electron-app': 0.7, web: 0.6, 'api-server': 0.6,
|
|
107
|
+
'chrome-extension': 0.5, mobile: 0.5, 'vscode-extension': 0.4, admin: 0.3, root: 0.2
|
|
108
|
+
};
|
|
109
|
+
const score = packageImportance[packageName] || 0.2;
|
|
110
|
+
const details = {
|
|
111
|
+
packageName,
|
|
112
|
+
importance: score >= 0.8 ? 'critical' : score >= 0.6 ? 'high' : score >= 0.4 ? 'medium' : 'low',
|
|
113
|
+
isCorePackage: packageName === 'core'
|
|
114
|
+
};
|
|
115
|
+
result.addFactor(PRIORITY_FACTORS.PACKAGE_IMPORTANCE, score, weights[PRIORITY_FACTORS.PACKAGE_IMPORTANCE], details);
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
function calculateChangeFrequencyFactor(fileAnalysis, result, weights, _config) {
|
|
119
|
+
const filePath = fileAnalysis.filePath;
|
|
120
|
+
const highFrequencyPatterns = [/config\//, /\/bin\//, /\/src\/main\//, /package\.json$/, /README\.md$/, /\.config\./];
|
|
121
|
+
const mediumFrequencyPatterns = [/\/src\/utils\//, /\/src\/helpers\//, /\/src\/services\//];
|
|
122
|
+
let score = 0.2;
|
|
123
|
+
let frequency = 'low';
|
|
124
|
+
if (highFrequencyPatterns.some(p => p.test(filePath))) {
|
|
125
|
+
score = 0.8;
|
|
126
|
+
frequency = 'high';
|
|
127
|
+
} else if (mediumFrequencyPatterns.some(p => p.test(filePath))) {
|
|
128
|
+
score = 0.5;
|
|
129
|
+
frequency = 'medium';
|
|
130
|
+
}
|
|
131
|
+
const details = { filePath, lastModified: fileAnalysis.lastModified, frequency };
|
|
132
|
+
if (fileAnalysis.lastModified) {
|
|
133
|
+
const daysSinceModified = (Date.now() - new Date(fileAnalysis.lastModified)) / (1000 * 60 * 60 * 24);
|
|
134
|
+
if (daysSinceModified < 7) {
|
|
135
|
+
score = Math.min(1.0, score + 0.2);
|
|
136
|
+
details.recentlyModified = true;
|
|
137
|
+
} else if (daysSinceModified < 30) {
|
|
138
|
+
score = Math.min(1.0, score + 0.1);
|
|
139
|
+
details.recentlyModified = false;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
result.addFactor(PRIORITY_FACTORS.CHANGE_FREQUENCY, score, weights[PRIORITY_FACTORS.CHANGE_FREQUENCY], details);
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
function calculateTestCoverageFactor(fileAnalysis, result, weights, _config) {
|
|
146
|
+
const filePath = fileAnalysis.filePath;
|
|
147
|
+
const isTestFile = fileAnalysis.isTestFile || /test|spec/.test(filePath);
|
|
148
|
+
let score = 0;
|
|
149
|
+
const details = { filePath, isTestFile };
|
|
150
|
+
if (isTestFile) {
|
|
151
|
+
details.coverage = 'test_file';
|
|
152
|
+
} else {
|
|
153
|
+
const testFile = findTestFile(filePath);
|
|
154
|
+
if (testFile) {
|
|
155
|
+
score = 0.2;
|
|
156
|
+
details.coverage = 'good';
|
|
157
|
+
details.testFile = testFile;
|
|
158
|
+
} else {
|
|
159
|
+
score = 0.6;
|
|
160
|
+
details.coverage = 'poor';
|
|
161
|
+
details.testFile = null;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
details.impact = score > 0.4 ? 'high_risk' : 'low_risk';
|
|
165
|
+
result.addFactor(PRIORITY_FACTORS.TEST_COVERAGE, score, weights[PRIORITY_FACTORS.TEST_COVERAGE], details);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
function calculateBusinessImpactFactor(fileAnalysis, result, weights, _config) {
|
|
169
|
+
const filePath = fileAnalysis.filePath;
|
|
170
|
+
const criticalPatterns = [/\/bin\//, /\/src\/main\//, /\/src\/app\//, /\/src\/index\./, /\/server\./, /\/app\./];
|
|
171
|
+
const importantPatterns = [/\/src\/api\//, /\/src\/controllers\//, /\/src\/services\//, /\/src\/models\//];
|
|
172
|
+
let score = 0.2;
|
|
173
|
+
let impact = 'standard';
|
|
174
|
+
if (criticalPatterns.some(p => p.test(filePath))) {
|
|
175
|
+
score = 0.8;
|
|
176
|
+
impact = 'critical';
|
|
177
|
+
} else if (importantPatterns.some(p => p.test(filePath))) {
|
|
178
|
+
score = 0.5;
|
|
179
|
+
impact = 'important';
|
|
180
|
+
}
|
|
181
|
+
const details = { filePath, impact, isBusinessCritical: score >= 0.8 };
|
|
182
|
+
result.addFactor(PRIORITY_FACTORS.BUSINESS_IMPACT, score, weights[PRIORITY_FACTORS.BUSINESS_IMPACT], details);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function runAllFactors(fileAnalysis, result, weights, config) {
|
|
186
|
+
calculateSizeViolationFactor(fileAnalysis, result, weights, config);
|
|
187
|
+
calculateComplexityFactor(fileAnalysis, result, weights, config);
|
|
188
|
+
calculateDependencyFactor(fileAnalysis, result, weights, config);
|
|
189
|
+
calculatePackageImportanceFactor(fileAnalysis, result, weights, config);
|
|
190
|
+
calculateChangeFrequencyFactor(fileAnalysis, result, weights, config);
|
|
191
|
+
calculateTestCoverageFactor(fileAnalysis, result, weights, config);
|
|
192
|
+
calculateBusinessImpactFactor(fileAnalysis, result, weights, config);
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
module.exports = {
|
|
196
|
+
runAllFactors,
|
|
197
|
+
calculateSizeViolationFactor,
|
|
198
|
+
calculateComplexityFactor,
|
|
199
|
+
calculateDependencyFactor,
|
|
200
|
+
calculatePackageImportanceFactor,
|
|
201
|
+
calculateChangeFrequencyFactor,
|
|
202
|
+
calculateTestCoverageFactor,
|
|
203
|
+
calculateBusinessImpactFactor
|
|
204
|
+
};
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Helper functions used by priority factor calculators.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Calculate complexity score for a file (0-100)
|
|
10
|
+
*/
|
|
11
|
+
function calculateComplexityScore(fileAnalysis) {
|
|
12
|
+
let score = 0;
|
|
13
|
+
if (fileAnalysis.lineCount > 1000) score += 30;
|
|
14
|
+
else if (fileAnalysis.lineCount > 555) score += 25;
|
|
15
|
+
else if (fileAnalysis.lineCount > 300) score += 15;
|
|
16
|
+
else if (fileAnalysis.lineCount > 100) score += 5;
|
|
17
|
+
const functionCount = fileAnalysis.functionCount || 0;
|
|
18
|
+
if (functionCount > 20) score += 20;
|
|
19
|
+
else if (functionCount > 10) score += 15;
|
|
20
|
+
else if (functionCount > 5) score += 10;
|
|
21
|
+
else if (functionCount > 2) score += 5;
|
|
22
|
+
const classCount = fileAnalysis.classCount || 0;
|
|
23
|
+
if (classCount > 5) score += 15;
|
|
24
|
+
else if (classCount > 3) score += 10;
|
|
25
|
+
else if (classCount > 1) score += 5;
|
|
26
|
+
const nestingDepth = fileAnalysis.nestingDepth || 0;
|
|
27
|
+
if (nestingDepth > 8) score += 15;
|
|
28
|
+
else if (nestingDepth > 5) score += 10;
|
|
29
|
+
else if (nestingDepth > 3) score += 5;
|
|
30
|
+
const dependencyCount = fileAnalysis.dependencyCount || 0;
|
|
31
|
+
if (dependencyCount > 20) score += 20;
|
|
32
|
+
else if (dependencyCount > 10) score += 15;
|
|
33
|
+
else if (dependencyCount > 5) score += 10;
|
|
34
|
+
else if (dependencyCount > 2) score += 5;
|
|
35
|
+
return Math.min(score, 100);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
function assessCouplingRisk(dependencyCount) {
|
|
39
|
+
if (dependencyCount > 20) return 'very_high';
|
|
40
|
+
if (dependencyCount > 15) return 'high';
|
|
41
|
+
if (dependencyCount > 10) return 'medium';
|
|
42
|
+
if (dependencyCount > 5) return 'low';
|
|
43
|
+
return 'very_low';
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
function findTestFile(filePath) {
|
|
47
|
+
const dir = path.dirname(filePath);
|
|
48
|
+
const basename = path.basename(filePath, path.extname(filePath));
|
|
49
|
+
const testPatterns = [
|
|
50
|
+
path.join(dir, `${basename}.test.js`),
|
|
51
|
+
path.join(dir, `${basename}.spec.js`),
|
|
52
|
+
path.join(dir, `${basename}.test.ts`),
|
|
53
|
+
path.join(dir, `${basename}.spec.ts`),
|
|
54
|
+
path.join(dir, '__tests__', `${basename}.js`),
|
|
55
|
+
path.join(dir, '__tests__', `${basename}.ts`),
|
|
56
|
+
path.join(dir, 'test', `${basename}.js`),
|
|
57
|
+
path.join(dir, 'test', `${basename}.ts`),
|
|
58
|
+
path.join(dir, 'tests', `${basename}.js`),
|
|
59
|
+
path.join(dir, 'tests', `${basename}.ts`)
|
|
60
|
+
];
|
|
61
|
+
for (const testPath of testPatterns) {
|
|
62
|
+
if (fs.existsSync(testPath)) return testPath;
|
|
63
|
+
}
|
|
64
|
+
return null;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
module.exports = {
|
|
68
|
+
calculateComplexityScore,
|
|
69
|
+
assessCouplingRisk,
|
|
70
|
+
findTestFile
|
|
71
|
+
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority constants and result model for refactoring priority calculation.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const PRIORITY_LEVELS = {
|
|
6
|
+
CRITICAL: 'critical',
|
|
7
|
+
HIGH: 'high',
|
|
8
|
+
MEDIUM: 'medium',
|
|
9
|
+
LOW: 'low',
|
|
10
|
+
NONE: 'none'
|
|
11
|
+
};
|
|
12
|
+
|
|
13
|
+
const PRIORITY_FACTORS = {
|
|
14
|
+
SIZE_VIOLATION: 'size_violation',
|
|
15
|
+
COMPLEXITY: 'complexity',
|
|
16
|
+
DEPENDENCY_COUNT: 'dependency_count',
|
|
17
|
+
CHANGE_FREQUENCY: 'change_frequency',
|
|
18
|
+
PACKAGE_IMPORTANCE: 'package_importance',
|
|
19
|
+
TEST_COVERAGE: 'test_coverage',
|
|
20
|
+
BUSINESS_IMPACT: 'business_impact'
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
class PriorityResult {
|
|
24
|
+
constructor(filePath) {
|
|
25
|
+
this.filePath = filePath;
|
|
26
|
+
this.priority = PRIORITY_LEVELS.NONE;
|
|
27
|
+
this.score = 0;
|
|
28
|
+
this.factors = {};
|
|
29
|
+
this.reasons = [];
|
|
30
|
+
this.recommendations = [];
|
|
31
|
+
this.metadata = {
|
|
32
|
+
calculatedAt: new Date().toISOString(),
|
|
33
|
+
version: '1.0.0'
|
|
34
|
+
};
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
addFactor(factorName, score, weight, details = {}) {
|
|
38
|
+
this.factors[factorName] = {
|
|
39
|
+
score,
|
|
40
|
+
weight,
|
|
41
|
+
weightedScore: score * weight,
|
|
42
|
+
details
|
|
43
|
+
};
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
addReason(reason) {
|
|
47
|
+
this.reasons.push(reason);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
addRecommendation(recommendation) {
|
|
51
|
+
this.recommendations.push(recommendation);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
setPriority(priority, score) {
|
|
55
|
+
this.priority = priority;
|
|
56
|
+
this.score = score;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
getFactorScore(factorName) {
|
|
60
|
+
return this.factors[factorName]?.weightedScore || 0;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
getTotalWeightedScore() {
|
|
64
|
+
return Object.values(this.factors)
|
|
65
|
+
.reduce((sum, factor) => sum + factor.weightedScore, 0);
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
module.exports = {
|
|
70
|
+
PRIORITY_LEVELS,
|
|
71
|
+
PRIORITY_FACTORS,
|
|
72
|
+
PriorityResult
|
|
73
|
+
};
|
|
@@ -0,0 +1,301 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Priority factor calculation functions for refactoring priority.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const fs = require('fs');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const { PRIORITY_FACTORS } = require('./priority-constants');
|
|
8
|
+
|
|
9
|
+
function calculateComplexityScore(fileAnalysis) {
|
|
10
|
+
let score = 0;
|
|
11
|
+
if (fileAnalysis.lineCount > 1000) score += 30;
|
|
12
|
+
else if (fileAnalysis.lineCount > 555) score += 25;
|
|
13
|
+
else if (fileAnalysis.lineCount > 300) score += 15;
|
|
14
|
+
else if (fileAnalysis.lineCount > 100) score += 5;
|
|
15
|
+
const functionCount = fileAnalysis.functionCount || 0;
|
|
16
|
+
if (functionCount > 20) score += 20;
|
|
17
|
+
else if (functionCount > 10) score += 15;
|
|
18
|
+
else if (functionCount > 5) score += 10;
|
|
19
|
+
else if (functionCount > 2) score += 5;
|
|
20
|
+
const classCount = fileAnalysis.classCount || 0;
|
|
21
|
+
if (classCount > 5) score += 15;
|
|
22
|
+
else if (classCount > 3) score += 10;
|
|
23
|
+
else if (classCount > 1) score += 5;
|
|
24
|
+
const nestingDepth = fileAnalysis.nestingDepth || 0;
|
|
25
|
+
if (nestingDepth > 8) score += 15;
|
|
26
|
+
else if (nestingDepth > 5) score += 10;
|
|
27
|
+
else if (nestingDepth > 3) score += 5;
|
|
28
|
+
const dependencyCount = fileAnalysis.dependencyCount || 0;
|
|
29
|
+
if (dependencyCount > 20) score += 20;
|
|
30
|
+
else if (dependencyCount > 10) score += 15;
|
|
31
|
+
else if (dependencyCount > 5) score += 10;
|
|
32
|
+
else if (dependencyCount > 2) score += 5;
|
|
33
|
+
return Math.min(score, 100);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function assessCouplingRisk(dependencyCount) {
|
|
37
|
+
if (dependencyCount > 20) return 'very_high';
|
|
38
|
+
if (dependencyCount > 15) return 'high';
|
|
39
|
+
if (dependencyCount > 10) return 'medium';
|
|
40
|
+
if (dependencyCount > 5) return 'low';
|
|
41
|
+
return 'very_low';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function findTestFile(filePath) {
|
|
45
|
+
const dir = path.dirname(filePath);
|
|
46
|
+
const basename = path.basename(filePath, path.extname(filePath));
|
|
47
|
+
const testPatterns = [
|
|
48
|
+
path.join(dir, `${basename}.test.js`),
|
|
49
|
+
path.join(dir, `${basename}.spec.js`),
|
|
50
|
+
path.join(dir, `${basename}.test.ts`),
|
|
51
|
+
path.join(dir, `${basename}.spec.ts`),
|
|
52
|
+
path.join(dir, '__tests__', `${basename}.js`),
|
|
53
|
+
path.join(dir, '__tests__', `${basename}.ts`),
|
|
54
|
+
path.join(dir, 'test', `${basename}.js`),
|
|
55
|
+
path.join(dir, 'test', `${basename}.ts`),
|
|
56
|
+
path.join(dir, 'tests', `${basename}.js`),
|
|
57
|
+
path.join(dir, 'tests', `${basename}.ts`)
|
|
58
|
+
];
|
|
59
|
+
for (const testPath of testPatterns) {
|
|
60
|
+
if (fs.existsSync(testPath)) return testPath;
|
|
61
|
+
}
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
function calculateSizeViolationFactor(fileAnalysis, result, weights, config) {
|
|
66
|
+
const limits = config.limits;
|
|
67
|
+
let score = 0;
|
|
68
|
+
const details = {};
|
|
69
|
+
if (fileAnalysis.lineCount > limits.criticalThreshold) {
|
|
70
|
+
score = 1.0;
|
|
71
|
+
details.violation = 'critical';
|
|
72
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
73
|
+
details.severity = 'critical';
|
|
74
|
+
} else if (fileAnalysis.lineCount > limits.maxFileSize) {
|
|
75
|
+
score = 0.8;
|
|
76
|
+
details.violation = 'major';
|
|
77
|
+
details.excessLines = fileAnalysis.lineCount - limits.maxFileSize;
|
|
78
|
+
details.severity = 'major';
|
|
79
|
+
} else if (fileAnalysis.lineCount > limits.warningThreshold) {
|
|
80
|
+
score = 0.6;
|
|
81
|
+
details.violation = 'minor';
|
|
82
|
+
details.excessLines = fileAnalysis.lineCount - limits.warningThreshold;
|
|
83
|
+
details.severity = 'minor';
|
|
84
|
+
} else if (fileAnalysis.lineCount > limits.mediumFileMax) {
|
|
85
|
+
score = 0.3;
|
|
86
|
+
details.violation = 'approaching';
|
|
87
|
+
details.excessLines = 0;
|
|
88
|
+
details.severity = 'low';
|
|
89
|
+
} else {
|
|
90
|
+
score = 0.0;
|
|
91
|
+
details.violation = 'none';
|
|
92
|
+
details.excessLines = 0;
|
|
93
|
+
details.severity = 'none';
|
|
94
|
+
}
|
|
95
|
+
details.lineCount = fileAnalysis.lineCount;
|
|
96
|
+
details.limit = limits.maxFileSize;
|
|
97
|
+
details.warningThreshold = limits.warningThreshold;
|
|
98
|
+
result.addFactor(PRIORITY_FACTORS.SIZE_VIOLATION, score, weights[PRIORITY_FACTORS.SIZE_VIOLATION], details);
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function calculateComplexityFactor(fileAnalysis, result, weights, calculateComplexityScoreFn) {
|
|
102
|
+
const complexityScore = fileAnalysis.getComplexityScore
|
|
103
|
+
? fileAnalysis.getComplexityScore()
|
|
104
|
+
: calculateComplexityScoreFn(fileAnalysis);
|
|
105
|
+
let score = 0;
|
|
106
|
+
const details = {};
|
|
107
|
+
if (complexityScore >= 80) {
|
|
108
|
+
score = 1.0;
|
|
109
|
+
details.level = 'very_high';
|
|
110
|
+
} else if (complexityScore >= 60) {
|
|
111
|
+
score = 0.8;
|
|
112
|
+
details.level = 'high';
|
|
113
|
+
} else if (complexityScore >= 40) {
|
|
114
|
+
score = 0.6;
|
|
115
|
+
details.level = 'medium';
|
|
116
|
+
} else if (complexityScore >= 20) {
|
|
117
|
+
score = 0.3;
|
|
118
|
+
details.level = 'low';
|
|
119
|
+
} else {
|
|
120
|
+
score = 0.0;
|
|
121
|
+
details.level = 'very_low';
|
|
122
|
+
}
|
|
123
|
+
details.complexityScore = complexityScore;
|
|
124
|
+
details.cyclomaticComplexity = fileAnalysis.cyclomaticComplexity || 0;
|
|
125
|
+
details.nestingDepth = fileAnalysis.nestingDepth || 0;
|
|
126
|
+
details.functionCount = fileAnalysis.functionCount || 0;
|
|
127
|
+
details.classCount = fileAnalysis.classCount || 0;
|
|
128
|
+
result.addFactor(PRIORITY_FACTORS.COMPLEXITY, score, weights[PRIORITY_FACTORS.COMPLEXITY], details);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function calculateDependencyFactor(fileAnalysis, result, weights, assessCouplingRiskFn) {
|
|
132
|
+
const dependencyCount = fileAnalysis.dependencyCount || fileAnalysis.imports?.length || 0;
|
|
133
|
+
const dependentCount = fileAnalysis.dependents?.length || 0;
|
|
134
|
+
const totalDependencies = dependencyCount + dependentCount;
|
|
135
|
+
let score = 0;
|
|
136
|
+
const details = {};
|
|
137
|
+
if (totalDependencies > 20) {
|
|
138
|
+
score = 1.0;
|
|
139
|
+
details.level = 'very_high';
|
|
140
|
+
} else if (totalDependencies > 15) {
|
|
141
|
+
score = 0.8;
|
|
142
|
+
details.level = 'high';
|
|
143
|
+
} else if (totalDependencies > 10) {
|
|
144
|
+
score = 0.6;
|
|
145
|
+
details.level = 'medium';
|
|
146
|
+
} else if (totalDependencies > 5) {
|
|
147
|
+
score = 0.3;
|
|
148
|
+
details.level = 'low';
|
|
149
|
+
} else {
|
|
150
|
+
score = 0.0;
|
|
151
|
+
details.level = 'very_low';
|
|
152
|
+
}
|
|
153
|
+
details.dependencyCount = dependencyCount;
|
|
154
|
+
details.dependentCount = dependentCount;
|
|
155
|
+
details.totalDependencies = totalDependencies;
|
|
156
|
+
details.couplingRisk = assessCouplingRiskFn(totalDependencies);
|
|
157
|
+
result.addFactor(PRIORITY_FACTORS.DEPENDENCY_COUNT, score, weights[PRIORITY_FACTORS.DEPENDENCY_COUNT], details);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
function calculatePackageImportanceFactor(fileAnalysis, result, weights) {
|
|
161
|
+
const packageName = fileAnalysis.package || 'root';
|
|
162
|
+
const packageImportance = {
|
|
163
|
+
core: 1.0,
|
|
164
|
+
cli: 0.8,
|
|
165
|
+
'electron-app': 0.7,
|
|
166
|
+
web: 0.6,
|
|
167
|
+
'api-server': 0.6,
|
|
168
|
+
'chrome-extension': 0.5,
|
|
169
|
+
mobile: 0.5,
|
|
170
|
+
'vscode-extension': 0.4,
|
|
171
|
+
admin: 0.3,
|
|
172
|
+
root: 0.2
|
|
173
|
+
};
|
|
174
|
+
const score = packageImportance[packageName] || 0.2;
|
|
175
|
+
const details = {
|
|
176
|
+
packageName,
|
|
177
|
+
importance: score >= 0.8 ? 'critical' : score >= 0.6 ? 'high' : score >= 0.4 ? 'medium' : 'low',
|
|
178
|
+
isCorePackage: packageName === 'core'
|
|
179
|
+
};
|
|
180
|
+
result.addFactor(PRIORITY_FACTORS.PACKAGE_IMPORTANCE, score, weights[PRIORITY_FACTORS.PACKAGE_IMPORTANCE], details);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
function calculateChangeFrequencyFactor(fileAnalysis, result, weights) {
|
|
184
|
+
const filePath = fileAnalysis.filePath;
|
|
185
|
+
const highFrequencyPatterns = [/config\//, /\/bin\//, /\/src\/main\//, /package\.json$/, /README\.md$/, /\.config\./];
|
|
186
|
+
const mediumFrequencyPatterns = [/\/src\/utils\//, /\/src\/helpers\//, /\/src\/services\//];
|
|
187
|
+
let score = 0.2;
|
|
188
|
+
const details = { filePath, lastModified: fileAnalysis.lastModified };
|
|
189
|
+
if (highFrequencyPatterns.some(p => p.test(filePath))) {
|
|
190
|
+
score = 0.8;
|
|
191
|
+
details.frequency = 'high';
|
|
192
|
+
} else if (mediumFrequencyPatterns.some(p => p.test(filePath))) {
|
|
193
|
+
score = 0.5;
|
|
194
|
+
details.frequency = 'medium';
|
|
195
|
+
} else {
|
|
196
|
+
details.frequency = 'low';
|
|
197
|
+
}
|
|
198
|
+
if (fileAnalysis.lastModified) {
|
|
199
|
+
const daysSinceModified = (Date.now() - new Date(fileAnalysis.lastModified)) / (1000 * 60 * 60 * 24);
|
|
200
|
+
if (daysSinceModified < 7) {
|
|
201
|
+
score = Math.min(1.0, score + 0.2);
|
|
202
|
+
details.recentlyModified = true;
|
|
203
|
+
} else if (daysSinceModified < 30) {
|
|
204
|
+
score = Math.min(1.0, score + 0.1);
|
|
205
|
+
details.recentlyModified = false;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
result.addFactor(PRIORITY_FACTORS.CHANGE_FREQUENCY, score, weights[PRIORITY_FACTORS.CHANGE_FREQUENCY], details);
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
function calculateTestCoverageFactor(fileAnalysis, result, weights, findTestFileFn) {
|
|
212
|
+
const filePath = fileAnalysis.filePath;
|
|
213
|
+
const isTestFile = fileAnalysis.isTestFile || /test|spec/.test(filePath);
|
|
214
|
+
let score = 0;
|
|
215
|
+
const details = { filePath, isTestFile };
|
|
216
|
+
if (isTestFile) {
|
|
217
|
+
score = 0.0;
|
|
218
|
+
details.coverage = 'test_file';
|
|
219
|
+
} else {
|
|
220
|
+
const testFile = findTestFileFn(filePath);
|
|
221
|
+
if (testFile) {
|
|
222
|
+
score = 0.2;
|
|
223
|
+
details.coverage = 'good';
|
|
224
|
+
details.testFile = testFile;
|
|
225
|
+
} else {
|
|
226
|
+
score = 0.6;
|
|
227
|
+
details.coverage = 'poor';
|
|
228
|
+
details.testFile = null;
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
details.impact = score > 0.4 ? 'high_risk' : 'low_risk';
|
|
232
|
+
result.addFactor(PRIORITY_FACTORS.TEST_COVERAGE, score, weights[PRIORITY_FACTORS.TEST_COVERAGE], details);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
function calculateBusinessImpactFactor(fileAnalysis, result, weights) {
|
|
236
|
+
const filePath = fileAnalysis.filePath;
|
|
237
|
+
const criticalPatterns = [/\/bin\//, /\/src\/main\//, /\/src\/app\//, /\/src\/index\./, /\/server\./, /\/app\./];
|
|
238
|
+
const importantPatterns = [/\/src\/api\//, /\/src\/controllers\//, /\/src\/services\//, /\/src\/models\//];
|
|
239
|
+
let score = 0.2;
|
|
240
|
+
const details = { filePath, impact: 'standard' };
|
|
241
|
+
if (criticalPatterns.some(p => p.test(filePath))) {
|
|
242
|
+
score = 0.8;
|
|
243
|
+
details.impact = 'critical';
|
|
244
|
+
} else if (importantPatterns.some(p => p.test(filePath))) {
|
|
245
|
+
score = 0.5;
|
|
246
|
+
details.impact = 'important';
|
|
247
|
+
}
|
|
248
|
+
details.isBusinessCritical = score >= 0.8;
|
|
249
|
+
result.addFactor(PRIORITY_FACTORS.BUSINESS_IMPACT, score, weights[PRIORITY_FACTORS.BUSINESS_IMPACT], details);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
function generateReasonsAndRecommendations(fileAnalysis, result) {
|
|
253
|
+
const reasons = [];
|
|
254
|
+
const recommendations = [];
|
|
255
|
+
const sizeFactor = result.factors[PRIORITY_FACTORS.SIZE_VIOLATION];
|
|
256
|
+
if (sizeFactor && sizeFactor.score > 0.6) {
|
|
257
|
+
reasons.push(`File has ${sizeFactor.details.excessLines} excess lines beyond limit`);
|
|
258
|
+
recommendations.push('Consider splitting large functions or extracting modules');
|
|
259
|
+
}
|
|
260
|
+
const complexityFactor = result.factors[PRIORITY_FACTORS.COMPLEXITY];
|
|
261
|
+
if (complexityFactor && complexityFactor.score > 0.6) {
|
|
262
|
+
reasons.push(`File has ${complexityFactor.details.level} complexity`);
|
|
263
|
+
recommendations.push('Reduce complexity through better organization and smaller functions');
|
|
264
|
+
}
|
|
265
|
+
const dependencyFactor = result.factors[PRIORITY_FACTORS.DEPENDENCY_COUNT];
|
|
266
|
+
if (dependencyFactor && dependencyFactor.score > 0.6) {
|
|
267
|
+
reasons.push(`File has ${dependencyFactor.details.totalDependencies} total dependencies`);
|
|
268
|
+
recommendations.push('Consider reducing dependencies through better separation of concerns');
|
|
269
|
+
}
|
|
270
|
+
const packageFactor = result.factors[PRIORITY_FACTORS.PACKAGE_IMPORTANCE];
|
|
271
|
+
if (packageFactor && packageFactor.score > 0.8) {
|
|
272
|
+
reasons.push(`File is in ${packageFactor.details.importance} package (${packageFactor.details.packageName})`);
|
|
273
|
+
recommendations.push('Ensure high code quality for critical package files');
|
|
274
|
+
}
|
|
275
|
+
const testFactor = result.factors[PRIORITY_FACTORS.TEST_COVERAGE];
|
|
276
|
+
if (testFactor && testFactor.score > 0.4) {
|
|
277
|
+
reasons.push('File has poor or no test coverage');
|
|
278
|
+
recommendations.push('Add test coverage before refactoring to ensure safety');
|
|
279
|
+
}
|
|
280
|
+
const businessFactor = result.factors[PRIORITY_FACTORS.BUSINESS_IMPACT];
|
|
281
|
+
if (businessFactor && businessFactor.score > 0.6) {
|
|
282
|
+
reasons.push(`File has ${businessFactor.details.impact} business impact`);
|
|
283
|
+
recommendations.push('Exercise extra caution when refactoring business-critical code');
|
|
284
|
+
}
|
|
285
|
+
result.reasons = reasons;
|
|
286
|
+
result.recommendations = recommendations;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
module.exports = {
|
|
290
|
+
calculateComplexityScore,
|
|
291
|
+
assessCouplingRisk,
|
|
292
|
+
findTestFile,
|
|
293
|
+
calculateSizeViolationFactor,
|
|
294
|
+
calculateComplexityFactor,
|
|
295
|
+
calculateDependencyFactor,
|
|
296
|
+
calculatePackageImportanceFactor,
|
|
297
|
+
calculateChangeFrequencyFactor,
|
|
298
|
+
calculateTestCoverageFactor,
|
|
299
|
+
calculateBusinessImpactFactor,
|
|
300
|
+
generateReasonsAndRecommendations
|
|
301
|
+
};
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Generates reasons and recommendations for priority results.
|
|
3
|
+
*/
|
|
4
|
+
|
|
5
|
+
const { PRIORITY_FACTORS } = require('./priority-constants');
|
|
6
|
+
|
|
7
|
+
function generateReasonsAndRecommendations(result) {
|
|
8
|
+
const reasons = [];
|
|
9
|
+
const recommendations = [];
|
|
10
|
+
const sizeFactor = result.factors[PRIORITY_FACTORS.SIZE_VIOLATION];
|
|
11
|
+
if (sizeFactor && sizeFactor.score > 0.6) {
|
|
12
|
+
reasons.push(`File has ${sizeFactor.details.excessLines} excess lines beyond limit`);
|
|
13
|
+
recommendations.push('Consider splitting large functions or extracting modules');
|
|
14
|
+
}
|
|
15
|
+
const complexityFactor = result.factors[PRIORITY_FACTORS.COMPLEXITY];
|
|
16
|
+
if (complexityFactor && complexityFactor.score > 0.6) {
|
|
17
|
+
reasons.push(`File has ${complexityFactor.details.level} complexity`);
|
|
18
|
+
recommendations.push('Reduce complexity through better organization and smaller functions');
|
|
19
|
+
}
|
|
20
|
+
const dependencyFactor = result.factors[PRIORITY_FACTORS.DEPENDENCY_COUNT];
|
|
21
|
+
if (dependencyFactor && dependencyFactor.score > 0.6) {
|
|
22
|
+
reasons.push(`File has ${dependencyFactor.details.totalDependencies} total dependencies`);
|
|
23
|
+
recommendations.push('Consider reducing dependencies through better separation of concerns');
|
|
24
|
+
}
|
|
25
|
+
const packageFactor = result.factors[PRIORITY_FACTORS.PACKAGE_IMPORTANCE];
|
|
26
|
+
if (packageFactor && packageFactor.score > 0.8) {
|
|
27
|
+
reasons.push(`File is in ${packageFactor.details.importance} package (${packageFactor.details.packageName})`);
|
|
28
|
+
recommendations.push('Ensure high code quality for critical package files');
|
|
29
|
+
}
|
|
30
|
+
const testFactor = result.factors[PRIORITY_FACTORS.TEST_COVERAGE];
|
|
31
|
+
if (testFactor && testFactor.score > 0.4) {
|
|
32
|
+
reasons.push('File has poor or no test coverage');
|
|
33
|
+
recommendations.push('Add test coverage before refactoring to ensure safety');
|
|
34
|
+
}
|
|
35
|
+
const businessFactor = result.factors[PRIORITY_FACTORS.BUSINESS_IMPACT];
|
|
36
|
+
if (businessFactor && businessFactor.score > 0.6) {
|
|
37
|
+
reasons.push(`File has ${businessFactor.details.impact} business impact`);
|
|
38
|
+
recommendations.push('Exercise extra caution when refactoring business-critical code');
|
|
39
|
+
}
|
|
40
|
+
result.reasons = reasons;
|
|
41
|
+
result.recommendations = recommendations;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { generateReasonsAndRecommendations };
|