diff --git a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java index fbc19709b23..35c153f350a 100644 --- a/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java +++ b/idea/src/org/jetbrains/jet/lang/parsing/JetExpressionParsing.java @@ -409,7 +409,7 @@ public class JetExpressionParsing extends AbstractJetParsing { private void parseCallExpression() { PsiBuilder.Marker mark = mark(); parseAtomicExpression(); - if (parseCallSuffix()) { + if (!myBuilder.newlineBeforeCurrentToken() && parseCallSuffix()) { mark.done(CALL_EXPRESSION); } else { diff --git a/idea/src/org/jetbrains/jet/lang/psi/JetChangeUtil.java b/idea/src/org/jetbrains/jet/lang/psi/JetChangeUtil.java index c28e18a82df..7d2c6df9982 100644 --- a/idea/src/org/jetbrains/jet/lang/psi/JetChangeUtil.java +++ b/idea/src/org/jetbrains/jet/lang/psi/JetChangeUtil.java @@ -45,7 +45,7 @@ public class JetChangeUtil { JetFile file = createFile(project, text); JetNamespace rootNamespace = file.getRootNamespace(); List dcls = rootNamespace.getDeclarations(); - assert dcls.size() == 1; + assert dcls.size() == 1 : dcls.size(); @SuppressWarnings("unchecked") T result = (T) dcls.get(0); return result; diff --git a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java index 34414a620f8..9da268d9306 100644 --- a/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java +++ b/idea/src/org/jetbrains/jet/lang/types/JetTypeInferrer.java @@ -543,24 +543,6 @@ public class JetTypeInferrer { throw new UnsupportedOperationException(); // TODO } - @Override - public void visitPredicateExpression(JetPredicateExpression expression) { -// JetExpression receiverExpression = expression.getReceiverExpression(); -// JetExpression selectorExpression = expression.getSelectorExpression(); -// JetType receiverType = getType(scope, receiverExpression, false); -// if (receiverType != null) { -// if (selectorExpression instanceof JetSimpleNameExpression) { -// JetScope compositeScope = new ScopeWithReceiver(scope, receiverType); -// result = getType(compositeScope, selectorExpression, false); -// } -// else if (selectorExpression != null) { -// // TODO : not a simple name -> resolve in scope, expect property type or a function type -// throw new UnsupportedOperationException(); -// } -// } - throw new UnsupportedOperationException(); // TODO - } - @Override public void visitQualifiedExpression(JetQualifiedExpression expression) { // TODO : functions @@ -569,30 +551,45 @@ public class JetTypeInferrer { JetType receiverType = getType(scope, receiverExpression, false); if (receiverType != null) { checkNullSafety(receiverType, expression); - JetScope compositeScope = new ScopeWithReceiver(scope, receiverType); - if (selectorExpression instanceof JetCallExpression) { - JetCallExpression callExpression = (JetCallExpression) selectorExpression; - OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression()); - resolveOverloads(scope, callExpression, overloadDomain); + JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression); + if (expression.getOperationSign() == JetTokens.QUEST) { + if (selectorReturnType != null && !isBoolean(selectorReturnType)) { + // TODO : more comprehensible error message + semanticServices.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType); + } + result = TypeUtils.makeNullable(receiverType); } - else if (selectorExpression instanceof JetSimpleNameExpression) { - result = getType(compositeScope, selectorExpression, false); - } - else if (selectorExpression != null) { - // TODO : not a simple name -> resolve in scope, expect property type or a function type - throw new UnsupportedOperationException(); + else { + result = selectorReturnType; } } } + private JetType getSelectorReturnType(JetType receiverType, JetExpression selectorExpression) { + JetScope compositeScope = new ScopeWithReceiver(scope, receiverType); + if (selectorExpression instanceof JetCallExpression) { + JetCallExpression callExpression = (JetCallExpression) selectorExpression; + OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression()); + return resolveOverloads(scope, callExpression, overloadDomain); + } + else if (selectorExpression instanceof JetSimpleNameExpression) { + return getType(compositeScope, selectorExpression, false); + } + else if (selectorExpression != null) { + // TODO : not a simple name -> resolve in scope, expect property type or a function type + throw new UnsupportedOperationException(); + } + return receiverType; + } + @Override public void visitCallExpression(JetCallExpression expression) { JetExpression calleeExpression = expression.getCalleeExpression(); OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression); - resolveOverloads(scope, expression, overloadDomain); + result = resolveOverloads(scope, expression, overloadDomain); } - private void resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) { + private JetType resolveOverloads(JetScope scope, JetCallExpression expression, OverloadDomain overloadDomain) { // 1) ends with a name -> (scope, name) to look up // 2) ends with something else -> just check types @@ -640,9 +637,10 @@ public class JetTypeInferrer { FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes); if (functionDescriptor != null) { - result = functionDescriptor.getUnsubstitutedReturnType(); + return functionDescriptor.getUnsubstitutedReturnType(); } } + return null; } @Override diff --git a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java index 588afd7c0ff..0dfaef02168 100644 --- a/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java +++ b/idea/tests/org/jetbrains/jet/types/JetTypeCheckerTest.java @@ -406,6 +406,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { assertType("true && false", "Boolean"); assertType("true || false", "Boolean"); assertType("null ?: false", "Boolean"); + assertType("new WithPredicate()?isValid()", "WithPredicate?"); + assertType("new WithPredicate()?isValid(1)", "WithPredicate?"); + assertType("new WithPredicate()?p", "WithPredicate?"); } private void assertSubtype(String type1, String type2) { @@ -500,7 +503,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase { "fun f(a : T) : Any {} " + "fun f(a : (Int, Int)) : T {} " + "fun f(a : E) : T {} " + - "}" + "}", + "class WithPredicate { " + + "fun isValid() : Boolean " + + "fun isValid(x : Int) : Boolean " + + "val p : Boolean " + + "}" }; private String[] FUNCTION_DECLARATIONS = { "fun f() : Unit {}",