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