8247352: improve error messages for sealed classes and records

Reviewed-by: mcimadamore
This commit is contained in:
Vicente Romero 2020-09-04 23:51:26 -04:00
parent 3e81b3ad48
commit 4b3a0b789e
14 changed files with 289 additions and 18 deletions

View File

@ -1075,7 +1075,7 @@ public class Attr extends JCTree.Visitor {
if (app == null ||
TreeInfo.name(app.meth) != names._this ||
!checkFirstConstructorStat(app, tree, false)) {
log.error(tree, Errors.FirstStatementMustBeCallToAnotherConstructor);
log.error(tree, Errors.FirstStatementMustBeCallToAnotherConstructor(env.enclClass.sym));
}
} else {
// but if it is the canonical:
@ -5052,7 +5052,7 @@ public class Attr extends JCTree.Visitor {
Errors.InvalidPermitsClause(Fragments.IsATypeVariable(subTypeSym.type)));
}
if (subTypeSym.isAnonymous() && !c.isEnum()) {
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.LocalClassesCantExtendSealed(Fragments.Anonymous));
}
if (permittedTypes.contains(subTypeSym)) {
DiagnosticPosition pos =
@ -5065,10 +5065,14 @@ public class Attr extends JCTree.Visitor {
}
if (sealedInUnnamed) {
if (subTypeSym.packge() != c.packge()) {
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree),
Errors.ClassInUnnamedModuleCantExtendSealedInDiffPackage(c)
);
}
} else if (subTypeSym.packge().modle != c.packge().modle) {
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree), Errors.CantInheritFromSealed(c));
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, env.tree),
Errors.ClassInModuleCantExtendSealedInDiffModule(c, c.packge().modle)
);
}
if (subTypeSym == c.type.tsym || types.isSuperType(subTypeSym.type, c.type)) {
log.error(TreeInfo.diagnosticPositionFor(subTypeSym, ((JCClassDecl)env.tree).permitting),
@ -5107,7 +5111,7 @@ public class Attr extends JCTree.Visitor {
}
} else {
if (c.isLocal() && !c.isEnum()) {
log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed);
log.error(TreeInfo.diagnosticPositionFor(c, env.tree), Errors.LocalClassesCantExtendSealed(c.isAnonymous() ? Fragments.Anonymous : Fragments.Local));
}
for (ClassSymbol supertypeSym : sealedSupers) {

View File

@ -3489,7 +3489,16 @@ compiler.err.sealed.class.must.have.subclasses=\
# errors in subclasses of sealed classes
# 0: symbol
compiler.err.cant.inherit.from.sealed=\
class is not allowed to extend sealed class: {0}
class is not allowed to extend sealed class: {0} \
(as it is not listed in its 'permits' clause)
# 0: symbol
compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package=\
class {0} in unnamed module cannot extend a sealed class in a different package
# 0: symbol, 1: symbol
compiler.err.class.in.module.cant.extend.sealed.in.diff.module=\
class {0} in module {1} cannot extend a sealed class in a different module
# 0: symbol
compiler.err.non.sealed.with.no.sealed.supertype=\
@ -3505,8 +3514,15 @@ compiler.err.non.sealed.or.sealed.expected=\
compiler.err.sealed.or.non.sealed.local.classes.not.allowed=\
sealed or non-sealed local classes are not allowed
# 0: fragment
compiler.err.local.classes.cant.extend.sealed=\
local classes must not extend sealed classes
{0} classes must not extend sealed classes\
compiler.misc.anonymous=\
anonymous
compiler.misc.local=\
local
###
# errors related to records
@ -3588,8 +3604,9 @@ compiler.err.record.cannot.declare.instance.fields=\
compiler.err.invalid.supertype.record=\
classes cannot directly extend {0}
# 0: symbol
compiler.err.first.statement.must.be.call.to.another.constructor=\
constructor is not canonical, so its first statement must invoke another constructor
constructor is not canonical, so its first statement must invoke another constructor of class {0}
compiler.err.instance.initializer.not.allowed.in.records=\
instance initializers not allowed in records

View File

@ -0,0 +1,38 @@
/*
* 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.
*/
// key: compiler.err.local.classes.cant.extend.sealed
// key: compiler.err.sealed.class.must.have.subclasses
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// key: compiler.misc.anonymous
// options: --enable-preview -source ${jdk.version}
class Main {
void m() {
Shape shape = new Shape() {};
}
}
sealed interface Shape {}

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
// key: compiler.err.class.in.module.cant.extend.sealed.in.diff.module
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: --add-reads mSealed=mSub --enable-preview -source ${jdk.version}

View File

@ -0,0 +1,26 @@
/*
* 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.
*/
package a;
public sealed class Base permits b.Impl {}

View File

@ -0,0 +1,24 @@
/*
* 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.
*/
module mSealed { exports a; }

View File

@ -0,0 +1,26 @@
/*
* 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.
*/
package b;
public final class Impl extends a.Base {}

View File

@ -0,0 +1,24 @@
/*
* 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.
*/
module mSub { exports b; requires mSealed; }

View File

@ -0,0 +1,27 @@
/*
* 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.
*/
// key: compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// options: --enable-preview -source ${jdk.version}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
package p1;
import p2.*;
public sealed class Sealed permits p2.Sub {}

View File

@ -0,0 +1,28 @@
/*
* 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.
*/
package p2;
import p1.*;
public final class Sub extends p1.Sealed {}

View File

@ -25,6 +25,7 @@
// key: compiler.err.sealed.class.must.have.subclasses
// key: compiler.note.preview.filename
// key: compiler.note.preview.recompile
// key: compiler.misc.local
// options: --enable-preview -source ${jdk.version}
sealed class C {
@ -32,3 +33,4 @@ sealed class C {
final class D extends C { }
}
}

View File

@ -26,7 +26,7 @@
/**
* RecordCompilationTests
*
* @test 8250629 8252307
* @test 8250629 8252307 8247352
* @summary Negative compilation tests, and positive compilation (smoke) tests for records
* @library /lib/combo /tools/lib /tools/javac/lib
* @modules
@ -394,6 +394,9 @@ public class RecordCompilationTests extends CompilationTestCase {
assertFail("compiler.err.first.statement.must.be.call.to.another.constructor",
"record R(int x, int y) { public R(int y, int x, int z) { this.x = this.y = 0; } }");
assertFail("compiler.err.first.statement.must.be.call.to.another.constructor",
"record R(int x, int y) { public R(int y, int x, int z) { super(); this.x = this.y = 0; } }");
assertOK("record R(int x, int y) { " +
" public R(int x, int y, int z) { this(x, y); } " +
"}");

View File

@ -22,7 +22,7 @@
*/
/*
* @test
* @test 8247352
* @summary test different configurations of sealed classes, same compilation unit, diff pkg or mdl, etc
* @library /tools/lib
* @modules jdk.compiler/com.sun.tools.javac.api
@ -373,7 +373,7 @@ public class SealedDiffConfigurationsTest extends TestRunner {
tb.writeJavaFiles(sub1,
"package pkg2;\n" +
"import pkg1.*;\n" +
"public class Sub1 extends pkg1.Sealed {\n" +
"public final class Sub1 extends pkg1.Sealed {\n" +
"}");
List<String> error = new JavacTask(tb)
@ -384,9 +384,8 @@ public class SealedDiffConfigurationsTest extends TestRunner {
.getOutputLines(OutputKind.DIRECT);
List<String> expected = List.of(
"Sub1.java:3:8: compiler.err.non.sealed.sealed.or.final.expected",
"Sealed.java:3:40: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
"2 errors");
"Sealed.java:3:40: compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package: pkg1.Sealed",
"1 error");
if (!error.containsAll(expected)) {
throw new AssertionError("Expected output not found. Expected: " + expected);
}
@ -461,7 +460,7 @@ public class SealedDiffConfigurationsTest extends TestRunner {
.getOutputLines(OutputKind.DIRECT);
List<String> expected = List.of(
"Sealed.java:3:40: compiler.err.cant.inherit.from.sealed: pkg1.Sealed",
"Sealed.java:3:40: compiler.err.class.in.unnamed.module.cant.extend.sealed.in.diff.package: pkg1.Sealed",
"1 error");
if (!error.containsAll(expected)) {
throw new AssertionError("Expected output not found. Found: " + error);
@ -601,9 +600,7 @@ public class SealedDiffConfigurationsTest extends TestRunner {
.getOutputLines(OutputKind.DIRECT);
List<String> expected = List.of(
"Base.java:1:46: compiler.err.cant.inherit.from.sealed: a.Base",
"- compiler.note.preview.filename: Base.java",
"- compiler.note.preview.recompile",
"Base.java:1:46: compiler.err.class.in.module.cant.extend.sealed.in.diff.module: a.Base, mSealed",
"1 error"
);
if (!error.containsAll(expected)) {