Backed out the BCEL based checking for unused class member variables.
This commit is contained in:
parent
8a65d2ff82
commit
92ea4cfb51
|
|
@ -10,7 +10,6 @@
|
|||
<property name="antlr.jar" value="lib/antlr.jar" />
|
||||
<property name="antlr-tools.jar" value="lib/antlr-tools.jar" />
|
||||
<property name="regexp.jar" value="lib/jakarta-regexp-1.2.jar" />
|
||||
<property name="bcel.jar" value="lib/bcel.jar" />
|
||||
<property name="junit.jar" value="lib/junit.jar" />
|
||||
|
||||
<property name="checkstyle.dir"
|
||||
|
|
@ -23,7 +22,6 @@
|
|||
<path id="build.classpath">
|
||||
<pathelement location="${antlr.jar}" />
|
||||
<pathelement location="${regexp.jar}" />
|
||||
<pathelement location="${bcel.jar}" />
|
||||
<pathelement location="${ant.home}/lib/ant.jar" />
|
||||
</path>
|
||||
|
||||
|
|
|
|||
BIN
lib/bcel.jar
BIN
lib/bcel.jar
Binary file not shown.
|
|
@ -607,12 +607,6 @@ public class Configuration
|
|||
return getBooleanProperty(Defn.JAVADOC_CHECK_UNUSED_THROWS_PROP);
|
||||
}
|
||||
|
||||
/** @return whether to check unused fields **/
|
||||
boolean isCheckUnusedFields()
|
||||
{
|
||||
return getBooleanProperty(Defn.CHECK_UNUSED_FIELDS_PROP);
|
||||
}
|
||||
|
||||
/** @return Set of pkg prefixes that are illegal in import statements */
|
||||
Set getIllegalImports()
|
||||
{
|
||||
|
|
|
|||
|
|
@ -127,8 +127,6 @@ public interface Defn
|
|||
String BASEDIR_PROP = "checkstyle.basedir";
|
||||
/** property name for wrapping lines on operators **/
|
||||
String WRAP_OP_PROP = "checkstyle.wrap.operator";
|
||||
/** property name for checking for unused fields **/
|
||||
String CHECK_UNUSED_FIELDS_PROP = "checkstyle.checkUnused.fields";
|
||||
|
||||
/** property name for the locale language for reporting **/
|
||||
String LOCALE_LANGUAGE_PROP = "checkstyle.locale.language";
|
||||
|
|
@ -153,7 +151,6 @@ public interface Defn
|
|||
JAVADOC_CHECK_UNUSED_THROWS_PROP,
|
||||
REQUIRE_PACKAGE_HTML_PROP,
|
||||
REQUIRE_VERSION_PROP,
|
||||
CHECK_UNUSED_FIELDS_PROP,
|
||||
};
|
||||
|
||||
/** All the properties that are a regulare expression */
|
||||
|
|
|
|||
|
|
@ -1,277 +0,0 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// checkstyle: Checks Java source code for adherence to a set of rules.
|
||||
// Copyright (C) 2001-2002 Oliver Burn
|
||||
//
|
||||
// This library is free software; you can redistribute it and/or
|
||||
// modify it under the terms of the GNU Lesser General Public
|
||||
// License as published by the Free Software Foundation; either
|
||||
// version 2.1 of the License, or (at your option) any later version.
|
||||
//
|
||||
// This library 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
|
||||
// Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public
|
||||
// License along with this library; if not, write to the Free Software
|
||||
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
package com.puppycrawl.tools.checkstyle;
|
||||
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Code;
|
||||
import org.apache.bcel.classfile.Field;
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
import org.apache.bcel.generic.InstructionHandle;
|
||||
import org.apache.bcel.generic.InstructionList;
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.GETFIELD;
|
||||
import org.apache.bcel.generic.PUTFIELD;
|
||||
import org.apache.bcel.generic.GETSTATIC;
|
||||
import org.apache.bcel.generic.PUTSTATIC;
|
||||
import org.apache.bcel.generic.FieldInstruction;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Used to locate unused constructs using BCEL.
|
||||
* A field is considered if:
|
||||
* <ul>
|
||||
* <li>It is private as another class can access it</li>
|
||||
* <li>It is not final as the compiler can optimise these away</li>
|
||||
* </ul>
|
||||
*
|
||||
* @author <a href="mailto:checkstyle@puppycrawl.com">Oliver Burn</a>
|
||||
* @version 1.0
|
||||
*/
|
||||
class UnusedDetector
|
||||
extends org.apache.bcel.classfile.EmptyVisitor
|
||||
{
|
||||
/** the class being examined */
|
||||
private final JavaClass mJavaClass;
|
||||
/** the found field statistics */
|
||||
private final Map mFieldStats = new HashMap();
|
||||
/** a BCEL pool */
|
||||
private final ConstantPoolGen mPoolGen;
|
||||
/** a BCEL pool */
|
||||
private final ConstantPool mPool;
|
||||
/** used to process the instructions */
|
||||
private final InstructionVisitor mIV = new InstructionVisitor();
|
||||
|
||||
/**
|
||||
* Creates a new <code>UnusedDetector</code> instance.
|
||||
*
|
||||
* @param aJavaClass a <code>JavaClass</code> value
|
||||
*/
|
||||
UnusedDetector(JavaClass aJavaClass)
|
||||
{
|
||||
mJavaClass = aJavaClass;
|
||||
mPool = aJavaClass.getConstantPool();
|
||||
mPoolGen = new ConstantPoolGen(mPool);
|
||||
}
|
||||
|
||||
/** @return the names of all unusued fields */
|
||||
String[] getUnusedFields()
|
||||
{
|
||||
final ArrayList unused = new ArrayList();
|
||||
final Iterator it = mFieldStats.values().iterator();
|
||||
while (it.hasNext()) {
|
||||
final FieldStats fs = (FieldStats) it.next();
|
||||
final Field details = fs.getDetails();
|
||||
if (details.isPrivate()
|
||||
&& !details.isFinal()
|
||||
&& !"this$0".equals(fs.getName()))
|
||||
{
|
||||
if (fs.getReads() == 0) {
|
||||
unused.add(fs.getName());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return (String[]) unused.toArray(new String[unused.size()]);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Classfile Visitor methods
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/** @see org.apache.bcel.classfile.Visitor */
|
||||
public void visitField(Field aField)
|
||||
{
|
||||
reportField(aField);
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.classfile.Visitor */
|
||||
public void visitCode(Code aCode)
|
||||
{
|
||||
// Process all the instructions
|
||||
final InstructionList list = new InstructionList(aCode.getCode());
|
||||
for (InstructionHandle handle = list.getStart();
|
||||
handle != null;
|
||||
handle = handle.getNext())
|
||||
{
|
||||
handle.getInstruction().accept(mIV);
|
||||
}
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Private methods
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* @param aField report the field found
|
||||
*/
|
||||
private void reportField(Field aField)
|
||||
{
|
||||
final FieldStats fs = findFieldStats(aField.getName());
|
||||
fs.setDetails(aField);
|
||||
}
|
||||
|
||||
/** @param aFI report the field is read */
|
||||
private void reportRead(FieldInstruction aFI)
|
||||
{
|
||||
if (memberOfClass(aFI)) {
|
||||
findFieldStats(aFI.getName(mPoolGen)).addRead();
|
||||
}
|
||||
}
|
||||
|
||||
/** @param aFI report the field is written to */
|
||||
private void reportWrite(FieldInstruction aFI)
|
||||
{
|
||||
if (memberOfClass(aFI)) {
|
||||
findFieldStats(aFI.getName(mPoolGen)).addWrite();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return whether the field is from this class
|
||||
* @param aFI the field to check
|
||||
*/
|
||||
private boolean memberOfClass(FieldInstruction aFI)
|
||||
{
|
||||
return mJavaClass.getClassName().equals(
|
||||
aFI.getClassType(mPoolGen).getClassName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the FieldStats for the specifed name. If one does not exist, it
|
||||
* is created
|
||||
* @param aName the field name
|
||||
*/
|
||||
private FieldStats findFieldStats(String aName)
|
||||
{
|
||||
FieldStats retVal = (FieldStats) mFieldStats.get(aName);
|
||||
if (retVal == null) {
|
||||
retVal = new FieldStats(aName);
|
||||
mFieldStats.put(aName, retVal);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Internal types
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Helper class for visiting all the Class instructions. Looks for access
|
||||
* to fields.
|
||||
*
|
||||
*/
|
||||
private class InstructionVisitor
|
||||
extends org.apache.bcel.generic.EmptyVisitor
|
||||
{
|
||||
/** @see org.apache.bcel.generic.EmptyVisitor */
|
||||
public void visitGETFIELD(GETFIELD aField)
|
||||
{
|
||||
reportRead(aField);
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.EmptyVisitor */
|
||||
public void visitPUTFIELD(PUTFIELD aField)
|
||||
{
|
||||
reportWrite(aField);
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.EmptyVisitor */
|
||||
public void visitGETSTATIC(GETSTATIC aField)
|
||||
{
|
||||
reportRead(aField);
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.EmptyVisitor */
|
||||
public void visitPUTSTATIC(PUTSTATIC aField)
|
||||
{
|
||||
reportWrite(aField);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the statistics for a field.
|
||||
*/
|
||||
private static class FieldStats
|
||||
{
|
||||
/** the name of the field */
|
||||
private final String mName;
|
||||
/** number of reads */
|
||||
private int mReads = 0;
|
||||
/** number of writes */
|
||||
private int mWrites = 0;
|
||||
/** field details */
|
||||
private Field mDetails;
|
||||
|
||||
/**
|
||||
* Creates a new <code>FieldStats</code> instance.
|
||||
*
|
||||
* @param aName name of the field
|
||||
*/
|
||||
FieldStats(String aName)
|
||||
{
|
||||
mName = aName;
|
||||
}
|
||||
|
||||
/** @return the name of the field */
|
||||
String getName()
|
||||
{
|
||||
return mName;
|
||||
}
|
||||
|
||||
/** @return the number of field reads */
|
||||
int getReads()
|
||||
{
|
||||
return mReads;
|
||||
}
|
||||
|
||||
/** @return the number of field writes */
|
||||
int getWrites()
|
||||
{
|
||||
return mWrites;
|
||||
}
|
||||
|
||||
/** Add a field read */
|
||||
void addRead()
|
||||
{
|
||||
mReads++;
|
||||
}
|
||||
|
||||
/** Add a field write */
|
||||
void addWrite()
|
||||
{
|
||||
mWrites++;
|
||||
}
|
||||
|
||||
/** @return the field details */
|
||||
Field getDetails()
|
||||
{
|
||||
return mDetails;
|
||||
}
|
||||
|
||||
/** @param aDetails set the field detail */
|
||||
void setDetails(Field aDetails)
|
||||
{
|
||||
mDetails = aDetails;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -28,14 +28,9 @@ import java.util.ListIterator;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
import java.io.InputStream;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.regexp.RE;
|
||||
import org.apache.regexp.RESyntaxException;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.DescendingVisitor;
|
||||
import org.apache.bcel.classfile.ClassParser;
|
||||
|
||||
/**
|
||||
* Verifier of Java rules. Each rule verifier takes the form of
|
||||
|
|
@ -179,7 +174,6 @@ class Verifier
|
|||
**/
|
||||
LocalizedMessage[] getMessages()
|
||||
{
|
||||
checkUnused();
|
||||
checkImports();
|
||||
return mMessages.getMessages();
|
||||
}
|
||||
|
|
@ -1492,59 +1486,6 @@ class Verifier
|
|||
return (i == -1) ? aType : aType.substring(i + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks for unused variables using BCEL.
|
||||
*/
|
||||
private void checkUnused()
|
||||
{
|
||||
if (!mConfig.isCheckUnusedFields()) {
|
||||
return;
|
||||
}
|
||||
|
||||
final Iterator typeNames = mTypeFieldsMap.keySet().iterator();
|
||||
while (typeNames.hasNext()) {
|
||||
final String type = (String) typeNames.next();
|
||||
String cname = type.replace('.', '$');
|
||||
if (mPkgName != null) {
|
||||
cname = mPkgName + "." + cname;
|
||||
}
|
||||
final String fname = cname.replace('.', '/') + ".class";
|
||||
final InputStream is =
|
||||
mConfig.getClassLoader().getResourceAsStream(fname);
|
||||
|
||||
final ClassParser parser = new ClassParser(is, cname);
|
||||
JavaClass jc = null;
|
||||
try {
|
||||
jc = parser.parse();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
catch (ClassFormatError e) {
|
||||
e.printStackTrace();
|
||||
return;
|
||||
}
|
||||
|
||||
// Visit the code using BCEL
|
||||
final UnusedDetector ud = new UnusedDetector(jc);
|
||||
final DescendingVisitor dv = new DescendingVisitor(jc, ud);
|
||||
dv.visit();
|
||||
|
||||
// Report all unused fields
|
||||
final Map typeVars = (Map) mTypeFieldsMap.get(type);
|
||||
final String[] unusedFields = ud.getUnusedFields();
|
||||
for (int i = 0; i < unusedFields.length; i++) {
|
||||
final MyVariable var =
|
||||
(MyVariable) typeVars.get(unusedFields[i]);
|
||||
mMessages.add(var.getLineNo(),
|
||||
var.getColumnNo() - 1,
|
||||
"field.unused",
|
||||
var.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Check the imports that are unused or unrequired. **/
|
||||
private void checkImports()
|
||||
{
|
||||
|
|
|
|||
Loading…
Reference in New Issue