Support for property reference inlining
This commit is contained in:
+1
-4
@@ -187,10 +187,7 @@ public class FunctionReferenceGenerationStrategy extends FunctionGenerationStrat
|
|||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
ClassDescriptor classDescriptor = (ClassDescriptor) codegen.getContext().getParentContext().getContextDescriptor();
|
||||||
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
Type asmType = codegen.getState().getTypeMapper().mapClass(classDescriptor);
|
||||||
return StackValue.field(
|
return CallableReferenceUtilKt.capturedReceiver(asmType, receiverType);
|
||||||
receiverType, asmType, AsmUtil.CAPTURED_RECEIVER_FIELD,
|
|
||||||
/* isStatic = */ false, StackValue.LOCAL_0
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
// 0 is this (the callable reference class), 1 is the invoke() method's first parameter
|
||||||
|
|||||||
@@ -236,8 +236,7 @@ class PropertyReferenceCodegen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (receiverType != null) {
|
if (receiverType != null) {
|
||||||
StackValue.field(receiverType, asmType, AsmUtil.CAPTURED_RECEIVER_FIELD, /* isStatic = */ false, StackValue.LOCAL_0)
|
capturedReceiver(asmType, receiverType).put(receiverType, v)
|
||||||
.put(receiverType, v)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
|
val receivers = originalFunctionDesc.valueParameters.dropLast(if (isGetter) 0 else 1)
|
||||||
|
|||||||
@@ -0,0 +1,23 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen
|
||||||
|
|
||||||
|
import org.jetbrains.org.objectweb.asm.Type
|
||||||
|
|
||||||
|
fun capturedReceiver(ownerType: Type, capturedReceiverType: Type): StackValue.Field {
|
||||||
|
return StackValue.field(capturedReceiverType, ownerType, AsmUtil.CAPTURED_RECEIVER_FIELD, /* isStatic = */ false, StackValue.LOCAL_0)
|
||||||
|
}
|
||||||
@@ -305,8 +305,8 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline) {
|
public MethodContext intoInlinedLambda(FunctionDescriptor descriptor, boolean isCrossInline, boolean isPropertyReference) {
|
||||||
return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline);
|
return new InlineLambdaContext(descriptor, getContextKind(), this, null, isCrossInline, isPropertyReference);
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.codegen.context
|
|||||||
|
|
||||||
import org.jetbrains.kotlin.codegen.OwnerKind
|
import org.jetbrains.kotlin.codegen.OwnerKind
|
||||||
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
import org.jetbrains.kotlin.codegen.binding.MutableClosure
|
||||||
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
|
||||||
class InlineLambdaContext(
|
class InlineLambdaContext(
|
||||||
@@ -26,14 +25,18 @@ class InlineLambdaContext(
|
|||||||
contextKind: OwnerKind,
|
contextKind: OwnerKind,
|
||||||
parentContext: CodegenContext<*>,
|
parentContext: CodegenContext<*>,
|
||||||
closure: MutableClosure?,
|
closure: MutableClosure?,
|
||||||
val isCrossInline: Boolean
|
val isCrossInline: Boolean,
|
||||||
|
val isPropertyReference: Boolean
|
||||||
) : MethodContext(functionDescriptor, contextKind, parentContext, closure) {
|
) : MethodContext(functionDescriptor, contextKind, parentContext, closure) {
|
||||||
|
|
||||||
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
|
override fun getFirstCrossInlineOrNonInlineContext(): CodegenContext<*> {
|
||||||
if (isCrossInline) return this
|
if (isCrossInline) return this
|
||||||
|
|
||||||
val parent = parentContext as? ClosureContext ?:
|
val parent = if (isPropertyReference) parentContext as? AnonymousClassContext else { parentContext as? ClosureContext } ?:
|
||||||
throw AssertionError("Parent of inlining lambda body should be ClosureContext, but: $parentContext")
|
throw AssertionError(
|
||||||
|
"Parent of inlining lambda body should be " +
|
||||||
|
"${if (isPropertyReference) "ClosureContext" else "AnonymousClassContext"}, but: $parentContext"
|
||||||
|
)
|
||||||
|
|
||||||
val grandParent = parent.parentContext ?:
|
val grandParent = parent.parentContext ?:
|
||||||
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
|
throw AssertionError("Parent context of lambda class context should exist: $contextDescriptor")
|
||||||
|
|||||||
@@ -372,7 +372,8 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
|
smap = createSMAPWithDefaultMapping(inliningFunction, parentCodegen.getOrCreateSourceMapper().getResultMappings());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction, jvmSignature, false, codegen);
|
smap = generateMethodBody(maxCalcAdapter, callableDescriptor, methodContext, inliningFunction, jvmSignature, codegen,
|
||||||
|
null);
|
||||||
}
|
}
|
||||||
maxCalcAdapter.visitMaxs(-1, -1);
|
maxCalcAdapter.visitMaxs(-1, -1);
|
||||||
maxCalcAdapter.visitEnd();
|
maxCalcAdapter.visitEnd();
|
||||||
@@ -504,8 +505,10 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
KtExpression declaration = info.getFunctionWithBodyOrCallableReference();
|
KtExpression declaration = info.getFunctionWithBodyOrCallableReference();
|
||||||
FunctionDescriptor descriptor = info.getFunctionDescriptor();
|
FunctionDescriptor descriptor = info.getFunctionDescriptor();
|
||||||
|
|
||||||
MethodContext context =
|
ClassContext closureContext = info.isPropertyReference()
|
||||||
codegen.getContext().intoClosure(descriptor, codegen, typeMapper).intoInlinedLambda(descriptor, info.isCrossInline);
|
? codegen.getContext().intoAnonymousClass(info.getClassDescriptor(), codegen, OwnerKind.IMPLEMENTATION)
|
||||||
|
: codegen.getContext().intoClosure(descriptor, codegen, typeMapper);
|
||||||
|
MethodContext context = closureContext.intoInlinedLambda(descriptor, info.isCrossInline, info.isPropertyReference());
|
||||||
|
|
||||||
JvmMethodSignature jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(descriptor);
|
JvmMethodSignature jvmMethodSignature = typeMapper.mapSignatureSkipGeneric(descriptor);
|
||||||
Method asmMethod = jvmMethodSignature.getAsmMethod();
|
Method asmMethod = jvmMethodSignature.getAsmMethod();
|
||||||
@@ -516,7 +519,7 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
|
|
||||||
MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);
|
MethodVisitor adapter = InlineCodegenUtil.wrapWithMaxLocalCalc(methodNode);
|
||||||
|
|
||||||
SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, true, codegen);
|
SMAP smap = generateMethodBody(adapter, descriptor, context, declaration, jvmMethodSignature, codegen, info);
|
||||||
adapter.visitMaxs(-1, -1);
|
adapter.visitMaxs(-1, -1);
|
||||||
return new SMAPAndMethodNode(methodNode, smap);
|
return new SMAPAndMethodNode(methodNode, smap);
|
||||||
}
|
}
|
||||||
@@ -528,9 +531,10 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
@NotNull MethodContext context,
|
@NotNull MethodContext context,
|
||||||
@NotNull KtExpression expression,
|
@NotNull KtExpression expression,
|
||||||
@NotNull JvmMethodSignature jvmMethodSignature,
|
@NotNull JvmMethodSignature jvmMethodSignature,
|
||||||
boolean isLambda,
|
@NotNull ExpressionCodegen codegen,
|
||||||
@NotNull ExpressionCodegen codegen
|
@Nullable LambdaInfo lambdaInfo
|
||||||
) {
|
) {
|
||||||
|
boolean isLambda = lambdaInfo != null;
|
||||||
GenerationState state = codegen.getState();
|
GenerationState state = codegen.getState();
|
||||||
|
|
||||||
// Wrapping for preventing marking actual parent codegen as containing reified markers
|
// Wrapping for preventing marking actual parent codegen as containing reified markers
|
||||||
@@ -544,18 +548,28 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
if (expression instanceof KtCallableReferenceExpression) {
|
if (expression instanceof KtCallableReferenceExpression) {
|
||||||
KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
|
KtCallableReferenceExpression callableReferenceExpression = (KtCallableReferenceExpression) expression;
|
||||||
KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
|
KtExpression receiverExpression = callableReferenceExpression.getReceiverExpression();
|
||||||
Type receiverValue =
|
Type receiverType =
|
||||||
receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
|
receiverExpression != null && codegen.getBindingContext().getType(receiverExpression) != null
|
||||||
? codegen.getState().getTypeMapper().mapType(codegen.getBindingContext().getType(receiverExpression))
|
? codegen.getState().getTypeMapper().mapType(codegen.getBindingContext().getType(receiverExpression))
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
strategy = new FunctionReferenceGenerationStrategy(
|
if (isLambda && lambdaInfo.isPropertyReference()) {
|
||||||
state,
|
Type asmType = state.getTypeMapper().mapClass(lambdaInfo.getClassDescriptor());
|
||||||
descriptor,
|
PropertyReferenceInfo info = lambdaInfo.getPropertyReferenceInfo();
|
||||||
CallUtilKt.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
strategy = new PropertyReferenceCodegen.PropertyReferenceGenerationStrategy(
|
||||||
receiverValue,
|
true, info.getGetFunction(), info.getTarget(), asmType, receiverType, lambdaInfo.expression, state
|
||||||
null
|
);
|
||||||
);
|
}
|
||||||
|
else {
|
||||||
|
strategy = new FunctionReferenceGenerationStrategy(
|
||||||
|
state,
|
||||||
|
descriptor,
|
||||||
|
CallUtilKt
|
||||||
|
.getResolvedCallWithAssert(callableReferenceExpression.getCallableReference(), codegen.getBindingContext()),
|
||||||
|
receiverType,
|
||||||
|
null
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
strategy = new FunctionGenerationStrategy.FunctionDefault(state, (KtDeclarationWithBody) expression);
|
strategy = new FunctionGenerationStrategy.FunctionDefault(state, (KtDeclarationWithBody) expression);
|
||||||
@@ -746,16 +760,10 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*lambda or callable reference*/
|
/*lambda or callable reference*/
|
||||||
private boolean isInliningParameter(@NotNull KtExpression expression, @NotNull ValueParameterDescriptor valueParameterDescriptor) {
|
private static boolean isInliningParameter(@NotNull KtExpression expression, @NotNull ValueParameterDescriptor valueParameterDescriptor) {
|
||||||
//TODO deparenthisise typed
|
//TODO deparenthisise typed
|
||||||
KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression);
|
KtExpression deparenthesized = KtPsiUtil.deparenthesize(expression);
|
||||||
|
|
||||||
if (deparenthesized instanceof KtCallableReferenceExpression) {
|
|
||||||
// TODO: support inline of property references passed to inlinable function parameters
|
|
||||||
SimpleFunctionDescriptor functionReference = state.getBindingContext().get(BindingContext.FUNCTION, deparenthesized);
|
|
||||||
if (functionReference == null) return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
return InlineUtil.isInlineLambdaParameter(valueParameterDescriptor) &&
|
||||||
isInlinableParameterExpression(deparenthesized);
|
isInlinableParameterExpression(deparenthesized);
|
||||||
}
|
}
|
||||||
@@ -770,12 +778,12 @@ public class InlineCodegen extends CallGenerator {
|
|||||||
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
KtExpression lambda = KtPsiUtil.deparenthesize(expression);
|
||||||
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
assert isInlinableParameterExpression(lambda) : "Couldn't find inline expression in " + expression.getText();
|
||||||
|
|
||||||
LambdaInfo info = new LambdaInfo(lambda, typeMapper, parameter.isCrossinline());
|
LambdaInfo info =
|
||||||
|
new LambdaInfo(lambda, typeMapper, parameter.isCrossinline(), getBoundCallableReferenceReceiver(expression) != null);
|
||||||
|
|
||||||
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
ParameterInfo closureInfo = invocationParamBuilder.addNextValueParameter(type, true, null, parameter.getIndex());
|
||||||
closureInfo.setLambda(info);
|
closureInfo.setLambda(info);
|
||||||
expressionMap.put(closureInfo.getIndex(), info);
|
expressionMap.put(closureInfo.getIndex(), info);
|
||||||
info.setBoundCallableReference(getBoundCallableReferenceReceiver(expression) != null);
|
|
||||||
return info;
|
return info;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -18,15 +18,19 @@ package org.jetbrains.kotlin.codegen.inline;
|
|||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.kotlin.codegen.AsmUtil;
|
import org.jetbrains.kotlin.codegen.AsmUtil;
|
||||||
|
import org.jetbrains.kotlin.codegen.PropertyReferenceCodegen;
|
||||||
import org.jetbrains.kotlin.codegen.StackValue;
|
import org.jetbrains.kotlin.codegen.StackValue;
|
||||||
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
import org.jetbrains.kotlin.codegen.binding.CalculatedClosure;
|
||||||
|
import org.jetbrains.kotlin.codegen.binding.CodegenBinding;
|
||||||
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
|
import org.jetbrains.kotlin.codegen.context.EnclosedValueDescriptor;
|
||||||
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
import org.jetbrains.kotlin.codegen.state.KotlinTypeMapper;
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor;
|
import org.jetbrains.kotlin.descriptors.*;
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor;
|
import org.jetbrains.kotlin.psi.KtCallableReferenceExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtExpression;
|
import org.jetbrains.kotlin.psi.KtExpression;
|
||||||
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
import org.jetbrains.kotlin.psi.KtLambdaExpression;
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext;
|
import org.jetbrains.kotlin.resolve.BindingContext;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.callUtil.CallUtilKt;
|
||||||
|
import org.jetbrains.kotlin.resolve.calls.model.ResolvedCall;
|
||||||
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
import org.jetbrains.kotlin.resolve.jvm.AsmTypes;
|
||||||
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;
|
||||||
@@ -51,20 +55,39 @@ public class LambdaInfo implements LabelOwner {
|
|||||||
|
|
||||||
private SMAPAndMethodNode node;
|
private SMAPAndMethodNode node;
|
||||||
private List<CapturedParamDesc> capturedVars;
|
private List<CapturedParamDesc> capturedVars;
|
||||||
private boolean isBoundCallableReference;
|
private final boolean isBoundCallableReference;
|
||||||
|
private final PropertyReferenceInfo propertyReferenceInfo;
|
||||||
|
|
||||||
public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline) {
|
public LambdaInfo(@NotNull KtExpression expression, @NotNull KotlinTypeMapper typeMapper, boolean isCrossInline, boolean isBoundCallableReference) {
|
||||||
this.isCrossInline = isCrossInline;
|
this.isCrossInline = isCrossInline;
|
||||||
this.expression = expression instanceof KtLambdaExpression ?
|
this.expression = expression instanceof KtLambdaExpression ?
|
||||||
((KtLambdaExpression) expression).getFunctionLiteral() : expression;
|
((KtLambdaExpression) expression).getFunctionLiteral() : expression;
|
||||||
|
|
||||||
this.typeMapper = typeMapper;
|
this.typeMapper = typeMapper;
|
||||||
|
this.isBoundCallableReference = isBoundCallableReference;
|
||||||
BindingContext bindingContext = typeMapper.getBindingContext();
|
BindingContext bindingContext = typeMapper.getBindingContext();
|
||||||
functionDescriptor = bindingContext.get(BindingContext.FUNCTION, this.expression);
|
FunctionDescriptor function = bindingContext.get(BindingContext.FUNCTION, this.expression);
|
||||||
assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText();
|
if (function == null && expression instanceof KtCallableReferenceExpression) {
|
||||||
|
VariableDescriptor variableDescriptor = bindingContext.get(BindingContext.VARIABLE, this.expression);
|
||||||
|
assert variableDescriptor instanceof VariableDescriptorWithAccessors :
|
||||||
|
"Reference expression not resolved to variable descriptor with accessors: " + expression.getText();
|
||||||
|
classDescriptor = CodegenBinding.anonymousClassForCallable(bindingContext, variableDescriptor);
|
||||||
|
closureClassType = typeMapper.mapClass(classDescriptor);
|
||||||
|
SimpleFunctionDescriptor getFunction = PropertyReferenceCodegen.findGetFunction(variableDescriptor);
|
||||||
|
functionDescriptor = PropertyReferenceCodegen.createFakeOpenDescriptor(getFunction, classDescriptor);
|
||||||
|
ResolvedCall<?> resolvedCall = CallUtilKt.getResolvedCallWithAssert(((KtCallableReferenceExpression) expression).getCallableReference(), bindingContext);
|
||||||
|
propertyReferenceInfo = new PropertyReferenceInfo(
|
||||||
|
(VariableDescriptor) resolvedCall.getResultingDescriptor(), getFunction
|
||||||
|
);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
propertyReferenceInfo = null;
|
||||||
|
functionDescriptor = function;
|
||||||
|
assert functionDescriptor != null : "Function is not resolved to descriptor: " + expression.getText();
|
||||||
|
classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor);
|
||||||
|
closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
||||||
|
}
|
||||||
|
|
||||||
classDescriptor = anonymousClassForCallable(bindingContext, functionDescriptor);
|
|
||||||
closureClassType = asmTypeForAnonymousClass(bindingContext, functionDescriptor);
|
|
||||||
|
|
||||||
closure = bindingContext.get(CLOSURE, classDescriptor);
|
closure = bindingContext.get(CLOSURE, classDescriptor);
|
||||||
assert closure != null : "Closure for lambda should be not null " + expression.getText();
|
assert closure != null : "Closure for lambda should be not null " + expression.getText();
|
||||||
@@ -171,7 +194,11 @@ public class LambdaInfo implements LabelOwner {
|
|||||||
return isBoundCallableReference;
|
return isBoundCallableReference;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setBoundCallableReference(boolean boundCallableReference) {
|
public boolean isPropertyReference() {
|
||||||
isBoundCallableReference = boundCallableReference;
|
return propertyReferenceInfo != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PropertyReferenceInfo getPropertyReferenceInfo() {
|
||||||
|
return propertyReferenceInfo;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,24 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2016 JetBrains s.r.o.
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.codegen.inline
|
||||||
|
|
||||||
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
|
import org.jetbrains.kotlin.descriptors.VariableDescriptor
|
||||||
|
|
||||||
|
class PropertyReferenceInfo(
|
||||||
|
val target: VariableDescriptor,
|
||||||
|
val getFunction: FunctionDescriptor)
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
class Foo(val a: String)
|
||||||
|
|
||||||
|
inline fun test(s: () -> String): String {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(Foo("OK")::a)
|
||||||
|
}
|
||||||
+19
@@ -0,0 +1,19 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
object Foo {
|
||||||
|
val a: String = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun test(s: () -> String): String {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(Foo::a)
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
object Foo {
|
||||||
|
val a: String = "OK"
|
||||||
|
}
|
||||||
|
|
||||||
|
inline fun test(s: () -> String): String {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.Foo.a
|
||||||
|
import test.test
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(::a)
|
||||||
|
}
|
||||||
+20
@@ -0,0 +1,20 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
class Foo(val z: String)
|
||||||
|
|
||||||
|
val Foo.a: String
|
||||||
|
get() = z
|
||||||
|
|
||||||
|
inline fun test(s: () -> String): String {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(Foo("OK")::a)
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
package test
|
package test
|
||||||
|
|
||||||
inline fun call(a: String, b: String, s: String.(String) -> String): Int {
|
inline fun call(a: String, b: String, s: String.(String) -> String): String {
|
||||||
return a.s(b)
|
return a.s(b)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -11,5 +11,5 @@ inline fun call(a: String, b: String, s: String.(String) -> String): Int {
|
|||||||
import test.*
|
import test.*
|
||||||
|
|
||||||
fun box() : String {
|
fun box() : String {
|
||||||
return return call("O", "K", String::plus)
|
return call("O", "K", String::plus)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
inline fun call(p: String, s: String.() -> Int): Int {
|
||||||
|
return p.s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box() : String {
|
||||||
|
return if (call("123", String::length) == 3) "OK" else "fail"
|
||||||
|
}
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
class Foo(val a: String)
|
||||||
|
|
||||||
|
inline fun <T> test(receiver: T, selector: (T) -> String): String {
|
||||||
|
return selector(receiver)
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(Foo("OK"), Foo::a)
|
||||||
|
}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
// FILE: 1.kt
|
||||||
|
|
||||||
|
package test
|
||||||
|
|
||||||
|
val a: String
|
||||||
|
get() = "OK"
|
||||||
|
|
||||||
|
inline fun test(s: () -> String): String {
|
||||||
|
return s()
|
||||||
|
}
|
||||||
|
|
||||||
|
// FILE: 2.kt
|
||||||
|
|
||||||
|
import test.*
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return test(::a)
|
||||||
|
}
|
||||||
@@ -565,6 +565,18 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyIntrinsic.kt")
|
||||||
|
public void testPropertyIntrinsic() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("topLevel.kt")
|
@TestMetadata("topLevel.kt")
|
||||||
public void testTopLevel() throws Exception {
|
public void testTopLevel() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevel.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevel.kt");
|
||||||
@@ -577,6 +589,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelProperty.kt")
|
||||||
|
public void testTopLevelProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -585,6 +603,12 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classProperty.kt")
|
||||||
|
public void testClassProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/classProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("expression.kt")
|
@TestMetadata("expression.kt")
|
||||||
public void testExpression() throws Exception {
|
public void testExpression() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
||||||
@@ -615,11 +639,29 @@ public class BlackBoxInlineCodegenTestGenerated extends AbstractBlackBoxInlineCo
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectProperty.kt")
|
||||||
|
public void testObjectProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/objectProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyImportedFromObject.kt")
|
||||||
|
public void testPropertyImportedFromObject() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/propertyImportedFromObject.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/callableReference/bound/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/simple.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelExtensionProperty.kt")
|
||||||
|
public void testTopLevelExtensionProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/topLevelExtensionProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+42
@@ -565,6 +565,18 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyIntrinsic.kt")
|
||||||
|
public void testPropertyIntrinsic() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyIntrinsic.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyReference.kt")
|
||||||
|
public void testPropertyReference() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/propertyReference.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("topLevel.kt")
|
@TestMetadata("topLevel.kt")
|
||||||
public void testTopLevel() throws Exception {
|
public void testTopLevel() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevel.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevel.kt");
|
||||||
@@ -577,6 +589,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelProperty.kt")
|
||||||
|
public void testTopLevelProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/topLevelProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
@TestMetadata("compiler/testData/codegen/boxInline/callableReference/bound")
|
||||||
@TestDataPath("$PROJECT_ROOT")
|
@TestDataPath("$PROJECT_ROOT")
|
||||||
@RunWith(JUnit3RunnerWithInners.class)
|
@RunWith(JUnit3RunnerWithInners.class)
|
||||||
@@ -585,6 +603,12 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxInline/callableReference/bound"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("classProperty.kt")
|
||||||
|
public void testClassProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/classProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("expression.kt")
|
@TestMetadata("expression.kt")
|
||||||
public void testExpression() throws Exception {
|
public void testExpression() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/expression.kt");
|
||||||
@@ -615,11 +639,29 @@ public class CompileKotlinAgainstInlineKotlinTestGenerated extends AbstractCompi
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("objectProperty.kt")
|
||||||
|
public void testObjectProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/objectProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("propertyImportedFromObject.kt")
|
||||||
|
public void testPropertyImportedFromObject() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/propertyImportedFromObject.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/callableReference/bound/simple.kt");
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/simple.kt");
|
||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("topLevelExtensionProperty.kt")
|
||||||
|
public void testTopLevelExtensionProperty() throws Exception {
|
||||||
|
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/codegen/boxInline/callableReference/bound/topLevelExtensionProperty.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user