pumuki-ast-hooks 5.5.46 → 5.5.48
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/docs/CODE_STANDARDS.md +5 -0
- package/docs/VIOLATIONS_RESOLUTION_PLAN.md +22 -34
- package/package.json +2 -2
- package/scripts/hooks-system/.audit_tmp/hook-metrics.jsonl +36 -0
- package/scripts/hooks-system/application/services/installation/FileSystemInstallerService.js +1 -1
- package/scripts/hooks-system/application/services/installation/VSCodeTaskConfigurator.js +8 -2
- package/scripts/hooks-system/bin/gitflow-cycle.js +0 -0
- package/scripts/hooks-system/config/project.config.json +1 -1
- package/scripts/hooks-system/infrastructure/ast/android/analyzers/AndroidSOLIDAnalyzer.js +11 -255
- package/scripts/hooks-system/infrastructure/ast/android/detectors/android-solid-detectors.js +227 -0
- package/scripts/hooks-system/infrastructure/ast/ast-core.js +12 -3
- package/scripts/hooks-system/infrastructure/ast/ast-intelligence.js +36 -13
- package/scripts/hooks-system/infrastructure/ast/backend/ast-backend.js +10 -83
- package/scripts/hooks-system/infrastructure/ast/backend/detectors/god-class-detector.js +83 -0
- package/scripts/hooks-system/infrastructure/ast/common/ast-common.js +17 -2
- package/scripts/hooks-system/infrastructure/ast/frontend/analyzers/FrontendArchitectureDetector.js +12 -142
- package/scripts/hooks-system/infrastructure/ast/frontend/detectors/frontend-architecture-strategies.js +126 -0
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSASTIntelligentAnalyzer.js +30 -783
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureDetector.js +21 -224
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSArchitectureRules.js +18 -605
- package/scripts/hooks-system/infrastructure/ast/ios/analyzers/iOSModernPracticesRules.js +4 -1
- package/scripts/hooks-system/infrastructure/ast/ios/ast-ios.js +4 -1
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-architecture-rules-strategies.js +595 -0
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-architecture-strategies.js +192 -0
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-ast-intelligent-strategies.js +789 -0
- package/scripts/hooks-system/infrastructure/ast/ios/detectors/ios-god-class-detector.js +79 -0
- package/scripts/hooks-system/infrastructure/ast/ios/native-bridge.js +4 -1
- package/skills/android-guidelines/SKILL.md +1 -0
- package/skills/backend-guidelines/SKILL.md +1 -0
- package/skills/frontend-guidelines/SKILL.md +1 -0
- package/skills/ios-guidelines/SKILL.md +1 -0
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
const { SyntaxKind } = require('../ast-core');
|
|
2
|
+
|
|
3
|
+
function analyzeGodClasses(sourceFile, findings, pushFinding, godClassBaseline) {
|
|
4
|
+
if (!godClassBaseline) return;
|
|
5
|
+
|
|
6
|
+
sourceFile.getDescendantsOfKind(SyntaxKind.ClassDeclaration).forEach((cls) => {
|
|
7
|
+
const className = cls.getName() || '';
|
|
8
|
+
const isValueObject = /DTO$|ViewModel$|State$|Props$|Entity$/.test(className);
|
|
9
|
+
const isTestClass = /Spec$|Test$|Mock/.test(className);
|
|
10
|
+
if (isValueObject || isTestClass) return;
|
|
11
|
+
|
|
12
|
+
const methodsCount = cls.getMethods().length;
|
|
13
|
+
const propertiesCount = cls.getProperties().length;
|
|
14
|
+
const startLine = cls.getStartLineNumber();
|
|
15
|
+
const endLine = cls.getEndLineNumber();
|
|
16
|
+
const lineCount = Math.max(0, endLine - startLine);
|
|
17
|
+
|
|
18
|
+
const decisionKinds = [
|
|
19
|
+
SyntaxKind.IfStatement,
|
|
20
|
+
SyntaxKind.ForStatement,
|
|
21
|
+
SyntaxKind.ForInStatement,
|
|
22
|
+
SyntaxKind.ForOfStatement,
|
|
23
|
+
SyntaxKind.WhileStatement,
|
|
24
|
+
SyntaxKind.DoStatement,
|
|
25
|
+
SyntaxKind.SwitchStatement,
|
|
26
|
+
SyntaxKind.ConditionalExpression,
|
|
27
|
+
SyntaxKind.TryStatement,
|
|
28
|
+
SyntaxKind.CatchClause
|
|
29
|
+
];
|
|
30
|
+
const complexity = decisionKinds.reduce((acc, kind) => acc + cls.getDescendantsOfKind(kind).length, 0);
|
|
31
|
+
|
|
32
|
+
const clsText = cls.getFullText();
|
|
33
|
+
const concerns = new Set();
|
|
34
|
+
if (/URLSession|URLRequest|Alamofire|HTTP/i.test(clsText)) concerns.add('network');
|
|
35
|
+
if (/CoreData|Realm|SQLite|Persistence/i.test(clsText)) concerns.add('persistence');
|
|
36
|
+
if (/DispatchQueue|asyncAfter|Timer/i.test(clsText)) concerns.add('async');
|
|
37
|
+
if (/CryptoKit|Keychain|JWT|token|bearer/i.test(clsText)) concerns.add('security');
|
|
38
|
+
if (/NotificationCenter|push|local notification/i.test(clsText)) concerns.add('notifications');
|
|
39
|
+
if (/UIKit|SwiftUI|View/i.test(clsText)) concerns.add('ui');
|
|
40
|
+
if (/Logger|print\(/i.test(clsText)) concerns.add('logging');
|
|
41
|
+
const concernCount = concerns.size;
|
|
42
|
+
|
|
43
|
+
const methodsZ = godClassBaseline.robustZ(methodsCount, godClassBaseline.med.methodsCount, godClassBaseline.mad.methodsCount);
|
|
44
|
+
const propsZ = godClassBaseline.robustZ(propertiesCount, godClassBaseline.med.propertiesCount, godClassBaseline.mad.propertiesCount);
|
|
45
|
+
const linesZ = godClassBaseline.robustZ(lineCount, godClassBaseline.med.lineCount, godClassBaseline.mad.lineCount);
|
|
46
|
+
const complexityZ = godClassBaseline.robustZ(complexity, godClassBaseline.med.complexity, godClassBaseline.mad.complexity);
|
|
47
|
+
|
|
48
|
+
const sizeOutlier =
|
|
49
|
+
methodsZ >= godClassBaseline.thresholds.outlier.methodsCountZ ||
|
|
50
|
+
propsZ >= godClassBaseline.thresholds.outlier.propertiesCountZ ||
|
|
51
|
+
linesZ >= godClassBaseline.thresholds.outlier.lineCountZ;
|
|
52
|
+
const complexityOutlier = complexityZ >= godClassBaseline.thresholds.outlier.complexityZ;
|
|
53
|
+
const concernOutlier = concernCount >= godClassBaseline.thresholds.outlier.concerns;
|
|
54
|
+
|
|
55
|
+
const isMassiveFile = lineCount > 500;
|
|
56
|
+
const isAbsoluteGod = lineCount > 900 ||
|
|
57
|
+
(lineCount > 450 && complexity > 50) ||
|
|
58
|
+
(lineCount > 450 && methodsCount > 20) ||
|
|
59
|
+
(lineCount > 550 && methodsCount > 25 && complexity > 70);
|
|
60
|
+
const isUnderThreshold = lineCount < 280 && methodsCount < 15 && complexity < 28;
|
|
61
|
+
|
|
62
|
+
let signalCount = 0;
|
|
63
|
+
if (sizeOutlier) signalCount++;
|
|
64
|
+
if (complexityOutlier) signalCount++;
|
|
65
|
+
if (concernOutlier) signalCount++;
|
|
66
|
+
if (isMassiveFile) signalCount++;
|
|
67
|
+
|
|
68
|
+
if (!isUnderThreshold && (signalCount >= 2 || isAbsoluteGod)) {
|
|
69
|
+
pushFinding("backend.antipattern.god_classes", "critical", sourceFile, cls,
|
|
70
|
+
`God class detected: ${methodsCount} methods, ${propertiesCount} properties, ${lineCount} lines, complexity ${complexity}, concerns ${concernCount} - VIOLATES SRP`,
|
|
71
|
+
findings
|
|
72
|
+
);
|
|
73
|
+
}
|
|
74
|
+
});
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
module.exports = {
|
|
78
|
+
analyzeGodClasses,
|
|
79
|
+
};
|
|
@@ -16,7 +16,10 @@ function getStagedSwiftFiles(repoRoot) {
|
|
|
16
16
|
.map(s => s.trim())
|
|
17
17
|
.filter(Boolean)
|
|
18
18
|
.filter(p => p.endsWith('.swift'));
|
|
19
|
-
} catch {
|
|
19
|
+
} catch (error) {
|
|
20
|
+
if (process.env.DEBUG) {
|
|
21
|
+
console.debug(`[iOS NativeBridge] Failed to read staged swift files: ${error.message}`);
|
|
22
|
+
}
|
|
20
23
|
return [];
|
|
21
24
|
}
|
|
22
25
|
}
|
|
@@ -34,6 +34,7 @@ Automatically activates when working on:
|
|
|
34
34
|
- [ ] **ViewModel**: Presentation/ui/{feature}/ViewModel
|
|
35
35
|
- [ ] **Tests**: Unit + integration tests
|
|
36
36
|
- [ ] **Error Handling**: Sealed class Result<T>
|
|
37
|
+
- [ ] **No empty catch**: Prohibido silenciar errores en tooling (AST: common.error.empty_catch)
|
|
37
38
|
|
|
38
39
|
### New Module Checklist
|
|
39
40
|
|
|
@@ -33,6 +33,7 @@ Automatically activates when working on:
|
|
|
33
33
|
- [ ] **Entity**: Domain model in domain/entities/
|
|
34
34
|
- [ ] **Tests**: Unit + integration tests
|
|
35
35
|
- [ ] **Error Handling**: Custom exceptions
|
|
36
|
+
- [ ] **No empty catch**: Prohibido `catch` vacío (AST: common.error.empty_catch)
|
|
36
37
|
|
|
37
38
|
### New Module Checklist
|
|
38
39
|
|
|
@@ -36,6 +36,7 @@ Creating a component? Follow this checklist:
|
|
|
36
36
|
- [ ] **i18n** - Use translation hooks, no hardcoded strings
|
|
37
37
|
- [ ] **Performance** - useMemo, useCallback when appropriate
|
|
38
38
|
- [ ] **Testing** - React Testing Library tests
|
|
39
|
+
- [ ] **No empty catch** - Prohibido silenciar errores (AST: common.error.empty_catch)
|
|
39
40
|
|
|
40
41
|
### New Feature Checklist
|
|
41
42
|
|
|
@@ -34,6 +34,7 @@ Automatically activates when working on:
|
|
|
34
34
|
- [ ] **ViewModel**: Application/ViewModels/ (if needed)
|
|
35
35
|
- [ ] **Tests**: Unit + integration tests
|
|
36
36
|
- [ ] **Error Handling**: Custom Error enum
|
|
37
|
+
- [ ] **No empty catch**: Prohibido `catch` vacío (AST: common.error.empty_catch)
|
|
37
38
|
|
|
38
39
|
### New Module Checklist
|
|
39
40
|
|