diff --git a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java index ef5eb18a511..eb410248fc5 100644 --- a/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java +++ b/idea/src/org/jetbrains/jet/lang/cfg/JetControlFlowProcessor.java @@ -213,17 +213,32 @@ public class JetControlFlowProcessor { @Override public void visitUnaryExpression(JetUnaryExpression expression) { - IElementType operationType = expression.getOperationSign().getReferencedNameElementType(); + JetSimpleNameExpression operationSign = expression.getOperationSign(); + IElementType operationType = operationSign.getReferencedNameElementType(); + JetExpression baseExpression = expression.getBaseExpression(); if (JetTokens.LABELS.contains(operationType)) { - String referencedName = expression.getOperationSign().getReferencedName(); + String referencedName = operationSign.getReferencedName(); referencedName = referencedName == null ? " " : referencedName; - visitLabeledExpression(referencedName.substring(1), expression.getBaseExpression()); + visitLabeledExpression(referencedName.substring(1), baseExpression); } else { - visitElement(expression); + value(baseExpression, false, false); + value(operationSign, false, false); + + boolean incrementOrDecrement = isIncrementOrDecrement(operationType); + if (incrementOrDecrement) { + builder.writeNode(expression, baseExpression); + } + + builder.readNode(expression); } } + private boolean isIncrementOrDecrement(IElementType operationType) { + return operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS; + } + + @Override public void visitIfExpression(JetIfExpression expression) { value(expression.getCondition(), false, true); @@ -462,6 +477,16 @@ public class JetControlFlowProcessor { builder.readNode(expression); } + @Override + public void visitBinaryWithTypeRHSExpression(JetBinaryExpressionWithTypeRHS expression) { + if (expression.getOperationSign().getReferencedNameElementType() == JetTokens.COLON) { + value(expression.getLeft(), false, false); + } + else { + visitJetElement(expression); // TODO + } + } + @Override public void visitTypeProjection(JetTypeProjection typeProjection) { // TODO : Support Type Arguments. Class object may be initialized at this point"); diff --git a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java index 51faa346f18..773f969e38c 100644 --- a/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java +++ b/idea/src/org/jetbrains/jet/lang/resolve/TopDownAnalyzer.java @@ -362,7 +362,7 @@ public class TopDownAnalyzer { @Override public void visitUnsupportedElementInstruction(UnsupportedElementInstruction instruction) { - semanticServices.getErrorHandler().genericError(instruction.getElement().getNode(), "Unsupported by control-flow builder"); + semanticServices.getErrorHandler().genericError(instruction.getElement().getNode(), "Unsupported by control-flow builder " + instruction.getElement()); } @Override diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 6636ff00dd9..8f555f7170b 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -1082,11 +1082,16 @@ public class JetTypeInferrer { if (functionDescriptor != null) { JetType returnType = functionDescriptor.getUnsubstitutedReturnType(); if (operationType == JetTokens.PLUSPLUS || operationType == JetTokens.MINUSMINUS) { - if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { - semanticServices.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); + if (semanticServices.getTypeChecker().isSubtypeOf(returnType, JetStandardClasses.getUnitType())) { + result = JetStandardClasses.getUnitType(); + } + else { + if (!semanticServices.getTypeChecker().isSubtypeOf(returnType, receiverType)) { + semanticServices.getErrorHandler().genericError(operationSign.getNode(), name + " must return " + receiverType + " but returns " + returnType); + } + // TODO : Maybe returnType? + result = receiverType; } - // TODO : Maybe returnType? - result = receiverType; } else { result = returnType; } @@ -1386,7 +1391,7 @@ public class JetTypeInferrer { String counterpartName = binaryOperationNames.get(assignmentOperationCounterparts.get(operationType)); getTypeForBinaryCall(expression, counterpartName, scope, true); } - result = null; // not an element + result = null; // not an expression } @Override diff --git a/idea/testData/checker/IncDec.jet b/idea/testData/checker/IncDec.jet new file mode 100644 index 00000000000..1c763ee6774 --- /dev/null +++ b/idea/testData/checker/IncDec.jet @@ -0,0 +1,46 @@ +class IncDec { + fun inc() : IncDec = this + fun dec() : IncDec = this +} + +fun testIncDec() { + var x = new IncDec() + x++ + ++x + x-- + --x + x = x++ + x = x-- + x = ++x + x = --x +} + +class WrongIncDec { + fun inc() : Int = 1 + fun dec() : Int = 1 +} + +fun testWrongIncDec() { + var x = new WrongIncDec() + x++ + ++x + x-- + --x +} + +class UnitIncDec { + fun inc() : Unit {} + fun dec() : Unit {} +} + +fun testUnitIncDec() { + var x = new UnitIncDec() + x++ + ++x + x-- + --x + x = x++ + x = x-- + x = ++x + x = --x +} \ No newline at end of file diff --git a/idea/testData/resolve/ResolveOfInfixExpressions.jet b/idea/testData/resolve/ResolveOfInfixExpressions.jet index 0c072ad25ca..458921abd93 100644 --- a/idea/testData/resolve/ResolveOfInfixExpressions.jet +++ b/idea/testData/resolve/ResolveOfInfixExpressions.jet @@ -85,3 +85,15 @@ fun tt(t : T) : T { 1 `std::Int.compareTo(Double)`>= 2.0 1 `std::Int.compareTo(Double)`<= 2.0 } + + +class UnitIncDec { + ~uinc~fun inc() : Unit + ~udec~fun dec() : Unit +} + +fun testUnitIncDec() { + var x = new UnitIncDec() + x`uinc`++ + x`udec`-- +} \ No newline at end of file