8019461: Clean up javac diagnostics

7196553: Review error messages for repeating annotations

Changes to the diagnostic messages to improve clarity and JLS coherence

Reviewed-by: jjg
This commit is contained in:
Eric McCorkle 2013-10-10 13:55:41 -04:00
parent a7125b5d2e
commit ad8c918fb1
6 changed files with 101 additions and 56 deletions

View file

@ -792,17 +792,19 @@ public class Attr extends JCTree.Visitor {
Type t = tree.type != null ? Type t = tree.type != null ?
tree.type : tree.type :
attribType(tree, env); attribType(tree, env);
return checkBase(t, tree, env, classExpected, interfaceExpected, checkExtensible); return checkBase(t, tree, env, classExpected, interfaceExpected, false, checkExtensible);
} }
Type checkBase(Type t, Type checkBase(Type t,
JCTree tree, JCTree tree,
Env<AttrContext> env, Env<AttrContext> env,
boolean classExpected, boolean classExpected,
boolean interfaceOrArrayExpected, boolean interfacesOnlyExpected,
boolean interfacesOrArraysExpected,
boolean checkExtensible) { boolean checkExtensible) {
if (t.isErroneous()) if (t.isErroneous())
return t; return t;
if (t.hasTag(TYPEVAR) && !classExpected && !interfaceOrArrayExpected) { if (t.hasTag(TYPEVAR) && !classExpected &&
!interfacesOrArraysExpected && !interfacesOnlyExpected) {
// check that type variable is already visible // check that type variable is already visible
if (t.getUpperBound() == null) { if (t.getUpperBound() == null) {
log.error(tree.pos(), "illegal.forward.ref"); log.error(tree.pos(), "illegal.forward.ref");
@ -814,12 +816,17 @@ public class Attr extends JCTree.Visitor {
t = chk.checkClassOrArrayType(tree.pos(), t, t = chk.checkClassOrArrayType(tree.pos(), t,
checkExtensible|!allowGenerics); checkExtensible|!allowGenerics);
} }
if (interfaceOrArrayExpected && if (interfacesOnlyExpected && !t.tsym.isInterface()) {
!(t.tsym.isInterface() || t.getTag() == ARRAY)) {
log.error(tree.pos(), "intf.expected.here"); log.error(tree.pos(), "intf.expected.here");
// return errType is necessary since otherwise there might // return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop // be undetected cycles which cause attribution to loop
return types.createErrorType(t); return types.createErrorType(t);
} else if (interfacesOrArraysExpected &&
!(t.tsym.isInterface() || t.getTag() == ARRAY)) {
log.error(tree.pos(), "intf.or.array.expected.here");
// return errType is necessary since otherwise there might
// be undetected cycles which cause attribution to loop
return types.createErrorType(t);
} else if (checkExtensible && } else if (checkExtensible &&
classExpected && classExpected &&
t.tsym.isInterface()) { t.tsym.isInterface()) {
@ -3988,7 +3995,7 @@ public class Attr extends JCTree.Visitor {
Set<Type> boundSet = new HashSet<Type>(); Set<Type> boundSet = new HashSet<Type>();
if (bounds.nonEmpty()) { if (bounds.nonEmpty()) {
// accept class or interface or typevar as first bound. // accept class or interface or typevar as first bound.
bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false); bounds.head.type = checkBase(bounds.head.type, bounds.head, env, false, false, false, false);
boundSet.add(types.erasure(bounds.head.type)); boundSet.add(types.erasure(bounds.head.type));
if (bounds.head.type.isErroneous()) { if (bounds.head.type.isErroneous()) {
return bounds.head.type; return bounds.head.type;
@ -4004,7 +4011,7 @@ public class Attr extends JCTree.Visitor {
// if first bound was a class or interface, accept only interfaces // if first bound was a class or interface, accept only interfaces
// as further bounds. // as further bounds.
for (JCExpression bound : bounds.tail) { for (JCExpression bound : bounds.tail) {
bound.type = checkBase(bound.type, bound, env, false, true, false); bound.type = checkBase(bound.type, bound, env, false, false, true, false);
if (bound.type.isErroneous()) { if (bound.type.isErroneous()) {
bounds = List.of(bound); bounds = List.of(bound);
} }

View file

@ -3420,15 +3420,14 @@ public class Check {
sym.name != names.error && sym.name != names.error &&
(!staticImport || !e.isStaticallyImported())) { (!staticImport || !e.isStaticallyImported())) {
if (!e.sym.type.isErroneous()) { if (!e.sym.type.isErroneous()) {
String what = e.sym.toString();
if (!isClassDecl) { if (!isClassDecl) {
if (staticImport) if (staticImport)
log.error(pos, "already.defined.static.single.import", what); log.error(pos, "already.defined.static.single.import", e.sym);
else else
log.error(pos, "already.defined.single.import", what); log.error(pos, "already.defined.single.import", e.sym);
} }
else if (sym != e.sym) else if (sym != e.sym)
log.error(pos, "already.defined.this.unit", what); log.error(pos, "already.defined.this.unit", e.sym);
} }
return false; return false;
} }

View file

@ -114,12 +114,15 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
deferredLintHandler = DeferredLintHandler.instance(context); deferredLintHandler = DeferredLintHandler.instance(context);
lint = Lint.instance(context); lint = Lint.instance(context);
allowTypeAnnos = source.allowTypeAnnotations(); allowTypeAnnos = source.allowTypeAnnotations();
allowRepeatedAnnos = source.allowRepeatedAnnotations();
} }
/** Switch: support type annotations. /** Switch: support type annotations.
*/ */
boolean allowTypeAnnos; boolean allowTypeAnnos;
boolean allowRepeatedAnnos;
/** A queue for classes whose members still need to be entered into the /** A queue for classes whose members still need to be entered into the
* symbol table. * symbol table.
*/ */
@ -906,14 +909,14 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
} }
if (annotated.containsKey(a.type.tsym)) { if (annotated.containsKey(a.type.tsym)) {
if (source.allowRepeatedAnnotations()) { if (!allowRepeatedAnnos) {
ListBuffer<Attribute.Compound> l = annotated.get(a.type.tsym); log.error(a.pos(), "repeatable.annotations.not.supported.in.source");
l = l.append(c); allowRepeatedAnnos = true;
annotated.put(a.type.tsym, l);
pos.put(c, a.pos());
} else {
log.error(a.pos(), "duplicate.annotation");
} }
ListBuffer<Attribute.Compound> l = annotated.get(a.type.tsym);
l = l.append(c);
annotated.put(a.type.tsym, l);
pos.put(c, a.pos());
} else { } else {
annotated.put(a.type.tsym, ListBuffer.of(c)); annotated.put(a.type.tsym, ListBuffer.of(c));
pos.put(c, a.pos()); pos.put(c, a.pos());
@ -1197,7 +1200,7 @@ public class MemberEnter extends JCTree.Visitor implements Completer {
annotated.put(a.type.tsym, l); annotated.put(a.type.tsym, l);
pos.put(tc, a.pos()); pos.put(tc, a.pos());
} else { } else {
log.error(a.pos(), "duplicate.annotation"); log.error(a.pos(), "repeatable.annotations.not.supported.in.source");
} }
} else { } else {
annotated.put(a.type.tsym, ListBuffer.of(tc)); annotated.put(a.type.tsym, ListBuffer.of(tc));

View file

@ -78,26 +78,26 @@ compiler.err.already.defined.in.clinit=\
# 0: string # 0: string
compiler.err.already.defined.single.import=\ compiler.err.already.defined.single.import=\
{0} is already defined in a single-type import a type with the same simple name is already defined by the single-type-import of {0}
# 0: string # 0: string
compiler.err.already.defined.static.single.import=\ compiler.err.already.defined.static.single.import=\
{0} is already defined in a static single-type import a type with the same simple name is already defined by the static single-type-import of {0}
compiler.err.already.defined.this.unit=\ compiler.err.already.defined.this.unit=\
{0} is already defined in this compilation unit {0} is already defined in this compilation unit
# 0: type, 1: list of name # 0: type, 1: list of name
compiler.err.annotation.missing.default.value=\ compiler.err.annotation.missing.default.value=\
annotation {0} is missing value for the attribute {1} annotation @{0} is missing a default value for the element ''{1}''
# 0: type, 1: list of name # 0: type, 1: list of name
compiler.err.annotation.missing.default.value.1=\ compiler.err.annotation.missing.default.value.1=\
annotation {0} is missing values for attributes {1} annotation @{0} is missing default values for elements {1}
# 0: type # 0: type
compiler.err.annotation.not.valid.for.type=\ compiler.err.annotation.not.valid.for.type=\
annotation not valid for a value of type {0} annotation not valid for an element of type {0}
compiler.err.annotation.type.not.applicable=\ compiler.err.annotation.type.not.applicable=\
annotation type not applicable to this kind of declaration annotation type not applicable to this kind of declaration
@ -135,7 +135,7 @@ compiler.err.array.req.but.found=\
array required, but {0} found array required, but {0} found
compiler.err.attribute.value.must.be.constant=\ compiler.err.attribute.value.must.be.constant=\
attribute value must be constant element value must be a constant expression
# 0: statement type # 0: statement type
compiler.err.bad.initializer=\ compiler.err.bad.initializer=\
@ -298,8 +298,9 @@ compiler.err.cont.outside.loop=\
compiler.err.cyclic.inheritance=\ compiler.err.cyclic.inheritance=\
cyclic inheritance involving {0} cyclic inheritance involving {0}
# 0: symbol
compiler.err.cyclic.annotation.element=\ compiler.err.cyclic.annotation.element=\
cyclic annotation element type type of element {0} is cyclic
# 0: unused # 0: unused
compiler.err.call.to.super.not.allowed.in.enum.ctor=\ compiler.err.call.to.super.not.allowed.in.enum.ctor=\
@ -307,73 +308,70 @@ compiler.err.call.to.super.not.allowed.in.enum.ctor=\
# 0: type # 0: type
compiler.err.no.superclass=\ compiler.err.no.superclass=\
{0} has no superclass {0} has no superclass.
# 0: symbol, 1: type, 2: symbol, 3: type, 4: unused # 0: symbol, 1: type, 2: symbol, 3: type, 4: unused
compiler.err.concrete.inheritance.conflict=\ compiler.err.concrete.inheritance.conflict=\
methods {0} from {1} and {2} from {3} are inherited with the same signature methods {0} from {1} and {2} from {3} are inherited with the same signature
compiler.err.default.allowed.in.intf.annotation.member=\ compiler.err.default.allowed.in.intf.annotation.member=\
default value only allowed in an @interface member default value only allowed in an annotation type declaration
# 0: symbol # 0: symbol
compiler.err.doesnt.exist=\ compiler.err.doesnt.exist=\
package {0} does not exist package {0} does not exist
compiler.err.duplicate.annotation=\
duplicate annotation
# 0: type # 0: type
compiler.err.duplicate.annotation.invalid.repeated=\ compiler.err.duplicate.annotation.invalid.repeated=\
annotation {0} cannot be repeated\nIt does not define a valid containing annotation. annotation {0} is not a valid repeatable annotation
# 0: name, 1: type # 0: name, 1: type
compiler.err.duplicate.annotation.member.value=\ compiler.err.duplicate.annotation.member.value=\
duplicate annotation member value {0} in {1} duplicate element ''{0}'' in annotation @{1}.
# 0: type, 1: type # 0: name, 1: unused
compiler.err.duplicate.annotation.missing.container=\ compiler.err.duplicate.annotation.missing.container=\
duplicate annotation: the declaration of {0} does not have a valid {1} annotation {0} is not a repeatable annotation type
# 0: type # 0: type, 1: unused
compiler.err.invalid.repeatable.annotation=\ compiler.err.invalid.repeatable.annotation=\
duplicate annotation: {0} is annotated with an invalid Repeatable annotation duplicate annotation: {0} is annotated with an invalid @Repeatable annotation
# 0: symbol or type # 0: symbol or type
compiler.err.invalid.repeatable.annotation.no.value=\ compiler.err.invalid.repeatable.annotation.no.value=\
duplicate annotation: {0} is not a valid Repeatable, no value element method declared {0} is not a valid @Repeatable, no value element method declared
# 0: type, 1: number # 0: type, 1: number
compiler.err.invalid.repeatable.annotation.multiple.values=\ compiler.err.invalid.repeatable.annotation.multiple.values=\
duplicate annotation: {0} is not a valid Repeatable, {1} value element methods declared {0} is not a valid @Repeatable, {1} element methods named ''value'' declared
# 0: type # 0: type
compiler.err.invalid.repeatable.annotation.invalid.value=\ compiler.err.invalid.repeatable.annotation.invalid.value=\
duplicate annotation: {0} is not a valid Repeatable: invalid value element {0} is not a valid @Repeatable: invalid value element
# 0: symbol type, 1: type, 2: type # 0: symbol type, 1: unused, 2: type
compiler.err.invalid.repeatable.annotation.value.return=\ compiler.err.invalid.repeatable.annotation.value.return=\
duplicate annotation: value element of containing annotation {0} should have type {2}, found {1} containing annotation type ({0}) must declare an element named ''value'' of type {2}
# 0: symbol or type, 1: symbol # 0: symbol or type, 1: symbol
compiler.err.invalid.repeatable.annotation.elem.nondefault=\ compiler.err.invalid.repeatable.annotation.elem.nondefault=\
containing annotation {0} does not have a default value for element {1} containing annotation type ({0}) does not have a default value for element {1}
# 0: symbol, 1: type, 2: symbol, 3: type # 0: symbol, 1: unused, 2: symbol, 3: unused
compiler.err.invalid.repeatable.annotation.retention=\ compiler.err.invalid.repeatable.annotation.retention=\
containing annotation {0} has shorter retention ({1}) than the contained annotation {2} with retention {3} retention of containing annotation type ({0}) is shorter than the retention of repeatable annotation type ({2})
# 0: symbol, 1: symbol # 0: symbol, 1: symbol
compiler.err.invalid.repeatable.annotation.not.documented=\ compiler.err.invalid.repeatable.annotation.not.documented=\
containing annotation type, {0}, is not @Documented while repeated annotation type, {1}, is repeatable annotation type ({1}) is @Documented while containing annotation type ({0}) is not
# 0: symbol, 1: symbol # 0: symbol, 1: symbol
compiler.err.invalid.repeatable.annotation.not.inherited=\ compiler.err.invalid.repeatable.annotation.not.inherited=\
containing annotation type, {0}, is not @Inherited while repeated annotation type, {1}, is repeatable annotation type ({1}) is @Inherited while containing annotation type ({0}) is not
# 0: symbol, 1: symbol # 0: symbol, 1: symbol
compiler.err.invalid.repeatable.annotation.incompatible.target=\ compiler.err.invalid.repeatable.annotation.incompatible.target=\
target of container annotation {0} is not a subset of target of repeated annotation {1} containing annotation type ({0}) is applicable to more targets than repeatable annotation type ({1})
# 0: symbol # 0: symbol
compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\ compiler.err.invalid.repeatable.annotation.repeated.and.container.present=\
@ -561,26 +559,31 @@ compiler.err.int.number.too.large=\
integer number too large: {0} integer number too large: {0}
compiler.err.intf.annotation.members.cant.have.params=\ compiler.err.intf.annotation.members.cant.have.params=\
@interface members may not have parameters elements in annotation type declarations cannot declare formal parameters
# 0: symbol
compiler.err.intf.annotation.cant.have.type.params=\ compiler.err.intf.annotation.cant.have.type.params=\
@interface may not have type parameters annotation type {0} cannot be generic
compiler.err.intf.annotation.members.cant.have.type.params=\ compiler.err.intf.annotation.members.cant.have.type.params=\
@interface members may not have type parameters elements in annotation type declarations cannot be generic methods
# 0: symbol, 1: type # 0: symbol, 1: type
compiler.err.intf.annotation.member.clash=\ compiler.err.intf.annotation.member.clash=\
@interface member clashes with method ''{0}'' in {1} annotation type {1} declares an element with the same name as method {0}
compiler.err.intf.expected.here=\ compiler.err.intf.expected.here=\
interface expected here interface expected here
compiler.err.intf.or.array.expected.here=\
interface or array type expected here
compiler.err.intf.meth.cant.have.body=\ compiler.err.intf.meth.cant.have.body=\
interface abstract methods cannot have body interface abstract methods cannot have body
# 0: symbol
compiler.err.invalid.annotation.member.type=\ compiler.err.invalid.annotation.member.type=\
invalid type for annotation member invalid type for element {0} of annotation type
compiler.err.invalid.binary.number=\ compiler.err.invalid.binary.number=\
binary numbers must contain at least one binary digit binary numbers must contain at least one binary digit
@ -2309,9 +2312,14 @@ compiler.err.type.annotations.not.supported.in.source=\
type annotations are not supported in -source {0}\n\ type annotations are not supported in -source {0}\n\
(use -source 8 or higher to enable type annotations) (use -source 8 or higher to enable type annotations)
# 0: string
compiler.err.repeatable.annotations.not.supported.in.source=\
repeated annotations are not supported in -source {0}\n\
(use -source 8 or higher to enable repeated annotations)
# 0: string # 0: string
compiler.err.foreach.not.supported.in.source=\ compiler.err.foreach.not.supported.in.source=\
for-each loops are not supported in -source {0}\n\ enhanced for loops are not supported in -source {0}\n\
(use -source 5 or higher to enable for-each loops) (use -source 5 or higher to enable for-each loops)
# 0: string # 0: string

View file

@ -0,0 +1,28 @@
/*
* Copyright (c) 2013, 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.intf.or.array.expected.here
import java.util.List;
class InterfaceExpected<T extends List & String> { }

View file

@ -21,7 +21,7 @@
* questions. * questions.
*/ */
// key: compiler.err.duplicate.annotation // key: compiler.err.repeatable.annotations.not.supported.in.source
// key: compiler.warn.source.no.bootclasspath // key: compiler.warn.source.no.bootclasspath
// options: -source 7 // options: -source 7
@ -29,4 +29,4 @@
@Anno @Anno
@Anno @Anno
class DuplicateAnnotation { } class RepeatableAnnotationsNotSupported { }