diff --git a/gitnexus/src/core/ingestion/call-processor.ts b/gitnexus/src/core/ingestion/call-processor.ts index c2f9be2d6..c388243e6 100644 --- a/gitnexus/src/core/ingestion/call-processor.ts +++ b/gitnexus/src/core/ingestion/call-processor.ts @@ -101,6 +101,14 @@ const findEnclosingFunction = ( innerDecl.children?.find((c: any) => c.type === 'identifier'); funcName = nameIdent?.text; label = 'Method'; // qualified_identifier => registered as Method + } else if (innerDecl?.type === 'field_identifier') { + // C++ inline method with body inside class: void myMethod() { ... } + funcName = innerDecl.text; + label = 'Method'; + } else if (innerDecl?.type === 'operator_name') { + // C++ operator overload inside class body: operator[] + funcName = innerDecl.text; + label = 'Method'; } } } diff --git a/gitnexus/src/core/ingestion/parsing-processor.ts b/gitnexus/src/core/ingestion/parsing-processor.ts index 817906163..67189f96c 100644 --- a/gitnexus/src/core/ingestion/parsing-processor.ts +++ b/gitnexus/src/core/ingestion/parsing-processor.ts @@ -311,7 +311,10 @@ const processParsingSequential = async ( let tree; try { - tree = parser.parse(file.content, undefined, { bufferSize: 1024 * 256 }); + // bufferSize must be >= file size. Use 2× file size, minimum 512KB, maximum 32MB. + const fileSizeBytes = Buffer.byteLength(file.content, 'utf8'); + const bufSize = Math.min(Math.max(fileSizeBytes * 2, 512 * 1024), 32 * 1024 * 1024); + tree = parser.parse(file.content, undefined, { bufferSize: bufSize }); } catch (parseError) { console.warn(`Skipping unparseable file: ${file.path}`); continue; diff --git a/gitnexus/src/core/ingestion/tree-sitter-queries.ts b/gitnexus/src/core/ingestion/tree-sitter-queries.ts index b2fe09e53..f03295bb8 100644 --- a/gitnexus/src/core/ingestion/tree-sitter-queries.ts +++ b/gitnexus/src/core/ingestion/tree-sitter-queries.ts @@ -228,13 +228,31 @@ export const CPP_QUERIES = ` (namespace_definition name: (namespace_identifier) @name) @definition.namespace (enum_specifier name: (type_identifier) @name) @definition.enum +; Typedefs and unions (common in C-style headers and mixed C/C++ code) +(type_definition declarator: (type_identifier) @name) @definition.typedef +(union_specifier name: (type_identifier) @name) @definition.union + +; Macros +(preproc_function_def name: (identifier) @name) @definition.macro +(preproc_def name: (identifier) @name) @definition.macro + ; Functions & Methods (function_definition declarator: (function_declarator declarator: (identifier) @name)) @definition.function (function_definition declarator: (function_declarator declarator: (qualified_identifier name: (identifier) @name))) @definition.method +; Function declarations / prototypes (common in headers) +(declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.function -; Inline class methods (defined inside the class body) +; Inline class method declarations (inside class body, no body: void Foo();) (field_declaration declarator: (function_declarator declarator: (identifier) @name)) @definition.method +; Inline class method definitions (inside class body, with body: void Foo() { ... }) +; The function_definition is a direct child of field_declaration_list, not wrapped in field_declaration. +; Name uses field_identifier (regular methods) or identifier (constructors) or operator_name (operators). +(field_declaration_list + (function_definition + declarator: (function_declarator + declarator: [(field_identifier) (identifier) (operator_name)] @name))) @definition.method + ; Templates (template_declaration (class_specifier name: (type_identifier) @name)) @definition.template (template_declaration (function_definition declarator: (function_declarator declarator: (identifier) @name))) @definition.template diff --git a/gitnexus/src/core/ingestion/utils.ts b/gitnexus/src/core/ingestion/utils.ts index 47fa8cbe4..0d2321966 100644 --- a/gitnexus/src/core/ingestion/utils.ts +++ b/gitnexus/src/core/ingestion/utils.ts @@ -37,11 +37,13 @@ export const getLanguageFromFilename = (filename: string): SupportedLanguages | if (filename.endsWith('.py')) return SupportedLanguages.Python; // Java if (filename.endsWith('.java')) return SupportedLanguages.Java; - // C (source and headers) - if (filename.endsWith('.c') || filename.endsWith('.h')) return SupportedLanguages.C; - // C++ (all common extensions) + // C source files + if (filename.endsWith('.c')) return SupportedLanguages.C; + // C++ (all common extensions, including .h) + // .h is parsed as C++ because tree-sitter-cpp is a strict superset of C, so pure-C + // headers parse correctly, and C++ headers (classes, templates) are handled properly. if (filename.endsWith('.cpp') || filename.endsWith('.cc') || filename.endsWith('.cxx') || - filename.endsWith('.hpp') || filename.endsWith('.hxx') || filename.endsWith('.hh')) return SupportedLanguages.CPlusPlus; + filename.endsWith('.h') || filename.endsWith('.hpp') || filename.endsWith('.hxx') || filename.endsWith('.hh')) return SupportedLanguages.CPlusPlus; // C# if (filename.endsWith('.cs')) return SupportedLanguages.CSharp; // Go diff --git a/gitnexus/src/core/ingestion/workers/parse-worker.ts b/gitnexus/src/core/ingestion/workers/parse-worker.ts index 004502366..771437595 100644 --- a/gitnexus/src/core/ingestion/workers/parse-worker.ts +++ b/gitnexus/src/core/ingestion/workers/parse-worker.ts @@ -353,6 +353,16 @@ const findEnclosingFunctionId = (node: any, filePath: string): string | null => innerDecl.children?.find((c: any) => c.type === 'identifier'); funcName = nameIdent?.text; label = 'Method'; // qualified_identifier => registered as Method + } else if (innerDecl?.type === 'field_identifier') { + // C++ inline method with body inside class: void myMethod() { ... } + // The function_definition is a direct child of field_declaration_list. + // Name node is field_identifier, registered as 'Method'. + funcName = innerDecl.text; + label = 'Method'; + } else if (innerDecl?.type === 'operator_name') { + // C++ operator overload inside class body: operator[] + funcName = innerDecl.text; + label = 'Method'; } } } @@ -1166,7 +1176,10 @@ const processFileGroup = ( let tree; try { - tree = parser.parse(file.content, undefined, { bufferSize: 1024 * 256 }); + // bufferSize must be >= file size. Use 2× file size, minimum 512KB, maximum 32MB. + const fileSizeBytes = Buffer.byteLength(file.content, 'utf8'); + const bufSize = Math.min(Math.max(fileSizeBytes * 2, 512 * 1024), 32 * 1024 * 1024); + tree = parser.parse(file.content, undefined, { bufferSize: bufSize }); } catch { continue; }