JS: support reified usage in extension functions
This commit is contained in:
@@ -41,6 +41,12 @@ public class ReifiedTestGenerated extends AbstractReifiedTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("extensionFun.kt")
|
||||||
|
public void testExtensionFun() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/reified/cases/extensionFun.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("extensionLambda.kt")
|
@TestMetadata("extensionLambda.kt")
|
||||||
public void testExtensionLambda() throws Exception {
|
public void testExtensionLambda() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/reified/cases/extensionLambda.kt");
|
String fileName = JetTestUtils.navigationMetadata("js/js.translator/testData/reified/cases/extensionLambda.kt");
|
||||||
|
|||||||
+10
-13
@@ -36,17 +36,14 @@ import org.jetbrains.kotlin.resolve.descriptorUtil.builtIns
|
|||||||
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
import org.jetbrains.kotlin.types.expressions.OperatorConventions
|
||||||
import java.util.ArrayList
|
import java.util.ArrayList
|
||||||
|
|
||||||
public fun addReceiverToArgs(receiver: JsExpression, arguments: List<JsExpression>): List<JsExpression> {
|
public fun CallArgumentTranslator.ArgumentsInfo.argsWithReceiver(receiver: JsExpression): List<JsExpression> {
|
||||||
if (arguments.isEmpty())
|
val allArguments = ArrayList<JsExpression>(1 + reifiedArguments.size() + valueArguments.size())
|
||||||
return SmartList(receiver)
|
allArguments.addAll(reifiedArguments)
|
||||||
|
allArguments.add(receiver)
|
||||||
val argumentList = ArrayList<JsExpression>(1 + arguments.size())
|
allArguments.addAll(valueArguments)
|
||||||
argumentList.add(receiver)
|
return allArguments
|
||||||
argumentList.addAll(arguments)
|
|
||||||
return argumentList
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// call may be native and|or with spreadOperator
|
// call may be native and|or with spreadOperator
|
||||||
object DefaultFunctionCallCase : FunctionCallCase {
|
object DefaultFunctionCallCase : FunctionCallCase {
|
||||||
// TODO: refactor after fix ArgumentsInfo - duplicate code
|
// TODO: refactor after fix ArgumentsInfo - duplicate code
|
||||||
@@ -118,13 +115,13 @@ object DefaultFunctionCallCase : FunctionCallCase {
|
|||||||
functionRef
|
functionRef
|
||||||
}
|
}
|
||||||
|
|
||||||
return JsInvocation(referenceToCall, addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments))
|
return JsInvocation(referenceToCall, argumentsInfo.argsWithReceiver(extensionReceiver!!))
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun FunctionCallInfo.bothReceivers(): JsExpression {
|
override fun FunctionCallInfo.bothReceivers(): JsExpression {
|
||||||
// TODO: think about crazy case: spreadOperator + native
|
// TODO: think about crazy case: spreadOperator + native
|
||||||
val functionRef = JsNameRef(functionName, dispatchReceiver!!)
|
val functionRef = JsNameRef(functionName, dispatchReceiver!!)
|
||||||
return JsInvocation(functionRef, addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments))
|
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(extensionReceiver!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -200,7 +197,7 @@ object InvokeIntrinsic : FunctionCallCase {
|
|||||||
* extLambda.call(obj, some, args)
|
* extLambda.call(obj, some, args)
|
||||||
*/
|
*/
|
||||||
override fun FunctionCallInfo.bothReceivers(): JsExpression {
|
override fun FunctionCallInfo.bothReceivers(): JsExpression {
|
||||||
return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), addReceiverToArgs(extensionReceiver!!, argumentsInfo.translateArguments))
|
return JsInvocation(Namer.getFunctionCallRef(dispatchReceiver!!), argumentsInfo.argsWithReceiver(extensionReceiver!!))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -227,7 +224,7 @@ object SuperCallCase : FunctionCallCase {
|
|||||||
// TODO: spread operator
|
// TODO: spread operator
|
||||||
val prototypeClass = JsNameRef(Namer.getPrototypeName(), dispatchReceiver!!)
|
val prototypeClass = JsNameRef(Namer.getPrototypeName(), dispatchReceiver!!)
|
||||||
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
val functionRef = Namer.getFunctionCallRef(JsNameRef(functionName, prototypeClass))
|
||||||
return JsInvocation(functionRef, addReceiverToArgs(JsLiteral.THIS, argumentsInfo.translateArguments))
|
return JsInvocation(functionRef, argumentsInfo.argsWithReceiver(JsLiteral.THIS))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-4
@@ -45,10 +45,14 @@ public class CallArgumentTranslator private (
|
|||||||
) : AbstractTranslator(context) {
|
) : AbstractTranslator(context) {
|
||||||
|
|
||||||
public data class ArgumentsInfo(
|
public data class ArgumentsInfo(
|
||||||
public val translateArguments: List<JsExpression>,
|
public val valueArguments: List<JsExpression>,
|
||||||
public val hasSpreadOperator: Boolean,
|
public val hasSpreadOperator: Boolean,
|
||||||
public val cachedReceiver: TemporaryConstVariable?
|
public val cachedReceiver: TemporaryConstVariable?,
|
||||||
)
|
public val reifiedArguments: List<JsExpression> = listOf()
|
||||||
|
) {
|
||||||
|
public val translateArguments: List<JsExpression>
|
||||||
|
get() = reifiedArguments + valueArguments
|
||||||
|
}
|
||||||
|
|
||||||
private enum class ArgumentsKind {
|
private enum class ArgumentsKind {
|
||||||
HAS_EMPTY_EXPRESSION_ARGUMENT
|
HAS_EMPTY_EXPRESSION_ARGUMENT
|
||||||
@@ -349,5 +353,5 @@ private fun Map<TypeParameterDescriptor, JetType>.addReifiedTypeArgsTo(
|
|||||||
reifiedTypeArguments.add(isCheckCallable)
|
reifiedTypeArguments.add(isCheckCallable)
|
||||||
}
|
}
|
||||||
|
|
||||||
return info.copy(translateArguments = reifiedTypeArguments + info.translateArguments)
|
return info.copy(reifiedArguments = reifiedTypeArguments)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,17 @@
|
|||||||
|
package foo
|
||||||
|
|
||||||
|
// CHECK_NOT_CALLED: canBeCastedTo
|
||||||
|
|
||||||
|
open class A
|
||||||
|
class B
|
||||||
|
class C : A()
|
||||||
|
|
||||||
|
inline fun Any.canBeCastedTo<reified T>(): Boolean = this is T
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
assertEquals(true, A().canBeCastedTo<A>(), "A().canBeCastedTo<A>()")
|
||||||
|
assertEquals(false, A().canBeCastedTo<B>(), "A().canBeCastedTo<B>()")
|
||||||
|
assertEquals(true, C().canBeCastedTo<A>(), "C().canBeCastedTo<A>()")
|
||||||
|
|
||||||
|
return "OK"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user