Support default property reference inlining
This commit is contained in:
@@ -33,6 +33,8 @@ import org.jetbrains.kotlin.resolve.BindingContext
|
||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCallWithAssert
|
||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
||||
import org.jetbrains.org.objectweb.asm.ClassReader
|
||||
import org.jetbrains.org.objectweb.asm.ClassVisitor
|
||||
import org.jetbrains.org.objectweb.asm.Type
|
||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||
@@ -90,10 +92,7 @@ class DefaultLambda(
|
||||
override lateinit var invokeMethod: Method
|
||||
private set
|
||||
|
||||
|
||||
override val invokeMethodDescriptor: FunctionDescriptor =
|
||||
parameterDescriptor.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single()
|
||||
|
||||
override lateinit var invokeMethodDescriptor: FunctionDescriptor
|
||||
|
||||
override lateinit var capturedVars: List<CapturedParamDesc>
|
||||
private set
|
||||
@@ -102,6 +101,25 @@ class DefaultLambda(
|
||||
|
||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
||||
var isPropertyReference = false
|
||||
var isFunctionReference = false
|
||||
classReader.accept(object: ClassVisitor(InlineCodegenUtil.API){
|
||||
override fun visit(version: Int, access: Int, name: String, signature: String?, superName: String?, interfaces: Array<out String>?) {
|
||||
isPropertyReference = superName?.startsWith("kotlin/jvm/internal/PropertyReference") ?: false
|
||||
isFunctionReference = "kotlin/jvm/internal/FunctionReference" == superName
|
||||
|
||||
super.visit(version, access, name, signature, superName, interfaces)
|
||||
}
|
||||
}, ClassReader.SKIP_CODE or ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG)
|
||||
|
||||
invokeMethodDescriptor =
|
||||
parameterDescriptor.type.memberScope
|
||||
.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND)
|
||||
.single()
|
||||
.let {
|
||||
//property reference generates erased 'get' method
|
||||
if (isPropertyReference) it.original else it
|
||||
}
|
||||
|
||||
val descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||
val constructor = InlineCodegenUtil.getMethodNode(
|
||||
@@ -121,7 +139,7 @@ class DefaultLambda(
|
||||
|
||||
|
||||
invokeMethod = Method(
|
||||
OperatorNameConventions.INVOKE.asString(),
|
||||
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
|
||||
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||
)
|
||||
|
||||
@@ -252,4 +270,4 @@ class ExpressionLambda(
|
||||
SMAPAndMethodNode(methodNode, smap)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,7 @@ object SMAPParser {
|
||||
}
|
||||
|
||||
val mapping =
|
||||
if (source == null || source.isEmpty())
|
||||
if (source == null || source.isEmpty() || methodStartLine > methodEndLine)
|
||||
FileMapping.SKIP
|
||||
else
|
||||
FileMapping(source, path).apply {
|
||||
|
||||
Vendored
-2
@@ -3,8 +3,6 @@
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
fun ok() = "OK"
|
||||
|
||||
class A(val value: String) {
|
||||
fun ok() = value
|
||||
}
|
||||
|
||||
Vendored
+22
@@ -0,0 +1,22 @@
|
||||
// FILE: 1.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
fun ok() = "OK"
|
||||
|
||||
object A {
|
||||
fun ok() = "OK"
|
||||
}
|
||||
|
||||
inline fun inlineFun(lambda: () -> String = A::ok): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun()
|
||||
}
|
||||
+18
@@ -0,0 +1,18 @@
|
||||
// FILE: 1.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
val ok = "OK"
|
||||
|
||||
inline fun inlineFun(lambda: () -> String = ::ok): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun()
|
||||
}
|
||||
Vendored
+18
@@ -0,0 +1,18 @@
|
||||
// FILE: 1.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
class A(val ok: String)
|
||||
|
||||
inline fun inlineFun(a: A, lambda: (A) -> String = A::ok): String {
|
||||
return lambda(a)
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun(A("OK"))
|
||||
}
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// FILE: 1.kt
|
||||
// LANGUAGE_VERSION: 1.2
|
||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||
package test
|
||||
|
||||
object A {
|
||||
val ok = "OK"
|
||||
}
|
||||
|
||||
inline fun inlineFun(lambda: () -> String = A::ok): String {
|
||||
return lambda()
|
||||
}
|
||||
|
||||
// FILE: 2.kt
|
||||
|
||||
import test.*
|
||||
|
||||
fun box(): String {
|
||||
return inlineFun()
|
||||
}
|
||||
@@ -979,6 +979,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceFromObject.kt")
|
||||
public void testFunctionReferenceFromObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("instanceCapuredInClass.kt")
|
||||
public void testInstanceCapuredInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
||||
@@ -1009,6 +1015,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReference.kt")
|
||||
public void testPropertyReference() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReferenceFromClass.kt")
|
||||
public void testPropertyReferenceFromClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReferenceFromObject.kt")
|
||||
public void testPropertyReferenceFromObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
||||
|
||||
+24
@@ -979,6 +979,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("functionReferenceFromObject.kt")
|
||||
public void testFunctionReferenceFromObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/functionReferenceFromObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("instanceCapuredInClass.kt")
|
||||
public void testInstanceCapuredInClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
||||
@@ -1009,6 +1015,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReference.kt")
|
||||
public void testPropertyReference() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReference.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReferenceFromClass.kt")
|
||||
public void testPropertyReferenceFromClass() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromClass.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("propertyReferenceFromObject.kt")
|
||||
public void testPropertyReferenceFromObject() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/propertyReferenceFromObject.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("simple.kt")
|
||||
public void testSimple() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
||||
|
||||
Reference in New Issue
Block a user