viberag 0.1.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.
- package/LICENSE +661 -0
- package/README.md +219 -0
- package/dist/cli/__tests__/mcp-setup.test.d.ts +6 -0
- package/dist/cli/__tests__/mcp-setup.test.js +597 -0
- package/dist/cli/app.d.ts +2 -0
- package/dist/cli/app.js +238 -0
- package/dist/cli/commands/handlers.d.ts +57 -0
- package/dist/cli/commands/handlers.js +231 -0
- package/dist/cli/commands/index.d.ts +2 -0
- package/dist/cli/commands/index.js +2 -0
- package/dist/cli/commands/mcp-setup.d.ts +107 -0
- package/dist/cli/commands/mcp-setup.js +509 -0
- package/dist/cli/commands/useRagCommands.d.ts +23 -0
- package/dist/cli/commands/useRagCommands.js +180 -0
- package/dist/cli/components/CleanWizard.d.ts +17 -0
- package/dist/cli/components/CleanWizard.js +169 -0
- package/dist/cli/components/InitWizard.d.ts +20 -0
- package/dist/cli/components/InitWizard.js +370 -0
- package/dist/cli/components/McpSetupWizard.d.ts +37 -0
- package/dist/cli/components/McpSetupWizard.js +387 -0
- package/dist/cli/components/SearchResultsDisplay.d.ts +13 -0
- package/dist/cli/components/SearchResultsDisplay.js +130 -0
- package/dist/cli/components/WelcomeBanner.d.ts +10 -0
- package/dist/cli/components/WelcomeBanner.js +26 -0
- package/dist/cli/components/index.d.ts +1 -0
- package/dist/cli/components/index.js +1 -0
- package/dist/cli/data/mcp-editors.d.ts +80 -0
- package/dist/cli/data/mcp-editors.js +270 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +26 -0
- package/dist/cli-bundle.cjs +5269 -0
- package/dist/common/commands/terminalSetup.d.ts +2 -0
- package/dist/common/commands/terminalSetup.js +144 -0
- package/dist/common/components/CommandSuggestions.d.ts +9 -0
- package/dist/common/components/CommandSuggestions.js +20 -0
- package/dist/common/components/StaticWithResize.d.ts +23 -0
- package/dist/common/components/StaticWithResize.js +62 -0
- package/dist/common/components/StatusBar.d.ts +8 -0
- package/dist/common/components/StatusBar.js +64 -0
- package/dist/common/components/TextInput.d.ts +12 -0
- package/dist/common/components/TextInput.js +239 -0
- package/dist/common/components/index.d.ts +3 -0
- package/dist/common/components/index.js +3 -0
- package/dist/common/hooks/index.d.ts +4 -0
- package/dist/common/hooks/index.js +4 -0
- package/dist/common/hooks/useCommandHistory.d.ts +7 -0
- package/dist/common/hooks/useCommandHistory.js +51 -0
- package/dist/common/hooks/useCtrlC.d.ts +9 -0
- package/dist/common/hooks/useCtrlC.js +40 -0
- package/dist/common/hooks/useKittyKeyboard.d.ts +10 -0
- package/dist/common/hooks/useKittyKeyboard.js +26 -0
- package/dist/common/hooks/useStaticOutputBuffer.d.ts +31 -0
- package/dist/common/hooks/useStaticOutputBuffer.js +58 -0
- package/dist/common/hooks/useTerminalResize.d.ts +28 -0
- package/dist/common/hooks/useTerminalResize.js +51 -0
- package/dist/common/hooks/useTextBuffer.d.ts +13 -0
- package/dist/common/hooks/useTextBuffer.js +165 -0
- package/dist/common/index.d.ts +13 -0
- package/dist/common/index.js +17 -0
- package/dist/common/types.d.ts +162 -0
- package/dist/common/types.js +1 -0
- package/dist/mcp/index.d.ts +12 -0
- package/dist/mcp/index.js +66 -0
- package/dist/mcp/server.d.ts +25 -0
- package/dist/mcp/server.js +837 -0
- package/dist/mcp/watcher.d.ts +86 -0
- package/dist/mcp/watcher.js +334 -0
- package/dist/rag/__tests__/grammar-smoke.test.d.ts +9 -0
- package/dist/rag/__tests__/grammar-smoke.test.js +161 -0
- package/dist/rag/__tests__/helpers.d.ts +30 -0
- package/dist/rag/__tests__/helpers.js +67 -0
- package/dist/rag/__tests__/merkle.test.d.ts +5 -0
- package/dist/rag/__tests__/merkle.test.js +161 -0
- package/dist/rag/__tests__/metadata-extraction.test.d.ts +10 -0
- package/dist/rag/__tests__/metadata-extraction.test.js +202 -0
- package/dist/rag/__tests__/multi-language.test.d.ts +13 -0
- package/dist/rag/__tests__/multi-language.test.js +535 -0
- package/dist/rag/__tests__/rag.test.d.ts +10 -0
- package/dist/rag/__tests__/rag.test.js +311 -0
- package/dist/rag/__tests__/search-exhaustive.test.d.ts +9 -0
- package/dist/rag/__tests__/search-exhaustive.test.js +87 -0
- package/dist/rag/__tests__/search-filters.test.d.ts +10 -0
- package/dist/rag/__tests__/search-filters.test.js +250 -0
- package/dist/rag/__tests__/search-modes.test.d.ts +8 -0
- package/dist/rag/__tests__/search-modes.test.js +133 -0
- package/dist/rag/config/index.d.ts +61 -0
- package/dist/rag/config/index.js +111 -0
- package/dist/rag/constants.d.ts +41 -0
- package/dist/rag/constants.js +57 -0
- package/dist/rag/embeddings/fastembed.d.ts +62 -0
- package/dist/rag/embeddings/fastembed.js +124 -0
- package/dist/rag/embeddings/gemini.d.ts +26 -0
- package/dist/rag/embeddings/gemini.js +116 -0
- package/dist/rag/embeddings/index.d.ts +10 -0
- package/dist/rag/embeddings/index.js +9 -0
- package/dist/rag/embeddings/local-4b.d.ts +28 -0
- package/dist/rag/embeddings/local-4b.js +51 -0
- package/dist/rag/embeddings/local.d.ts +29 -0
- package/dist/rag/embeddings/local.js +119 -0
- package/dist/rag/embeddings/mistral.d.ts +22 -0
- package/dist/rag/embeddings/mistral.js +85 -0
- package/dist/rag/embeddings/openai.d.ts +22 -0
- package/dist/rag/embeddings/openai.js +85 -0
- package/dist/rag/embeddings/types.d.ts +37 -0
- package/dist/rag/embeddings/types.js +1 -0
- package/dist/rag/gitignore/index.d.ts +57 -0
- package/dist/rag/gitignore/index.js +178 -0
- package/dist/rag/index.d.ts +15 -0
- package/dist/rag/index.js +25 -0
- package/dist/rag/indexer/chunker.d.ts +129 -0
- package/dist/rag/indexer/chunker.js +1352 -0
- package/dist/rag/indexer/index.d.ts +6 -0
- package/dist/rag/indexer/index.js +6 -0
- package/dist/rag/indexer/indexer.d.ts +73 -0
- package/dist/rag/indexer/indexer.js +356 -0
- package/dist/rag/indexer/types.d.ts +68 -0
- package/dist/rag/indexer/types.js +47 -0
- package/dist/rag/logger/index.d.ts +20 -0
- package/dist/rag/logger/index.js +75 -0
- package/dist/rag/manifest/index.d.ts +50 -0
- package/dist/rag/manifest/index.js +97 -0
- package/dist/rag/merkle/diff.d.ts +26 -0
- package/dist/rag/merkle/diff.js +95 -0
- package/dist/rag/merkle/hash.d.ts +34 -0
- package/dist/rag/merkle/hash.js +165 -0
- package/dist/rag/merkle/index.d.ts +68 -0
- package/dist/rag/merkle/index.js +298 -0
- package/dist/rag/merkle/node.d.ts +51 -0
- package/dist/rag/merkle/node.js +69 -0
- package/dist/rag/search/filters.d.ts +21 -0
- package/dist/rag/search/filters.js +100 -0
- package/dist/rag/search/fts.d.ts +32 -0
- package/dist/rag/search/fts.js +61 -0
- package/dist/rag/search/hybrid.d.ts +17 -0
- package/dist/rag/search/hybrid.js +58 -0
- package/dist/rag/search/index.d.ts +89 -0
- package/dist/rag/search/index.js +367 -0
- package/dist/rag/search/types.d.ts +130 -0
- package/dist/rag/search/types.js +4 -0
- package/dist/rag/search/vector.d.ts +25 -0
- package/dist/rag/search/vector.js +44 -0
- package/dist/rag/storage/index.d.ts +92 -0
- package/dist/rag/storage/index.js +287 -0
- package/dist/rag/storage/lancedb-native.d.ts +7 -0
- package/dist/rag/storage/lancedb-native.js +10 -0
- package/dist/rag/storage/schema.d.ts +23 -0
- package/dist/rag/storage/schema.js +50 -0
- package/dist/rag/storage/types.d.ts +100 -0
- package/dist/rag/storage/types.js +68 -0
- package/package.json +67 -0
- package/scripts/check-node-version.js +37 -0
|
@@ -0,0 +1,535 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Language Support Tests.
|
|
3
|
+
*
|
|
4
|
+
* Tests that the indexer correctly handles 8 additional languages:
|
|
5
|
+
* - Go, Rust, Java, C#, Dart, Swift, Kotlin, PHP
|
|
6
|
+
*
|
|
7
|
+
* Validates:
|
|
8
|
+
* - Export detection (capitalization, pub, public, underscore prefix)
|
|
9
|
+
* - Decorator/attribute extraction (#[], @, [])
|
|
10
|
+
* - Docstring extraction (various comment styles)
|
|
11
|
+
* - Cross-language search capabilities
|
|
12
|
+
*/
|
|
13
|
+
import { describe, it, expect, beforeAll, afterAll } from 'vitest';
|
|
14
|
+
import { Indexer } from '../indexer/indexer.js';
|
|
15
|
+
import { SearchEngine } from '../search/index.js';
|
|
16
|
+
import { copyFixtureToTemp } from './helpers.js';
|
|
17
|
+
describe('Multi-Language Support', () => {
|
|
18
|
+
let ctx;
|
|
19
|
+
let search;
|
|
20
|
+
beforeAll(async () => {
|
|
21
|
+
ctx = await copyFixtureToTemp('codebase');
|
|
22
|
+
const indexer = new Indexer(ctx.projectRoot);
|
|
23
|
+
await indexer.index();
|
|
24
|
+
indexer.close();
|
|
25
|
+
search = new SearchEngine(ctx.projectRoot);
|
|
26
|
+
}, 180000);
|
|
27
|
+
afterAll(async () => {
|
|
28
|
+
search.close();
|
|
29
|
+
await ctx.cleanup();
|
|
30
|
+
});
|
|
31
|
+
describe('Go Language', () => {
|
|
32
|
+
it('indexes .go files', async () => {
|
|
33
|
+
const results = await search.search('Greeter', {
|
|
34
|
+
filters: { extension: ['.go'] },
|
|
35
|
+
});
|
|
36
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
37
|
+
expect(results.results[0]?.filepath).toContain('.go');
|
|
38
|
+
}, 60000);
|
|
39
|
+
it('detects exported symbols (capitalized)', async () => {
|
|
40
|
+
// Exported function (capitalized)
|
|
41
|
+
const exported = await search.search('NewGreeter', {
|
|
42
|
+
mode: 'definition',
|
|
43
|
+
filters: { extension: ['.go'] },
|
|
44
|
+
});
|
|
45
|
+
if (exported.results.length > 0) {
|
|
46
|
+
const result = exported.results.find(r => r.name?.includes('NewGreeter'));
|
|
47
|
+
if (result) {
|
|
48
|
+
expect(result.isExported).toBe(true);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
}, 60000);
|
|
52
|
+
it('detects unexported symbols (lowercase)', async () => {
|
|
53
|
+
const unexported = await search.search('privateHelper', {
|
|
54
|
+
mode: 'definition',
|
|
55
|
+
filters: { extension: ['.go'] },
|
|
56
|
+
});
|
|
57
|
+
if (unexported.results.length > 0) {
|
|
58
|
+
const result = unexported.results.find(r => r.name?.includes('privateHelper'));
|
|
59
|
+
if (result) {
|
|
60
|
+
expect(result.isExported).toBe(false);
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}, 60000);
|
|
64
|
+
it('extracts Go doc comments', async () => {
|
|
65
|
+
const results = await search.search('Add two integers', {
|
|
66
|
+
mode: 'semantic',
|
|
67
|
+
filters: { extension: ['.go'] },
|
|
68
|
+
});
|
|
69
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
70
|
+
}, 60000);
|
|
71
|
+
});
|
|
72
|
+
describe('Rust Language', () => {
|
|
73
|
+
it('indexes .rs files', async () => {
|
|
74
|
+
const results = await search.search('Greeter', {
|
|
75
|
+
filters: { extension: ['.rs'] },
|
|
76
|
+
});
|
|
77
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
78
|
+
expect(results.results[0]?.filepath).toContain('.rs');
|
|
79
|
+
}, 60000);
|
|
80
|
+
it('detects pub exports', async () => {
|
|
81
|
+
const results = await search.search('add', {
|
|
82
|
+
mode: 'definition',
|
|
83
|
+
filters: { extension: ['.rs'] },
|
|
84
|
+
});
|
|
85
|
+
if (results.results.length > 0) {
|
|
86
|
+
const pubFn = results.results.find(r => r.name === 'add');
|
|
87
|
+
if (pubFn) {
|
|
88
|
+
expect(pubFn.isExported).toBe(true);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}, 60000);
|
|
92
|
+
it('detects private functions', async () => {
|
|
93
|
+
const results = await search.search('private_function', {
|
|
94
|
+
mode: 'definition',
|
|
95
|
+
filters: { extension: ['.rs'] },
|
|
96
|
+
});
|
|
97
|
+
if (results.results.length > 0) {
|
|
98
|
+
const privateFn = results.results.find(r => r.name?.includes('private'));
|
|
99
|
+
if (privateFn) {
|
|
100
|
+
expect(privateFn.isExported).toBe(false);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
}, 60000);
|
|
104
|
+
it('extracts #[derive] attributes via filter', async () => {
|
|
105
|
+
const results = await search.search('Greeter', {
|
|
106
|
+
filters: {
|
|
107
|
+
extension: ['.rs'],
|
|
108
|
+
decoratorContains: 'derive',
|
|
109
|
+
},
|
|
110
|
+
});
|
|
111
|
+
// Should find Greeter struct with #[derive(...)]
|
|
112
|
+
expect(results.results.some(r => r.filepath.includes('.rs'))).toBe(true);
|
|
113
|
+
}, 60000);
|
|
114
|
+
it('extracts /// doc comments', async () => {
|
|
115
|
+
const results = await search.search('greeting message', {
|
|
116
|
+
mode: 'semantic',
|
|
117
|
+
filters: { extension: ['.rs'] },
|
|
118
|
+
});
|
|
119
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
120
|
+
}, 60000);
|
|
121
|
+
});
|
|
122
|
+
describe('Java Language', () => {
|
|
123
|
+
it('indexes .java files', async () => {
|
|
124
|
+
const results = await search.search('Sample class', {
|
|
125
|
+
filters: { extension: ['.java'] },
|
|
126
|
+
});
|
|
127
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
128
|
+
expect(results.results[0]?.filepath).toContain('.java');
|
|
129
|
+
}, 60000);
|
|
130
|
+
it('detects public methods', async () => {
|
|
131
|
+
const results = await search.search('getName', {
|
|
132
|
+
mode: 'definition',
|
|
133
|
+
filters: { extension: ['.java'] },
|
|
134
|
+
});
|
|
135
|
+
if (results.results.length > 0) {
|
|
136
|
+
const method = results.results.find(r => r.name?.includes('getName'));
|
|
137
|
+
if (method) {
|
|
138
|
+
expect(method.isExported).toBe(true);
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
}, 60000);
|
|
142
|
+
it('detects package-private classes', async () => {
|
|
143
|
+
const results = await search.search('PrivateHelper', {
|
|
144
|
+
mode: 'definition',
|
|
145
|
+
filters: { extension: ['.java'] },
|
|
146
|
+
});
|
|
147
|
+
if (results.results.length > 0) {
|
|
148
|
+
const helper = results.results.find(r => r.name?.includes('PrivateHelper'));
|
|
149
|
+
if (helper) {
|
|
150
|
+
expect(helper.isExported).toBe(false);
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}, 60000);
|
|
154
|
+
it('extracts @Override annotation via filter', async () => {
|
|
155
|
+
const results = await search.search('toString', {
|
|
156
|
+
filters: {
|
|
157
|
+
extension: ['.java'],
|
|
158
|
+
decoratorContains: 'Override',
|
|
159
|
+
},
|
|
160
|
+
});
|
|
161
|
+
// Should find toString with @Override when grammar supports it
|
|
162
|
+
// Note: If grammar ABI is incompatible, falls back to module-level chunking
|
|
163
|
+
expect(results).toBeDefined();
|
|
164
|
+
if (results.results.length > 0) {
|
|
165
|
+
expect(results.results.some(r => r.filepath.includes('.java'))).toBe(true);
|
|
166
|
+
}
|
|
167
|
+
}, 60000);
|
|
168
|
+
it('extracts Javadoc comments', async () => {
|
|
169
|
+
const results = await search.search('greeting string', {
|
|
170
|
+
mode: 'semantic',
|
|
171
|
+
filters: { extension: ['.java'] },
|
|
172
|
+
});
|
|
173
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
174
|
+
}, 60000);
|
|
175
|
+
});
|
|
176
|
+
describe('C# Language', () => {
|
|
177
|
+
it('indexes .cs files', async () => {
|
|
178
|
+
const results = await search.search('Greeter class', {
|
|
179
|
+
filters: { extension: ['.cs'] },
|
|
180
|
+
});
|
|
181
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
182
|
+
expect(results.results[0]?.filepath).toContain('.cs');
|
|
183
|
+
}, 60000);
|
|
184
|
+
it('detects public classes', async () => {
|
|
185
|
+
const results = await search.search('Greeter', {
|
|
186
|
+
mode: 'definition',
|
|
187
|
+
filters: { extension: ['.cs'] },
|
|
188
|
+
});
|
|
189
|
+
if (results.results.length > 0) {
|
|
190
|
+
const cls = results.results.find(r => r.name?.includes('Greeter'));
|
|
191
|
+
if (cls) {
|
|
192
|
+
expect(cls.isExported).toBe(true);
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
}, 60000);
|
|
196
|
+
it('detects internal classes', async () => {
|
|
197
|
+
const results = await search.search('PrivateHelper', {
|
|
198
|
+
mode: 'definition',
|
|
199
|
+
filters: { extension: ['.cs'] },
|
|
200
|
+
});
|
|
201
|
+
if (results.results.length > 0) {
|
|
202
|
+
const helper = results.results.find(r => r.name?.includes('PrivateHelper'));
|
|
203
|
+
if (helper) {
|
|
204
|
+
expect(helper.isExported).toBe(false);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}, 60000);
|
|
208
|
+
it('extracts [Obsolete] attribute via filter', async () => {
|
|
209
|
+
const results = await search.search('Greet', {
|
|
210
|
+
filters: {
|
|
211
|
+
extension: ['.cs'],
|
|
212
|
+
decoratorContains: 'Obsolete',
|
|
213
|
+
},
|
|
214
|
+
});
|
|
215
|
+
// Should find Greet method with [Obsolete] when grammar supports it
|
|
216
|
+
// Note: C# grammar may have ABI compatibility issues with current web-tree-sitter
|
|
217
|
+
expect(results).toBeDefined();
|
|
218
|
+
if (results.results.length > 0) {
|
|
219
|
+
expect(results.results.some(r => r.filepath.includes('.cs'))).toBe(true);
|
|
220
|
+
}
|
|
221
|
+
}, 60000);
|
|
222
|
+
it('extracts XML doc comments', async () => {
|
|
223
|
+
const results = await search.search('formal greeting', {
|
|
224
|
+
mode: 'semantic',
|
|
225
|
+
filters: { extension: ['.cs'] },
|
|
226
|
+
});
|
|
227
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
228
|
+
}, 60000);
|
|
229
|
+
});
|
|
230
|
+
describe('Dart Language', () => {
|
|
231
|
+
it('indexes .dart files', async () => {
|
|
232
|
+
const results = await search.search('Greeter class', {
|
|
233
|
+
filters: { extension: ['.dart'] },
|
|
234
|
+
});
|
|
235
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
236
|
+
expect(results.results[0]?.filepath).toContain('.dart');
|
|
237
|
+
}, 60000);
|
|
238
|
+
it('detects public functions (no underscore)', async () => {
|
|
239
|
+
const results = await search.search('add', {
|
|
240
|
+
mode: 'definition',
|
|
241
|
+
filters: { extension: ['.dart'] },
|
|
242
|
+
});
|
|
243
|
+
if (results.results.length > 0) {
|
|
244
|
+
const fn = results.results.find(r => r.name === 'add' && r.filepath.includes('.dart'));
|
|
245
|
+
if (fn) {
|
|
246
|
+
expect(fn.isExported).toBe(true);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
}, 60000);
|
|
250
|
+
it('detects private classes (underscore prefix)', async () => {
|
|
251
|
+
const results = await search.search('_PrivateHelper', {
|
|
252
|
+
mode: 'definition',
|
|
253
|
+
filters: { extension: ['.dart'] },
|
|
254
|
+
});
|
|
255
|
+
if (results.results.length > 0) {
|
|
256
|
+
const cls = results.results.find(r => r.name?.includes('_PrivateHelper'));
|
|
257
|
+
if (cls) {
|
|
258
|
+
expect(cls.isExported).toBe(false);
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
}, 60000);
|
|
262
|
+
it('extracts @Deprecated annotation via filter', async () => {
|
|
263
|
+
const results = await search.search('processData', {
|
|
264
|
+
filters: {
|
|
265
|
+
extension: ['.dart'],
|
|
266
|
+
decoratorContains: 'Deprecated',
|
|
267
|
+
},
|
|
268
|
+
});
|
|
269
|
+
// Should find processData with @Deprecated when grammar supports it
|
|
270
|
+
// Note: Dart grammar may have ABI compatibility issues with current web-tree-sitter
|
|
271
|
+
expect(results).toBeDefined();
|
|
272
|
+
if (results.results.length > 0) {
|
|
273
|
+
expect(results.results.some(r => r.filepath.includes('.dart'))).toBe(true);
|
|
274
|
+
}
|
|
275
|
+
}, 60000);
|
|
276
|
+
it('extracts /// doc comments', async () => {
|
|
277
|
+
const results = await search.search('greeting messages', {
|
|
278
|
+
mode: 'semantic',
|
|
279
|
+
filters: { extension: ['.dart'] },
|
|
280
|
+
});
|
|
281
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
282
|
+
}, 60000);
|
|
283
|
+
});
|
|
284
|
+
describe('Swift Language', () => {
|
|
285
|
+
it('indexes .swift files', async () => {
|
|
286
|
+
const results = await search.search('Greeter struct', {
|
|
287
|
+
filters: { extension: ['.swift'] },
|
|
288
|
+
});
|
|
289
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
290
|
+
expect(results.results[0]?.filepath).toContain('.swift');
|
|
291
|
+
}, 60000);
|
|
292
|
+
it('detects public functions', async () => {
|
|
293
|
+
const results = await search.search('add', {
|
|
294
|
+
mode: 'definition',
|
|
295
|
+
filters: { extension: ['.swift'] },
|
|
296
|
+
});
|
|
297
|
+
if (results.results.length > 0) {
|
|
298
|
+
const fn = results.results.find(r => r.name === 'add' && r.filepath.includes('.swift'));
|
|
299
|
+
if (fn) {
|
|
300
|
+
expect(fn.isExported).toBe(true);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
}, 60000);
|
|
304
|
+
it('detects private functions', async () => {
|
|
305
|
+
const results = await search.search('privateFunction', {
|
|
306
|
+
mode: 'definition',
|
|
307
|
+
filters: { extension: ['.swift'] },
|
|
308
|
+
});
|
|
309
|
+
if (results.results.length > 0) {
|
|
310
|
+
const fn = results.results.find(r => r.name?.includes('privateFunction'));
|
|
311
|
+
if (fn) {
|
|
312
|
+
expect(fn.isExported).toBe(false);
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}, 60000);
|
|
316
|
+
it('extracts @available attribute via filter', async () => {
|
|
317
|
+
const results = await search.search('Greeter', {
|
|
318
|
+
filters: {
|
|
319
|
+
extension: ['.swift'],
|
|
320
|
+
decoratorContains: 'available',
|
|
321
|
+
},
|
|
322
|
+
});
|
|
323
|
+
// Should find Greeter with @available when grammar supports it
|
|
324
|
+
// Note: Swift grammar may have ABI compatibility issues with current web-tree-sitter
|
|
325
|
+
expect(results).toBeDefined();
|
|
326
|
+
if (results.results.length > 0) {
|
|
327
|
+
expect(results.results.some(r => r.filepath.includes('.swift'))).toBe(true);
|
|
328
|
+
}
|
|
329
|
+
}, 60000);
|
|
330
|
+
it('extracts /// doc comments', async () => {
|
|
331
|
+
const results = await search.search('greeting message', {
|
|
332
|
+
mode: 'semantic',
|
|
333
|
+
filters: { extension: ['.swift'] },
|
|
334
|
+
});
|
|
335
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
336
|
+
}, 60000);
|
|
337
|
+
});
|
|
338
|
+
describe('Kotlin Language', () => {
|
|
339
|
+
it('indexes .kt files', async () => {
|
|
340
|
+
const results = await search.search('Greeter data class', {
|
|
341
|
+
filters: { extension: ['.kt'] },
|
|
342
|
+
});
|
|
343
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
344
|
+
expect(results.results[0]?.filepath).toContain('.kt');
|
|
345
|
+
}, 60000);
|
|
346
|
+
it('detects public functions (default)', async () => {
|
|
347
|
+
const results = await search.search('add', {
|
|
348
|
+
mode: 'definition',
|
|
349
|
+
filters: { extension: ['.kt'] },
|
|
350
|
+
});
|
|
351
|
+
if (results.results.length > 0) {
|
|
352
|
+
const fn = results.results.find(r => r.name === 'add' && r.filepath.includes('.kt'));
|
|
353
|
+
if (fn) {
|
|
354
|
+
expect(fn.isExported).toBe(true);
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}, 60000);
|
|
358
|
+
it('detects internal classes', async () => {
|
|
359
|
+
const results = await search.search('PrivateHelper', {
|
|
360
|
+
mode: 'definition',
|
|
361
|
+
filters: { extension: ['.kt'] },
|
|
362
|
+
});
|
|
363
|
+
if (results.results.length > 0) {
|
|
364
|
+
const cls = results.results.find(r => r.name?.includes('PrivateHelper'));
|
|
365
|
+
if (cls) {
|
|
366
|
+
expect(cls.isExported).toBe(false);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
}, 60000);
|
|
370
|
+
it('extracts @Deprecated annotation via filter', async () => {
|
|
371
|
+
const results = await search.search('processData', {
|
|
372
|
+
filters: {
|
|
373
|
+
extension: ['.kt'],
|
|
374
|
+
decoratorContains: 'Deprecated',
|
|
375
|
+
},
|
|
376
|
+
});
|
|
377
|
+
// Should find processData with @Deprecated when grammar supports it
|
|
378
|
+
// Note: Kotlin grammar may have ABI compatibility issues with current web-tree-sitter
|
|
379
|
+
expect(results).toBeDefined();
|
|
380
|
+
if (results.results.length > 0) {
|
|
381
|
+
expect(results.results.some(r => r.filepath.includes('.kt'))).toBe(true);
|
|
382
|
+
}
|
|
383
|
+
}, 60000);
|
|
384
|
+
it('extracts KDoc comments', async () => {
|
|
385
|
+
const results = await search.search('greeting message', {
|
|
386
|
+
mode: 'semantic',
|
|
387
|
+
filters: { extension: ['.kt'] },
|
|
388
|
+
});
|
|
389
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
390
|
+
}, 60000);
|
|
391
|
+
});
|
|
392
|
+
describe('PHP Language', () => {
|
|
393
|
+
it('indexes .php files', async () => {
|
|
394
|
+
const results = await search.search('Greeter class', {
|
|
395
|
+
filters: { extension: ['.php'] },
|
|
396
|
+
});
|
|
397
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
398
|
+
expect(results.results[0]?.filepath).toContain('.php');
|
|
399
|
+
}, 60000);
|
|
400
|
+
it('detects public methods', async () => {
|
|
401
|
+
const results = await search.search('greet', {
|
|
402
|
+
mode: 'definition',
|
|
403
|
+
filters: { extension: ['.php'] },
|
|
404
|
+
});
|
|
405
|
+
if (results.results.length > 0) {
|
|
406
|
+
const method = results.results.find(r => r.name === 'greet' && r.filepath.includes('.php'));
|
|
407
|
+
if (method) {
|
|
408
|
+
expect(method.isExported).toBe(true);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}, 60000);
|
|
412
|
+
it('detects private methods', async () => {
|
|
413
|
+
const results = await search.search('privateMethod', {
|
|
414
|
+
mode: 'definition',
|
|
415
|
+
filters: { extension: ['.php'] },
|
|
416
|
+
});
|
|
417
|
+
if (results.results.length > 0) {
|
|
418
|
+
const method = results.results.find(r => r.name?.includes('privateMethod') && r.filepath.includes('.php'));
|
|
419
|
+
if (method) {
|
|
420
|
+
expect(method.isExported).toBe(false);
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
}, 60000);
|
|
424
|
+
it('extracts PHP 8 #[Attribute] via filter', async () => {
|
|
425
|
+
const results = await search.search('add', {
|
|
426
|
+
filters: {
|
|
427
|
+
extension: ['.php'],
|
|
428
|
+
decoratorContains: 'Pure',
|
|
429
|
+
},
|
|
430
|
+
});
|
|
431
|
+
// Should find add function with #[Pure] when grammar supports it
|
|
432
|
+
// Note: PHP grammar may have ABI compatibility issues with current web-tree-sitter
|
|
433
|
+
expect(results).toBeDefined();
|
|
434
|
+
if (results.results.length > 0) {
|
|
435
|
+
expect(results.results.some(r => r.filepath.includes('.php'))).toBe(true);
|
|
436
|
+
}
|
|
437
|
+
}, 60000);
|
|
438
|
+
it('extracts PHPDoc comments', async () => {
|
|
439
|
+
const results = await search.search('greeting message', {
|
|
440
|
+
mode: 'semantic',
|
|
441
|
+
filters: { extension: ['.php'] },
|
|
442
|
+
});
|
|
443
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
444
|
+
}, 60000);
|
|
445
|
+
});
|
|
446
|
+
describe('Cross-Language Search', () => {
|
|
447
|
+
it('finds Greeter implementations across all languages', async () => {
|
|
448
|
+
const results = await search.search('Greeter class greeting', {
|
|
449
|
+
mode: 'semantic',
|
|
450
|
+
limit: 20,
|
|
451
|
+
});
|
|
452
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
453
|
+
// Should find results from multiple languages
|
|
454
|
+
const extensions = new Set(results.results.map(r => {
|
|
455
|
+
const ext = r.filepath.split('.').pop();
|
|
456
|
+
return ext ? `.${ext}` : '';
|
|
457
|
+
}));
|
|
458
|
+
expect(extensions.size).toBeGreaterThan(1);
|
|
459
|
+
}, 60000);
|
|
460
|
+
it('finds add functions across languages', async () => {
|
|
461
|
+
const results = await search.search('add two numbers integers', {
|
|
462
|
+
mode: 'semantic',
|
|
463
|
+
filters: { type: ['function'] },
|
|
464
|
+
limit: 20,
|
|
465
|
+
});
|
|
466
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
467
|
+
// Should have add functions from multiple languages
|
|
468
|
+
const langs = results.results.filter(r => r.name?.toLowerCase().includes('add'));
|
|
469
|
+
expect(langs.length).toBeGreaterThan(1);
|
|
470
|
+
}, 60000);
|
|
471
|
+
it('finds process functions across languages', async () => {
|
|
472
|
+
const results = await search.search('process data validation', {
|
|
473
|
+
mode: 'semantic',
|
|
474
|
+
limit: 20,
|
|
475
|
+
});
|
|
476
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
477
|
+
}, 60000);
|
|
478
|
+
it('filters by exported across languages', async () => {
|
|
479
|
+
const results = await search.search('greeting', {
|
|
480
|
+
mode: 'semantic',
|
|
481
|
+
filters: { isExported: true },
|
|
482
|
+
limit: 20,
|
|
483
|
+
});
|
|
484
|
+
// All results should be exported
|
|
485
|
+
results.results.forEach(r => {
|
|
486
|
+
expect(r.isExported).toBe(true);
|
|
487
|
+
});
|
|
488
|
+
}, 60000);
|
|
489
|
+
it('filters by type works across languages', async () => {
|
|
490
|
+
// Find classes
|
|
491
|
+
const classResults = await search.search('helper', {
|
|
492
|
+
filters: { type: ['class'] },
|
|
493
|
+
limit: 10,
|
|
494
|
+
});
|
|
495
|
+
classResults.results.forEach(r => {
|
|
496
|
+
expect(r.type).toBe('class');
|
|
497
|
+
});
|
|
498
|
+
// Find functions
|
|
499
|
+
const fnResults = await search.search('add', {
|
|
500
|
+
filters: { type: ['function'] },
|
|
501
|
+
limit: 10,
|
|
502
|
+
});
|
|
503
|
+
fnResults.results.forEach(r => {
|
|
504
|
+
expect(['function', 'method']).toContain(r.type);
|
|
505
|
+
});
|
|
506
|
+
}, 60000);
|
|
507
|
+
it('hasDocstring filter works across languages', async () => {
|
|
508
|
+
const results = await search.search('greeting', {
|
|
509
|
+
filters: { hasDocstring: true },
|
|
510
|
+
limit: 20,
|
|
511
|
+
});
|
|
512
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
513
|
+
}, 60000);
|
|
514
|
+
});
|
|
515
|
+
describe('Language Extension Mapping', () => {
|
|
516
|
+
const langExtensions = [
|
|
517
|
+
{ ext: '.go', lang: 'Go' },
|
|
518
|
+
{ ext: '.rs', lang: 'Rust' },
|
|
519
|
+
{ ext: '.java', lang: 'Java' },
|
|
520
|
+
{ ext: '.cs', lang: 'C#' },
|
|
521
|
+
{ ext: '.dart', lang: 'Dart' },
|
|
522
|
+
{ ext: '.swift', lang: 'Swift' },
|
|
523
|
+
{ ext: '.kt', lang: 'Kotlin' },
|
|
524
|
+
{ ext: '.php', lang: 'PHP' },
|
|
525
|
+
];
|
|
526
|
+
it.each(langExtensions)('$lang files ($ext) are indexed and searchable', async ({ ext }) => {
|
|
527
|
+
const results = await search.search('function', {
|
|
528
|
+
filters: { extension: [ext] },
|
|
529
|
+
limit: 5,
|
|
530
|
+
});
|
|
531
|
+
expect(results.results.length).toBeGreaterThan(0);
|
|
532
|
+
expect(results.results[0]?.filepath).toContain(ext);
|
|
533
|
+
}, 60000);
|
|
534
|
+
});
|
|
535
|
+
});
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* E2E tests for the RAG system.
|
|
3
|
+
*
|
|
4
|
+
* Tests system behavior, not library correctness:
|
|
5
|
+
* - Merkle tree correctly detects file changes
|
|
6
|
+
* - Search returns expected files for known queries
|
|
7
|
+
* - Incremental indexing only reprocesses what changed
|
|
8
|
+
* - Manifest persistence enables recovery
|
|
9
|
+
*/
|
|
10
|
+
export {};
|