8247849: permits clause of sealed interfaces should not allow parameterized types

Reviewed-by: jlahoda
This commit is contained in:
Vicente Romero 2020-06-25 17:48:53 -04:00
parent 8a424425e1
commit fc82768478
2 changed files with 63 additions and 19 deletions

View File

@ -3761,15 +3761,7 @@ public class JavacParser implements Parser {
nextToken();
implementing = typeList();
}
List<JCExpression> permitting = List.nil();
if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
checkSourceLevel(Feature.SEALED_CLASSES);
if ((mods.flags & Flags.SEALED) == 0) {
log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("class")));
}
nextToken();
permitting = qualidentList(false);
}
List<JCExpression> permitting = permitsClause(mods, "class");
List<JCTree> defs = classInterfaceOrRecordBody(name, false, false);
JCClassDecl result = toP(F.at(pos).ClassDef(
mods, name, typarams, extending, implementing, permitting, defs));
@ -3849,15 +3841,7 @@ public class JavacParser implements Parser {
nextToken();
extending = typeList();
}
List<JCExpression> permitting = List.nil();
if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
checkSourceLevel(Feature.SEALED_CLASSES);
if ((mods.flags & Flags.SEALED) == 0) {
log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed("interface")));
}
nextToken();
permitting = typeList();
}
List<JCExpression> permitting = permitsClause(mods, "interface");
List<JCTree> defs;
defs = classInterfaceOrRecordBody(name, true, false);
JCClassDecl result = toP(F.at(pos).ClassDef(
@ -3866,6 +3850,18 @@ public class JavacParser implements Parser {
return result;
}
List<JCExpression> permitsClause(JCModifiers mods, String classOrInterface) {
if (allowSealedTypes && token.kind == IDENTIFIER && token.name() == names.permits) {
checkSourceLevel(Feature.SEALED_CLASSES);
if ((mods.flags & Flags.SEALED) == 0) {
log.error(token.pos, Errors.InvalidPermitsClause(Fragments.ClassIsNotSealed(classOrInterface)));
}
nextToken();
return qualidentList(false);
}
return List.nil();
}
/** EnumDeclaration = ENUM Ident [IMPLEMENTS TypeList] EnumBody
* @param mods The modifiers starting the enum declaration
* @param dc The documentation comment for the enum, or null.

View File

@ -768,8 +768,14 @@ public class SealedCompilationTests extends CompilationTestCase {
}
}
public void testParameterizedPermitted() {
private static String[] PRIMITIVES_VOID_AND_PRIMITIVE_ARRAYS = new String[] {
"byte", "short", "int", "long", "float", "double", "char", "boolean", "void",
"byte[]", "short[]", "int[]", "long[]", "float[]", "double[]", "char[]", "boolean[]"
};
public void testPermitsClause() {
for (String s : List.of(
// can't include a parameterized type
"""
sealed class C<T> permits Sub<T> {}
final class Sub<T> extends C<T> {}
@ -777,10 +783,52 @@ public class SealedCompilationTests extends CompilationTestCase {
"""
sealed class C permits Sub<String> {}
final class Sub<T> extends C {}
""",
"""
sealed class C permits Sub<String> {}
non-sealed class Sub<T> extends C {}
""",
"""
sealed interface IC permits ID<String> {}
non-sealed interface ID<T> extends IC {}
""",
// can't include an array type
"""
sealed class C<T> permits Sub[] {}
final class Sub<T> extends C<T> {}
""",
"""
sealed class C permits Sub[] {}
non-sealed class Sub<T> extends C {}
""",
"""
sealed interface IC permits ID[] {}
non-sealed interface ID<T> extends IC {}
"""
)) {
assertFail("compiler.err.expected", s);
}
for (String s : List.of(
// can't include primitives, void or primitive arrays
"""
sealed class C<T> permits # {}
final class Sub<T> extends C<T> {}
""",
"""
sealed class C permits # {}
non-sealed class Sub<T> extends C {}
""",
"""
sealed interface IC permits # {}
non-sealed interface ID<T> extends IC {}
"""
)) {
for (String t: PRIMITIVES_VOID_AND_PRIMITIVE_ARRAYS){
assertFail("compiler.err.expected", s, t);
}
}
}
private Path[] findJavaFiles(Path... paths) throws IOException {