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.constants.CompileTimeConstant;
|
||||||
import org.jetbrains.jet.lang.resolve.java.*;
|
import org.jetbrains.jet.lang.resolve.java.*;
|
||||||
import org.jetbrains.jet.lang.resolve.java.descriptor.ClassDescriptorFromJvmBytecode;
|
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.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.*;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -1888,24 +1887,14 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return invokeFunction(call, receiver, resolvedCall);
|
return invokeFunction(call, receiver, resolvedCall);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
private void samAwareGen(@NotNull JetExpression expression, @NotNull Type defaultType) {
|
||||||
private FunctionDescriptor getOriginalIfSamAdapter(@NotNull CallableDescriptor fun) {
|
ClassDescriptorFromJvmBytecode samInterface = bindingContext.get(CodegenBinding.SAM_VALUE, expression);
|
||||||
if (!(fun instanceof FunctionDescriptor)) {
|
if (samInterface != null) {
|
||||||
return null;
|
genSamInterfaceValue(expression, samInterface);
|
||||||
}
|
}
|
||||||
FunctionDescriptor original = ((FunctionDescriptor) fun).getOriginal();
|
else {
|
||||||
if (original.getKind() == CallableMemberDescriptor.Kind.SYNTHESIZED) {
|
gen(expression, defaultType);
|
||||||
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(overridden);
|
|
||||||
if (originalIfSamAdapter != null) {
|
|
||||||
return originalIfSamAdapter;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private StackValue invokeSamConstructor(
|
private StackValue invokeSamConstructor(
|
||||||
@@ -2064,7 +2053,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd));
|
return typeMapper.mapToFunctionInvokeCallableMethod(createInvoke(fd));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) getOriginalIfSamAdapter(fd);
|
SimpleFunctionDescriptor originalOfSamAdapter = (SimpleFunctionDescriptor) SamCodegenUtil
|
||||||
|
.getOriginalIfSamAdapter(bindingContext, fd);
|
||||||
return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall,
|
return typeMapper.mapToCallableMethod(originalOfSamAdapter != null ? originalOfSamAdapter : fd, superCall,
|
||||||
isCallInsideSameClassAsDeclared(fd, context),
|
isCallInsideSameClassAsDeclared(fd, context),
|
||||||
isCallInsideSameModuleAsDeclared(fd, context),
|
isCallInsideSameModuleAsDeclared(fd, context),
|
||||||
@@ -2298,31 +2288,19 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
|
|
||||||
int mask = 0;
|
int mask = 0;
|
||||||
|
|
||||||
FunctionDescriptor originalOfSamAdapter = getOriginalIfSamAdapter(fd);
|
|
||||||
|
|
||||||
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
|
for (ValueParameterDescriptor valueParameter : fd.getValueParameters()) {
|
||||||
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
ResolvedValueArgument resolvedValueArgument = valueArguments.get(valueParameter.getIndex());
|
||||||
|
Type parameterType = valueParameterTypes.get(valueParameter.getIndex());
|
||||||
if (resolvedValueArgument instanceof ExpressionValueArgument) {
|
if (resolvedValueArgument instanceof ExpressionValueArgument) {
|
||||||
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
|
ValueArgument valueArgument = ((ExpressionValueArgument) resolvedValueArgument).getValueArgument();
|
||||||
assert valueArgument != null;
|
assert valueArgument != null;
|
||||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||||
assert argumentExpression != null : valueArgument.asElement().getText();
|
assert argumentExpression != null : valueArgument.asElement().getText();
|
||||||
|
|
||||||
if (originalOfSamAdapter != null) {
|
samAwareGen(argumentExpression, parameterType);
|
||||||
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()));
|
|
||||||
}
|
}
|
||||||
else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
else if (resolvedValueArgument instanceof DefaultValueArgument) {
|
||||||
Type type = valueParameterTypes.get(valueParameter.getIndex());
|
pushDefaultValueOnStack(parameterType, v);
|
||||||
pushDefaultValueOnStack(type, v);
|
|
||||||
mask |= (1 << valueParameter.getIndex());
|
mask |= (1 << valueParameter.getIndex());
|
||||||
}
|
}
|
||||||
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
else if (resolvedValueArgument instanceof VarargValueArgument) {
|
||||||
@@ -3274,7 +3252,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
|||||||
//See StackValue.receiver for more info
|
//See StackValue.receiver for more info
|
||||||
pushClosureOnStack(closure, resolvedCall.getThisObject().exists() || resolvedCall.getReceiverArgument().exists());
|
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);
|
CallableMethod method = typeMapper.mapToCallableMethod(originalOfSamAdapter == null ? constructorDescriptor : originalOfSamAdapter);
|
||||||
invokeMethodWithArguments(method, resolvedCall, null, StackValue.none());
|
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 com.intellij.util.containers.Stack;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
import org.jetbrains.jet.codegen.SamCodegenUtil;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
|
||||||
import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorImpl;
|
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.BindingContext;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
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.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.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
||||||
import org.jetbrains.jet.lang.resolve.java.PackageClassUtils;
|
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.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
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.Collections;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack;
|
import static org.jetbrains.jet.codegen.CodegenUtil.peekFromStack;
|
||||||
@@ -339,4 +345,50 @@ class CodegenAnnotatingVisitor extends JetVisitorVoid {
|
|||||||
return null;
|
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.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
import org.jetbrains.jet.lang.resolve.java.JvmAbi;
|
||||||
import org.jetbrains.jet.lang.resolve.java.JvmClassName;
|
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.FqName;
|
||||||
import org.jetbrains.jet.lang.resolve.name.Name;
|
import org.jetbrains.jet.lang.resolve.name.Name;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
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<ClassDescriptor, Collection<ClassDescriptor>> INNER_CLASSES = Slices.createSimpleSlice();
|
||||||
|
|
||||||
|
public static final WritableSlice<JetExpression, ClassDescriptorFromJvmBytecode> SAM_VALUE = Slices.createSimpleSlice();
|
||||||
|
|
||||||
private CodegenBinding() {
|
private CodegenBinding() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user