From f502283de7d37548a58596107fddc473789a33f6 Mon Sep 17 00:00:00 2001 From: Roman Shevchenko Date: Thu, 28 Sep 2017 16:13:16 +0200 Subject: [PATCH] [java] fixes degenerate enums parsing (IDEA-179650) --- .../lang/java/parser/DeclarationParser.java | 40 ++++++++----------- .../lang/java/parser/ExpressionParser.java | 25 +++--------- .../parser-partial/declarations/EnumBody7.txt | 8 ++++ .../parser-partial/declarations/EnumBody8.txt | 12 ++++++ .../parser-partial/declarations/EnumBody9.txt | 15 +++++++ .../parser/partial/DeclarationParserTest.java | 21 +++------- 6 files changed, 63 insertions(+), 58 deletions(-) create mode 100644 java/java-tests/testData/psi/parser-partial/declarations/EnumBody7.txt create mode 100644 java/java-tests/testData/psi/parser-partial/declarations/EnumBody8.txt create mode 100644 java/java-tests/testData/psi/parser-partial/declarations/EnumBody9.txt diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java index 99abf21b7345..e34307b050f7 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/DeclarationParser.java @@ -1,18 +1,6 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 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.JavaErrorMessages; @@ -133,6 +121,7 @@ public class DeclarationParser { } private void parseEnumConstants(final PsiBuilder builder) { + boolean first = true; while (builder.getTokenType() != null) { if (expect(builder, JavaTokenType.SEMICOLON)) { return; @@ -143,16 +132,21 @@ public class DeclarationParser { return; } - final PsiBuilder.Marker enumConstant = parseEnumConstant(builder); - if (enumConstant == null) { - error(builder, JavaErrorMessages.message("expected.identifier")); + PsiBuilder.Marker enumConstant = parseEnumConstant(builder); + if (enumConstant == null && builder.getTokenType() == JavaTokenType.COMMA && first) { + IElementType next = builder.lookAhead(1); + if (next != JavaTokenType.SEMICOLON && next != JavaTokenType.RBRACE) { + error(builder, JavaErrorMessages.message("expected.identifier")); + } } - if (!expect(builder, JavaTokenType.COMMA)) { - if (builder.getTokenType() != null && builder.getTokenType() != JavaTokenType.SEMICOLON) { - error(builder, JavaErrorMessages.message("expected.comma.or.semicolon")); - return; - } + first = false; + + if (!expect(builder, JavaTokenType.COMMA) && + builder.getTokenType() != null && + builder.getTokenType() != JavaTokenType.SEMICOLON) { + error(builder, JavaErrorMessages.message("expected.comma.or.semicolon")); + return; } } } diff --git a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java index ba7f13a23108..3c51536d9d24 100644 --- a/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java +++ b/java/java-psi-impl/src/com/intellij/lang/java/parser/ExpressionParser.java @@ -1,18 +1,6 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 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.JavaErrorMessages; @@ -654,11 +642,8 @@ public class ExpressionParser { first = false; - final IElementType tokenType = builder.getTokenType(); - if (tokenType == JavaTokenType.COMMA) { - builder.advanceLexer(); - } - else if (tokenType != JavaTokenType.RBRACE) { + IElementType tokenType = builder.getTokenType(); + if (!expect(builder, JavaTokenType.COMMA) && tokenType != JavaTokenType.RBRACE) { error(builder, JavaErrorMessages.message("expected.comma")); } } diff --git a/java/java-tests/testData/psi/parser-partial/declarations/EnumBody7.txt b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody7.txt new file mode 100644 index 000000000000..783c658e5c9a --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody7.txt @@ -0,0 +1,8 @@ +PsiJavaFile:EnumBody7.java + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiJavaToken:SEMICOLON(';') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/declarations/EnumBody8.txt b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody8.txt new file mode 100644 index 000000000000..adf65c0b9954 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody8.txt @@ -0,0 +1,12 @@ +PsiJavaFile:EnumBody8.java + PsiJavaToken:LBRACE('{') + PsiWhiteSpace(' ') + PsiEnumConstant:A + PsiModifierList: + + PsiIdentifier:A('A') + PsiExpressionList + + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testData/psi/parser-partial/declarations/EnumBody9.txt b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody9.txt new file mode 100644 index 000000000000..e3cdbb685ea7 --- /dev/null +++ b/java/java-tests/testData/psi/parser-partial/declarations/EnumBody9.txt @@ -0,0 +1,15 @@ +PsiJavaFile:EnumBody9.java + PsiJavaToken:LBRACE('{') + PsiErrorElement:Identifier expected + + PsiWhiteSpace(' ') + PsiJavaToken:COMMA(',') + PsiWhiteSpace(' ') + PsiEnumConstant:B + PsiModifierList: + + PsiIdentifier:B('B') + PsiExpressionList + + PsiWhiteSpace(' ') + PsiJavaToken:RBRACE('}') \ No newline at end of file diff --git a/java/java-tests/testSrc/com/intellij/java/parser/partial/DeclarationParserTest.java b/java/java-tests/testSrc/com/intellij/java/parser/partial/DeclarationParserTest.java index d22b2e752578..006a7692a41c 100644 --- a/java/java-tests/testSrc/com/intellij/java/parser/partial/DeclarationParserTest.java +++ b/java/java-tests/testSrc/com/intellij/java/parser/partial/DeclarationParserTest.java @@ -1,18 +1,6 @@ -/* - * Copyright 2000-2017 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ +// Copyright 2000-2017 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; @@ -48,6 +36,9 @@ public class DeclarationParserTest extends JavaParsingTestCase { public void testEnumBody4() { doParserTest("{ RED(0), GREEN(1), BLUE(2); }", false, true); } public void testEnumBody5() { doParserTest("{ @ANNOTATION A(10) }", false, true); } public void testEnumBody6() { doParserTest("{ RED, GREEN, BLUE\n OurEnum() {} }", false, true); } + public void testEnumBody7() { doParserTest("{ , ; }", false, true); } + public void testEnumBody8() { doParserTest("{ A, }", false, true); } + public void testEnumBody9() { doParserTest("{ , B }", false, true); } public void testEnumWithInitializedConstants() { doParserTest("{ A(10) { },\n B { void method() {} } }", false, true); } public void testEnumWithoutConstants() { doParserTest("{ private A }", false, true); }