mirror of
https://github.com/openjdk/jdk.git
synced 2026-03-15 10:23:28 +00:00
8027682: javac wrongly accepts semicolons in package and import decls
Reviewed-by: vromero
This commit is contained in:
parent
c00d0885ae
commit
4b8f7db6be
@ -3839,16 +3839,32 @@ public class JavacParser implements Parser {
|
||||
defs.append(pd);
|
||||
}
|
||||
|
||||
boolean checkForImports = true;
|
||||
boolean firstTypeDecl = true;
|
||||
boolean firstTypeDecl = true; // have we see a class, enum, or interface declaration yet?
|
||||
while (token.kind != EOF) {
|
||||
if (token.pos <= endPosTable.errorEndPos) {
|
||||
// error recovery
|
||||
skip(checkForImports, false, false, false);
|
||||
skip(firstTypeDecl, false, false, false);
|
||||
if (token.kind == EOF)
|
||||
break;
|
||||
}
|
||||
if (checkForImports && mods == null && token.kind == IMPORT) {
|
||||
// JLS 7.3 doesn't allow extra semicolons after package or import declarations,
|
||||
// but here we try to provide a more helpful error message if we encounter any.
|
||||
// Do that by slurping in as many semicolons as possible, and then seeing what
|
||||
// comes after before deciding how best to handle them.
|
||||
ListBuffer<JCTree> semiList = new ListBuffer<>();
|
||||
while (firstTypeDecl && mods == null && token.kind == SEMI) {
|
||||
semiList.append(toP(F.at(token.pos).Skip()));
|
||||
nextToken();
|
||||
if (token.kind == EOF)
|
||||
break;
|
||||
}
|
||||
if (firstTypeDecl && mods == null && token.kind == IMPORT) {
|
||||
if (!semiList.isEmpty()) {
|
||||
if (source.compareTo(Source.JDK21) >= 0)
|
||||
reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
|
||||
else
|
||||
log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
|
||||
}
|
||||
seenImport = true;
|
||||
defs.append(importDeclaration());
|
||||
} else {
|
||||
@ -3860,6 +3876,12 @@ public class JavacParser implements Parser {
|
||||
if (mods != null || token.kind != SEMI)
|
||||
mods = modifiersOpt(mods);
|
||||
if (firstTypeDecl && token.kind == IDENTIFIER) {
|
||||
if (!semiList.isEmpty()) {
|
||||
if (source.compareTo(Source.JDK21) >= 0)
|
||||
reportSyntaxError(semiList.first().pos, Errors.ExtraneousSemicolon);
|
||||
else
|
||||
log.warning(semiList.first().pos, Warnings.ExtraneousSemicolon);
|
||||
}
|
||||
ModuleKind kind = ModuleKind.STRONG;
|
||||
if (token.name() == names.open) {
|
||||
kind = ModuleKind.OPEN;
|
||||
@ -3876,12 +3898,11 @@ public class JavacParser implements Parser {
|
||||
reportSyntaxError(token.pos, Errors.ExpectedModule);
|
||||
}
|
||||
}
|
||||
defs.appendList(semiList.toList());
|
||||
JCTree def = typeDeclaration(mods, docComment);
|
||||
if (def instanceof JCExpressionStatement statement)
|
||||
def = statement.expr;
|
||||
defs.append(def);
|
||||
if (def instanceof JCClassDecl)
|
||||
checkForImports = false;
|
||||
mods = null;
|
||||
firstTypeDecl = false;
|
||||
}
|
||||
|
||||
@ -2358,6 +2358,12 @@ compiler.err.enum.constant.expected=\
|
||||
compiler.err.enum.constant.not.expected=\
|
||||
enum constant not expected here
|
||||
|
||||
compiler.err.extraneous.semicolon=\
|
||||
extraneous semicolon
|
||||
|
||||
compiler.warn.extraneous.semicolon=\
|
||||
extraneous semicolon
|
||||
|
||||
## The following are related in form, but do not easily fit the above paradigm.
|
||||
compiler.err.expected.module.or.open=\
|
||||
''module'' or ''open'' expected
|
||||
|
||||
@ -30,7 +30,7 @@
|
||||
|
||||
import com.sun.jndi.dns.ResourceRecord;
|
||||
import javax.naming.CommunicationException;
|
||||
import javax.naming.InvalidNameException;;
|
||||
import javax.naming.InvalidNameException;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
|
||||
@ -34,8 +34,8 @@ import java.lang.constant.MethodTypeDesc;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodHandles.Lookup;
|
||||
import java.lang.invoke.MethodType;
|
||||
import java.security.AccessControlException;;
|
||||
import java.security.Permission;;
|
||||
import java.security.AccessControlException;
|
||||
import java.security.Permission;
|
||||
|
||||
import static jdk.test.lib.Asserts.*;
|
||||
|
||||
|
||||
@ -45,7 +45,7 @@ import java.util.concurrent.atomic.AtomicInteger;
|
||||
import javax.management.*;
|
||||
import javax.management.openmbean.CompositeData;
|
||||
import java.lang.management.*;
|
||||
import static java.lang.management.MemoryNotificationInfo.*;;
|
||||
import static java.lang.management.MemoryNotificationInfo.*;
|
||||
import static java.lang.management.ManagementFactory.*;
|
||||
|
||||
import jdk.test.whitebox.code.Compiler;
|
||||
|
||||
@ -51,7 +51,7 @@ import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.concurrent.ThreadFactory;
|
||||
import java.util.concurrent.TimeoutException;;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import static java.nio.file.StandardOpenOption.*;
|
||||
|
||||
@ -33,7 +33,7 @@ import jdk.jfr.Recording;
|
||||
import jdk.test.lib.JDKToolLauncher;
|
||||
import jdk.test.lib.Utils;
|
||||
import jdk.test.lib.process.OutputAnalyzer;
|
||||
import jdk.test.lib.process.ProcessTools;;
|
||||
import jdk.test.lib.process.ProcessTools;
|
||||
|
||||
final class ExecuteHelper {
|
||||
|
||||
|
||||
@ -1,7 +1,7 @@
|
||||
AnnotatedImport.java:10:13: compiler.err.expected: token.identifier
|
||||
AnnotatedImport.java:10:16: compiler.err.expected4: class, interface, enum, record
|
||||
AnnotatedImport.java:11:7: compiler.err.expected: token.identifier
|
||||
AnnotatedImport.java:11:1: compiler.err.expected4: class, interface, enum, record
|
||||
AnnotatedImport.java:11:11: compiler.err.expected4: class, interface, enum, record
|
||||
AnnotatedImport.java:12:18: compiler.err.expected: token.identifier
|
||||
AnnotatedImport.java:12:1: compiler.err.expected4: class, interface, enum, record
|
||||
AnnotatedImport.java:12:21: compiler.err.expected4: class, interface, enum, record
|
||||
6 errors
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
AnnotatedPackage1.java:9:14: compiler.err.expected: token.identifier
|
||||
AnnotatedPackage1.java:9:17: compiler.err.expected4: class, interface, enum, record
|
||||
2 errors
|
||||
AnnotatedPackage1.java:11:1: compiler.err.expected4: class, interface, enum, record
|
||||
3 errors
|
||||
|
||||
@ -1,3 +1,4 @@
|
||||
AnnotatedPackage2.java:9:8: compiler.err.expected: token.identifier
|
||||
AnnotatedPackage2.java:9:12: compiler.err.expected4: class, interface, enum, record
|
||||
2 errors
|
||||
AnnotatedPackage2.java:11:1: compiler.err.expected4: class, interface, enum, record
|
||||
3 errors
|
||||
|
||||
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.err.extraneous.semicolon
|
||||
|
||||
import java.util.Map;; // NOTE: extra semicolon
|
||||
import java.util.Set;
|
||||
|
||||
class ExtraImportSemicolonError {
|
||||
}
|
||||
@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright (c) 2023, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
// key: compiler.warn.extraneous.semicolon
|
||||
// options: --release 20
|
||||
|
||||
import java.util.Map;; // NOTE: extra semicolon
|
||||
import java.util.Set;
|
||||
|
||||
class ExtraImportSemicolonWarning {
|
||||
}
|
||||
13
test/langtools/tools/javac/parser/ExtraImportSemicolon.java
Normal file
13
test/langtools/tools/javac/parser/ExtraImportSemicolon.java
Normal file
@ -0,0 +1,13 @@
|
||||
/*
|
||||
* @test /nodynamiccopyright/
|
||||
* @bug 5059679
|
||||
* @summary Verify proper error reporting of extra semicolon before import statement
|
||||
* @compile/fail/ref=ExtraImportSemicolon.out1 -XDrawDiagnostics ExtraImportSemicolon.java
|
||||
* @compile/ref=ExtraImportSemicolon.out2 --release 20 -XDrawDiagnostics ExtraImportSemicolon.java
|
||||
*/
|
||||
|
||||
import java.util.Map;; // NOTE: extra semicolon
|
||||
import java.util.Set;
|
||||
|
||||
class ExtraImportSemicolon {
|
||||
}
|
||||
@ -0,0 +1,2 @@
|
||||
ExtraImportSemicolon.java:9:22: compiler.err.extraneous.semicolon
|
||||
1 error
|
||||
@ -0,0 +1,2 @@
|
||||
ExtraImportSemicolon.java:9:22: compiler.warn.extraneous.semicolon
|
||||
1 warning
|
||||
@ -1,60 +0,0 @@
|
||||
/*
|
||||
* Copyright (c) 2011, 2015, Oracle and/or its affiliates. All rights reserved.
|
||||
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
|
||||
*
|
||||
* This code is free software; you can redistribute it and/or modify it
|
||||
* under the terms of the GNU General Public License version 2 only, as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* This code is distributed in the hope that it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||
* version 2 for more details (a copy is included in the LICENSE file that
|
||||
* accompanied this code).
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License version
|
||||
* 2 along with this work; if not, write to the Free Software Foundation,
|
||||
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
|
||||
* or visit www.oracle.com if you need additional information or have any
|
||||
* questions.
|
||||
*/
|
||||
|
||||
/*
|
||||
* @test
|
||||
* @bug 6963934
|
||||
* @summary JCCompilationUnit.getImports does not report all imports
|
||||
* @modules jdk.compiler
|
||||
*/
|
||||
|
||||
import java.io.File;
|
||||
import javax.tools.JavaCompiler;
|
||||
import javax.tools.StandardJavaFileManager;
|
||||
import javax.tools.ToolProvider;; // NOTE: extra semicolon for test
|
||||
|
||||
import com.sun.source.tree.CompilationUnitTree;
|
||||
import com.sun.source.tree.ImportTree;
|
||||
import com.sun.source.util.JavacTask;
|
||||
; // NOTE: extra semicolon for test
|
||||
|
||||
public class T6963934 {
|
||||
public static void main(String[] args) throws Exception {
|
||||
File testSrc = new File(System.getProperty("test.src"));
|
||||
File thisSrc = new File(testSrc, T6963934.class.getSimpleName() + ".java");
|
||||
JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
|
||||
try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, null, null)) {
|
||||
JavacTask task = (JavacTask) compiler.getTask(null, fileManager, null, null, null,
|
||||
fileManager.getJavaFileObjects(thisSrc));
|
||||
CompilationUnitTree tree = task.parse().iterator().next();
|
||||
int count = 0;
|
||||
for (ImportTree importTree : tree.getImports()) {
|
||||
System.out.println(importTree);
|
||||
count++;
|
||||
}
|
||||
int expected = 7;
|
||||
if (count != expected)
|
||||
throw new Exception("unexpected number of imports found: " + count + ", expected: " + expected);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -23,7 +23,7 @@
|
||||
|
||||
package q;
|
||||
|
||||
import jdk.internal.perf.PerfCounter;;
|
||||
import jdk.internal.perf.PerfCounter;
|
||||
|
||||
public class Counter {
|
||||
public static void create(String name) {
|
||||
|
||||
@ -464,7 +464,7 @@ public class TypeHarness {
|
||||
|
||||
String id;
|
||||
String type;
|
||||
String template = "#Package;\n" +
|
||||
String template = "#Package\n" +
|
||||
"#Imports\n" +
|
||||
"class G#Id#TypeVars {\n" +
|
||||
" #FieldType var;" +
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user