fix(apex): match qualified and generic method return types (#3217) - #3276
fix(apex): match qualified and generic method return types (#3217)#3276Soumyadip2003-AI wants to merge 2 commits into
Conversation
…Labs#3217) `method_re` matched the return type with `[\w<>\[\]]+`, so any signature whose return type carried a dot, a comma, or a space never matched and the method was dropped with no node, no edges, and no warning. That covers the two most common shapes in real Apex: `Database.QueryLocator` (every `Database.Batchable.start()`) and `Map<String, Object>` (the `@AuraEnabled` controller convention), plus nested generics like `List<Map<String, Id>>`. Widen the return type to a single `_TYPE` pattern that admits a namespace-qualified name and generic arguments. Whitespace is admitted only adjacent to a comma, so a statement such as `insert new Account(...)` or `Integer a = 1, b = compute();` still cannot be read as a declaration - extraction of the existing fixtures is byte-identical. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01UEfivKVYzq1e5E6hJHiuKi
There was a problem hiding this comment.
Graphify reviewed this change.
Worth a look — the grounded gate found no coupling regressions or blocking issues, but 1 advisory finding(s) below merit a look before merge.
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Widens the Apex method-signature regex to accept namespace-qualified and generic return types (Database.QueryLocator, Map<String, Object>, List<Map<String, Id>>), so those methods are now extracted instead of dropped. The new _TYPE pattern only allows whitespace adjacent to a comma, keeping statements like insert new Account(...) from being misread as declarations (#3217). Adds tests covering the qualified/generic return types and confirming ordinary statement bodies yield no spurious method nodes.
Worth a look
- Generic return types with legal whitespace around angle brackets are skipped —
graphify/extractors/apex.py:81· Escalate · medium- agreed by 2 of 2 members but NOT verified (no proof, no reproducing execution) — consensus is not a verdict; needs human review
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 560 functions depend on the 560 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract_apex()— 17 callers, 4 callees
Verification — 560 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 560 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify extract\_apex.
The verifier did not have enough to check extract\_apex, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set
· 1 more finding(s) on lines outside this diff (see the check run).
… type
Review follow-up. The first pass admitted whitespace only next to a comma, so a
return type spaced around the angle brackets themselves - all legal Apex - was
still dropped:
public Map <String, Object> spaceBeforeAngle() # dropped
public List< Account > spacesInside() # dropped
public List < Map< String, Id > > roomy() # dropped
Read the type as segments joined by the type punctuators `<`, `>` and `,`, with
whitespace allowed only adjacent to one of them and never between two bare
words. That separator rule is what still bars an ordinary statement from being
read as a declaration, so a bare `<`/`>` used as a comparison
(`if (a > b) { doIt(x); }`, `while (i < list.size()) { next(); }`) fabricates
nothing; the negative test grew those cases plus a generic cast, and extraction
of the existing fixtures is unchanged.
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01UEfivKVYzq1e5E6hJHiuKi
|
Thanks — the advisory finding is correct, and I reproduced it. Pushed a follow-up commit.
public Map<String, Object> tight() { return null; } // matched
public Map<String , Object> spaceBeforeComma() { return null; } // matched (\s*,\s*)
public Map <String, Object> spaceBeforeAngle() { return null; } // DROPPED
public List< Account > spacesInside() { return null; } // DROPPED
public List < Map< String, Id > > roomy() { return null; } // DROPPEDFixRead the type as segments joined by the type punctuators _TYPE = r"[\w.\[\]]+(?:\s*[<>,]\s*[\w.\[\]]*)*"That separator rule is what still bars an ordinary statement from being read as a declaration: the return type and the method name have to be separated by whitespace the type itself cannot swallow, and On the widened pattern not re-opening the false-positive riskThe obvious worry is that admitting Measured over the two spellings, positives found / statements misread as declarations:
Extraction of On the other two sections of the review, for the record: the formal verification row is an honest abstention ( One thing I could not act on: the review ends with "1 more finding(s) on lines outside this diff (see the check run)", but that finding does not appear in the check-run output or in the PR's review-comment payload, so I have no way to read it. If it can be surfaced I am happy to address it. While testing I did notice one pre-existing false positive that may be it — 🤖 Generated with Claude Code |
There was a problem hiding this comment.
Graphify reviewed this change.
Looks safe to merge — no coupling regressions and no blocking issues, checked against the code graph (not a self-assessment).
Formal verification. No changes could be formally verified in this run.
Graphify review — findings
Tightens the Apex method-declaration regex so return types are matched as </>/,-punctuated segments rather than a single [\w<>\[\]]+ token, correctly recognizing namespace-qualified (Database.QueryLocator), generic (Map<String, Object>), nested-generic, array, and whitespace-loose (Map <String, Id>) returns. Because whitespace is only allowed adjacent to a type punctuator, statements like insert new Account(...) and bare comparisons (if (a > b)) no longer register as declarations. Adds tests covering both the newly-recognized return-type forms and the statements that must not be read as methods.
No blocking issues surfaced. 4 lower-confidence candidates did not survive cross-model review.
Analysis details — impact, health, verification
Impact & health
Graphify review
Impact — 560 functions depend on the 560 functions this change touches.
Health — this change adds coupling hotspots:
- new:
extract_apex()— 17 callers, 4 callees
Verification — 560 functions in the blast radius were not formally verified this run (proofs are advisory here).
Gate & verification
graphify gate
PASS — objectively clean (no health regressions, tests not run — proofs not run this pass (advisory)). Grounded, not self-assessed.
Advisory (not blocking):
- verification_scope: 560 function(s) in the blast radius were not formally verified this run
Formal verification
Could not verify: Could not verify extract\_apex.
The verifier did not have enough to check extract\_apex, so it is saying so rather than guessing. No false assurance is the whole point.
Guarantee: No guarantee either way, this is an honest abstention, not a pass.
Note: Reason: parameter `path` is annotated `Path` — outside the synthesizable primitive/collection set
· 1 more finding(s) on lines outside this diff (see the check run).
Fixes #3217.
The bug
method_reingraphify/extractors/apex.pymatched a method's return type with a single character class:rf"^{_ANNOTATION}\s*{_ACCESS}{_MOD}\s*(?:static\s+)?[\w<>\[\]]+\s+(\w+)\s*\([^)]*\)..."[\w<>\[\]]+admits word characters and angle/square brackets only. Any signature whose return type carries a dot, a comma, or a space therefore never matches, and the method is dropped from the graph entirely — no node, nomethodedge, no warning.That covers the two most common shapes in real Apex:
Database.QueryLocator— everyDatabase.Batchableimplementation'sstart()Map<String, Object>— the@AuraEnabledcontroller conventionList<Map<String, Id>>— nested genericsRepro
The fix
One
_TYPEsub-pattern for an Apex type expression, admitting a namespace-qualified name and generic arguments:The important constraint is that whitespace is admitted only adjacent to a comma. A blanket
\sin the type class would let ordinary statements be read as declarations —insert new Account(Name = 'x');would match with return typeinsertand method namenew...Account. Restricting whitespace to comma-adjacent positions keeps every such statement unmatchable, because the type and the method name still have to be separated by whitespace that the type itself cannot swallow.Verification
tests/fixtures/sample.cls,sample.trigger) is byte-identical before and after — no new nodes, no lost ones.tests/test_languages.py:test_apex_method_qualified_and_generic_return_types— the five signature shapes above.test_apex_statements_are_not_read_as_methods— a negative guard asserting thatinsert new Account(...),System.assertEquals(1, ids.size()),Map<String, Object> m = new Map<String, Object>();,results.put('a', compute(x));,this.helper(1, 2);andInteger a = 1, b = compute();still produce exactly one method node.5299 passed, 12 skipped. The one failure,tests/test_labeling.py::test_label_communities_batches_when_over_batch_size, reproduces identically on a clean checkout ofv8and is unrelated to this change.Out of scope
While building the repro I hit a second, separate bug in the same file that this PR deliberately does not touch: the class heritage clause (
(?:\s+extends\s+(\w+))?(?:\s+implements\s+([\w,\s]+))?) also stops at a dot, soclass Batch implements Database.Batchable<sObject>, Schedulablefabricates a node labelledDatabaseand losesSchedulableentirely. Filed separately.🤖 Generated with Claude Code
https://claude.ai/code/session_01UEfivKVYzq1e5E6hJHiuKi