diff --git a/java/java-frontback-tests/testSrc/com/intellij/java/parser/declarationParsing/AbstractBasicClassParsingTest.java b/java/java-frontback-tests/testSrc/com/intellij/java/parser/declarationParsing/AbstractBasicClassParsingTest.java index 6563e4df0b3a..282f3f5a0ef1 100644 --- a/java/java-frontback-tests/testSrc/com/intellij/java/parser/declarationParsing/AbstractBasicClassParsingTest.java +++ b/java/java-frontback-tests/testSrc/com/intellij/java/parser/declarationParsing/AbstractBasicClassParsingTest.java @@ -81,6 +81,7 @@ public abstract class AbstractBasicClassParsingTest extends AbstractBasicJavaPar } public void testValueClass() { doTest(true); } + public void testNoSoftKeywordInLambdaParameters() { doTest(true); } public void testSealedInterface() { doTest(true); } public void testSealedClassOldLanguageLevel() { diff --git a/java/java-syntax/src/com/intellij/java/syntax/element/SyntaxElementTypes.kt b/java/java-syntax/src/com/intellij/java/syntax/element/SyntaxElementTypes.kt index 702ff962b678..fcd0e3680434 100644 --- a/java/java-syntax/src/com/intellij/java/syntax/element/SyntaxElementTypes.kt +++ b/java/java-syntax/src/com/intellij/java/syntax/element/SyntaxElementTypes.kt @@ -43,6 +43,11 @@ object SyntaxElementTypes { JToken.VOLATILE_KEYWORD, JToken.DEFAULT_KEYWORD, JToken.SEALED_KEYWORD, JToken.NON_SEALED_KEYWORD, JToken.VALUE_KEYWORD ) + // While only 'final' modifier is acceptable in the (method or lambda) parameter modifier list, we still parse any modifier, + // except the soft ones, as they should be parsed as variable name in lambda parameter list. + val PARAMETER_MODIFIER_BIT_SET: SyntaxElementTypeSet = + MODIFIER_BIT_SET - setOf(JToken.SEALED_KEYWORD, JToken.NON_SEALED_KEYWORD, JToken.VALUE_KEYWORD) + val PRIMITIVE_TYPE_BIT_SET: SyntaxElementTypeSet = syntaxElementTypeSetOf( JToken.BOOLEAN_KEYWORD, JToken.BYTE_KEYWORD, JToken.SHORT_KEYWORD, JToken.INT_KEYWORD, JToken.LONG_KEYWORD, JToken.CHAR_KEYWORD, JToken.FLOAT_KEYWORD, JToken.DOUBLE_KEYWORD, JToken.VOID_KEYWORD diff --git a/java/java-syntax/src/com/intellij/java/syntax/parser/DeclarationParser.kt b/java/java-syntax/src/com/intellij/java/syntax/parser/DeclarationParser.kt index b0b52c4e8d83..69f5091463f1 100644 --- a/java/java-syntax/src/com/intellij/java/syntax/parser/DeclarationParser.kt +++ b/java/java-syntax/src/com/intellij/java/syntax/parser/DeclarationParser.kt @@ -8,6 +8,7 @@ import com.intellij.java.syntax.element.JavaSyntaxTokenType import com.intellij.java.syntax.element.SyntaxElementTypes.CLASS_KEYWORD_BIT_SET import com.intellij.java.syntax.element.SyntaxElementTypes.KEYWORD_BIT_SET import com.intellij.java.syntax.element.SyntaxElementTypes.MODIFIER_BIT_SET +import com.intellij.java.syntax.element.SyntaxElementTypes.PARAMETER_MODIFIER_BIT_SET import com.intellij.java.syntax.element.SyntaxElementTypes.PRIMITIVE_TYPE_BIT_SET import com.intellij.platform.syntax.SyntaxElementType import com.intellij.platform.syntax.SyntaxElementTypeSet @@ -423,11 +424,11 @@ open class DeclarationParser(private val myParser: JavaParser) { while (true) { var tokenType = builder.tokenType ?: break - if (isValueToken(builder, tokenType)) { + if (isValueToken(builder, tokenType) && modifiers.contains(JavaSyntaxTokenType.VALUE_KEYWORD)) { builder.remapCurrentToken(JavaSyntaxTokenType.VALUE_KEYWORD) tokenType = JavaSyntaxTokenType.VALUE_KEYWORD } - else if (isSealedToken(builder, tokenType)) { + else if (isSealedToken(builder, tokenType) && modifiers.contains(JavaSyntaxTokenType.SEALED_KEYWORD)) { builder.remapCurrentToken(JavaSyntaxTokenType.SEALED_KEYWORD) tokenType = JavaSyntaxTokenType.SEALED_KEYWORD } @@ -697,7 +698,8 @@ open class DeclarationParser(private val myParser: JavaParser) { ): SyntaxTreeBuilder.Marker? { val param = builder.mark() - val modListInfo = parseModifierList(builder) + val modListInfo = parseModifierList( + builder, if (type === JavaSyntaxElementType.PARAMETER) PARAMETER_MODIFIER_BIT_SET else MODIFIER_BIT_SET) val typeInfo: ReferenceParser.TypeInfo? if (typed) { diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.java b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.java new file mode 100644 index 000000000000..e5c85a468c97 --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.java @@ -0,0 +1,12 @@ +public class ValueInLambda { + void test() { + Fn fn = value -> value; + Fn fn2 = (value) -> value; + Fn fn3 = (int value) -> value; + Fn fn4 = sealed -> sealed; + } + + interface Fn { + int x(int y); + } +} \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.txt new file mode 100644 index 000000000000..eef4ea3b27fc --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters.txt @@ -0,0 +1,203 @@ +PsiJavaFile:NoSoftKeywordInLambdaParameters.java + PsiImportList + + PsiClass:ValueInLambda + PsiModifierList:public + PsiKeyword:public('public') + PsiWhiteSpace(' ') + PsiKeyword:class('class') + PsiWhiteSpace(' ') + PsiIdentifier:ValueInLambda('ValueInLambda') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiMethod:test + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:void + PsiKeyword:void('void') + PsiWhiteSpace(' ') + PsiIdentifier:test('test') + PsiParameterList:() + PsiJavaToken:LPARENTH('(') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiWhiteSpace(' ') + PsiCodeBlock + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiDeclarationStatement + PsiLocalVariable:fn + PsiModifierList: + + PsiTypeElement:Fn + PsiJavaCodeReferenceElement:Fn + PsiIdentifier:Fn('Fn') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:fn('fn') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression + PsiParameterList:value + PsiParameter:value + PsiModifierList: + + PsiIdentifier:value('value') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiReferenceExpression:value + PsiReferenceParameterList + + PsiIdentifier:value('value') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n ') + PsiDeclarationStatement + PsiLocalVariable:fn2 + PsiModifierList: + + PsiTypeElement:Fn + PsiJavaCodeReferenceElement:Fn + PsiIdentifier:Fn('Fn') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:fn2('fn2') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression + PsiParameterList:(value) + PsiJavaToken:LPARENTH('(') + PsiParameter:value + PsiModifierList: + + PsiIdentifier:value('value') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiReferenceExpression:value + PsiReferenceParameterList + + PsiIdentifier:value('value') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n ') + PsiDeclarationStatement + PsiLocalVariable:fn3 + PsiModifierList: + + PsiTypeElement:Fn + PsiJavaCodeReferenceElement:Fn + PsiIdentifier:Fn('Fn') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:fn3('fn3') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression + PsiParameterList:(int value) + PsiJavaToken:LPARENTH('(') + PsiParameter:value + PsiModifierList: + + PsiTypeElement:int + PsiKeyword:int('int') + PsiWhiteSpace(' ') + PsiIdentifier:value('value') + PsiJavaToken:RPARENTH(')') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiReferenceExpression:value + PsiReferenceParameterList + + PsiIdentifier:value('value') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n ') + PsiDeclarationStatement + PsiLocalVariable:fn4 + PsiModifierList: + + PsiTypeElement:Fn + PsiJavaCodeReferenceElement:Fn + PsiIdentifier:Fn('Fn') + PsiReferenceParameterList + + PsiWhiteSpace(' ') + PsiIdentifier:fn4('fn4') + PsiWhiteSpace(' ') + PsiJavaToken:EQ('=') + PsiWhiteSpace(' ') + PsiLambdaExpression + PsiParameterList:sealed + PsiParameter:sealed + PsiModifierList: + + PsiIdentifier:sealed('sealed') + PsiWhiteSpace(' ') + PsiJavaToken:ARROW('->') + PsiWhiteSpace(' ') + PsiReferenceExpression:sealed + PsiReferenceParameterList + + PsiIdentifier:sealed('sealed') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n ') + PsiJavaToken:RBRACE('}') + PsiWhiteSpace('\n\n ') + PsiClass:Fn + PsiModifierList: + + PsiKeyword:interface('interface') + PsiWhiteSpace(' ') + PsiIdentifier:Fn('Fn') + PsiTypeParameterList + + PsiReferenceList + + PsiReferenceList + + PsiWhiteSpace(' ') + PsiJavaToken:LBRACE('{') + PsiWhiteSpace('\n ') + PsiMethod:x + PsiModifierList: + + PsiTypeParameterList + + PsiTypeElement:int + PsiKeyword:int('int') + PsiWhiteSpace(' ') + PsiIdentifier:x('x') + PsiParameterList:(int y) + PsiJavaToken:LPARENTH('(') + PsiParameter:y + PsiModifierList: + + PsiTypeElement:int + PsiKeyword:int('int') + PsiWhiteSpace(' ') + PsiIdentifier:y('y') + PsiJavaToken:RPARENTH(')') + PsiReferenceList + + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace('\n ') + PsiJavaToken:RBRACE('}') + PsiWhiteSpace('\n') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters_node.txt b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters_node.txt new file mode 100644 index 000000000000..5799cfb2adfe --- /dev/null +++ b/java/java-tests/testData/psi/parser-full/declarationParsing/class/NoSoftKeywordInLambdaParameters_node.txt @@ -0,0 +1,203 @@ +java.FILE + IMPORT_LIST + + CLASS + MODIFIER_LIST + PUBLIC_KEYWORD + WHITE_SPACE + CLASS_KEYWORD + WHITE_SPACE + IDENTIFIER + TYPE_PARAMETER_LIST + + EXTENDS_LIST + + IMPLEMENTS_LIST + + WHITE_SPACE + LBRACE + WHITE_SPACE + METHOD + MODIFIER_LIST + + TYPE_PARAMETER_LIST + + TYPE + VOID_KEYWORD + WHITE_SPACE + IDENTIFIER + PARAMETER_LIST + LPARENTH + RPARENTH + THROWS_LIST + + WHITE_SPACE + CODE_BLOCK + LBRACE + WHITE_SPACE + DECLARATION_STATEMENT + LOCAL_VARIABLE + MODIFIER_LIST + + TYPE + JAVA_CODE_REFERENCE + IDENTIFIER + REFERENCE_PARAMETER_LIST + + WHITE_SPACE + IDENTIFIER + WHITE_SPACE + EQ + WHITE_SPACE + LAMBDA_EXPRESSION + PARAMETER_LIST + PARAMETER + MODIFIER_LIST + + IDENTIFIER + WHITE_SPACE + ARROW + WHITE_SPACE + REFERENCE_EXPRESSION + REFERENCE_PARAMETER_LIST + + IDENTIFIER + SEMICOLON + WHITE_SPACE + DECLARATION_STATEMENT + LOCAL_VARIABLE + MODIFIER_LIST + + TYPE + JAVA_CODE_REFERENCE + IDENTIFIER + REFERENCE_PARAMETER_LIST + + WHITE_SPACE + IDENTIFIER + WHITE_SPACE + EQ + WHITE_SPACE + LAMBDA_EXPRESSION + PARAMETER_LIST + LPARENTH + PARAMETER + MODIFIER_LIST + + IDENTIFIER + RPARENTH + WHITE_SPACE + ARROW + WHITE_SPACE + REFERENCE_EXPRESSION + REFERENCE_PARAMETER_LIST + + IDENTIFIER + SEMICOLON + WHITE_SPACE + DECLARATION_STATEMENT + LOCAL_VARIABLE + MODIFIER_LIST + + TYPE + JAVA_CODE_REFERENCE + IDENTIFIER + REFERENCE_PARAMETER_LIST + + WHITE_SPACE + IDENTIFIER + WHITE_SPACE + EQ + WHITE_SPACE + LAMBDA_EXPRESSION + PARAMETER_LIST + LPARENTH + PARAMETER + MODIFIER_LIST + + TYPE + INT_KEYWORD + WHITE_SPACE + IDENTIFIER + RPARENTH + WHITE_SPACE + ARROW + WHITE_SPACE + REFERENCE_EXPRESSION + REFERENCE_PARAMETER_LIST + + IDENTIFIER + SEMICOLON + WHITE_SPACE + DECLARATION_STATEMENT + LOCAL_VARIABLE + MODIFIER_LIST + + TYPE + JAVA_CODE_REFERENCE + IDENTIFIER + REFERENCE_PARAMETER_LIST + + WHITE_SPACE + IDENTIFIER + WHITE_SPACE + EQ + WHITE_SPACE + LAMBDA_EXPRESSION + PARAMETER_LIST + PARAMETER + MODIFIER_LIST + + IDENTIFIER + WHITE_SPACE + ARROW + WHITE_SPACE + REFERENCE_EXPRESSION + REFERENCE_PARAMETER_LIST + + IDENTIFIER + SEMICOLON + WHITE_SPACE + RBRACE + WHITE_SPACE + CLASS + MODIFIER_LIST + + INTERFACE_KEYWORD + WHITE_SPACE + IDENTIFIER + TYPE_PARAMETER_LIST + + EXTENDS_LIST + + IMPLEMENTS_LIST + + WHITE_SPACE + LBRACE + WHITE_SPACE + METHOD + MODIFIER_LIST + + TYPE_PARAMETER_LIST + + TYPE + INT_KEYWORD + WHITE_SPACE + IDENTIFIER + PARAMETER_LIST + LPARENTH + PARAMETER + MODIFIER_LIST + + TYPE + INT_KEYWORD + WHITE_SPACE + IDENTIFIER + RPARENTH + THROWS_LIST + + SEMICOLON + WHITE_SPACE + RBRACE + WHITE_SPACE + RBRACE \ No newline at end of file