Skip to content
Permalink
Browse files
8246353: Sealed types not supported by jshell
Reviewed-by: rfield, vromero
  • Loading branch information
Jan Lahoda committed Jun 8, 2020
1 parent 3943f9d commit 358714bcd0d208ae95e1e533464275fe816ec57d
Showing 11 changed files with 135 additions and 30 deletions.
@@ -5091,7 +5091,12 @@ void attribClass(ClassSymbol c) throws CompletionFailure {

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()) {
@@ -1237,8 +1237,11 @@ private DiagList modifierDiagnostics(ModifiersTree modtree,
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;
}
@@ -37,11 +37,11 @@
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
@@ -66,11 +66,13 @@ private void add(Set<String> p, Name name) {
// -- 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;
}
@@ -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 void classesIgnoredModifiers() {
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,17 +261,17 @@ public void classesIgnoredModifiersAnnotation() {
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();
}

public void classesIgnoredModifiersOtherModifiers() {
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();
}

@@ -78,7 +78,7 @@ public void testWarnings() {
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;
@@ -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 void testVarModifier() {
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 void testVarModifierAnnotation() {
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 void testVarModifierOtherModifier() {
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 void testMisplacedIgnoredModifier() {
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() {
@@ -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 void methodsWarn() {
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();
@@ -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;
@@ -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"));
}
}
@@ -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.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 @@ enum Enum {
}
}

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(
"""

0 comments on commit 358714b

Please sign in to comment.