mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Lambda expressions support: drop generic lambda expressions
This commit is contained in:
@@ -22,14 +22,6 @@ import org.jetbrains.annotations.Nullable;
|
||||
* Represents a Java lambda expression.
|
||||
*/
|
||||
public interface PsiLambdaExpression extends PsiExpression {
|
||||
/**
|
||||
* Returns this lambda expression's type parameter list (if any).
|
||||
*
|
||||
* @return type parameter list or null.
|
||||
*/
|
||||
@Nullable
|
||||
PsiTypeParameterList getTypeParameterList();
|
||||
|
||||
/**
|
||||
* Returns this lambda expression's parameter list.
|
||||
*
|
||||
|
||||
@@ -163,7 +163,7 @@ public class ExpressionParser {
|
||||
return parseBinary(builder, ExprType.UNARY, MULTIPLICATIVE_OPS);
|
||||
|
||||
case UNARY:
|
||||
return parseUnary(builder, false);
|
||||
return parseUnary(builder);
|
||||
|
||||
case TYPE:
|
||||
return myParser.getReferenceParser().parseType(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
|
||||
@@ -246,14 +246,14 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiBuilder.Marker parseUnary(final PsiBuilder builder, final boolean afterCast) {
|
||||
private PsiBuilder.Marker parseUnary(final PsiBuilder builder) {
|
||||
final IElementType tokenType = builder.getTokenType();
|
||||
|
||||
if (PREFIX_OPS.contains(tokenType)) {
|
||||
final PsiBuilder.Marker unary = builder.mark();
|
||||
builder.advanceLexer();
|
||||
|
||||
final PsiBuilder.Marker operand = parseUnary(builder, false);
|
||||
final PsiBuilder.Marker operand = parseUnary(builder);
|
||||
if (operand == null) {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
}
|
||||
@@ -269,19 +269,19 @@ public class ExpressionParser {
|
||||
myParser.getReferenceParser().parseTypeInfo(builder, ReferenceParser.EAT_LAST_DOT | ReferenceParser.WILDCARD);
|
||||
if (typeInfo == null || !expect(builder, JavaTokenType.RPARENTH)) {
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder, false);
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
|
||||
if (PREF_ARITHMETIC_OPS.contains(builder.getTokenType()) && !typeInfo.isPrimitive) {
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder, false);
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
|
||||
final PsiBuilder.Marker expr = parseUnary(builder, true);
|
||||
final PsiBuilder.Marker expr = parseUnary(builder);
|
||||
if (expr == null) {
|
||||
if (!typeInfo.isParameterized) { // cannot parse correct parenthesized expression after correct parameterized type
|
||||
typeCast.rollbackTo();
|
||||
return parsePostfix(builder, false);
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
else {
|
||||
error(builder, JavaErrorMessages.message("expected.expression"));
|
||||
@@ -292,13 +292,13 @@ public class ExpressionParser {
|
||||
return typeCast;
|
||||
}
|
||||
else {
|
||||
return parsePostfix(builder, afterCast);
|
||||
return parsePostfix(builder);
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiBuilder.Marker parsePostfix(final PsiBuilder builder, final boolean afterCast) {
|
||||
PsiBuilder.Marker operand = parsePrimary(builder, null, -1, afterCast);
|
||||
private PsiBuilder.Marker parsePostfix(final PsiBuilder builder) {
|
||||
PsiBuilder.Marker operand = parsePrimary(builder, null, -1);
|
||||
if (operand == null) return null;
|
||||
|
||||
while (POSTFIX_OPS.contains(builder.getTokenType())) {
|
||||
@@ -315,13 +315,10 @@ public class ExpressionParser {
|
||||
|
||||
// todo[r.sh] make 'this', 'super' and 'class' reference expressions
|
||||
@Nullable
|
||||
private PsiBuilder.Marker parsePrimary(final PsiBuilder builder,
|
||||
@Nullable final BreakPoint breakPoint,
|
||||
final int breakOffset,
|
||||
final boolean afterCast) {
|
||||
private PsiBuilder.Marker parsePrimary(final PsiBuilder builder, @Nullable final BreakPoint breakPoint, final int breakOffset) {
|
||||
PsiBuilder.Marker startMarker = builder.mark();
|
||||
|
||||
PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder, afterCast);
|
||||
PsiBuilder.Marker expr = parsePrimaryExpressionStart(builder);
|
||||
if (expr == null) {
|
||||
startMarker.drop();
|
||||
return null;
|
||||
@@ -349,7 +346,7 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
|
||||
if (classObjAccess == null || builder.getCurrentOffset() < offset) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, BreakPoint.P1, offset, false);
|
||||
return parsePrimary(builder, BreakPoint.P1, offset);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
@@ -373,13 +370,13 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker ref = myParser.getReferenceParser().parseJavaCodeReference(builder, false, true, false, false, false);
|
||||
if (ref == null || builder.getTokenType() != JavaTokenType.DOT || builder.getCurrentOffset() != dotOffset) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, BreakPoint.P2, offset, false);
|
||||
return parsePrimary(builder, BreakPoint.P2, offset);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
if (builder.getTokenType() != dotTokenType) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, BreakPoint.P2, offset, false);
|
||||
return parsePrimary(builder, BreakPoint.P2, offset);
|
||||
}
|
||||
builder.advanceLexer();
|
||||
|
||||
@@ -420,7 +417,7 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker copy = startMarker.precede();
|
||||
startMarker.rollbackTo();
|
||||
|
||||
final PsiBuilder.Marker qualifier = parsePrimaryExpressionStart(builder, false);
|
||||
final PsiBuilder.Marker qualifier = parsePrimaryExpressionStart(builder);
|
||||
if (qualifier != null) {
|
||||
final PsiBuilder.Marker refExpr = qualifier.precede();
|
||||
if (builder.getTokenType() == JavaTokenType.DOT) {
|
||||
@@ -436,7 +433,7 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, BreakPoint.P3, -1, false);
|
||||
return parsePrimary(builder, BreakPoint.P3, -1);
|
||||
}
|
||||
else {
|
||||
startMarker.drop();
|
||||
@@ -465,7 +462,7 @@ public class ExpressionParser {
|
||||
final PsiBuilder.Marker classObjAccess = parseClassAccessOrMethodReference(builder);
|
||||
if (classObjAccess == null || builder.getCurrentOffset() <= pos) {
|
||||
copy.rollbackTo();
|
||||
return parsePrimary(builder, BreakPoint.P4, -1, false);
|
||||
return parsePrimary(builder, BreakPoint.P4, -1);
|
||||
}
|
||||
|
||||
startMarker = copy;
|
||||
@@ -505,7 +502,7 @@ public class ExpressionParser {
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder, final boolean afterCast) {
|
||||
private PsiBuilder.Marker parsePrimaryExpressionStart(final PsiBuilder builder) {
|
||||
IElementType tokenType = builder.getTokenType();
|
||||
|
||||
if (LITERALS.contains(tokenType)) {
|
||||
@@ -597,29 +594,6 @@ public class ExpressionParser {
|
||||
if (tokenType == JavaTokenType.LT) {
|
||||
expr = builder.mark();
|
||||
|
||||
if (!afterCast) {
|
||||
final PsiBuilder.Marker typeParams = myParser.getReferenceParser().parseTypeParameters(builder, true);
|
||||
|
||||
if (typeParams != null) {
|
||||
tokenType = builder.getTokenType();
|
||||
|
||||
PsiBuilder.Marker lambda = null;
|
||||
if (tokenType == JavaTokenType.LPARENTH) {
|
||||
lambda = parseLambdaAfterParenth(builder, typeParams);
|
||||
}
|
||||
else if (tokenType == JavaTokenType.IDENTIFIER && builder.lookAhead(1) == JavaTokenType.ARROW) {
|
||||
lambda = parseLambdaExpression(builder, false, typeParams);
|
||||
}
|
||||
if (lambda != null) {
|
||||
expr.drop();
|
||||
return lambda;
|
||||
}
|
||||
|
||||
expr.rollbackTo();
|
||||
expr = builder.mark();
|
||||
}
|
||||
}
|
||||
|
||||
if (!myParser.getReferenceParser().parseReferenceParameterList(builder, false, false)) {
|
||||
expr.rollbackTo();
|
||||
return null;
|
||||
|
||||
@@ -297,13 +297,6 @@ public class ReferenceParser {
|
||||
|
||||
@NotNull
|
||||
public PsiBuilder.Marker parseTypeParameters(final PsiBuilder builder) {
|
||||
final PsiBuilder.Marker marker = parseTypeParameters(builder, false);
|
||||
assert marker != null;
|
||||
return marker;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public PsiBuilder.Marker parseTypeParameters(final PsiBuilder builder, final boolean stopOnErrors) {
|
||||
final PsiBuilder.Marker list = builder.mark();
|
||||
if (!expect(builder, JavaTokenType.LT)) {
|
||||
list.done(JavaElementType.TYPE_PARAMETER_LIST);
|
||||
@@ -313,10 +306,6 @@ public class ReferenceParser {
|
||||
while (true) {
|
||||
final PsiBuilder.Marker param = parseTypeParameter(builder);
|
||||
if (param == null) {
|
||||
if (stopOnErrors) {
|
||||
list.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
error(builder, JavaErrorMessages.message("expected.type.parameter"));
|
||||
}
|
||||
if (!expect(builder, JavaTokenType.COMMA)) {
|
||||
@@ -325,11 +314,6 @@ public class ReferenceParser {
|
||||
}
|
||||
|
||||
if (!expect(builder, JavaTokenType.GT)) {
|
||||
if (stopOnErrors) {
|
||||
list.rollbackTo();
|
||||
return null;
|
||||
}
|
||||
|
||||
// hack for completion
|
||||
if (builder.getTokenType() == JavaTokenType.IDENTIFIER) {
|
||||
if (builder.lookAhead(1) == JavaTokenType.GT) {
|
||||
|
||||
@@ -187,7 +187,7 @@ public class PsiImplUtil {
|
||||
final boolean fromBody = lastParent instanceof PsiCodeBlock;
|
||||
final PsiTypeParameterList typeParameterList = method.getTypeParameterList();
|
||||
final PsiParameterList parameterList = method.getParameterList();
|
||||
return processDeclarationsInMethodLike(method, processor, state, fromBody, place, typeParameterList, parameterList);
|
||||
return processDeclarationsInMethodLike(method, processor, state, place, fromBody, typeParameterList, parameterList);
|
||||
}
|
||||
|
||||
public static boolean processDeclarationsInLambda(@NotNull final PsiLambdaExpression lambda,
|
||||
@@ -196,23 +196,24 @@ public class PsiImplUtil {
|
||||
final PsiElement lastParent,
|
||||
@NotNull final PsiElement place) {
|
||||
final boolean fromBody = lastParent != null && lastParent == lambda.getBody();
|
||||
final PsiTypeParameterList typeParameterList = lambda.getTypeParameterList();
|
||||
final PsiParameterList parameterList = lambda.getParameterList();
|
||||
return processDeclarationsInMethodLike(lambda, processor, state, fromBody, place, typeParameterList, parameterList);
|
||||
return processDeclarationsInMethodLike(lambda, processor, state, place, fromBody, null, parameterList);
|
||||
}
|
||||
|
||||
private static boolean processDeclarationsInMethodLike(@NotNull final PsiElement element,
|
||||
@NotNull final PsiScopeProcessor processor,
|
||||
@NotNull final ResolveState state,
|
||||
final boolean fromBody,
|
||||
@NotNull final PsiElement place,
|
||||
final boolean fromBody,
|
||||
@Nullable final PsiTypeParameterList typeParameterList,
|
||||
@NotNull final PsiParameterList parameterList) {
|
||||
processor.handleEvent(PsiScopeProcessor.Event.SET_DECLARATION_HOLDER, element);
|
||||
|
||||
final ElementClassHint hint = processor.getHint(ElementClassHint.KEY);
|
||||
if (hint == null || hint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
|
||||
if (typeParameterList != null && !typeParameterList.processDeclarations(processor, state, null, place)) return false;
|
||||
if (typeParameterList != null) {
|
||||
final ElementClassHint hint = processor.getHint(ElementClassHint.KEY);
|
||||
if (hint == null || hint.shouldProcess(ElementClassHint.DeclarationKind.CLASS)) {
|
||||
if (!typeParameterList.processDeclarations(processor, state, null, place)) return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (fromBody) {
|
||||
|
||||
-6
@@ -27,12 +27,6 @@ public class PsiLambdaExpressionImpl extends ExpressionPsiElement implements Psi
|
||||
super(JavaElementType.LAMBDA_EXPRESSION);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PsiTypeParameterList getTypeParameterList() {
|
||||
final PsiElement element = getFirstChild();
|
||||
return element instanceof PsiTypeParameterList ? (PsiTypeParameterList)element : null;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiParameterList getParameterList() {
|
||||
|
||||
-5
@@ -26,16 +26,11 @@ class C {
|
||||
int parse(String s);
|
||||
}
|
||||
|
||||
interface ListProducer<T> {
|
||||
List<T> produce();
|
||||
}
|
||||
|
||||
void test() {
|
||||
Simplest simplest = <weak_warning descr="Lambda expressions type check is not yet implemented">() -> { }</weak_warning>;
|
||||
use(<weak_warning descr="Lambda expressions type check is not yet implemented">() -> { }</weak_warning>);
|
||||
|
||||
IntParser intParser = <weak_warning descr="Lambda expressions type check is not yet implemented">(String s) -> Integer.parseInt(s)</weak_warning>;
|
||||
ListProducer<String> listProducer = <weak_warning descr="Lambda expressions type check is not yet implemented"><T>() -> new ArrayList<T>()</weak_warning>;
|
||||
}
|
||||
|
||||
Runnable foo() {
|
||||
|
||||
@@ -1,33 +1,18 @@
|
||||
PsiJavaFile:LambdaExpression12.java
|
||||
PsiLambdaExpression:<T>() -> new C<T>()
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiParameterList:()
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:LT('<')
|
||||
PsiIdentifier:T('T')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiNewExpression:new C<T>()
|
||||
PsiKeyword:new('new')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaCodeReferenceElement:C<T>
|
||||
PsiIdentifier:C('C')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:T
|
||||
PsiJavaCodeReferenceElement:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiKeyword:new('new')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:C('C')
|
||||
PsiJavaToken:LT('<')
|
||||
PsiIdentifier:T('T')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
@@ -1,21 +1,10 @@
|
||||
PsiJavaFile:LambdaExpression13.java
|
||||
PsiLambdaExpression:<T>t -> t
|
||||
PsiTypeParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeParameter:T
|
||||
PsiIdentifier:T('T')
|
||||
PsiElement(EXTENDS_BOUND_LIST)
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiParameterList:t
|
||||
PsiParameter:t
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiIdentifier:t('t')
|
||||
PsiErrorElement:Unparsed tokens
|
||||
PsiJavaToken:LT('<')
|
||||
PsiIdentifier:T('T')
|
||||
PsiJavaToken:GT('>')
|
||||
PsiIdentifier:t('t')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiReferenceExpression:t
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:t('t')
|
||||
PsiIdentifier:t('t')
|
||||
+2
-2
@@ -134,8 +134,8 @@ public class ExpressionParserTest extends JavaParsingTestCase {
|
||||
public void testLambdaExpression9() { doParserTest("(I)p -> null"); }
|
||||
public void testLambdaExpression10() { doParserTest("(I)(p -> null)"); }
|
||||
public void testLambdaExpression11() { doParserTest("() -> { }"); }
|
||||
public void testLambdaExpression12() { doParserTest("<T>() -> new C<T>()"); }
|
||||
public void testLambdaExpression13() { doParserTest("<T>t -> t"); }
|
||||
public void testLambdaExpression12() { doParserTest("<T>() -> new C<T>()"); } // these two expressions
|
||||
public void testLambdaExpression13() { doParserTest("<T>t -> t"); } // should no longer be parsed
|
||||
public void testLambdaExpression14() { doParserTest("(String t) -> t"); }
|
||||
public void testLambdaExpression15() { doParserTest("(int a, int b) -> a + b"); }
|
||||
public void testLambdaExpression16() { doParserTest("(final int x) -> x"); }
|
||||
|
||||
Reference in New Issue
Block a user