11import fs from "node:fs"
22import 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"
55import { SymbolWithRange } from ".."
66import { getUriFileExtension } from "./uri"
77
@@ -119,11 +119,11 @@ export const IGNORE_PATH_PATTERNS: Partial<Record<LanguageName, RegExp[]>> = {
119119}
120120
121121export 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
219223async 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