@@ -36,6 +36,16 @@ function extractDefinitions(matches: any[]) {
3636 return defs ;
3737}
3838
39+ function extractCapturedCallNames ( matches : any [ ] ) {
40+ const names : string [ ] = [ ] ;
41+ for ( const match of matches ) {
42+ if ( ! match . captures . some ( ( c : any ) => c . name === 'call' ) ) continue ;
43+ const nameCapture = match . captures . find ( ( c : any ) => c . name === 'call.name' ) ;
44+ if ( nameCapture ) names . push ( nameCapture . node . text ) ;
45+ }
46+ return names ;
47+ }
48+
3949describe ( 'Tree-sitter multi-language parsing' , ( ) => {
4050 let parser : Parser ;
4151
@@ -288,6 +298,48 @@ describe('Tree-sitter multi-language parsing', () => {
288298 expect ( names ) . toContain ( 'helper' ) ;
289299 } ) ;
290300
301+ it ( 'treats CUDA .cu and .cuh files as C++ for definition extraction' , async ( ) => {
302+ expect ( getLanguageFromFilename ( 'src/kernels/force.cu' ) ) . toBe ( SupportedLanguages . CPlusPlus ) ;
303+ expect ( getLanguageFromFilename ( 'src/force/nep.cuh' ) ) . toBe ( SupportedLanguages . CPlusPlus ) ;
304+
305+ await loadLanguage ( SupportedLanguages . CPlusPlus , 'src/kernels/force.cu' ) ;
306+ const code = `class Force { public: void apply(); };\nvoid launchKernel() {}` ;
307+ const provider = getProvider ( SupportedLanguages . CPlusPlus ) ;
308+ const { matches } = parseAndQuery ( parser , code , provider . treeSitterQueries ) ;
309+ const defs = extractDefinitions ( matches ) ;
310+ const names = defs . map ( ( d ) => d . name ) ;
311+
312+ expect ( defs . some ( ( d ) => d . type === 'definition.class' && d . name === 'Force' ) ) . toBe ( true ) ;
313+ expect ( names ) . toContain ( 'launchKernel' ) ;
314+ } ) ;
315+
316+ it ( 'characterizes CUDA syntax when routed through the C++ parser' , async ( ) => {
317+ await loadLanguage ( SupportedLanguages . CPlusPlus , 'src/kernels/force.cu' ) ;
318+ const code = `
319+ __global__ void axpy(float *x) { x[0] = 1.0f; }
320+ void host() {
321+ axpy<<<1, 32>>>(nullptr);
322+ cudaDeviceSynchronize();
323+ }
324+ ` ;
325+ const provider = getProvider ( SupportedLanguages . CPlusPlus ) ;
326+ const { tree, matches } = parseAndQuery ( parser , code , provider . treeSitterQueries ) ;
327+ const defs = extractDefinitions ( matches ) ;
328+ const callNames = extractCapturedCallNames ( matches ) ;
329+ const ordinaryCalls = extractCapturedCallNames (
330+ parseAndQuery (
331+ parser ,
332+ 'void host() { cudaDeviceSynchronize(); }' ,
333+ provider . treeSitterQueries ,
334+ ) . matches ,
335+ ) ;
336+
337+ expect ( tree . rootNode . hasError ) . toBe ( true ) ;
338+ expect ( defs . some ( ( d ) => d . name === 'axpy' ) ) . toBe ( true ) ;
339+ expect ( ordinaryCalls ) . toContain ( 'cudaDeviceSynchronize' ) ;
340+ expect ( callNames ) . not . toContain ( 'axpy' ) ;
341+ } ) ;
342+
291343 it ( 'captures C++ typedef anonymous structs, enums, and enumerators' , async ( ) => {
292344 await loadLanguage ( SupportedLanguages . CPlusPlus ) ;
293345 const code = `
0 commit comments