Support for a?b
This commit is contained in:
@@ -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 {}",
|
||||||
|
|||||||
Reference in New Issue
Block a user