mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-06 11:50:54 +07:00
Constructor references with type parameters are not recognized as PsiMethodReferenceExpression
StatementParser used to ignore type parameters to constructor references and it prevents the tokens of such statements from being grouped under the PsiMethodReferenceExpression node in the PSI tree. Since constructor references can have type parameters one might look like a variable declaration. The parser didn't take this fact into account and fails due to "::" after closing ">" of type arguments. This patch adds a new check in StatementParser#parseStatement after the attempt of parsing of a declaration statement fails to see if the type declaration follows by "::" which is a marker that the examined line might be a constructor reference. Signed-off-by: Nikita Eshkeev <neshkeev@yandex.ru> GitOrigin-RevId: 968f4884c45c922ce2fd6a8e3614cca01423d5b3
This commit is contained in:
committed by
intellij-monorepo-bot
parent
b6c9e5cce3
commit
707933fffd
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.lang.java.parser;
|
||||
|
||||
import com.intellij.codeInsight.daemon.JavaErrorBundle;
|
||||
@@ -160,16 +160,31 @@ public class StatementParser {
|
||||
skipQualifiedName(builder);
|
||||
IElementType suspectedLT = builder.getTokenType(), next = builder.lookAhead(1);
|
||||
refPos.rollbackTo();
|
||||
|
||||
if (suspectedLT == JavaTokenType.LT || suspectedLT == JavaTokenType.DOT && next == JavaTokenType.AT) {
|
||||
final boolean constructorRef;
|
||||
|
||||
PsiBuilder.Marker declStatement = builder.mark();
|
||||
PsiBuilder.Marker decl = myParser.getDeclarationParser().parse(builder, DeclarationParser.Context.CODE_BLOCK);
|
||||
|
||||
if (decl == null) {
|
||||
PsiBuilder.Marker marker = myParser.getReferenceParser().parseType(builder, 0);
|
||||
error(builder, JavaErrorBundle.message("expected.identifier"));
|
||||
if (marker == null) builder.advanceLexer();
|
||||
// if the type declaration ends with "::" then it is a method reference to a constructor
|
||||
constructorRef = builder.getTokenType() == JavaTokenType.DOUBLE_COLON;
|
||||
if (!constructorRef) {
|
||||
error(builder, JavaErrorBundle.message("expected.identifier"));
|
||||
if (marker == null) builder.advanceLexer();
|
||||
}
|
||||
}
|
||||
done(declStatement, JavaElementType.DECLARATION_STATEMENT);
|
||||
return declStatement;
|
||||
else {
|
||||
constructorRef = false;
|
||||
}
|
||||
|
||||
if (!constructorRef) {
|
||||
done(declStatement, JavaElementType.DECLARATION_STATEMENT);
|
||||
return declStatement;
|
||||
}
|
||||
declStatement.rollbackTo();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
PsiJavaFile:ConstructorRef.java
|
||||
PsiExpressionStatement
|
||||
PsiMethodReferenceExpression
|
||||
PsiReferenceExpression:Foo
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:Foo('Foo')
|
||||
PsiJavaToken:DOUBLE_COLON('::')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:new('new')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
@@ -0,0 +1,20 @@
|
||||
PsiJavaFile:ConstructorWithTypeParamsRef.java
|
||||
PsiExpressionStatement
|
||||
PsiMethodReferenceExpression
|
||||
PsiTypeElement:Foo<Integer>
|
||||
PsiJavaCodeReferenceElement:Foo<Integer>
|
||||
PsiIdentifier:Foo('Foo')
|
||||
PsiReferenceParameterList
|
||||
PsiJavaToken:LT('<')
|
||||
PsiTypeElement:Integer
|
||||
PsiJavaCodeReferenceElement:Integer
|
||||
PsiIdentifier:Integer('Integer')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiJavaToken:GT('>')
|
||||
PsiJavaToken:DOUBLE_COLON('::')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiKeyword:new('new')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.java.parser.partial;
|
||||
|
||||
import com.intellij.java.parser.JavaParsingTestCase;
|
||||
@@ -185,6 +185,9 @@ public class StatementParserTest extends JavaParsingTestCase {
|
||||
public void testWhileIncomplete4() { doParserTest("while(cond)"); }
|
||||
public void testWhileIncomplete5() { doParserTest("while() foo();"); }
|
||||
|
||||
public void testConstructorRef() { doParserTest("Foo::new"); }
|
||||
public void testConstructorWithTypeParamsRef() { doParserTest("Foo<Integer>::new"); }
|
||||
|
||||
private void doBlockParserTest(String text) {
|
||||
doParserTest(text, builder -> JavaParser.INSTANCE.getStatementParser().parseCodeBlockDeep(builder, true));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user