8246353: Sealed types not supported by jshell

Reviewed-by: rfield, vromero
This commit is contained in:
Jan Lahoda 2020-06-08 16:59:43 +02:00
parent 3943f9d0b7
commit 358714bcd0
11 changed files with 135 additions and 30 deletions

View File

@ -5091,7 +5091,12 @@ public class Attr extends JCTree.Visitor {
if (sealedSupers.isEmpty()) {
if ((c.flags_field & Flags.NON_SEALED) != 0) {
log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
boolean hasErrorSuper = types.directSupertypes(c.type)
.stream()
.anyMatch(s -> s.tsym.kind == Kind.ERR);
if (!hasErrorSuper) {
log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.NonSealedWithNoSealedSupertype(c));
}
}
} else {
if (c.isLocal() && !c.isEnum()) {

View File

@ -1237,8 +1237,11 @@ class Eval {
case PRIVATE:
// quietly ignore, user cannot see effects one way or the other
break;
case STATIC:
case FINAL:
//OK to declare an element final
//final classes needed for sealed classes
break;
case STATIC:
list.add(mod);
break;
}

View File

@ -37,11 +37,11 @@ import java.util.stream.Stream;
class MaskCommentsAndModifiers {
private final static Set<String> IGNORED_MODIFIERS =
Stream.of( "public", "protected", "private", "static", "final" )
Stream.of( "public", "protected", "private", "static" )
.collect( Collectors.toSet() );
private final static Set<String> OTHER_MODIFIERS =
Stream.of( "abstract", "strictfp", "transient", "volatile", "synchronized", "native", "default" )
Stream.of( "abstract", "strictfp", "transient", "volatile", "synchronized", "native", "default", "final" )
.collect( Collectors.toSet() );
// Builder to accumulate non-masked characters

View File

@ -66,11 +66,13 @@ class TreeDependencyScanner extends TreeScanner<Void, Set<String>> {
// -- Differentiate declaration references from body references ---
@Override
@SuppressWarnings("preview")
public Void visitClass(ClassTree node, Set<String> p) {
scan(node.getModifiers(), p);
scan(node.getTypeParameters(), p);
scan(node.getExtendsClause(), p);
scan(node.getImplementsClause(), p);
scan(node.getPermitsClause(), p);
scan(node.getMembers(), body);
return null;
}

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8145239 8129559 8080354 8189248 8010319
* @bug 8145239 8129559 8080354 8189248 8010319 8246353
* @summary Tests for EvaluationState.classes
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng ClassesTest
@ -251,8 +251,8 @@ public class ClassesTest extends KullaTesting {
assertEval("public interface A { }");
assertDeclareWarn1("static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("final interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 6, 0, -1, -1, Diagnostic.Kind.WARNING));
assertActiveKeys();
}
@ -261,8 +261,8 @@ public class ClassesTest extends KullaTesting {
assertEval("@X public interface A { }");
assertDeclareWarn1("@X static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("@X final interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 8, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("@X static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 9, 0, -1, -1, Diagnostic.Kind.WARNING));
assertActiveKeys();
}
@ -270,8 +270,8 @@ public class ClassesTest extends KullaTesting {
assertEval("strictfp public interface A { }");
assertDeclareWarn1("strictfp static class B implements A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("strictfp final interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 14, 0, -1, -1, Diagnostic.Kind.WARNING));
assertDeclareWarn1("strictfp static interface C extends A { }",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 15, 0, -1, -1, Diagnostic.Kind.WARNING));
assertActiveKeys();
}

View File

@ -78,7 +78,7 @@ public class ErrorTranslationTest extends ReplToolTesting {
ExpectedDiagnostic[] diagnostics = new ExpectedDiagnostic[]{
newExpectedDiagnostic(0, 6, 0, -1, -1, Diagnostic.Kind.WARNING),
newExpectedDiagnostic(0, 5, 0, -1, -1, Diagnostic.Kind.WARNING)};
String[] mods = {"static", "final"};
String[] mods = {"static"};
for (int i = 0; i < mods.length; ++i) {
for (String code : new String[] {"class A {}", "void f() {}", "int a;"}) {
final int finalI = i;

View File

@ -22,7 +22,8 @@
*/
/*
* @test 8129559
* @test
* @bug 8129559 8246353
* @summary Test the ignoring of comments and certain modifiers
* @build KullaTesting TestingInputStream
* @run testng IgnoreTest
@ -66,8 +67,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = (VarSnippet) assertDeclareWarn1("final int x5;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = varKey(assertEval("final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
public void testVarModifierAnnotation() {
@ -80,8 +81,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("@A static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = (VarSnippet) assertDeclareWarn1("@A(1111) final int x5;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = varKey(assertEval("@A(1111) final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
public void testVarModifierOtherModifier() {
@ -93,8 +94,8 @@ public class IgnoreTest extends KullaTesting {
assertVariableDeclSnippet(x3, "x3", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
VarSnippet x4 = (VarSnippet) assertDeclareWarn1("volatile static int x4;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x4, "x4", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = (VarSnippet) assertDeclareWarn1("transient final int x5;", "jdk.eval.warn.illegal.modifiers");
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 1);
VarSnippet x5 = varKey(assertEval("transient final int x5;"));
assertVariableDeclSnippet(x5, "x5", "int", VALID, VAR_DECLARATION_SUBKIND, 0, 0);
}
public void testMisplacedIgnoredModifier() {
@ -106,23 +107,23 @@ public class IgnoreTest extends KullaTesting {
public void testMethodModifier() {
MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("static void m4() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
MethodSnippet m5 = (MethodSnippet) assertDeclareWarn1("final void m5() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 1);
MethodSnippet m5 = methodKey(assertEval("final void m5() {}"));
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 0);
}
public void testMethodModifierAnnotation() {
assertEval("@interface A { int value() default 0; }");
MethodSnippet m4 = (MethodSnippet) assertDeclareWarn1("@A static void m4() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m4, "m4", "()void", VALID, 0, 1);
MethodSnippet m5 = (MethodSnippet) assertDeclareWarn1("@A(value=66)final void m5() {}", "jdk.eval.warn.illegal.modifiers");
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 1);
MethodSnippet m5 = methodKey(assertEval("@A(value=66)final void m5() {}"));
assertMethodDeclSnippet(m5, "m5", "()void", VALID, 0, 0);
}
public void testClassModifier() {
TypeDeclSnippet c4 = (TypeDeclSnippet) assertDeclareWarn1("static class C4 {}", "jdk.eval.warn.illegal.modifiers");
assertTypeDeclSnippet(c4, "C4", VALID, CLASS_SUBKIND, 0, 1);
TypeDeclSnippet c5 = (TypeDeclSnippet) assertDeclareWarn1("final class C5 {}", "jdk.eval.warn.illegal.modifiers");
assertTypeDeclSnippet(c5, "C5", VALID, CLASS_SUBKIND, 0, 1);
TypeDeclSnippet c5 = classKey(assertEval("final class C5 {}"));
assertTypeDeclSnippet(c5, "C5", VALID, CLASS_SUBKIND, 0, 0);
}
public void testInsideModifier() {

View File

@ -23,7 +23,7 @@
/*
* @test
* @bug 8080357 8167643 8187359 8199762 8080353
* @bug 8080357 8167643 8187359 8199762 8080353 8246353
* @summary Tests for EvaluationState.methods
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng MethodsTest
@ -298,8 +298,8 @@ public class MethodsTest extends KullaTesting {
assertActiveKeys();
assertDeclareWarn1("final String f() {return null;}",
new ExpectedDiagnostic("jdk.eval.warn.illegal.modifiers", 0, 5, 0, -1, -1, Diagnostic.Kind.WARNING),
ste(MAIN_SNIPPET, VALID, VALID, false, null),
null,
ste(MAIN_SNIPPET, VALID, VALID, true, null),
ste(f, VALID, OVERWRITTEN, false, MAIN_SNIPPET));
assertNumberOfActiveMethods(1);
assertActiveKeys();

View File

@ -44,13 +44,13 @@ public class ModifiersTest extends KullaTesting {
public Object[][] getTestCases() {
List<Object[]> testCases = new ArrayList<>();
String[] ignoredModifiers = new String[] {
"static", "final"
"static"
};
String[] silentlyIgnoredModifiers = new String[] {
"public", "protected", "private"
};
String[] before = new String[] {
"strictfp", "abstract", "@X", "@X(value=9)"
"strictfp", "abstract", "final", "@X", "@X(value=9)"
};
String context = "@interface X { int value() default 0; }";
Consumer<String> eval = this::assertEval;

View File

@ -0,0 +1,72 @@
/*
* Copyright (c) 2020, 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 8246353
* @summary Test sealed class in jshell
* @modules jdk.jshell
* @build KullaTesting TestingInputStream ExpectedDiagnostic
* @run testng SealedClassesTest
*/
import javax.lang.model.SourceVersion;
import jdk.jshell.TypeDeclSnippet;
import jdk.jshell.Snippet.Status;
import org.testng.annotations.BeforeMethod;
import org.testng.annotations.Test;
import static jdk.jshell.Snippet.Status.VALID;
@Test
public class SealedClassesTest extends KullaTesting {
public void testSealed() {
TypeDeclSnippet base = classKey(
assertEval("sealed class B permits I {}",
ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_NOT_DEFINED, false, null)));
assertEval("final class I extends B {}",
added(VALID),
ste(base, Status.RECOVERABLE_NOT_DEFINED, Status.VALID, true, null));
assertEval("new I()");
}
public void testNonSealed() {
TypeDeclSnippet base = classKey(
assertEval("sealed class B permits I {}",
ste(MAIN_SNIPPET, Status.NONEXISTENT, Status.RECOVERABLE_NOT_DEFINED, false, null)));
assertEval("non-sealed class I extends B {}",
added(VALID),
ste(base, Status.RECOVERABLE_NOT_DEFINED, Status.VALID, true, null));
assertEval("class I2 extends I {}");
assertEval("new I2()");
}
@BeforeMethod
public void setUp() {
setUp(b -> b.compilerOptions("--enable-preview", "-source", String.valueOf(SourceVersion.latest().ordinal()))
.remoteVMOptions("--enable-preview"));
}
}

View File

@ -27,6 +27,7 @@
* SealedCompilationTests
*
* @test
* @bug 8246353
* @summary Negative compilation tests, and positive compilation (smoke) tests for sealed classes
* @library /lib/combo /tools/lib
* @modules
@ -58,11 +59,13 @@ import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.element.TypeElement;
import javax.lang.model.SourceVersion;
import com.sun.tools.javac.util.Assert;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
import static org.testng.Assert.fail;
import org.testng.annotations.Test;
import tools.javac.combo.CompilationTestCase;
@ -90,11 +93,18 @@ public class SealedCompilationTests extends CompilationTestCase {
/* simplest annotation processor just to force a round of annotation processing for all tests
*/
@SupportedAnnotationTypes("*")
public static class SimplestAP extends AbstractProcessor {
@Override
public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
return true;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
}
public SealedCompilationTests() {
@ -693,6 +703,18 @@ public class SealedCompilationTests extends CompilationTestCase {
}
}
public void testNonSealedErroneousSuper() {
assertFail("compiler.err.cant.resolve",
d -> {
if (diags.keys().size() != 1) {
fail("Unexpected errors: " + diags.toString());
}
},
"""
non-sealed class C extends Undefined {}
""");
}
public void testIllFormedNonSealed() {
for (String s : List.of(
"""