diff --git a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java index 4df270d6376..49740db4b1d 100644 --- a/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java +++ b/idea/src/org/jetbrains/jet/lang/annotations/JetPsiChecker.java @@ -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()); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java index 401b2de46f8..4464143bf11 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TypeResolver.java @@ -34,6 +34,7 @@ public class TypeResolver { return type; } + @NotNull private Type resolveTypeElement(final JetScope scope, final List attributes, JetTypeElement typeElement, final boolean nullable) { final Type[] result = new Type[1]; if (typeElement != null) { diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java index fab2ac4b3fe..fca21a33970 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeChecker.java @@ -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; } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 2815e4223ff..2d2d7ca169e 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -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 indexExpressions = expression.getIndexExpressions(); + List 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 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.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 argumentTypes) { + OverloadDomain overloadDomain = semanticServices.getOverloadResolver().getOverloadDomain(receiverType, scope, name); + overloadDomain = wrapForTracing(overloadDomain, reference); + return overloadDomain.getFunctionDescriptorForPositionedArguments(Collections.emptyList(), argumentTypes); + } + + @Nullable + private List getTypes(JetScope scope, List indexExpressions) { + List argumentTypes = new ArrayList(); + 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 typeArguments, @NotNull List 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);