@getmikk/core 2.0.14 → 2.0.15

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 (64) hide show
  1. package/README.md +4 -4
  2. package/package.json +2 -1
  3. package/src/analysis/type-flow.ts +1 -1
  4. package/src/cache/incremental-cache.ts +86 -80
  5. package/src/contract/contract-reader.ts +1 -0
  6. package/src/contract/lock-compiler.ts +95 -13
  7. package/src/contract/schema.ts +2 -0
  8. package/src/error-handler.ts +2 -1
  9. package/src/graph/cluster-detector.ts +2 -4
  10. package/src/graph/dead-code-detector.ts +303 -117
  11. package/src/graph/graph-builder.ts +21 -161
  12. package/src/graph/impact-analyzer.ts +1 -0
  13. package/src/graph/index.ts +2 -0
  14. package/src/graph/rich-function-index.ts +1080 -0
  15. package/src/graph/symbol-table.ts +252 -0
  16. package/src/hash/hash-store.ts +1 -0
  17. package/src/index.ts +2 -0
  18. package/src/parser/base-extractor.ts +19 -0
  19. package/src/parser/boundary-checker.ts +31 -12
  20. package/src/parser/error-recovery.ts +5 -4
  21. package/src/parser/function-body-extractor.ts +248 -0
  22. package/src/parser/go/go-extractor.ts +249 -676
  23. package/src/parser/index.ts +132 -318
  24. package/src/parser/language-registry.ts +57 -0
  25. package/src/parser/oxc-parser.ts +166 -28
  26. package/src/parser/oxc-resolver.ts +179 -11
  27. package/src/parser/parser-constants.ts +1 -0
  28. package/src/parser/rust/rust-extractor.ts +109 -0
  29. package/src/parser/tree-sitter/parser.ts +369 -62
  30. package/src/parser/tree-sitter/queries.ts +106 -10
  31. package/src/parser/types.ts +20 -1
  32. package/src/search/bm25.ts +21 -8
  33. package/src/search/direct-search.ts +472 -0
  34. package/src/search/embedding-provider.ts +249 -0
  35. package/src/search/index.ts +12 -0
  36. package/src/search/semantic-search.ts +435 -0
  37. package/src/utils/artifact-transaction.ts +1 -0
  38. package/src/utils/atomic-write.ts +1 -0
  39. package/src/utils/errors.ts +89 -4
  40. package/src/utils/fs.ts +104 -50
  41. package/src/utils/json.ts +1 -0
  42. package/src/utils/language-registry.ts +84 -6
  43. package/src/utils/path.ts +26 -0
  44. package/tests/dead-code.test.ts +3 -2
  45. package/tests/direct-search.test.ts +435 -0
  46. package/tests/error-recovery.test.ts +143 -0
  47. package/tests/fixtures/simple-api/src/index.ts +1 -1
  48. package/tests/go-parser.test.ts +19 -335
  49. package/tests/js-parser.test.ts +18 -1089
  50. package/tests/language-registry-all.test.ts +276 -0
  51. package/tests/language-registry.test.ts +6 -4
  52. package/tests/parse-diagnostics.test.ts +9 -96
  53. package/tests/parser.test.ts +42 -771
  54. package/tests/polyglot-parser.test.ts +117 -0
  55. package/tests/rich-function-index.test.ts +703 -0
  56. package/tests/tree-sitter-parser.test.ts +108 -80
  57. package/tests/ts-parser.test.ts +8 -8
  58. package/tests/verification.test.ts +175 -0
  59. package/src/parser/base-parser.ts +0 -16
  60. package/src/parser/go/go-parser.ts +0 -43
  61. package/src/parser/javascript/js-extractor.ts +0 -278
  62. package/src/parser/javascript/js-parser.ts +0 -101
  63. package/src/parser/typescript/ts-extractor.ts +0 -447
  64. package/src/parser/typescript/ts-parser.ts +0 -36
@@ -0,0 +1,276 @@
1
+ import { describe, test, expect } from 'bun:test'
2
+ import {
3
+ languageForExtension,
4
+ parserKindForExtension,
5
+ isTreeSitterExtension,
6
+ toParsedFileLanguage,
7
+ type RegistryLanguage,
8
+ type ParsedFileLanguage
9
+ } from '../src/utils/language-registry.js'
10
+
11
+ describe('Language Registry - All 22 Languages', () => {
12
+ describe('Core Languages (Top 10)', () => {
13
+ test('JavaScript/TypeScript uses oxc parser (polyglot)', () => {
14
+ expect(parserKindForExtension('.js')).toBe('oxc')
15
+ expect(parserKindForExtension('.jsx')).toBe('oxc')
16
+ expect(parserKindForExtension('.ts')).toBe('oxc')
17
+ expect(parserKindForExtension('.tsx')).toBe('oxc')
18
+ expect(parserKindForExtension('.mjs')).toBe('oxc')
19
+ expect(parserKindForExtension('.cjs')).toBe('oxc')
20
+ })
21
+
22
+ test('TypeScript/JavaScript files detected', () => {
23
+ const detected = languageForExtension('.js')
24
+ expect(['typescript', 'javascript']).toContain(detected)
25
+ expect(languageForExtension('.ts')).toBe('typescript')
26
+ })
27
+
28
+ test('Python support', () => {
29
+ expect(languageForExtension('.py')).toBe('python')
30
+ expect(languageForExtension('.pyw')).toBe('python')
31
+ expect(parserKindForExtension('.py')).toBe('tree-sitter')
32
+ expect(isTreeSitterExtension('.py')).toBe(true)
33
+ })
34
+
35
+ test('Java support', () => {
36
+ expect(languageForExtension('.java')).toBe('java')
37
+ expect(parserKindForExtension('.java')).toBe('tree-sitter')
38
+ expect(isTreeSitterExtension('.java')).toBe(true)
39
+ })
40
+
41
+ test('C# support', () => {
42
+ expect(languageForExtension('.cs')).toBe('csharp')
43
+ expect(parserKindForExtension('.cs')).toBe('tree-sitter')
44
+ expect(isTreeSitterExtension('.cs')).toBe(true)
45
+ })
46
+
47
+ test('C/C++ support', () => {
48
+ expect(languageForExtension('.c')).toBe('c')
49
+ expect(languageForExtension('.cpp')).toBe('cpp')
50
+ expect(languageForExtension('.cc')).toBe('cpp')
51
+ expect(languageForExtension('.h')).toBe('c')
52
+ expect(languageForExtension('.hpp')).toBe('cpp')
53
+ })
54
+
55
+ test('PHP support', () => {
56
+ expect(languageForExtension('.php')).toBe('php')
57
+ expect(parserKindForExtension('.php')).toBe('tree-sitter')
58
+ })
59
+
60
+ test('Ruby support', () => {
61
+ expect(languageForExtension('.rb')).toBe('ruby')
62
+ expect(parserKindForExtension('.rb')).toBe('tree-sitter')
63
+ })
64
+
65
+ test('Swift support', () => {
66
+ expect(languageForExtension('.swift')).toBe('swift')
67
+ expect(parserKindForExtension('.swift')).toBe('tree-sitter')
68
+ })
69
+
70
+ test('Go support', () => {
71
+ expect(languageForExtension('.go')).toBe('go')
72
+ expect(parserKindForExtension('.go')).toBe('go')
73
+ })
74
+ })
75
+
76
+ describe('JVM Languages', () => {
77
+ test('Kotlin support', () => {
78
+ expect(languageForExtension('.kt')).toBe('kotlin')
79
+ expect(languageForExtension('.kts')).toBe('kotlin')
80
+ expect(parserKindForExtension('.kt')).toBe('tree-sitter')
81
+ })
82
+
83
+ test('Scala support', () => {
84
+ expect(languageForExtension('.scala')).toBe('scala')
85
+ expect(languageForExtension('.sc')).toBe('scala')
86
+ expect(parserKindForExtension('.scala')).toBe('tree-sitter')
87
+ })
88
+ })
89
+
90
+ describe('Systems Languages', () => {
91
+ test('Rust support', () => {
92
+ expect(languageForExtension('.rs')).toBe('rust')
93
+ expect(parserKindForExtension('.rs')).toBe('tree-sitter')
94
+ })
95
+
96
+ test('Zig support', () => {
97
+ expect(languageForExtension('.zig')).toBe('zig')
98
+ expect(parserKindForExtension('.zig')).toBe('tree-sitter')
99
+ })
100
+ })
101
+
102
+ describe('Apple/Mobile Languages', () => {
103
+ test('Dart support', () => {
104
+ expect(languageForExtension('.dart')).toBe('dart')
105
+ expect(parserKindForExtension('.dart')).toBe('tree-sitter')
106
+ })
107
+ })
108
+
109
+ describe('Functional Languages', () => {
110
+ test('Haskell support', () => {
111
+ expect(languageForExtension('.hs')).toBe('haskell')
112
+ expect(parserKindForExtension('.hs')).toBe('tree-sitter')
113
+ })
114
+
115
+ test('Elixir support', () => {
116
+ expect(languageForExtension('.ex')).toBe('elixir')
117
+ expect(languageForExtension('.exs')).toBe('elixir')
118
+ expect(parserKindForExtension('.ex')).toBe('tree-sitter')
119
+ })
120
+
121
+ test('Clojure support', () => {
122
+ expect(languageForExtension('.clj')).toBe('clojure')
123
+ expect(languageForExtension('.cljs')).toBe('clojure')
124
+ expect(languageForExtension('.cljc')).toBe('clojure')
125
+ expect(parserKindForExtension('.clj')).toBe('tree-sitter')
126
+ })
127
+
128
+ test('OCaml support', () => {
129
+ expect(languageForExtension('.ml')).toBe('ocaml')
130
+ expect(languageForExtension('.mli')).toBe('ocaml')
131
+ expect(parserKindForExtension('.ml')).toBe('tree-sitter')
132
+ })
133
+
134
+ test('F# support', () => {
135
+ expect(languageForExtension('.fs')).toBe('fsharp')
136
+ expect(languageForExtension('.fsx')).toBe('fsharp')
137
+ expect(languageForExtension('.fsi')).toBe('fsharp')
138
+ expect(parserKindForExtension('.fs')).toBe('tree-sitter')
139
+ })
140
+ })
141
+
142
+ describe('Scripting Languages', () => {
143
+ test('Lua support', () => {
144
+ expect(languageForExtension('.lua')).toBe('lua')
145
+ expect(parserKindForExtension('.lua')).toBe('tree-sitter')
146
+ })
147
+
148
+ test('Perl support', () => {
149
+ expect(languageForExtension('.pl')).toBe('perl')
150
+ expect(languageForExtension('.pm')).toBe('perl')
151
+ expect(parserKindForExtension('.pl')).toBe('tree-sitter')
152
+ })
153
+
154
+ test('R support', () => {
155
+ expect(languageForExtension('.r')).toBe('r')
156
+ expect(languageForExtension('.R')).toBe('r')
157
+ expect(parserKindForExtension('.r')).toBe('tree-sitter')
158
+ })
159
+
160
+ test('Julia support', () => {
161
+ expect(languageForExtension('.jl')).toBe('julia')
162
+ expect(parserKindForExtension('.jl')).toBe('tree-sitter')
163
+ })
164
+ })
165
+
166
+ describe('Config/Special Purpose', () => {
167
+ test('SQL support', () => {
168
+ expect(languageForExtension('.sql')).toBe('sql')
169
+ expect(parserKindForExtension('.sql')).toBe('tree-sitter')
170
+ })
171
+
172
+ test('Terraform support', () => {
173
+ expect(languageForExtension('.tf')).toBe('terraform')
174
+ expect(parserKindForExtension('.tf')).toBe('tree-sitter')
175
+ })
176
+
177
+ test('Shell/Bash support', () => {
178
+ expect(languageForExtension('.sh')).toBe('shell')
179
+ expect(languageForExtension('.bash')).toBe('shell')
180
+ expect(languageForExtension('.zsh')).toBe('shell')
181
+ expect(parserKindForExtension('.sh')).toBe('tree-sitter')
182
+ })
183
+ })
184
+
185
+ describe('Web Frameworks', () => {
186
+ test('Vue support', () => {
187
+ expect(languageForExtension('.vue')).toBe('vue')
188
+ expect(parserKindForExtension('.vue')).toBe('oxc')
189
+ })
190
+
191
+ test('Svelte support', () => {
192
+ expect(languageForExtension('.svelte')).toBe('svelte')
193
+ expect(parserKindForExtension('.svelte')).toBe('oxc')
194
+ })
195
+ })
196
+
197
+ describe('ParsedFileLanguage conversion', () => {
198
+ test('converts known languages correctly', () => {
199
+ expect(toParsedFileLanguage('python')).toBe('python')
200
+ expect(toParsedFileLanguage('java')).toBe('java')
201
+ expect(toParsedFileLanguage('go')).toBe('go')
202
+ expect(toParsedFileLanguage('rust')).toBe('rust')
203
+ expect(toParsedFileLanguage('dart')).toBe('dart')
204
+ expect(toParsedFileLanguage('kotlin')).toBe('kotlin')
205
+ expect(toParsedFileLanguage('scala')).toBe('scala')
206
+ expect(toParsedFileLanguage('swift')).toBe('swift')
207
+ })
208
+
209
+ test('converts functional languages', () => {
210
+ expect(toParsedFileLanguage('haskell')).toBe('haskell')
211
+ expect(toParsedFileLanguage('elixir')).toBe('elixir')
212
+ expect(toParsedFileLanguage('clojure')).toBe('clojure')
213
+ expect(toParsedFileLanguage('fsharp')).toBe('fsharp')
214
+ expect(toParsedFileLanguage('ocaml')).toBe('ocaml')
215
+ })
216
+
217
+ test('converts scripting languages', () => {
218
+ expect(toParsedFileLanguage('lua')).toBe('lua')
219
+ expect(toParsedFileLanguage('perl')).toBe('perl')
220
+ expect(toParsedFileLanguage('r')).toBe('r')
221
+ expect(toParsedFileLanguage('julia')).toBe('julia')
222
+ })
223
+
224
+ test('converts special purpose languages', () => {
225
+ expect(toParsedFileLanguage('sql')).toBe('sql')
226
+ expect(toParsedFileLanguage('terraform')).toBe('terraform')
227
+ expect(toParsedFileLanguage('shell')).toBe('shell')
228
+ })
229
+
230
+ test('falls back to unknown for unsupported languages', () => {
231
+ expect(toParsedFileLanguage('cobol' as RegistryLanguage)).toBe('unknown')
232
+ expect(toParsedFileLanguage('fortran' as RegistryLanguage)).toBe('unknown')
233
+ })
234
+ })
235
+
236
+ describe('Extension coverage', () => {
237
+ test('all 22+ languages have valid extensions', () => {
238
+ const languages: Array<{name: RegistryLanguage, extensions: string[]}> = [
239
+ { name: 'typescript', extensions: ['.ts', '.mts', '.cts', '.mjs', '.cjs', '.jsx'] },
240
+ { name: 'python', extensions: ['.py', '.pyw'] },
241
+ { name: 'java', extensions: ['.java'] },
242
+ { name: 'csharp', extensions: ['.cs'] },
243
+ { name: 'c', extensions: ['.c', '.h'] },
244
+ { name: 'cpp', extensions: ['.cpp', '.cc', '.cxx', '.hpp', '.hxx', '.hh'] },
245
+ { name: 'php', extensions: ['.php'] },
246
+ { name: 'ruby', extensions: ['.rb'] },
247
+ { name: 'swift', extensions: ['.swift'] },
248
+ { name: 'go', extensions: ['.go'] },
249
+ { name: 'kotlin', extensions: ['.kt', '.kts'] },
250
+ { name: 'rust', extensions: ['.rs'] },
251
+ { name: 'dart', extensions: ['.dart'] },
252
+ { name: 'scala', extensions: ['.scala', '.sc'] },
253
+ { name: 'haskell', extensions: ['.hs'] },
254
+ { name: 'elixir', extensions: ['.ex', '.exs'] },
255
+ { name: 'clojure', extensions: ['.clj', '.cljs', '.cljc'] },
256
+ { name: 'fsharp', extensions: ['.fs', '.fsx', '.fsi'] },
257
+ { name: 'ocaml', extensions: ['.ml', '.mli'] },
258
+ { name: 'zig', extensions: ['.zig'] },
259
+ { name: 'lua', extensions: ['.lua'] },
260
+ { name: 'perl', extensions: ['.pl', '.pm'] },
261
+ { name: 'r', extensions: ['.r', '.R'] },
262
+ { name: 'julia', extensions: ['.jl'] },
263
+ { name: 'sql', extensions: ['.sql'] },
264
+ { name: 'terraform', extensions: ['.tf'] },
265
+ { name: 'shell', extensions: ['.sh', '.bash', '.zsh'] },
266
+ ]
267
+
268
+ for (const lang of languages) {
269
+ for (const ext of lang.extensions) {
270
+ const detected = languageForExtension(ext)
271
+ expect(detected).toBe(lang.name)
272
+ }
273
+ }
274
+ })
275
+ })
276
+ })
@@ -47,10 +47,12 @@ describe('language-registry', () => {
47
47
  it('returns discovery extension sets for mixed JVM repos', () => {
48
48
  const javaDiscovery = getDiscoveryExtensions('java')
49
49
  expect(javaDiscovery).toContain('.java')
50
- expect(javaDiscovery).toContain('.kt')
51
- expect(javaDiscovery).toContain('.kts')
52
50
 
53
- // Even though Java discovery includes Kotlin files, extension-to-language remains Kotlin.
51
+ const kotlinDiscovery = getDiscoveryExtensions('kotlin')
52
+ expect(kotlinDiscovery).toContain('.kt')
53
+ expect(kotlinDiscovery).toContain('.kts')
54
+
55
+ // Extension-to-language remains separate.
54
56
  expect(languageForExtension('.kt')).toBe('kotlin')
55
57
  expect(languageForExtension('.kts')).toBe('kotlin')
56
58
  })
@@ -61,4 +63,4 @@ describe('language-registry', () => {
61
63
  expect(isTreeSitterExtension('.ts')).toBe(false)
62
64
  expect(isTreeSitterExtension('.go')).toBe(false)
63
65
  })
64
- })
66
+ })
@@ -1,115 +1,28 @@
1
1
  import { describe, it, expect } from 'bun:test'
2
2
  import { parseFilesWithDiagnostics } from '../src/parser/index'
3
3
 
4
- describe('parseFilesWithDiagnostics preflight', () => {
5
- it('returns parser-unavailable diagnostic and no files in strict preflight mode', async () => {
6
- const result = await parseFilesWithDiagnostics(
7
- ['src/example.py'],
8
- '/project',
9
- async () => 'def run():\n return 1\n',
10
- {
11
- strictParserPreflight: true,
12
- treeSitterRuntimeAvailable: false,
13
- },
14
- )
15
-
16
- expect(result.files).toHaveLength(0)
17
- expect(result.summary.requestedFiles).toBe(1)
18
- expect(result.summary.parsedFiles).toBe(0)
19
- expect(result.summary.diagnostics).toBeGreaterThan(0)
20
- expect(result.diagnostics.some(d => d.reason === 'parser-unavailable')).toBe(true)
21
- })
22
-
23
- it('falls back and continues in non-strict mode when parser runtime is unavailable', async () => {
24
- const result = await parseFilesWithDiagnostics(
25
- ['src/example.py'],
26
- '/project',
27
- async () => 'def run():\n return 1\n',
28
- {
29
- strictParserPreflight: false,
30
- treeSitterRuntimeAvailable: false,
31
- },
32
- )
33
-
34
- expect(result.files).toHaveLength(1)
35
- expect(result.summary.diagnostics).toBeGreaterThan(0)
36
- expect(result.diagnostics.some(d => d.reason === 'parser-unavailable')).toBe(true)
37
- })
38
-
39
- it('skips tree-sitter preflight when only oxc/go files are requested', async () => {
40
- const result = await parseFilesWithDiagnostics(
41
- ['src/index.ts'],
42
- '/project',
43
- async () => 'export function ok(): number { return 1 }',
44
- {
45
- strictParserPreflight: true,
46
- treeSitterRuntimeAvailable: false,
47
- },
48
- )
49
-
50
- expect(result.summary.requestedFiles).toBe(1)
51
- expect(result.summary.parsedFiles).toBe(1)
52
- expect(result.diagnostics.some(d => d.reason === 'parser-unavailable')).toBe(false)
53
- })
54
-
55
- it('returns language-correct fallback files for multiple tree-sitter languages in non-strict mode', async () => {
56
- const files = [
57
- 'src/main.py',
58
- 'src/App.java',
59
- 'src/service.kt',
60
- 'src/tool.swift',
61
- 'src/lib.rs',
62
- 'src/Program.cs',
63
- 'src/main.php',
64
- 'src/app.rb',
65
- 'src/native.c',
66
- 'src/native.cpp',
67
- ]
68
-
4
+ describe('parseFilesWithDiagnostics regressions', () => {
5
+ it('returns language-correct fallback files for unsupported extensions', async () => {
6
+ const files = ['src/main.xyz']
69
7
  const result = await parseFilesWithDiagnostics(
70
8
  files,
71
9
  '/project',
72
10
  async () => '',
73
- {
74
- strictParserPreflight: false,
75
- treeSitterRuntimeAvailable: false,
76
- },
77
11
  )
78
12
 
79
13
  expect(result.files).toHaveLength(files.length)
80
- expect(result.diagnostics.some(d => d.reason === 'parser-unavailable')).toBe(true)
81
-
82
- const languageBySuffix = (suffix: string): string | undefined => {
83
- const hit = result.files.find(f => f.path.replace(/\\/g, '/').endsWith(suffix))
84
- return hit?.language
85
- }
86
-
87
- expect(languageBySuffix('/src/main.py')).toBe('python')
88
- expect(languageBySuffix('/src/App.java')).toBe('java')
89
- expect(languageBySuffix('/src/service.kt')).toBe('kotlin')
90
- expect(languageBySuffix('/src/tool.swift')).toBe('swift')
91
- expect(languageBySuffix('/src/lib.rs')).toBe('rust')
92
- expect(languageBySuffix('/src/Program.cs')).toBe('csharp')
93
- expect(languageBySuffix('/src/main.php')).toBe('php')
94
- expect(languageBySuffix('/src/app.rb')).toBe('ruby')
95
- expect(languageBySuffix('/src/native.c')).toBe('c')
96
- expect(languageBySuffix('/src/native.cpp')).toBe('cpp')
14
+ expect(result.diagnostics.some(d => d.reason === 'unsupported-extension')).toBe(true)
97
15
  })
98
16
 
99
- it('aborts full batch in strict preflight when any tree-sitter file is present', async () => {
17
+ it('correctly parses mixed oxc and tree-sitter files', async () => {
100
18
  const result = await parseFilesWithDiagnostics(
101
19
  ['src/index.ts', 'src/main.py'],
102
20
  '/project',
103
- async () => 'export const ok = 1',
104
- {
105
- strictParserPreflight: true,
106
- treeSitterRuntimeAvailable: false,
107
- },
21
+ async (fp) => fp.endsWith('.ts') ? 'export const x = 1' : 'def run(): pass',
108
22
  )
109
23
 
110
- expect(result.files).toHaveLength(0)
111
- expect(result.summary.requestedFiles).toBe(2)
112
- expect(result.summary.parsedFiles).toBe(0)
113
- expect(result.diagnostics.some(d => d.reason === 'parser-unavailable')).toBe(true)
24
+ expect(result.summary.parsedFiles).toBe(2)
25
+ expect(result.files.some(f => f.language === 'python')).toBe(true)
26
+ expect(result.files.some(f => f.language === 'typescript')).toBe(true)
114
27
  })
115
28
  })