mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
refactor [java]: simpler modifier list parsing without Pair
Space-RevId: bdb7b5111b0b087c52afbd396b1001294238271f GitOrigin-RevId: f871c5a1894d2e3618c9116409b41b82e682a3db
This commit is contained in:
committed by
intellij-monorepo-bot
parent
fa8e49b309
commit
5d88b90720
+2
-1
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.parser.declarationParsing;
|
||||
|
||||
import com.intellij.java.parser.AbstractBasicJavaParsingTestCase;
|
||||
@@ -102,4 +102,5 @@ public abstract class AbstractBasicClassParsingTest extends AbstractBasicJavaPar
|
||||
public void testImplicitClassJavaDoc() { doTest(true); }
|
||||
|
||||
public void testIncompleteClass() { doTest(true); }
|
||||
public void testIncorrectModifier() { doTest(true); }
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.syntax.element
|
||||
|
||||
import com.intellij.java.syntax.element.JavaSyntaxTokenType
|
||||
@@ -43,11 +43,6 @@ 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
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.syntax.parser
|
||||
|
||||
import com.intellij.java.syntax.JavaSyntaxBundle
|
||||
@@ -8,7 +8,6 @@ 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
|
||||
@@ -244,9 +243,7 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
|
||||
val declaration = builder.mark()
|
||||
val declarationStart = builder.currentOffset
|
||||
|
||||
val modListInfo = parseModifierList(builder)
|
||||
val modList = modListInfo.first
|
||||
val modList = parseModifierList(builder)
|
||||
|
||||
if (builder.expect(JavaSyntaxTokenType.AT)) {
|
||||
if (builder.tokenType === JavaSyntaxTokenType.INTERFACE_KEYWORD) {
|
||||
@@ -356,7 +353,7 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
|
||||
if (!builder.expect(JavaSyntaxTokenType.IDENTIFIER)) {
|
||||
if (context != Context.CODE_BLOCK ||
|
||||
!modListInfo.second ||
|
||||
modList.getStartOffset() != modList.getEndOffset() ||
|
||||
(type.isPrimitive && builder.tokenType !== JavaSyntaxTokenType.DOT)
|
||||
) {
|
||||
typeParams?.precede()?.errorBefore(message("unexpected.token"), type.marker)
|
||||
@@ -415,12 +412,8 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
}
|
||||
|
||||
@JvmOverloads
|
||||
fun parseModifierList(
|
||||
builder: SyntaxTreeBuilder,
|
||||
modifiers: SyntaxElementTypeSet = MODIFIER_BIT_SET
|
||||
): Pair<SyntaxTreeBuilder.Marker, Boolean> {
|
||||
fun parseModifierList(builder: SyntaxTreeBuilder, modifiers: SyntaxElementTypeSet = MODIFIER_BIT_SET): SyntaxTreeBuilder.Marker {
|
||||
val modList = builder.mark()
|
||||
var isEmpty = true
|
||||
|
||||
while (true) {
|
||||
var tokenType = builder.tokenType ?: break
|
||||
@@ -436,18 +429,15 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
val nonSealed = builder.mark()
|
||||
builder.advance(3)
|
||||
nonSealed.collapse(JavaSyntaxTokenType.NON_SEALED_KEYWORD)
|
||||
isEmpty = false
|
||||
}
|
||||
else if (modifiers.contains(tokenType)) {
|
||||
builder.advanceLexer()
|
||||
isEmpty = false
|
||||
}
|
||||
else if (tokenType === JavaSyntaxTokenType.AT) {
|
||||
if (KEYWORD_BIT_SET.contains(builder.lookAhead(1))) {
|
||||
break
|
||||
}
|
||||
parseAnnotation(builder)
|
||||
isEmpty = false
|
||||
}
|
||||
else {
|
||||
break
|
||||
@@ -455,7 +445,7 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
}
|
||||
|
||||
JavaParserUtil.done(modList, JavaSyntaxElementType.MODIFIER_LIST, languageLevel)
|
||||
return modList to isEmpty
|
||||
return modList
|
||||
}
|
||||
|
||||
private fun parseMethodFromLeftParenth(
|
||||
@@ -698,16 +688,13 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
): SyntaxTreeBuilder.Marker? {
|
||||
val param = builder.mark()
|
||||
|
||||
val modListInfo = parseModifierList(
|
||||
builder, if (type === JavaSyntaxElementType.PARAMETER) PARAMETER_MODIFIER_BIT_SET else MODIFIER_BIT_SET)
|
||||
|
||||
val typeInfo: ReferenceParser.TypeInfo?
|
||||
val modList: SyntaxTreeBuilder.Marker
|
||||
if (typed) {
|
||||
modList = parseModifierList(builder)
|
||||
val flags = ReferenceParser.EAT_LAST_DOT or ReferenceParser.WILDCARD or typeFlags
|
||||
typeInfo = myParser.referenceParser.parseTypeInfo(builder, flags)
|
||||
|
||||
if (typeInfo == null) {
|
||||
if (modListInfo.second) {
|
||||
if (myParser.referenceParser.parseTypeInfo(builder, flags) == null) {
|
||||
if (modList.getStartOffset() == modList.getEndOffset()) {
|
||||
param.rollbackTo()
|
||||
return null
|
||||
}
|
||||
@@ -716,13 +703,9 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
JavaParserUtil.emptyElement(builder, JavaSyntaxElementType.TYPE)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (typed) {
|
||||
val tokenType = builder.tokenType
|
||||
if (tokenType === JavaSyntaxTokenType.THIS_KEYWORD ||
|
||||
tokenType === JavaSyntaxTokenType.IDENTIFIER && builder.lookAhead(1) === JavaSyntaxTokenType.DOT
|
||||
) {
|
||||
tokenType === JavaSyntaxTokenType.IDENTIFIER && builder.lookAhead(1) === JavaSyntaxTokenType.DOT) {
|
||||
val mark = builder.mark()
|
||||
|
||||
val expr = myParser.expressionParser.parse(builder)
|
||||
@@ -735,6 +718,10 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
mark.rollbackTo()
|
||||
}
|
||||
}
|
||||
else {
|
||||
modList = builder.mark() // modifier list is empty for lambda expression with untyped parameters
|
||||
modList.done(JavaSyntaxElementType.MODIFIER_LIST)
|
||||
}
|
||||
|
||||
if (builder.expect(JavaSyntaxTokenType.IDENTIFIER)) {
|
||||
if (type === JavaSyntaxElementType.PARAMETER || type === JavaSyntaxElementType.RECORD_COMPONENT) {
|
||||
@@ -746,13 +733,11 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
else {
|
||||
JavaParserUtil.error(builder, message("expected.identifier"))
|
||||
param.drop()
|
||||
return modListInfo.first
|
||||
return modList
|
||||
}
|
||||
|
||||
if (JavaParserUtil.expectOrError(builder, JavaSyntaxTokenType.EQ, "expected.eq")) {
|
||||
if (myParser.expressionParser.parse(builder) == null) {
|
||||
JavaParserUtil.error(builder, message("expected.expression"))
|
||||
}
|
||||
if (JavaParserUtil.expectOrError(builder, JavaSyntaxTokenType.EQ, "expected.eq") && myParser.expressionParser.parse(builder) == null) {
|
||||
JavaParserUtil.error(builder, message("expected.expression"))
|
||||
}
|
||||
|
||||
JavaParserUtil.done(param, JavaSyntaxElementType.RESOURCE_VARIABLE, languageLevel)
|
||||
@@ -847,10 +832,7 @@ open class DeclarationParser(private val myParser: JavaParser) {
|
||||
return declaration
|
||||
}
|
||||
|
||||
private fun eatBrackets(
|
||||
builder: SyntaxTreeBuilder,
|
||||
errorKey: @PropertyKey(resourceBundle = JavaSyntaxBundle.BUNDLE) String?
|
||||
): Boolean {
|
||||
private fun eatBrackets(builder: SyntaxTreeBuilder, errorKey: @PropertyKey(resourceBundle = JavaSyntaxBundle.BUNDLE) String?): Boolean {
|
||||
val tokenType = builder.tokenType
|
||||
if (tokenType !== JavaSyntaxTokenType.LBRACKET && tokenType !== JavaSyntaxTokenType.AT) return true
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
// Copyright 2000-2025 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
// Copyright 2000-2026 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
|
||||
package com.intellij.java.syntax.parser
|
||||
|
||||
import com.intellij.java.syntax.JavaSyntaxBundle.message
|
||||
@@ -42,7 +42,8 @@ class PatternParser(private val myParser: JavaParser) {
|
||||
|
||||
fun preParsePattern(builder: SyntaxTreeBuilder): SyntaxTreeBuilder.Marker? {
|
||||
val patternStart = builder.mark()
|
||||
val hasNoModifier = myParser.declarationParser.parseModifierList(builder, PATTERN_MODIFIERS).second
|
||||
val modList = myParser.declarationParser.parseModifierList(builder, PATTERN_MODIFIERS)
|
||||
val hasNoModifier = modList.getStartOffset() == modList.getEndOffset()
|
||||
val type = myParser.referenceParser.parseType(builder, ReferenceParser.EAT_LAST_DOT or ReferenceParser.WILDCARD)
|
||||
val isPattern = type != null &&
|
||||
(builder.tokenType === JavaSyntaxTokenType.IDENTIFIER || (builder.tokenType === JavaSyntaxTokenType.LPARENTH && hasNoModifier))
|
||||
@@ -109,7 +110,8 @@ class PatternParser(private val myParser: JavaParser) {
|
||||
private fun parseTypeOrRecordPattern(builder: SyntaxTreeBuilder, expectVar: Boolean): SyntaxTreeBuilder.Marker {
|
||||
val pattern = builder.mark()
|
||||
val patternVariable = builder.mark()
|
||||
val hasNoModifiers = myParser.declarationParser.parseModifierList(builder, PATTERN_MODIFIERS).second
|
||||
val modList = myParser.declarationParser.parseModifierList(builder, PATTERN_MODIFIERS)
|
||||
val hasNoModifiers = modList.getStartOffset() == modList.getEndOffset()
|
||||
|
||||
var flags = ReferenceParser.EAT_LAST_DOT or ReferenceParser.WILDCARD
|
||||
if (expectVar) {
|
||||
|
||||
+7
@@ -0,0 +1,7 @@
|
||||
class IncorrectModifier {
|
||||
X x = (sealed var y) -> System.out.println()
|
||||
|
||||
interface X {
|
||||
void x(String s);
|
||||
}
|
||||
}
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
PsiJavaFile:IncorrectModifier.java
|
||||
PsiImportList
|
||||
<empty list>
|
||||
PsiClass:IncorrectModifier
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiKeyword:class('class')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:IncorrectModifier('IncorrectModifier')
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiField:x
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:X
|
||||
PsiJavaCodeReferenceElement:X
|
||||
PsiIdentifier:X('X')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:x('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:EQ('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiLambdaExpression
|
||||
PsiParameterList:(sealed var y)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:y
|
||||
PsiModifierList:sealed
|
||||
PsiKeyword:sealed('sealed')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiTypeElement:var
|
||||
PsiKeyword:var('var')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:y('y')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:ARROW('->')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiMethodCallExpression:System.out.println()
|
||||
PsiReferenceExpression:System.out.println
|
||||
PsiReferenceExpression:System.out
|
||||
PsiReferenceExpression:System
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:System('System')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:out('out')
|
||||
PsiJavaToken:DOT('.')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiIdentifier:println('println')
|
||||
PsiExpressionList
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiErrorElement:';' expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' \n \n ')
|
||||
PsiClass:X
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiKeyword:interface('interface')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:X('X')
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiJavaToken:LBRACE('{')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiMethod:x
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeParameterList
|
||||
<empty list>
|
||||
PsiTypeElement:void
|
||||
PsiKeyword:void('void')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:x('x')
|
||||
PsiParameterList:(String s)
|
||||
PsiJavaToken:LPARENTH('(')
|
||||
PsiParameter:s
|
||||
PsiModifierList:
|
||||
<empty list>
|
||||
PsiTypeElement:String
|
||||
PsiJavaCodeReferenceElement:String
|
||||
PsiIdentifier:String('String')
|
||||
PsiReferenceParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PsiIdentifier:s('s')
|
||||
PsiJavaToken:RPARENTH(')')
|
||||
PsiReferenceList
|
||||
<empty list>
|
||||
PsiJavaToken:SEMICOLON(';')
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
PsiWhiteSpace('\n')
|
||||
PsiJavaToken:RBRACE('}')
|
||||
+111
@@ -0,0 +1,111 @@
|
||||
java.FILE
|
||||
IMPORT_LIST
|
||||
<empty list>
|
||||
CLASS
|
||||
MODIFIER_LIST
|
||||
<empty list>
|
||||
CLASS_KEYWORD
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
TYPE_PARAMETER_LIST
|
||||
<empty list>
|
||||
EXTENDS_LIST
|
||||
<empty list>
|
||||
IMPLEMENTS_LIST
|
||||
<empty list>
|
||||
WHITE_SPACE
|
||||
LBRACE
|
||||
WHITE_SPACE
|
||||
FIELD
|
||||
MODIFIER_LIST
|
||||
<empty list>
|
||||
TYPE
|
||||
JAVA_CODE_REFERENCE
|
||||
IDENTIFIER
|
||||
REFERENCE_PARAMETER_LIST
|
||||
<empty list>
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
WHITE_SPACE
|
||||
EQ
|
||||
WHITE_SPACE
|
||||
LAMBDA_EXPRESSION
|
||||
PARAMETER_LIST
|
||||
LPARENTH
|
||||
PARAMETER
|
||||
MODIFIER_LIST
|
||||
SEALED
|
||||
WHITE_SPACE
|
||||
TYPE
|
||||
VAR
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
RPARENTH
|
||||
WHITE_SPACE
|
||||
ARROW
|
||||
WHITE_SPACE
|
||||
METHOD_CALL_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
REFERENCE_EXPRESSION
|
||||
REFERENCE_PARAMETER_LIST
|
||||
<empty list>
|
||||
IDENTIFIER
|
||||
DOT
|
||||
REFERENCE_PARAMETER_LIST
|
||||
<empty list>
|
||||
IDENTIFIER
|
||||
DOT
|
||||
REFERENCE_PARAMETER_LIST
|
||||
<empty list>
|
||||
IDENTIFIER
|
||||
EXPRESSION_LIST
|
||||
LPARENTH
|
||||
RPARENTH
|
||||
ERROR_ELEMENT
|
||||
<empty list>
|
||||
WHITE_SPACE
|
||||
CLASS
|
||||
MODIFIER_LIST
|
||||
<empty list>
|
||||
INTERFACE_KEYWORD
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
TYPE_PARAMETER_LIST
|
||||
<empty list>
|
||||
EXTENDS_LIST
|
||||
<empty list>
|
||||
IMPLEMENTS_LIST
|
||||
<empty list>
|
||||
WHITE_SPACE
|
||||
LBRACE
|
||||
WHITE_SPACE
|
||||
METHOD
|
||||
MODIFIER_LIST
|
||||
<empty list>
|
||||
TYPE_PARAMETER_LIST
|
||||
<empty list>
|
||||
TYPE
|
||||
VOID_KEYWORD
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
PARAMETER_LIST
|
||||
LPARENTH
|
||||
PARAMETER
|
||||
MODIFIER_LIST
|
||||
<empty list>
|
||||
TYPE
|
||||
JAVA_CODE_REFERENCE
|
||||
IDENTIFIER
|
||||
REFERENCE_PARAMETER_LIST
|
||||
<empty list>
|
||||
WHITE_SPACE
|
||||
IDENTIFIER
|
||||
RPARENTH
|
||||
THROWS_LIST
|
||||
<empty list>
|
||||
SEMICOLON
|
||||
WHITE_SPACE
|
||||
RBRACE
|
||||
WHITE_SPACE
|
||||
RBRACE
|
||||
Reference in New Issue
Block a user