6747671: -Xlint:rawtypes

Add an Xlint option for detecting all raw types usages (ccc-approved)

Reviewed-by: jjg
This commit is contained in:
Maurizio Cimadamore 2008-09-29 12:00:29 +01:00
parent a8d5a91270
commit 5fc92453b6
8 changed files with 128 additions and 30 deletions

View File

@ -183,7 +183,12 @@ public class Lint
/** /**
* Warn about unchecked operations on raw types. * Warn about unchecked operations on raw types.
*/ */
UNCHECKED("unchecked"); UNCHECKED("unchecked"),
/**
* Warn about unchecked operations on raw types.
*/
RAW("rawtypes");
LintCategory(String option) { LintCategory(String option) {
this.option = option; this.option = option;

View File

@ -614,14 +614,14 @@ public class Attr extends JCTree.Visitor {
} }
// Check that type parameters are well-formed. // Check that type parameters are well-formed.
chk.validateTypeParams(tree.typarams); chk.validate(tree.typarams, localEnv);
if ((owner.flags() & ANNOTATION) != 0 && if ((owner.flags() & ANNOTATION) != 0 &&
tree.typarams.nonEmpty()) tree.typarams.nonEmpty())
log.error(tree.typarams.head.pos(), log.error(tree.typarams.head.pos(),
"intf.annotation.members.cant.have.type.params"); "intf.annotation.members.cant.have.type.params");
// Check that result type is well-formed. // Check that result type is well-formed.
chk.validate(tree.restype); chk.validate(tree.restype, localEnv);
if ((owner.flags() & ANNOTATION) != 0) if ((owner.flags() & ANNOTATION) != 0)
chk.validateAnnotationType(tree.restype); chk.validateAnnotationType(tree.restype);
@ -707,7 +707,7 @@ public class Attr extends JCTree.Visitor {
} }
// Check that the variable's declared type is well-formed. // Check that the variable's declared type is well-formed.
chk.validate(tree.vartype); chk.validate(tree.vartype, env);
VarSymbol v = tree.sym; VarSymbol v = tree.sym;
Lint lint = env.info.lint.augment(v.attributes_field, v.flags()); Lint lint = env.info.lint.augment(v.attributes_field, v.flags());
@ -1322,7 +1322,7 @@ public class Attr extends JCTree.Visitor {
// current context. Also, capture the return type // current context. Also, capture the return type
result = check(tree, capture(restype), VAL, pkind, pt); result = check(tree, capture(restype), VAL, pkind, pt);
} }
chk.validate(tree.typeargs); chk.validate(tree.typeargs, localEnv);
} }
//where //where
/** Check that given application node appears as first statement /** Check that given application node appears as first statement
@ -1397,7 +1397,7 @@ public class Attr extends JCTree.Visitor {
// symbol + type back into the attributed tree. // symbol + type back into the attributed tree.
Type clazztype = chk.checkClassType( Type clazztype = chk.checkClassType(
tree.clazz.pos(), attribType(clazz, env), true); tree.clazz.pos(), attribType(clazz, env), true);
chk.validate(clazz); chk.validate(clazz, localEnv);
if (tree.encl != null) { if (tree.encl != null) {
// We have to work in this case to store // We have to work in this case to store
// symbol + type back into the attributed tree. // symbol + type back into the attributed tree.
@ -1533,7 +1533,7 @@ public class Attr extends JCTree.Visitor {
owntype = clazztype; owntype = clazztype;
} }
result = check(tree, owntype, VAL, pkind, pt); result = check(tree, owntype, VAL, pkind, pt);
chk.validate(tree.typeargs); chk.validate(tree.typeargs, localEnv);
} }
/** Make an attributed null check tree. /** Make an attributed null check tree.
@ -1555,7 +1555,7 @@ public class Attr extends JCTree.Visitor {
Type elemtype; Type elemtype;
if (tree.elemtype != null) { if (tree.elemtype != null) {
elemtype = attribType(tree.elemtype, env); elemtype = attribType(tree.elemtype, env);
chk.validate(tree.elemtype); chk.validate(tree.elemtype, env);
owntype = elemtype; owntype = elemtype;
for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) { for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
attribExpr(l.head, env, syms.intType); attribExpr(l.head, env, syms.intType);
@ -1711,6 +1711,7 @@ public class Attr extends JCTree.Visitor {
public void visitTypeCast(JCTypeCast tree) { public void visitTypeCast(JCTypeCast tree) {
Type clazztype = attribType(tree.clazz, env); Type clazztype = attribType(tree.clazz, env);
chk.validate(tree.clazz, env);
Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly); Type exprtype = attribExpr(tree.expr, env, Infer.anyPoly);
Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype); Type owntype = chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
if (exprtype.constValue() != null) if (exprtype.constValue() != null)
@ -1723,6 +1724,7 @@ public class Attr extends JCTree.Visitor {
tree.expr.pos(), attribExpr(tree.expr, env)); tree.expr.pos(), attribExpr(tree.expr, env));
Type clazztype = chk.checkReifiableReferenceType( Type clazztype = chk.checkReifiableReferenceType(
tree.clazz.pos(), attribType(tree.clazz, env)); tree.clazz.pos(), attribType(tree.clazz, env));
chk.validate(tree.clazz, env);
chk.checkCastable(tree.expr.pos(), exprtype, clazztype); chk.checkCastable(tree.expr.pos(), exprtype, clazztype);
result = check(tree, syms.booleanType, VAL, pkind, pt); result = check(tree, syms.booleanType, VAL, pkind, pt);
} }
@ -2695,9 +2697,9 @@ public class Attr extends JCTree.Visitor {
// Validate type parameters, supertype and interfaces. // Validate type parameters, supertype and interfaces.
attribBounds(tree.typarams); attribBounds(tree.typarams);
chk.validateTypeParams(tree.typarams); chk.validate(tree.typarams, env);
chk.validate(tree.extending); chk.validate(tree.extending, env);
chk.validate(tree.implementing); chk.validate(tree.implementing, env);
// If this is a non-abstract class, check that it has no abstract // If this is a non-abstract class, check that it has no abstract
// methods or unimplemented methods of an implemented interface. // methods or unimplemented methods of an implemented interface.

View File

@ -764,26 +764,32 @@ public class Check {
/** Visitor method: Validate a type expression, if it is not null, catching /** Visitor method: Validate a type expression, if it is not null, catching
* and reporting any completion failures. * and reporting any completion failures.
*/ */
void validate(JCTree tree) { void validate(JCTree tree, Env<AttrContext> env) {
try { try {
if (tree != null) tree.accept(validator); if (tree != null) {
validator.env = env;
tree.accept(validator);
checkRaw(tree, env);
}
} catch (CompletionFailure ex) { } catch (CompletionFailure ex) {
completionError(tree.pos(), 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. /** 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) for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail)
validate(l.head); validate(l.head, env);
}
/** 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);
} }
/** A visitor class for type validation. /** A visitor class for type validation.
@ -791,7 +797,7 @@ public class Check {
class Validator extends JCTree.Visitor { class Validator extends JCTree.Visitor {
public void visitTypeArray(JCArrayTypeTree tree) { public void visitTypeArray(JCArrayTypeTree tree) {
validate(tree.elemtype); validate(tree.elemtype, env);
} }
public void visitTypeApply(JCTypeApply tree) { public void visitTypeApply(JCTypeApply tree) {
@ -805,7 +811,7 @@ public class Check {
// For matching pairs of actual argument types `a' and // For matching pairs of actual argument types `a' and
// formal type parameters with declared bound `b' ... // formal type parameters with declared bound `b' ...
while (args.nonEmpty() && forms.nonEmpty()) { while (args.nonEmpty() && forms.nonEmpty()) {
validate(args.head); validate(args.head, env);
// exact type arguments needs to know their // exact type arguments needs to know their
// bounds (for upper and lower bound // bounds (for upper and lower bound
@ -849,14 +855,14 @@ public class Check {
} }
public void visitTypeParameter(JCTypeParameter tree) { public void visitTypeParameter(JCTypeParameter tree) {
validate(tree.bounds); validate(tree.bounds, env);
checkClassBounds(tree.pos(), tree.type); checkClassBounds(tree.pos(), tree.type);
} }
@Override @Override
public void visitWildcard(JCWildcard tree) { public void visitWildcard(JCWildcard tree) {
if (tree.inner != null) if (tree.inner != null)
validate(tree.inner); validate(tree.inner, env);
} }
public void visitSelect(JCFieldAccess tree) { public void visitSelect(JCFieldAccess tree) {
@ -870,7 +876,7 @@ public class Check {
} }
} }
public void visitSelectInternal(JCFieldAccess tree) { public void visitSelectInternal(JCFieldAccess tree) {
if (tree.type.getEnclosingType().tag != CLASS && if (tree.type.tsym.isStatic() &&
tree.selected.type.isParameterized()) { tree.selected.type.isParameterized()) {
// The enclosing type is not a class, so we are // The enclosing type is not a class, so we are
// looking at a static member type. However, the // looking at a static member type. However, the
@ -878,7 +884,7 @@ public class Check {
log.error(tree.pos(), "cant.select.static.class.from.param.type"); log.error(tree.pos(), "cant.select.static.class.from.param.type");
} else { } else {
// otherwise validate the rest of the expression // otherwise validate the rest of the expression
validate(tree.selected); tree.selected.accept(this);
} }
} }
@ -886,6 +892,8 @@ public class Check {
*/ */
public void visitTree(JCTree tree) { public void visitTree(JCTree tree) {
} }
Env<AttrContext> env;
} }
/* ************************************************************************* /* *************************************************************************

View File

@ -770,6 +770,10 @@ compiler.warn.annotation.method.not.found=\
compiler.warn.annotation.method.not.found.reason=\ compiler.warn.annotation.method.not.found.reason=\
Cannot find annotation method ''{1}()'' in type ''{0}'': {2} 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 ## The following are tokens which are non-terminals in the language. They should

View File

@ -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 T6304921.java:667/667/682: warning: [unchecked] unchecked conversion
found : java.util.ArrayList found : java.util.ArrayList
required: java.util.List<java.lang.Integer> required: java.util.List<java.lang.Integer>
@ -18,4 +22,4 @@ T6304921.java:812/816/822: operator + cannot be applied to int,boolean
return 123 + true; // bad binary expression return 123 + true; // bad binary expression
^ ^
2 errors 2 errors
3 warnings 4 warnings

View File

@ -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
}
}

View File

@ -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

View File

@ -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: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 Unchecked.java:58:14: compiler.warn.unchecked.call.mbr.of.raw.type: add(E), java.util.List
2 warnings 7 warnings