@g1cloud/api-gen 1.0.0

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 (86) hide show
  1. package/.claude/settings.local.json +22 -0
  2. package/CLAUDE.md +63 -0
  3. package/README.md +379 -0
  4. package/dist/analyzer/controllerAnalyzer.d.ts +20 -0
  5. package/dist/analyzer/controllerAnalyzer.d.ts.map +1 -0
  6. package/dist/analyzer/controllerAnalyzer.js +101 -0
  7. package/dist/analyzer/controllerAnalyzer.js.map +1 -0
  8. package/dist/analyzer/parameterAnalyzer.d.ts +19 -0
  9. package/dist/analyzer/parameterAnalyzer.d.ts.map +1 -0
  10. package/dist/analyzer/parameterAnalyzer.js +207 -0
  11. package/dist/analyzer/parameterAnalyzer.js.map +1 -0
  12. package/dist/analyzer/responseAnalyzer.d.ts +12 -0
  13. package/dist/analyzer/responseAnalyzer.d.ts.map +1 -0
  14. package/dist/analyzer/responseAnalyzer.js +116 -0
  15. package/dist/analyzer/responseAnalyzer.js.map +1 -0
  16. package/dist/analyzer/schemaGenerator.d.ts +6 -0
  17. package/dist/analyzer/schemaGenerator.d.ts.map +1 -0
  18. package/dist/analyzer/schemaGenerator.js +347 -0
  19. package/dist/analyzer/schemaGenerator.js.map +1 -0
  20. package/dist/analyzer/securityAnalyzer.d.ts +6 -0
  21. package/dist/analyzer/securityAnalyzer.d.ts.map +1 -0
  22. package/dist/analyzer/securityAnalyzer.js +177 -0
  23. package/dist/analyzer/securityAnalyzer.js.map +1 -0
  24. package/dist/generator/openapiGenerator.d.ts +14 -0
  25. package/dist/generator/openapiGenerator.d.ts.map +1 -0
  26. package/dist/generator/openapiGenerator.js +340 -0
  27. package/dist/generator/openapiGenerator.js.map +1 -0
  28. package/dist/index.d.ts +3 -0
  29. package/dist/index.d.ts.map +1 -0
  30. package/dist/index.js +218 -0
  31. package/dist/index.js.map +1 -0
  32. package/dist/lib.d.ts +61 -0
  33. package/dist/lib.d.ts.map +1 -0
  34. package/dist/lib.js +199 -0
  35. package/dist/lib.js.map +1 -0
  36. package/dist/mcp-server.d.ts +9 -0
  37. package/dist/mcp-server.d.ts.map +1 -0
  38. package/dist/mcp-server.js +257 -0
  39. package/dist/mcp-server.js.map +1 -0
  40. package/dist/mcp-server.mjs +45586 -0
  41. package/dist/parser/astAnalyzer.d.ts +87 -0
  42. package/dist/parser/astAnalyzer.d.ts.map +1 -0
  43. package/dist/parser/astAnalyzer.js +321 -0
  44. package/dist/parser/astAnalyzer.js.map +1 -0
  45. package/dist/parser/javaParser.d.ts +10 -0
  46. package/dist/parser/javaParser.d.ts.map +1 -0
  47. package/dist/parser/javaParser.js +805 -0
  48. package/dist/parser/javaParser.js.map +1 -0
  49. package/dist/types/index.d.ts +217 -0
  50. package/dist/types/index.d.ts.map +1 -0
  51. package/dist/types/index.js +3 -0
  52. package/dist/types/index.js.map +1 -0
  53. package/examples/CreateUserRequest.java +80 -0
  54. package/examples/DepartmentDTO.java +45 -0
  55. package/examples/Filter.java +39 -0
  56. package/examples/PaginatedList.java +71 -0
  57. package/examples/ProductController.java +136 -0
  58. package/examples/ProductDTO.java +129 -0
  59. package/examples/RoleDTO.java +47 -0
  60. package/examples/SearchParam.java +55 -0
  61. package/examples/Sort.java +70 -0
  62. package/examples/UpdateUserRequest.java +74 -0
  63. package/examples/UserController.java +98 -0
  64. package/examples/UserDTO.java +119 -0
  65. package/package.json +51 -0
  66. package/prompt/01_Initial.md +358 -0
  67. package/prompt/02_/354/266/224/352/260/200.md +31 -0
  68. package/src/analyzer/controllerAnalyzer.ts +125 -0
  69. package/src/analyzer/parameterAnalyzer.ts +259 -0
  70. package/src/analyzer/responseAnalyzer.ts +142 -0
  71. package/src/analyzer/schemaGenerator.ts +412 -0
  72. package/src/analyzer/securityAnalyzer.ts +200 -0
  73. package/src/generator/openapiGenerator.ts +378 -0
  74. package/src/index.ts +212 -0
  75. package/src/lib.ts +240 -0
  76. package/src/mcp-server.ts +310 -0
  77. package/src/parser/astAnalyzer.ts +373 -0
  78. package/src/parser/javaParser.ts +901 -0
  79. package/src/types/index.ts +238 -0
  80. package/test-boolean.yaml +607 -0
  81. package/test-filter.yaml +576 -0
  82. package/test-inner.ts +59 -0
  83. package/test-output.yaml +650 -0
  84. package/test-paginated.yaml +585 -0
  85. package/tsconfig.json +20 -0
  86. package/tsup.config.ts +30 -0
@@ -0,0 +1,805 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.JavaFileParser = void 0;
37
+ exports.parseJavaSource = parseJavaSource;
38
+ const fs = __importStar(require("fs"));
39
+ const path = __importStar(require("path"));
40
+ const java_parser_1 = require("java-parser");
41
+ /**
42
+ * Extract Javadoc comments from source code
43
+ */
44
+ function extractJavadocs(content) {
45
+ const javadocs = new Map();
46
+ const javadocRegex = /\/\*\*[\s\S]*?\*\//g;
47
+ let match;
48
+ while ((match = javadocRegex.exec(content)) !== null) {
49
+ const javadocText = match[0];
50
+ // Count newlines to find the end line of the javadoc
51
+ const beforeMatch = content.substring(0, match.index + javadocText.length);
52
+ const endLine = beforeMatch.split('\n').length;
53
+ // Parse the javadoc content
54
+ const parsedJavadoc = parseJavadocContent(javadocText);
55
+ if (parsedJavadoc.description || parsedJavadoc.info.returns || Object.keys(parsedJavadoc.info.params).length > 0) {
56
+ javadocs.set(endLine, parsedJavadoc);
57
+ }
58
+ }
59
+ return javadocs;
60
+ }
61
+ /**
62
+ * Parse Javadoc content and extract the description, @param, and @return
63
+ */
64
+ function parseJavadocContent(javadoc) {
65
+ // Remove /** and */
66
+ let content = javadoc.replace(/^\/\*\*/, '').replace(/\*\/$/, '');
67
+ // Split into lines and process each line
68
+ const lines = content.split('\n').map((line) => {
69
+ // Remove leading whitespace and asterisks
70
+ return line.replace(/^\s*\*?\s?/, '');
71
+ });
72
+ const descriptionLines = [];
73
+ const params = {};
74
+ let returns;
75
+ let currentTag = null;
76
+ let currentParamName = null;
77
+ let currentTagContent = [];
78
+ const flushCurrentTag = () => {
79
+ if (currentTag === 'param' && currentParamName) {
80
+ params[currentParamName] = currentTagContent.join(' ').trim();
81
+ }
82
+ else if (currentTag === 'return' || currentTag === 'returns') {
83
+ returns = currentTagContent.join(' ').trim();
84
+ }
85
+ currentTag = null;
86
+ currentParamName = null;
87
+ currentTagContent = [];
88
+ };
89
+ for (const line of lines) {
90
+ if (line.startsWith('@param ')) {
91
+ flushCurrentTag();
92
+ currentTag = 'param';
93
+ // Extract param name and description
94
+ const paramMatch = line.match(/^@param\s+(\w+)\s*(.*)/);
95
+ if (paramMatch) {
96
+ currentParamName = paramMatch[1];
97
+ if (paramMatch[2]) {
98
+ currentTagContent.push(paramMatch[2]);
99
+ }
100
+ }
101
+ }
102
+ else if (line.startsWith('@return ') || line.startsWith('@returns ')) {
103
+ flushCurrentTag();
104
+ currentTag = 'return';
105
+ const returnMatch = line.match(/^@returns?\s+(.*)/);
106
+ if (returnMatch && returnMatch[1]) {
107
+ currentTagContent.push(returnMatch[1]);
108
+ }
109
+ }
110
+ else if (line.startsWith('@')) {
111
+ // Other tags like @throws, @see, etc. - flush current and ignore
112
+ flushCurrentTag();
113
+ }
114
+ else if (currentTag) {
115
+ // Continuation of current tag
116
+ currentTagContent.push(line);
117
+ }
118
+ else {
119
+ // Description line
120
+ descriptionLines.push(line);
121
+ }
122
+ }
123
+ // Flush any remaining tag
124
+ flushCurrentTag();
125
+ return {
126
+ description: descriptionLines.join('\n').trim(),
127
+ info: {
128
+ description: descriptionLines.join('\n').trim() || undefined,
129
+ params,
130
+ returns,
131
+ },
132
+ };
133
+ }
134
+ class JavaFileParser {
135
+ sourceDir;
136
+ constructor(sourceDir) {
137
+ this.sourceDir = sourceDir;
138
+ }
139
+ async parseAllJavaFiles() {
140
+ const javaClasses = new Map();
141
+ const javaFiles = this.findJavaFiles(this.sourceDir);
142
+ for (const filePath of javaFiles) {
143
+ try {
144
+ const classes = await this.parseJavaFile(filePath);
145
+ for (const javaClass of classes) {
146
+ javaClasses.set(javaClass.name, javaClass);
147
+ }
148
+ }
149
+ catch (error) {
150
+ console.error(`Error parsing ${filePath}:`, error instanceof Error ? error.message : error);
151
+ }
152
+ }
153
+ return javaClasses;
154
+ }
155
+ findJavaFiles(dir) {
156
+ const files = [];
157
+ if (!fs.existsSync(dir)) {
158
+ return files;
159
+ }
160
+ const entries = fs.readdirSync(dir, { withFileTypes: true });
161
+ for (const entry of entries) {
162
+ const fullPath = path.join(dir, entry.name);
163
+ if (entry.isDirectory()) {
164
+ files.push(...this.findJavaFiles(fullPath));
165
+ }
166
+ else if (entry.isFile() && entry.name.endsWith('.java')) {
167
+ files.push(fullPath);
168
+ }
169
+ }
170
+ return files;
171
+ }
172
+ async parseJavaFile(filePath) {
173
+ const content = fs.readFileSync(filePath, 'utf-8');
174
+ try {
175
+ const cst = (0, java_parser_1.parse)(content);
176
+ const javadocs = extractJavadocs(content);
177
+ const extractor = new JavaClassExtractor(filePath, content, javadocs);
178
+ extractor.visit(cst);
179
+ return extractor.getAllClasses();
180
+ }
181
+ catch (error) {
182
+ console.error(`Failed to parse ${filePath}:`, error instanceof Error ? error.message : error);
183
+ return [];
184
+ }
185
+ }
186
+ }
187
+ exports.JavaFileParser = JavaFileParser;
188
+ class JavaClassExtractor extends java_parser_1.BaseJavaCstVisitorWithDefaults {
189
+ filePath;
190
+ sourceContent;
191
+ javadocs;
192
+ _packageName = '';
193
+ currentAnnotations = [];
194
+ // Stack for handling nested classes
195
+ classStack = [];
196
+ allClasses = [];
197
+ constructor(filePath, sourceContent, javadocs) {
198
+ super();
199
+ this.filePath = filePath;
200
+ this.sourceContent = sourceContent;
201
+ this.javadocs = javadocs;
202
+ this.validateVisitor();
203
+ }
204
+ get currentClass() {
205
+ return this.classStack[this.classStack.length - 1];
206
+ }
207
+ getJavaClass() {
208
+ // Return the first (top-level) class for backward compatibility
209
+ return this.allClasses.length > 0 ? this.allClasses[0] : null;
210
+ }
211
+ getAllClasses() {
212
+ return this.allClasses;
213
+ }
214
+ finalizeClass(ctx) {
215
+ this.allClasses.push({
216
+ name: ctx.className,
217
+ packageName: this._packageName,
218
+ annotations: ctx.classAnnotations,
219
+ methods: ctx.methods,
220
+ fields: ctx.fields,
221
+ filePath: this.filePath,
222
+ javadoc: ctx.classJavadoc,
223
+ superClass: ctx.superClassName,
224
+ isEnum: ctx.isEnum,
225
+ enumValues: ctx.isEnum ? ctx.enumValues : undefined,
226
+ });
227
+ }
228
+ packageDeclaration(ctx) {
229
+ if (ctx.Identifier) {
230
+ this._packageName = ctx.Identifier.map((id) => id.image).join('.');
231
+ }
232
+ }
233
+ normalClassDeclaration(ctx) {
234
+ // Create a new class context
235
+ const classContext = {
236
+ className: '',
237
+ classAnnotations: [...this.currentAnnotations],
238
+ methods: [],
239
+ fields: [],
240
+ isEnum: false,
241
+ enumValues: [],
242
+ };
243
+ this.currentAnnotations = [];
244
+ // Extract class name
245
+ if (ctx.typeIdentifier?.[0]?.children?.Identifier?.[0]) {
246
+ classContext.className = ctx.typeIdentifier[0].children.Identifier[0].image;
247
+ // Find javadoc for this class
248
+ const classToken = ctx.typeIdentifier[0].children.Identifier[0];
249
+ if (classToken.startLine) {
250
+ const parsedJavadoc = this.findJavadocForLine(classToken.startLine);
251
+ classContext.classJavadoc = parsedJavadoc?.description;
252
+ }
253
+ }
254
+ // Extract superclass name from classExtends
255
+ if (ctx.classExtends?.[0]) {
256
+ const classExtendsChildren = ctx.classExtends[0].children || ctx.classExtends[0];
257
+ if (classExtendsChildren.classType?.[0]) {
258
+ const classTypeChildren = classExtendsChildren.classType[0].children || classExtendsChildren.classType[0];
259
+ if (classTypeChildren.Identifier) {
260
+ // Join all identifiers for fully qualified names
261
+ classContext.superClassName = classTypeChildren.Identifier.map((id) => id.image).join('.');
262
+ }
263
+ }
264
+ }
265
+ // Push to stack and visit class body
266
+ this.classStack.push(classContext);
267
+ if (ctx.classBody) {
268
+ this.visit(ctx.classBody);
269
+ }
270
+ // Pop from stack and finalize the class
271
+ const completed = this.classStack.pop();
272
+ if (completed && completed.className) {
273
+ this.finalizeClass(completed);
274
+ }
275
+ }
276
+ enumDeclaration(ctx) {
277
+ // Create a new enum context
278
+ const enumContext = {
279
+ className: '',
280
+ classAnnotations: [...this.currentAnnotations],
281
+ methods: [],
282
+ fields: [],
283
+ isEnum: true,
284
+ enumValues: [],
285
+ };
286
+ this.currentAnnotations = [];
287
+ // Get enum name
288
+ if (ctx.typeIdentifier?.[0]?.children?.Identifier?.[0]) {
289
+ enumContext.className = ctx.typeIdentifier[0].children.Identifier[0].image;
290
+ // Find javadoc for this enum
291
+ const enumToken = ctx.typeIdentifier[0].children.Identifier[0];
292
+ if (enumToken.startLine) {
293
+ const parsedJavadoc = this.findJavadocForLine(enumToken.startLine);
294
+ enumContext.classJavadoc = parsedJavadoc?.description;
295
+ }
296
+ }
297
+ // Extract enum constants
298
+ if (ctx.enumBody?.[0]) {
299
+ const enumBodyChildren = ctx.enumBody[0].children || ctx.enumBody[0];
300
+ if (enumBodyChildren.enumConstantList?.[0]) {
301
+ const constantListChildren = enumBodyChildren.enumConstantList[0].children || enumBodyChildren.enumConstantList[0];
302
+ if (constantListChildren.enumConstant) {
303
+ for (const enumConstant of constantListChildren.enumConstant) {
304
+ const constantChildren = enumConstant.children || enumConstant;
305
+ if (constantChildren.Identifier?.[0]) {
306
+ enumContext.enumValues.push(constantChildren.Identifier[0].image);
307
+ }
308
+ }
309
+ }
310
+ }
311
+ }
312
+ // Finalize the enum (enums don't have a body to visit for nested classes)
313
+ if (enumContext.className) {
314
+ this.finalizeClass(enumContext);
315
+ }
316
+ }
317
+ /**
318
+ * Find javadoc that ends near the given line (within a few lines before)
319
+ */
320
+ findJavadocForLine(targetLine) {
321
+ // Look for javadoc that ends 1-10 lines before the target line
322
+ // (allowing for annotations between javadoc and declaration)
323
+ for (let offset = 1; offset <= 10; offset++) {
324
+ const javadoc = this.javadocs.get(targetLine - offset);
325
+ if (javadoc) {
326
+ return javadoc;
327
+ }
328
+ }
329
+ return undefined;
330
+ }
331
+ classModifier(ctx) {
332
+ if (ctx.annotation) {
333
+ for (const annotationCtx of ctx.annotation) {
334
+ const annotation = this.extractAnnotation(annotationCtx);
335
+ if (annotation) {
336
+ this.currentAnnotations.push(annotation);
337
+ }
338
+ }
339
+ }
340
+ }
341
+ methodDeclaration(ctx) {
342
+ // Extract annotations directly from methodModifier nodes
343
+ const methodAnnotations = [];
344
+ let methodStartLine;
345
+ if (ctx.methodModifier) {
346
+ for (const modifierCtx of ctx.methodModifier) {
347
+ const modChildren = modifierCtx.children || modifierCtx;
348
+ if (modChildren.annotation) {
349
+ for (const annotationCtx of modChildren.annotation) {
350
+ const annotation = this.extractAnnotation(annotationCtx);
351
+ if (annotation) {
352
+ methodAnnotations.push(annotation);
353
+ }
354
+ // Track the earliest line of the method declaration
355
+ const annChildren = annotationCtx.children || annotationCtx;
356
+ if (annChildren.At?.[0]?.startLine && (!methodStartLine || annChildren.At[0].startLine < methodStartLine)) {
357
+ methodStartLine = annChildren.At[0].startLine;
358
+ }
359
+ }
360
+ }
361
+ }
362
+ }
363
+ const methodHeader = ctx.methodHeader?.[0];
364
+ if (!methodHeader)
365
+ return;
366
+ const methodName = this.extractMethodName(methodHeader);
367
+ const returnType = this.extractReturnType(methodHeader);
368
+ const parameters = this.extractParameters(methodHeader);
369
+ // Find javadoc for this method
370
+ let methodJavadoc;
371
+ let methodJavadocInfo;
372
+ if (methodStartLine) {
373
+ const parsedJavadoc = this.findJavadocForLine(methodStartLine);
374
+ methodJavadoc = parsedJavadoc?.description;
375
+ methodJavadocInfo = parsedJavadoc?.info;
376
+ }
377
+ if (methodName && this.currentClass) {
378
+ this.currentClass.methods.push({
379
+ name: methodName,
380
+ returnType: returnType.type,
381
+ returnGenericType: returnType.genericType,
382
+ parameters,
383
+ annotations: methodAnnotations,
384
+ javadoc: methodJavadoc,
385
+ javadocInfo: methodJavadocInfo,
386
+ });
387
+ }
388
+ }
389
+ fieldDeclaration(ctx) {
390
+ // Extract annotations and check for static modifier from fieldModifier nodes
391
+ const fieldAnnotations = [];
392
+ let isStatic = false;
393
+ let fieldStartLine;
394
+ if (ctx.fieldModifier) {
395
+ for (const modifier of ctx.fieldModifier) {
396
+ const modChildren = modifier.children || modifier;
397
+ // Check for static modifier
398
+ if (modChildren.Static) {
399
+ isStatic = true;
400
+ }
401
+ // Extract annotations and track start line
402
+ if (modChildren.annotation) {
403
+ for (const annotationCtx of modChildren.annotation) {
404
+ const annotation = this.extractAnnotation(annotationCtx);
405
+ if (annotation) {
406
+ fieldAnnotations.push(annotation);
407
+ }
408
+ // Track the earliest line of the field declaration
409
+ const annChildren = annotationCtx.children || annotationCtx;
410
+ if (annChildren.At?.[0]?.startLine && (!fieldStartLine || annChildren.At[0].startLine < fieldStartLine)) {
411
+ fieldStartLine = annChildren.At[0].startLine;
412
+ }
413
+ }
414
+ }
415
+ }
416
+ }
417
+ // Skip static fields
418
+ if (isStatic)
419
+ return;
420
+ const unannType = ctx.unannType?.[0];
421
+ const variableDeclaratorList = ctx.variableDeclaratorList?.[0];
422
+ if (!unannType || !variableDeclaratorList)
423
+ return;
424
+ // If no annotation found, try to get start line from type
425
+ if (!fieldStartLine && unannType) {
426
+ fieldStartLine = this.getStartLineFromNode(unannType);
427
+ }
428
+ const typeInfo = this.extractType(unannType);
429
+ const fieldNames = this.extractFieldNames(variableDeclaratorList);
430
+ // Find javadoc for this field
431
+ let fieldJavadoc;
432
+ if (fieldStartLine) {
433
+ const parsedJavadoc = this.findJavadocForLine(fieldStartLine);
434
+ fieldJavadoc = parsedJavadoc?.description;
435
+ }
436
+ if (this.currentClass) {
437
+ for (const fieldName of fieldNames) {
438
+ this.currentClass.fields.push({
439
+ name: fieldName,
440
+ type: typeInfo.type,
441
+ genericType: typeInfo.genericType,
442
+ annotations: fieldAnnotations,
443
+ accessModifier: 'private', // Default, could be extracted from modifiers
444
+ javadoc: fieldJavadoc,
445
+ });
446
+ }
447
+ }
448
+ }
449
+ /**
450
+ * Get the start line from a CST node by recursively searching for tokens
451
+ */
452
+ getStartLineFromNode(node) {
453
+ if (!node)
454
+ return undefined;
455
+ const children = node.children || node;
456
+ // Check if this is a token with startLine
457
+ if (children.startLine) {
458
+ return children.startLine;
459
+ }
460
+ // Recursively search children
461
+ for (const key of Object.keys(children)) {
462
+ const child = children[key];
463
+ if (Array.isArray(child)) {
464
+ for (const item of child) {
465
+ if (item?.startLine) {
466
+ return item.startLine;
467
+ }
468
+ const result = this.getStartLineFromNode(item);
469
+ if (result)
470
+ return result;
471
+ }
472
+ }
473
+ else if (child?.startLine) {
474
+ return child.startLine;
475
+ }
476
+ }
477
+ return undefined;
478
+ }
479
+ extractAnnotation(ctx) {
480
+ const children = ctx.children || ctx;
481
+ // Get annotation name
482
+ let name = '';
483
+ if (children.typeName?.[0]) {
484
+ name = this.extractTypeName(children.typeName[0]);
485
+ }
486
+ else if (children.Identifier) {
487
+ name = children.Identifier.map((id) => id.image).join('.');
488
+ }
489
+ if (!name)
490
+ return null;
491
+ // Remove @ prefix if present
492
+ name = name.replace(/^@/, '');
493
+ // Extract annotation values
494
+ const values = {};
495
+ if (children.elementValuePairList?.[0]) {
496
+ this.extractElementValuePairs(children.elementValuePairList[0], values);
497
+ }
498
+ else if (children.elementValue?.[0]) {
499
+ // Single value annotation like @GetMapping("/path")
500
+ values['value'] = this.extractElementValue(children.elementValue[0]);
501
+ }
502
+ return { name, values };
503
+ }
504
+ extractElementValuePairs(ctx, values) {
505
+ const children = ctx.children || ctx;
506
+ const pairs = children.elementValuePair || [];
507
+ for (const pair of pairs) {
508
+ const pairChildren = pair.children || pair;
509
+ const key = pairChildren.Identifier?.[0]?.image || 'value';
510
+ const value = this.extractElementValue(pairChildren.elementValue?.[0]);
511
+ values[key] = value;
512
+ }
513
+ }
514
+ extractElementValue(ctx) {
515
+ if (!ctx)
516
+ return '';
517
+ const children = ctx.children || ctx;
518
+ // Array initializer
519
+ if (children.elementValueArrayInitializer?.[0]) {
520
+ const arrayInit = children.elementValueArrayInitializer[0];
521
+ const arrayChildren = arrayInit.children || arrayInit;
522
+ const elementValues = arrayChildren.elementValue || [];
523
+ return elementValues.map((ev) => this.extractElementValue(ev)).flat();
524
+ }
525
+ // Conditional expression (includes literals and identifiers)
526
+ if (children.conditionalExpression?.[0]) {
527
+ return this.extractExpressionValue(children.conditionalExpression[0]);
528
+ }
529
+ // Annotation
530
+ if (children.annotation?.[0]) {
531
+ return this.extractAnnotationAsString(children.annotation[0]);
532
+ }
533
+ return '';
534
+ }
535
+ extractExpressionValue(ctx) {
536
+ const children = ctx.children || ctx;
537
+ // Handle string literals
538
+ if (children.StringLiteral?.[0]) {
539
+ return children.StringLiteral[0].image.replace(/^"|"$/g, '');
540
+ }
541
+ // Handle boolean literals
542
+ if (children.True?.[0])
543
+ return 'true';
544
+ if (children.False?.[0])
545
+ return 'false';
546
+ // Handle numeric literals
547
+ if (children.IntegerLiteral?.[0])
548
+ return children.IntegerLiteral[0].image;
549
+ if (children.FloatingPointLiteral?.[0])
550
+ return children.FloatingPointLiteral[0].image;
551
+ // Handle identifiers (enum values, etc.)
552
+ if (children.Identifier?.[0])
553
+ return children.Identifier[0].image;
554
+ // Recursively search for values in nested structures
555
+ for (const key of Object.keys(children)) {
556
+ if (Array.isArray(children[key]) && children[key].length > 0) {
557
+ const result = this.extractExpressionValue(children[key][0]);
558
+ if (result)
559
+ return result;
560
+ }
561
+ }
562
+ return '';
563
+ }
564
+ extractAnnotationAsString(ctx) {
565
+ const children = ctx.children || ctx;
566
+ let name = '';
567
+ if (children.typeName?.[0]) {
568
+ name = this.extractTypeName(children.typeName[0]);
569
+ }
570
+ return `@${name}`;
571
+ }
572
+ extractTypeName(ctx) {
573
+ const children = ctx.children || ctx;
574
+ if (children.Identifier) {
575
+ return children.Identifier.map((id) => id.image).join('.');
576
+ }
577
+ return '';
578
+ }
579
+ extractMethodName(methodHeader) {
580
+ const children = methodHeader.children || methodHeader;
581
+ const declarator = children.methodDeclarator?.[0];
582
+ if (declarator) {
583
+ const declChildren = declarator.children || declarator;
584
+ return declChildren.Identifier?.[0]?.image || '';
585
+ }
586
+ return '';
587
+ }
588
+ extractReturnType(methodHeader) {
589
+ const children = methodHeader.children || methodHeader;
590
+ const result = children.result?.[0];
591
+ if (!result)
592
+ return { type: 'void' };
593
+ const resultChildren = result.children || result;
594
+ if (resultChildren.Void) {
595
+ return { type: 'void' };
596
+ }
597
+ if (resultChildren.unannType?.[0]) {
598
+ return this.extractType(resultChildren.unannType[0]);
599
+ }
600
+ return { type: 'Object' };
601
+ }
602
+ extractType(typeCtx) {
603
+ const children = typeCtx.children || typeCtx;
604
+ // Handle primitive types with optional dims suffix (e.g., boolean, int, etc.)
605
+ if (children.unannPrimitiveTypeWithOptionalDimsSuffix?.[0]) {
606
+ const primitiveWithDims = children.unannPrimitiveTypeWithOptionalDimsSuffix[0].children || children.unannPrimitiveTypeWithOptionalDimsSuffix[0];
607
+ if (primitiveWithDims.unannPrimitiveType?.[0]) {
608
+ const primitiveChildren = primitiveWithDims.unannPrimitiveType[0].children || primitiveWithDims.unannPrimitiveType[0];
609
+ return this.extractPrimitiveType(primitiveChildren);
610
+ }
611
+ }
612
+ // Handle primitive types directly (fallback for older parser versions)
613
+ if (children.unannPrimitiveType?.[0]) {
614
+ const primitiveChildren = children.unannPrimitiveType[0].children || children.unannPrimitiveType[0];
615
+ return this.extractPrimitiveType(primitiveChildren);
616
+ }
617
+ // Handle reference types
618
+ if (children.unannReferenceType?.[0]) {
619
+ return this.extractReferenceType(children.unannReferenceType[0]);
620
+ }
621
+ return { type: 'Object' };
622
+ }
623
+ extractPrimitiveType(primitiveChildren) {
624
+ if (primitiveChildren.numericType?.[0]) {
625
+ const numericChildren = primitiveChildren.numericType[0].children || primitiveChildren.numericType[0];
626
+ if (numericChildren.integralType?.[0]) {
627
+ const integralChildren = numericChildren.integralType[0].children || numericChildren.integralType[0];
628
+ for (const key of ['Int', 'Long', 'Short', 'Byte', 'Char']) {
629
+ if (integralChildren[key])
630
+ return { type: key.toLowerCase() };
631
+ }
632
+ }
633
+ if (numericChildren.floatingPointType?.[0]) {
634
+ const floatChildren = numericChildren.floatingPointType[0].children || numericChildren.floatingPointType[0];
635
+ if (floatChildren.Float)
636
+ return { type: 'float' };
637
+ if (floatChildren.Double)
638
+ return { type: 'double' };
639
+ }
640
+ }
641
+ if (primitiveChildren.Boolean)
642
+ return { type: 'boolean' };
643
+ return { type: 'Object' };
644
+ }
645
+ extractReferenceType(refTypeCtx) {
646
+ const children = refTypeCtx.children || refTypeCtx;
647
+ // Handle class or interface type
648
+ if (children.unannClassOrInterfaceType?.[0]) {
649
+ return this.extractClassOrInterfaceType(children.unannClassOrInterfaceType[0]);
650
+ }
651
+ // Handle array type
652
+ if (children.unannArrayType?.[0]) {
653
+ const arrayChildren = children.unannArrayType[0].children || children.unannArrayType[0];
654
+ if (arrayChildren.unannClassOrInterfaceType?.[0]) {
655
+ const innerType = this.extractClassOrInterfaceType(arrayChildren.unannClassOrInterfaceType[0]);
656
+ return { type: `${innerType.type}[]`, genericType: innerType.genericType };
657
+ }
658
+ }
659
+ return { type: 'Object' };
660
+ }
661
+ extractClassOrInterfaceType(ctx) {
662
+ const children = ctx.children || ctx;
663
+ let type = '';
664
+ let genericType;
665
+ // Handle the class type
666
+ if (children.unannClassType?.[0]) {
667
+ const classTypeChildren = children.unannClassType[0].children || children.unannClassType[0];
668
+ // Get the class name from annotation chain or directly
669
+ if (classTypeChildren.Identifier) {
670
+ type = classTypeChildren.Identifier.map((id) => id.image).join('.');
671
+ }
672
+ // Check for generic type arguments
673
+ if (classTypeChildren.typeArguments?.[0]) {
674
+ genericType = this.extractTypeArguments(classTypeChildren.typeArguments[0]);
675
+ }
676
+ }
677
+ return { type: type || 'Object', genericType };
678
+ }
679
+ extractTypeArguments(ctx) {
680
+ const children = ctx.children || ctx;
681
+ const typeArgumentList = children.typeArgumentList?.[0];
682
+ if (!typeArgumentList)
683
+ return '';
684
+ const typeArgChildren = typeArgumentList.children || typeArgumentList;
685
+ const typeArguments = typeArgChildren.typeArgument || [];
686
+ const types = typeArguments.map((arg) => {
687
+ const argChildren = arg.children || arg;
688
+ if (argChildren.referenceType?.[0]) {
689
+ const refType = this.extractReferenceTypeFromGeneric(argChildren.referenceType[0]);
690
+ return refType;
691
+ }
692
+ if (argChildren.wildcard?.[0]) {
693
+ return '?';
694
+ }
695
+ return 'Object';
696
+ });
697
+ return types.join(', ');
698
+ }
699
+ extractReferenceTypeFromGeneric(refTypeCtx) {
700
+ const children = refTypeCtx.children || refTypeCtx;
701
+ if (children.classOrInterfaceType?.[0]) {
702
+ const classTypeChildren = children.classOrInterfaceType[0].children || children.classOrInterfaceType[0];
703
+ if (classTypeChildren.classType?.[0]) {
704
+ const innerClassChildren = classTypeChildren.classType[0].children || classTypeChildren.classType[0];
705
+ if (innerClassChildren.Identifier) {
706
+ let typeName = innerClassChildren.Identifier.map((id) => id.image).join('.');
707
+ // Handle nested generic types
708
+ if (innerClassChildren.typeArguments?.[0]) {
709
+ const nestedGenerics = this.extractTypeArguments(innerClassChildren.typeArguments[0]);
710
+ if (nestedGenerics) {
711
+ typeName += `<${nestedGenerics}>`;
712
+ }
713
+ }
714
+ return typeName;
715
+ }
716
+ }
717
+ }
718
+ return 'Object';
719
+ }
720
+ extractParameters(methodHeader) {
721
+ const children = methodHeader.children || methodHeader;
722
+ const declarator = children.methodDeclarator?.[0];
723
+ if (!declarator)
724
+ return [];
725
+ const declChildren = declarator.children || declarator;
726
+ const formalParameterList = declChildren.formalParameterList?.[0];
727
+ if (!formalParameterList)
728
+ return [];
729
+ const formalChildren = formalParameterList.children || formalParameterList;
730
+ const parameters = [];
731
+ // Handle regular formal parameters
732
+ if (formalChildren.formalParameter) {
733
+ for (const param of formalChildren.formalParameter) {
734
+ const parameter = this.extractFormalParameter(param);
735
+ if (parameter) {
736
+ parameters.push(parameter);
737
+ }
738
+ }
739
+ }
740
+ return parameters;
741
+ }
742
+ extractFormalParameter(paramCtx) {
743
+ let children = paramCtx.children || paramCtx;
744
+ // Handle variableParaRegularParameter wrapper
745
+ if (children.variableParaRegularParameter?.[0]) {
746
+ children = children.variableParaRegularParameter[0].children || children.variableParaRegularParameter[0];
747
+ }
748
+ // Extract annotations from variableModifier
749
+ const annotations = [];
750
+ if (children.variableModifier) {
751
+ for (const modifier of children.variableModifier) {
752
+ const modChildren = modifier.children || modifier;
753
+ if (modChildren.annotation?.[0]) {
754
+ const annotation = this.extractAnnotation(modChildren.annotation[0]);
755
+ if (annotation) {
756
+ annotations.push(annotation);
757
+ }
758
+ }
759
+ }
760
+ }
761
+ // Extract type
762
+ let type = 'Object';
763
+ let genericType;
764
+ if (children.unannType?.[0]) {
765
+ const typeInfo = this.extractType(children.unannType[0]);
766
+ type = typeInfo.type;
767
+ genericType = typeInfo.genericType;
768
+ }
769
+ // Extract parameter name
770
+ let name = '';
771
+ if (children.variableDeclaratorId?.[0]) {
772
+ const varIdChildren = children.variableDeclaratorId[0].children || children.variableDeclaratorId[0];
773
+ name = varIdChildren.Identifier?.[0]?.image || '';
774
+ }
775
+ if (!name)
776
+ return null;
777
+ return {
778
+ name,
779
+ type,
780
+ genericType,
781
+ annotations,
782
+ };
783
+ }
784
+ extractFieldNames(variableDeclaratorList) {
785
+ const children = variableDeclaratorList.children || variableDeclaratorList;
786
+ const declarators = children.variableDeclarator || [];
787
+ const names = [];
788
+ for (const declarator of declarators) {
789
+ const declChildren = declarator.children || declarator;
790
+ if (declChildren.variableDeclaratorId?.[0]) {
791
+ const varIdChildren = declChildren.variableDeclaratorId[0].children || declChildren.variableDeclaratorId[0];
792
+ const name = varIdChildren.Identifier?.[0]?.image;
793
+ if (name) {
794
+ names.push(name);
795
+ }
796
+ }
797
+ }
798
+ return names;
799
+ }
800
+ }
801
+ function parseJavaSource(sourceDir) {
802
+ const parser = new JavaFileParser(sourceDir);
803
+ return parser.parseAllJavaFiles();
804
+ }
805
+ //# sourceMappingURL=javaParser.js.map