Skip to content

feat: add C/C++ language support - #69

Open
kapelner wants to merge 2 commits into
NanoNets:mainfrom
kapelner:feat/cpp-support
Open

feat: add C/C++ language support#69
kapelner wants to merge 2 commits into
NanoNets:mainfrom
kapelner:feat/cpp-support

Conversation

@kapelner

@kapelner kapelner commented Aug 9, 2026

Copy link
Copy Markdown

Summary

Adds C/C++ language support to graft's Tier-1 extraction, following the same pattern established for the other supported languages (Go, Python, TS). One "cpp" grammar (tree-sitter-cpp) parses the whole C/C++ family — .c/.h/.cpp/.hpp/.cc/.cxx/.hh/.hxx — uniformly, the same approach clangd and most polyglot tooling take. No separate .c-only language for v1 (documented limitation below).

  • Classes/structs/enums/templates extracted directly (class_specifier/struct_specifier/enum_specifier all carry a name field; template_declaration spans are attributed back to the templated class/function so the card doesn't cut off the template<typename T> line).
  • Functions/methods need a dedicated describeCpp(): function_definition carries no name field at all — it's buried in a declarator chain that can be a plain identifier, an out-of-class Class::method qualifier, a destructor (~Class), or an operator overload (operator==). A header-declared prototype and its .cpp out-of-line definition resolve to exactly one node, not two or zero — the single most important case to get right for a header/source-split codebase.
  • Visibility is stateful: an access_specifier token (public:/private:/protected:) applies to every subsequent class member until the next one (default private for class, public for struct) — unlike every other supported language's per-node exported check, which needed new plumbing (ctx.cppAccess threaded through the walk).
  • Heritage (: public Base) always emits extends — C++ has no interface keyword, so no "first = extends, rest = implements" heuristic is needed (simpler than the analogous C#-style precedent this was modeled on).
  • Calls: member (./->), qualified (Class::static_method, ns::fn) resolved via a direct recvType supply (bypassing the bindings-lookup path, since the qualifier already IS the type name).
  • #include edges capture both "local.h" and <system> forms.

Known limitations (documented in code + CHANGELOG)

  • Macros that expand to declarations aren't understood — same class of limitation as any AST-only tool.
  • Template specializations are treated as ordinary functions/methods by name (no specialization identity modeled).
  • A bareword #include "local.h" (no ./ prefix) only resolves to an in-repo file when it happens to match a real repo-relative path — C's directory-relative-without-prefix include convention isn't specially handled by resolve.ts's existing import resolver.

Test plan

  • tsc --noEmit clean
  • npm run build clean
  • test/graph-cpp.test.ts — 7 tests covering classes/structs/enums/templates, the header/source-split single-node guarantee, access-specifier visibility, heritage, member/qualified calls, #include edges, and contains edges
  • Full existing test suite green, no regressions
  • Smoke-tested via graft build against a real header/source-split C++ fixture

🤖 Generated with Claude Code

kapelner and others added 2 commits August 7, 2026 11:47
One "cpp" grammar (tree-sitter-cpp) parses the whole C/C++ family
uniformly. Extracts classes, structs, enums, and template classes/functions;
resolves header-declared prototypes and their out-of-line `Class::method`
definitions to a single node via declarator-chain unwrapping; tracks
stateful access_specifier visibility (default private for class, public
for struct); emits extends-only heritage (no interface keyword in C++);
and captures member/qualified call edges plus #include edges for both
local and system forms.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Needed to install tree-sitter-cpp and run ad-hoc grammar-inspection
scripts while building C++ support.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
acelan added a commit to acelan/agent-codebase-bench that referenced this pull request Aug 11, 2026
graff's npm package bundles only Go/Python/TypeScript tree-sitter grammars
(no tree-sitter-c), so it cannot index the kernel's C code: builds return
0 C cards and ask() returns unrelated Python matches for i915. Set
graft.enabled: false and drop its broken run data/report row. Re-enable when
the C/C++ parser lands (NanoNets/Graft#69).
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.

1 participant