Skip to content

Commit a819c6c

Browse files
committed
refactor: fix tree sitter wasm loader
1 parent 358e5c0 commit a819c6c

File tree

1 file changed

+47
-50
lines changed

1 file changed

+47
-50
lines changed

src/services/continuedev/core/util/treeSitter.ts

Lines changed: 47 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import fs from "node:fs"
22
import path from "path"
33

4-
import { Parser, Language, Node as SyntaxNode, Query, Tree } from "web-tree-sitter"
4+
import type { Language, Node as SyntaxNode, Query, Tree } from "web-tree-sitter"
55
import { SymbolWithRange } from ".."
66
import { getUriFileExtension } from "./uri"
77

@@ -119,11 +119,11 @@ export const IGNORE_PATH_PATTERNS: Partial<Record<LanguageName, RegExp[]>> = {
119119
}
120120

121121
export async function getParserForFile(filepath: string) {
122-
console.log('getting parser for filePath', filepath)
123122
try {
124-
console.log('calling parser init')
123+
// Dynamically import Parser to avoid issues with WASM loading
124+
const { Parser } = require("web-tree-sitter")
125+
125126
await Parser.init()
126-
console.log('parse init worked')
127127
const parser = new Parser()
128128

129129
const language = await getLanguageForFile(filepath)
@@ -135,11 +135,21 @@ export async function getParserForFile(filepath: string) {
135135

136136
return parser
137137
} catch (e) {
138-
console.debug("Unable to load language for file", filepath, e)
138+
console.error("Unable to load language for file", filepath, e)
139139
return undefined
140140
}
141141
}
142142

143+
// Helper function to find the first existing path from a list of candidates
144+
function findExistingPath(candidatePaths: string[]): string | undefined {
145+
for (const p of candidatePaths) {
146+
if (fs.existsSync(p)) {
147+
return p
148+
}
149+
}
150+
return undefined
151+
}
152+
143153
// Loading the wasm files to create a Language object is an expensive operation and with
144154
// sufficient number of files can result in errors, instead keep a map of language name
145155
// to Language object
@@ -189,69 +199,56 @@ export async function getQueryForFile(filepathOrUri: string, queryPath: string):
189199

190200
// Resolve the query file from consolidated tree-sitter directory.
191201
// Prefer repo-root/tree-sitter in tests and runtime, but also fall back to core-local layout.
202+
const repoRoot = path.resolve(__dirname, "..", "..", "..", "..")
192203
const baseRoots = [
193204
// In tests (running from src): src/services/continuedev/core/util -> src/services/continuedev
194205
path.resolve(__dirname, "..", ".."),
195206
// In production (dist): dist/services/continuedev/core/util -> src/services/continuedev
196-
path.resolve(__dirname, "..", "..", "..", "..", "src", "services", "continuedev"),
207+
path.join(repoRoot, "src", "services", "continuedev"),
197208
// Fallback: repo root
198-
path.resolve(__dirname, "..", "..", "..", ".."),
199-
].filter(Boolean) as string[]
200-
201-
let sourcePath: string | undefined = undefined
202-
for (const root of baseRoots) {
203-
const candidate = path.join(root, "tree-sitter", queryPath)
204-
if (fs.existsSync(candidate)) {
205-
sourcePath = candidate
206-
break
207-
}
208-
}
209+
repoRoot,
210+
]
211+
212+
const candidatePaths = baseRoots.map((root) => path.join(root, "tree-sitter", queryPath))
213+
const sourcePath = findExistingPath(candidatePaths)
214+
209215
if (!sourcePath) {
210216
return undefined
211217
}
212218

213219
const querySource = fs.readFileSync(sourcePath).toString()
214-
215-
const query = language.query(querySource)
216-
return query
220+
return language.query(querySource)
217221
}
218222

219223
async function loadLanguageForFileExt(fileExtension: string): Promise<Language> {
224+
// Dynamically import Language to avoid issues with WASM loading
225+
const { Language } = require("web-tree-sitter")
226+
220227
const filename = `tree-sitter-${supportedLanguages[fileExtension]}.wasm`
228+
const repoRoot = path.resolve(__dirname, "..", "..", "..", "..")
229+
230+
// The WASM files are copied to src/dist/ during build
231+
// In production (compiled): __dirname = /path/to/kilocode/src/dist or dist/
232+
// In development: __dirname = /path/to/kilocode/src/services/continuedev/core/util
233+
const candidatePaths: string[] = [
234+
// Production: WASM files are in the same directory as the compiled code
235+
path.join(__dirname, filename),
236+
// Development: from src/services/continuedev/core/util -> src/dist
237+
path.join(repoRoot, "dist", filename),
238+
// Fallback: repo root
239+
path.join(repoRoot, filename),
240+
// Legacy: node_modules location (fallback for older setups)
241+
path.join(repoRoot, "src", "node_modules", "tree-sitter-wasms", "out", filename),
242+
]
221243

222-
// Try multiple locations to support both hoisted (root node_modules) and local installs.
223-
const candidateRoots = [
224-
// Prefer repo root first so hoisted node_modules are found (…/continue)
225-
path.resolve(__dirname, "..", "..", ".."),
226-
// Then current working directory when running tests (often …/continue/core)
227-
process.env.NODE_ENV === "test" ? process.cwd() : undefined,
228-
// Compiled dir for runtime usage
229-
__dirname,
230-
// Core directory (…/continue/core)
231-
path.resolve(__dirname, "..", ".."),
232-
].filter(Boolean) as string[]
233-
234-
const candidatePaths: string[] = []
235-
for (const root of candidateRoots) {
236-
// Typical hoisted location in monorepo tests
237-
candidatePaths.push(path.join(root, "node_modules", "tree-sitter-wasms", "out", filename))
238-
// Legacy/local bundled layout
239-
candidatePaths.push(path.join(root, "tree-sitter-wasms", filename))
240-
}
244+
const wasmPath = findExistingPath(candidatePaths)
241245

242-
for (const p of candidatePaths) {
243-
if (fs.existsSync(p)) {
244-
console.log('trying to load', p)
245-
return await Language.load(p)
246-
} else {
247-
console.log('not found', p)
248-
}
246+
if (!wasmPath) {
247+
console.error(`Could not find ${filename}. Tried paths:`, candidatePaths)
248+
throw new Error(`Could not find language WASM file: ${filename}`)
249249
}
250250

251-
// Fallback (will throw with a clear path in error if still missing)
252-
const fallback = path.join(candidateRoots[0]!, "node_modules", "tree-sitter-wasms", "out", filename)
253-
console.log('loading fallback path', fallback)
254-
return await Language.load(fallback)
251+
return await Language.load(wasmPath)
255252
}
256253

257254
// See https://tree-sitter.github.io/tree-sitter/using-parsers

0 commit comments

Comments
 (0)