Skip to content

fix(extraction): detect export-macro-annotated class in .h language check (#1159)#1207

Merged
colbymchenry merged 1 commit into
mainfrom
fix/cpp-export-macro-header-detection-1159
Jul 7, 2026
Merged

fix(extraction): detect export-macro-annotated class in .h language check (#1159)#1207
colbymchenry merged 1 commit into
mainfrom
fix/cpp-export-macro-header-detection-1159

Conversation

@colbymchenry

Copy link
Copy Markdown
Owner

Carries @luoyxy's #1133 forward onto current main (rebased to resolve conflicts with the UE work — #1158 and the #1206 dense-header guard — that landed after #1133 was opened; the fix itself in grammars.ts was unchanged and auto-merged).

Fixes #1159.

The bug

A .h file defaults to C and is only reclassified as C++ when looksLikeCpp finds a C++-specific construct. That check couldn't see through an export/visibility macro: in class ENGINE_API UFoo : public UObject the macro sits between class and the type name, so the macro-blind \bclass\s+\w+\s*[:{] branch failed to match. A lean Unreal-Engine header carrying only that macro-annotated class plus GENERATED_BODY() — no public: / virtual / namespace / template to fall back on — was therefore parsed as C. The C extractor has classTypes: [] and no export-macro pre-parse, so the class definition and its inheritance edge silently vanished, quietly undoing the macro-class recovery from #1061.

Note: the issue's literal minimal repro has a public: inside the body, which already trips the existing heuristic → detects cpp. The true failing shape is the lean header (no other C++ signal), which this PR targets.

The fix

One alternation branch added to looksLikeCpp, mirroring the exact shape blankCppExportMacros already recovers:

\b(?:class|struct)\s+[A-Z][A-Z0-9_]+\s+\w+\s*(?:final\s*)?[:{]

The macro shape [A-Z][A-Z0-9_]+ is identical to blankCppExportMacros (c-cpp.ts) — so the exact set of headers this routes to cpp is precisely the set the C++ path then recovers (no "routes to cpp but still collapses" gap). The two-token <keyword> <MACRO> <Name> before a [:{] never occurs in valid C, so genuine C headers are unaffected.

Verified (on current main)

Header (.h) before after
class ENGINE_API UFoo : public UObject + GENERATED_BODY(), no public: c cpp
struct ENGINE_API FBar : public FBase {}; c cpp
class MYMODULE_API FFoo { (brace next line, no base) c cpp
C guards (struct Point {…}, struct FOO bar;, struct FOO getFoo(){, enum COLOR{…}, struct FOO x = {5}, typedef struct FOO T;) c c ✓ (unchanged)

Test plan

  • New regression test in __tests__/extraction.test.ts (macro class, macro struct w/ inheritance, brace-next-line, plus a genuine-C guard)
  • npx vitest run __tests__/extraction.test.ts — 579 passed
  • npx tsc --noEmit clean

🤖 Generated with Claude Code

…heck (#1133)

A `.h` file defaults to C and is reclassified as C++ only when
`looksLikeCpp` finds a C++-specific construct. Its class branch
(`\bclass\s+\w+\s*[:{]`) couldn't see through an export/visibility macro:
in `class ENGINE_API UFoo : public UObject` the macro sits between `class`
and the type name, so `\w+` consumed the macro and the following `[:{]`
guard failed. A lean Unreal-Engine header carrying only that macro-class
plus `GENERATED_BODY()` — with no `public:` / `virtual` / `namespace` /
`template` to fall back on — was therefore parsed as C. The C extractor
has `classTypes: []` and no export-macro pre-parse, so the class
definition and its inheritance edge silently vanished, undoing the
macro-class recovery from #1061.

Add a detection branch for a macro-annotated `class`/`struct` declaration,
mirroring the shape `blankCppExportMacros` already recovers before
parsing. The two-token `<keyword> <MACRO> <Name>` before a `[:{]` never
occurs in valid C, so genuine C headers stay classified as C (covered by a
new regression guard).

Thanks @luoyxy for the report and root-cause analysis.
@colbymchenry colbymchenry merged commit a9e8fa4 into main Jul 7, 2026
1 check passed
@colbymchenry colbymchenry deleted the fix/cpp-export-macro-header-detection-1159 branch July 7, 2026 17:21
pull Bot pushed a commit to TheTechOddBug/codegraph that referenced this pull request Jul 7, 2026
…heck (colbymchenry#1159) (colbymchenry#1207)

Carries colbymchenry#1133 forward onto current main (rebased for conflicts). A lean Unreal-Engine-style `.h` whose only C++ signal is `class ENGINE_API Foo : public Bar` (no public:/virtual/namespace/template) was misdetected as C and its class + inheritance edge silently dropped; looksLikeCpp now recognizes the export-macro-annotated class/struct shape, matching what blankCppExportMacros already recovers.

Fixes colbymchenry#1159.

Co-Authored-By: robertyluo <robertyluo@tencent.com>
Co-Authored-By: Claude Opus 4.8 (1M context) <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.

UE-style single-line export-macro class headers (class ENGINE_API Foo : public Bar) are misdetected as C and their class definitions are dropped

1 participant