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.calls.callUtil.getResolvedCallWithAssert
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
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.Type
|
||||||
import org.jetbrains.org.objectweb.asm.commons.Method
|
import org.jetbrains.org.objectweb.asm.commons.Method
|
||||||
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
import org.jetbrains.org.objectweb.asm.tree.FieldInsnNode
|
||||||
@@ -90,10 +92,7 @@ class DefaultLambda(
|
|||||||
override lateinit var invokeMethod: Method
|
override lateinit var invokeMethod: Method
|
||||||
private set
|
private set
|
||||||
|
|
||||||
|
override lateinit var invokeMethodDescriptor: FunctionDescriptor
|
||||||
override val invokeMethodDescriptor: FunctionDescriptor =
|
|
||||||
parameterDescriptor.type.memberScope.getContributedFunctions(OperatorNameConventions.INVOKE, NoLookupLocation.FROM_BACKEND).single()
|
|
||||||
|
|
||||||
|
|
||||||
override lateinit var capturedVars: List<CapturedParamDesc>
|
override lateinit var capturedVars: List<CapturedParamDesc>
|
||||||
private set
|
private set
|
||||||
@@ -102,6 +101,25 @@ class DefaultLambda(
|
|||||||
|
|
||||||
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
override fun generateLambdaBody(codegen: ExpressionCodegen, reifiedTypeInliner: ReifiedTypeInliner) {
|
||||||
val classReader = InlineCodegenUtil.buildClassReaderByInternalName(codegen.state, lambdaClassType.internalName)
|
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 descriptor = Type.getMethodDescriptor(Type.VOID_TYPE, *capturedArgs)
|
||||||
val constructor = InlineCodegenUtil.getMethodNode(
|
val constructor = InlineCodegenUtil.getMethodNode(
|
||||||
@@ -121,7 +139,7 @@ class DefaultLambda(
|
|||||||
|
|
||||||
|
|
||||||
invokeMethod = Method(
|
invokeMethod = Method(
|
||||||
OperatorNameConventions.INVOKE.asString(),
|
(if (isPropertyReference) OperatorNameConventions.GET else OperatorNameConventions.INVOKE).asString(),
|
||||||
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
codegen.state.typeMapper.mapSignatureSkipGeneric(invokeMethodDescriptor).asmMethod.descriptor
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -252,4 +270,4 @@ class ExpressionLambda(
|
|||||||
SMAPAndMethodNode(methodNode, smap)
|
SMAPAndMethodNode(methodNode, smap)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -25,7 +25,7 @@ object SMAPParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
val mapping =
|
val mapping =
|
||||||
if (source == null || source.isEmpty())
|
if (source == null || source.isEmpty() || methodStartLine > methodEndLine)
|
||||||
FileMapping.SKIP
|
FileMapping.SKIP
|
||||||
else
|
else
|
||||||
FileMapping(source, path).apply {
|
FileMapping(source, path).apply {
|
||||||
|
|||||||
Vendored
-2
@@ -3,8 +3,6 @@
|
|||||||
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
// SKIP_INLINE_CHECK_IN: inlineFun$default
|
||||||
package test
|
package test
|
||||||
|
|
||||||
fun ok() = "OK"
|
|
||||||
|
|
||||||
class A(val value: String) {
|
class A(val value: String) {
|
||||||
fun ok() = value
|
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);
|
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")
|
@TestMetadata("instanceCapuredInClass.kt")
|
||||||
public void testInstanceCapuredInClass() throws Exception {
|
public void testInstanceCapuredInClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
||||||
@@ -1009,6 +1015,24 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
||||||
|
|||||||
+24
@@ -979,6 +979,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("instanceCapuredInClass.kt")
|
||||||
public void testInstanceCapuredInClass() throws Exception {
|
public void testInstanceCapuredInClass() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/instanceCapuredInClass.kt");
|
||||||
@@ -1009,6 +1015,24 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
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")
|
@TestMetadata("simple.kt")
|
||||||
public void testSimple() throws Exception {
|
public void testSimple() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/defaultValues/lambdaInlining/simple.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user