diff --git a/CHANGELOG.md b/CHANGELOG.md index 141cf103db..476726ad8d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -398,6 +398,8 @@ and adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). - The Claude Code prompt hook no longer runs on the task-notification messages Claude Code injects when a background agent finishes, removing a multi-second stall on every such turn. (#1832) +- Indexing a project that vendors tree-sitter grammars is faster: the C function-pointer pass now skips generated C files, and a tree-sitter `parser.c` counts as generated even when it carries no banner (releases before 0.25 print none). + - Rust calls on `self` now stay with the enclosing type instead of linking to an unrelated type’s same-named method. Thanks @L4XB. (#1861) - Turning telemetry off now resets its identity and stops running processes from recording, sending, or restoring unsent data. (#1869) diff --git a/__tests__/generated-detection.test.ts b/__tests__/generated-detection.test.ts index 9269e771f4..ffd27de687 100644 --- a/__tests__/generated-detection.test.ts +++ b/__tests__/generated-detection.test.ts @@ -187,6 +187,13 @@ describe('hasGeneratedHeader — per-marker coverage (#1500)', () => { expect(hasGeneratedHeader(`${shortFiller}\n// Code generated by foo. DO NOT EDIT.\npackage main\n`)).toBe(true); }); + it('flags a bannerless tree-sitter parser.c, not the grammar\'s hand-written scanner.c', () => { + const parser = '#include "tree_sitter/parser.h"\n\n#if defined(__GNUC__)\n#pragma GCC diagnostic ignored "-Wmissing-field-initializers"\n#endif\n\n#define LANGUAGE_VERSION 14\n#define STATE_COUNT 9\n'; + const scanner = '#include "tree_sitter/parser.h"\n#include \n\nenum TokenType { AUTOMATIC_SEMICOLON };\n'; + expect(hasGeneratedHeader(parser)).toBe(true); + expect(hasGeneratedHeader(scanner)).toBe(false); + }); + it('requires a comment line — the same words in executable code are not a banner', () => { // No comment leader, no open block: this is a bare statement. expect(hasGeneratedHeader('const banner = "Code generated by tool. DO NOT EDIT.";\n')).toBe(false); diff --git a/src/extraction/generated-detection.ts b/src/extraction/generated-detection.ts index 83ec2b1aad..660e993b54 100644 --- a/src/extraction/generated-detection.ts +++ b/src/extraction/generated-detection.ts @@ -195,6 +195,16 @@ const GENERATED_CONTENT_PATTERNS: ReadonlyArray = [ /\bdo not (?:edit|modify)\b.{0,120}?\b(?:auto[- ]?generated|generated file|generated code)\b/i, ]; +/** + * A tree-sitter `parser.c`. Releases before 0.25 print no banner, but every + * generated parser includes the runtime header and defines + * `LANGUAGE_VERSION`; a grammar's hand-written `scanner.c` includes the + * header and never defines the version. + */ +function isTreeSitterParser(head: string): boolean { + return /^#include\s+"tree_sitter\/parser\.h"/m.test(head) && /^#define\s+LANGUAGE_VERSION\s+\d+/m.test(head); +} + /** * Whether the head of `content` carries a recognized machine-generation * banner. Bounded to {@link HEADER_SCAN_CHARS} / {@link HEADER_SCAN_LINES}, @@ -208,6 +218,7 @@ export function hasGeneratedHeader(content: string): boolean { if (!content) return false; const head = content.length > HEADER_SCAN_CHARS ? content.slice(0, HEADER_SCAN_CHARS) : content; + if (isTreeSitterParser(head)) return true; // Fast reject for ~every hand-written file: no line splitting, no allocation // (V8 keeps `head` as a sliced view of `content`). if (!GENERATED_STEM.test(head)) return false; diff --git a/src/resolution/c-fnptr-synthesizer.ts b/src/resolution/c-fnptr-synthesizer.ts index 568b782c9f..61cab1ea31 100644 --- a/src/resolution/c-fnptr-synthesizer.ts +++ b/src/resolution/c-fnptr-synthesizer.ts @@ -432,13 +432,19 @@ interface FileFacts { const NO_INCLUDES: string[] = []; export async function cFnPointerDispatchEdges( - _queries: QueryBuilder, + queries: QueryBuilder, ctx: ResolutionContext, onYield: MaybeYield, onFraction?: (fraction: number) => void ): Promise { let scannedFiles = 0; - const files = ctx.getAllFiles().filter((f) => C_CPP_EXT.test(f)); + const cFiles = ctx.getAllFiles().filter((f) => C_CPP_EXT.test(f)); + // Generated C (parser tables, protobuf-c, bison output) holds data tables, + // not the hand-written registrations and dispatch sites this pass links, + // and it can dwarf the real code: 248 MB of tree-sitter parsers in one + // repository, for no edges. + const generated = queries.generatedPredicateFor(cFiles); + const files = cFiles.filter((f) => !generated(f)); if (files.length === 0) return []; // CODEGRAPH_SYNTH_TIMINGS sub-attribution: this pass is 86% of kernel-scale