6747671: -Xlint:rawtypes
Summary: add an Xlint option for detecting all raw types usages (ccc-approved)
Reviewed-by: jjg
--- a/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/code/Lint.java Mon Sep 29 12:00:29 2008 +0100
@@ -183,7 +183,12 @@
/**
* Warn about unchecked operations on raw types.
*/
- UNCHECKED("unchecked");
+ UNCHECKED("unchecked"),
+
+ /**
+ * Warn about unchecked operations on raw types.
+ */
+ RAW("rawtypes");
LintCategory(String option) {
this.option = option;
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Attr.java Mon Sep 29 12:00:29 2008 +0100
@@ -614,14 +614,14 @@
}
// Check that type parameters are well-formed.
- chk.validateTypeParams(tree.typarams);
+ chk.validate(tree.typarams, localEnv);
if ((owner.flags() & ANNOTATION) != 0 &&
tree.typarams.nonEmpty())
log.error(tree.typarams.head.pos(),
"intf.annotation.members.cant.have.type.params");
// Check that result type is well-formed.
- chk.validate(tree.restype);
+ chk.validate(tree.restype, localEnv);
if ((owner.flags() & ANNOTATION) != 0)
chk.validateAnnotationType(tree.restype);
@@ -707,7 +707,7 @@
}
// Check that the variable's declared type is well-formed.
- chk.validate(tree.vartype);
+ chk.validate(tree.vartype, env);
VarSymbol v = tree.sym;
Lint lint = env.info.lint.augment(v.attributes_field, v.flags());
@@ -1322,7 +1322,7 @@
// current context. Also, capture the return type
result = check(tree, capture(restype), VAL, pkind, pt);
}
- chk.validate(tree.typeargs);
+ chk.validate(tree.typeargs, localEnv);
}
//where
/** Check that given application node appears as first statement
@@ -1397,7 +1397,7 @@
// symbol + type back into the attributed tree.
Type clazztype = chk.checkClassType(
tree.clazz.pos(), attribType(clazz, env), true);
- chk.validate(clazz);
+ chk.validate(clazz, localEnv);
if (tree.encl != null) {
// We have to work in this case to store
// symbol + type back into the attributed tree.
@@ -1533,7 +1533,7 @@
owntype = clazztype;
}
result = check(tree, owntype, VAL, pkind, pt);
- chk.validate(tree.typeargs);
+ chk.validate(tree.typeargs, localEnv);
}
/** Make an attributed null check tree.
@@ -1555,7 +1555,7 @@
Type elemtype;
if (tree.elemtype != null) {
elemtype = attribType(tree.elemtype, env);
- chk.validate(tree.elemtype);
+ chk.validate(tree.elemtype, env);
owntype = elemtype;
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
attribExpr(l.head, env, syms.intType);
@@ -1711,6 +1711,7 @@
public void visitTypeCast(JCTypeCast tree) {
Type clazztype = attribType(tree.clazz, env);
+ chk.validate(tree.clazz, env);
Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly);
Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
if (exprtype.constValue() != null)
@@ -1723,6 +1724,7 @@
tree.expr.pos(), attribExpr(tree.expr, env));
Type clazztype = chk.checkReifiableReferenceType(
tree.clazz.pos(), attribType(tree.clazz, env));
+ chk.validate(tree.clazz, env);
chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
result = check(tree, syms.booleanType, VAL, pkind, pt);
}
@@ -2695,9 +2697,9 @@
// Validate type parameters, supertype and interfaces.
attribBounds(tree.typarams);
- chk.validateTypeParams(tree.typarams);
- chk.validate(tree.extending);
- chk.validate(tree.implementing);
+ chk.validate(tree.typarams, env);
+ chk.validate(tree.extending, env);
+ chk.validate(tree.implementing, env);
// If this is a non-abstract class, check that it has no abstract
// methods or unimplemented methods of an implemented interface.
--- a/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/comp/Check.java Mon Sep 29 12:00:29 2008 +0100
@@ -764,26 +764,32 @@
/** Visitor method: Validate a type expression, if it is not null, catching
* and reporting any completion failures.
*/
- void validate(JCTree tree) {
+ void validate(JCTree tree, Env<AttrContext> env) {
try {
- if (tree != null) tree.accept(validator);
+ if (tree != null) {
+ validator.env = env;
+ tree.accept(validator);
+ checkRaw(tree, env);
+ }
} catch (CompletionFailure ex) {
completionError(tree.pos(), ex);
}
}
+ //where
+ void checkRaw(JCTree tree, Env<AttrContext> env) {
+ if (lint.isEnabled(Lint.LintCategory.RAW) &&
+ tree.type.tag == CLASS &&
+ !env.enclClass.name.isEmpty() && //anonymous or intersection
+ tree.type.isRaw()) {
+ log.warning(tree.pos(), "raw.class.use", tree.type, tree.type.tsym.type);
+ }
+ }
/** Visitor method: Validate a list of type expressions.
*/
- void validate(List<? extends JCTree> trees) {
+ void validate(List<? extends JCTree> trees, Env<AttrContext> env) {
for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
- validate(l.head);
- }
-
- /** Visitor method: Validate a list of type parameters.
- */
- void validateTypeParams(List<JCTypeParameter> trees) {
- for (List<JCTypeParameter> l = trees; l.nonEmpty(); l = l.tail)
- validate(l.head);
+ validate(l.head, env);
}
/** A visitor class for type validation.
@@ -791,7 +797,7 @@
class Validator extends JCTree.Visitor {
public void visitTypeArray(JCArrayTypeTree tree) {
- validate(tree.elemtype);
+ validate(tree.elemtype, env);
}
public void visitTypeApply(JCTypeApply tree) {
@@ -805,7 +811,7 @@
// For matching pairs of actual argument types `a' and
// formal type parameters with declared bound `b' ...
while (args.nonEmpty() && forms.nonEmpty()) {
- validate(args.head);
+ validate(args.head, env);
// exact type arguments needs to know their
// bounds (for upper and lower bound
@@ -849,14 +855,14 @@
}
public void visitTypeParameter(JCTypeParameter tree) {
- validate(tree.bounds);
+ validate(tree.bounds, env);
checkClassBounds(tree.pos(), tree.type);
}
@Override
public void visitWildcard(JCWildcard tree) {
if (tree.inner != null)
- validate(tree.inner);
+ validate(tree.inner, env);
}
public void visitSelect(JCFieldAccess tree) {
@@ -870,7 +876,7 @@
}
}
public void visitSelectInternal(JCFieldAccess tree) {
- if (tree.type.getEnclosingType().tag != CLASS &&
+ if (tree.type.tsym.isStatic() &&
tree.selected.type.isParameterized()) {
// The enclosing type is not a class, so we are
// looking at a static member type. However, the
@@ -878,7 +884,7 @@
log.error(tree.pos(), "cant.select.static.class.from.param.type");
} else {
// otherwise validate the rest of the expression
- validate(tree.selected);
+ tree.selected.accept(this);
}
}
@@ -886,6 +892,8 @@
*/
public void visitTree(JCTree tree) {
}
+
+ Env<AttrContext> env;
}
/* *************************************************************************
--- a/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/src/share/classes/com/sun/tools/javac/resources/compiler.properties Mon Sep 29 12:00:29 2008 +0100
@@ -770,6 +770,10 @@
compiler.warn.annotation.method.not.found.reason=\
Cannot find annotation method ''{1}()'' in type ''{0}'': {2}
+compiler.warn.raw.class.use=\
+ [raw-type] found raw type: {0}\n\
+ missing type parameters for generic class {1}
+
#####
## The following are tokens which are non-terminals in the language. They should
--- a/langtools/test/tools/javac/6304921/T6304921.out Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/test/tools/javac/6304921/T6304921.out Mon Sep 29 12:00:29 2008 +0100
@@ -1,3 +1,7 @@
+T6304921.java:671/671/680: warning: [raw-type] found raw type: java.util.ArrayList
+missing type parameters for generic class java.util.ArrayList<E>
+ List<Integer> list = new ArrayList();
+ ^
T6304921.java:667/667/682: warning: [unchecked] unchecked conversion
found : java.util.ArrayList
required: java.util.List<java.lang.Integer>
@@ -18,4 +22,4 @@
return 123 + true; // bad binary expression
^
2 errors
-3 warnings
+4 warnings
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/6747671/T6747671.java Mon Sep 29 12:00:29 2008 +0100
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2008 Sun Microsystems, Inc. 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
+ * CA 95054 USA or visit www.sun.com if you need additional information or
+ * have any questions.
+ */
+
+/**
+ * @test
+ * @bug 6747671
+ * @summary -Xlint:rawtypes
+ * @compile/ref=T6747671.out -XDrawDiagnostics -Xlint:rawtypes T6747671.java
+ */
+
+
+class T6747671<E> {
+
+ static class B<X> {}
+
+ class A<X> {
+ class X {}
+ class Z<Y> {}
+ }
+
+
+ A.X x1;//raw warning
+ A.Z z1;//raw warning
+
+ T6747671.B<Integer> b1;//ok
+ T6747671.B b2;//raw warning
+
+ A<String>.X x2;//ok
+ A<String>.Z<Integer> z2;//ok
+ A<B>.Z<A<B>> z3;//raw warning (2)
+
+ void test(Object arg1, B arg2) {//raw warning
+ boolean b = arg1 instanceof A;//raw warning
+ Object a = (A)arg1;//raw warning
+ A a2 = new A() {};//raw warning (2)
+ a2.new Z() {};//raw warning
+ }
+}
\ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/langtools/test/tools/javac/warnings/6747671/T6747671.out Mon Sep 29 12:00:29 2008 +0100
@@ -0,0 +1,12 @@
+T6747671.java:42:6: compiler.warn.raw.class.use: T6747671.A.X, T6747671<E>.A<X>.X
+T6747671.java:43:6: compiler.warn.raw.class.use: T6747671.A.Z, T6747671<E>.A<X>.Z<Y>
+T6747671.java:46:13: compiler.warn.raw.class.use: T6747671.B, T6747671.B<X>
+T6747671.java:50:14: compiler.warn.raw.class.use: T6747671.B, T6747671.B<X>
+T6747671.java:50:7: compiler.warn.raw.class.use: T6747671.B, T6747671.B<X>
+T6747671.java:52:28: compiler.warn.raw.class.use: T6747671.B, T6747671.B<X>
+T6747671.java:53:37: compiler.warn.raw.class.use: T6747671.A, T6747671<E>.A<X>
+T6747671.java:54:21: compiler.warn.raw.class.use: T6747671.A, T6747671<E>.A<X>
+T6747671.java:55:9: compiler.warn.raw.class.use: T6747671.A, T6747671<E>.A<X>
+T6747671.java:55:20: compiler.warn.raw.class.use: T6747671.A, T6747671<E>.A<X>
+T6747671.java:56:16: compiler.warn.raw.class.use: T6747671.A.Z, T6747671<E>.A<X>.Z<Y>
+11 warnings
\ No newline at end of file
--- a/langtools/test/tools/javac/warnings/Unchecked.lintAll.out Mon Sep 29 11:48:09 2008 +0100
+++ b/langtools/test/tools/javac/warnings/Unchecked.lintAll.out Mon Sep 29 12:00:29 2008 +0100
@@ -1,3 +1,8 @@
+Unchecked.java:16:9: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
Unchecked.java:17:14: compiler.warn.unchecked.call.mbr.of.raw.type: add(E), java.util.List
+Unchecked.java:26:9: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
+Unchecked.java:35:9: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
+Unchecked.java:46:21: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
+Unchecked.java:57:9: compiler.warn.raw.class.use: java.util.List, java.util.List<E>
Unchecked.java:58:14: compiler.warn.unchecked.call.mbr.of.raw.type: add(E), java.util.List
-2 warnings
+7 warnings
\ No newline at end of file