Implicit receivers checked properly. Receiver checks restructured.
This commit is contained in:
@@ -73,7 +73,7 @@ public class ClassContext {
|
|||||||
thisIdx++;
|
thisIdx++;
|
||||||
}
|
}
|
||||||
|
|
||||||
final boolean hasReceiver = descriptor.getReceiver().exists();
|
final boolean hasReceiver = descriptor.getReceiverParameter().exists();
|
||||||
if (hasReceiver) {
|
if (hasReceiver) {
|
||||||
thisIdx++;
|
thisIdx++;
|
||||||
}
|
}
|
||||||
@@ -104,7 +104,7 @@ public class ClassContext {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private ReceiverDescriptor receiver() {
|
private ReceiverDescriptor receiver() {
|
||||||
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiver() : ReceiverDescriptor.NO_RECEIVER;
|
return contextType instanceof FunctionDescriptor ? ((FunctionDescriptor) contextType).getReceiverParameter() : ReceiverDescriptor.NO_RECEIVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasReceiver() {
|
private boolean hasReceiver() {
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ public class ClosureCodegen {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
public static Method erasedInvokeSignature(FunctionDescriptor fd) {
|
||||||
boolean isExtensionFunction = fd.getReceiver().exists();
|
boolean isExtensionFunction = fd.getReceiverParameter().exists();
|
||||||
int paramCount = fd.getValueParameters().size();
|
int paramCount = fd.getValueParameters().size();
|
||||||
if (isExtensionFunction) {
|
if (isExtensionFunction) {
|
||||||
paramCount++;
|
paramCount++;
|
||||||
@@ -151,7 +151,7 @@ public class ClosureCodegen {
|
|||||||
|
|
||||||
iv.load(0, Type.getObjectType(className));
|
iv.load(0, Type.getObjectType(className));
|
||||||
|
|
||||||
final ReceiverDescriptor receiver = funDescriptor.getReceiver();
|
final ReceiverDescriptor receiver = funDescriptor.getReceiverParameter();
|
||||||
int count = 1;
|
int count = 1;
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
StackValue.local(count, JetTypeMapper.TYPE_OBJECT).put(JetTypeMapper.TYPE_OBJECT, iv);
|
||||||
@@ -229,7 +229,7 @@ public class ClosureCodegen {
|
|||||||
|
|
||||||
public static String getInternalClassName(FunctionDescriptor descriptor) {
|
public static String getInternalClassName(FunctionDescriptor descriptor) {
|
||||||
final int paramCount = descriptor.getValueParameters().size();
|
final int paramCount = descriptor.getValueParameters().size();
|
||||||
if (descriptor.getReceiver().exists()) {
|
if (descriptor.getReceiverParameter().exists()) {
|
||||||
return "jet/ExtensionFunction" + paramCount;
|
return "jet/ExtensionFunction" + paramCount;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -250,7 +250,7 @@ public class ClosureCodegen {
|
|||||||
Method descriptor = erasedInvokeSignature(fd);
|
Method descriptor = erasedInvokeSignature(fd);
|
||||||
String owner = getInternalClassName(fd);
|
String owner = getInternalClassName(fd);
|
||||||
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
final CallableMethod result = new CallableMethod(owner, descriptor, Opcodes.INVOKEVIRTUAL, Arrays.asList(descriptor.getArgumentTypes()));
|
||||||
if (fd.getReceiver().exists()) {
|
if (fd.getReceiverParameter().exists()) {
|
||||||
result.setNeedsReceiver(null);
|
result.setNeedsReceiver(null);
|
||||||
}
|
}
|
||||||
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
|
result.requestGenerateCallee(Type.getObjectType(getInternalClassName(fd)));
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package org.jetbrains.jet.codegen;
|
|||||||
|
|
||||||
import com.intellij.psi.*;
|
import com.intellij.psi.*;
|
||||||
import com.intellij.psi.util.PsiTreeUtil;
|
import com.intellij.psi.util.PsiTreeUtil;
|
||||||
import jet.Function1;
|
|
||||||
import jet.JetObject;
|
import jet.JetObject;
|
||||||
import jet.typeinfo.TypeInfo;
|
import jet.typeinfo.TypeInfo;
|
||||||
import jet.typeinfo.TypeInfoProjection;
|
import jet.typeinfo.TypeInfoProjection;
|
||||||
@@ -546,7 +545,7 @@ public class JetTypeMapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public Method mapSignature(String name, FunctionDescriptor f) {
|
public Method mapSignature(String name, FunctionDescriptor f) {
|
||||||
final ReceiverDescriptor receiver = f.getReceiver();
|
final ReceiverDescriptor receiver = f.getReceiverParameter();
|
||||||
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
final List<ValueParameterDescriptor> parameters = f.getValueParameters();
|
||||||
List<Type> parameterTypes = new ArrayList<Type>();
|
List<Type> parameterTypes = new ArrayList<Type>();
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.jetbrains.jet.lang.descriptors;
|
package org.jetbrains.jet.lang.descriptors;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ImplicitReceiverDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
import org.jetbrains.jet.lang.types.TypeSubstitutor;
|
||||||
@@ -14,7 +13,7 @@ import java.util.Set;
|
|||||||
*/
|
*/
|
||||||
public interface CallableDescriptor extends DeclarationDescriptor {
|
public interface CallableDescriptor extends DeclarationDescriptor {
|
||||||
@NotNull
|
@NotNull
|
||||||
ReceiverDescriptor getReceiver();
|
ReceiverDescriptor getReceiverParameter();
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
List<TypeParameterDescriptor> getTypeParameters();
|
List<TypeParameterDescriptor> getTypeParameters();
|
||||||
|
|||||||
+3
-3
@@ -71,7 +71,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ReceiverDescriptor getReceiver() {
|
public ReceiverDescriptor getReceiverParameter() {
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -133,7 +133,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
|||||||
|
|
||||||
JetType substitutedReceiverType = null;
|
JetType substitutedReceiverType = null;
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
substitutedReceiverType = substitutor.substitute(getReceiver().getType(), Variance.IN_VARIANCE);
|
substitutedReceiverType = substitutor.substitute(getReceiverParameter().getType(), Variance.IN_VARIANCE);
|
||||||
if (substitutedReceiverType == null) {
|
if (substitutedReceiverType == null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -181,7 +181,7 @@ public class FunctionDescriptorImpl extends DeclarationDescriptorImpl implements
|
|||||||
public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
|
public FunctionDescriptor copy(DeclarationDescriptor newOwner, boolean makeNonAbstract) {
|
||||||
FunctionDescriptorImpl copy = new FunctionDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), getName());
|
FunctionDescriptorImpl copy = new FunctionDescriptorImpl(newOwner, Lists.newArrayList(getAnnotations()), getName());
|
||||||
copy.initialize(
|
copy.initialize(
|
||||||
getReceiver().exists() ? getReceiver().getType() : null,
|
getReceiverParameter().exists() ? getReceiverParameter().getType() : null,
|
||||||
DescriptorUtils.copyTypeParameters(copy, typeParameters),
|
DescriptorUtils.copyTypeParameters(copy, typeParameters),
|
||||||
DescriptorUtils.copyValueParameters(copy, unsubstitutedValueParameters),
|
DescriptorUtils.copyValueParameters(copy, unsubstitutedValueParameters),
|
||||||
unsubstitutedReturnType,
|
unsubstitutedReturnType,
|
||||||
|
|||||||
+1
-1
@@ -95,7 +95,7 @@ public class FunctionDescriptorUtil {
|
|||||||
@NotNull
|
@NotNull
|
||||||
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
|
public static JetScope getFunctionInnerScope(@NotNull JetScope outerScope, @NotNull FunctionDescriptor descriptor, @NotNull BindingTrace trace) {
|
||||||
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope");
|
WritableScope parameterScope = new WritableScopeImpl(outerScope, descriptor, new TraceBasedRedeclarationHandler(trace)).setDebugName("Function inner scope");
|
||||||
ReceiverDescriptor receiver = descriptor.getReceiver();
|
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
parameterScope.setImplicitReceiver(receiver);
|
parameterScope.setImplicitReceiver(receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public class PropertyDescriptor extends VariableDescriptorImpl implements Callab
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ReceiverDescriptor getReceiver() {
|
public ReceiverDescriptor getReceiverParameter() {
|
||||||
return receiver;
|
return receiver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-2
@@ -35,8 +35,8 @@ public class PropertyGetterDescriptor extends PropertyAccessorDescriptor {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ReceiverDescriptor getReceiver() {
|
public ReceiverDescriptor getReceiverParameter() {
|
||||||
return getCorrespondingProperty().getReceiver();
|
return getCorrespondingProperty().getReceiverParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+2
-2
@@ -44,8 +44,8 @@ public class PropertySetterDescriptor extends PropertyAccessorDescriptor {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ReceiverDescriptor getReceiver() {
|
public ReceiverDescriptor getReceiverParameter() {
|
||||||
return getCorrespondingProperty().getReceiver();
|
return getCorrespondingProperty().getReceiverParameter();
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+1
-1
@@ -74,7 +74,7 @@ public abstract class VariableDescriptorImpl extends DeclarationDescriptorImpl i
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@Override
|
@Override
|
||||||
public ReceiverDescriptor getReceiver() {
|
public ReceiverDescriptor getReceiverParameter() {
|
||||||
return ReceiverDescriptor.NO_RECEIVER;
|
return ReceiverDescriptor.NO_RECEIVER;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -459,7 +459,7 @@ public class BodyResolver {
|
|||||||
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
|
for (TypeParameterDescriptor typeParameterDescriptor : propertyDescriptor.getTypeParameters()) {
|
||||||
result.addTypeParameterDescriptor(typeParameterDescriptor);
|
result.addTypeParameterDescriptor(typeParameterDescriptor);
|
||||||
}
|
}
|
||||||
ReceiverDescriptor receiver = propertyDescriptor.getReceiver();
|
ReceiverDescriptor receiver = propertyDescriptor.getReceiverParameter();
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
result.setImplicitReceiver(receiver);
|
result.setImplicitReceiver(receiver);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,11 +4,14 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
@@ -22,7 +25,7 @@ public class DescriptorUtils {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
|
public Boolean visitFunctionDescriptor(FunctionDescriptor descriptor, Void data) {
|
||||||
return descriptor.getReceiver().exists();
|
return descriptor.getReceiverParameter().exists();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -32,7 +35,7 @@ public class DescriptorUtils {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
|
public Boolean visitPropertyDescriptor(PropertyDescriptor descriptor, Void data) {
|
||||||
return descriptor.getReceiver().exists();
|
return descriptor.getReceiverParameter().exists();
|
||||||
}
|
}
|
||||||
}, null);
|
}, null);
|
||||||
}
|
}
|
||||||
@@ -111,4 +114,19 @@ public class DescriptorUtils {
|
|||||||
if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
|
if (makeNonAbstract && modality == Modality.ABSTRACT) return Modality.OPEN;
|
||||||
return modality;
|
return modality;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public static ReceiverDescriptor getExpectedThisObject(@NotNull DeclarationDescriptor descriptor) {
|
||||||
|
if (descriptor instanceof ConstructorDescriptor) {
|
||||||
|
ConstructorDescriptor constructorDescriptor = (ConstructorDescriptor) descriptor;
|
||||||
|
ClassDescriptor classDescriptor = constructorDescriptor.getContainingDeclaration();
|
||||||
|
return getExpectedThisObject(classDescriptor);
|
||||||
|
}
|
||||||
|
DeclarationDescriptor containingDeclaration = descriptor.getContainingDeclaration();
|
||||||
|
if (containingDeclaration instanceof ClassDescriptor) {
|
||||||
|
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
||||||
|
return classDescriptor.getImplicitReceiver();
|
||||||
|
}
|
||||||
|
return NO_RECEIVER;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
|||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.*;
|
import org.jetbrains.jet.lang.types.*;
|
||||||
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
import org.jetbrains.jet.lang.types.inference.ConstraintSystem;
|
||||||
|
import org.jetbrains.jet.lexer.JetTokens;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
@@ -22,6 +23,7 @@ import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
|||||||
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
import static org.jetbrains.jet.lang.resolve.BindingContext.*;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_CANDIDATE;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_CANDIDATE;
|
||||||
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_RESULT;
|
import static org.jetbrains.jet.lang.resolve.calls.ResolvedCall.MAP_TO_RESULT;
|
||||||
|
import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor.NO_RECEIVER;
|
||||||
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
import static org.jetbrains.jet.lang.types.JetTypeInferrer.NO_EXPECTED_TYPE;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -142,7 +144,7 @@ public class CallResolver {
|
|||||||
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
trace.report(NO_CONSTRUCTOR.on(reportAbsenceOn));
|
||||||
return checkArgumentTypesAndFail(trace, scope, call);
|
return checkArgumentTypesAndFail(trace, scope, call);
|
||||||
}
|
}
|
||||||
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(ResolvedCall.convertCollection(constructors), call, DataFlowInfo.getEmpty()));
|
prioritizedTasks.add(new ResolutionTask<FunctionDescriptor>(TaskPrioritizer.convertWithImpliedThis(scope, Collections.<ReceiverDescriptor>singletonList(NO_RECEIVER), constructors), call, DataFlowInfo.getEmpty()));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
|
// trace.getErrorHandler().genericError(calleeExpression.getNode(), "Not a class");
|
||||||
@@ -173,7 +175,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private FunctionDescriptor checkArgumentTypesAndFail(BindingTrace trace, JetScope scope, Call call) {
|
private FunctionDescriptor checkArgumentTypesAndFail(BindingTrace trace, JetScope scope, Call call) {
|
||||||
checkTypesWithNoCallee(trace, scope, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
|
checkTypesWithNoCallee(trace, scope, call);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -235,6 +237,17 @@ public class CallResolver {
|
|||||||
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
|
trace.report(MISSING_RECEIVER.on(reference, expectedReceiver.getType()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {
|
||||||
|
if (receiverArgument instanceof ExpressionReceiver) {
|
||||||
|
ExpressionReceiver expressionReceiver = (ExpressionReceiver) receiverArgument;
|
||||||
|
trace.report(TYPE_MISMATCH.on(expressionReceiver.getExpression(), receiverParameter.getType(), receiverArgument.getType()));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(TYPE_MISMATCH.on(reference, receiverParameter.getType(), receiverArgument.getType()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
public void noReceiverAllowed(@NotNull BindingTrace trace) {
|
||||||
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
trace.report(NO_RECEIVER_ADMITTED.on(reference));
|
||||||
@@ -273,6 +286,23 @@ public class CallResolver {
|
|||||||
trace.report(TYPE_INFERENCE_FAILED.on(callNode));
|
trace.report(TYPE_INFERENCE_FAILED.on(callNode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
||||||
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
|
if (callOperationNode != null) {
|
||||||
|
trace.report(UNSAFE_CALL.on(callOperationNode, type));
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
trace.report(UNSAFE_CALL.on(reference, type));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {
|
||||||
|
ASTNode callOperationNode = call.getCallOperationNode();
|
||||||
|
assert callOperationNode != null;
|
||||||
|
trace.report(UNNECESSARY_SAFE_CALL.on(reference, callOperationNode, type));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
for (ResolutionTask<D> task : prioritizedTasks) {
|
for (ResolutionTask<D> task : prioritizedTasks) {
|
||||||
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
TemporaryBindingTrace temporaryTrace = TemporaryBindingTrace.create(trace);
|
||||||
@@ -294,7 +324,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
trace.report(UNRESOLVED_REFERENCE.on(reference));
|
trace.report(UNRESOLVED_REFERENCE.on(reference));
|
||||||
checkTypesWithNoCallee(trace, scope, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments());
|
checkTypesWithNoCallee(trace, scope, call);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -315,21 +345,19 @@ public class CallResolver {
|
|||||||
|
|
||||||
if (ErrorUtils.isError(candidate)) {
|
if (ErrorUtils.isError(candidate)) {
|
||||||
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
||||||
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
boolean errorInArgumentMapping = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall);
|
||||||
// Map<ValueArgument, ValueParameterDescriptor> argumentsToParameters = Maps.newHashMap();
|
if (errorInArgumentMapping) {
|
||||||
boolean error = ValueArgumentsToParametersMapper.mapValueArgumentsToParameters(task, tracing, candidateCall);
|
|
||||||
|
|
||||||
if (error) {
|
|
||||||
failedCandidates.add(candidateCall);
|
failedCandidates.add(candidateCall);
|
||||||
checkTypesWithNoCallee(temporaryTrace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
checkTypesWithNoCallee(temporaryTrace, scope, task.getCall());
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (task.getTypeArguments().isEmpty()) {
|
List<JetTypeProjection> jetTypeArguments = task.getCall().getTypeArguments();
|
||||||
|
if (jetTypeArguments.isEmpty()) {
|
||||||
if (!candidate.getTypeParameters().isEmpty()) {
|
if (!candidate.getTypeParameters().isEmpty()) {
|
||||||
// Type argument inference
|
// Type argument inference
|
||||||
|
|
||||||
@@ -356,10 +384,11 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkReceiverAbsence(candidateCall, tracing, candidate);
|
// checkReceiverAbsence(candidateCall, tracing, candidate);
|
||||||
|
|
||||||
// Error is already reported if something is missing
|
// Error is already reported if something is missing
|
||||||
ReceiverDescriptor receiverParameter = candidateCall.getReceiverParameter();
|
ReceiverDescriptor receiverParameter = candidateCall.getReceiverArgument();
|
||||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter();
|
||||||
if (receiverParameter.exists() && candidateReceiver.exists()) {
|
if (receiverParameter.exists() && candidateReceiver.exists()) {
|
||||||
constraintSystem.addSubtypingConstraint(receiverParameter.getType(), candidateReceiver.getType());
|
constraintSystem.addSubtypingConstraint(receiverParameter.getType(), candidateReceiver.getType());
|
||||||
}
|
}
|
||||||
@@ -382,8 +411,7 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if (checkValueArgumentTypes(scope, candidateCall)
|
if (checkAllValueArguments(scope, tracing, task, candidateCall, candidate)) {
|
||||||
&& checkReceiver(candidateCall, tracing, candidate)) {
|
|
||||||
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
successfulCandidates.add(candidateCall.setResultingDescriptor(candidate));
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -394,8 +422,6 @@ public class CallResolver {
|
|||||||
else {
|
else {
|
||||||
// Explicit type arguments passed
|
// Explicit type arguments passed
|
||||||
|
|
||||||
final List<JetTypeProjection> jetTypeArguments = task.getTypeArguments();
|
|
||||||
|
|
||||||
for (JetTypeProjection typeArgument : jetTypeArguments) {
|
for (JetTypeProjection typeArgument : jetTypeArguments) {
|
||||||
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
|
if (typeArgument.getProjectionKind() != JetProjectionKind.NONE) {
|
||||||
// temporaryTrace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
|
// temporaryTrace.getErrorHandler().genericError(typeArgument.getNode(), "Projections are not allowed on type parameters for methods"); // TODO : better positioning
|
||||||
@@ -415,14 +441,14 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace);
|
checkGenericBoundsInAFunctionCall(jetTypeArguments, typeArguments, candidate, temporaryTrace);
|
||||||
|
|
||||||
Map<TypeConstructor, TypeProjection> substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
|
Map<TypeConstructor, TypeProjection> substitutionContext = FunctionDescriptorUtil.createSubstitutionContext((FunctionDescriptor) candidate, typeArguments);
|
||||||
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
|
D substitutedDescriptor = (D) candidate.substitute(TypeSubstitutor.create(substitutionContext));
|
||||||
|
|
||||||
|
candidateCall.setResultingDescriptor(substitutedDescriptor);
|
||||||
replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
|
replaceValueParametersWithSubstitutedOnes(candidateCall, substitutedDescriptor);
|
||||||
if (checkValueArgumentTypes(scope, candidateCall)
|
if (checkAllValueArguments(scope, tracing, task, candidateCall, substitutedDescriptor)) {
|
||||||
&& checkReceiver(candidateCall, tracing, substitutedDescriptor)) {
|
successfulCandidates.add(candidateCall);
|
||||||
successfulCandidates.add(candidateCall.setResultingDescriptor(substitutedDescriptor));
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
failedCandidates.add(candidateCall);
|
failedCandidates.add(candidateCall);
|
||||||
@@ -437,13 +463,13 @@ public class CallResolver {
|
|||||||
|
|
||||||
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
|
task.performAdvancedChecks(candidate, temporaryTrace, tracing);
|
||||||
|
|
||||||
recordAutoCastIfNecessary(candidateCall.getReceiverParameter(), candidateCall.getTrace());
|
recordAutoCastIfNecessary(candidateCall.getReceiverArgument(), candidateCall.getTrace());
|
||||||
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
recordAutoCastIfNecessary(candidateCall.getThisObject(), candidateCall.getTrace());
|
||||||
}
|
}
|
||||||
|
|
||||||
OverloadResolutionResults<D> results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates);
|
OverloadResolutionResults<D> results = computeResultAndReportErrors(trace, tracing, successfulCandidates, failedCandidates);
|
||||||
if (!results.singleDescriptor()) {
|
if (!results.singleDescriptor()) {
|
||||||
checkTypesWithNoCallee(trace, scope, task.getTypeArguments(), task.getValueArguments(), task.getFunctionLiteralArguments());
|
checkTypesWithNoCallee(trace, scope, task.getCall());
|
||||||
}
|
}
|
||||||
return results;
|
return results;
|
||||||
}
|
}
|
||||||
@@ -467,19 +493,19 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, List<JetTypeProjection> typeArguments, List<? extends ValueArgument> valueArguments, List<JetExpression> functionLiteralArguments) {
|
private void checkTypesWithNoCallee(BindingTrace trace, JetScope scope, Call call) {
|
||||||
for (ValueArgument valueArgument : valueArguments) {
|
for (ValueArgument valueArgument : call.getValueArguments()) {
|
||||||
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
||||||
if (argumentExpression != null) {
|
if (argumentExpression != null) {
|
||||||
typeInferrer.getServices(trace).getType(scope, argumentExpression, NO_EXPECTED_TYPE);
|
typeInferrer.getServices(trace).getType(scope, argumentExpression, NO_EXPECTED_TYPE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetExpression expression : functionLiteralArguments) {
|
for (JetExpression expression : call.getFunctionLiteralArguments()) {
|
||||||
typeInferrer.getServices(trace).getType(scope, expression, NO_EXPECTED_TYPE);
|
typeInferrer.getServices(trace).getType(scope, expression, NO_EXPECTED_TYPE);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (JetTypeProjection typeProjection : typeArguments) {
|
for (JetTypeProjection typeProjection : call.getTypeArguments()) {
|
||||||
new TypeResolver(semanticServices, trace, true).resolveType(scope, typeProjection.getTypeReference());
|
new TypeResolver(semanticServices, trace, true).resolveType(scope, typeProjection.getTypeReference());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -515,9 +541,33 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> boolean checkValueArgumentTypes(
|
private <D extends CallableDescriptor> boolean checkAllValueArguments(JetScope scope, TracingStrategy tracing, ResolutionTask<D> task, ResolvedCall<D> candidateCall, D substitutedDescriptor) {
|
||||||
JetScope scope,
|
boolean result = checkValueArgumentTypes(scope, candidateCall);
|
||||||
ResolvedCall<D> candidateCall) {
|
// result &= checkReceiver(task, candidateCall, tracing, substitutedDescriptor);
|
||||||
|
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
||||||
|
ReceiverDescriptor receiverParameter = candidateCall.getResultingDescriptor().getReceiverParameter();
|
||||||
|
boolean safeAccess = task.getCall().getCallOperationNode() == JetTokens.SAFE_ACCESS;
|
||||||
|
if (receiverParameter.exists() && receiverArgument.exists()) {
|
||||||
|
JetType receiverArgumentType = receiverArgument.getType();
|
||||||
|
if (!safeAccess && !receiverParameter.getType().isNullable() && receiverArgumentType.isNullable()) {
|
||||||
|
tracing.unsafeCall(candidateCall.getTrace(), receiverArgumentType);
|
||||||
|
result = false;
|
||||||
|
}
|
||||||
|
else if (!semanticServices.getTypeChecker().isSubtypeOf(receiverArgument.getType(), receiverParameter.getType())) {
|
||||||
|
tracing.wrongReceiverType(candidateCall.getTrace(), receiverParameter, receiverArgument);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (safeAccess && (receiverParameter.getType().isNullable() || !receiverArgumentType.isNullable())) {
|
||||||
|
tracing.unnecessarySafeCall(candidateCall.getTrace(), receiverArgumentType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private <D extends CallableDescriptor> boolean checkValueArgumentTypes(JetScope scope, ResolvedCall<D> candidateCall) {
|
||||||
boolean result = true;
|
boolean result = true;
|
||||||
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
|
for (Map.Entry<ValueParameterDescriptor, ResolvedValueArgument> entry : candidateCall.getValueArguments().entrySet()) {
|
||||||
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
ValueParameterDescriptor parameterDescriptor = entry.getKey();
|
||||||
@@ -557,59 +607,40 @@ public class CallResolver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// for (Map.Entry<ValueArgument, ValueParameterDescriptor> entry : argumentsToParameters.entrySet()) {
|
|
||||||
// ValueArgument valueArgument = entry.getKey();
|
|
||||||
// ValueParameterDescriptor valueParameterDescriptor = entry.getValue();
|
|
||||||
//
|
|
||||||
// ValueParameterDescriptor substitutedParameter = parameterMap.apply(valueParameterDescriptor);
|
|
||||||
//
|
|
||||||
// assert substitutedParameter != null;
|
|
||||||
//
|
|
||||||
// JetType parameterType = substitutedParameter.getOutType();
|
|
||||||
// JetExpression argumentExpression = valueArgument.getArgumentExpression();
|
|
||||||
// if (argumentExpression != null) {
|
|
||||||
// JetTypeInferrer.Services temporaryServices = typeInferrer.getServices(temporaryTrace);
|
|
||||||
// JetType type = temporaryServices.getType(scope, argumentExpression, parameterType);
|
|
||||||
// if (type == null) {
|
|
||||||
// dirty.set(true);
|
|
||||||
// }
|
|
||||||
// else if (!semanticServices.getTypeChecker().isSubtypeOf(type, parameterType)) {
|
|
||||||
// result = false;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private <D extends CallableDescriptor> boolean checkReceiver(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
|
// private <D extends CallableDescriptor> boolean checkReceiver(ResolutionTask<D> task, ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
|
||||||
if (!checkReceiverAbsence(resolvedCall, tracing, candidate)) return false;
|
// if (!checkReceiverAbsence(resolvedCall, tracing, candidate)) return false;
|
||||||
ReceiverDescriptor receiver = resolvedCall.getReceiverParameter();
|
// ReceiverDescriptor actualReceiver = resolvedCall.getReceiverArgument();
|
||||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
// ReceiverDescriptor expectedReceiver = candidate.getReceiverParameter();
|
||||||
if (receiver.exists()
|
//
|
||||||
&& candidateReceiver.exists()
|
// if (actualReceiver.exists()
|
||||||
&& !semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), candidateReceiver.getType())) {
|
// && expectedReceiver.exists()) {
|
||||||
tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
|
// if (!semanticServices.getTypeChecker().isSubtypeOf(actualReceiver.getType(), expectedReceiver.getType())) {
|
||||||
return false;
|
// tracing.missingReceiver(resolvedCall.getTrace(), expectedReceiver);
|
||||||
}
|
// return false;
|
||||||
return true;
|
// }
|
||||||
}
|
// }
|
||||||
|
// return true;
|
||||||
private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
|
// }
|
||||||
ReceiverDescriptor receiver = resolvedCall.getReceiverParameter();
|
//
|
||||||
ReceiverDescriptor candidateReceiver = candidate.getReceiver();
|
// private <D extends CallableDescriptor> boolean checkReceiverAbsence(ResolvedCall<D> resolvedCall, TracingStrategy tracing, D candidate) {
|
||||||
if (receiver.exists()) {
|
// ReceiverDescriptor receiver = resolvedCall.getReceiverArgument();
|
||||||
if (!candidateReceiver.exists()) {
|
// ReceiverDescriptor candidateReceiver = candidate.getReceiverParameter();
|
||||||
tracing.noReceiverAllowed(resolvedCall.getTrace());
|
// if (receiver.exists()) {
|
||||||
return false;
|
// if (!candidateReceiver.exists()) {
|
||||||
}
|
// tracing.noReceiverAllowed(resolvedCall.getTrace());
|
||||||
}
|
// return false;
|
||||||
else if (candidateReceiver.exists()) {
|
// }
|
||||||
tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
|
// }
|
||||||
return false;
|
// else if (candidateReceiver.exists()) {
|
||||||
}
|
// tracing.missingReceiver(resolvedCall.getTrace(), candidateReceiver);
|
||||||
return true;
|
// return false;
|
||||||
}
|
// }
|
||||||
|
// return true;
|
||||||
|
// }
|
||||||
|
//
|
||||||
@NotNull
|
@NotNull
|
||||||
private <D extends CallableDescriptor> OverloadResolutionResults<D> computeResultAndReportErrors(
|
private <D extends CallableDescriptor> OverloadResolutionResults<D> computeResultAndReportErrors(
|
||||||
BindingTrace trace,
|
BindingTrace trace,
|
||||||
@@ -747,7 +778,7 @@ public class CallResolver {
|
|||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
|
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
|
||||||
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
|
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
if (functionDescriptor.getReceiver().exists()) continue;
|
if (functionDescriptor.getReceiverParameter().exists()) continue;
|
||||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||||
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
|
if (!checkValueParameters(functionDescriptor, parameterTypes)) continue;
|
||||||
result.add(resolvedCall);
|
result.add(resolvedCall);
|
||||||
@@ -760,7 +791,7 @@ public class CallResolver {
|
|||||||
boolean found = false;
|
boolean found = false;
|
||||||
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
|
for (ResolvedCall<FunctionDescriptor> resolvedCall : candidates) {
|
||||||
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
|
FunctionDescriptor functionDescriptor = resolvedCall.getResultingDescriptor();
|
||||||
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiver();
|
ReceiverDescriptor functionReceiver = functionDescriptor.getReceiverParameter();
|
||||||
if (!functionReceiver.exists()) continue;
|
if (!functionReceiver.exists()) continue;
|
||||||
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
if (!functionDescriptor.getTypeParameters().isEmpty()) continue;
|
||||||
if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
|
if (!semanticServices.getTypeChecker().isSubtypeOf(receiver.getType(), functionReceiver.getType())) continue;
|
||||||
|
|||||||
+3
-3
@@ -72,9 +72,9 @@ public class OverloadingConflictResolver {
|
|||||||
if (OverridingUtil.overrides(f, g)) return true;
|
if (OverridingUtil.overrides(f, g)) return true;
|
||||||
if (OverridingUtil.overrides(g, f)) return false;
|
if (OverridingUtil.overrides(g, f)) return false;
|
||||||
|
|
||||||
ReceiverDescriptor receiverOfF = f.getReceiver();
|
ReceiverDescriptor receiverOfF = f.getReceiverParameter();
|
||||||
ReceiverDescriptor receiverOfG = g.getReceiver();
|
ReceiverDescriptor receiverOfG = g.getReceiverParameter();
|
||||||
if (f.getReceiver().exists() && g.getReceiver().exists()) {
|
if (f.getReceiverParameter().exists() && g.getReceiverParameter().exists()) {
|
||||||
if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
|
if (!typeMoreSpecific(receiverOfF.getType(), receiverOfG.getType())) return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -3,45 +3,29 @@ package org.jetbrains.jet.lang.resolve.calls;
|
|||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
import org.jetbrains.jet.lang.psi.Call;
|
||||||
import org.jetbrains.jet.lang.psi.JetExpression;
|
|
||||||
import org.jetbrains.jet.lang.psi.JetTypeProjection;
|
|
||||||
import org.jetbrains.jet.lang.psi.ValueArgument;
|
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author abreslav
|
* @author abreslav
|
||||||
*/
|
*/
|
||||||
/*package*/ class ResolutionTask<D extends CallableDescriptor> {
|
/*package*/ class ResolutionTask<D extends CallableDescriptor> {
|
||||||
|
private final Call call;
|
||||||
private final Collection<ResolvedCall<D>> candidates;
|
private final Collection<ResolvedCall<D>> candidates;
|
||||||
private final List<JetTypeProjection> typeArguments;
|
|
||||||
private final List<? extends ValueArgument> valueArguments;
|
|
||||||
private final List<JetExpression> functionLiteralArguments;
|
|
||||||
private final DataFlowInfo dataFlowInfo;
|
private final DataFlowInfo dataFlowInfo;
|
||||||
private DescriptorCheckStrategy checkingStrategy;
|
private DescriptorCheckStrategy checkingStrategy;
|
||||||
|
|
||||||
public ResolutionTask(
|
|
||||||
@NotNull Collection<ResolvedCall<D>> candidates,
|
|
||||||
@NotNull List<JetTypeProjection> typeArguments,
|
|
||||||
@NotNull List<? extends ValueArgument> valueArguments,
|
|
||||||
@NotNull List<JetExpression> functionLiteralArguments,
|
|
||||||
@NotNull DataFlowInfo dataFlowInfo) {
|
|
||||||
this.candidates = candidates;
|
|
||||||
this.typeArguments = typeArguments;
|
|
||||||
this.valueArguments = valueArguments;
|
|
||||||
this.functionLiteralArguments = functionLiteralArguments;
|
|
||||||
this.dataFlowInfo = dataFlowInfo;
|
|
||||||
}
|
|
||||||
|
|
||||||
public ResolutionTask(
|
public ResolutionTask(
|
||||||
@NotNull Collection<ResolvedCall<D>> candidates,
|
@NotNull Collection<ResolvedCall<D>> candidates,
|
||||||
@NotNull Call call,
|
@NotNull Call call,
|
||||||
@NotNull DataFlowInfo dataFlowInfo
|
@NotNull DataFlowInfo dataFlowInfo
|
||||||
) {
|
) {
|
||||||
this(candidates, call.getTypeArguments(), call.getValueArguments(), call.getFunctionLiteralArguments(), dataFlowInfo);
|
this.candidates = candidates;
|
||||||
|
this.call = call;
|
||||||
|
this.dataFlowInfo = dataFlowInfo;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -55,20 +39,10 @@ import java.util.List;
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public List<JetTypeProjection> getTypeArguments() {
|
public Call getCall() {
|
||||||
return typeArguments;
|
return call;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<? extends ValueArgument> getValueArguments() {
|
|
||||||
return valueArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
@NotNull
|
|
||||||
public List<JetExpression> getFunctionLiteralArguments() {
|
|
||||||
return functionLiteralArguments;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
public void setCheckingStrategy(DescriptorCheckStrategy strategy) {
|
||||||
checkingStrategy = strategy;
|
checkingStrategy = strategy;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,9 +4,8 @@ import com.google.common.collect.Lists;
|
|||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.intellij.util.Function;
|
import com.intellij.util.Function;
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.descriptors.TypeParameterDescriptor;
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
|
||||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
@@ -53,7 +52,7 @@ public class ResolvedCall<D extends CallableDescriptor> {
|
|||||||
private final D candidateDescriptor;
|
private final D candidateDescriptor;
|
||||||
private D resultingDescriptor; // Probably substituted
|
private D resultingDescriptor; // Probably substituted
|
||||||
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
|
private ReceiverDescriptor thisObject = NO_RECEIVER; // receiver object of a method
|
||||||
private ReceiverDescriptor receiverParameter = NO_RECEIVER; // receiver of an extension function
|
private ReceiverDescriptor receiverArgument = NO_RECEIVER; // receiver of an extension function
|
||||||
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
private final Map<TypeParameterDescriptor, JetType> typeArguments = Maps.newLinkedHashMap();
|
||||||
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
|
private final Map<ValueParameterDescriptor, JetType> autoCasts = Maps.newHashMap();
|
||||||
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
|
private final Map<ValueParameterDescriptor, ResolvedValueArgument> valueArguments = Maps.newHashMap();
|
||||||
@@ -104,12 +103,12 @@ public class ResolvedCall<D extends CallableDescriptor> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ReceiverDescriptor getReceiverParameter() {
|
public ReceiverDescriptor getReceiverArgument() {
|
||||||
return receiverParameter;
|
return receiverArgument;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setReceiverParameter(@NotNull ReceiverDescriptor receiverParameter) {
|
public void setReceiverArgument(@NotNull ReceiverDescriptor receiverParameter) {
|
||||||
this.receiverParameter = receiverParameter;
|
this.receiverArgument = receiverParameter;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
@@ -133,4 +132,9 @@ public class ResolvedCall<D extends CallableDescriptor> {
|
|||||||
public boolean isDirty() {
|
public boolean isDirty() {
|
||||||
return someArgumentHasNoType;
|
return someArgumentHasNoType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@NotNull
|
||||||
|
public ReceiverDescriptor getExpectedThisObject() {
|
||||||
|
return DescriptorUtils.getExpectedThisObject(getResultingDescriptor());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,13 @@ import org.jetbrains.annotations.NotNull;
|
|||||||
import org.jetbrains.jet.lang.descriptors.*;
|
import org.jetbrains.jet.lang.descriptors.*;
|
||||||
import org.jetbrains.jet.lang.psi.Call;
|
import org.jetbrains.jet.lang.psi.Call;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||||
|
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
import org.jetbrains.jet.lang.resolve.scopes.JetScope;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
import org.jetbrains.jet.lang.types.DataFlowInfo;
|
||||||
import org.jetbrains.jet.lang.types.JetType;
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
import org.jetbrains.jet.lang.types.JetTypeChecker;
|
||||||
|
import org.jetbrains.jet.lang.types.NamespaceType;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -65,16 +68,14 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull ReceiverDescriptor receiver, @NotNull Call call, @NotNull String name) {
|
|
||||||
// List<ResolutionTask<D>> result = Lists.newArrayList();
|
|
||||||
// doComputeTasks(scope, receiver, call, name, result);
|
|
||||||
// return result;
|
|
||||||
// }
|
|
||||||
|
|
||||||
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
|
public List<ResolutionTask<D>> computePrioritizedTasks(@NotNull JetScope scope, @NotNull Call call, @NotNull String name, @NotNull BindingContext bindingContext, @NotNull DataFlowInfo dataFlowInfo) {
|
||||||
List<ResolutionTask<D>> result = Lists.newArrayList();
|
List<ResolutionTask<D>> result = Lists.newArrayList();
|
||||||
|
|
||||||
ReceiverDescriptor explicitReceiver = call.getExplicitReceiver();
|
ReceiverDescriptor explicitReceiver = call.getExplicitReceiver();
|
||||||
|
if (explicitReceiver.exists() && explicitReceiver.getType() instanceof NamespaceType) {
|
||||||
|
scope = explicitReceiver.getType().getMemberScope();
|
||||||
|
explicitReceiver = NO_RECEIVER;
|
||||||
|
}
|
||||||
doComputeTasks(scope, explicitReceiver, call, name, result, NO_AUTO_CASTS);
|
doComputeTasks(scope, explicitReceiver, call, name, result, NO_AUTO_CASTS);
|
||||||
|
|
||||||
ReceiverDescriptor receiverToCast = explicitReceiver.exists() ? explicitReceiver : scope.getImplicitReceiver();
|
ReceiverDescriptor receiverToCast = explicitReceiver.exists() ? explicitReceiver : scope.getImplicitReceiver();
|
||||||
@@ -121,15 +122,15 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
private void doComputeTasks(JetScope scope, ReceiverDescriptor explicitReceiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
|
private void doComputeTasks(JetScope scope, ReceiverDescriptor receiver, Call call, String name, List<ResolutionTask<D>> result, @NotNull AutoCastService autoCastService) {
|
||||||
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
|
DataFlowInfo dataFlowInfo = autoCastService.getDataFlowInfo();
|
||||||
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
List<ReceiverDescriptor> implicitReceivers = Lists.newArrayList();
|
||||||
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
scope.getImplicitReceiversHierarchy(implicitReceivers);
|
||||||
// AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverToCast)
|
// AutoCastUtils.getAutoCastVariants(bindingContext, dataFlowInfo, receiverToCast)
|
||||||
if (explicitReceiver.exists()) {
|
if (receiver.exists()) {
|
||||||
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(explicitReceiver);
|
List<ReceiverDescriptor> variantsForExplicitReceiver = autoCastService.getVariantsForReceiver(receiver);
|
||||||
|
|
||||||
Collection<ResolvedCall<D>> extensionFunctions = convertWithImpliedThis(variantsForExplicitReceiver, getExtensionsByName(scope, name));
|
Collection<ResolvedCall<D>> extensionFunctions = convertWithImpliedThis(scope, variantsForExplicitReceiver, getExtensionsByName(scope, name));
|
||||||
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
|
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
|
||||||
List<ResolvedCall<D>> locals = Lists.newArrayList();
|
List<ResolvedCall<D>> locals = Lists.newArrayList();
|
||||||
//noinspection unchecked,RedundantTypeArguments
|
//noinspection unchecked,RedundantTypeArguments
|
||||||
@@ -153,7 +154,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
addTask(result, call, nonlocals, dataFlowInfo);
|
addTask(result, call, nonlocals, dataFlowInfo);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
Collection<ResolvedCall<D>> functions = convertWithImpliedThis(Collections.singletonList(explicitReceiver), getNonExtensionsByName(scope, name));
|
Collection<ResolvedCall<D>> functions = convertWithImpliedThis(scope, Collections.singletonList(receiver), getNonExtensionsByName(scope, name));
|
||||||
|
|
||||||
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
|
List<ResolvedCall<D>> nonlocals = Lists.newArrayList();
|
||||||
List<ResolvedCall<D>> locals = Lists.newArrayList();
|
List<ResolvedCall<D>> locals = Lists.newArrayList();
|
||||||
@@ -183,7 +184,7 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
for (D extension : descriptors) {
|
for (D extension : descriptors) {
|
||||||
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
|
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
|
||||||
resolvedCall.setThisObject(thisObject);
|
resolvedCall.setThisObject(thisObject);
|
||||||
resolvedCall.setReceiverParameter(receiverParameter);
|
resolvedCall.setReceiverArgument(receiverParameter);
|
||||||
result.add(resolvedCall);
|
result.add(resolvedCall);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -191,33 +192,36 @@ import static org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor
|
|||||||
// return result;
|
// return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Collection<ResolvedCall<D>> convertWithImpliedThis(Iterable<ReceiverDescriptor> receiverParameters, Collection<D> descriptors) {
|
public static <D extends CallableDescriptor> Collection<ResolvedCall<D>> convertWithImpliedThis(JetScope scope, Iterable<ReceiverDescriptor> receiverParameters, Collection<D> descriptors) {
|
||||||
Collection<ResolvedCall<D>> result = Lists.newArrayList();
|
Collection<ResolvedCall<D>> result = Lists.newArrayList();
|
||||||
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
for (ReceiverDescriptor receiverParameter : receiverParameters) {
|
||||||
for (D extension : descriptors) {
|
for (D extension : descriptors) {
|
||||||
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
|
ResolvedCall<D> resolvedCall = ResolvedCall.create(extension);
|
||||||
resolvedCall.setReceiverParameter(receiverParameter);
|
resolvedCall.setReceiverArgument(receiverParameter);
|
||||||
setImpliedThis(resolvedCall);
|
if (setImpliedThis(scope, resolvedCall)) {
|
||||||
result.add(resolvedCall);
|
result.add(resolvedCall);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setImpliedThis(ResolvedCall<D> resolvedCall) {
|
private static <D extends CallableDescriptor> boolean setImpliedThis(@NotNull JetScope scope, ResolvedCall<D> resolvedCall) {
|
||||||
ReceiverDescriptor thisObject;
|
ReceiverDescriptor expectedThisObject = DescriptorUtils.getExpectedThisObject(resolvedCall.getCandidateDescriptor());
|
||||||
DeclarationDescriptor containingDeclaration = resolvedCall.getCandidateDescriptor().getContainingDeclaration();
|
if (!expectedThisObject.exists()) return true;
|
||||||
if (containingDeclaration instanceof ClassDescriptor) {
|
List<ReceiverDescriptor> receivers = Lists.newArrayList();
|
||||||
ClassDescriptor classDescriptor = (ClassDescriptor) containingDeclaration;
|
scope.getImplicitReceiversHierarchy(receivers);
|
||||||
thisObject = classDescriptor.getImplicitReceiver();
|
for (ReceiverDescriptor receiver : receivers) {
|
||||||
|
if (JetTypeChecker.INSTANCE.isSubtypeOf(receiver.getType(), expectedThisObject.getType())) {
|
||||||
|
// TODO : Autocasts & nullability
|
||||||
|
resolvedCall.setThisObject(expectedThisObject);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else {
|
return false;
|
||||||
thisObject = NO_RECEIVER;
|
|
||||||
}
|
|
||||||
resolvedCall.setThisObject(thisObject);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCall<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
|
private void addTask(@NotNull List<ResolutionTask<D>> result, @NotNull Call call, @NotNull Collection<ResolvedCall<D>> candidates, @NotNull DataFlowInfo dataFlowInfo) {
|
||||||
if (candidates.isEmpty()) return;
|
if (candidates.isEmpty()) return;
|
||||||
result.add(new ResolutionTask<D>(candidates, call, dataFlowInfo));
|
result.add(new ResolutionTask<D>(candidates, call, dataFlowInfo));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class TaskPrioritizers {
|
|||||||
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
|
Set<FunctionDescriptor> functions = Sets.newLinkedHashSet(scope.getFunctions(name));
|
||||||
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
|
for (Iterator<FunctionDescriptor> iterator = functions.iterator(); iterator.hasNext(); ) {
|
||||||
FunctionDescriptor functionDescriptor = iterator.next();
|
FunctionDescriptor functionDescriptor = iterator.next();
|
||||||
if (functionDescriptor.getReceiver().exists()) {
|
if (functionDescriptor.getReceiverParameter().exists()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -53,7 +53,7 @@ public class TaskPrioritizers {
|
|||||||
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
|
Set<FunctionDescriptor> extensionFunctions = Sets.newHashSet(scope.getFunctions(name));
|
||||||
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
for (Iterator<FunctionDescriptor> iterator = extensionFunctions.iterator(); iterator.hasNext(); ) {
|
||||||
FunctionDescriptor descriptor = iterator.next();
|
FunctionDescriptor descriptor = iterator.next();
|
||||||
if (!descriptor.getReceiver().exists()) {
|
if (!descriptor.getReceiverParameter().exists()) {
|
||||||
iterator.remove();
|
iterator.remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -71,11 +71,11 @@ public class TaskPrioritizers {
|
|||||||
|
|
||||||
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
|
private void addVariableAsFunction(JetScope scope, String name, Set<FunctionDescriptor> functions, boolean receiverNeeded) {
|
||||||
VariableDescriptor variable = scope.getVariable(name);
|
VariableDescriptor variable = scope.getVariable(name);
|
||||||
if (variable != null && !variable.getReceiver().exists()) {
|
if (variable != null && !variable.getReceiverParameter().exists()) {
|
||||||
JetType outType = variable.getOutType();
|
JetType outType = variable.getOutType();
|
||||||
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
|
if (outType != null && JetStandardClasses.isFunctionType(outType)) {
|
||||||
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
|
VariableAsFunctionDescriptor functionDescriptor = VariableAsFunctionDescriptor.create(variable);
|
||||||
if ((functionDescriptor.getReceiver().exists()) == receiverNeeded) {
|
if ((functionDescriptor.getReceiverParameter().exists()) == receiverNeeded) {
|
||||||
functions.add(functionDescriptor);
|
functions.add(functionDescriptor);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -89,7 +89,7 @@ public class TaskPrioritizers {
|
|||||||
@Override
|
@Override
|
||||||
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
protected Collection<VariableDescriptor> getNonExtensionsByName(JetScope scope, String name) {
|
||||||
VariableDescriptor variable = scope.getVariable(name);
|
VariableDescriptor variable = scope.getVariable(name);
|
||||||
if (variable != null && !variable.getReceiver().exists()) {
|
if (variable != null && !variable.getReceiverParameter().exists()) {
|
||||||
return Collections.singleton(variable);
|
return Collections.singleton(variable);
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
@@ -109,7 +109,7 @@ public class TaskPrioritizers {
|
|||||||
@Override
|
@Override
|
||||||
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
protected Collection<VariableDescriptor> getExtensionsByName(JetScope scope, String name) {
|
||||||
VariableDescriptor variable = scope.getVariable(name);
|
VariableDescriptor variable = scope.getVariable(name);
|
||||||
if (variable != null && variable.getReceiver().exists()) {
|
if (variable != null && variable.getReceiverParameter().exists()) {
|
||||||
return Collections.singleton(variable);
|
return Collections.singleton(variable);
|
||||||
}
|
}
|
||||||
return Collections.emptyList();
|
return Collections.emptyList();
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
import org.jetbrains.jet.lang.resolve.BindingTrace;
|
||||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
|
import org.jetbrains.jet.lang.types.JetType;
|
||||||
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
@@ -26,6 +27,9 @@ import java.util.Set;
|
|||||||
@Override
|
@Override
|
||||||
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
|
public void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument) {}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
|
public void noReceiverAllowed(@NotNull BindingTrace trace) {}
|
||||||
|
|
||||||
@@ -46,6 +50,12 @@ import java.util.Set;
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void typeInferenceFailed(@NotNull BindingTrace trace) {}
|
public void typeInferenceFailed(@NotNull BindingTrace trace) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall);
|
<D extends CallableDescriptor> void bindReference(@NotNull BindingTrace trace, @NotNull ResolvedCall<D> resolvedCall);
|
||||||
@@ -56,6 +66,8 @@ import java.util.Set;
|
|||||||
|
|
||||||
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
|
void missingReceiver(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor expectedReceiver);
|
||||||
|
|
||||||
|
void wrongReceiverType(@NotNull BindingTrace trace, @NotNull ReceiverDescriptor receiverParameter, @NotNull ReceiverDescriptor receiverArgument);
|
||||||
|
|
||||||
void noReceiverAllowed(@NotNull BindingTrace trace);
|
void noReceiverAllowed(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter);
|
void noValueForParameter(@NotNull BindingTrace trace, @NotNull ValueParameterDescriptor valueParameter);
|
||||||
@@ -69,4 +81,8 @@ import java.util.Set;
|
|||||||
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
|
void instantiationOfAbstractClass(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
void typeInferenceFailed(@NotNull BindingTrace trace);
|
void typeInferenceFailed(@NotNull BindingTrace trace);
|
||||||
|
|
||||||
|
void unsafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
|
||||||
|
|
||||||
|
void unnecessarySafeCall(@NotNull BindingTrace trace, @NotNull JetType type);
|
||||||
}
|
}
|
||||||
|
|||||||
+17
-2
@@ -7,6 +7,7 @@ import org.jetbrains.jet.lang.descriptors.CallableDescriptor;
|
|||||||
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
import org.jetbrains.jet.lang.descriptors.ValueParameterDescriptor;
|
||||||
import org.jetbrains.jet.lang.psi.*;
|
import org.jetbrains.jet.lang.psi.*;
|
||||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||||
|
import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor;
|
||||||
import org.jetbrains.jet.lang.types.CallMaker;
|
import org.jetbrains.jet.lang.types.CallMaker;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@@ -38,7 +39,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
parameterByName.put(valueParameter.getName(), valueParameter);
|
parameterByName.put(valueParameter.getName(), valueParameter);
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends ValueArgument> valueArguments = task.getValueArguments();
|
List<? extends ValueArgument> valueArguments = task.getCall().getValueArguments();
|
||||||
|
|
||||||
boolean error = false;
|
boolean error = false;
|
||||||
boolean someNamed = false;
|
boolean someNamed = false;
|
||||||
@@ -103,7 +104,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
List<JetExpression> functionLiteralArguments = task.getFunctionLiteralArguments();
|
List<JetExpression> functionLiteralArguments = task.getCall().getFunctionLiteralArguments();
|
||||||
if (!functionLiteralArguments.isEmpty()) {
|
if (!functionLiteralArguments.isEmpty()) {
|
||||||
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
|
JetExpression possiblyLabeledFunctionLiteral = functionLiteralArguments.get(0);
|
||||||
|
|
||||||
@@ -164,6 +165,20 @@ import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ReceiverDescriptor receiverParameter = candidate.getReceiverParameter();
|
||||||
|
ReceiverDescriptor receiverArgument = candidateCall.getReceiverArgument();
|
||||||
|
if (receiverParameter.exists() &&!receiverArgument.exists()) {
|
||||||
|
tracing.missingReceiver(temporaryTrace, receiverParameter);
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
if (!receiverParameter.exists() && receiverArgument.exists()) {
|
||||||
|
tracing.noReceiverAllowed(temporaryTrace);
|
||||||
|
error = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert candidateCall.getThisObject().exists() == candidateCall.getExpectedThisObject().exists() : "Shouldn't happen because of TaskPrioritizer: " + candidateCall.getCandidateDescriptor();
|
||||||
|
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -127,6 +127,10 @@ public class CallMaker {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return getCallNode().getText();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<JetExpression> argumentExpressions) {
|
public static Call makeCallWithExpressions(@NotNull JetElement callElement, @NotNull ReceiverDescriptor explicitReceiver, @Nullable ASTNode callOperationNode, @NotNull JetExpression calleeExpression, @NotNull List<JetExpression> argumentExpressions) {
|
||||||
|
|||||||
@@ -222,7 +222,7 @@ public class JetTypeInferrer {
|
|||||||
// if (receiverType != null && callee != null) {
|
// if (receiverType != null && callee != null) {
|
||||||
// boolean namespaceType = receiverType instanceof NamespaceType;
|
// boolean namespaceType = receiverType instanceof NamespaceType;
|
||||||
// boolean nullableReceiver = !namespaceType && receiverType.isNullable();
|
// boolean nullableReceiver = !namespaceType && receiverType.isNullable();
|
||||||
// ReceiverDescriptor calleeReceiver = callee.getReceiver();
|
// ReceiverDescriptor calleeReceiver = callee.getReceiverParameter();
|
||||||
// boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable();
|
// boolean calleeForbidsNullableReceiver = !calleeReceiver.exists() || !calleeReceiver.getType().isNullable();
|
||||||
//
|
//
|
||||||
// IElementType operationSign = operationTokenNode.getElementType();
|
// IElementType operationSign = operationTokenNode.getElementType();
|
||||||
@@ -1275,7 +1275,7 @@ public class JetTypeInferrer {
|
|||||||
}
|
}
|
||||||
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
else if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||||
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
FunctionDescriptor functionDescriptor = (FunctionDescriptor) declarationDescriptor;
|
||||||
thisReceiver = functionDescriptor.getReceiver();
|
thisReceiver = functionDescriptor.getReceiverParameter();
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw new UnsupportedOperationException(); // TODO
|
throw new UnsupportedOperationException(); // TODO
|
||||||
@@ -1289,7 +1289,7 @@ public class JetTypeInferrer {
|
|||||||
if (psiElement instanceof JetFunctionLiteralExpression) {
|
if (psiElement instanceof JetFunctionLiteralExpression) {
|
||||||
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
DeclarationDescriptor declarationDescriptor = context.trace.getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, psiElement);
|
||||||
if (declarationDescriptor instanceof FunctionDescriptor) {
|
if (declarationDescriptor instanceof FunctionDescriptor) {
|
||||||
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiver();
|
thisReceiver = ((FunctionDescriptor) declarationDescriptor).getReceiverParameter();
|
||||||
if (thisReceiver.exists()) {
|
if (thisReceiver.exists()) {
|
||||||
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
context.trace.record(REFERENCE_TARGET, targetLabel, declarationDescriptor);
|
||||||
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
context.trace.record(REFERENCE_TARGET, expression.getThisReference(), declarationDescriptor);
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ public class DescriptorRenderer implements Renderer {
|
|||||||
renderModality(descriptor.getModality(), builder);
|
renderModality(descriptor.getModality(), builder);
|
||||||
String typeString = renderPropertyPrefixAndComputeTypeString(
|
String typeString = renderPropertyPrefixAndComputeTypeString(
|
||||||
builder, descriptor.getTypeParameters(),
|
builder, descriptor.getTypeParameters(),
|
||||||
descriptor.getReceiver(),
|
descriptor.getReceiverParameter(),
|
||||||
descriptor.getOutType(),
|
descriptor.getOutType(),
|
||||||
descriptor.getInType());
|
descriptor.getInType());
|
||||||
renderName(descriptor, builder);
|
renderName(descriptor, builder);
|
||||||
@@ -215,7 +215,7 @@ public class DescriptorRenderer implements Renderer {
|
|||||||
builder.append(renderKeyword("fun")).append(" ");
|
builder.append(renderKeyword("fun")).append(" ");
|
||||||
renderTypeParameters(descriptor.getTypeParameters(), builder);
|
renderTypeParameters(descriptor.getTypeParameters(), builder);
|
||||||
|
|
||||||
ReceiverDescriptor receiver = descriptor.getReceiver();
|
ReceiverDescriptor receiver = descriptor.getReceiverParameter();
|
||||||
if (receiver.exists()) {
|
if (receiver.exists()) {
|
||||||
builder.append(escape(renderType(receiver.getType()))).append(".");
|
builder.append(escape(renderType(receiver.getType()))).append(".");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user