KT-555 Parse error for generic function invocation
#KT-555 Fixed
This commit is contained in:
@@ -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))
|
||||
}
|
||||
@@ -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<*>()
|
||||
}
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user