@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 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/analyzers/best-practices/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,qBAAqB,EAAE,MAAM,8BAA8B,CAAC;AACrE,OAAO,EAAE,kBAAkB,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEnD,8BAA8B;AAC9B,cAAc,6BAA6B,CAAC"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Base Smell Detector
3
+ *
4
+ * Abstract base class for all smell detectors
5
+ */
6
+ import { ASTParser } from '../ast/parser.js';
7
+ import type { SmellDetector, CodeSmell, SmellType, DetectorConfig } from './types.js';
8
+ import { SmellSeverity } from './types.js';
9
+ export declare abstract class BaseSmellDetector implements SmellDetector {
10
+ readonly type: SmellType;
11
+ readonly config: DetectorConfig;
12
+ protected astParser: ASTParser;
13
+ constructor(type: SmellType, config: DetectorConfig);
14
+ /**
15
+ * Detect smells in a file
16
+ */
17
+ abstract detect(filePath: string): Promise<CodeSmell[]>;
18
+ /**
19
+ * Check if detector is enabled
20
+ */
21
+ protected isEnabled(): boolean;
22
+ /**
23
+ * Get threshold value
24
+ */
25
+ protected getThreshold(key: string, defaultValue: number): number;
26
+ /**
27
+ * Create a code smell object
28
+ */
29
+ protected createSmell(filePath: string, startLine: number, endLine: number, message: string, suggestion: string, severity: SmellSeverity, metadata?: Record<string, unknown>): CodeSmell;
30
+ }
@@ -0,0 +1,44 @@
1
+ /**
2
+ * Base Smell Detector
3
+ *
4
+ * Abstract base class for all smell detectors
5
+ */
6
+ import { ASTParser } from '../ast/parser.js';
7
+ export class BaseSmellDetector {
8
+ type;
9
+ config;
10
+ astParser;
11
+ constructor(type, config) {
12
+ this.type = type;
13
+ this.config = config;
14
+ this.astParser = new ASTParser();
15
+ }
16
+ /**
17
+ * Check if detector is enabled
18
+ */
19
+ isEnabled() {
20
+ return this.config.enabled;
21
+ }
22
+ /**
23
+ * Get threshold value
24
+ */
25
+ getThreshold(key, defaultValue) {
26
+ return this.config.thresholds?.[key] ?? defaultValue;
27
+ }
28
+ /**
29
+ * Create a code smell object
30
+ */
31
+ createSmell(filePath, startLine, endLine, message, suggestion, severity, metadata = {}) {
32
+ return Object.freeze({
33
+ type: this.type,
34
+ severity,
35
+ filePath,
36
+ startLine,
37
+ endLine,
38
+ message,
39
+ suggestion,
40
+ metadata: Object.freeze(metadata),
41
+ });
42
+ }
43
+ }
44
+ //# sourceMappingURL=base-smell-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"base-smell-detector.js","sourceRoot":"","sources":["../../../src/analyzers/code-smells/base-smell-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAI7C,MAAM,OAAgB,iBAAiB;IAInB;IACA;IAJR,SAAS,CAAY;IAE/B,YACkB,IAAe,EACf,MAAsB;QADtB,SAAI,GAAJ,IAAI,CAAW;QACf,WAAM,GAAN,MAAM,CAAgB;QAEtC,IAAI,CAAC,SAAS,GAAG,IAAI,SAAS,EAAE,CAAC;IACnC,CAAC;IAOD;;OAEG;IACO,SAAS;QACjB,OAAO,IAAI,CAAC,MAAM,CAAC,OAAO,CAAC;IAC7B,CAAC;IAED;;OAEG;IACO,YAAY,CAAC,GAAW,EAAE,YAAoB;QACtD,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,GAAG,CAAC,IAAI,YAAY,CAAC;IACvD,CAAC;IAED;;OAEG;IACO,WAAW,CACnB,QAAgB,EAChB,SAAiB,EACjB,OAAe,EACf,OAAe,EACf,UAAkB,EAClB,QAAuB,EACvB,WAAoC,EAAE;QAEtC,OAAO,MAAM,CAAC,MAAM,CAAC;YACnB,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,QAAQ;YACR,QAAQ;YACR,SAAS;YACT,OAAO;YACP,OAAO;YACP,UAAU;YACV,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC;SAClC,CAAC,CAAC;IACL,CAAC;CACF"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Code Smell Analyzer
3
+ *
4
+ * Main orchestrator for code smell detection
5
+ */
6
+ import { type CodeSmell, type CodeSmellAnalysisResult, type CodeSmellAnalysisOptions } from './types.js';
7
+ export declare class CodeSmellAnalyzer {
8
+ private detectors;
9
+ constructor(options?: CodeSmellAnalysisOptions);
10
+ /**
11
+ * Initialize all detectors with configuration
12
+ */
13
+ private initializeDetectors;
14
+ /**
15
+ * Analyze directory for code smells
16
+ */
17
+ analyzeDirectory(directory: string, pattern?: string, options?: CodeSmellAnalysisOptions): Promise<CodeSmellAnalysisResult>;
18
+ /**
19
+ * Analyze single file
20
+ */
21
+ analyzeFile(filePath: string): Promise<CodeSmell[]>;
22
+ /**
23
+ * Calculate summary statistics
24
+ */
25
+ private calculateSummary;
26
+ /**
27
+ * Calculate code health score (0-100)
28
+ */
29
+ private calculateHealthScore;
30
+ }
@@ -0,0 +1,167 @@
1
+ /**
2
+ * Code Smell Analyzer
3
+ *
4
+ * Main orchestrator for code smell detection
5
+ */
6
+ import { glob } from 'glob';
7
+ import { SmellType, SmellSeverity } from './types.js';
8
+ import { LongMethodDetector } from './detectors/long-method-detector.js';
9
+ import { LargeClassDetector } from './detectors/large-class-detector.js';
10
+ import { LongParameterListDetector } from './detectors/long-parameter-list-detector.js';
11
+ import { MagicNumbersDetector } from './detectors/magic-numbers-detector.js';
12
+ import { NestedConditionalsDetector } from './detectors/nested-conditionals-detector.js';
13
+ import { DeadCodeDetector } from './detectors/dead-code-detector.js';
14
+ import { DuplicateCodeDetector } from './detectors/duplicate-code-detector.js';
15
+ import { FeatureEnvyDetector } from './detectors/feature-envy-detector.js';
16
+ import { DataClumpsDetector } from './detectors/data-clumps-detector.js';
17
+ import { InappropriateIntimacyDetector } from './detectors/inappropriate-intimacy-detector.js';
18
+ export class CodeSmellAnalyzer {
19
+ detectors;
20
+ constructor(options = {}) {
21
+ this.detectors = new Map();
22
+ this.initializeDetectors(options);
23
+ }
24
+ /**
25
+ * Initialize all detectors with configuration
26
+ */
27
+ initializeDetectors(options) {
28
+ const defaultConfig = { enabled: true };
29
+ const detectorClasses = [
30
+ LongMethodDetector,
31
+ LargeClassDetector,
32
+ LongParameterListDetector,
33
+ MagicNumbersDetector,
34
+ NestedConditionalsDetector,
35
+ DeadCodeDetector,
36
+ DuplicateCodeDetector,
37
+ FeatureEnvyDetector,
38
+ DataClumpsDetector,
39
+ InappropriateIntimacyDetector,
40
+ ];
41
+ for (const DetectorClass of detectorClasses) {
42
+ const detector = new DetectorClass(defaultConfig);
43
+ const config = options.detectorConfigs?.[detector.type] ?? defaultConfig;
44
+ const configuredDetector = new DetectorClass(config);
45
+ this.detectors.set(configuredDetector.type, configuredDetector);
46
+ }
47
+ }
48
+ /**
49
+ * Analyze directory for code smells
50
+ */
51
+ async analyzeDirectory(directory, pattern = '**/*.{ts,tsx,js,jsx}', options = {}) {
52
+ const timestamp = new Date();
53
+ // Find all files
54
+ const ignorePatterns = [
55
+ '**/node_modules/**',
56
+ '**/dist/**',
57
+ '**/build/**',
58
+ '**/.git/**',
59
+ '**/*.test.{ts,tsx,js,jsx}',
60
+ '**/*.spec.{ts,tsx,js,jsx}',
61
+ ...(options.ignorePatterns || []),
62
+ ];
63
+ const files = await glob(pattern, {
64
+ cwd: directory,
65
+ absolute: true,
66
+ nodir: true,
67
+ ignore: ignorePatterns,
68
+ });
69
+ // Analyze all files
70
+ const allSmells = [];
71
+ const filesWithSmells = new Set();
72
+ for (const file of files) {
73
+ for (const detector of this.detectors.values()) {
74
+ try {
75
+ const smells = await detector.detect(file);
76
+ if (smells.length > 0) {
77
+ allSmells.push(...smells);
78
+ filesWithSmells.add(file);
79
+ }
80
+ }
81
+ catch (error) {
82
+ // Skip detector errors
83
+ console.error(`Error running ${detector.type} on ${file}:`, error);
84
+ }
85
+ }
86
+ }
87
+ // Calculate summary
88
+ const summary = this.calculateSummary(allSmells, files.length, filesWithSmells.size);
89
+ return Object.freeze({
90
+ smells: Object.freeze(allSmells),
91
+ summary: Object.freeze(summary),
92
+ timestamp,
93
+ });
94
+ }
95
+ /**
96
+ * Analyze single file
97
+ */
98
+ async analyzeFile(filePath) {
99
+ const smells = [];
100
+ for (const detector of this.detectors.values()) {
101
+ try {
102
+ const detectedSmells = await detector.detect(filePath);
103
+ smells.push(...detectedSmells);
104
+ }
105
+ catch (error) {
106
+ console.error(`Error running ${detector.type} on ${filePath}:`, error);
107
+ }
108
+ }
109
+ return smells;
110
+ }
111
+ /**
112
+ * Calculate summary statistics
113
+ */
114
+ calculateSummary(smells, totalFiles, filesWithSmells) {
115
+ // Count by type
116
+ const smellsByType = {};
117
+ for (const type of Object.values(SmellType)) {
118
+ smellsByType[type] = 0;
119
+ }
120
+ for (const smell of smells) {
121
+ smellsByType[smell.type]++;
122
+ }
123
+ // Count by severity
124
+ const smellsBySeverity = {};
125
+ for (const severity of Object.values(SmellSeverity)) {
126
+ smellsBySeverity[severity] = 0;
127
+ }
128
+ for (const smell of smells) {
129
+ smellsBySeverity[smell.severity]++;
130
+ }
131
+ // Calculate health score
132
+ const codeHealthScore = this.calculateHealthScore(smells, totalFiles);
133
+ return {
134
+ totalSmells: smells.length,
135
+ smellsByType: Object.freeze(smellsByType),
136
+ smellsBySeverity: Object.freeze(smellsBySeverity),
137
+ filesAnalyzed: totalFiles,
138
+ filesWithSmells,
139
+ averageSmellsPerFile: totalFiles > 0 ? smells.length / totalFiles : 0,
140
+ codeHealthScore,
141
+ };
142
+ }
143
+ /**
144
+ * Calculate code health score (0-100)
145
+ */
146
+ calculateHealthScore(smells, totalFiles) {
147
+ if (totalFiles === 0)
148
+ return 100;
149
+ // Weighted penalties by severity
150
+ const severityWeights = {
151
+ [SmellSeverity.LOW]: 1,
152
+ [SmellSeverity.MEDIUM]: 3,
153
+ [SmellSeverity.HIGH]: 7,
154
+ [SmellSeverity.CRITICAL]: 15,
155
+ };
156
+ let totalPenalty = 0;
157
+ for (const smell of smells) {
158
+ totalPenalty += severityWeights[smell.severity];
159
+ }
160
+ // Normalize penalty per file (penalty per file should reduce score)
161
+ const penaltyPerFile = totalPenalty / totalFiles;
162
+ // Score calculation: 100 - (penalty per file, capped at 100)
163
+ const score = Math.max(0, 100 - Math.min(100, penaltyPerFile * 2));
164
+ return Math.round(score);
165
+ }
166
+ }
167
+ //# sourceMappingURL=code-smell-analyzer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"code-smell-analyzer.js","sourceRoot":"","sources":["../../../src/analyzers/code-smells/code-smell-analyzer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Data Clumps Detector
3
+ *
4
+ * Detects groups of parameters that frequently appear together
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class DataClumpsDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ }
@@ -0,0 +1,66 @@
1
+ /**
2
+ * Data Clumps Detector
3
+ *
4
+ * Detects groups of parameters that frequently appear together
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class DataClumpsDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true, thresholds: { minOccurrences: 3, minParams: 3 } }) {
10
+ super(SmellType.DATA_CLUMPS, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ const minOccurrences = this.getThreshold('minOccurrences', 3);
17
+ const minParams = this.getThreshold('minParams', 3);
18
+ try {
19
+ const ast = this.astParser.parseFile(filePath);
20
+ // Collect parameter combinations
21
+ const paramCombinations = new Map();
22
+ // Check functions
23
+ for (const func of ast.functions) {
24
+ if (func.parameters.length >= minParams) {
25
+ const paramNames = func.parameters.map(p => p.name).sort().join(',');
26
+ if (!paramCombinations.has(paramNames)) {
27
+ paramCombinations.set(paramNames, []);
28
+ }
29
+ paramCombinations.get(paramNames).push({
30
+ location: `function ${func.name}`,
31
+ line: func.startLine,
32
+ params: func.parameters.map(p => p.name),
33
+ });
34
+ }
35
+ }
36
+ // Check methods
37
+ for (const cls of ast.classes) {
38
+ for (const method of cls.methods) {
39
+ if (method.parameters.length >= minParams) {
40
+ const paramNames = method.parameters.map(p => p.name).sort().join(',');
41
+ if (!paramCombinations.has(paramNames)) {
42
+ paramCombinations.set(paramNames, []);
43
+ }
44
+ paramCombinations.get(paramNames).push({
45
+ location: `${cls.name}.${method.name}`,
46
+ line: method.startLine,
47
+ params: method.parameters.map(p => p.name),
48
+ });
49
+ }
50
+ }
51
+ }
52
+ // Report data clumps
53
+ for (const [, occurrences] of paramCombinations.entries()) {
54
+ if (occurrences.length >= minOccurrences) {
55
+ const firstOccurrence = occurrences[0];
56
+ smells.push(this.createSmell(filePath, firstOccurrence.line, firstOccurrence.line, `Data clump detected: Parameters (${firstOccurrence.params.join(', ')}) appear together in ${occurrences.length} locations`, `Consider creating a data class or configuration object to group these related parameters.`, occurrences.length >= 5 ? SmellSeverity.HIGH : SmellSeverity.MEDIUM, { parameters: firstOccurrence.params, occurrences: occurrences.length, locations: occurrences.map(o => o.location) }));
57
+ }
58
+ }
59
+ }
60
+ catch (error) {
61
+ // Skip files that can't be parsed
62
+ }
63
+ return smells;
64
+ }
65
+ }
66
+ //# sourceMappingURL=data-clumps-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"data-clumps-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/data-clumps-detector.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Dead Code Detector
3
+ *
4
+ * Detects unused exports and variables
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class DeadCodeDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ }
@@ -0,0 +1,53 @@
1
+ /**
2
+ * Dead Code Detector
3
+ *
4
+ * Detects unused exports and variables
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class DeadCodeDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true }) {
10
+ super(SmellType.DEAD_CODE, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ try {
17
+ const ast = this.astParser.parseFile(filePath);
18
+ const sourceFile = this.astParser.getSourceFile(filePath);
19
+ // Find all exported symbols
20
+ const exportedSymbols = new Set(ast.exports.map(e => e.name));
21
+ // Find all variable declarations
22
+ const variables = sourceFile.getVariableDeclarations();
23
+ for (const variable of variables) {
24
+ const name = variable.getName();
25
+ // Skip exported variables
26
+ if (exportedSymbols.has(name))
27
+ continue;
28
+ // Check if variable is referenced
29
+ const references = variable.findReferencesAsNodes();
30
+ // If only 1 reference (the declaration itself), it's unused
31
+ if (references.length <= 1) {
32
+ smells.push(this.createSmell(filePath, variable.getStartLineNumber(), variable.getEndLineNumber(), `Unused variable '${name}'`, `Remove this unused variable or export it if needed elsewhere.`, SmellSeverity.LOW, { variableName: name, references: references.length }));
33
+ }
34
+ }
35
+ // Check for unused functions (not exported and not called)
36
+ const functions = sourceFile.getFunctions();
37
+ for (const func of functions) {
38
+ const name = func.getName();
39
+ if (!name || exportedSymbols.has(name))
40
+ continue;
41
+ const references = func.findReferencesAsNodes();
42
+ if (references.length <= 1) {
43
+ smells.push(this.createSmell(filePath, func.getStartLineNumber(), func.getEndLineNumber(), `Unused function '${name}'`, `Remove this unused function or export it if needed.`, SmellSeverity.MEDIUM, { functionName: name, references: references.length }));
44
+ }
45
+ }
46
+ }
47
+ catch (error) {
48
+ // Skip files that can't be parsed
49
+ }
50
+ return smells;
51
+ }
52
+ }
53
+ //# sourceMappingURL=dead-code-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dead-code-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/dead-code-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,gBAAiB,SAAQ,iBAAiB;IACrD,YAAY,SAAyB,EAAE,OAAO,EAAE,IAAI,EAAE;QACpD,KAAK,CAAC,SAAS,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,EAAE,CAAC;QAEjC,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAE1D,4BAA4B;YAC5B,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;YAE9D,iCAAiC;YACjC,MAAM,SAAS,GAAG,UAAU,CAAC,uBAAuB,EAAE,CAAC;YAEvD,KAAK,MAAM,QAAQ,IAAI,SAAS,EAAE,CAAC;gBACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,OAAO,EAAE,CAAC;gBAEhC,0BAA0B;gBAC1B,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAExC,kCAAkC;gBAClC,MAAM,UAAU,GAAG,QAAQ,CAAC,qBAAqB,EAAE,CAAC;gBAEpD,4DAA4D;gBAC5D,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;oBAC3B,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,QAAQ,CAAC,kBAAkB,EAAE,EAC7B,QAAQ,CAAC,gBAAgB,EAAE,EAC3B,oBAAoB,IAAI,GAAG,EAC3B,+DAA+D,EAC/D,aAAa,CAAC,GAAG,EACjB,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,CACtD,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;YAED,2DAA2D;YAC3D,MAAM,SAAS,GAAG,UAAU,CAAC,YAAY,EAAE,CAAC;YAC5C,KAAK,MAAM,IAAI,IAAI,SAAS,EAAE,CAAC;gBAC7B,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;gBAC5B,IAAI,CAAC,IAAI,IAAI,eAAe,CAAC,GAAG,CAAC,IAAI,CAAC;oBAAE,SAAS;gBAEjD,MAAM,UAAU,GAAG,IAAI,CAAC,qBAAqB,EAAE,CAAC;gBAChD,IAAI,UAAU,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;oBAC3B,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,IAAI,CAAC,kBAAkB,EAAE,EACzB,IAAI,CAAC,gBAAgB,EAAE,EACvB,oBAAoB,IAAI,GAAG,EAC3B,qDAAqD,EACrD,aAAa,CAAC,MAAM,EACpB,EAAE,YAAY,EAAE,IAAI,EAAE,UAAU,EAAE,UAAU,CAAC,MAAM,EAAE,CACtD,CACF,CAAC;gBACJ,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kCAAkC;QACpC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Duplicate Code Detector
3
+ *
4
+ * Detects similar code blocks (simplified heuristic-based detection)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class DuplicateCodeDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ }
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Duplicate Code Detector
3
+ *
4
+ * Detects similar code blocks (simplified heuristic-based detection)
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { SmellType, SmellSeverity } from '../types.js';
8
+ export class DuplicateCodeDetector extends BaseSmellDetector {
9
+ constructor(config = { enabled: true, thresholds: { minLines: 5 } }) {
10
+ super(SmellType.DUPLICATE_CODE, config);
11
+ }
12
+ async detect(filePath) {
13
+ if (!this.isEnabled())
14
+ return [];
15
+ const smells = [];
16
+ try {
17
+ const ast = this.astParser.parseFile(filePath);
18
+ // Simplified detection: Check for functions/methods with identical names (potential copy-paste)
19
+ const functionSignatures = new Map();
20
+ // Collect function signatures
21
+ for (const func of ast.functions) {
22
+ const signature = `${func.name}_${func.parameters.length}`;
23
+ if (!functionSignatures.has(signature)) {
24
+ functionSignatures.set(signature, []);
25
+ }
26
+ functionSignatures.get(signature).push({
27
+ name: func.name,
28
+ line: func.startLine,
29
+ params: func.parameters.length,
30
+ });
31
+ }
32
+ // Check for methods with very similar signatures across classes
33
+ const methodMap = new Map();
34
+ for (const cls of ast.classes) {
35
+ for (const method of cls.methods) {
36
+ const key = `${method.name}_${method.parameters.length}`;
37
+ methodMap.set(key, (methodMap.get(key) || 0) + 1);
38
+ // If same method appears in multiple classes, might be code duplication
39
+ if (methodMap.get(key) > 1) {
40
+ smells.push(this.createSmell(filePath, method.startLine, method.endLine, `Potential code duplication: Method '${method.name}' with ${method.parameters.length} parameters appears in multiple classes`, `Consider extracting common logic into a shared utility function or base class.`, SmellSeverity.MEDIUM, { methodName: method.name, occurrences: methodMap.get(key) }));
41
+ }
42
+ }
43
+ }
44
+ }
45
+ catch (error) {
46
+ // Skip files that can't be parsed
47
+ }
48
+ return smells;
49
+ }
50
+ }
51
+ //# sourceMappingURL=duplicate-code-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"duplicate-code-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/duplicate-code-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,qBAAsB,SAAQ,iBAAiB;IAC1D,YAAY,SAAyB,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,EAAE;QACjF,KAAK,CAAC,SAAS,CAAC,cAAc,EAAE,MAAM,CAAC,CAAC;IAC1C,CAAC;IAED,KAAK,CAAC,MAAM,CAAC,QAAgB;QAC3B,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE;YAAE,OAAO,EAAE,CAAC;QAEjC,MAAM,MAAM,GAAgB,EAAE,CAAC;QAE/B,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,SAAS,CAAC,QAAQ,CAAC,CAAC;YAE/C,gGAAgG;YAChG,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAiE,CAAC;YAEpG,8BAA8B;YAC9B,KAAK,MAAM,IAAI,IAAI,GAAG,CAAC,SAAS,EAAE,CAAC;gBACjC,MAAM,SAAS,GAAG,GAAG,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;gBAC3D,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACvC,kBAAkB,CAAC,GAAG,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;gBACxC,CAAC;gBACD,kBAAkB,CAAC,GAAG,CAAC,SAAS,CAAE,CAAC,IAAI,CAAC;oBACtC,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,IAAI,CAAC,SAAS;oBACpB,MAAM,EAAE,IAAI,CAAC,UAAU,CAAC,MAAM;iBAC/B,CAAC,CAAC;YACL,CAAC;YAED,gEAAgE;YAChE,MAAM,SAAS,GAAG,IAAI,GAAG,EAAkB,CAAC;YAC5C,KAAK,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;gBAC9B,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,OAAO,EAAE,CAAC;oBACjC,MAAM,GAAG,GAAG,GAAG,MAAM,CAAC,IAAI,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,EAAE,CAAC;oBACzD,SAAS,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;oBAElD,wEAAwE;oBACxE,IAAI,SAAS,CAAC,GAAG,CAAC,GAAG,CAAE,GAAG,CAAC,EAAE,CAAC;wBAC5B,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,MAAM,CAAC,SAAS,EAChB,MAAM,CAAC,OAAO,EACd,uCAAuC,MAAM,CAAC,IAAI,UAAU,MAAM,CAAC,UAAU,CAAC,MAAM,yCAAyC,EAC7H,gFAAgF,EAChF,aAAa,CAAC,MAAM,EACpB,EAAE,UAAU,EAAE,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,SAAS,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAC7D,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;CACF"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Feature Envy Detector
3
+ *
4
+ * Detects methods that use more features from other classes than their own
5
+ */
6
+ import { BaseSmellDetector } from '../base-smell-detector.js';
7
+ import { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class FeatureEnvyDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * Feature Envy Detector
3
+ *
4
+ * Detects methods that use more features from other classes than their own
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 FeatureEnvyDetector extends BaseSmellDetector {
10
+ constructor(config = { enabled: true, thresholds: { ratio: 0.7 } }) {
11
+ super(SmellType.FEATURE_ENVY, config);
12
+ }
13
+ async detect(filePath) {
14
+ if (!this.isEnabled())
15
+ return [];
16
+ const smells = [];
17
+ const envyRatio = this.getThreshold('ratio', 0.7);
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 classProperties = new Set(cls.getProperties().map(p => p.getName()));
24
+ for (const method of cls.getMethods()) {
25
+ const methodName = method.getName();
26
+ let ownPropertyAccess = 0;
27
+ let externalPropertyAccess = 0;
28
+ // Count property accesses
29
+ method.forEachDescendant((node) => {
30
+ if (node.getKind() === SyntaxKind.PropertyAccessExpression) {
31
+ const text = node.getText();
32
+ // Check if accessing own property
33
+ if (text.startsWith('this.')) {
34
+ const propName = text.slice(5).split('.')[0];
35
+ if (classProperties.has(propName)) {
36
+ ownPropertyAccess++;
37
+ }
38
+ else {
39
+ externalPropertyAccess++;
40
+ }
41
+ }
42
+ else {
43
+ externalPropertyAccess++;
44
+ }
45
+ }
46
+ });
47
+ const totalAccess = ownPropertyAccess + externalPropertyAccess;
48
+ if (totalAccess > 5) {
49
+ // Only check if significant number of accesses
50
+ const externalRatio = externalPropertyAccess / totalAccess;
51
+ if (externalRatio >= envyRatio) {
52
+ smells.push(this.createSmell(filePath, method.getStartLineNumber(), method.getEndLineNumber(), `Method '${className}.${methodName}' exhibits feature envy (${Math.round(externalRatio * 100)}% external access)`, `This method accesses more external properties than its own. Consider moving this logic to the class it's most interested in.`, externalRatio >= 0.9 ? SmellSeverity.HIGH : SmellSeverity.MEDIUM, { className, methodName, ownAccess: ownPropertyAccess, externalAccess: externalPropertyAccess }));
53
+ }
54
+ }
55
+ }
56
+ }
57
+ }
58
+ catch (error) {
59
+ // Skip files that can't be parsed
60
+ }
61
+ return smells;
62
+ }
63
+ }
64
+ //# sourceMappingURL=feature-envy-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-envy-detector.js","sourceRoot":"","sources":["../../../../src/analyzers/code-smells/detectors/feature-envy-detector.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,SAAS,EAAE,aAAa,EAAuC,MAAM,aAAa,CAAC;AAC5F,OAAO,EAAE,UAAU,EAAE,MAAM,UAAU,CAAC;AAEtC,MAAM,OAAO,mBAAoB,SAAQ,iBAAiB;IACxD,YAAY,SAAyB,EAAE,OAAO,EAAE,IAAI,EAAE,UAAU,EAAE,EAAE,KAAK,EAAE,GAAG,EAAE,EAAE;QAChF,KAAK,CAAC,SAAS,CAAC,YAAY,EAAE,MAAM,CAAC,CAAC;IACxC,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,OAAO,EAAE,GAAG,CAAC,CAAC;QAElD,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,aAAa,CAAC,QAAQ,CAAC,CAAC;YAC1D,MAAM,OAAO,GAAG,UAAU,CAAC,UAAU,EAAE,CAAC;YAExC,KAAK,MAAM,GAAG,IAAI,OAAO,EAAE,CAAC;gBAC1B,MAAM,SAAS,GAAG,GAAG,CAAC,OAAO,EAAE,IAAI,WAAW,CAAC;gBAC/C,MAAM,eAAe,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;gBAE3E,KAAK,MAAM,MAAM,IAAI,GAAG,CAAC,UAAU,EAAE,EAAE,CAAC;oBACtC,MAAM,UAAU,GAAG,MAAM,CAAC,OAAO,EAAE,CAAC;oBACpC,IAAI,iBAAiB,GAAG,CAAC,CAAC;oBAC1B,IAAI,sBAAsB,GAAG,CAAC,CAAC;oBAE/B,0BAA0B;oBAC1B,MAAM,CAAC,iBAAiB,CAAC,CAAC,IAAI,EAAE,EAAE;wBAChC,IAAI,IAAI,CAAC,OAAO,EAAE,KAAK,UAAU,CAAC,wBAAwB,EAAE,CAAC;4BAC3D,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,EAAE,CAAC;4BAE5B,kCAAkC;4BAClC,IAAI,IAAI,CAAC,UAAU,CAAC,OAAO,CAAC,EAAE,CAAC;gCAC7B,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;gCAC7C,IAAI,eAAe,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;oCAClC,iBAAiB,EAAE,CAAC;gCACtB,CAAC;qCAAM,CAAC;oCACN,sBAAsB,EAAE,CAAC;gCAC3B,CAAC;4BACH,CAAC;iCAAM,CAAC;gCACN,sBAAsB,EAAE,CAAC;4BAC3B,CAAC;wBACH,CAAC;oBACH,CAAC,CAAC,CAAC;oBAEH,MAAM,WAAW,GAAG,iBAAiB,GAAG,sBAAsB,CAAC;oBAC/D,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;wBACpB,+CAA+C;wBAC/C,MAAM,aAAa,GAAG,sBAAsB,GAAG,WAAW,CAAC;wBAE3D,IAAI,aAAa,IAAI,SAAS,EAAE,CAAC;4BAC/B,MAAM,CAAC,IAAI,CACT,IAAI,CAAC,WAAW,CACd,QAAQ,EACR,MAAM,CAAC,kBAAkB,EAAE,EAC3B,MAAM,CAAC,gBAAgB,EAAE,EACzB,WAAW,SAAS,IAAI,UAAU,4BAA4B,IAAI,CAAC,KAAK,CAAC,aAAa,GAAG,GAAG,CAAC,oBAAoB,EACjH,8HAA8H,EAC9H,aAAa,IAAI,GAAG,CAAC,CAAC,CAAC,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,aAAa,CAAC,MAAM,EAChE,EAAE,SAAS,EAAE,UAAU,EAAE,SAAS,EAAE,iBAAiB,EAAE,cAAc,EAAE,sBAAsB,EAAE,CAChG,CACF,CAAC;wBACJ,CAAC;oBACH,CAAC;gBACH,CAAC;YACH,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,kCAAkC;QACpC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;CACF"}
@@ -0,0 +1,11 @@
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 { type CodeSmell, type DetectorConfig } from '../types.js';
8
+ export declare class InappropriateIntimacyDetector extends BaseSmellDetector {
9
+ constructor(config?: DetectorConfig);
10
+ detect(filePath: string): Promise<CodeSmell[]>;
11
+ }