Ports the #645/#608 chained-receiver mechanism to Pascal/Delphi — which I'd previously mis-scoped as blocked. The paren'd chained form extracts fine; it just hit the chained-call gap like the others (with a decoy, `TFoo.GetInstance().DoIt()` mis-resolved to a same-named method on an unrelated class). - pascal.ts: getReturnType reads the method's `typeref` (a `function GetInstance: TBar` returns TBar; an interface return `IFoo` is captured too). - tree-sitter.ts: extractPascalCall now re-encodes a chained call `TFoo.GetInstance().DoIt` (the exprDot's receiver is an exprCall) instead of collapsing it to bare `DoIt`. Gated on the Delphi type-naming convention (`TFoo`/`IFoo`) so a capitalized VARIABLE chain (Pascal capitalizes locals too — `Curve.X().Y()`, `Self.X().Y()`) stays bare and keeps its existing bare-name resolution. - name-matcher.ts: `pascal` joins the dotted-chain gate + CHAIN_LANGUAGES + CONSTRUCTS_VIA_BARE_CALL (a `TFoo(x)` typecast yields a TFoo). When the factory's return type wasn't captured (a `constructor Create` has no `: TBar` but returns its class), resolve the method on the factory class itself. resolveMethodOnType validates, so a wrong inference yields no edge. Validation: 4 synthetic tests (factory+decoy, constructor chain, typecast chain, absent-method safety). Real-repo A/B on PascalCoin (772 files): +19 / -18 — 15 of the -18 are correct class→interface retargets (`GetInstance(): IAsn1OctetString` resolves `.GetOctets` on the declared interface, not baseline's concrete-class guess); 3 are negligible drops (0.02%). EXTRACTION_VERSION 15->16. Full suite green. Co-authored-by: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
a4d19a5ed8
commit
af56f3539d
@@ -603,9 +603,11 @@ export function matchScopedCallChain(
|
||||
* so a bare `Foo()` there is a method call, not construction — excluded. Scala's
|
||||
* `Foo(args)` is a case-class / companion `apply`, which conventionally returns
|
||||
* `Foo` — and resolveMethodOnType validates, so a non-conventional `apply` that
|
||||
* returns another type simply yields no edge rather than a wrong one.
|
||||
* returns another type simply yields no edge rather than a wrong one. Pascal/Delphi:
|
||||
* a `TFoo(x)` is a TYPECAST whose result is a `TFoo`, so `TFoo(x).method()` resolves
|
||||
* the method on `TFoo` — same shape, same validation.
|
||||
*/
|
||||
const CONSTRUCTS_VIA_BARE_CALL = new Set(['kotlin', 'swift', 'scala', 'dart']);
|
||||
const CONSTRUCTS_VIA_BARE_CALL = new Set(['kotlin', 'swift', 'scala', 'dart', 'pascal']);
|
||||
|
||||
/**
|
||||
* Resolve a dotted chained call whose receiver is a static factory / fluent call —
|
||||
@@ -688,6 +690,18 @@ export function matchDottedCallChain(
|
||||
if (ref.language === 'objc' && /^[A-Z]/.test(factoryClass)) {
|
||||
return resolveMethodOnType(factoryClass, method, ref, context, 0.8, 'instance-method', importedFqnOf(factoryClass, ref, context));
|
||||
}
|
||||
// Pascal/Delphi: the extractor only re-encodes a `TFoo`/`IFoo`-prefixed chain
|
||||
// (the type-naming convention), so `factoryClass` is always a real class here.
|
||||
// A factory whose return type wasn't captured is a CONSTRUCTOR
|
||||
// (`TFileMem.Create().SetCachePerformance` — `constructor Create` has no `:
|
||||
// TBar` annotation but returns its own class) or an unannotated function. In
|
||||
// both cases the receiver's type is the class itself, so resolve the method on
|
||||
// `factoryClass`. resolveMethodOnType validates against it (and its
|
||||
// supertypes), so a wrong inference yields no edge — and this never fires when
|
||||
// a return type WAS captured but lacks the method (absent-method safety above).
|
||||
if (ref.language === 'pascal' && /^[TI]/.test(factoryClass)) {
|
||||
return resolveMethodOnType(factoryClass, method, ref, context, 0.8, 'instance-method', importedFqnOf(factoryClass, ref, context));
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return resolveMethodOnType(ret, method, ref, context, 0.85, 'instance-method', importedFqnOf(ret, ref, context));
|
||||
@@ -1153,7 +1167,8 @@ export function matchReference(
|
||||
ref.language === 'go' ||
|
||||
ref.language === 'scala' ||
|
||||
ref.language === 'dart' ||
|
||||
ref.language === 'objc'
|
||||
ref.language === 'objc' ||
|
||||
ref.language === 'pascal'
|
||||
) {
|
||||
result = matchDottedCallChain(ref, context);
|
||||
if (result) return result;
|
||||
|
||||
Reference in New Issue
Block a user