@defai.digital/ax-cli 3.4.6 → 3.5.4

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.
Files changed (223) hide show
  1. package/LICENSE +2 -6
  2. package/README.md +109 -2
  3. package/dist/analyzers/ast/index.d.ts +9 -0
  4. package/dist/analyzers/ast/index.js +10 -0
  5. package/dist/analyzers/ast/index.js.map +1 -0
  6. package/dist/analyzers/ast/node-helpers.d.ts +81 -0
  7. package/dist/analyzers/ast/node-helpers.js +128 -0
  8. package/dist/analyzers/ast/node-helpers.js.map +1 -0
  9. package/dist/analyzers/ast/parser.d.ts +59 -0
  10. package/dist/analyzers/ast/parser.js +293 -0
  11. package/dist/analyzers/ast/parser.js.map +1 -0
  12. package/dist/analyzers/ast/traverser.d.ts +67 -0
  13. package/dist/analyzers/ast/traverser.js +156 -0
  14. package/dist/analyzers/ast/traverser.js.map +1 -0
  15. package/dist/analyzers/ast/types.d.ts +107 -0
  16. package/dist/analyzers/ast/types.js +7 -0
  17. package/dist/analyzers/ast/types.js.map +1 -0
  18. package/dist/analyzers/best-practices/index.d.ts +10 -0
  19. package/dist/analyzers/best-practices/index.js +11 -0
  20. package/dist/analyzers/best-practices/index.js.map +1 -0
  21. package/dist/analyzers/code-smells/base-smell-detector.d.ts +30 -0
  22. package/dist/analyzers/code-smells/base-smell-detector.js +44 -0
  23. package/dist/analyzers/code-smells/base-smell-detector.js.map +1 -0
  24. package/dist/analyzers/code-smells/code-smell-analyzer.d.ts +30 -0
  25. package/dist/analyzers/code-smells/code-smell-analyzer.js +167 -0
  26. package/dist/analyzers/code-smells/code-smell-analyzer.js.map +1 -0
  27. package/dist/analyzers/code-smells/detectors/data-clumps-detector.d.ts +11 -0
  28. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js +66 -0
  29. package/dist/analyzers/code-smells/detectors/data-clumps-detector.js.map +1 -0
  30. package/dist/analyzers/code-smells/detectors/dead-code-detector.d.ts +11 -0
  31. package/dist/analyzers/code-smells/detectors/dead-code-detector.js +53 -0
  32. package/dist/analyzers/code-smells/detectors/dead-code-detector.js.map +1 -0
  33. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.d.ts +11 -0
  34. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js +51 -0
  35. package/dist/analyzers/code-smells/detectors/duplicate-code-detector.js.map +1 -0
  36. package/dist/analyzers/code-smells/detectors/feature-envy-detector.d.ts +11 -0
  37. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js +64 -0
  38. package/dist/analyzers/code-smells/detectors/feature-envy-detector.js.map +1 -0
  39. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.d.ts +11 -0
  40. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js +56 -0
  41. package/dist/analyzers/code-smells/detectors/inappropriate-intimacy-detector.js.map +1 -0
  42. package/dist/analyzers/code-smells/detectors/large-class-detector.d.ts +13 -0
  43. package/dist/analyzers/code-smells/detectors/large-class-detector.js +58 -0
  44. package/dist/analyzers/code-smells/detectors/large-class-detector.js.map +1 -0
  45. package/dist/analyzers/code-smells/detectors/long-method-detector.d.ts +12 -0
  46. package/dist/analyzers/code-smells/detectors/long-method-detector.js +52 -0
  47. package/dist/analyzers/code-smells/detectors/long-method-detector.js.map +1 -0
  48. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.d.ts +12 -0
  49. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js +50 -0
  50. package/dist/analyzers/code-smells/detectors/long-parameter-list-detector.js.map +1 -0
  51. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.d.ts +12 -0
  52. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js +54 -0
  53. package/dist/analyzers/code-smells/detectors/magic-numbers-detector.js.map +1 -0
  54. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.d.ts +13 -0
  55. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js +71 -0
  56. package/dist/analyzers/code-smells/detectors/nested-conditionals-detector.js.map +1 -0
  57. package/dist/analyzers/code-smells/index.d.ts +16 -0
  58. package/dist/analyzers/code-smells/index.js +19 -0
  59. package/dist/analyzers/code-smells/index.js.map +1 -0
  60. package/dist/analyzers/code-smells/types.d.ts +82 -0
  61. package/dist/analyzers/code-smells/types.js +30 -0
  62. package/dist/analyzers/code-smells/types.js.map +1 -0
  63. package/dist/analyzers/dependency/circular-detector.d.ts +17 -0
  64. package/dist/analyzers/dependency/circular-detector.js +71 -0
  65. package/dist/analyzers/dependency/circular-detector.js.map +1 -0
  66. package/dist/analyzers/dependency/coupling-calculator.d.ts +24 -0
  67. package/dist/analyzers/dependency/coupling-calculator.js +86 -0
  68. package/dist/analyzers/dependency/coupling-calculator.js.map +1 -0
  69. package/dist/analyzers/dependency/dependency-analyzer.d.ts +40 -0
  70. package/dist/analyzers/dependency/dependency-analyzer.js +214 -0
  71. package/dist/analyzers/dependency/dependency-analyzer.js.map +1 -0
  72. package/dist/analyzers/dependency/dependency-graph.d.ts +57 -0
  73. package/dist/analyzers/dependency/dependency-graph.js +186 -0
  74. package/dist/analyzers/dependency/dependency-graph.js.map +1 -0
  75. package/dist/analyzers/dependency/index.d.ts +8 -0
  76. package/dist/analyzers/dependency/index.js +8 -0
  77. package/dist/analyzers/dependency/index.js.map +1 -0
  78. package/dist/analyzers/dependency/types.d.ts +105 -0
  79. package/dist/analyzers/dependency/types.js +5 -0
  80. package/dist/analyzers/dependency/types.js.map +1 -0
  81. package/dist/analyzers/git/churn-calculator.d.ts +34 -0
  82. package/dist/analyzers/git/churn-calculator.js +214 -0
  83. package/dist/analyzers/git/churn-calculator.js.map +1 -0
  84. package/dist/analyzers/git/git-analyzer.d.ts +19 -0
  85. package/dist/analyzers/git/git-analyzer.js +71 -0
  86. package/dist/analyzers/git/git-analyzer.js.map +1 -0
  87. package/dist/analyzers/git/hotspot-detector.d.ts +34 -0
  88. package/dist/analyzers/git/hotspot-detector.js +170 -0
  89. package/dist/analyzers/git/hotspot-detector.js.map +1 -0
  90. package/dist/analyzers/git/index.d.ts +7 -0
  91. package/dist/analyzers/git/index.js +7 -0
  92. package/dist/analyzers/git/index.js.map +1 -0
  93. package/dist/analyzers/git/types.d.ts +88 -0
  94. package/dist/analyzers/git/types.js +5 -0
  95. package/dist/analyzers/git/types.js.map +1 -0
  96. package/dist/analyzers/metrics/halstead-calculator.d.ts +30 -0
  97. package/dist/analyzers/metrics/halstead-calculator.js +150 -0
  98. package/dist/analyzers/metrics/halstead-calculator.js.map +1 -0
  99. package/dist/analyzers/metrics/index.d.ts +9 -0
  100. package/dist/analyzers/metrics/index.js +9 -0
  101. package/dist/analyzers/metrics/index.js.map +1 -0
  102. package/dist/analyzers/metrics/maintainability-calculator.d.ts +17 -0
  103. package/dist/analyzers/metrics/maintainability-calculator.js +46 -0
  104. package/dist/analyzers/metrics/maintainability-calculator.js.map +1 -0
  105. package/dist/analyzers/metrics/metrics-analyzer.d.ts +32 -0
  106. package/dist/analyzers/metrics/metrics-analyzer.js +140 -0
  107. package/dist/analyzers/metrics/metrics-analyzer.js.map +1 -0
  108. package/dist/analyzers/metrics/types.d.ts +67 -0
  109. package/dist/analyzers/metrics/types.js +5 -0
  110. package/dist/analyzers/metrics/types.js.map +1 -0
  111. package/dist/analyzers/security/base-detector.d.ts +58 -0
  112. package/dist/analyzers/security/base-detector.js +104 -0
  113. package/dist/analyzers/security/base-detector.js.map +1 -0
  114. package/dist/analyzers/security/detectors/command-injection-detector.d.ts +12 -0
  115. package/dist/analyzers/security/detectors/command-injection-detector.js +84 -0
  116. package/dist/analyzers/security/detectors/command-injection-detector.js.map +1 -0
  117. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.d.ts +16 -0
  118. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js +140 -0
  119. package/dist/analyzers/security/detectors/hardcoded-secrets-detector.js.map +1 -0
  120. package/dist/analyzers/security/detectors/insecure-deserialization-detector.d.ts +12 -0
  121. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js +109 -0
  122. package/dist/analyzers/security/detectors/insecure-deserialization-detector.js.map +1 -0
  123. package/dist/analyzers/security/detectors/insecure-random-detector.d.ts +12 -0
  124. package/dist/analyzers/security/detectors/insecure-random-detector.js +61 -0
  125. package/dist/analyzers/security/detectors/insecure-random-detector.js.map +1 -0
  126. package/dist/analyzers/security/detectors/path-traversal-detector.d.ts +12 -0
  127. package/dist/analyzers/security/detectors/path-traversal-detector.js +82 -0
  128. package/dist/analyzers/security/detectors/path-traversal-detector.js.map +1 -0
  129. package/dist/analyzers/security/detectors/sql-injection-detector.d.ts +12 -0
  130. package/dist/analyzers/security/detectors/sql-injection-detector.js +88 -0
  131. package/dist/analyzers/security/detectors/sql-injection-detector.js.map +1 -0
  132. package/dist/analyzers/security/detectors/weak-crypto-detector.d.ts +12 -0
  133. package/dist/analyzers/security/detectors/weak-crypto-detector.js +104 -0
  134. package/dist/analyzers/security/detectors/weak-crypto-detector.js.map +1 -0
  135. package/dist/analyzers/security/detectors/xss-detector.d.ts +12 -0
  136. package/dist/analyzers/security/detectors/xss-detector.js +90 -0
  137. package/dist/analyzers/security/detectors/xss-detector.js.map +1 -0
  138. package/dist/analyzers/security/index.d.ts +16 -0
  139. package/dist/analyzers/security/index.js +18 -0
  140. package/dist/analyzers/security/index.js.map +1 -0
  141. package/dist/analyzers/security/security-analyzer.d.ts +38 -0
  142. package/dist/analyzers/security/security-analyzer.js +215 -0
  143. package/dist/analyzers/security/security-analyzer.js.map +1 -0
  144. package/dist/analyzers/security/types.d.ts +95 -0
  145. package/dist/analyzers/security/types.js +7 -0
  146. package/dist/analyzers/security/types.js.map +1 -0
  147. package/dist/hooks/use-enhanced-input.d.ts +0 -1
  148. package/dist/hooks/use-enhanced-input.js.map +1 -1
  149. package/dist/index.js +0 -0
  150. package/dist/mcp/validation.js +12 -6
  151. package/dist/mcp/validation.js.map +1 -1
  152. package/dist/tools/analysis-tools.d.ts +73 -0
  153. package/dist/tools/analysis-tools.js +422 -0
  154. package/dist/tools/analysis-tools.js.map +1 -0
  155. package/dist/tools/bash.js +2 -1
  156. package/dist/tools/bash.js.map +1 -1
  157. package/dist/ui/components/toast-notification.js +0 -1
  158. package/dist/ui/components/toast-notification.js.map +1 -1
  159. package/dist/ui/components/welcome-panel.js +1 -1
  160. package/dist/ui/components/welcome-panel.js.map +1 -1
  161. package/dist/ui/hooks/use-input-history.d.ts +9 -0
  162. package/dist/ui/hooks/use-input-history.js +117 -0
  163. package/dist/ui/hooks/use-input-history.js.map +1 -0
  164. package/dist/utils/parallel-analyzer.js +30 -17
  165. package/dist/utils/parallel-analyzer.js.map +1 -1
  166. package/eslint.config.js +3 -0
  167. package/package.json +5 -5
  168. package/vitest.config.ts +1 -0
  169. package/.ax-cli/checkpoints/2025-11-20/checkpoint-11e9e0ba-c39d-4fd2-aa77-bc818811c921.json +0 -69
  170. package/.ax-cli/checkpoints/2025-11-20/checkpoint-2b260b98-b418-4c7c-9694-e2b94967e662.json +0 -24
  171. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7e03601e-e8ab-4cd7-9841-a74b66adf78f.json +0 -69
  172. package/.ax-cli/checkpoints/2025-11-20/checkpoint-7f9c6562-771f-4fd0-adcf-9e7e9ac34ae8.json +0 -44
  173. package/.ax-cli/checkpoints/2025-11-20/checkpoint-e1ebe666-4c3a-4367-ba5c-27fe512a9c70.json +0 -24
  174. package/.ax-cli/checkpoints/2025-11-21/checkpoint-15743e7d-430c-4d76-b6fc-955d7a5c250c.json +0 -44
  175. package/.ax-cli/checkpoints/2025-11-21/checkpoint-25cf7679-0b3f-4988-83d7-704548fbba91.json +0 -69
  176. package/.ax-cli/checkpoints/2025-11-21/checkpoint-54aedbac-6db0-464e-8ebb-dbb3979e6dca.json +0 -24
  177. package/.ax-cli/checkpoints/2025-11-21/checkpoint-7658aed8-fe5d-4222-903f-1a7c63717ea7.json +0 -24
  178. package/.ax-cli/checkpoints/2025-11-21/checkpoint-c9c13497-40dc-4294-a327-6a5fc854eaa1.json +0 -69
  179. package/automatosx.config.json +0 -333
  180. package/config/messages.yaml +0 -75
  181. package/config/models.yaml +0 -66
  182. package/config/prompts.yaml +0 -156
  183. package/config/settings.yaml +0 -86
  184. package/dist/commands/weather.d.ts +0 -8
  185. package/dist/commands/weather.js +0 -160
  186. package/dist/commands/weather.js.map +0 -1
  187. package/dist/grok/client.d.ts +0 -144
  188. package/dist/grok/client.js +0 -237
  189. package/dist/grok/client.js.map +0 -1
  190. package/dist/grok/tools.d.ts +0 -8
  191. package/dist/grok/tools.js +0 -318
  192. package/dist/grok/tools.js.map +0 -1
  193. package/dist/grok/types.d.ts +0 -291
  194. package/dist/grok/types.js +0 -127
  195. package/dist/grok/types.js.map +0 -1
  196. package/dist/tools/morph-editor.d.ts +0 -36
  197. package/dist/tools/morph-editor.js +0 -308
  198. package/dist/tools/morph-editor.js.map +0 -1
  199. package/dist/ui/components/session-recovery.d.ts +0 -12
  200. package/dist/ui/components/session-recovery.js +0 -93
  201. package/dist/ui/components/session-recovery.js.map +0 -1
  202. package/dist/utils/model-config.d.ts +0 -28
  203. package/dist/utils/model-config.js +0 -43
  204. package/dist/utils/model-config.js.map +0 -1
  205. package/dist/utils/tool-helpers.d.ts +0 -25
  206. package/dist/utils/tool-helpers.js +0 -79
  207. package/dist/utils/tool-helpers.js.map +0 -1
  208. package/packages/schemas/dist/index.d.ts +0 -14
  209. package/packages/schemas/dist/index.d.ts.map +0 -1
  210. package/packages/schemas/dist/index.js +0 -19
  211. package/packages/schemas/dist/index.js.map +0 -1
  212. package/packages/schemas/dist/public/core/brand-types.d.ts +0 -308
  213. package/packages/schemas/dist/public/core/brand-types.d.ts.map +0 -1
  214. package/packages/schemas/dist/public/core/brand-types.js +0 -243
  215. package/packages/schemas/dist/public/core/brand-types.js.map +0 -1
  216. package/packages/schemas/dist/public/core/enums.d.ts +0 -227
  217. package/packages/schemas/dist/public/core/enums.d.ts.map +0 -1
  218. package/packages/schemas/dist/public/core/enums.js +0 -222
  219. package/packages/schemas/dist/public/core/enums.js.map +0 -1
  220. package/packages/schemas/dist/public/core/id-types.d.ts +0 -286
  221. package/packages/schemas/dist/public/core/id-types.d.ts.map +0 -1
  222. package/packages/schemas/dist/public/core/id-types.js +0 -136
  223. package/packages/schemas/dist/public/core/id-types.js.map +0 -1
@@ -0,0 +1,56 @@
1
+ /**
2
+ * Inappropriate Intimacy Detector
3
+ *
4
+ * Detects classes that are too tightly coupled
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ import { SyntaxKind } from 'ts-morph';
9
+ export class InappropriateIntimacyDetector extends BaseSmellDetector {
10
+ constructor(config = { enabled: true, thresholds: { maxAccess: 10 } }) {
11
+ super(SmellType.INAPPROPRIATE_INTIMACY, config);
12
+ }
13
+ async detect(filePath) {
14
+ if (!this.isEnabled())
15
+ return [];
16
+ const smells = [];
17
+ const maxAccess = this.getThreshold('maxAccess', 10);
18
+ try {
19
+ const sourceFile = this.astParser.getSourceFile(filePath);
20
+ const classes = sourceFile.getClasses();
21
+ for (const cls of classes) {
22
+ const className = cls.getName() || 'anonymous';
23
+ const externalClassAccess = new Map();
24
+ // Count accesses to other classes
25
+ cls.forEachDescendant((node) => {
26
+ if (node.getKind() === SyntaxKind.PropertyAccessExpression) {
27
+ const text = node.getText();
28
+ // Skip 'this.' accesses
29
+ if (text.startsWith('this.'))
30
+ return;
31
+ // Extract potential class name from property access (e.g., 'otherClass.property')
32
+ const parts = text.split('.');
33
+ if (parts.length >= 2) {
34
+ const potentialClass = parts[0];
35
+ // Simple heuristic: capitalized names or common object names
36
+ if (potentialClass.length > 0 && /^[a-z][a-zA-Z]*$/.test(potentialClass)) {
37
+ externalClassAccess.set(potentialClass, (externalClassAccess.get(potentialClass) || 0) + 1);
38
+ }
39
+ }
40
+ }
41
+ });
42
+ // Report excessive coupling
43
+ for (const [externalClass, accessCount] of externalClassAccess.entries()) {
44
+ if (accessCount > maxAccess) {
45
+ smells.push(this.createSmell(filePath, cls.getStartLineNumber(), cls.getEndLineNumber(), `Class '${className}' is too intimate with '${externalClass}' (${accessCount} accesses)`, `Consider refactoring to reduce coupling. Move shared functionality to a common base class or use composition.`, accessCount >= 20 ? SmellSeverity.HIGH : SmellSeverity.MEDIUM, { className, targetClass: externalClass, accessCount, threshold: maxAccess }));
46
+ }
47
+ }
48
+ }
49
+ }
50
+ catch (error) {
51
+ // Skip files that can't be parsed
52
+ }
53
+ return smells;
54
+ }
55
+ }
56
+ //# sourceMappingURL=inappropriate-intimacy-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"inappropriate-intimacy-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/inappropriate-intimacy-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Large Class Detector
3
+ *
4
+ * Detects classes that are too large (lines or method count)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class LargeClassDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ private getSeverityByRatio;
12
+ private updateSeverity;
13
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * Large Class Detector
3
+ *
4
+ * Detects classes that are too large (lines or method count)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class LargeClassDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true, thresholds: { maxLines: 300, maxMethods: 20 } }) {
10
+ super(SmellType.LARGE_CLASS, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ const maxLines = this.getThreshold('maxLines', 300);
17
+ const maxMethods = this.getThreshold('maxMethods', 20);
18
+ try {
19
+ const ast = this.astParser.parseFile(filePath);
20
+ for (const cls of ast.classes) {
21
+ const issues = [];
22
+ let severity = SmellSeverity.LOW;
23
+ // Check line count
24
+ if (cls.length > maxLines) {
25
+ issues.push(`${cls.length} lines (threshold: ${maxLines})`);
26
+ severity = this.updateSeverity(severity, this.getSeverityByRatio(cls.length, maxLines));
27
+ }
28
+ // Check method count
29
+ if (cls.methods.length > maxMethods) {
30
+ issues.push(`${cls.methods.length} methods (threshold: ${maxMethods})`);
31
+ severity = this.updateSeverity(severity, this.getSeverityByRatio(cls.methods.length, maxMethods));
32
+ }
33
+ if (issues.length > 0) {
34
+ smells.push(this.createSmell(filePath, cls.startLine, cls.endLine, `Class '${cls.name}' is too large: ${issues.join(', ')}`, `Consider splitting this class into smaller, more focused classes following the Single Responsibility Principle.`, severity, { className: cls.name, lines: cls.length, methods: cls.methods.length }));
35
+ }
36
+ }
37
+ }
38
+ catch (error) {
39
+ // Skip files that can't be parsed
40
+ }
41
+ return smells;
42
+ }
43
+ getSeverityByRatio(value, threshold) {
44
+ const ratio = value / threshold;
45
+ if (ratio >= 3)
46
+ return SmellSeverity.CRITICAL;
47
+ if (ratio >= 2)
48
+ return SmellSeverity.HIGH;
49
+ if (ratio >= 1.5)
50
+ return SmellSeverity.MEDIUM;
51
+ return SmellSeverity.LOW;
52
+ }
53
+ updateSeverity(current, newSev) {
54
+ const order = { LOW: 0, MEDIUM: 1, HIGH: 2, CRITICAL: 3 };
55
+ return order[newSev] > order[current] ? newSev : current;
56
+ }
57
+ }
58
+ //# sourceMappingURL=large-class-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"large-class-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/large-class-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Long Method Detector
3
+ *
4
+ * Detects functions/methods that exceed a threshold line count
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class LongMethodDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ private getSeverity;
12
+ }
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Long Method Detector
3
+ *
4
+ * Detects functions/methods that exceed a threshold line count
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class LongMethodDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true, thresholds: { maxLines: 50 } }) {
10
+ super(SmellType.LONG_METHOD, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ const maxLines = this.getThreshold('maxLines', 50);
17
+ try {
18
+ const ast = this.astParser.parseFile(filePath);
19
+ // Check functions
20
+ for (const func of ast.functions) {
21
+ if (func.length > maxLines) {
22
+ const severity = this.getSeverity(func.length, maxLines);
23
+ smells.push(this.createSmell(filePath, func.startLine, func.endLine, `Function '${func.name}' is too long (${func.length} lines)`, `Consider breaking this function into smaller, focused functions. Aim for functions under ${maxLines} lines.`, severity, { functionName: func.name, lines: func.length, threshold: maxLines }));
24
+ }
25
+ }
26
+ // Check methods in classes
27
+ for (const cls of ast.classes) {
28
+ for (const method of cls.methods) {
29
+ if (method.length > maxLines) {
30
+ const severity = this.getSeverity(method.length, maxLines);
31
+ smells.push(this.createSmell(filePath, method.startLine, method.endLine, `Method '${cls.name}.${method.name}' is too long (${method.length} lines)`, `Consider extracting parts of this method into smaller helper methods.`, severity, { className: cls.name, methodName: method.name, lines: method.length, threshold: maxLines }));
32
+ }
33
+ }
34
+ }
35
+ }
36
+ catch (error) {
37
+ // Skip files that can't be parsed
38
+ }
39
+ return smells;
40
+ }
41
+ getSeverity(lines, threshold) {
42
+ const ratio = lines / threshold;
43
+ if (ratio >= 4)
44
+ return SmellSeverity.CRITICAL;
45
+ if (ratio >= 2)
46
+ return SmellSeverity.HIGH;
47
+ if (ratio >= 1.5)
48
+ return SmellSeverity.MEDIUM;
49
+ return SmellSeverity.LOW;
50
+ }
51
+ }
52
+ //# sourceMappingURL=long-method-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-method-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/long-method-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Long Parameter List Detector
3
+ *
4
+ * Detects functions with too many parameters
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class LongParameterListDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ private getSeverity;
12
+ }
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Long Parameter List Detector
3
+ *
4
+ * Detects functions with too many parameters
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class LongParameterListDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true, thresholds: { maxParams: 5 } }) {
10
+ super(SmellType.LONG_PARAMETER_LIST, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ const maxParams = this.getThreshold('maxParams', 5);
17
+ try {
18
+ const ast = this.astParser.parseFile(filePath);
19
+ // Check functions
20
+ for (const func of ast.functions) {
21
+ if (func.parameters.length > maxParams) {
22
+ smells.push(this.createSmell(filePath, func.startLine, func.endLine, `Function '${func.name}' has too many parameters (${func.parameters.length})`, `Consider using a parameter object or builder pattern to reduce the parameter count. Aim for ${maxParams} or fewer parameters.`, this.getSeverity(func.parameters.length, maxParams), { functionName: func.name, paramCount: func.parameters.length, threshold: maxParams }));
23
+ }
24
+ }
25
+ // Check methods
26
+ for (const cls of ast.classes) {
27
+ for (const method of cls.methods) {
28
+ if (method.parameters.length > maxParams) {
29
+ smells.push(this.createSmell(filePath, method.startLine, method.endLine, `Method '${cls.name}.${method.name}' has too many parameters (${method.parameters.length})`, `Consider using a parameter object or refactoring to reduce dependencies.`, this.getSeverity(method.parameters.length, maxParams), { className: cls.name, methodName: method.name, paramCount: method.parameters.length, threshold: maxParams }));
30
+ }
31
+ }
32
+ }
33
+ }
34
+ catch (error) {
35
+ // Skip files that can't be parsed
36
+ }
37
+ return smells;
38
+ }
39
+ getSeverity(count, threshold) {
40
+ const ratio = count / threshold;
41
+ if (ratio >= 2.5)
42
+ return SmellSeverity.CRITICAL;
43
+ if (ratio >= 2)
44
+ return SmellSeverity.HIGH;
45
+ if (ratio >= 1.5)
46
+ return SmellSeverity.MEDIUM;
47
+ return SmellSeverity.LOW;
48
+ }
49
+ }
50
+ //# sourceMappingURL=long-parameter-list-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"long-parameter-list-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/long-parameter-list-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuC,MAAM,aAAa,CAAC;AAE5F,MAAM,OAAO,yBAA0B,SAAQ,iBAAiB;IAC9D,YAAY,SAAyB,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,SAAS,EAAE,CAAC,EAAE,EAAE;QAClF,KAAK,CAAC,SAAS,CAAC,mBAAmB,EAAE,MAAM,CAAC,CAAC;IAC/C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,EAAE,CAAC;QAEjC,MAAM,MAAM,GAAgB,EAAE,CAAC;QAC/B,MAAM,SAAS,GAAG,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE,CAAC,CAAC,CAAC;QAEpD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAE/C,kBAAkB;YAClB,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACjC,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;oBACvC,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,IAAI,CAAC,SAAS,EACd,IAAI,CAAC,OAAO,EACZ,aAAa,IAAI,CAAC,IAAI,8BAA8B,IAAI,CAAC,UAAU,CAAC,MAAM,GAAG,EAC7E,+FAA+F,SAAS,uBAAuB,EAC/H,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,EACnD,EAAE,YAAY,EAAE,IAAI,CAAC,IAAI,EAAE,UAAU,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CACtF,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,gBAAgB;YAChB,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC9B,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBACjC,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,SAAS,EAAE,CAAC;wBACzC,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,OAAO,EACd,WAAW,GAAG,CAAC,IAAI,IAAI,MAAM,CAAC,IAAI,8BAA8B,MAAM,CAAC,UAAU,CAAC,MAAM,GAAG,EAC3F,0EAA0E,EAC1E,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,CAAC,EACrD,EAAE,SAAS,EAAE,GAAG,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,CAC7G,CACF,CAAC;oBACJ,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kCAAkC;QACpC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAEO,WAAW,CAAC,KAAa,EAAE,SAAiB;QAClD,MAAM,KAAK,GAAG,KAAK,GAAG,SAAS,CAAC;QAChC,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,aAAa,CAAC,QAAQ,CAAC;QAChD,IAAI,KAAK,IAAI,CAAC;YAAE,OAAO,aAAa,CAAC,IAAI,CAAC;QAC1C,IAAI,KAAK,IAAI,GAAG;YAAE,OAAO,aAAa,CAAC,MAAM,CAAC;QAC9C,OAAO,aAAa,CAAC,GAAG,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,12 @@
1
+ /**
2
+ * Magic Numbers Detector
3
+ *
4
+ * Detects hardcoded numeric literals (excluding common values like 0, 1, -1, 100)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class MagicNumbersDetector extends BaseSmellDetector {
9
+ private readonly ALLOWED_NUMBERS;
10
+ constructor(config?: DetectorConfig);
11
+ detect(filePath: string): Promise<CodeSmell[]>;
12
+ }
@@ -0,0 +1,54 @@
1
+ /**
2
+ * Magic Numbers Detector
3
+ *
4
+ * Detects hardcoded numeric literals (excluding common values like 0, 1, -1, 100)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ import { SyntaxKind } from 'ts-morph';
9
+ export class MagicNumbersDetector extends BaseSmellDetector {
10
+ ALLOWED_NUMBERS = new Set([0, 1, -1, 2, 10, 100, 1000]);
11
+ constructor(config = { enabled: true }) {
12
+ super(SmellType.MAGIC_NUMBERS, config);
13
+ }
14
+ async detect(filePath) {
15
+ if (!this.isEnabled())
16
+ return [];
17
+ const smells = [];
18
+ try {
19
+ const sourceFile = this.astParser.getSourceFile(filePath);
20
+ const magicNumbers = new Map();
21
+ // Find all numeric literals
22
+ sourceFile.forEachDescendant((node) => {
23
+ if (node.getKind() === SyntaxKind.NumericLiteral) {
24
+ const value = Number(node.getText());
25
+ // Skip allowed numbers
26
+ if (this.ALLOWED_NUMBERS.has(value))
27
+ return;
28
+ // Skip if in const declaration (already named)
29
+ const parent = node.getParent();
30
+ if (parent && parent.getKind() === SyntaxKind.VariableDeclaration) {
31
+ return;
32
+ }
33
+ const line = node.getStartLineNumber();
34
+ if (!magicNumbers.has(value)) {
35
+ magicNumbers.set(value, []);
36
+ }
37
+ magicNumbers.get(value).push({ line, text: node.getText() });
38
+ }
39
+ });
40
+ // Create smells for magic numbers
41
+ for (const [value, occurrences] of magicNumbers.entries()) {
42
+ if (occurrences.length > 0) {
43
+ const firstOccurrence = occurrences[0];
44
+ smells.push(this.createSmell(filePath, firstOccurrence.line, firstOccurrence.line, `Magic number '${value}' found (${occurrences.length} occurrence${occurrences.length > 1 ? 's' : ''})`, `Replace this magic number with a named constant to improve code readability and maintainability.`, occurrences.length >= 3 ? SmellSeverity.MEDIUM : SmellSeverity.LOW, { value, occurrences: occurrences.length, lines: occurrences.map(o => o.line) }));
45
+ }
46
+ }
47
+ }
48
+ catch (error) {
49
+ // Skip files that can't be parsed
50
+ }
51
+ return smells;
52
+ }
53
+ }
54
+ //# sourceMappingURL=magic-numbers-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"magic-numbers-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/magic-numbers-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Nested Conditionals Detector
3
+ *
4
+ * Detects deeply nested if/else/switch statements
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class NestedConditionalsDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ private getMaxNestingDepth;
12
+ private getSeverity;
13
+ }
@@ -0,0 +1,71 @@
1
+ /**
2
+ * Nested Conditionals Detector
3
+ *
4
+ * Detects deeply nested if/else/switch statements
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ import { SyntaxKind } from 'ts-morph';
9
+ export class NestedConditionalsDetector extends BaseSmellDetector {
10
+ constructor(config = { enabled: true, thresholds: { maxDepth: 3 } }) {
11
+ super(SmellType.NESTED_CONDITIONALS, config);
12
+ }
13
+ async detect(filePath) {
14
+ if (!this.isEnabled())
15
+ return [];
16
+ const smells = [];
17
+ const maxDepth = this.getThreshold('maxDepth', 3);
18
+ try {
19
+ const sourceFile = this.astParser.getSourceFile(filePath);
20
+ // Check each function/method
21
+ const functions = sourceFile.getFunctions();
22
+ for (const func of functions) {
23
+ const depth = this.getMaxNestingDepth(func);
24
+ if (depth > maxDepth) {
25
+ smells.push(this.createSmell(filePath, func.getStartLineNumber(), func.getEndLineNumber(), `Function '${func.getName() || 'anonymous'}' has deeply nested conditionals (depth: ${depth})`, `Reduce nesting by using early returns, extracting methods, or simplifying logic.`, this.getSeverity(depth, maxDepth), { functionName: func.getName() || 'anonymous', depth, threshold: maxDepth }));
26
+ }
27
+ }
28
+ // Check methods
29
+ const classes = sourceFile.getClasses();
30
+ for (const cls of classes) {
31
+ for (const method of cls.getMethods()) {
32
+ const depth = this.getMaxNestingDepth(method);
33
+ if (depth > maxDepth) {
34
+ smells.push(this.createSmell(filePath, method.getStartLineNumber(), method.getEndLineNumber(), `Method '${cls.getName()}.${method.getName()}' has deeply nested conditionals (depth: ${depth})`, `Reduce nesting by using guard clauses or extracting sub-methods.`, this.getSeverity(depth, maxDepth), { className: cls.getName(), methodName: method.getName(), depth, threshold: maxDepth }));
35
+ }
36
+ }
37
+ }
38
+ }
39
+ catch (error) {
40
+ // Skip files that can't be parsed
41
+ }
42
+ return smells;
43
+ }
44
+ getMaxNestingDepth(node) {
45
+ let maxDepth = 0;
46
+ const traverse = (n, currentDepth) => {
47
+ const kind = n.getKind();
48
+ // Increment depth for conditional statements
49
+ const isConditional = kind === SyntaxKind.IfStatement ||
50
+ kind === SyntaxKind.SwitchStatement ||
51
+ kind === SyntaxKind.ConditionalExpression;
52
+ const newDepth = isConditional ? currentDepth + 1 : currentDepth;
53
+ maxDepth = Math.max(maxDepth, newDepth);
54
+ // Traverse children
55
+ n.forEachChild((child) => traverse(child, newDepth));
56
+ };
57
+ traverse(node, 0);
58
+ return maxDepth;
59
+ }
60
+ getSeverity(depth, threshold) {
61
+ const ratio = depth / threshold;
62
+ if (ratio >= 2.5)
63
+ return SmellSeverity.CRITICAL;
64
+ if (ratio >= 2)
65
+ return SmellSeverity.HIGH;
66
+ if (ratio >= 1.5)
67
+ return SmellSeverity.MEDIUM;
68
+ return SmellSeverity.LOW;
69
+ }
70
+ }
71
+ //# sourceMappingURL=nested-conditionals-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"nested-conditionals-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/nested-conditionals-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * Code Smell Analyzer Module
3
+ */
4
+ export { CodeSmellAnalyzer } from './code-smell-analyzer.js';
5
+ export { BaseSmellDetector } from './base-smell-detector.js';
6
+ export { LongMethodDetector } from './detectors/long-method-detector.js';
7
+ export { LargeClassDetector } from './detectors/large-class-detector.js';
8
+ export { LongParameterListDetector } from './detectors/long-parameter-list-detector.js';
9
+ export { MagicNumbersDetector } from './detectors/magic-numbers-detector.js';
10
+ export { NestedConditionalsDetector } from './detectors/nested-conditionals-detector.js';
11
+ export { DeadCodeDetector } from './detectors/dead-code-detector.js';
12
+ export { DuplicateCodeDetector } from './detectors/duplicate-code-detector.js';
13
+ export { FeatureEnvyDetector } from './detectors/feature-envy-detector.js';
14
+ export { DataClumpsDetector } from './detectors/data-clumps-detector.js';
15
+ export { InappropriateIntimacyDetector } from './detectors/inappropriate-intimacy-detector.js';
16
+ export { SmellType, SmellSeverity, type CodeSmell, type DetectorConfig, type CodeSmellAnalysisOptions, type CodeSmellAnalysisResult, type CodeSmellSummary, type SmellDetector, } from './types.js';
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Code Smell Analyzer Module
3
+ */
4
+ export { CodeSmellAnalyzer } from './code-smell-analyzer.js';
5
+ export { BaseSmellDetector } from './base-smell-detector.js';
6
+ // Detectors
7
+ export { LongMethodDetector } from './detectors/long-method-detector.js';
8
+ export { LargeClassDetector } from './detectors/large-class-detector.js';
9
+ export { LongParameterListDetector } from './detectors/long-parameter-list-detector.js';
10
+ export { MagicNumbersDetector } from './detectors/magic-numbers-detector.js';
11
+ export { NestedConditionalsDetector } from './detectors/nested-conditionals-detector.js';
12
+ export { DeadCodeDetector } from './detectors/dead-code-detector.js';
13
+ export { DuplicateCodeDetector } from './detectors/duplicate-code-detector.js';
14
+ export { FeatureEnvyDetector } from './detectors/feature-envy-detector.js';
15
+ export { DataClumpsDetector } from './detectors/data-clumps-detector.js';
16
+ export { InappropriateIntimacyDetector } from './detectors/inappropriate-intimacy-detector.js';
17
+ // Types
18
+ export { SmellType, SmellSeverity, } from './types.js';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/code-smells/index.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAC7D,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,YAAY;AACZ,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,yBAAyB,EAAE,MAAM,6CAA6C,CAAC;AACxF,OAAO,EAAE,oBAAoB,EAAE,MAAM,uCAAuC,CAAC;AAC7E,OAAO,EAAE,0BAA0B,EAAE,MAAM,6CAA6C,CAAC;AACzF,OAAO,EAAE,gBAAgB,EAAE,MAAM,mCAAmC,CAAC;AACrE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wCAAwC,CAAC;AAC/E,OAAO,EAAE,mBAAmB,EAAE,MAAM,sCAAsC,CAAC;AAC3E,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAC;AACzE,OAAO,EAAE,6BAA6B,EAAE,MAAM,gDAAgD,CAAC;AAE/F,QAAQ;AACR,OAAO,EACL,SAAS,EACT,aAAa,GAOd,MAAM,YAAY,CAAC"}
@@ -0,0 +1,82 @@
1
+ /**
2
+ * Code Smell Detector Types
3
+ */
4
+ /**
5
+ * Type of code smell
6
+ */
7
+ export declare enum SmellType {
8
+ LONG_METHOD = "LONG_METHOD",
9
+ LARGE_CLASS = "LARGE_CLASS",
10
+ LONG_PARAMETER_LIST = "LONG_PARAMETER_LIST",
11
+ DUPLICATE_CODE = "DUPLICATE_CODE",
12
+ DEAD_CODE = "DEAD_CODE",
13
+ MAGIC_NUMBERS = "MAGIC_NUMBERS",
14
+ NESTED_CONDITIONALS = "NESTED_CONDITIONALS",
15
+ FEATURE_ENVY = "FEATURE_ENVY",
16
+ DATA_CLUMPS = "DATA_CLUMPS",
17
+ INAPPROPRIATE_INTIMACY = "INAPPROPRIATE_INTIMACY"
18
+ }
19
+ /**
20
+ * Severity of code smell
21
+ */
22
+ export declare enum SmellSeverity {
23
+ LOW = "LOW",
24
+ MEDIUM = "MEDIUM",
25
+ HIGH = "HIGH",
26
+ CRITICAL = "CRITICAL"
27
+ }
28
+ /**
29
+ * Code smell detection result
30
+ */
31
+ export interface CodeSmell {
32
+ readonly type: SmellType;
33
+ readonly severity: SmellSeverity;
34
+ readonly filePath: string;
35
+ readonly startLine: number;
36
+ readonly endLine: number;
37
+ readonly message: string;
38
+ readonly suggestion: string;
39
+ readonly metadata: Readonly<Record<string, unknown>>;
40
+ }
41
+ /**
42
+ * Detector configuration
43
+ */
44
+ export interface DetectorConfig {
45
+ readonly enabled: boolean;
46
+ readonly thresholds?: Readonly<Record<string, number>>;
47
+ }
48
+ /**
49
+ * Analysis options
50
+ */
51
+ export interface CodeSmellAnalysisOptions {
52
+ readonly detectorConfigs?: Readonly<Record<SmellType, DetectorConfig>>;
53
+ readonly ignorePatterns?: readonly string[];
54
+ }
55
+ /**
56
+ * Analysis result
57
+ */
58
+ export interface CodeSmellAnalysisResult {
59
+ readonly smells: ReadonlyArray<CodeSmell>;
60
+ readonly summary: CodeSmellSummary;
61
+ readonly timestamp: Date;
62
+ }
63
+ /**
64
+ * Summary statistics
65
+ */
66
+ export interface CodeSmellSummary {
67
+ readonly totalSmells: number;
68
+ readonly smellsByType: Readonly<Record<SmellType, number>>;
69
+ readonly smellsBySeverity: Readonly<Record<SmellSeverity, number>>;
70
+ readonly filesAnalyzed: number;
71
+ readonly filesWithSmells: number;
72
+ readonly averageSmellsPerFile: number;
73
+ readonly codeHealthScore: number;
74
+ }
75
+ /**
76
+ * Base detector interface
77
+ */
78
+ export interface SmellDetector {
79
+ readonly type: SmellType;
80
+ readonly config: DetectorConfig;
81
+ detect(filePath: string): Promise<CodeSmell[]>;
82
+ }
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Code Smell Detector Types
3
+ */
4
+ /**
5
+ * Type of code smell
6
+ */
7
+ export var SmellType;
8
+ (function (SmellType) {
9
+ SmellType["LONG_METHOD"] = "LONG_METHOD";
10
+ SmellType["LARGE_CLASS"] = "LARGE_CLASS";
11
+ SmellType["LONG_PARAMETER_LIST"] = "LONG_PARAMETER_LIST";
12
+ SmellType["DUPLICATE_CODE"] = "DUPLICATE_CODE";
13
+ SmellType["DEAD_CODE"] = "DEAD_CODE";
14
+ SmellType["MAGIC_NUMBERS"] = "MAGIC_NUMBERS";
15
+ SmellType["NESTED_CONDITIONALS"] = "NESTED_CONDITIONALS";
16
+ SmellType["FEATURE_ENVY"] = "FEATURE_ENVY";
17
+ SmellType["DATA_CLUMPS"] = "DATA_CLUMPS";
18
+ SmellType["INAPPROPRIATE_INTIMACY"] = "INAPPROPRIATE_INTIMACY";
19
+ })(SmellType || (SmellType = {}));
20
+ /**
21
+ * Severity of code smell
22
+ */
23
+ export var SmellSeverity;
24
+ (function (SmellSeverity) {
25
+ SmellSeverity["LOW"] = "LOW";
26
+ SmellSeverity["MEDIUM"] = "MEDIUM";
27
+ SmellSeverity["HIGH"] = "HIGH";
28
+ SmellSeverity["CRITICAL"] = "CRITICAL";
29
+ })(SmellSeverity || (SmellSeverity = {}));
30
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/analyzers/code-smells/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,MAAM,CAAN,IAAY,SAWX;AAXD,WAAY,SAAS;IACnB,wCAA2B,CAAA;IAC3B,wCAA2B,CAAA;IAC3B,wDAA2C,CAAA;IAC3C,8CAAiC,CAAA;IACjC,oCAAuB,CAAA;IACvB,4CAA+B,CAAA;IAC/B,wDAA2C,CAAA;IAC3C,0CAA6B,CAAA;IAC7B,wCAA2B,CAAA;IAC3B,8DAAiD,CAAA;AACnD,CAAC,EAXW,SAAS,KAAT,SAAS,QAWpB;AAED;;GAEG;AACH,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,4BAAW,CAAA;IACX,kCAAiB,CAAA;IACjB,8BAAa,CAAA;IACb,sCAAqB,CAAA;AACvB,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Circular Dependency Detector
3
+ *
4
+ * Uses Tarjan's Strongly Connected Components algorithm
5
+ */
6
+ import type { DependencyGraph } from './dependency-graph.js';
7
+ import type { CircularDependency } from './types.js';
8
+ export declare class CircularDependencyDetector {
9
+ /**
10
+ * Detect all circular dependencies
11
+ */
12
+ detectCycles(graph: DependencyGraph): CircularDependency[];
13
+ /**
14
+ * Create circular dependency object from SCC
15
+ */
16
+ private createCircularDependency;
17
+ }