api-tests-coverage 1.0.16 → 1.0.18

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 (135) hide show
  1. package/dist/dashboard/dist/assets/_basePickBy-CYB1KXah.js +1 -0
  2. package/dist/dashboard/dist/assets/_baseUniq-Bwm426M6.js +1 -0
  3. package/dist/dashboard/dist/assets/arc-B7p8x22e.js +1 -0
  4. package/dist/dashboard/dist/assets/architectureDiagram-VXUJARFQ-wVr1_uNB.js +36 -0
  5. package/dist/dashboard/dist/assets/blockDiagram-VD42YOAC-BBXc88fn.js +122 -0
  6. package/dist/dashboard/dist/assets/c4Diagram-YG6GDRKO-BsgzPfQ3.js +10 -0
  7. package/dist/dashboard/dist/assets/channel-psxgcQ_j.js +1 -0
  8. package/dist/dashboard/dist/assets/chunk-4BX2VUAB-BF8loPLD.js +1 -0
  9. package/dist/dashboard/dist/assets/chunk-55IACEB6-C3HNF-UF.js +1 -0
  10. package/dist/dashboard/dist/assets/chunk-B4BG7PRW-wQ6TCEMq.js +165 -0
  11. package/dist/dashboard/dist/assets/chunk-DI55MBZ5-B7xHuqZu.js +220 -0
  12. package/dist/dashboard/dist/assets/chunk-FMBD7UC4-K3PC79JF.js +15 -0
  13. package/dist/dashboard/dist/assets/chunk-QN33PNHL-CmeZ1h1Z.js +1 -0
  14. package/dist/dashboard/dist/assets/chunk-QZHKN3VN-Cyg7Km90.js +1 -0
  15. package/dist/dashboard/dist/assets/chunk-TZMSLE5B-C8KNXDi7.js +1 -0
  16. package/dist/dashboard/dist/assets/classDiagram-2ON5EDUG-AMwn99HP.js +1 -0
  17. package/dist/dashboard/dist/assets/classDiagram-v2-WZHVMYZB-AMwn99HP.js +1 -0
  18. package/dist/dashboard/dist/assets/clone-KEkbvJY9.js +1 -0
  19. package/dist/dashboard/dist/assets/cose-bilkent-S5V4N54A-YL9kFxCl.js +1 -0
  20. package/dist/dashboard/dist/assets/dagre-6UL2VRFP-NZWnQN_Y.js +4 -0
  21. package/dist/dashboard/dist/assets/diagram-PSM6KHXK-DGtyS7lD.js +24 -0
  22. package/dist/dashboard/dist/assets/diagram-QEK2KX5R-CSCGZUfr.js +43 -0
  23. package/dist/dashboard/dist/assets/diagram-S2PKOQOG-DdqZVGN1.js +24 -0
  24. package/dist/dashboard/dist/assets/erDiagram-Q2GNP2WA-Dhb_VQMS.js +60 -0
  25. package/dist/dashboard/dist/assets/flowDiagram-NV44I4VS-gKUH-GJ2.js +162 -0
  26. package/dist/dashboard/dist/assets/ganttDiagram-JELNMOA3-Dm_lLo9y.js +267 -0
  27. package/dist/dashboard/dist/assets/gitGraphDiagram-V2S2FVAM-DM9AW1aP.js +65 -0
  28. package/dist/dashboard/dist/assets/graph-Clj85F2M.js +1 -0
  29. package/dist/dashboard/dist/assets/index-CqEIqNus.js +781 -0
  30. package/dist/dashboard/dist/assets/index-xecKLQ58.css +1 -0
  31. package/dist/dashboard/dist/assets/infoDiagram-HS3SLOUP-BMp4C5wf.js +2 -0
  32. package/dist/dashboard/dist/assets/journeyDiagram-XKPGCS4Q-BC0GSZ7W.js +139 -0
  33. package/dist/dashboard/dist/assets/kanban-definition-3W4ZIXB7-D6aRd_q1.js +89 -0
  34. package/dist/dashboard/dist/assets/layout-BbJNDkTr.js +1 -0
  35. package/dist/dashboard/dist/assets/mindmap-definition-VGOIOE7T-B93XW27v.js +68 -0
  36. package/dist/dashboard/dist/assets/pieDiagram-ADFJNKIX-9G1tEuaq.js +30 -0
  37. package/dist/dashboard/dist/assets/quadrantDiagram-AYHSOK5B-jDtdB4Ws.js +7 -0
  38. package/dist/dashboard/dist/assets/requirementDiagram-UZGBJVZJ-WIJ0qiJG.js +64 -0
  39. package/dist/dashboard/dist/assets/sankeyDiagram-TZEHDZUN-Cb4WB9UB.js +10 -0
  40. package/dist/dashboard/dist/assets/sequenceDiagram-WL72ISMW-BqGJWVUS.js +145 -0
  41. package/dist/dashboard/dist/assets/stateDiagram-FKZM4ZOC-0Wd-KmOv.js +1 -0
  42. package/dist/dashboard/dist/assets/stateDiagram-v2-4FDKWEC3-BlwaoFEG.js +1 -0
  43. package/dist/dashboard/dist/assets/timeline-definition-IT6M3QCI-CAmQOjBu.js +61 -0
  44. package/dist/dashboard/dist/assets/treemap-GDKQZRPO-CRP-WvE-.js +162 -0
  45. package/dist/dashboard/dist/assets/xychartDiagram-PRI3JC2R-5DoR2_q5.js +7 -0
  46. package/dist/dashboard/dist/index.html +2 -2
  47. package/dist/src/config/defaultConfig.d.ts.map +1 -1
  48. package/dist/src/config/defaultConfig.js +37 -0
  49. package/dist/src/config/types.d.ts +42 -0
  50. package/dist/src/config/types.d.ts.map +1 -1
  51. package/dist/src/config/validateConfig.d.ts.map +1 -1
  52. package/dist/src/config/validateConfig.js +3 -0
  53. package/dist/src/discovery/fileClassifier.d.ts.map +1 -1
  54. package/dist/src/discovery/fileClassifier.js +15 -16
  55. package/dist/src/discovery/projectDiscovery.d.ts.map +1 -1
  56. package/dist/src/discovery/projectDiscovery.js +4 -1
  57. package/dist/src/generation/ai-flow-exporter.d.ts +7 -0
  58. package/dist/src/generation/ai-flow-exporter.d.ts.map +1 -0
  59. package/dist/src/generation/ai-flow-exporter.js +260 -0
  60. package/dist/src/generation/context-builder.d.ts +16 -0
  61. package/dist/src/generation/context-builder.d.ts.map +1 -0
  62. package/dist/src/generation/context-builder.js +170 -0
  63. package/dist/src/generation/engine.d.ts +19 -0
  64. package/dist/src/generation/engine.d.ts.map +1 -0
  65. package/dist/src/generation/engine.js +204 -0
  66. package/dist/src/generation/file-router.d.ts +8 -0
  67. package/dist/src/generation/file-router.d.ts.map +1 -0
  68. package/dist/src/generation/file-router.js +98 -0
  69. package/dist/src/generation/gap-extractor.d.ts +7 -0
  70. package/dist/src/generation/gap-extractor.d.ts.map +1 -0
  71. package/dist/src/generation/gap-extractor.js +291 -0
  72. package/dist/src/generation/index.d.ts +9 -0
  73. package/dist/src/generation/index.d.ts.map +1 -0
  74. package/dist/src/generation/index.js +15 -0
  75. package/dist/src/generation/quality-scorer.d.ts +15 -0
  76. package/dist/src/generation/quality-scorer.d.ts.map +1 -0
  77. package/dist/src/generation/quality-scorer.js +273 -0
  78. package/dist/src/generation/template-renderer.d.ts +12 -0
  79. package/dist/src/generation/template-renderer.d.ts.map +1 -0
  80. package/dist/src/generation/template-renderer.js +546 -0
  81. package/dist/src/generation/types.d.ts +269 -0
  82. package/dist/src/generation/types.d.ts.map +1 -0
  83. package/dist/src/generation/types.js +6 -0
  84. package/dist/src/index.js +113 -0
  85. package/dist/src/languages/java/semanticBuilder.d.ts.map +1 -1
  86. package/dist/src/languages/java/semanticBuilder.js +69 -12
  87. package/dist/src/languages/javascript/angularDetector.d.ts.map +1 -1
  88. package/dist/src/languages/javascript/angularDetector.js +50 -17
  89. package/dist/src/languages/javascript/assertionResolver.js +6 -4
  90. package/dist/src/languages/javascript/hapiDetector.d.ts.map +1 -1
  91. package/dist/src/languages/javascript/hapiDetector.js +48 -5
  92. package/dist/src/languages/javascript/vueDetector.d.ts +2 -0
  93. package/dist/src/languages/javascript/vueDetector.d.ts.map +1 -1
  94. package/dist/src/languages/javascript/vueDetector.js +22 -0
  95. package/dist/src/languages/python/index.d.ts +1 -1
  96. package/dist/src/languages/python/index.d.ts.map +1 -1
  97. package/dist/src/languages/python/index.js +33 -3
  98. package/dist/src/pipeline/confidence.d.ts +6 -1
  99. package/dist/src/pipeline/confidence.d.ts.map +1 -1
  100. package/dist/src/pipeline/confidence.js +8 -3
  101. package/dist/src/pipeline/graph.d.ts.map +1 -1
  102. package/dist/src/pipeline/graph.js +16 -4
  103. package/dist/src/pipeline/stages/ast/astStage.d.ts.map +1 -1
  104. package/dist/src/pipeline/stages/ast/astStage.js +46 -2
  105. package/dist/src/pipeline/stages/ast/baseUrlComposer.d.ts.map +1 -1
  106. package/dist/src/pipeline/stages/ast/baseUrlComposer.js +18 -4
  107. package/dist/src/pipeline/stages/ast/crossFileResolver.js +29 -0
  108. package/dist/src/pipeline/stages/ast/graphBuilder.d.ts.map +1 -1
  109. package/dist/src/pipeline/stages/ast/graphBuilder.js +81 -0
  110. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts +3 -1
  111. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.d.ts.map +1 -1
  112. package/dist/src/pipeline/stages/ast/optionalAuthUnifier.js +34 -14
  113. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.d.ts.map +1 -1
  114. package/dist/src/pipeline/stages/ast/resolvers/angularInjectionResolver.js +22 -3
  115. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.d.ts.map +1 -1
  116. package/dist/src/pipeline/stages/ast/resolvers/dddLayerResolver.js +104 -28
  117. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.d.ts.map +1 -1
  118. package/dist/src/pipeline/stages/ast/resolvers/mybatisResolver.js +56 -0
  119. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.d.ts.map +1 -1
  120. package/dist/src/pipeline/stages/ast/resolvers/vuexActionResolver.js +43 -18
  121. package/dist/src/pipeline/stages/ast/rulesEnforcer.d.ts.map +1 -1
  122. package/dist/src/pipeline/stages/ast/rulesEnforcer.js +336 -45
  123. package/dist/src/pipeline/stages/merge/conflictDetector.d.ts +2 -0
  124. package/dist/src/pipeline/stages/merge/conflictDetector.d.ts.map +1 -1
  125. package/dist/src/pipeline/stages/merge/conflictDetector.js +54 -2
  126. package/dist/src/pipeline/stages/merge/coverageMappingBuilder.d.ts.map +1 -1
  127. package/dist/src/pipeline/stages/merge/coverageMappingBuilder.js +67 -3
  128. package/dist/src/pipeline/stages/tia/mockBoundaryDetector.d.ts.map +1 -1
  129. package/dist/src/pipeline/stages/tia/mockBoundaryDetector.js +8 -1
  130. package/dist/src/pipeline/stages/tia/parameterizedTestExpander.js +8 -4
  131. package/dist/src/pipeline/stages/tia/testLayerClassifier.d.ts.map +1 -1
  132. package/dist/src/pipeline/stages/tia/testLayerClassifier.js +36 -10
  133. package/dist/src/pipeline/types.d.ts +1 -1
  134. package/dist/src/pipeline/types.d.ts.map +1 -1
  135. package/package.json +3 -3
@@ -0,0 +1,269 @@
1
+ /**
2
+ * Feature 28 — Test Generation & Quality Intelligence Engine
3
+ * Type definitions for the test generation pipeline.
4
+ */
5
+ export type GapType = 'endpoint' | 'parameter' | 'error' | 'business' | 'integration' | 'security' | 'auth';
6
+ export type GapPriority = 'P0' | 'P1' | 'P2' | 'P3' | 'P4' | 'P5';
7
+ export type TestType = 'unit' | 'integration' | 'cypress' | 'security';
8
+ export type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH' | 'HEAD' | 'OPTIONS';
9
+ export type AuthType = 'jwt' | 'basic' | 'oauth2' | 'apikey';
10
+ export type ParameterLocation = 'query' | 'path' | 'header' | 'body';
11
+ export type MissingCase = 'boundary-min' | 'boundary-max' | 'invalid-type' | 'missing-required' | 'sql-injection' | 'xss';
12
+ export type SecurityControlType = 'sql-injection' | 'xss' | 'auth-bypass' | 'rate-limit' | 'mass-assignment';
13
+ export type FileNamingConvention = 'kebab' | 'camelCase' | 'snake_case';
14
+ export interface DetectedGap {
15
+ id: string;
16
+ type: GapType;
17
+ priority: GapPriority;
18
+ riskScore: number;
19
+ endpoint: {
20
+ method: HttpMethod;
21
+ path: string;
22
+ operationId?: string;
23
+ summary?: string;
24
+ tags?: string[];
25
+ auth: {
26
+ required: boolean;
27
+ optional: boolean;
28
+ type?: AuthType;
29
+ headerName?: string;
30
+ scheme?: string;
31
+ };
32
+ };
33
+ parameters?: ParameterInfo[];
34
+ responses?: ResponseInfo[];
35
+ businessRule?: BusinessRuleInfo;
36
+ securityControl?: SecurityControlInfo;
37
+ flow?: FlowInfo;
38
+ }
39
+ export interface ParameterInfo {
40
+ name: string;
41
+ in: ParameterLocation;
42
+ required: boolean;
43
+ schema: {
44
+ type: string;
45
+ format?: string;
46
+ minimum?: number;
47
+ maximum?: number;
48
+ minLength?: number;
49
+ maxLength?: number;
50
+ enum?: unknown[];
51
+ pattern?: string;
52
+ };
53
+ missingCases: MissingCase[];
54
+ }
55
+ export interface ResponseInfo {
56
+ statusCode: number;
57
+ description?: string;
58
+ schema?: unknown;
59
+ }
60
+ export interface BusinessRuleInfo {
61
+ id: string;
62
+ description: string;
63
+ condition: string;
64
+ acceptanceCriteria: string[];
65
+ }
66
+ export interface SecurityControlInfo {
67
+ type: SecurityControlType;
68
+ description: string;
69
+ attackVector: string;
70
+ expectedStatusCode: number;
71
+ }
72
+ export interface FlowInfo {
73
+ id: string;
74
+ name: string;
75
+ steps: Array<{
76
+ method: string;
77
+ path: string;
78
+ description: string;
79
+ }>;
80
+ missingStepIndex: number;
81
+ }
82
+ export interface GenerationContext {
83
+ gap: {
84
+ id: string;
85
+ type: GapType;
86
+ priority: GapPriority;
87
+ riskScore: number;
88
+ };
89
+ endpoint: {
90
+ method: string;
91
+ path: string;
92
+ pathNormalized: string;
93
+ operationId?: string;
94
+ summary?: string;
95
+ tags?: string[];
96
+ auth: {
97
+ required: boolean;
98
+ optional: boolean;
99
+ type?: AuthType;
100
+ headerName?: string;
101
+ scheme?: string;
102
+ };
103
+ };
104
+ parameters: ParameterInfo[];
105
+ responses: ResponseInfo[];
106
+ fixtures: {
107
+ validPayload: Record<string, unknown>;
108
+ invalidPayload: Record<string, unknown>;
109
+ authToken: string;
110
+ pathParams: Record<string, string>;
111
+ };
112
+ project: {
113
+ name: string;
114
+ language: string;
115
+ framework: string;
116
+ testFramework: string;
117
+ baseUrl: string;
118
+ importPrefix: string;
119
+ };
120
+ businessRule?: BusinessRuleInfo;
121
+ securityControl?: SecurityControlInfo;
122
+ flow?: FlowInfo;
123
+ }
124
+ export interface GeneratedFile {
125
+ gapId: string;
126
+ filePath: string;
127
+ relativePath: string;
128
+ content: string;
129
+ testType: TestType;
130
+ language: string;
131
+ framework: string;
132
+ }
133
+ export interface GenerationResult {
134
+ files: GeneratedFile[];
135
+ dryRun: boolean;
136
+ totalGaps: number;
137
+ generatedCount: number;
138
+ skippedCount: number;
139
+ errors: Array<{
140
+ gapId: string;
141
+ message: string;
142
+ }>;
143
+ }
144
+ export interface GenerationOptions {
145
+ reportsDir: string;
146
+ outDir: string;
147
+ language?: string;
148
+ framework?: string;
149
+ priority?: GapPriority;
150
+ dryRun?: boolean;
151
+ overwrite?: boolean;
152
+ gapId?: string;
153
+ types?: GapType[];
154
+ noSecurity?: boolean;
155
+ noCypress?: boolean;
156
+ }
157
+ export interface QualityDimensions {
158
+ assertionDepth: number;
159
+ negativePathCoverage: number;
160
+ authCoverage: number;
161
+ boundaryCoverage: number;
162
+ testIndependence: number;
163
+ }
164
+ export interface FileQualityScore {
165
+ file: string;
166
+ score: number;
167
+ dimensions: QualityDimensions;
168
+ issues: string[];
169
+ strengths: string[];
170
+ }
171
+ export interface HighRiskLowQualityGap {
172
+ endpoint: string;
173
+ qualityScore: number;
174
+ riskScore: number;
175
+ primaryIssue: string;
176
+ }
177
+ export interface TestQualityReport {
178
+ overallScore: number;
179
+ byFile: FileQualityScore[];
180
+ lowestQualityFiles: string[];
181
+ highestRiskLowQualityGaps: HighRiskLowQualityGap[];
182
+ }
183
+ export interface QualityScorerOptions {
184
+ testsGlob?: string;
185
+ reportsDir?: string;
186
+ failBelow?: number;
187
+ }
188
+ export interface MissingTestCase {
189
+ id: string;
190
+ description: string;
191
+ expectedStatus: number;
192
+ }
193
+ export interface AiFlowGap {
194
+ gapId: string;
195
+ priority: GapPriority;
196
+ riskScore: number;
197
+ type: GapType;
198
+ endpoint: {
199
+ method: string;
200
+ path: string;
201
+ auth: {
202
+ required: boolean;
203
+ type?: AuthType;
204
+ scheme?: string;
205
+ };
206
+ };
207
+ missingTestCases: MissingTestCase[];
208
+ requestSchema?: unknown;
209
+ responseSchema?: unknown;
210
+ copilotPrompt: string;
211
+ suggestedOutputPath: string;
212
+ existingSimilarTests: string[];
213
+ generatedCode?: string;
214
+ }
215
+ export interface AiReadyFlows {
216
+ generatedAt: string;
217
+ project: {
218
+ name: string;
219
+ language: string;
220
+ testFramework: string;
221
+ appImportPath: string;
222
+ };
223
+ gaps: AiFlowGap[];
224
+ }
225
+ export interface AiFlowExporterOptions {
226
+ reportsDir: string;
227
+ outDir: string;
228
+ format?: 'markdown' | 'json' | 'both';
229
+ maxGaps?: number;
230
+ priority?: GapPriority;
231
+ }
232
+ export interface GenerationConfig {
233
+ enabled?: boolean;
234
+ outputDir?: string;
235
+ dryRun?: boolean;
236
+ overwrite?: boolean;
237
+ minPriority?: GapPriority;
238
+ unitFramework?: string;
239
+ integrationFramework?: string;
240
+ e2eFramework?: string;
241
+ fileNaming?: FileNamingConvention;
242
+ includeTypes?: GapType[];
243
+ securityTests?: {
244
+ enabled?: boolean;
245
+ includeInjection?: boolean;
246
+ includeAuthBypass?: boolean;
247
+ includeRateLimit?: boolean;
248
+ };
249
+ fixtures?: {
250
+ authTokenPlaceholder?: string;
251
+ baseUrl?: string;
252
+ };
253
+ }
254
+ export interface TestQualityConfig {
255
+ enabled?: boolean;
256
+ minimumScore?: number;
257
+ enforceOnGlob?: string;
258
+ excludeGlob?: string;
259
+ outputPath?: string;
260
+ }
261
+ export interface AiFlowsConfig {
262
+ enabled?: boolean;
263
+ outputDir?: string;
264
+ maxGapsPerExport?: number;
265
+ minPriority?: GapPriority;
266
+ includeGeneratedCode?: boolean;
267
+ copilotPromptMaxTokens?: number;
268
+ }
269
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/generation/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ /**
3
+ * Feature 28 — Test Generation & Quality Intelligence Engine
4
+ * Type definitions for the test generation pipeline.
5
+ */
6
+ Object.defineProperty(exports, "__esModule", { value: true });
package/dist/src/index.js CHANGED
@@ -63,6 +63,7 @@ const integrationFlowInference_1 = require("./inference/integrationFlowInference
63
63
  const routeInference_1 = require("./inference/routeInference");
64
64
  const scanManifest_1 = require("./inference/scanManifest");
65
65
  const serveDashboard_1 = require("./serveDashboard");
66
+ const index_4 = require("./generation/index");
66
67
  // Register all language AST analyzers at startup.
67
68
  // This side-effect import ensures each language module's registerAnalyzer() call runs.
68
69
  (0, astAnalysisOrchestrator_1.registerAllAnalyzers)();
@@ -2044,6 +2045,118 @@ program
2044
2045
  });
2045
2046
  // Keep the process alive while the server runs
2046
2047
  });
2048
+ program
2049
+ .command('generate-tests')
2050
+ .description('Generate test scaffolds for detected coverage gaps')
2051
+ .option('--reports-dir <dir>', 'Directory with coverage reports', 'reports/')
2052
+ .option('--out-dir <dir>', 'Output directory for generated tests', 'generated-tests/')
2053
+ .option('--language <lang>', 'Target language override (auto-detected if omitted)')
2054
+ .option('--framework <fw>', 'Test framework override (auto-detected if omitted)')
2055
+ .option('--priority <p>', 'Only generate for gaps at this priority or higher', 'P1')
2056
+ .option('--dry-run', 'Print generated tests to stdout, do not write files', false)
2057
+ .option('--overwrite', 'Overwrite existing generated files', false)
2058
+ .option('--gap-id <id>', 'Generate tests for a single specific gap')
2059
+ .option('--types <list>', 'Comma-separated gap types to generate (default: all)')
2060
+ .option('--no-security', 'Skip security test generation')
2061
+ .option('--no-cypress', 'Skip Cypress test generation')
2062
+ .action(async (options) => {
2063
+ const types = options.types
2064
+ ? options.types.split(',').map(t => t.trim())
2065
+ : undefined;
2066
+ const result = await (0, index_4.generateTests)({
2067
+ reportsDir: options.reportsDir,
2068
+ outDir: options.outDir,
2069
+ language: options.language,
2070
+ framework: options.framework,
2071
+ priority: options.priority,
2072
+ dryRun: Boolean(options.dryRun),
2073
+ overwrite: Boolean(options.overwrite),
2074
+ gapId: options.gapId,
2075
+ types,
2076
+ noSecurity: Boolean(options.noSecurity),
2077
+ noCypress: Boolean(options.noCypress),
2078
+ });
2079
+ if (result.dryRun) {
2080
+ for (const file of result.files) {
2081
+ console.log(`\n${'='.repeat(60)}`);
2082
+ console.log(`// FILE: ${file.relativePath}`);
2083
+ console.log(`${'='.repeat(60)}`);
2084
+ console.log(file.content);
2085
+ }
2086
+ }
2087
+ else {
2088
+ console.log(`\nTest generation complete:`);
2089
+ console.log(` Gaps processed: ${result.totalGaps}`);
2090
+ console.log(` Files generated: ${result.generatedCount}`);
2091
+ console.log(` Errors: ${result.errors.length}`);
2092
+ if (result.errors.length > 0) {
2093
+ for (const err of result.errors) {
2094
+ console.error(` ERROR [${err.gapId}]: ${err.message}`);
2095
+ }
2096
+ }
2097
+ }
2098
+ });
2099
+ program
2100
+ .command('export-ai-flows')
2101
+ .description('Export AI-ready flow documentation for Copilot/Cursor/Claude')
2102
+ .option('--reports-dir <dir>', 'Directory with coverage reports', 'reports/')
2103
+ .option('--out-dir <dir>', 'Output directory for AI flow files', 'reports/')
2104
+ .option('--format <fmt>', 'Output format: markdown, json, or both', 'both')
2105
+ .option('--max-gaps <n>', 'Maximum number of gaps to include', '50')
2106
+ .option('--priority <p>', 'Only include gaps at this priority or higher', 'P3')
2107
+ .action(async (options) => {
2108
+ const flows = await (0, index_4.exportAiFlows)({
2109
+ reportsDir: options.reportsDir,
2110
+ outDir: options.outDir,
2111
+ format: options.format,
2112
+ maxGaps: parseInt(options.maxGaps, 10),
2113
+ priority: options.priority,
2114
+ });
2115
+ console.log(`\nAI flows export complete:`);
2116
+ console.log(` Gaps exported: ${flows.gaps.length}`);
2117
+ console.log(` Project: ${flows.project.name}`);
2118
+ console.log(` Language: ${flows.project.language}`);
2119
+ });
2120
+ program
2121
+ .command('score-tests')
2122
+ .description('Score quality of existing test suite on 5 dimensions (0-100)')
2123
+ .option('--tests <glob>', 'Glob pattern for test files to score', 'tests/**/*.test.ts')
2124
+ .option('--reports-dir <dir>', 'Directory to write quality score output', 'reports/')
2125
+ .option('--fail-below <score>', 'Exit non-zero if any file scores below this', '0')
2126
+ .action(async (options) => {
2127
+ var _a;
2128
+ try {
2129
+ const report = await (0, index_4.scoreTests)({
2130
+ testsGlob: options.tests,
2131
+ reportsDir: options.reportsDir,
2132
+ failBelow: parseInt(options.failBelow, 10),
2133
+ });
2134
+ console.log(`\nTest Quality Score Report:`);
2135
+ console.log(` Overall score: ${report.overallScore}/100`);
2136
+ console.log(` Files scored: ${report.byFile.length}`);
2137
+ if (report.lowestQualityFiles.length > 0) {
2138
+ console.log(`\n Lowest quality files:`);
2139
+ for (const f of report.lowestQualityFiles) {
2140
+ const entry = report.byFile.find(b => b.file === f);
2141
+ console.log(` ${f}: ${(_a = entry === null || entry === void 0 ? void 0 : entry.score) !== null && _a !== void 0 ? _a : '?'}/100`);
2142
+ }
2143
+ }
2144
+ if (report.highestRiskLowQualityGaps.length > 0) {
2145
+ console.log(`\n High risk + low quality:`);
2146
+ for (const g of report.highestRiskLowQualityGaps) {
2147
+ console.log(` ${g.endpoint}: quality=${g.qualityScore}, risk=${g.riskScore}`);
2148
+ console.log(` → ${g.primaryIssue}`);
2149
+ }
2150
+ }
2151
+ console.log(`\n Report written to: ${options.reportsDir}/test-quality.json`);
2152
+ }
2153
+ catch (err) {
2154
+ if (err instanceof Error) {
2155
+ console.error(err.message);
2156
+ }
2157
+ process.exit(1);
2158
+ }
2159
+ });
2047
2160
  // Parse the command-line arguments
2048
2161
  program.parse(process.argv);
2049
2162
  // When invoked with no arguments (no subcommand), display help
@@ -1 +1 @@
1
- {"version":3,"file":"semanticBuilder.d.ts","sourceRoot":"","sources":["../../../../src/languages/java/semanticBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAOnC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GACX;IAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAmErF;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACrC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAqC/B;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACtC,GAAG,EAAE,gBAAgB,EAAE,GACtB,IAAI,CA6DN;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAyBvE;AAID,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAa3E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAa3D"}
1
+ {"version":3,"file":"semanticBuilder.d.ts","sourceRoot":"","sources":["../../../../src/languages/java/semanticBuilder.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAEV,cAAc,EACd,gBAAgB,EAChB,gBAAgB,EAChB,iBAAiB,EACjB,eAAe,EACf,OAAO,EACR,MAAM,oBAAoB,CAAC;AAC5B,OAAO,EAKL,KAAK,MAAM,EACZ,MAAM,2BAA2B,CAAC;AAOnC,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,MAAM,GACX;IAAE,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,CAAC;IAAC,KAAK,EAAE,GAAG,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAmErF;AAID,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,GACrC,GAAG,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAwC/B;AAID,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,MAAM,EACb,SAAS,EAAE,GAAG,CAAC,MAAM,EAAE,cAAc,CAAC,EACtC,GAAG,EAAE,gBAAgB,EAAE,GACtB,IAAI,CA+EN;AAID,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAyBvE;AAID,wBAAgB,2BAA2B,CAAC,IAAI,EAAE,MAAM,GAAG,eAAe,EAAE,CAa3E;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,EAAE,CAa3D"}
@@ -97,6 +97,8 @@ function extractJavaFunctions(root, constants) {
97
97
  continue;
98
98
  const annotations = extractAnnotationNames(method);
99
99
  const block = (_e = (_d = method.childForFieldName) === null || _d === void 0 ? void 0 : _d.call(method, 'body')) !== null && _e !== void 0 ? _e : (0, treeSitterUtils_1.firstChildOfType)(method, 'block');
100
+ // Extract method parameters
101
+ const parameters = extractMethodParameters(method);
100
102
  const bodyHttpCalls = [];
101
103
  const calledFunctions = [];
102
104
  let returnValue;
@@ -109,7 +111,7 @@ function extractJavaFunctions(root, constants) {
109
111
  const cucumberPattern = extractCucumberPattern(annotations, method);
110
112
  graph.set(name, {
111
113
  name,
112
- parameters: [],
114
+ parameters,
113
115
  bodyHttpCalls,
114
116
  calledFunctions,
115
117
  returnValue,
@@ -121,14 +123,44 @@ function extractJavaFunctions(root, constants) {
121
123
  }
122
124
  // ─── HTTP call extraction ─────────────────────────────────────────────────────
123
125
  function extractJavaHttpCalls(block, constants, out) {
124
- var _a, _b, _c, _d, _e, _f, _g;
126
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k, _l, _m, _o, _p, _q, _r, _s;
125
127
  const methodInvocations = (0, treeSitterUtils_1.findNodes)(block, ['method_invocation']);
126
128
  for (const invoc of methodInvocations) {
127
129
  const methodName = (_e = (_c = (_b = (_a = invoc.childForFieldName) === null || _a === void 0 ? void 0 : _a.call(invoc, 'name')) === null || _b === void 0 ? void 0 : _b.text) !== null && _c !== void 0 ? _c : (_d = firstChildNamed(invoc, 'identifier')) === null || _d === void 0 ? void 0 : _d.text) !== null && _e !== void 0 ? _e : '';
128
130
  const lowerMethod = methodName.toLowerCase();
131
+ // MockMvc: perform(get("/path")) — extract the inner HTTP method call
132
+ if (lowerMethod === 'perform') {
133
+ const argList = (_g = (_f = invoc.childForFieldName) === null || _f === void 0 ? void 0 : _f.call(invoc, 'arguments')) !== null && _g !== void 0 ? _g : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
134
+ if (!argList)
135
+ continue;
136
+ // The argument to perform() is a method invocation like get("/path") or post("/path")
137
+ const innerInvocations = (0, treeSitterUtils_1.findNodes)(argList, ['method_invocation']);
138
+ for (const innerInvoc of innerInvocations) {
139
+ const innerMethodName = (_m = (_k = (_j = (_h = innerInvoc.childForFieldName) === null || _h === void 0 ? void 0 : _h.call(innerInvoc, 'name')) === null || _j === void 0 ? void 0 : _j.text) !== null && _k !== void 0 ? _k : (_l = firstChildNamed(innerInvoc, 'identifier')) === null || _l === void 0 ? void 0 : _l.text) !== null && _m !== void 0 ? _m : '';
140
+ const innerLower = innerMethodName.toLowerCase();
141
+ if (!HTTP_METHODS.has(innerLower))
142
+ continue;
143
+ const innerArgList = (_p = (_o = innerInvoc.childForFieldName) === null || _o === void 0 ? void 0 : _o.call(innerInvoc, 'arguments')) !== null && _p !== void 0 ? _p : (0, treeSitterUtils_1.firstChildOfType)(innerInvoc, 'argument_list');
144
+ if (!innerArgList)
145
+ continue;
146
+ const innerStringArg = findFirstStringInArgList(innerArgList, constants);
147
+ if (!innerStringArg)
148
+ continue;
149
+ const normalizedPath = innerStringArg.value.startsWith('/') ? (0, resolvePaths_1.normalizePathToTemplate)(innerStringArg.value) : undefined;
150
+ out.push({
151
+ method: innerLower.toUpperCase(),
152
+ rawPathArg: (_q = innerStringArg.varName) !== null && _q !== void 0 ? _q : innerStringArg.value,
153
+ resolvedPath: innerStringArg.value,
154
+ normalizedPath,
155
+ resolutionType: innerStringArg.isDirect ? 'direct' : 'constant',
156
+ confidence: innerStringArg.isDirect ? 'high' : 'medium',
157
+ });
158
+ }
159
+ continue;
160
+ }
129
161
  if (!HTTP_METHODS.has(lowerMethod))
130
162
  continue;
131
- const argList = (_g = (_f = invoc.childForFieldName) === null || _f === void 0 ? void 0 : _f.call(invoc, 'arguments')) !== null && _g !== void 0 ? _g : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
163
+ const argList = (_s = (_r = invoc.childForFieldName) === null || _r === void 0 ? void 0 : _r.call(invoc, 'arguments')) !== null && _s !== void 0 ? _s : (0, treeSitterUtils_1.firstChildOfType)(invoc, 'argument_list');
132
164
  if (!argList)
133
165
  continue;
134
166
  // Extract the first string argument (path)
@@ -138,15 +170,6 @@ function extractJavaHttpCalls(block, constants, out) {
138
170
  const { value: path, isDirect, varName } = firstStringArg;
139
171
  // Try to detect the HTTP method from context
140
172
  let httpMethod = lowerMethod.toUpperCase();
141
- // RestAssured: .when().get("/path") or .given().get("/path")
142
- // The method name IS the HTTP method in RestAssured style
143
- if (!HTTP_METHODS.has(lowerMethod))
144
- continue;
145
- // MockMvc: perform(get("/path")) — perform wraps a method call
146
- if (lowerMethod === 'perform') {
147
- // The arg is another method invocation
148
- continue; // Handled when we process the inner get/post
149
- }
150
173
  if (lowerMethod === 'request') {
151
174
  // generic request(method, path) — try to get HTTP method from first arg
152
175
  const stringArgs = findAllStringsInArgList(argList, constants);
@@ -224,6 +247,40 @@ function extractJavaFlowRefs(root) {
224
247
  return refs;
225
248
  }
226
249
  // ─── Helpers ──────────────────────────────────────────────────────────────────
250
+ /**
251
+ * Extract method parameters with their annotations (e.g. @RequestParam, @PathVariable, @RequestBody).
252
+ */
253
+ function extractMethodParameters(method) {
254
+ var _a;
255
+ const params = [];
256
+ const formalParams = (0, treeSitterUtils_1.firstChildOfType)(method, 'formal_parameters');
257
+ if (!formalParams)
258
+ return params;
259
+ const paramNodes = (0, treeSitterUtils_1.findNodes)(formalParams, ['formal_parameter', 'spread_parameter']);
260
+ for (const paramNode of paramNodes) {
261
+ const paramAnnotations = [];
262
+ (0, treeSitterUtils_1.walkTree)(paramNode, (n) => {
263
+ var _a;
264
+ if (n.type === 'annotation' || n.type === 'marker_annotation') {
265
+ const nameNode = (0, treeSitterUtils_1.firstChildOfType)(n, 'identifier');
266
+ if (nameNode)
267
+ paramAnnotations.push('@' + ((_a = nameNode.text) !== null && _a !== void 0 ? _a : ''));
268
+ }
269
+ });
270
+ const nameNode = firstChildNamed(paramNode, 'identifier');
271
+ const name = (_a = nameNode === null || nameNode === void 0 ? void 0 : nameNode.text) !== null && _a !== void 0 ? _a : '';
272
+ if (!name)
273
+ continue;
274
+ // Include annotation prefix for annotated params (Spring @RequestParam, @PathVariable, etc.)
275
+ if (paramAnnotations.length > 0) {
276
+ params.push(`${paramAnnotations.join(' ')} ${name}`);
277
+ }
278
+ else {
279
+ params.push(name);
280
+ }
281
+ }
282
+ return params;
283
+ }
227
284
  function extractModifierTexts(node) {
228
285
  const modifiers = [];
229
286
  (0, treeSitterUtils_1.walkTree)(node, (n) => {
@@ -1 +1 @@
1
- {"version":3,"file":"angularDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/angularDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,aAAa,GAAG,WAAW,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IACnC,SAAS,EAAE,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAyC9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CAuChG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAyCxF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgCpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAY7F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEhE"}
1
+ {"version":3,"file":"angularDetector.d.ts","sourceRoot":"","sources":["../../../../src/languages/javascript/angularDetector.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,eAAe;IAC9B,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,wCAAwC;IACxC,aAAa,EAAE,MAAM,CAAC;IACtB,mCAAmC;IACnC,YAAY,EAAE,MAAM,CAAC;IACrB,+DAA+D;IAC/D,KAAK,EAAE,aAAa,GAAG,WAAW,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,YAAY,GAAG,aAAa,CAAC;IACnC,SAAS,EAAE,aAAa,GAAG,kBAAkB,GAAG,eAAe,GAAG,SAAS,GAAG,UAAU,CAAC;IACzF,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,kBAAkB;IACjC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,aAAa,GAAG,YAAY,CAAC;IACnC,UAAU,EAAE,MAAM,CAAC;IACnB,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,gBAAgB;IAC/B,2BAA2B,EAAE,OAAO,CAAC;IACrC,oBAAoB,EAAE,MAAM,EAAE,CAAC;IAC/B,UAAU,EAAE,MAAM,CAAC;CACpB;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,eAAe,EAAE,CAyC9F;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,EAAE,CA2EhG;AAED;;GAEG;AACH,wBAAgB,mBAAmB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,YAAY,EAAE,CAyCxF;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,kBAAkB,EAAE,CAgCpG;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,UAAU,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,gBAAgB,CAY7F;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAEhE"}
@@ -68,33 +68,66 @@ function detectAngularInjections(sourceText, filePath) {
68
68
  const injections = [];
69
69
  const lines = sourceText.split('\n');
70
70
  let currentClass = '';
71
+ let currentConstHost = '';
72
+ let inConstructorParams = false;
71
73
  for (let i = 0; i < lines.length; i++) {
72
74
  const line = lines[i];
73
75
  // Track current class
74
76
  const classMatch = line.match(/class\s+(\w+)/);
75
77
  if (classMatch)
76
78
  currentClass = classMatch[1];
79
+ // Track current const/export const assignment as potential host for inject() outside class.
80
+ // Only update when the line is NOT itself an inject() call (e.g. skip `const x = inject(Y)`).
81
+ if (!currentClass) {
82
+ const constHostMatch = line.match(/(?:export\s+)?(?:const|let)\s+(\w+)\s*(?::\s*\S+)?\s*=/);
83
+ if (constHostMatch && !line.match(/=\s*inject\s*\(/)) {
84
+ currentConstHost = constHostMatch[1];
85
+ }
86
+ }
87
+ // Track constructor parameter block boundaries
88
+ if (/\bconstructor\s*\(/.test(line)) {
89
+ inConstructorParams = true;
90
+ }
91
+ if (inConstructorParams && line.includes(')')) {
92
+ // Process this line (it's still inside the constructor params), then close
93
+ // We'll close after checking for injections below
94
+ }
77
95
  // Constructor injection: constructor(private http: HttpClient)
78
- const ctorMatch = line.match(/(?:private|protected|public|readonly)\s+(\w+)\s*:\s*(\w+)/);
79
- if (ctorMatch && currentClass) {
80
- injections.push({
81
- consumerClass: currentClass,
82
- serviceClass: ctorMatch[2],
83
- style: 'constructor',
84
- sourceFile: filePath,
85
- line: i + 1,
86
- });
96
+ // Only match visibility-modified parameters when inside a constructor(...) block
97
+ if (inConstructorParams) {
98
+ const ctorParamPattern = /(?:private|protected|public|readonly)\s+(\w+)\s*:\s*(\w+)/g;
99
+ let ctorMatch;
100
+ while ((ctorMatch = ctorParamPattern.exec(line)) !== null) {
101
+ if (currentClass) {
102
+ injections.push({
103
+ consumerClass: currentClass,
104
+ serviceClass: ctorMatch[2],
105
+ style: 'constructor',
106
+ sourceFile: filePath,
107
+ line: i + 1,
108
+ });
109
+ }
110
+ }
111
+ }
112
+ // Close the constructor param block after processing (handles closing paren on same line)
113
+ if (inConstructorParams && line.includes(')')) {
114
+ inConstructorParams = false;
87
115
  }
88
116
  // Functional inject: inject(HttpClient)
89
117
  const injectMatch = line.match(/(\w+)\s*=\s*inject\s*\(\s*(\w+)\s*\)/);
90
- if (injectMatch && currentClass) {
91
- injections.push({
92
- consumerClass: currentClass,
93
- serviceClass: injectMatch[2],
94
- style: 'inject-fn',
95
- sourceFile: filePath,
96
- line: i + 1,
97
- });
118
+ if (injectMatch) {
119
+ // Use the enclosing class, or fall back to the enclosing const/export const host
120
+ // (e.g. functional guards/interceptors: `export const authGuard: CanActivateFn = ...`)
121
+ const hostName = currentClass || currentConstHost;
122
+ if (hostName) {
123
+ injections.push({
124
+ consumerClass: hostName,
125
+ serviceClass: injectMatch[2],
126
+ style: 'inject-fn',
127
+ sourceFile: filePath,
128
+ line: i + 1,
129
+ });
130
+ }
98
131
  }
99
132
  }
100
133
  return injections;