Kotlin: Fix extension and dispatch parameter order in $default functions

This commit is contained in:
Tamas Vajk
2022-12-07 12:24:41 +01:00
parent 6457e059f5
commit d93dce0fa9
8 changed files with 71 additions and 50 deletions

View File

@@ -1896,7 +1896,8 @@ class VarAccess extends Expr, @varaccess {
class ExtensionReceiverAccess extends VarAccess {
ExtensionReceiverAccess() {
exists(Parameter p |
this.getVariable() = p and p.getPosition() = 0 and p.getCallable() instanceof ExtensionMethod
this.getVariable() = p and
p.isExtensionParameter()
)
}

View File

@@ -327,18 +327,8 @@ class Callable extends StmtParent, Member, @callable {
this instanceof Method and
result instanceof Method and
this.getName() + "$default" = result.getName() and
extraLeadingParams <= 1 and
(
if ktExtensionFunctions(this, _, _)
then
// Both extension receivers are expected to occur at arg0, with any
// dispatch receiver inserted afterwards in the $default proxy's parameter list.
// Check the extension receiver matches here, and note regular args
// are bumped one position to the right.
regularParamsStartIdx = extraLeadingParams + 1 and
this.getParameterType(0).getErasure() = eraseRaw(result.getParameterType(0))
else regularParamsStartIdx = extraLeadingParams
) and
extraLeadingParams <= 1 and // 0 for static methods, 1 for instance methods
regularParamsStartIdx = extraLeadingParams and
lastParamType instanceof TypeObject
)
|
@@ -824,4 +814,19 @@ class ExtensionMethod extends Method {
KotlinType getExtendedKotlinType() { result = extendedKotlinType }
override string getAPrimaryQlClass() { result = "ExtensionMethod" }
/**
* Gets the index of the parameter that is the extension receiver. This is typically index 0. In case of `$default`
* extension methods that are defined as members, the index is 1. Index 0 is the dispatch receiver of the `$default`
* method.
*/
int getExtensionParameterIndex() {
if
exists(Method src |
this = src.getKotlinParameterDefaultsProxy() and
src.getNumberOfParameters() = this.getNumberOfParameters() - 3 // 2 extra parameters + 1 dispatch receiver
)
then result = 1
else result = 0
}
}

View File

@@ -91,7 +91,7 @@ class Parameter extends Element, @param, LocalScopeVariable {
/** Holds if this formal parameter is a parameter representing the dispatch receiver in an extension method. */
predicate isExtensionParameter() {
this.getPosition() = 0 and this.getCallable() instanceof ExtensionMethod
this.getPosition() = this.getCallable().(ExtensionMethod).getExtensionParameterIndex()
}
/**