@skillsmith/core 0.2.0 → 2.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 (233) hide show
  1. package/README.md +233 -2
  2. package/dist/.tsbuildinfo +1 -1
  3. package/dist/src/analysis/__tests__/incremental.test.d.ts +13 -0
  4. package/dist/src/analysis/__tests__/incremental.test.d.ts.map +1 -0
  5. package/dist/src/analysis/__tests__/incremental.test.js +515 -0
  6. package/dist/src/analysis/__tests__/incremental.test.js.map +1 -0
  7. package/dist/src/analysis/__tests__/integration.test.d.ts +14 -0
  8. package/dist/src/analysis/__tests__/integration.test.d.ts.map +1 -0
  9. package/dist/src/analysis/__tests__/integration.test.js +1059 -0
  10. package/dist/src/analysis/__tests__/integration.test.js.map +1 -0
  11. package/dist/src/analysis/__tests__/metrics.test.d.ts +9 -0
  12. package/dist/src/analysis/__tests__/metrics.test.d.ts.map +1 -0
  13. package/dist/src/analysis/__tests__/metrics.test.js +369 -0
  14. package/dist/src/analysis/__tests__/metrics.test.js.map +1 -0
  15. package/dist/src/analysis/__tests__/performance.test.d.ts +15 -0
  16. package/dist/src/analysis/__tests__/performance.test.d.ts.map +1 -0
  17. package/dist/src/analysis/__tests__/performance.test.js +402 -0
  18. package/dist/src/analysis/__tests__/performance.test.js.map +1 -0
  19. package/dist/src/analysis/adapters/__tests__/go.test.d.ts +12 -0
  20. package/dist/src/analysis/adapters/__tests__/go.test.d.ts.map +1 -0
  21. package/dist/src/analysis/adapters/__tests__/go.test.js +561 -0
  22. package/dist/src/analysis/adapters/__tests__/go.test.js.map +1 -0
  23. package/dist/src/analysis/adapters/__tests__/python.test.d.ts +11 -0
  24. package/dist/src/analysis/adapters/__tests__/python.test.d.ts.map +1 -0
  25. package/dist/src/analysis/adapters/__tests__/python.test.js +669 -0
  26. package/dist/src/analysis/adapters/__tests__/python.test.js.map +1 -0
  27. package/dist/src/analysis/adapters/__tests__/rust.test.d.ts +12 -0
  28. package/dist/src/analysis/adapters/__tests__/rust.test.d.ts.map +1 -0
  29. package/dist/src/analysis/adapters/__tests__/rust.test.js +676 -0
  30. package/dist/src/analysis/adapters/__tests__/rust.test.js.map +1 -0
  31. package/dist/src/analysis/adapters/__tests__/typescript.test.d.ts +14 -0
  32. package/dist/src/analysis/adapters/__tests__/typescript.test.d.ts.map +1 -0
  33. package/dist/src/analysis/adapters/__tests__/typescript.test.js +381 -0
  34. package/dist/src/analysis/adapters/__tests__/typescript.test.js.map +1 -0
  35. package/dist/src/analysis/adapters/base.d.ts +83 -0
  36. package/dist/src/analysis/adapters/base.d.ts.map +1 -0
  37. package/dist/src/analysis/adapters/base.js +40 -0
  38. package/dist/src/analysis/adapters/base.js.map +1 -0
  39. package/dist/src/analysis/adapters/factory.d.ts +150 -0
  40. package/dist/src/analysis/adapters/factory.d.ts.map +1 -0
  41. package/dist/src/analysis/adapters/factory.js +244 -0
  42. package/dist/src/analysis/adapters/factory.js.map +1 -0
  43. package/dist/src/analysis/adapters/go.d.ts +131 -0
  44. package/dist/src/analysis/adapters/go.d.ts.map +1 -0
  45. package/dist/src/analysis/adapters/go.js +414 -0
  46. package/dist/src/analysis/adapters/go.js.map +1 -0
  47. package/dist/src/analysis/adapters/index.d.ts +20 -0
  48. package/dist/src/analysis/adapters/index.d.ts.map +1 -0
  49. package/dist/src/analysis/adapters/index.js +23 -0
  50. package/dist/src/analysis/adapters/index.js.map +1 -0
  51. package/dist/src/analysis/adapters/java.d.ts +154 -0
  52. package/dist/src/analysis/adapters/java.d.ts.map +1 -0
  53. package/dist/src/analysis/adapters/java.js +407 -0
  54. package/dist/src/analysis/adapters/java.js.map +1 -0
  55. package/dist/src/analysis/adapters/python.d.ts +165 -0
  56. package/dist/src/analysis/adapters/python.d.ts.map +1 -0
  57. package/dist/src/analysis/adapters/python.js +475 -0
  58. package/dist/src/analysis/adapters/python.js.map +1 -0
  59. package/dist/src/analysis/adapters/rust.d.ts +116 -0
  60. package/dist/src/analysis/adapters/rust.d.ts.map +1 -0
  61. package/dist/src/analysis/adapters/rust.js +476 -0
  62. package/dist/src/analysis/adapters/rust.js.map +1 -0
  63. package/dist/src/analysis/adapters/typescript.d.ts +68 -0
  64. package/dist/src/analysis/adapters/typescript.d.ts.map +1 -0
  65. package/dist/src/analysis/adapters/typescript.js +79 -0
  66. package/dist/src/analysis/adapters/typescript.js.map +1 -0
  67. package/dist/src/analysis/aggregator.d.ts +193 -0
  68. package/dist/src/analysis/aggregator.d.ts.map +1 -0
  69. package/dist/src/analysis/aggregator.js +283 -0
  70. package/dist/src/analysis/aggregator.js.map +1 -0
  71. package/dist/src/analysis/cache.d.ts +180 -0
  72. package/dist/src/analysis/cache.d.ts.map +1 -0
  73. package/dist/src/analysis/cache.js +279 -0
  74. package/dist/src/analysis/cache.js.map +1 -0
  75. package/dist/src/analysis/file-streamer.d.ts +136 -0
  76. package/dist/src/analysis/file-streamer.d.ts.map +1 -0
  77. package/dist/src/analysis/file-streamer.js +291 -0
  78. package/dist/src/analysis/file-streamer.js.map +1 -0
  79. package/dist/src/analysis/incremental-parser.d.ts +186 -0
  80. package/dist/src/analysis/incremental-parser.d.ts.map +1 -0
  81. package/dist/src/analysis/incremental-parser.js +291 -0
  82. package/dist/src/analysis/incremental-parser.js.map +1 -0
  83. package/dist/src/analysis/incremental.d.ts +186 -0
  84. package/dist/src/analysis/incremental.d.ts.map +1 -0
  85. package/dist/src/analysis/incremental.js +247 -0
  86. package/dist/src/analysis/incremental.js.map +1 -0
  87. package/dist/src/analysis/index.d.ts +25 -3
  88. package/dist/src/analysis/index.d.ts.map +1 -1
  89. package/dist/src/analysis/index.js +45 -3
  90. package/dist/src/analysis/index.js.map +1 -1
  91. package/dist/src/analysis/language-detector.d.ts +92 -0
  92. package/dist/src/analysis/language-detector.d.ts.map +1 -0
  93. package/dist/src/analysis/language-detector.js +602 -0
  94. package/dist/src/analysis/language-detector.js.map +1 -0
  95. package/dist/src/analysis/memory-monitor.d.ts +199 -0
  96. package/dist/src/analysis/memory-monitor.d.ts.map +1 -0
  97. package/dist/src/analysis/memory-monitor.js +271 -0
  98. package/dist/src/analysis/memory-monitor.js.map +1 -0
  99. package/dist/src/analysis/metrics.d.ts +300 -0
  100. package/dist/src/analysis/metrics.d.ts.map +1 -0
  101. package/dist/src/analysis/metrics.js +537 -0
  102. package/dist/src/analysis/metrics.js.map +1 -0
  103. package/dist/src/analysis/router.d.ts +264 -0
  104. package/dist/src/analysis/router.d.ts.map +1 -0
  105. package/dist/src/analysis/router.js +398 -0
  106. package/dist/src/analysis/router.js.map +1 -0
  107. package/dist/src/analysis/tree-cache.d.ts +208 -0
  108. package/dist/src/analysis/tree-cache.d.ts.map +1 -0
  109. package/dist/src/analysis/tree-cache.js +288 -0
  110. package/dist/src/analysis/tree-cache.js.map +1 -0
  111. package/dist/src/analysis/tree-sitter/manager.d.ts +141 -0
  112. package/dist/src/analysis/tree-sitter/manager.d.ts.map +1 -0
  113. package/dist/src/analysis/tree-sitter/manager.js +239 -0
  114. package/dist/src/analysis/tree-sitter/manager.js.map +1 -0
  115. package/dist/src/analysis/types.d.ts +69 -6
  116. package/dist/src/analysis/types.d.ts.map +1 -1
  117. package/dist/src/analysis/types.js +23 -2
  118. package/dist/src/analysis/types.js.map +1 -1
  119. package/dist/src/analysis/worker-pool.d.ts +141 -0
  120. package/dist/src/analysis/worker-pool.d.ts.map +1 -0
  121. package/dist/src/analysis/worker-pool.js +418 -0
  122. package/dist/src/analysis/worker-pool.js.map +1 -0
  123. package/dist/src/analytics/schema.d.ts +1 -1
  124. package/dist/src/analytics/schema.d.ts.map +1 -1
  125. package/dist/src/analytics/schema.js +72 -0
  126. package/dist/src/analytics/schema.js.map +1 -1
  127. package/dist/src/api/cache.d.ts +24 -1
  128. package/dist/src/api/cache.d.ts.map +1 -1
  129. package/dist/src/api/cache.js +50 -2
  130. package/dist/src/api/cache.js.map +1 -1
  131. package/dist/src/api/client.d.ts +132 -2
  132. package/dist/src/api/client.d.ts.map +1 -1
  133. package/dist/src/api/client.js +214 -18
  134. package/dist/src/api/client.js.map +1 -1
  135. package/dist/src/api/index.d.ts +2 -0
  136. package/dist/src/api/index.d.ts.map +1 -1
  137. package/dist/src/api/index.js +7 -0
  138. package/dist/src/api/index.js.map +1 -1
  139. package/dist/src/api/types.d.ts +251 -0
  140. package/dist/src/api/types.d.ts.map +1 -0
  141. package/dist/src/api/types.js +9 -0
  142. package/dist/src/api/types.js.map +1 -0
  143. package/dist/src/benchmarks/memory/MemoryProfiler.d.ts.map +1 -1
  144. package/dist/src/benchmarks/memory/MemoryProfiler.js.map +1 -1
  145. package/dist/src/embeddings/index.d.ts.map +1 -1
  146. package/dist/src/embeddings/index.js.map +1 -1
  147. package/dist/src/errors.d.ts +1 -0
  148. package/dist/src/errors.d.ts.map +1 -1
  149. package/dist/src/errors.js +1 -0
  150. package/dist/src/errors.js.map +1 -1
  151. package/dist/src/index.d.ts +3 -3
  152. package/dist/src/index.d.ts.map +1 -1
  153. package/dist/src/index.js +4 -4
  154. package/dist/src/index.js.map +1 -1
  155. package/dist/src/repositories/IndexerRepository.d.ts.map +1 -1
  156. package/dist/src/repositories/IndexerRepository.js +1 -0
  157. package/dist/src/repositories/IndexerRepository.js.map +1 -1
  158. package/dist/src/repositories/SkillRepository.d.ts.map +1 -1
  159. package/dist/src/repositories/SkillRepository.js +1 -0
  160. package/dist/src/repositories/SkillRepository.js.map +1 -1
  161. package/dist/src/repositories/quarantine/QuarantineRepository.d.ts.map +1 -1
  162. package/dist/src/repositories/quarantine/QuarantineRepository.js.map +1 -1
  163. package/dist/src/repositories/quarantine/query-builder.d.ts.map +1 -1
  164. package/dist/src/repositories/quarantine/query-builder.js +1 -1
  165. package/dist/src/repositories/quarantine/query-builder.js.map +1 -1
  166. package/dist/src/scripts/__tests__/scan-imported-skills.test.js +3 -3
  167. package/dist/src/scripts/__tests__/scan-imported-skills.test.js.map +1 -1
  168. package/dist/src/scripts/github-import/index.js.map +1 -1
  169. package/dist/src/scripts/import-github-skills.js +1 -1
  170. package/dist/src/scripts/import-github-skills.js.map +1 -1
  171. package/dist/src/scripts/skill-scanner/reporter.d.ts.map +1 -1
  172. package/dist/src/scripts/skill-scanner/reporter.js.map +1 -1
  173. package/dist/src/scripts/skill-scanner/scanner.d.ts.map +1 -1
  174. package/dist/src/scripts/skill-scanner/scanner.js.map +1 -1
  175. package/dist/src/scripts/skill-scanner/trust-scorer.d.ts.map +1 -1
  176. package/dist/src/scripts/skill-scanner/trust-scorer.js.map +1 -1
  177. package/dist/src/scripts/validation/index.js +1 -2
  178. package/dist/src/scripts/validation/index.js.map +1 -1
  179. package/dist/src/scripts/validation/pipeline.d.ts.map +1 -1
  180. package/dist/src/scripts/validation/pipeline.js.map +1 -1
  181. package/dist/src/scripts/validation/types.d.ts +2 -2
  182. package/dist/src/security/scanner/SecurityScanner.d.ts.map +1 -1
  183. package/dist/src/security/scanner/SecurityScanner.js.map +1 -1
  184. package/dist/src/services/SearchService.d.ts.map +1 -1
  185. package/dist/src/services/SearchService.js +1 -0
  186. package/dist/src/services/SearchService.js.map +1 -1
  187. package/dist/src/session/SessionHealthMonitor.d.ts +1 -1
  188. package/dist/src/session/SessionHealthMonitor.d.ts.map +1 -1
  189. package/dist/src/session/SessionHealthMonitor.js +1 -1
  190. package/dist/src/session/SessionHealthMonitor.js.map +1 -1
  191. package/dist/src/telemetry/index.d.ts +1 -1
  192. package/dist/src/telemetry/index.d.ts.map +1 -1
  193. package/dist/src/telemetry/index.js +2 -2
  194. package/dist/src/telemetry/index.js.map +1 -1
  195. package/dist/src/telemetry/posthog.d.ts +27 -5
  196. package/dist/src/telemetry/posthog.d.ts.map +1 -1
  197. package/dist/src/telemetry/posthog.js +20 -5
  198. package/dist/src/telemetry/posthog.js.map +1 -1
  199. package/dist/src/types/skill.d.ts +3 -0
  200. package/dist/src/types/skill.d.ts.map +1 -1
  201. package/dist/src/types.d.ts +2 -1
  202. package/dist/src/types.d.ts.map +1 -1
  203. package/dist/src/types.js +2 -2
  204. package/dist/src/types.js.map +1 -1
  205. package/dist/tests/adapters-factory.test.d.ts +13 -0
  206. package/dist/tests/adapters-factory.test.d.ts.map +1 -0
  207. package/dist/tests/adapters-factory.test.js +308 -0
  208. package/dist/tests/adapters-factory.test.js.map +1 -0
  209. package/dist/tests/adapters-java.test.d.ts +13 -0
  210. package/dist/tests/adapters-java.test.d.ts.map +1 -0
  211. package/dist/tests/adapters-java.test.js +925 -0
  212. package/dist/tests/adapters-java.test.js.map +1 -0
  213. package/dist/tests/api/client.validation.test.d.ts +7 -0
  214. package/dist/tests/api/client.validation.test.d.ts.map +1 -0
  215. package/dist/tests/api/client.validation.test.js +183 -0
  216. package/dist/tests/api/client.validation.test.js.map +1 -0
  217. package/dist/tests/language-detector.test.d.ts +13 -0
  218. package/dist/tests/language-detector.test.d.ts.map +1 -0
  219. package/dist/tests/language-detector.test.js +674 -0
  220. package/dist/tests/language-detector.test.js.map +1 -0
  221. package/dist/tests/telemetry/posthog.test.d.ts +13 -0
  222. package/dist/tests/telemetry/posthog.test.d.ts.map +1 -0
  223. package/dist/tests/telemetry/posthog.test.js +600 -0
  224. package/dist/tests/telemetry/posthog.test.js.map +1 -0
  225. package/package.json +5 -6
  226. package/dist/src/security/RateLimiter.d.ts +0 -337
  227. package/dist/src/security/RateLimiter.d.ts.map +0 -1
  228. package/dist/src/security/RateLimiter.js +0 -782
  229. package/dist/src/security/RateLimiter.js.map +0 -1
  230. package/dist/src/security/scanner.d.ts +0 -151
  231. package/dist/src/security/scanner.d.ts.map +0 -1
  232. package/dist/src/security/scanner.js +0 -599
  233. package/dist/src/security/scanner.js.map +0 -1
@@ -0,0 +1,925 @@
1
+ /**
2
+ * SMI-1307: Java Language Adapter Tests
3
+ *
4
+ * Comprehensive tests for the Java adapter including:
5
+ * - Import extraction (regular, static, wildcard)
6
+ * - Export detection (class, interface, enum, @interface)
7
+ * - Function extraction (with visibility, annotations, generics)
8
+ * - pom.xml parsing (Maven dependencies)
9
+ * - build.gradle parsing (Gradle dependencies)
10
+ * - Framework detection rules
11
+ */
12
+ import { describe, it, expect, beforeEach, afterEach } from 'vitest';
13
+ import { JavaAdapter, parsePomXml, parseBuildGradle } from '../src/analysis/adapters/java.js';
14
+ describe('JavaAdapter', () => {
15
+ let adapter;
16
+ beforeEach(() => {
17
+ adapter = new JavaAdapter();
18
+ });
19
+ afterEach(() => {
20
+ adapter.dispose();
21
+ });
22
+ describe('canHandle', () => {
23
+ it('handles .java files', () => {
24
+ expect(adapter.canHandle('Main.java')).toBe(true);
25
+ expect(adapter.canHandle('UserService.java')).toBe(true);
26
+ expect(adapter.canHandle('path/to/File.java')).toBe(true);
27
+ });
28
+ it('does not handle non-Java files', () => {
29
+ expect(adapter.canHandle('main.ts')).toBe(false);
30
+ expect(adapter.canHandle('main.py')).toBe(false);
31
+ expect(adapter.canHandle('main.go')).toBe(false);
32
+ expect(adapter.canHandle('main.rs')).toBe(false);
33
+ expect(adapter.canHandle('pom.xml')).toBe(false);
34
+ expect(adapter.canHandle('build.gradle')).toBe(false);
35
+ });
36
+ it('handles case-insensitive extensions', () => {
37
+ expect(adapter.canHandle('Main.JAVA')).toBe(true);
38
+ expect(adapter.canHandle('Main.Java')).toBe(true);
39
+ });
40
+ });
41
+ describe('parseFile - imports', () => {
42
+ it('extracts regular import', () => {
43
+ const content = `
44
+ package com.example;
45
+
46
+ import java.util.List;
47
+ `;
48
+ const result = adapter.parseFile(content, 'Main.java');
49
+ expect(result.imports).toHaveLength(1);
50
+ expect(result.imports[0]).toMatchObject({
51
+ module: 'java.util.List',
52
+ namedImports: ['List'],
53
+ isTypeOnly: true,
54
+ sourceFile: 'Main.java',
55
+ });
56
+ });
57
+ it('extracts static import', () => {
58
+ const content = `
59
+ package com.example;
60
+
61
+ import static org.junit.Assert.assertEquals;
62
+ `;
63
+ const result = adapter.parseFile(content, 'Test.java');
64
+ expect(result.imports).toHaveLength(1);
65
+ expect(result.imports[0]).toMatchObject({
66
+ module: 'org.junit.Assert.assertEquals',
67
+ namedImports: ['assertEquals'],
68
+ isTypeOnly: false, // Static imports are not type-only
69
+ sourceFile: 'Test.java',
70
+ });
71
+ });
72
+ it('extracts wildcard import', () => {
73
+ const content = `
74
+ package com.example;
75
+
76
+ import java.util.*;
77
+ `;
78
+ const result = adapter.parseFile(content, 'Main.java');
79
+ expect(result.imports).toHaveLength(1);
80
+ expect(result.imports[0]).toMatchObject({
81
+ module: 'java.util',
82
+ namedImports: [],
83
+ namespaceImport: '*',
84
+ sourceFile: 'Main.java',
85
+ });
86
+ });
87
+ it('extracts static wildcard import', () => {
88
+ const content = `
89
+ package com.example;
90
+
91
+ import static java.lang.Math.*;
92
+ `;
93
+ const result = adapter.parseFile(content, 'Math.java');
94
+ expect(result.imports).toHaveLength(1);
95
+ expect(result.imports[0]).toMatchObject({
96
+ module: 'java.lang.Math',
97
+ namespaceImport: '*',
98
+ isTypeOnly: false,
99
+ });
100
+ });
101
+ it('extracts multiple imports', () => {
102
+ const content = `
103
+ package com.example;
104
+
105
+ import java.util.List;
106
+ import java.util.Map;
107
+ import java.util.ArrayList;
108
+ import static org.junit.Assert.*;
109
+ import com.google.gson.Gson;
110
+ `;
111
+ const result = adapter.parseFile(content, 'Service.java');
112
+ expect(result.imports).toHaveLength(5);
113
+ expect(result.imports.map((i) => i.module)).toContain('java.util.List');
114
+ expect(result.imports.map((i) => i.module)).toContain('java.util.Map');
115
+ expect(result.imports.map((i) => i.module)).toContain('java.util.ArrayList');
116
+ expect(result.imports.map((i) => i.module)).toContain('org.junit.Assert');
117
+ expect(result.imports.map((i) => i.module)).toContain('com.google.gson.Gson');
118
+ });
119
+ it('records line numbers for imports', () => {
120
+ const content = `package com.example;
121
+
122
+ import java.util.List;
123
+ import java.util.Map;
124
+ `;
125
+ const result = adapter.parseFile(content, 'Main.java');
126
+ expect(result.imports[0].line).toBe(3);
127
+ expect(result.imports[1].line).toBe(4);
128
+ });
129
+ });
130
+ describe('parseFile - exports', () => {
131
+ it('detects public class', () => {
132
+ const content = `
133
+ package com.example;
134
+
135
+ public class UserService {
136
+ // class body
137
+ }
138
+ `;
139
+ const result = adapter.parseFile(content, 'UserService.java');
140
+ expect(result.exports).toHaveLength(1);
141
+ expect(result.exports[0]).toMatchObject({
142
+ name: 'UserService',
143
+ kind: 'class',
144
+ isDefault: false,
145
+ visibility: 'public',
146
+ sourceFile: 'UserService.java',
147
+ });
148
+ });
149
+ it('detects package-private class', () => {
150
+ const content = `
151
+ package com.example;
152
+
153
+ class InternalHelper {
154
+ // class body
155
+ }
156
+ `;
157
+ const result = adapter.parseFile(content, 'InternalHelper.java');
158
+ expect(result.exports).toHaveLength(1);
159
+ expect(result.exports[0]).toMatchObject({
160
+ name: 'InternalHelper',
161
+ kind: 'class',
162
+ visibility: 'internal',
163
+ });
164
+ });
165
+ it('detects public interface', () => {
166
+ const content = `
167
+ package com.example;
168
+
169
+ public interface UserRepository {
170
+ User findById(Long id);
171
+ }
172
+ `;
173
+ const result = adapter.parseFile(content, 'UserRepository.java');
174
+ expect(result.exports).toHaveLength(1);
175
+ expect(result.exports[0]).toMatchObject({
176
+ name: 'UserRepository',
177
+ kind: 'interface',
178
+ visibility: 'public',
179
+ });
180
+ });
181
+ it('detects public enum', () => {
182
+ const content = `
183
+ package com.example;
184
+
185
+ public enum Status {
186
+ ACTIVE,
187
+ INACTIVE,
188
+ PENDING
189
+ }
190
+ `;
191
+ const result = adapter.parseFile(content, 'Status.java');
192
+ expect(result.exports).toHaveLength(1);
193
+ expect(result.exports[0]).toMatchObject({
194
+ name: 'Status',
195
+ kind: 'enum',
196
+ visibility: 'public',
197
+ });
198
+ });
199
+ it('detects annotation type', () => {
200
+ const content = `
201
+ package com.example;
202
+
203
+ public @interface MyAnnotation {
204
+ String value();
205
+ }
206
+ `;
207
+ const result = adapter.parseFile(content, 'MyAnnotation.java');
208
+ expect(result.exports).toHaveLength(1);
209
+ expect(result.exports[0]).toMatchObject({
210
+ name: 'MyAnnotation',
211
+ kind: 'interface',
212
+ visibility: 'public',
213
+ });
214
+ });
215
+ it('detects abstract class', () => {
216
+ const content = `
217
+ package com.example;
218
+
219
+ public abstract class BaseService {
220
+ public abstract void process();
221
+ }
222
+ `;
223
+ const result = adapter.parseFile(content, 'BaseService.java');
224
+ expect(result.exports).toHaveLength(1);
225
+ expect(result.exports[0]).toMatchObject({
226
+ name: 'BaseService',
227
+ kind: 'class',
228
+ visibility: 'public',
229
+ });
230
+ });
231
+ it('detects generic class', () => {
232
+ const content = `
233
+ package com.example;
234
+
235
+ public class Repository<T, ID> {
236
+ // generic class body
237
+ }
238
+ `;
239
+ const result = adapter.parseFile(content, 'Repository.java');
240
+ expect(result.exports).toHaveLength(1);
241
+ expect(result.exports[0]).toMatchObject({
242
+ name: 'Repository',
243
+ kind: 'class',
244
+ visibility: 'public',
245
+ });
246
+ });
247
+ it('detects multiple classes in file', () => {
248
+ const content = `
249
+ package com.example;
250
+
251
+ public class MainClass {
252
+ }
253
+
254
+ class HelperClass {
255
+ }
256
+
257
+ interface SomeInterface {
258
+ }
259
+ `;
260
+ const result = adapter.parseFile(content, 'MainClass.java');
261
+ expect(result.exports).toHaveLength(3);
262
+ expect(result.exports.map((e) => e.name)).toEqual([
263
+ 'MainClass',
264
+ 'HelperClass',
265
+ 'SomeInterface',
266
+ ]);
267
+ });
268
+ });
269
+ describe('parseFile - functions', () => {
270
+ it('extracts public method', () => {
271
+ const content = `
272
+ package com.example;
273
+
274
+ public class Service {
275
+ public void doSomething() {
276
+ }
277
+ }
278
+ `;
279
+ const result = adapter.parseFile(content, 'Service.java');
280
+ expect(result.functions).toHaveLength(1);
281
+ expect(result.functions[0]).toMatchObject({
282
+ name: 'doSomething',
283
+ parameterCount: 0,
284
+ isAsync: false,
285
+ isExported: true,
286
+ sourceFile: 'Service.java',
287
+ });
288
+ });
289
+ it('extracts private method', () => {
290
+ const content = `
291
+ package com.example;
292
+
293
+ public class Service {
294
+ private void helperMethod() {
295
+ }
296
+ }
297
+ `;
298
+ const result = adapter.parseFile(content, 'Service.java');
299
+ expect(result.functions).toHaveLength(1);
300
+ expect(result.functions[0]).toMatchObject({
301
+ name: 'helperMethod',
302
+ isExported: false,
303
+ });
304
+ });
305
+ it('extracts protected method', () => {
306
+ const content = `
307
+ package com.example;
308
+
309
+ public class Service {
310
+ protected void inheritableMethod() {
311
+ }
312
+ }
313
+ `;
314
+ const result = adapter.parseFile(content, 'Service.java');
315
+ expect(result.functions).toHaveLength(1);
316
+ expect(result.functions[0]).toMatchObject({
317
+ name: 'inheritableMethod',
318
+ isExported: true, // protected is considered exported
319
+ });
320
+ });
321
+ it('extracts method with parameters', () => {
322
+ const content = `
323
+ package com.example;
324
+
325
+ public class Service {
326
+ public String greet(String name, int age) {
327
+ return "Hello " + name;
328
+ }
329
+ }
330
+ `;
331
+ const result = adapter.parseFile(content, 'Service.java');
332
+ expect(result.functions).toHaveLength(1);
333
+ expect(result.functions[0]).toMatchObject({
334
+ name: 'greet',
335
+ parameterCount: 2,
336
+ });
337
+ });
338
+ it('extracts static method', () => {
339
+ const content = `
340
+ package com.example;
341
+
342
+ public class Utils {
343
+ public static String format(String input) {
344
+ return input.trim();
345
+ }
346
+ }
347
+ `;
348
+ const result = adapter.parseFile(content, 'Utils.java');
349
+ expect(result.functions).toHaveLength(1);
350
+ expect(result.functions[0]).toMatchObject({
351
+ name: 'format',
352
+ parameterCount: 1,
353
+ isExported: true,
354
+ });
355
+ });
356
+ it('extracts generic method', () => {
357
+ const content = `
358
+ package com.example;
359
+
360
+ public class Utils {
361
+ public <T> List<T> filter(List<T> items, Predicate<T> predicate) {
362
+ return items.stream().filter(predicate).collect(Collectors.toList());
363
+ }
364
+ }
365
+ `;
366
+ const result = adapter.parseFile(content, 'Utils.java');
367
+ expect(result.functions).toHaveLength(1);
368
+ expect(result.functions[0]).toMatchObject({
369
+ name: 'filter',
370
+ parameterCount: 2,
371
+ });
372
+ });
373
+ it('extracts method with annotations', () => {
374
+ const content = `
375
+ package com.example;
376
+
377
+ public class Service {
378
+ @Override
379
+ public String toString() {
380
+ return "Service";
381
+ }
382
+
383
+ @Test
384
+ @DisplayName("Test method")
385
+ public void testSomething() {
386
+ }
387
+ }
388
+ `;
389
+ const result = adapter.parseFile(content, 'Service.java');
390
+ expect(result.functions).toHaveLength(2);
391
+ expect(result.functions[0].decorators).toEqual(['Override']);
392
+ expect(result.functions[1].decorators).toEqual(['Test', 'DisplayName']);
393
+ });
394
+ it('extracts abstract method', () => {
395
+ const content = `
396
+ package com.example;
397
+
398
+ public abstract class BaseService {
399
+ public abstract void process();
400
+ }
401
+ `;
402
+ const result = adapter.parseFile(content, 'BaseService.java');
403
+ expect(result.functions).toHaveLength(1);
404
+ expect(result.functions[0]).toMatchObject({
405
+ name: 'process',
406
+ parameterCount: 0,
407
+ });
408
+ });
409
+ it('handles generics in parameters correctly', () => {
410
+ const content = `
411
+ package com.example;
412
+
413
+ public class Service {
414
+ public void process(Map<String, List<Integer>> data, Function<String, Integer> mapper) {
415
+ }
416
+ }
417
+ `;
418
+ const result = adapter.parseFile(content, 'Service.java');
419
+ expect(result.functions).toHaveLength(1);
420
+ expect(result.functions[0]).toMatchObject({
421
+ name: 'process',
422
+ parameterCount: 2, // Should count correctly despite nested generics
423
+ });
424
+ });
425
+ it('records line numbers for methods', () => {
426
+ const content = `package com.example;
427
+
428
+ public class Service {
429
+ public void first() {}
430
+
431
+ public void second() {}
432
+
433
+ public void third() {}
434
+ }
435
+ `;
436
+ const result = adapter.parseFile(content, 'Service.java');
437
+ expect(result.functions).toHaveLength(3);
438
+ expect(result.functions[0].line).toBe(4);
439
+ expect(result.functions[1].line).toBe(6);
440
+ expect(result.functions[2].line).toBe(8);
441
+ });
442
+ });
443
+ describe('parseFile - complex cases', () => {
444
+ it('parses a complete Spring Boot controller', () => {
445
+ const content = `
446
+ package com.example.controller;
447
+
448
+ import org.springframework.beans.factory.annotation.Autowired;
449
+ import org.springframework.web.bind.annotation.*;
450
+ import java.util.List;
451
+
452
+ @RestController
453
+ @RequestMapping("/api/users")
454
+ public class UserController {
455
+
456
+ @Autowired
457
+ private UserService userService;
458
+
459
+ @GetMapping
460
+ public List<User> getAllUsers() {
461
+ return userService.findAll();
462
+ }
463
+
464
+ @GetMapping("/{id}")
465
+ public User getUserById(@PathVariable Long id) {
466
+ return userService.findById(id);
467
+ }
468
+
469
+ @PostMapping
470
+ public User createUser(@RequestBody User user) {
471
+ return userService.save(user);
472
+ }
473
+
474
+ @DeleteMapping("/{id}")
475
+ public void deleteUser(@PathVariable Long id) {
476
+ userService.deleteById(id);
477
+ }
478
+ }
479
+ `;
480
+ const result = adapter.parseFile(content, 'UserController.java');
481
+ // Imports
482
+ expect(result.imports.length).toBeGreaterThanOrEqual(3);
483
+ expect(result.imports.map((i) => i.module)).toContain('org.springframework.beans.factory.annotation.Autowired');
484
+ // Exports (class)
485
+ expect(result.exports).toHaveLength(1);
486
+ expect(result.exports[0].name).toBe('UserController');
487
+ // Functions
488
+ expect(result.functions).toHaveLength(4);
489
+ expect(result.functions.map((f) => f.name)).toEqual([
490
+ 'getAllUsers',
491
+ 'getUserById',
492
+ 'createUser',
493
+ 'deleteUser',
494
+ ]);
495
+ // Check annotations
496
+ expect(result.functions[0].decorators).toEqual(['GetMapping']);
497
+ expect(result.functions[2].decorators).toEqual(['PostMapping']);
498
+ });
499
+ it('parses JUnit test class', () => {
500
+ const content = `
501
+ package com.example.test;
502
+
503
+ import org.junit.jupiter.api.*;
504
+ import static org.junit.jupiter.api.Assertions.*;
505
+
506
+ class UserServiceTest {
507
+
508
+ private UserService userService;
509
+
510
+ @BeforeEach
511
+ void setUp() {
512
+ userService = new UserService();
513
+ }
514
+
515
+ @Test
516
+ @DisplayName("Should find user by ID")
517
+ void testFindById() {
518
+ User user = userService.findById(1L);
519
+ assertNotNull(user);
520
+ }
521
+
522
+ @Test
523
+ void testCreateUser() {
524
+ User user = new User("John");
525
+ User saved = userService.save(user);
526
+ assertEquals("John", saved.getName());
527
+ }
528
+ }
529
+ `;
530
+ const result = adapter.parseFile(content, 'UserServiceTest.java');
531
+ expect(result.imports).toHaveLength(2);
532
+ expect(result.exports).toHaveLength(1);
533
+ expect(result.exports[0].name).toBe('UserServiceTest');
534
+ expect(result.functions).toHaveLength(3);
535
+ expect(result.functions[0].decorators).toEqual(['BeforeEach']);
536
+ expect(result.functions[1].decorators).toEqual(['Test', 'DisplayName']);
537
+ expect(result.functions[2].decorators).toEqual(['Test']);
538
+ });
539
+ });
540
+ describe('getFrameworkRules', () => {
541
+ it('includes Spring Boot framework detection', () => {
542
+ const rules = adapter.getFrameworkRules();
543
+ const springBoot = rules.find((r) => r.name === 'Spring Boot');
544
+ expect(springBoot).toBeDefined();
545
+ expect(springBoot?.depIndicators).toContain('spring-boot');
546
+ expect(springBoot?.importIndicators).toContain('org.springframework.boot');
547
+ });
548
+ it('includes JUnit detection', () => {
549
+ const rules = adapter.getFrameworkRules();
550
+ const junit = rules.find((r) => r.name === 'JUnit');
551
+ expect(junit).toBeDefined();
552
+ expect(junit?.depIndicators).toContain('junit');
553
+ expect(junit?.importIndicators).toContain('org.junit');
554
+ });
555
+ it('includes Hibernate detection', () => {
556
+ const rules = adapter.getFrameworkRules();
557
+ const hibernate = rules.find((r) => r.name === 'Hibernate');
558
+ expect(hibernate).toBeDefined();
559
+ expect(hibernate?.depIndicators).toContain('hibernate');
560
+ expect(hibernate?.importIndicators).toContain('javax.persistence');
561
+ });
562
+ it('includes Lombok detection', () => {
563
+ const rules = adapter.getFrameworkRules();
564
+ const lombok = rules.find((r) => r.name === 'Lombok');
565
+ expect(lombok).toBeDefined();
566
+ expect(lombok?.depIndicators).toContain('lombok');
567
+ expect(lombok?.importIndicators).toContain('lombok');
568
+ });
569
+ it('includes Quarkus detection', () => {
570
+ const rules = adapter.getFrameworkRules();
571
+ const quarkus = rules.find((r) => r.name === 'Quarkus');
572
+ expect(quarkus).toBeDefined();
573
+ expect(quarkus?.depIndicators).toContain('io.quarkus');
574
+ });
575
+ it('includes Mockito detection', () => {
576
+ const rules = adapter.getFrameworkRules();
577
+ const mockito = rules.find((r) => r.name === 'Mockito');
578
+ expect(mockito).toBeDefined();
579
+ expect(mockito?.importIndicators).toContain('org.mockito');
580
+ });
581
+ });
582
+ describe('parseIncremental', () => {
583
+ it('returns same result as parseFile', () => {
584
+ const content = `
585
+ package com.example;
586
+
587
+ import java.util.List;
588
+
589
+ public class Service {
590
+ public void process() {
591
+ }
592
+ }
593
+ `;
594
+ const parseResult = adapter.parseFile(content, 'Service.java');
595
+ const incrementalResult = adapter.parseIncremental(content, 'Service.java');
596
+ expect(incrementalResult).toEqual(parseResult);
597
+ });
598
+ });
599
+ });
600
+ describe('parsePomXml', () => {
601
+ it('extracts single dependency', () => {
602
+ const content = `
603
+ <?xml version="1.0" encoding="UTF-8"?>
604
+ <project>
605
+ <dependencies>
606
+ <dependency>
607
+ <groupId>org.springframework.boot</groupId>
608
+ <artifactId>spring-boot-starter</artifactId>
609
+ <version>3.0.0</version>
610
+ </dependency>
611
+ </dependencies>
612
+ </project>
613
+ `;
614
+ const result = parsePomXml(content);
615
+ expect(result).toHaveLength(1);
616
+ expect(result[0]).toEqual({
617
+ name: 'org.springframework.boot:spring-boot-starter',
618
+ version: '3.0.0',
619
+ isDev: false,
620
+ });
621
+ });
622
+ it('extracts multiple dependencies', () => {
623
+ const content = `
624
+ <?xml version="1.0" encoding="UTF-8"?>
625
+ <project>
626
+ <dependencies>
627
+ <dependency>
628
+ <groupId>org.springframework.boot</groupId>
629
+ <artifactId>spring-boot-starter-web</artifactId>
630
+ <version>3.0.0</version>
631
+ </dependency>
632
+ <dependency>
633
+ <groupId>com.google.guava</groupId>
634
+ <artifactId>guava</artifactId>
635
+ <version>31.1-jre</version>
636
+ </dependency>
637
+ </dependencies>
638
+ </project>
639
+ `;
640
+ const result = parsePomXml(content);
641
+ expect(result).toHaveLength(2);
642
+ expect(result.map((d) => d.name)).toContain('org.springframework.boot:spring-boot-starter-web');
643
+ expect(result.map((d) => d.name)).toContain('com.google.guava:guava');
644
+ });
645
+ it('identifies test scope dependencies as dev', () => {
646
+ const content = `
647
+ <?xml version="1.0" encoding="UTF-8"?>
648
+ <project>
649
+ <dependencies>
650
+ <dependency>
651
+ <groupId>org.junit.jupiter</groupId>
652
+ <artifactId>junit-jupiter</artifactId>
653
+ <version>5.9.0</version>
654
+ <scope>test</scope>
655
+ </dependency>
656
+ </dependencies>
657
+ </project>
658
+ `;
659
+ const result = parsePomXml(content);
660
+ expect(result).toHaveLength(1);
661
+ expect(result[0].isDev).toBe(true);
662
+ });
663
+ it('identifies provided scope dependencies as dev', () => {
664
+ const content = `
665
+ <?xml version="1.0" encoding="UTF-8"?>
666
+ <project>
667
+ <dependencies>
668
+ <dependency>
669
+ <groupId>javax.servlet</groupId>
670
+ <artifactId>javax.servlet-api</artifactId>
671
+ <version>4.0.1</version>
672
+ <scope>provided</scope>
673
+ </dependency>
674
+ </dependencies>
675
+ </project>
676
+ `;
677
+ const result = parsePomXml(content);
678
+ expect(result).toHaveLength(1);
679
+ expect(result[0].isDev).toBe(true);
680
+ });
681
+ it('handles dependencies without version', () => {
682
+ const content = `
683
+ <?xml version="1.0" encoding="UTF-8"?>
684
+ <project>
685
+ <dependencies>
686
+ <dependency>
687
+ <groupId>org.springframework.boot</groupId>
688
+ <artifactId>spring-boot-starter</artifactId>
689
+ </dependency>
690
+ </dependencies>
691
+ </project>
692
+ `;
693
+ const result = parsePomXml(content);
694
+ expect(result).toHaveLength(1);
695
+ expect(result[0].version).toBe('unspecified');
696
+ });
697
+ it('ignores XML comments', () => {
698
+ const content = `
699
+ <?xml version="1.0" encoding="UTF-8"?>
700
+ <project>
701
+ <dependencies>
702
+ <!-- This is commented out
703
+ <dependency>
704
+ <groupId>com.example</groupId>
705
+ <artifactId>commented-out</artifactId>
706
+ <version>1.0.0</version>
707
+ </dependency>
708
+ -->
709
+ <dependency>
710
+ <groupId>com.example</groupId>
711
+ <artifactId>real-dependency</artifactId>
712
+ <version>2.0.0</version>
713
+ </dependency>
714
+ </dependencies>
715
+ </project>
716
+ `;
717
+ const result = parsePomXml(content);
718
+ expect(result).toHaveLength(1);
719
+ expect(result[0].name).toBe('com.example:real-dependency');
720
+ });
721
+ it('parses complete pom.xml with various scopes', () => {
722
+ const content = `
723
+ <?xml version="1.0" encoding="UTF-8"?>
724
+ <project xmlns="http://maven.apache.org/POM/4.0.0">
725
+ <modelVersion>4.0.0</modelVersion>
726
+ <groupId>com.example</groupId>
727
+ <artifactId>myapp</artifactId>
728
+ <version>1.0.0</version>
729
+
730
+ <dependencies>
731
+ <dependency>
732
+ <groupId>org.springframework.boot</groupId>
733
+ <artifactId>spring-boot-starter-web</artifactId>
734
+ <version>3.0.0</version>
735
+ </dependency>
736
+ <dependency>
737
+ <groupId>org.springframework.boot</groupId>
738
+ <artifactId>spring-boot-starter-data-jpa</artifactId>
739
+ <version>3.0.0</version>
740
+ </dependency>
741
+ <dependency>
742
+ <groupId>org.projectlombok</groupId>
743
+ <artifactId>lombok</artifactId>
744
+ <version>1.18.24</version>
745
+ <scope>provided</scope>
746
+ </dependency>
747
+ <dependency>
748
+ <groupId>org.junit.jupiter</groupId>
749
+ <artifactId>junit-jupiter</artifactId>
750
+ <version>5.9.0</version>
751
+ <scope>test</scope>
752
+ </dependency>
753
+ </dependencies>
754
+ </project>
755
+ `;
756
+ const result = parsePomXml(content);
757
+ expect(result).toHaveLength(4);
758
+ expect(result.filter((d) => d.isDev)).toHaveLength(2);
759
+ expect(result.filter((d) => !d.isDev)).toHaveLength(2);
760
+ });
761
+ });
762
+ describe('parseBuildGradle', () => {
763
+ it('extracts implementation dependency with single quotes', () => {
764
+ const content = `
765
+ plugins {
766
+ id 'java'
767
+ }
768
+
769
+ dependencies {
770
+ implementation 'org.springframework.boot:spring-boot-starter:3.0.0'
771
+ }
772
+ `;
773
+ const result = parseBuildGradle(content);
774
+ expect(result).toHaveLength(1);
775
+ expect(result[0]).toEqual({
776
+ name: 'org.springframework.boot:spring-boot-starter',
777
+ version: '3.0.0',
778
+ isDev: false,
779
+ });
780
+ });
781
+ it('extracts implementation dependency with double quotes', () => {
782
+ const content = `
783
+ plugins {
784
+ id 'java'
785
+ }
786
+
787
+ dependencies {
788
+ implementation "org.springframework.boot:spring-boot-starter:3.0.0"
789
+ }
790
+ `;
791
+ const result = parseBuildGradle(content);
792
+ expect(result).toHaveLength(1);
793
+ expect(result[0].name).toBe('org.springframework.boot:spring-boot-starter');
794
+ });
795
+ it('extracts Kotlin DSL style dependency', () => {
796
+ const content = `
797
+ plugins {
798
+ kotlin("jvm")
799
+ }
800
+
801
+ dependencies {
802
+ implementation("org.springframework.boot:spring-boot-starter:3.0.0")
803
+ }
804
+ `;
805
+ const result = parseBuildGradle(content);
806
+ expect(result).toHaveLength(1);
807
+ expect(result[0].name).toBe('org.springframework.boot:spring-boot-starter');
808
+ });
809
+ it('identifies testImplementation as dev dependency', () => {
810
+ const content = `
811
+ dependencies {
812
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0'
813
+ }
814
+ `;
815
+ const result = parseBuildGradle(content);
816
+ expect(result).toHaveLength(1);
817
+ expect(result[0].isDev).toBe(true);
818
+ });
819
+ it('extracts api dependency', () => {
820
+ const content = `
821
+ dependencies {
822
+ api 'org.apache.commons:commons-lang3:3.12.0'
823
+ }
824
+ `;
825
+ const result = parseBuildGradle(content);
826
+ expect(result).toHaveLength(1);
827
+ expect(result[0].isDev).toBe(false);
828
+ });
829
+ it('extracts annotationProcessor as dev dependency', () => {
830
+ const content = `
831
+ dependencies {
832
+ annotationProcessor 'org.projectlombok:lombok:1.18.24'
833
+ }
834
+ `;
835
+ const result = parseBuildGradle(content);
836
+ expect(result).toHaveLength(1);
837
+ expect(result[0].isDev).toBe(true);
838
+ });
839
+ it('handles dependency without version', () => {
840
+ const content = `
841
+ dependencies {
842
+ implementation 'org.springframework.boot:spring-boot-starter'
843
+ }
844
+ `;
845
+ const result = parseBuildGradle(content);
846
+ expect(result).toHaveLength(1);
847
+ expect(result[0].version).toBe('unspecified');
848
+ });
849
+ it('extracts multiple dependencies', () => {
850
+ const content = `
851
+ dependencies {
852
+ implementation 'org.springframework.boot:spring-boot-starter-web:3.0.0'
853
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.0'
854
+ runtimeOnly 'org.postgresql:postgresql:42.5.0'
855
+ testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.0'
856
+ testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0'
857
+ }
858
+ `;
859
+ const result = parseBuildGradle(content);
860
+ expect(result).toHaveLength(5);
861
+ expect(result.filter((d) => d.isDev)).toHaveLength(2);
862
+ expect(result.filter((d) => !d.isDev)).toHaveLength(3);
863
+ });
864
+ it('extracts Kotlin DSL with named parameters', () => {
865
+ const content = `
866
+ dependencies {
867
+ implementation(group = "org.springframework.boot", name = "spring-boot-starter", version = "3.0.0")
868
+ testImplementation(group = "org.junit.jupiter", name = "junit-jupiter", version = "5.9.0")
869
+ }
870
+ `;
871
+ const result = parseBuildGradle(content);
872
+ expect(result).toHaveLength(2);
873
+ expect(result[0]).toEqual({
874
+ name: 'org.springframework.boot:spring-boot-starter',
875
+ version: '3.0.0',
876
+ isDev: false,
877
+ });
878
+ expect(result[1].isDev).toBe(true);
879
+ });
880
+ it('ignores project dependencies', () => {
881
+ const content = `
882
+ dependencies {
883
+ implementation project(':core')
884
+ implementation 'org.springframework.boot:spring-boot-starter:3.0.0'
885
+ }
886
+ `;
887
+ const result = parseBuildGradle(content);
888
+ // Should only capture the external dependency, not the project reference
889
+ expect(result).toHaveLength(1);
890
+ expect(result[0].name).toBe('org.springframework.boot:spring-boot-starter');
891
+ });
892
+ it('parses complete build.gradle file', () => {
893
+ const content = `
894
+ plugins {
895
+ id 'java'
896
+ id 'org.springframework.boot' version '3.0.0'
897
+ }
898
+
899
+ group = 'com.example'
900
+ version = '1.0.0'
901
+
902
+ repositories {
903
+ mavenCentral()
904
+ }
905
+
906
+ dependencies {
907
+ implementation 'org.springframework.boot:spring-boot-starter-web:3.0.0'
908
+ implementation 'org.springframework.boot:spring-boot-starter-data-jpa:3.0.0'
909
+ compileOnly 'org.projectlombok:lombok:1.18.24'
910
+ annotationProcessor 'org.projectlombok:lombok:1.18.24'
911
+ runtimeOnly 'org.postgresql:postgresql:42.5.0'
912
+ testImplementation 'org.springframework.boot:spring-boot-starter-test:3.0.0'
913
+ }
914
+
915
+ test {
916
+ useJUnitPlatform()
917
+ }
918
+ `;
919
+ const result = parseBuildGradle(content);
920
+ expect(result.length).toBeGreaterThanOrEqual(5);
921
+ expect(result.map((d) => d.name)).toContain('org.springframework.boot:spring-boot-starter-web');
922
+ expect(result.map((d) => d.name)).toContain('org.projectlombok:lombok');
923
+ });
924
+ });
925
+ //# sourceMappingURL=adapters-java.test.js.map