diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java index 9f793d08152..24a7e80f670 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetBinaryExpressionWithTypeRHS.java @@ -28,7 +28,7 @@ public class JetBinaryExpressionWithTypeRHS extends JetExpression { @Nullable @IfNotParsed public JetTypeReference getRight() { - ASTNode node = getOperationReference().getNode(); + ASTNode node = getOperationSign().getNode(); while (node != null) { PsiElement psi = node.getPsi(); if (psi instanceof JetTypeReference) { @@ -40,7 +40,7 @@ public class JetBinaryExpressionWithTypeRHS extends JetExpression { return null; } @NotNull - public JetSimpleNameExpression getOperationReference() { + public JetSimpleNameExpression getOperationSign() { return (JetSimpleNameExpression) findChildByType(JetNodeTypes.OPERATION_REFERENCE); } diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index b53d9345025..e89d40d46b8 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -16,6 +16,46 @@ import java.util.*; */ public class JetTypeInferrer { + private static final Map unaryOperationNames = new HashMap(); + static { + unaryOperationNames.put(JetTokens.PLUSPLUS, "inc"); + unaryOperationNames.put(JetTokens.MINUSMINUS, "dec"); + unaryOperationNames.put(JetTokens.EXCL, "not"); + } + + private static final Map binaryOperationNames = new HashMap(); + static { + binaryOperationNames.put(JetTokens.MUL, "times"); + binaryOperationNames.put(JetTokens.PLUS, "plus"); + binaryOperationNames.put(JetTokens.MINUS, "minus"); + binaryOperationNames.put(JetTokens.DIV, "div"); + binaryOperationNames.put(JetTokens.PERC, "mod"); + binaryOperationNames.put(JetTokens.ARROW, "arrow"); + binaryOperationNames.put(JetTokens.RANGE, "rangeTo"); + } + + private static final Set comparisonOperations = new HashSet(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ)); + private static final Set equalsOperations = new HashSet(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ)); + private static final Set inOperations = new HashSet(Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.NOT_IN)); + + private static final Map assignmentOperationNames = new HashMap(); + static { + assignmentOperationNames.put(JetTokens.MULTEQ, "timesAssign"); + assignmentOperationNames.put(JetTokens.DIVEQ, "divAssign"); + assignmentOperationNames.put(JetTokens.PERCEQ, "modAssign"); + assignmentOperationNames.put(JetTokens.PLUSEQ, "plusAssign"); + assignmentOperationNames.put(JetTokens.MINUSEQ, "minusAssign"); + } + + private static final Map assignmentOperationCounterparts = new HashMap(); + static { + assignmentOperationCounterparts.put(JetTokens.MULTEQ, JetTokens.MUL); + assignmentOperationCounterparts.put(JetTokens.DIVEQ, JetTokens.DIV); + assignmentOperationCounterparts.put(JetTokens.PERCEQ, JetTokens.PERC); + assignmentOperationCounterparts.put(JetTokens.PLUSEQ, JetTokens.PLUS); + assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS); + } + private final BindingTrace trace; private final JetSemanticServices semanticServices; private final TypeResolver typeResolver; @@ -354,17 +394,24 @@ public class JetTypeInferrer { @Override public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { - if (expression.getOperationReference().getReferencedNameElementType() == JetTokens.COLON) { - JetType actualType = getType(scope, expression.getLeft(), false); - JetType expectedType = typeResolver.resolveType(scope, expression.getRight()); - if (actualType != null && !semanticServices.getTypeChecker().isSubtypeOf(actualType, expectedType)) { - // TODO - semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), expectedType, actualType); + IElementType operationType = expression.getOperationSign().getReferencedNameElementType(); + JetType actualType = getType(scope, expression.getLeft(), false); + JetTypeReference right = expression.getRight(); + if (right != null) { + JetType targetType = typeResolver.resolveType(scope, right); + if (operationType == JetTokens.COLON) { + if (actualType != null && !semanticServices.getTypeChecker().isSubtypeOf(actualType, targetType)) { + semanticServices.getErrorHandler().typeMismatch(expression.getLeft(), targetType, actualType); + } } - result = expectedType; - return; + else if (operationType == JetTokens.AS_KEYWORD) { + // TODO : Check for cast impossibility + } + else { + semanticServices.getErrorHandler().structuralError(expression.getOperationSign().getNode(), "Unsupported binary operation"); + } + result = targetType; } - throw new UnsupportedOperationException(); // TODO } @Override @@ -698,46 +745,4 @@ public class JetTypeInferrer { return null; } } - - private static final Map unaryOperationNames = new HashMap(); - static { - unaryOperationNames.put(JetTokens.PLUSPLUS, "inc"); - unaryOperationNames.put(JetTokens.MINUSMINUS, "dec"); - unaryOperationNames.put(JetTokens.EXCL, "not"); - } - - private static final Map binaryOperationNames = new HashMap(); - static { - binaryOperationNames.put(JetTokens.MUL, "times"); - binaryOperationNames.put(JetTokens.PLUS, "plus"); - binaryOperationNames.put(JetTokens.MINUS, "minus"); - binaryOperationNames.put(JetTokens.DIV, "div"); - binaryOperationNames.put(JetTokens.PERC, "mod"); - binaryOperationNames.put(JetTokens.ARROW, "arrow"); - binaryOperationNames.put(JetTokens.RANGE, "rangeTo"); - } - - private static final Set comparisonOperations = new HashSet(Arrays.asList(JetTokens.LT, JetTokens.GT, JetTokens.LTEQ, JetTokens.GTEQ)); - private static final Set equalsOperations = new HashSet(Arrays.asList(JetTokens.EQEQ, JetTokens.EXCLEQ)); - private static final Set inOperations = new HashSet(Arrays.asList(JetTokens.IN_KEYWORD, JetTokens.NOT_IN)); - - private static final Map assignmentOperationNames = new HashMap(); - static { - assignmentOperationNames.put(JetTokens.MULTEQ, "timesAssign"); - assignmentOperationNames.put(JetTokens.DIVEQ, "divAssign"); - assignmentOperationNames.put(JetTokens.PERCEQ, "modAssign"); - assignmentOperationNames.put(JetTokens.PLUSEQ, "plusAssign"); - assignmentOperationNames.put(JetTokens.MINUSEQ, "minusAssign"); - } - - private static final Map assignmentOperationCounterparts = new HashMap(); - static { - assignmentOperationCounterparts.put(JetTokens.MULTEQ, JetTokens.MUL); - assignmentOperationCounterparts.put(JetTokens.DIVEQ, JetTokens.DIV); - assignmentOperationCounterparts.put(JetTokens.PERCEQ, JetTokens.PERC); - assignmentOperationCounterparts.put(JetTokens.PLUSEQ, JetTokens.PLUS); - assignmentOperationCounterparts.put(JetTokens.MINUSEQ, JetTokens.MINUS); - } - - } diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 9697ddc7028..6454f0607c7 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -398,6 +398,10 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertType("\"1\".plus('1')", "String"); } + public void testBinaryOperations() throws Exception { + assertType("1 as Any", "Any"); + } + private void assertSubtype(String type1, String type2) { assertSubtypingRelation(type1, type2, true); }