Skip to content

fix(extraction): preload the Objective-C grammar for C-family headers (#1628) - #1634

Open
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1628-objc-header-grammar
Open

fix(extraction): preload the Objective-C grammar for C-family headers (#1628)#1634
maxmilian wants to merge 1 commit into
colbymchenry:mainfrom
maxmilian:fix/1628-objc-header-grammar

Conversation

@maxmilian

Copy link
Copy Markdown
Contributor

Fixes #1628.

A .h file is classified from its path alone as C, so the preload set handed to the parse workers contains c — plus cpp, added explicitly because a header might turn out to be C++. Parse-time detection then reads the source and can also return objc (detectLanguage's .h branch checks looksLikeCpp and looksLikeObjc), and no worker holds that grammar. The file fails outright with Failed to get parser for language: objc and nothing in it reaches the index.

That is why the failure looked arbitrary: any .m file in the project pulls objc into the set by path, so the very same header indexes fine. @Juddd's control experiment — adding a one-line grammar_seed.m and watching both files index — pins it exactly.

So objc is preloaded alongside cpp whenever c is present: both are readings that content-aware .h detection can produce, and both have to be available before the workers start.

Verified against the reporter's reproduction

A directory containing only:

@interface CGRepro
- (void)run;
@end

Before (codegraph init --yes on current main):

1 parser initialization failures
# .codegraph/errors.log
repro.h: Failed to get parser for language: objc

After:

Indexed 1 files
2 nodes, 1 edges in 315ms

One refactor, and why it's in scope

The three lines that build this set existed twice — once for the full index, once for the changed-file reindex — and fixing only the copy the issue points at leaves the other one carrying the same bug for incremental runs. Both now call preloadLanguagesForFiles(), which also makes the rule unit-testable instead of buried inside a 200-line method.

Tests

__tests__/preload-languages.test.ts, four cases: both ambiguous readings of a .h are covered; a project with no C-family header gets neither grammar added; a language the files already need isn't duplicated; extension overrides still drive the base set.

Confirmed red by reverting just the objc half of the change (expected [ 'c', 'cpp' ] to include 'objc'), so the test pins this fix rather than restating the implementation.

Full suite: 179 files / 3056 tests passing (3052 on main plus these four). tsc --noEmit clean.

Reported and diagnosed by @Juddd.

…colbymchenry#1628)

A .h file is classified from its path as C, so the preload set that the parse
workers receive contains c (and cpp, added explicitly for exactly this
reason). Parse-time detection then reads the source and can return objc — a
grammar no worker holds, so the file fails outright with 'Failed to get
parser for language: objc' and nothing in it is indexed. A project with any
.m file happened to work, because that pulled objc into the set by path.

Preload objc alongside cpp whenever c is present: both are readings that
content-aware .h detection can produce, so both have to be available before
the workers start.

The same three lines existed twice (full index and changed-file reindex), and
only one of them would have been easy to remember to change, so this extracts
preloadLanguagesForFiles() and uses it in both places.

Verified end to end against the reporter's reproduction — a directory holding
only an Objective-C .h file:
  before: 1 parser initialization failures / 'Failed to get parser for
          language: objc' in .codegraph/errors.log
  after:  Indexed 1 files, 2 nodes, 1 edges

Co-Authored-By: Claude <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Objective-C .h files fail to parse unless a .m file preloads the grammar

1 participant