Storing info about expressions which should be generated as SAM values.
This commit is contained in:
@@ -53,7 +53,6 @@ import org.jetbrains.jet.lang.resolve.calls.util.ExpressionAsFunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.*;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
@@ -1888,24 +1887,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return invokeFunction(call, receiver, resolvedCall);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private FunctionDescriptor getOriginalIfSamAdapter(@NotNull CallableDescriptor fun) {
|
||||
if (!(fun instanceof FunctionDescriptor)) {
|
||||
return null;
|
||||
private void samAwareGen(@NotNull JetExpression expression, @NotNull Type defaultType) {
|
||||
ClassDescriptorFromJvmBytecode samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression);
|
||||
if (samInterface != null) {
|
||||
genSamInterfaceValue(expression, samInterface);
|
||||
}
|
||||
FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal();
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
||||
return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
|
||||
else {
|
||||
gen(expression, defaultType);
|
||||
}
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
|
||||
FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(overridden);
|
||||
if (originalIfSamAdapter != null) {
|
||||
return originalIfSamAdapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private StackValue invokeSamConstructor(
|
||||
@@ -2064,7 +2053,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd));
|
||||
}
|
||||
else {
|
||||
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) getOriginalIfSamAdapter(fd);
|
||||
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil
|
||||
.getOriginalIfSamAdapter(bindingContext, fd);
|
||||
return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall,
|
||||
isCallInsideSameClassAsDeclared(fd, context),
|
||||
isCallInsideSameModuleAsDeclared(fd, context),
|
||||
@@ -2298,31 +2288,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
int mask = 0;
|
||||
|
||||
FunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd);
|
||||
|
||||
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
|
||||
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
||||
Type parameterType = valueParameterTypes.get(valueParameter.getIndex());
|
||||
if (resolvedValueArgument instanceof ExpressionValueArgument) {
|
||||
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
|
||||
assert valueArgument != null;
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||
|
||||
if (originalOfSamAdapter != null) {
|
||||
JetType samAdapterType = originalOfSamAdapter.getValueParameters().get(valueParameter.getIndex()).getType();
|
||||
if (SingleAbstractMethodUtils.isSamType(samAdapterType)) {
|
||||
ClassDescriptorFromJvmBytecode samInterface = (ClassDescriptorFromJvmBytecode) samAdapterType.getConstructor().getDeclarationDescriptor();
|
||||
assert samInterface != null;
|
||||
|
||||
genSamInterfaceValue(argumentExpression, samInterface);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
gen(argumentExpression, valueParameterTypes.get(valueParameter.getIndex()));
|
||||
samAwareGen(argumentExpression, parameterType);
|
||||
}
|
||||
else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
||||
Type type = valueParameterTypes.get(valueParameter.getIndex());
|
||||
pushDefaultValueOnStack(type, v);
|
||||
pushDefaultValueOnStack(parameterType, v);
|
||||
mask |= (1 << valueParameter.getIndex());
|
||||
}
|
||||
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
||||
@@ -3274,7 +3252,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
//See StackValue.receiver for more info
|
||||
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists());
|
||||
|
||||
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) getOriginalIfSamAdapter(constructorDescriptor);
|
||||
ConstructorDescriptor originalOfSamAdapter = (ConstructorDescriptor) SamCodegenUtil
|
||||
.getOriginalIfSamAdapter(bindingContext, constructorDescriptor);
|
||||
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
|
||||
invokeMethodWithArguments(method, resolvedCall, null, StackValue.none());
|
||||
|
||||
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 2010-2013 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.jet.codegen;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.FunctionDescriptor;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaBindingContext;
|
||||
|
||||
public class SamCodegenUtil {
|
||||
@Nullable
|
||||
public static FunctionDescriptor getOriginalIfSamAdapter(@NotNull BindingContext bindingContext, @NotNull CallableDescriptor fun) {
|
||||
if (!(fun instanceof FunctionDescriptor)) {
|
||||
return null;
|
||||
}
|
||||
FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal();
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
||||
return bindingContext.get(JavaBindingContext.SAM_ADAPTER_FUNCTION_TO_ORIGINAL, original);
|
||||
}
|
||||
if (original.getKind() == CallableMemberDescriptor.Kind.FAKE_OVERRIDE) {
|
||||
for (FunctionDescriptor overridden : original.getOverriddenDescriptors()) {
|
||||
FunctionDescriptor originalIfSamAdapter = getOriginalIfSamAdapter(bindingContext, overridden);
|
||||
if (originalIfSamAdapter != null) {
|
||||
return originalIfSamAdapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private SamCodegenUtil() {
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen.binding;
|
||||
import com.intellij.util.containers.Stack;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.SamCodegenUtil;
|
||||
import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
|
||||
@@ -26,10 +27,14 @@ import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ExpressionValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.model.ResolvedValueArgument;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.java.sam.SingleAbstractMethodUtils;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -37,6 +42,7 @@ import org.jetbrains.jet.lang.types.JetType;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack;
|
||||
@@ -339,4 +345,50 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitCallExpression(JetCallExpression expression) {
|
||||
super.visitCallExpression(expression);
|
||||
ResolvedCall<? extends CallableDescriptor> call = bindingContext.get(BindingContext.RESOLVED_CALL, expression.getCalleeExpression());
|
||||
if (call == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
CallableDescriptor descriptor = call.getResultingDescriptor();
|
||||
if (!(descriptor instanceof FunctionDescriptor)) {
|
||||
return;
|
||||
}
|
||||
FunctionDescriptor original = SamCodegenUtil.getOriginalIfSamAdapter(bindingContext, descriptor);
|
||||
|
||||
if (original == null) {
|
||||
return;
|
||||
}
|
||||
List<ResolvedValueArgument> valueArguments = call.getValueArgumentsByIndex();
|
||||
for (ValueParameterDescriptor valueParameter : original.getValueParameters()) {
|
||||
ClassDescriptorFromJvmBytecode samInterface = getInterfaceIfSamType(valueParameter.getType());
|
||||
if (samInterface == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
||||
assert resolvedValueArgument instanceof ExpressionValueArgument : resolvedValueArgument;
|
||||
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
|
||||
assert valueArgument != null;
|
||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||
|
||||
bindingTrace.record(CodegenBinding.SAM_VALUE, argumentExpression, samInterface);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static ClassDescriptorFromJvmBytecode getInterfaceIfSamType(@NotNull JetType originalType) {
|
||||
if (!SingleAbstractMethodUtils.isSamType(originalType)) {
|
||||
return null;
|
||||
}
|
||||
ClassDescriptorFromJvmBytecode samInterface =
|
||||
(ClassDescriptorFromJvmBytecode) originalType.getConstructor().getDeclarationDescriptor();
|
||||
assert samInterface != null;
|
||||
return samInterface;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,6 +28,7 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
||||
import org.jetbrains.jet.lang.resolve.name.FqName;
|
||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||
@@ -57,6 +58,8 @@ public class CodegenBinding {
|
||||
|
||||
public static final WritableSlice<ClassDescriptor, Collection<ClassDescriptor>> INNER_CLASSES = Slices.createSimpleSlice();
|
||||
|
||||
public static final WritableSlice<JetExpression, ClassDescriptorFromJvmBytecode> SAM_VALUE = Slices.createSimpleSlice();
|
||||
|
||||
private CodegenBinding() {
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user