Resolve for array access. Proper references are pending

This commit is contained in:
Andrey Breslav
2011-03-11 18:30:08 +03:00
parent 917dfd402e
commit f54e601620
4 changed files with 83 additions and 10 deletions
@@ -1,8 +1,10 @@
package org.jetbrains.jet.lang.annotations;
import com.intellij.codeInspection.ProblemHighlightType;
import com.intellij.lang.ASTNode;
import com.intellij.lang.annotation.AnnotationHolder;
import com.intellij.lang.annotation.Annotator;
import com.intellij.openapi.progress.ProcessCanceledException;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.TextRange;
import com.intellij.psi.PsiElement;
@@ -28,7 +30,7 @@ public class JetPsiChecker implements Annotator {
final BindingContext bindingContext = AnalyzingUtils.analyzeFile(file, new ErrorHandler() {
@Override
public void unresolvedReference(JetReferenceExpression referenceExpression) {
holder.createErrorAnnotation(referenceExpression, "Unresolved");
holder.createErrorAnnotation(referenceExpression, "Unresolved").setHighlightType(ProblemHighlightType.LIKE_UNKNOWN_SYMBOL);
}
@Override
@@ -59,6 +61,9 @@ public class JetPsiChecker implements Annotator {
}
});
}
catch (ProcessCanceledException e) {
// Canceled. We are fine
}
catch (Throwable e) {
// TODO
holder.createErrorAnnotation(new TextRange(0, 1), e.getClass().getCanonicalName() + ": " + e.getMessage());
@@ -34,6 +34,7 @@ public class TypeResolver {
return type;
}
@NotNull
private Type resolveTypeElement(final JetScope scope, final List<Attribute> attributes, JetTypeElement typeElement, final boolean nullable) {
final Type[] result = new Type[1];
if (typeElement != null) {
@@ -1,5 +1,6 @@
package org.jetbrains.jet.lang.types;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.psi.JetExpression;
@@ -293,7 +294,7 @@ public class JetTypeChecker {
return false;
}
public boolean isSubtypeOf(Type subtype, Type supertype) {
public boolean isSubtypeOf(@NotNull Type subtype, @NotNull Type supertype) {
if (!supertype.isNullable() && subtype.isNullable()) {
return false;
}
@@ -170,7 +170,7 @@ public class JetTypeInferrer {
if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.COLON) {
Type actualType = getType(scope, expression.getLeft(), false);
Type expectedType = typeResolver.resolveType(scope, expression.getRight());
if (!semanticServices.getTypeChecker().isSubtypeOf(actualType, expectedType)) {
if (actualType != null && !semanticServices.getTypeChecker().isSubtypeOf(actualType, expectedType)) {
// TODO
semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), expectedType, actualType);
}
@@ -350,11 +350,53 @@ public class JetTypeInferrer {
}
else if (operationType == JetTokens.PLUS) {
result[0] = getTypeForBinaryCall(expression, "plus", scope);
}
else if (operationType == JetTokens.EQ) {
JetExpression left = expression.getLeft();
if (left instanceof JetArrayAccessExpression) {
JetArrayAccessExpression arrayAccessExpression = (JetArrayAccessExpression) left;
resolveArrayAccessToLValue(arrayAccessExpression, expression.getRight(), expression.getOperationReference());
}
else {
throw new UnsupportedOperationException();
}
result[0] = null; // TODO : This is not an expression, in fact!
} else {
throw new UnsupportedOperationException(); // TODO
}
}
@Override
public void visitArrayAccessExpression(JetArrayAccessExpression expression) {
JetExpression arrayExpression = expression.getArrayExpression();
Type receiverType = getType(scope, arrayExpression, false);
List<JetExpression> indexExpressions = expression.getIndexExpressions();
List<Type> argumentTypes = getTypes(scope, indexExpressions);
if (argumentTypes == null) return;
// TODO : record unresolved
FunctionDescriptor functionDescriptor = lookupFunction(scope, null, "get", receiverType, argumentTypes);
if (functionDescriptor != null) {
result[0] = functionDescriptor.getUnsubstitutedReturnType();
}
}
private void resolveArrayAccessToLValue(JetArrayAccessExpression arrayAccessExpression, JetExpression rightHandSide, JetReferenceExpression operationSign) {
List<Type> argumentTypes = getTypes(scope, arrayAccessExpression.getIndexExpressions());
if (argumentTypes == null) return;
Type rhsType = getType(scope, rightHandSide, false);
if (rhsType == null) return;
argumentTypes.add(rhsType);
Type receiverType = getType(scope, arrayAccessExpression.getArrayExpression(), false);
if (receiverType == null) return;
FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, "set", receiverType, argumentTypes);
if (functionDescriptor != null) {
result[0] = functionDescriptor.getUnsubstitutedReturnType();
}
}
@Override
public void visitJetElement(JetElement elem) {
throw new IllegalArgumentException("Unsupported element: " + elem);
@@ -369,9 +411,7 @@ public class JetTypeInferrer {
return ErrorType.createErrorType("No right argument");
}
Type rightType = getType(scope, right, false);
OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(leftType, scope, name);
overloadDomain = wrapForTracing(overloadDomain, operationSign);
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), Collections.singletonList(rightType));
FunctionDescriptor functionDescriptor = lookupFunction(scope, operationSign, name, leftType, Collections.singletonList(rightType));
if (functionDescriptor != null) {
return functionDescriptor.getUnsubstitutedReturnType();
}
@@ -384,6 +424,26 @@ public class JetTypeInferrer {
return result[0];
}
@Nullable
private FunctionDescriptor lookupFunction(JetScope scope, JetReferenceExpression reference, String name, Type receiverType, List<Type> argumentTypes) {
OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name);
overloadDomain = wrapForTracing(overloadDomain, reference);
return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.<Type>emptyList(), argumentTypes);
}
@Nullable
private List<Type> getTypes(JetScope scope, List<JetExpression> indexExpressions) {
List<Type> argumentTypes = new ArrayList<Type>();
for (JetExpression indexExpression : indexExpressions) {
Type type = getType(scope, indexExpression, false);
if (type == null) {
return null;
}
argumentTypes.add(type);
}
return argumentTypes;
}
private OverloadDomain getOverloadDomain(final JetScope scope, JetExpression calleeExpression) {
final OverloadDomain[] result = new OverloadDomain[1];
@@ -440,7 +500,7 @@ public class JetTypeInferrer {
return wrapForTracing(result[0], reference[0]);
}
private OverloadDomain wrapForTracing(final OverloadDomain overloadDomain, final JetReferenceExpression referenceExpression) {
private OverloadDomain wrapForTracing(final OverloadDomain overloadDomain, @Nullable final JetReferenceExpression referenceExpression) {
if (overloadDomain == null) return OverloadDomain.EMPTY;
return new OverloadDomain() {
@Override
@@ -458,9 +518,13 @@ public class JetTypeInferrer {
public FunctionDescriptor getFunctionDescriptorForPositionedArguments(@NotNull List<Type> typeArguments, @NotNull List<Type> positionedValueArgumentTypes) {
FunctionDescriptor descriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(typeArguments, positionedValueArgumentTypes);
if (descriptor != null) {
trace.recordReferenceResolution(referenceExpression, descriptor);
if (referenceExpression != null) {
trace.recordReferenceResolution(referenceExpression, descriptor);
}
} else {
semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
if (referenceExpression != null) {
semanticServices.getErrorHandler().unresolvedReference(referenceExpression);
}
}
return descriptor;
}
@@ -476,7 +540,9 @@ public class JetTypeInferrer {
// TODO: consider other declarations
if (statement instanceof JetProperty) {
JetProperty property = (JetProperty) statement;
scope.addPropertyDescriptor(classDescriptorResolver.resolvePropertyDescriptor(scope, property));
PropertyDescriptor propertyDescriptor = classDescriptorResolver.resolvePropertyDescriptor(scope, property);
scope.addPropertyDescriptor(propertyDescriptor);
trace.recordDeclarationResolution(property, propertyDescriptor);
}
else if (statement instanceof JetExpression) {
getType(scope, (JetExpression) statement, true);