JET-39 Process ?. correctly in the receiver types

This commit is contained in:
Andrey Breslav
2011-05-21 14:00:18 +04:00
parent caad86e880
commit 9d123b5c4f
4 changed files with 59 additions and 14 deletions
@@ -862,23 +862,39 @@ public class JetParsing extends AbstractJetParsing {
return FUN; return FUN;
} }
boolean parameterListOccured = false; boolean typeParameterListOccured = false;
if (at(LT)) { if (at(LT)) {
parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR)); parseTypeParameterList(TokenSet.create(LBRACKET, LBRACE, LPAR));
parameterListOccured = true; typeParameterListOccured = true;
} }
TokenSet receiverTypeTerminators = TokenSet.create(DOT, SAFE_ACCESS);
int lastDot = findLastBefore(TokenSet.create(DOT), TokenSet.create(LPAR), true); int lastDot = findLastBefore(receiverTypeTerminators, TokenSet.create(LPAR), true);
if (lastDot == -1) { // There's no explicit receiver type specified if (lastDot == -1) { // There's no explicit receiver type specified
parseAttributeList(); parseAttributeList();
expect(IDENTIFIER, "Expecting function name or receiver type"); expect(IDENTIFIER, "Expecting function name or receiver type");
} else { } else {
createTruncatedBuilder(lastDot).parseTypeRef(); PsiBuilder.Marker typeRefMarker = mark();
PsiBuilder.Marker nullableType = mark();
typeRefMarker = createTruncatedBuilder(lastDot).parseTypeRefContents(typeRefMarker);
if (at(SAFE_ACCESS)) {
nullableType.done(NULLABLE_TYPE);
}
else {
nullableType.drop();
}
typeRefMarker.done(TYPE_REFERENCE);
TokenSet functionNameFollow = TokenSet.create(LT, LPAR, COLON, EQ); TokenSet functionNameFollow = TokenSet.create(LT, LPAR, COLON, EQ);
expect(DOT, "Expecting '.' before a function name", functionNameFollow); if (atSet(receiverTypeTerminators)) {
advance(); // expectation
}
else {
errorWithRecovery("Expecting '.' before a function name", functionNameFollow);
}
// expect(DOT, "Expecting '.' before a function name", functionNameFollow);
expect(IDENTIFIER, "Expecting function name", functionNameFollow); expect(IDENTIFIER, "Expecting function name", functionNameFollow);
} }
@@ -887,7 +903,7 @@ public class JetParsing extends AbstractJetParsing {
if (at(LT)) { if (at(LT)) {
PsiBuilder.Marker error = mark(); PsiBuilder.Marker error = mark();
parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow)); parseTypeParameterList(TokenSet.orSet(TokenSet.create(LPAR), valueParametersFollow));
if (parameterListOccured) { if (typeParameterListOccured) {
error.error("Only one type parameter list is allowed for a function"); // TODO : discuss error.error("Only one type parameter list is allowed for a function"); // TODO : discuss
} }
else { else {
@@ -1158,8 +1174,10 @@ public class JetParsing extends AbstractJetParsing {
* : typeDescriptor "?" * : typeDescriptor "?"
*/ */
public void parseTypeRef() { public void parseTypeRef() {
PsiBuilder.Marker type = mark(); parseTypeRefContents(mark()).done(TYPE_REFERENCE);
}
private PsiBuilder.Marker parseTypeRefContents(PsiBuilder.Marker typeRefMarker) {
parseAttributeList(); parseAttributeList();
if (at(IDENTIFIER) || at(NAMESPACE_KEYWORD)) { if (at(IDENTIFIER) || at(NAMESPACE_KEYWORD)) {
@@ -1181,14 +1199,14 @@ public class JetParsing extends AbstractJetParsing {
} }
while (at(QUEST)) { while (at(QUEST)) {
PsiBuilder.Marker precede = type.precede(); PsiBuilder.Marker precede = typeRefMarker.precede();
advance(); // QUEST advance(); // QUEST
type.done(NULLABLE_TYPE); typeRefMarker.done(NULLABLE_TYPE);
type = precede; typeRefMarker = precede;
} }
type.done(TYPE_REFERENCE); return typeRefMarker;
} }
/* /*
@@ -1425,7 +1425,9 @@ public class JetTypeInferrer {
trace.getErrorHandler().genericWarning(expression.getNode(), "Expression always evaluates to false"); // TODO : make an error? trace.getErrorHandler().genericWarning(expression.getNode(), "Expression always evaluates to false"); // TODO : make an error?
} }
} }
}
else {
trace.getErrorHandler().genericError(pattern.getNode(), "Unsupported [JetTypeInferrer]");
} }
result = semanticServices.getStandardLibrary().getBooleanType(); result = semanticServices.getStandardLibrary().getBooleanType();
} }
+2
View File
@@ -21,3 +21,5 @@ fun [a()] T.foo<T : {(a) : b}>(a : foo) : bar {}
fun [a] {[a] T<T>.(A<B>) : ()}.foo() {} fun [a] {[a] T<T>.(A<B>) : ()}.foo() {}
fun [a()] T.foo<T : [a] {(a) : b}>(a : foo) : bar {} fun [a()] T.foo<T : [a] {(a) : b}>(a : foo) : bar {}
fun A?.foo() : bar?
+24 -1
View File
@@ -813,4 +813,27 @@ JetFile: Functions.jet
PsiWhiteSpace(' ') PsiWhiteSpace(' ')
BLOCK BLOCK
PsiElement(LBRACE)('{') PsiElement(LBRACE)('{')
PsiElement(RBRACE)('}') PsiElement(RBRACE)('}')
PsiWhiteSpace('\n\n')
FUN
PsiElement(fun)('fun')
PsiWhiteSpace(' ')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('A')
PsiElement(SAFE_ACCESS)('?.')
PsiElement(IDENTIFIER)('foo')
VALUE_PARAMETER_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace(' ')
PsiElement(COLON)(':')
PsiWhiteSpace(' ')
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('bar')
PsiElement(QUEST)('?')