ResolvedCalls for indexed expressions
This commit is contained in:
@@ -12,7 +12,6 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.diagnostics.DiagnosticUtils;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContextUtils;
|
||||
import org.jetbrains.jet.lang.resolve.calls.*;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstant;
|
||||
import org.jetbrains.jet.lang.resolve.java.JavaClassDescriptor;
|
||||
@@ -1976,14 +1975,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> {
|
||||
boolean isGetter = accessor.getSignature().getName().equals("get");
|
||||
|
||||
if(isGetter) {
|
||||
FunctionDescriptor setterDescriptor = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_SET, expression);
|
||||
FunctionDescriptor setterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
return StackValue.collectionElement(
|
||||
accessor.getSignature().getReturnType(),
|
||||
accessor,
|
||||
setterDescriptor != null ? typeMapper.mapToCallableMethod(setterDescriptor, OwnerKind.IMPLEMENTATION) : null);
|
||||
}
|
||||
else {
|
||||
FunctionDescriptor getterDescriptor = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = bindingContext.get(BindingContext.INDEXED_LVALUE_GET, expression);
|
||||
FunctionDescriptor getterDescriptor = resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
return StackValue.collectionElement(
|
||||
accessor.getSignature().getArgumentTypes()[1],
|
||||
getterDescriptor != null ? typeMapper.mapToCallableMethod(getterDescriptor, OwnerKind.IMPLEMENTATION) : null,
|
||||
|
||||
@@ -36,8 +36,8 @@ public interface BindingContext {
|
||||
WritableSlice<JetExpression, CallableDescriptor> LOOP_RANGE_HAS_NEXT = Slices.createSimpleSlice("LOOP_RANGE_HAS_NEXT");
|
||||
WritableSlice<JetExpression, FunctionDescriptor> LOOP_RANGE_NEXT = Slices.createSimpleSlice("LOOP_RANGE_NEXT");
|
||||
|
||||
WritableSlice<JetExpression, FunctionDescriptor> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET");
|
||||
WritableSlice<JetExpression, FunctionDescriptor> INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET");
|
||||
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_GET = Slices.createSimpleSlice("INDEXED_LVALUE_GET");
|
||||
WritableSlice<JetExpression, ResolvedCall<FunctionDescriptor>> INDEXED_LVALUE_SET = Slices.createSimpleSlice("INDEXED_LVALUE_SET");
|
||||
|
||||
WritableSlice<JetExpression, JetType> AUTOCAST = Slices.createSimpleSlice("AUTOCAST");
|
||||
WritableSlice<JetExpression, JetScope> RESOLUTION_SCOPE = Slices.createSimpleSlice("RESOLUTION_SCOPE");
|
||||
|
||||
@@ -78,7 +78,7 @@ public class CallResolver {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenName(
|
||||
public ResolvedCall<FunctionDescriptor> resolveCallWithGivenName(
|
||||
@NotNull BindingTrace trace,
|
||||
@NotNull JetScope scope,
|
||||
@NotNull final Call call,
|
||||
@@ -86,7 +86,7 @@ public class CallResolver {
|
||||
@NotNull String name,
|
||||
@NotNull JetType expectedType) {
|
||||
List<ResolutionTask<FunctionDescriptor>> tasks = TaskPrioritizers.FUNCTION_TASK_PRIORITIZER.computePrioritizedTasks(scope, call, name, trace.getBindingContext(), dataFlowInfo);
|
||||
return resolveCallToDescriptor(trace, scope, call, expectedType, tasks, functionReference);
|
||||
return doResolveCall(trace, scope, call, expectedType, tasks, functionReference);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
@@ -174,7 +174,8 @@ public class CallResolver {
|
||||
prioritizedTasks = Collections.singletonList(new ResolutionTask<FunctionDescriptor>(ResolvedCallImpl.convertCollection(constructors), call, DataFlowInfo.EMPTY));
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedOperationException("Type argument inference not implemented for " + call);
|
||||
trace.report(UNSUPPORTED.on(call.getCallNode(), "Type argument inference is not supported for this callee: " + calleeExpression));
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-14
@@ -11,6 +11,7 @@ import org.jetbrains.jet.lang.descriptors.*;
|
||||
import org.jetbrains.jet.lang.psi.*;
|
||||
import org.jetbrains.jet.lang.resolve.*;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.constants.*;
|
||||
@@ -559,11 +560,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(facade, baseExpression, context.replaceExpectedType(NO_EXPECTED_TYPE).replaceScope(context.scope));
|
||||
if (receiver == null) return null;
|
||||
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
|
||||
CallMaker.makeCall(receiver, expression),
|
||||
expression.getOperationSign(),
|
||||
name,
|
||||
receiver);
|
||||
name);
|
||||
|
||||
if (functionDescriptor == null) return null;
|
||||
JetType returnType = functionDescriptor.getReturnType();
|
||||
@@ -705,10 +705,10 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
public void checkInExpression(JetElement callElement, @NotNull JetSimpleNameExpression operationSign, @NotNull JetExpression left, @NotNull JetExpression right, ExpressionTypingContext context) {
|
||||
String name = "contains";
|
||||
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, right, context.replaceExpectedType(NO_EXPECTED_TYPE));
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenNameToDescriptor(
|
||||
CallMaker.makeCallWithExpressions(callElement, receiver, null, operationSign, Collections.singletonList(left)),
|
||||
operationSign,
|
||||
name, receiver);
|
||||
name);
|
||||
JetType containsType = functionDescriptor != null ? functionDescriptor.getReturnType() : null;
|
||||
ensureBooleanResult(operationSign, name, containsType, context);
|
||||
}
|
||||
@@ -752,14 +752,14 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayExpression, context.replaceScope(context.scope));
|
||||
|
||||
if (receiver != null) {
|
||||
FunctionDescriptor functionDescriptor = context.resolveCallWithGivenName(
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = context.resolveCallWithGivenName(
|
||||
CallMaker.makeCallWithExpressions(expression, receiver, null, expression, expression.getIndexExpressions()),
|
||||
expression,
|
||||
"get",
|
||||
receiver);
|
||||
if (functionDescriptor != null) {
|
||||
context.trace.record(INDEXED_LVALUE_GET, expression, functionDescriptor);
|
||||
return DataFlowUtils.checkType(functionDescriptor.getReturnType(), expression, contextWithExpectedType);
|
||||
"get"
|
||||
);
|
||||
if (resolvedCall != null) {
|
||||
context.trace.record(INDEXED_LVALUE_GET, expression, resolvedCall);
|
||||
return DataFlowUtils.checkType(resolvedCall.getResultingDescriptor().getReturnType(), expression, contextWithExpectedType);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -768,11 +768,11 @@ public class BasicExpressionTypingVisitor extends ExpressionTypingVisitor {
|
||||
@Nullable
|
||||
protected JetType getTypeForBinaryCall(JetScope scope, String name, ExpressionTypingContext context, JetBinaryExpression binaryExpression) {
|
||||
ExpressionReceiver receiver = safeGetExpressionReceiver(facade, binaryExpression.getLeft(), context.replaceScope(scope));
|
||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenName(
|
||||
FunctionDescriptor functionDescriptor = context.replaceScope(scope).resolveCallWithGivenNameToDescriptor(
|
||||
CallMaker.makeCall(receiver, binaryExpression),
|
||||
binaryExpression.getOperationReference(),
|
||||
name,
|
||||
receiver);
|
||||
name
|
||||
);
|
||||
if (functionDescriptor != null) {
|
||||
return functionDescriptor.getReturnType();
|
||||
}
|
||||
|
||||
+8
-1
@@ -12,6 +12,7 @@ import org.jetbrains.jet.lang.resolve.ClassDescriptorResolver;
|
||||
import org.jetbrains.jet.lang.resolve.TypeResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallResolver;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.calls.autocasts.DataFlowInfo;
|
||||
import org.jetbrains.jet.lang.resolve.calls.OverloadResolutionResults;
|
||||
import org.jetbrains.jet.lang.resolve.constants.CompileTimeConstantResolver;
|
||||
@@ -172,10 +173,16 @@ import java.util.Map;
|
||||
////////// Call resolution utilities
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name, @NotNull ReceiverDescriptor receiver) {
|
||||
public ResolvedCall<FunctionDescriptor> resolveCallWithGivenName(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) {
|
||||
return getCallResolver().resolveCallWithGivenName(trace, scope, call, functionReference, name, expectedType);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public FunctionDescriptor resolveCallWithGivenNameToDescriptor(@NotNull Call call, @NotNull JetReferenceExpression functionReference, @NotNull String name) {
|
||||
ResolvedCall<FunctionDescriptor> resolvedCall = resolveCallWithGivenName(call, functionReference, name);
|
||||
return resolvedCall == null ? null : resolvedCall.getResultingDescriptor();
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public JetType resolveCall(@NotNull ReceiverDescriptor receiver, @Nullable ASTNode callOperationNode, @NotNull JetCallExpression callExpression) {
|
||||
return getCallResolver().resolveCall(trace, scope, CallMaker.makeCall(receiver, callOperationNode, callExpression), expectedType);
|
||||
|
||||
+25
-22
@@ -9,15 +9,16 @@ import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.TemporaryBindingTrace;
|
||||
import org.jetbrains.jet.lang.resolve.TopDownAnalyzer;
|
||||
import org.jetbrains.jet.lang.resolve.calls.CallMaker;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.WritableScope;
|
||||
import org.jetbrains.jet.lang.resolve.scopes.receivers.ExpressionReceiver;
|
||||
import org.jetbrains.jet.lang.types.ErrorUtils;
|
||||
import org.jetbrains.jet.lang.types.JetStandardClasses;
|
||||
import org.jetbrains.jet.lang.types.JetType;
|
||||
import org.jetbrains.jet.lang.types.TypeUtils;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
|
||||
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_GET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.INDEXED_LVALUE_SET;
|
||||
import static org.jetbrains.jet.lang.resolve.BindingContext.REFERENCE_TARGET;
|
||||
import static org.jetbrains.jet.lang.types.expressions.ExpressionTypingUtils.getExpressionReceiver;
|
||||
@@ -123,7 +124,7 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
||||
if (typeForBinaryCall != null) {
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
if (left instanceof JetArrayAccessExpression) {
|
||||
resolveArrayAccessToLValue((JetArrayAccessExpression) left, expression.getRight(), expression.getOperationReference(), context, true);
|
||||
resolveArrayAccessToLValue((JetArrayAccessExpression) left, expression.getRight(), expression.getOperationReference(), context);
|
||||
}
|
||||
|
||||
context.trace.record(BindingContext.VARIABLE_REASSIGNMENT, expression);
|
||||
@@ -138,14 +139,14 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
||||
|
||||
@Override
|
||||
protected JetType visitAssignment(JetBinaryExpression expression, ExpressionTypingContext context) {
|
||||
boolean getterNeeded = false;
|
||||
JetExpression left = JetPsiUtil.deparenthesize(expression.getLeft());
|
||||
JetExpression right = expression.getRight();
|
||||
if (left instanceof JetArrayAccessExpression) {
|
||||
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
|
||||
return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context, getterNeeded);
|
||||
return resolveArrayAccessToLValue(arrayAccessExpression, right, expression.getOperationReference(), context);
|
||||
}
|
||||
JetType leftType = facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope));
|
||||
JetType leftType = left == null ? ErrorUtils.createErrorType("No expression")
|
||||
: facade.getType(left, context.replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).replaceScope(scope));
|
||||
if (right != null) {
|
||||
JetType rightType = facade.getType(right, context.replaceExpectedType(leftType).replaceScope(scope));
|
||||
}
|
||||
@@ -164,30 +165,32 @@ public class ExpressionTypingVisitorForStatements extends BasicExpressionTypingV
|
||||
return checkExpectedType(expression, context);
|
||||
}
|
||||
|
||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context, boolean getterNeeded) {
|
||||
private JetType resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetSimpleNameExpression operationSign, ExpressionTypingContext context) {
|
||||
ExpressionReceiver receiver = getExpressionReceiver(facade, arrayAccessExpression.getArrayExpression(), context.replaceScope(scope));
|
||||
if (receiver == null) return null;
|
||||
|
||||
Call call = CallMaker.makeArraySetCall(receiver, arrayAccessExpression, rightHandSide);
|
||||
FunctionDescriptor setFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
ResolvedCall<FunctionDescriptor> setFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
call,
|
||||
arrayAccessExpression,
|
||||
"set", receiver);
|
||||
if (setFunction == null) return null;
|
||||
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunction);
|
||||
"set");
|
||||
if (setFunctionCall == null) return null;
|
||||
FunctionDescriptor setFunctionDescriptor = setFunctionCall.getResultingDescriptor();
|
||||
|
||||
if (getterNeeded) {
|
||||
FunctionDescriptor getFunction = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
|
||||
arrayAccessExpression,
|
||||
"get", receiver);
|
||||
if (getFunction == null) return null;
|
||||
context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunction);
|
||||
}
|
||||
else {
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, setFunction);
|
||||
}
|
||||
return DataFlowUtils.checkType(setFunction.getReturnType(), arrayAccessExpression, context);
|
||||
context.trace.record(INDEXED_LVALUE_SET, arrayAccessExpression, setFunctionCall);
|
||||
|
||||
// if (getterNeeded) {
|
||||
// ResolvedCall<FunctionDescriptor> getFunctionCall = context.replaceScope(scope).replaceExpectedType(TypeUtils.NO_EXPECTED_TYPE).resolveCallWithGivenName(
|
||||
// CallMaker.makeArrayGetCall(receiver, arrayAccessExpression),
|
||||
// arrayAccessExpression,
|
||||
// "get");
|
||||
// if (getFunctionCall == null) return null;
|
||||
// context.trace.record(INDEXED_LVALUE_GET, arrayAccessExpression, getFunctionCall);
|
||||
// }
|
||||
// else {
|
||||
context.trace.record(REFERENCE_TARGET, operationSign, setFunctionDescriptor);
|
||||
// }
|
||||
return DataFlowUtils.checkType(setFunctionDescriptor.getReturnType(), arrayAccessExpression, context);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -8,6 +8,7 @@ import org.jetbrains.jet.lang.psi.JetArrayAccessExpression;
|
||||
import org.jetbrains.jet.lang.psi.JetContainerNode;
|
||||
import org.jetbrains.jet.lang.psi.JetFile;
|
||||
import org.jetbrains.jet.lang.resolve.BindingContext;
|
||||
import org.jetbrains.jet.lang.resolve.calls.ResolvedCall;
|
||||
import org.jetbrains.jet.lexer.JetTokens;
|
||||
import org.jetbrains.jet.plugin.compiler.WholeProjectAnalyzerFacade;
|
||||
|
||||
@@ -40,8 +41,8 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
|
||||
@Override
|
||||
protected PsiElement doResolve() {
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
|
||||
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
if (getFunction != null && setFunction != null) {
|
||||
return null; // Call doMultiResolve
|
||||
}
|
||||
@@ -51,10 +52,10 @@ class JetArrayAccessReference extends JetPsiReference implements MultiRangeRefer
|
||||
@Override
|
||||
protected ResolveResult[] doMultiResolve() {
|
||||
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) getElement().getContainingFile());
|
||||
FunctionDescriptor getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction);
|
||||
FunctionDescriptor setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction);
|
||||
ResolvedCall<FunctionDescriptor> getFunction = bindingContext.get(INDEXED_LVALUE_GET, expression);
|
||||
PsiElement getFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, getFunction.getResultingDescriptor());
|
||||
ResolvedCall<FunctionDescriptor> setFunction = bindingContext.get(INDEXED_LVALUE_SET, expression);
|
||||
PsiElement setFunctionElement = bindingContext.get(DESCRIPTOR_TO_DECLARATION, setFunction.getResultingDescriptor());
|
||||
return new ResolveResult[] {new PsiElementResolveResult(getFunctionElement, true), new PsiElementResolveResult(setFunctionElement, true)};
|
||||
// return super.doMultiResolve();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user