Support for a?b

This commit is contained in:
Andrey Breslav
2011-03-16 20:42:14 +03:00
parent 955faa350f
commit b46543b872
4 changed files with 41 additions and 35 deletions
@@ -409,7 +409,7 @@ public class JetExpressionParsing extends AbstractJetParsing {
private void parseCallExpression() { private void parseCallExpression() {
PsiBuilder.Marker mark = mark(); PsiBuilder.Marker mark = mark();
parseAtomicExpression(); parseAtomicExpression();
if (parseCallSuffix()) { if (!myBuilder.newlineBeforeCurrentToken() && parseCallSuffix()) {
mark.done(CALL_EXPRESSION); mark.done(CALL_EXPRESSION);
} }
else { else {
@@ -45,7 +45,7 @@ public class JetChangeUtil {
JetFile file = createFile(project, text); JetFile file = createFile(project, text);
JetNamespace rootNamespace = file.getRootNamespace(); JetNamespace rootNamespace = file.getRootNamespace();
List<JetDeclaration> dcls = rootNamespace.getDeclarations(); List<JetDeclaration> dcls = rootNamespace.getDeclarations();
assert dcls.size() == 1; assert dcls.size() == 1 : dcls.size();
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
T result = (T) dcls.get(0); T result = (T) dcls.get(0);
return result; return result;
@@ -543,24 +543,6 @@ public class JetTypeInferrer {
throw new UnsupportedOperationException(); // TODO 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 @Override
public void visitQualifiedExpression(JetQualifiedExpression expression) { public void visitQualifiedExpression(JetQualifiedExpression expression) {
// TODO : functions // TODO : functions
@@ -569,30 +551,45 @@ public class JetTypeInferrer {
JetType receiverType = getType(scope, receiverExpression, false); JetType receiverType = getType(scope, receiverExpression, false);
if (receiverType != null) { if (receiverType != null) {
checkNullSafety(receiverType, expression); checkNullSafety(receiverType, expression);
JetScope compositeScope = new ScopeWithReceiver(scope, receiverType); JetType selectorReturnType = getSelectorReturnType(receiverType, selectorExpression);
if (selectorExpression instanceof JetCallExpression) { if (expression.getOperationSign() == JetTokens.QUEST) {
JetCallExpression callExpression = (JetCallExpression) selectorExpression; if (selectorReturnType != null && !isBoolean(selectorReturnType)) {
OverloadDomain overloadDomain = getOverloadDomain(compositeScope, callExpression.getCalleeExpression()); // TODO : more comprehensible error message
resolveOverloads(scope, callExpression, overloadDomain); semanticServices.getErrorHandler().typeMismatch(selectorExpression, semanticServices.getStandardLibrary().getBooleanType(), selectorReturnType);
}
result = TypeUtils.makeNullable(receiverType);
} }
else if (selectorExpression instanceof JetSimpleNameExpression) { else {
result = getType(compositeScope, selectorExpression, false); result = selectorReturnType;
}
else if (selectorExpression != null) {
// TODO : not a simple name -> resolve in scope, expect property type or a function type
throw new UnsupportedOperationException();
} }
} }
} }
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 @Override
public void visitCallExpression(JetCallExpression expression) { public void visitCallExpression(JetCallExpression expression) {
JetExpression calleeExpression = expression.getCalleeExpression(); JetExpression calleeExpression = expression.getCalleeExpression();
OverloadDomain overloadDomain = getOverloadDomain(scope, calleeExpression); 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 // 1) ends with a name -> (scope, name) to look up
// 2) ends with something else -> just check types // 2) ends with something else -> just check types
@@ -640,9 +637,10 @@ public class JetTypeInferrer {
FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes); FunctionDescriptor functionDescriptor = overloadDomain.getFunctionDescriptorForPositionedArguments(types, valueArgumentTypes);
if (functionDescriptor != null) { if (functionDescriptor != null) {
result = functionDescriptor.getUnsubstitutedReturnType(); return functionDescriptor.getUnsubstitutedReturnType();
} }
} }
return null;
} }
@Override @Override
@@ -406,6 +406,9 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
assertType("true && false", "Boolean"); assertType("true && false", "Boolean");
assertType("true || false", "Boolean"); assertType("true || false", "Boolean");
assertType("null ?: 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) { private void assertSubtype(String type1, String type2) {
@@ -500,7 +503,12 @@ public class JetTypeCheckerTest extends LightDaemonAnalyzerTestCase {
"fun f(a : T) : Any {} " + "fun f(a : T) : Any {} " +
"fun f(a : (Int, Int)) : T {} " + "fun f(a : (Int, Int)) : T {} " +
"fun f<E>(a : E) : T {} " + "fun f<E>(a : E) : T {} " +
"}" "}",
"class WithPredicate { " +
"fun isValid() : Boolean " +
"fun isValid(x : Int) : Boolean " +
"val p : Boolean " +
"}"
}; };
private String[] FUNCTION_DECLARATIONS = { private String[] FUNCTION_DECLARATIONS = {
"fun f() : Unit {}", "fun f() : Unit {}",