Commit Graph
1 Commits
Author SHA1 Message Date
Colby MchenryandClaude Opus 5.5 ed8957710f fix(objc): a file-scope constant or global is indexed, in an @implementation too (#2699)
Objective-C read a file-scope declaration through the generic variable
fallback, which takes only a declarator that is a bare name (`int count;`).
Its most common globals were never indexed: `NSString *const
SDWebImageErrorDomain = @"…";`, `static const NSInteger kMaxRetries = 3;`,
`static dispatch_queue_t queues[4];`. A declaration written inside an
@implementation, file-scope C in the language, was not read at all,
because the class counts as an enclosing scope.

- tree-sitter.ts: Objective-C takes C's declarator branch in
  extractVariable (initialized, pointer and array declarators, with the
  initializer as the signature), keeping the bare names it always read.
  A declaration whose parent is an implementation_definition takes the
  variable branch; its globals are qualified under the class, as the
  C functions written there already are. A block or function-pointer
  variable reads as a prototype, as in C, and stays out.
- c-cpp.ts: isConstDeclaration, C's isConst, is shared, and objc.ts uses
  it, so `static const NSInteger kMaxRetries` is a constant.
- name-matcher.ts: a global that a .m or .mm file defines joins the C
  types that #2690 made file-local (OBJC_FILE_LOCAL_KINDS). A new
  isObjcFileLocalElsewhere drops such a candidate in the exact-match and
  fuzzy chains, before one is picked, and isVisibleAcrossFiles applies it
  to the pick. Before the pick, so that a header's `extern NSString
  *MJConfigFile;` stands for the definition in variables.m. Rejecting only
  the pick left Hammerspoon's MJConfigFile references unresolved. Without
  the rule, React Native's completionHandler(nil, image) block-parameter
  calls reached a completionHandler in another .mm, and #include <vector>
  a .mm's vector.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-20 01:43:14 +00:00