KT-555 Parse error for generic function invocation

#KT-555 Fixed
This commit is contained in:
Andrey Breslav
2012-03-14 12:51:21 +04:00
parent 7adcecb634
commit 8019357bd5
7 changed files with 245 additions and 69 deletions
@@ -53,7 +53,9 @@ public class JetExpressionParsing extends AbstractJetParsing {
FUN_KEYWORD, FOR_KEYWORD, NULL_KEYWORD,
TRUE_KEYWORD, FALSE_KEYWORD, IS_KEYWORD, THROW_KEYWORD, RETURN_KEYWORD, BREAK_KEYWORD,
CONTINUE_KEYWORD, OBJECT_KEYWORD, IF_KEYWORD, TRY_KEYWORD, ELSE_KEYWORD, WHILE_KEYWORD, DO_KEYWORD,
WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS, MUL, PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
WHEN_KEYWORD, RBRACKET, RBRACE, RPAR, PLUSPLUS, MINUSMINUS,
// MUL,
PLUS, MINUS, EXCL, DIV, PERC, LTEQ,
// TODO GTEQ, foo<bar, baz>=x
EQEQEQ, EXCLEQEQEQ, EQEQ, EXCLEQ, ANDAND, OROR, SAFE_ACCESS, ELVIS,
SEMICOLON, RANGE, EQ, MULTEQ, DIVEQ, PERCEQ, PLUSEQ, MINUSEQ, NOT_IN, NOT_IS, //HASH,
@@ -385,13 +387,6 @@ public class JetExpressionParsing extends AbstractJetParsing {
expression.done(SAFE_ACCESS_EXPRESSION);
}
// else if (at(QUEST)) {
// advance(); // QUEST
//
// parseCallExpression();
//
// expression.done(PREDICATE_EXPRESSION);
// }
// else if (at(HASH)) {
// advance(); // HASH
//
@@ -426,31 +421,16 @@ public class JetExpressionParsing extends AbstractJetParsing {
parseCallWithClosure();
}
else if (at(LT)) {
// TODO: be (even) more clever
int gtPos = matchTokenStreamPredicate(new FirstBefore(
new At(GT),
new AtSet(TYPE_ARGUMENT_LIST_STOPPERS, TokenSet.create(RPAR, RBRACE, RBRACKET))
.or(new AtFirstTokenOfTokens(IDENTIFIER, LPAR)
// .or(new AtFirstTokenOfTokens(QUEST, IDENTIFIER))
)
) {
@Override
public boolean isTopLevel(int openAngleBrackets, int openBrackets, int openBraces, int openParentheses) {
return openAngleBrackets == 1 && openBrackets == 0 && openBraces == 0 && openParentheses == 0;
}
@Override
public boolean handleUnmatchedClosing(IElementType token) {
fail();
return true;
}
});
if (gtPos >= 0) {
myJetParsing.parseTypeArgumentList(gtPos);
PsiBuilder.Marker typeArgumentList = mark();
if (myJetParsing.tryParseTypeArgumentList(TYPE_ARGUMENT_LIST_STOPPERS)) {
typeArgumentList.done(TYPE_ARGUMENT_LIST);
if (!myBuilder.newlineBeforeCurrentToken() && at(LPAR)) parseValueArgumentList();
parseCallWithClosure();
}
else return false;
else {
typeArgumentList.rollbackTo();
return false;
}
}
else {
return false;
@@ -396,7 +396,7 @@ public class JetParsing extends AbstractJetParsing {
typeReference.done(TYPE_REFERENCE);
reference.done(CONSTRUCTOR_CALLEE);
parseTypeArgumentList(-1);
parseTypeArgumentList();
if (at(LPAR)) {
myExpressionParsing.parseValueArgumentList();
@@ -1295,11 +1295,17 @@ public class JetParsing extends AbstractJetParsing {
* : typeDescriptor "?"
*/
public void parseTypeRef() {
PsiBuilder.Marker typeRefMarker = parseTypeRefContents();
parseTypeRef(TokenSet.EMPTY);
}
public void parseTypeRef(TokenSet extraRecoverySet) {
PsiBuilder.Marker typeRefMarker = parseTypeRefContents(extraRecoverySet);
typeRefMarker.done(TYPE_REFERENCE);
}
private PsiBuilder.Marker parseTypeRefContents() {
// The extraRecoverySet is needed for the foo(bar<x, 1, y>(z)) case, to tell whether we should stop
// on expression-indicating symbols or not
private PsiBuilder.Marker parseTypeRefContents(TokenSet extraRecoverySet) {
// Disabling token merge is required for cases like
// Int?.(Foo) -> Bar
// we don't support this case now
@@ -1318,7 +1324,7 @@ public class JetParsing extends AbstractJetParsing {
// This may be a function parameter list or just a prenthesized type
advance(); // LPAR
parseTypeRefContents().drop(); // parenthesized types, no reference element around it is needed
parseTypeRefContents(TokenSet.EMPTY).drop(); // parenthesized types, no reference element around it is needed
if (at(RPAR)) {
advance(); // RPAR
@@ -1350,7 +1356,7 @@ public class JetParsing extends AbstractJetParsing {
else {
errorWithRecovery("Type expected",
TokenSet.orSet(TOPLEVEL_OBJECT_FIRST,
TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON)));
TokenSet.create(EQ, COMMA, GT, RBRACKET, DOT, RPAR, RBRACE, LBRACE, SEMICOLON), extraRecoverySet));
}
while (at(QUEST)) {
@@ -1409,7 +1415,7 @@ public class JetParsing extends AbstractJetParsing {
break;
}
parseTypeArgumentList(-1);
parseTypeArgumentList();
if (!at(DOT)) {
break;
}
@@ -1446,11 +1452,18 @@ public class JetParsing extends AbstractJetParsing {
/*
* (optionalProjection type){","}
*/
public PsiBuilder.Marker parseTypeArgumentList(int expectedGtOffset) {
public PsiBuilder.Marker parseTypeArgumentList() {
if (!at(LT)) return null;
PsiBuilder.Marker list = mark();
tryParseTypeArgumentList(TokenSet.EMPTY);
list.done(TYPE_ARGUMENT_LIST);
return list;
}
public boolean tryParseTypeArgumentList(TokenSet extraRecoverySet) {
myBuilder.disableNewlines();
advance(); // LT
@@ -1465,27 +1478,24 @@ public class JetParsing extends AbstractJetParsing {
if (at(MUL)) {
advance(); // MUL
} else {
parseTypeRef();
}
else {
parseTypeRef(extraRecoverySet);
}
projection.done(TYPE_PROJECTION);
if (!at(COMMA)) break;
advance(); // COMMA
}
if (expectedGtOffset >= 0 && myBuilder.getCurrentOffset() < expectedGtOffset) {
final PsiBuilder.Marker error = mark();
while (myBuilder.getCurrentOffset() < expectedGtOffset) {
advance();
}
error.error("Expecting a '>'");
boolean atGT = at(GT);
if (!atGT) {
error("Expecting a '>'");
}
else {
advance(); // GT
}
expect(GT, "Expecting a '>'");
myBuilder.restoreNewlinesState();
list.done(TYPE_ARGUMENT_LIST);
return list;
return atGT;
}
private void parseModifierListWithShortAnnotations(JetNodeType modifierList, TokenSet lookFor, TokenSet stopAt) {
@@ -22,8 +22,8 @@ import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import javax.inject.Inject;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.diagnostics.Errors;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.calls.autocasts.AutoCastServiceImpl;
@@ -40,6 +40,7 @@ import org.jetbrains.jet.lang.types.lang.JetStandardClasses;
import org.jetbrains.jet.lexer.JetToken;
import org.jetbrains.jet.lexer.JetTokens;
import javax.inject.Inject;
import java.util.*;
import static org.jetbrains.jet.lang.diagnostics.Errors.*;
@@ -632,6 +633,9 @@ public class CallResolver {
if (typeReference != null) {
typeArguments.add(typeResolver.resolveType(scope, typeReference, temporaryTrace, true));
}
else {
typeArguments.add(ErrorUtils.createErrorType("Star projection in a call"));
}
}
int expectedTypeArgumentCount = candidate.getTypeParameters().size();
if (expectedTypeArgumentCount == jetTypeArguments.size()) {
@@ -731,7 +735,13 @@ public class CallResolver {
}
for (JetTypeProjection typeProjection : call.getTypeArguments()) {
typeResolver.resolveType(scope, typeProjection.getTypeReference(), trace, true);
JetTypeReference typeReference = typeProjection.getTypeReference();
if (typeReference == null) {
trace.report(Errors.PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT.on(typeProjection));
}
else {
typeResolver.resolveType(scope, typeReference, trace, true);
}
}
}
@@ -958,8 +968,9 @@ public class CallResolver {
TypeParameterDescriptor typeParameterDescriptor = typeParameters.get(i);
JetType typeArgument = typeArguments.get(i);
JetTypeReference typeReference = jetTypeArguments.get(i).getTypeReference();
assert typeReference != null;
descriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
if (typeReference != null) {
descriptorResolver.checkBounds(typeReference, typeArgument, typeParameterDescriptor, substitutor, trace);
}
}
}
@@ -0,0 +1,13 @@
fun getT<T>() {}
fun getTT<A, B>() {}
fun getTTT<A, B, C>(<!UNUSED_PARAMETER!>x<!> : Any) {}
fun foo(<!UNUSED_PARAMETER!>a<!> : Any?) {}
open fun main() {
getT<<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>>()
<!UNRESOLVED_REFERENCE!>ggetT<!><<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>>()
getTT<<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>, <!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>>()
getTT<<!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>, Int>()
getTT<Int, <!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>>()
foo(getTTT<Int, <!PROJECTION_ON_NON_CLASS_TYPE_ARGUMENT!>*<!>, Int>(1))
}
+5
View File
@@ -27,4 +27,9 @@ fun foo() {
f(foo<a, b>(a))
f(foo<a, 1, b>(a))
f(foo<a, (1 + 2), b>(a))
f(foo<a, 1 + 2, b>(a))
f(foo<a, 1 * 2, b>(a))
f(foo<a, *, b>(a))
f(foo<a, "", b>(a))
foo<*>()
}
+162
View File
@@ -327,5 +327,167 @@ JetFile: FunctionCalls.jet
PsiElement(IDENTIFIER)('a')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('f')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
OPERATION_REFERENCE
PsiElement(LT)('<')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(PLUS)('+')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
OPERATION_REFERENCE
PsiElement(GT)('>')
PARENTHESIZED
PsiElement(LPAR)('(')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('f')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
OPERATION_REFERENCE
PsiElement(LT)('<')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
BINARY_EXPRESSION
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('1')
PsiWhiteSpace(' ')
OPERATION_REFERENCE
PsiElement(MUL)('*')
PsiWhiteSpace(' ')
INTEGER_CONSTANT
PsiElement(INTEGER_LITERAL)('2')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
OPERATION_REFERENCE
PsiElement(GT)('>')
PARENTHESIZED
PsiElement(LPAR)('(')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('f')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
TYPE_PROJECTION
PsiElement(MUL)('*')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
TYPE_PROJECTION
TYPE_REFERENCE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
PsiElement(GT)('>')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('f')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
OPERATION_REFERENCE
PsiElement(LT)('<')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
STRING_TEMPLATE
PsiElement(OPEN_QUOTE)('"')
PsiElement(CLOSING_QUOTE)('"')
PsiElement(COMMA)(',')
PsiWhiteSpace(' ')
VALUE_ARGUMENT
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('b')
OPERATION_REFERENCE
PsiElement(GT)('>')
PARENTHESIZED
PsiElement(LPAR)('(')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('a')
PsiElement(RPAR)(')')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('foo')
TYPE_ARGUMENT_LIST
PsiElement(LT)('<')
TYPE_PROJECTION
PsiElement(MUL)('*')
PsiElement(GT)('>')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n')
PsiElement(RBRACE)('}')
@@ -29,24 +29,19 @@ JetFile: TypeExpressionAmbiguities_ERR.jet
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
BINARY_EXPRESSION
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('fooo')
TYPE_ARGUMENT_LIST
OPERATION_REFERENCE
PsiElement(LT)('<')
TYPE_PROJECTION
TYPE_REFERENCE
NULLABLE_TYPE
USER_TYPE
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Double')
PsiElement(QUEST)('?')
PsiErrorElement:Expecting a '>'
PsiElement(IDENTIFIER)('addddd')
PsiElement(GT)('>')
VALUE_ARGUMENT_LIST
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
REFERENCE_EXPRESSION
PsiElement(IDENTIFIER)('Double')
PsiErrorElement:Unexpected tokens (use ';' to separate expressions on the same line)
PsiElement(QUEST)('?')
PsiElement(IDENTIFIER)('addddd')
PsiElement(GT)('>')
PsiElement(LPAR)('(')
PsiElement(RPAR)(')')
PsiWhiteSpace('\n ')
CALL_EXPRESSION
REFERENCE_EXPRESSION