* docs: add Objective-C fork provider notes * feat(objective-c): add deterministic provider and grammar * feat(objective-c): finalize provider MVP * fix(objective-c): harden provider integration * fix(objective-c): normalize bare macro markers * docs(objective-c): integrate provider documentation * fix(objective-c): harden resolution and header classification * fix(objective-c): complete provider follow-ups * fix: address Objective-C review follow-ups * chore: format Objective-C grammar sources * fix(objective-c): harden review follow-ups * Address PR review feedback (#3179) Keep Objective-C chunking and macro recovery aligned with the grammar, and stop Community MEMBER_OF edges from leaking into symbol context. Co-authored-by: Cursor <cursoragent@cursor.com> * Address follow-up review on ObjC chunking and language fallback. Keep preprocessor directive text from changing file-scope brace depth, group real ivar nodes, skip header modifiers, and restore Rakefile/Gemfile detection through getLanguageFromFilename. Co-authored-by: Cursor <cursoragent@cursor.com> * Parse Objective-C headers with the objc grammar in embeddings. ensureAndParse and structural extraction now use the same content classifier as ingest, including method snippets from .h files, so Protocol/Category/Class chunks are not re-parsed as C++. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Keep file-scope macro elision off C line splices and @interface/@protocol/@implementation bodies, and attach ivar attributes to the following instance variable when chunking. Co-authored-by: Cursor <cursoragent@cursor.com> * chore(bench): rebaseline Objective-C CSV emit * feat(objective-c): add workspace resolution and linear emit benches Plain .h files are classified as C++, so the ObjC pass could not resolve #import of those headers. Load a C/C#-style workspace once per pass, and keep protocol-candidate USES linear. Refs #3179 Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) - Compare LadybugDB labels() as a scalar when excluding Community MEMBER_OF edges. - Walk superclass members, skip file-static C sibling defs, and ignore comments in ObjC header/macro scans. Note: pre-existing failure in objective-c-provider integration (worker-pool ready timeout) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Emit Objective-C declaration captures so compilation-unit siblings can share header/implementation bindings, and keep class vs protocol visibility groups distinct. Note: pre-existing failure in worker-pool startup (GITNEXUS_WORKER_READY_TIMEOUT_MS) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> * Address PR review feedback (#3179) Emit every comma-separated property/ivar declarator, and count @interface after a multiline block comment closes so in-declaration macros stay intact. Note: pre-existing failure in worker-pool startup (GITNEXUS_WORKER_READY_TIMEOUT_MS) not addressed by this PR. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: ximengkai <ximengkai@soyoung.com> Co-authored-by: Gergő Magyar <gergomagyar@icloud.com> Co-authored-by: Gergo Magyar <gergomagyar0@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com>
9.1 KiB
Objective-C Language Provider
Status: implemented
The deterministic provider is covered by focused unit and integration tests. The parser-loader ABI smoke runs in the published multi-OS test matrix, and the native prebuild workflow owns Objective-C together with all six vendored grammar targets. This status describes the implemented MVP; it does not promise full Objective-C runtime dispatch.
Goal
Add deterministic, symbol-level Objective-C analysis to GitNexus. The first release must support high-confidence code navigation and direct static dependency analysis for .m, .mm, and Objective-C .h files. It must not imply that Objective-C runtime dispatch is fully resolved.
The provider belongs in the existing language-provider and scope-resolution extension points. Shared ingestion code must remain language-agnostic.
Compatibility contract
- Existing language detection and parsing must remain unchanged.
- A
.hfile must be classified from its content or surrounding context; it cannot be unconditionally claimed by Objective-C because C and C++ also use that extension. - If Objective-C grammar loading fails, the error must clearly name the missing provider/grammar and cannot corrupt a previously valid index.
- Provider and grammar versions must be stored in index metadata. A version change that can alter node identity or edges requires a full rebuild.
- No LLM participates in parsing, name resolution, or edge creation. Analysis is Tree-sitter plus deterministic static resolution.
MVP model
The provider must extract and connect:
- Classes, superclasses, protocols, categories, class extensions, properties, ivars, C functions, imports, declarations, and implementations.
- Instance and class methods, preserving their complete multi-part selector.
- Inheritance, protocol conformance, import, declaration/implementation, host-class/category, and statically resolved call relationships.
Stable identity must include enough ownership to distinguish same-named methods. Recommended forms are:
objc:class:<ClassName>
objc:protocol:<ProtocolName>
objc:category:<HostClass>:<CategoryName>
objc:method:<Owner>:-:<selector>
objc:method:<Owner>:+:<selector>
objc:function:<qualified-or-file-scoped-name>
For example, -loadData:completion: and +loadData:completion: are different symbols. A category method remains linked to both its category and host class; querying the host class must expose distributed implementations.
Resolution policy
Resolution must be conservative. A missing or dynamic target is evidence of uncertainty, not proof that no target exists.
| Receiver case | Required result |
|---|---|
Explicit class name, self, or super |
Resolve when the owner is statically known. |
| Local, parameter, property, or ivar with known static type | Resolve to matching owner and selector. |
| Protocol-typed receiver | Link the protocol method and identify possible implementations as candidates. |
| Multiple host-class/category implementations of one selector | Record all static candidates as evidence; do not emit a certain call edge because runtime image-load order is unknown. |
id, Class, macros, reflection, performSelector:, NSInvocation, runtime injection, or unknown type |
Store selector/location with resolution=unresolved; do not emit a certain call edge. |
The provider should first collect file-local declarations, imports, and types, then resolve across the repository. It must use structured Tree-sitter captures or AST traversal, not regular expressions over source text. Multi-part selectors, block arguments, nullability annotations, generics, macros, and multiline declarations make a regex-only extractor unsafe.
Imports and incremental correctness
- Resolve quoted project imports against the current directory, configured include roots, and indexed headers. Model framework imports as external-module evidence without downloading SDK source.
- Merge
@interface,@implementation, categories, and extensions across files. - A changed header, protocol, class declaration, or category invalidates importing and affected implementation/call-resolution state. Incremental output after such a change must match a full rebuild.
- Index metadata must record provider version, grammar version, include/exclude configuration, and parsing options used for resolution.
Implementation sequence
- Add and package a pinned Objective-C Tree-sitter grammar; verify macOS arm64 and the production Linux runner can load it.
- Add language detection for
.m,.mm, and content-classified.hfiles. - Implement AST extraction and stable IDs for declarations and definitions.
- Implement repository-level merge, imports, inheritance, protocol, and category relationships.
- Add conservative message-send resolution and explicit unresolved evidence.
- Integrate invalidation, metadata comparison, MCP/CLI output, and fixtures.
Fixtures and acceptance
Create a minimal Objective-C fixture containing a class, protocol, category, extension, superclass, properties, ivars, C function, imports, multi-part selector, block parameter, self, super, protocol receiver, and id receiver. Use symodulebridge as a real integration fixture after the minimal suite is stable.
The acceptance bar is:
query "SYModuleCaller"yields class/method semantic nodes, not only file nodes.context "SYModuleCaller" --file <path>yields declaration, implementation, imports, and known references.- Known statically typed message sends create call edges; dynamic sends are marked unresolved.
- Same selector on multiple classes, a category override, and
+versus-methods remain distinct. - A
.m,.h, protocol, or category edit produces results equivalent to a clean rebuild. - Generated documentation, dependency directories, and build output are excluded through explicit indexing configuration.
Non-goals
The MVP does not promise exact runtime type inference for id or instancetype, reflection, swizzling, arbitrary category replacement, dynamic selector construction, or complete impact analysis across every runtime dispatch path. Tool results must surface confidence and unresolved evidence rather than presenting guesses as certain graph facts.
Current implementation coverage
Implemented capabilities:
- Vendored
tree-sitter-objcgrammar, registered through the existing Tree-sitter loader. .mand.mmlanguage mapping plus content-based.hclassification so plain C/C++ headers are not unconditionally claimed.- LanguageProvider extraction for classes, protocols, categories, extensions, methods, properties, ivars, C functions, imports, unresolved message evidence, stable Objective-C qualified names, and provider/grammar metadata.
- Length-preserving preprocessing of bare, file-scope all-caps macro markers before Tree-sitter parsing. This recovers declarations after wrappers such as
RCT_EXTERN_C_BEGIN/RCT_EXTERN_C_ENDwithout expanding macros or adding framework-specific rules. - ScopeResolver edges for imports, inheritance, protocol conformance, category host membership, implementation evidence, and conservative static message sends.
- Persisted query/context support for Objective-C class and method nodes, including implementation evidence via
DECLARES. - Regression tests for grammar loading,
.hclassification, stable identities, conservative calls, metadata feature mismatch, persisted query/context behavior, and incremental-vs-force parity for Objective-C fixture edits.
Known limits of this MVP:
- The first version does not perform full Objective-C runtime dispatch, swizzling, dynamic selector construction, macro expansion, or
idflow inference. Bare file-scope marker macros are elided only to preserve parser recovery; their expansion semantics are not interpreted. - Protocol receiver handling records the protocol method and candidate implementation evidence, but candidate implementations are not emitted as certain call edges.
- When a host class and one or more named categories define the same selector, the provider records candidate evidence rather than choosing a runtime winner or emitting multiple certain call edges.
- Objective-C++
.mmfiles are parsed with the Objective-C grammar path for this MVP; deep C++ semantic extraction inside Objective-C++ bodies remains outside this provider.