|
@@ -603,9 +603,11 @@ export function matchScopedCallChain(
|
|
|
* so a bare `Foo()` there is a method call, not construction — excluded. Scala's
|
|
* 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(args)` is a case-class / companion `apply`, which conventionally returns
|
|
|
* `Foo` — and resolveMethodOnType validates, so a non-conventional `apply` that
|
|
* `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 —
|
|
* 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)) {
|
|
if (ref.language === 'objc' && /^[A-Z]/.test(factoryClass)) {
|
|
|
return resolveMethodOnType(factoryClass, method, ref, context, 0.8, 'instance-method', importedFqnOf(factoryClass, ref, context));
|
|
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 null;
|
|
|
}
|
|
}
|
|
|
return resolveMethodOnType(ret, method, ref, context, 0.85, 'instance-method', importedFqnOf(ret, ref, context));
|
|
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 === 'go' ||
|
|
|
ref.language === 'scala' ||
|
|
ref.language === 'scala' ||
|
|
|
ref.language === 'dart' ||
|
|
ref.language === 'dart' ||
|
|
|
- ref.language === 'objc'
|
|
|
|
|
|
|
+ ref.language === 'objc' ||
|
|
|
|
|
+ ref.language === 'pascal'
|
|
|
) {
|
|
) {
|
|
|
result = matchDottedCallChain(ref, context);
|
|
result = matchDottedCallChain(ref, context);
|
|
|
if (result) return result;
|
|
if (result) return result;
|