The guide documents ambiguous_reference for an unqualified call into
another file and a refusal for R6 methods, but no fixture covered
either. Add both. The R6 method is refused by the provider as a class
member (unsupported_occurrence); the guide wrongly listed it among the
shared engine's stale_graph refusals, which now name only dotted
functions and S4 classes.
The guide said 18-provider registry. The providers table in
languages/index.ts has 19 entries with R, one per SupportedLanguages
value (counted from the built registry: Object.keys(providers).length).
R skips a binding that is not a function when it looks up the callee of
f(x), but the rename provider claimed every parameter, so a call under
function(x, helper = 2) was left unrenamed and failed after the rename.
A parameter whose default is a constant and which the body never assigns
is no longer claimed, so the call is renamed with the function it
reaches. A parameter that may hold a function (a function or computed
default, or an assignment to it in the body) is claimed as before, and
a call of the name under it is refused as ambiguous_reference, since it
may reach either. A parameter without a default that is called stays a
function-valued parameter and its call is left alone.
A <<- inside a function is a global re-definition that the scope graph
keeps as a second declaration of the same name. A rename dropped the
selected function and its calls but left the superassignment, so after
the rename the function wrote a new global of the old name instead of
replacing the renamed one. The top-level form was already refused by
the engine; checkSafety now refuses any <<- or ->> to the name, in or
out of a function, with the same ambiguous_reference code.
The guard looked only at the text before the first dot, so
to.json.foo (a method of the dotted generic to.json) passed, and base
generics such as print, format, summary and plot were never checked
unless the sources defined them. Every dot-separated prefix of the new
name is now tested against the functions the indexed sources define and
a small list of base generics.
A function written in backticks keeps them in its binding key and on its
node, while NAMESPACE entries and importFrom() carry the bare symbol, so
importFrom(pkg, `%||%`) found no defining file and the call degraded to
the name-based guess, which cannot tell two packages' `%||%` apart.
rFileTopLevel now keys the top-level names by symbol (rBareName) and
records the spellings it saw. resolveRNamedImport looks files up by
symbol, populateRNamespaceImports synthesises the import with the
definition's own spelling (one per spelling the provider uses) and lets
a backtick-defined function of the caller package mask its import. The
global-name-fallback veto and the pkg::name() lookups compare symbols.
The dotted-tail guard still compares the name as written, which is how
finalize indexes it. Names without backticks answer exactly as before,
pinned by a characterisation snapshot recorded before the change.
A call and its definition must spell a backticked name alike to be linked,
and importFrom() of a backtick-defined function does not bind. NAMESPACE
exports and rename match the symbol either way.
The slot pattern matched only list(...) and representation(...), although
the field extractor accepts any call, so setClass("A", slots = c(a =
"numeric")) and setRefClass("R", fields = c(...)) created no Property nodes.
Accept c(...) for both. An unnamed string in slots = c("a", "b") or
fields = c("a", "b") names an untyped member, as in R; an unnamed string in
representation(...) or list(...) is still not a member. The new pattern
captures its callee as @_vecOwner, so the class-naming capture filter does
not mistake these strings for the class name.
Member ids carried no owner, so a second class in one file that shared a
member name with an earlier one (push, items, a setMethod generic, a slot)
minted the same id as the first and lost the member, along with its
HAS_METHOD or HAS_PROPERTY edge.
Register resolveDetachedOwnerName for R. It names the class declared by an
ancestor R6Class assignment, setClass or setRefClass call, or the signature
class of a setMethod call, so ids become Method:<file>:Stack.push#n and
Property:<file>:Stack.items. The owner edge is still attached by postParse
through ownerNameHint. The change is R-only: the hook is optional and
undefined for every other language.
The r-packages characterisation counts now include Child.greet, the member
the id collision used to drop.
r-provider.md: state that an empty or missing if arm is the header's seq
edge (control dependence labels it as the complement of the other arm);
extend the bare-callee limit to library(), require() and source(); say that
NAMESPACE raw strings and strings spanning lines are dropped without a
warning, which the logged-warning sentence did not cover; name the language
registrations that do mention R; give the devtools::load_all() rationale for
the unfiltered library() wildcard.
type-resolution-system.md: R binds no declaration, call-result or
method-call-result types (extractDeclaration is empty and there is no
extractPendingAssignment), and its cross-file propagation is partial, with a
test cited. Drop R from the footnote about synthesizeWildcardImportBindings(),
which does not exist.
The R rename guard compared the raw text of each `string_content` node with the
old and new name. An escaped spelling (`"f\u006fo"`, `'f\x6fo'`, octal) keeps
its escape inside string_content, and a raw string (`r"(foo)"`) has no
string_content node at all, so renaming `foo` proceeded while a get() or
do.call() on the escaped or raw spelling still resolved the old name.
Reproduction: 10 cases in the new test/unit/r-rename-string-guard.test.ts
returned 'ok' instead of unsupported_occurrence on the unfixed provider, and the
two new fixtures string-lookup-escaped and string-lookup-raw (rename-provider-r)
renamed successfully on the unfixed build. The guard now decodes each `string`
node (escapes, octal, raw strings) and compares the value.
docs/languages/r-provider.md said "spelled as a string literal"; it now states
the whole-value rule and what is still not detected (substring, paste0(),
non-indexed files).
Review finding: `methods::setClass(...)` is ignored by the S4 field detector.
Confirmed by test, and wider than fields: every S4/RefClass pattern
(setClass, setRefClass, setGeneric, setMethod in R_QUERIES, plus the field and
method extractors) requires a bare identifier callee, so a namespace_operator
callee creates no class, slot, generic or method. R6::R6Class is supported.
Widening touches nine files (queries, naming-argument, captures, owner hooks,
post-parse, scope resolver, both extractors) and the qualifier-veto logic, so
it is not a trivial change. Documented as a known limit in
docs/languages/r-provider.md and pinned by characterisation tests in
r-definition-anchors.test.ts (each paired with its unqualified control).
Plain R functions rename through the scope graph; S3, string-spelled,
S4, R6 and NAMESPACE-exported names are refused. Adds fixtures, the
rename-provider-r test and its cross-platform shard entries.
populateRNamespaceImports synthesised a named import for every
importFrom(localpkg, name). Names the provider does not export, does not
define at top level, spells with a dot, or defines beside a dotted S3
method of the same tail never resolve, yet the unresolved import counted as
an explicit name claim and suppressed the documented 0.5-confidence
global-name-fallback edge.
Skip the import when resolveRNamedImport returns null, so such names create
no phantom claim and their calls keep the fallback.
Upstream took SCHEMA_BUMP 133 to 137, so the R provider bump moves to 138.
The pin test and the taken-versions list are updated to match. The import-target
benchmark keeps both the R and Rust arms in the heap-budgeted and context
language lists, and the tree-sitter readiness tests keep the R grammar checks
against the reworked report (R is now a peer-patch grammar and the held-grammar
counts changed).
S3method(generic, class, method) registers method, not generic.class, as the S3
method. parseRNamespaceExports ignored the third argument and so marked a
function called generic.class public while the registered method stayed
non-exported. Use the third argument when it is a plain name, else generic.class.
R matches named arguments first, so in setClass(a = "Q", "B", Class = "A") the
class is A. The naming-argument scan stopped at the first unnamed argument and
named both B and A. Keep scanning the list, once and cached, and drop the choice
when an argument spelled with the formal appears. Replaces the pinned known-limit
test and the known-limit wording in the file header and the provider guide.
* 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>