restrict field and method reference recording to configured reference check scopes
This commit is contained in:
parent
ed7fc0e632
commit
3da302031b
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
|
|
@ -16,6 +17,7 @@ import org.apache.bcel.generic.INVOKEVIRTUAL;
|
|||
import org.apache.bcel.generic.PUTFIELD;
|
||||
import org.apache.bcel.generic.PUTSTATIC;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Scope;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.ReferenceDAO;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference;
|
||||
|
|
@ -29,10 +31,17 @@ import com.puppycrawl.tools.checkstyle.bcel.generic.PUTSTATICReference;
|
|||
* Records references during a deep parse tree traversal.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public final class ReferenceVisitor extends EmptyDeepVisitor {
|
||||
public final class ReferenceVisitor extends EmptyDeepVisitor
|
||||
{
|
||||
/** singleton */
|
||||
private static ReferenceVisitor sInstance = new ReferenceVisitor();
|
||||
|
||||
/** scope for checking field references */
|
||||
private Set mFieldScopes = new HashSet();
|
||||
|
||||
/** scope for checking method references */
|
||||
private Set mMethodScopes = new HashSet();
|
||||
|
||||
/** maps a JavaClass to a JavaClassDefinition */
|
||||
private ReferenceDAO mReferenceDAO;
|
||||
|
||||
|
|
@ -45,60 +54,71 @@ public final class ReferenceVisitor extends EmptyDeepVisitor {
|
|||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
private class GenericVisitor extends org.apache.bcel.generic.EmptyVisitor {
|
||||
private class GenericVisitor extends org.apache.bcel.generic.EmptyVisitor
|
||||
{
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKESPECIAL(INVOKESPECIAL aINVOKESPECIAL) {
|
||||
public void visitINVOKESPECIAL(INVOKESPECIAL aINVOKESPECIAL)
|
||||
{
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKESPECIAL, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKESTATIC(INVOKESTATIC aINVOKESTATIC) {
|
||||
public void visitINVOKESTATIC(INVOKESTATIC aINVOKESTATIC)
|
||||
{
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKESTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL) {
|
||||
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL)
|
||||
{
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKEVIRTUAL, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitGETSTATIC(GETSTATIC aGETSTATIC) {
|
||||
public void visitGETSTATIC(GETSTATIC aGETSTATIC)
|
||||
{
|
||||
addFieldReference(
|
||||
new GETSTATICReference(aGETSTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitGETFIELD(GETFIELD aGETFIELD) {
|
||||
public void visitGETFIELD(GETFIELD aGETFIELD)
|
||||
{
|
||||
addFieldReference(
|
||||
new GETFIELDReference(aGETFIELD, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitPUTSTATIC(PUTSTATIC aPUTSTATIC) {
|
||||
public void visitPUTSTATIC(PUTSTATIC aPUTSTATIC)
|
||||
{
|
||||
addFieldReference(
|
||||
new PUTSTATICReference(aPUTSTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitPUTFIELD(PUTFIELD aPUTFIELD) {
|
||||
public void visitPUTFIELD(PUTFIELD aPUTFIELD)
|
||||
{
|
||||
addFieldReference(
|
||||
new PUTFIELDReference(aPUTFIELD, mCurrentPoolGen));
|
||||
}
|
||||
}
|
||||
|
||||
/** prevent client construction */
|
||||
private ReferenceVisitor() {
|
||||
private ReferenceVisitor()
|
||||
{
|
||||
setGenericVisitor(new GenericVisitor());
|
||||
addFieldScope(Scope.PRIVATE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton ReferencesVisitor
|
||||
* @return the singleton
|
||||
*/
|
||||
public static ReferenceVisitor getInstance() {
|
||||
public static ReferenceVisitor getInstance()
|
||||
{
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
|
|
@ -106,7 +126,8 @@ public final class ReferenceVisitor extends EmptyDeepVisitor {
|
|||
* Adds an invoke reference to the reference DAO.
|
||||
* @param aReference the reference.
|
||||
*/
|
||||
private void addInvokeReference(InvokeReference aReference) {
|
||||
private void addInvokeReference(InvokeReference aReference)
|
||||
{
|
||||
getReferenceDAO().addInvokeReference(aReference);
|
||||
}
|
||||
|
||||
|
|
@ -114,25 +135,30 @@ public final class ReferenceVisitor extends EmptyDeepVisitor {
|
|||
* Adds an field reference to the reference DAO.
|
||||
* @param aReference the reference.
|
||||
*/
|
||||
private void addFieldReference(FieldReference aReference) {
|
||||
private void addFieldReference(FieldReference aReference)
|
||||
{
|
||||
getReferenceDAO().addFieldReference(aReference);
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
|
||||
public void visitSet(Set aJavaClasses) {
|
||||
mReferenceDAO = new ReferenceDAO(aJavaClasses);
|
||||
public void visitSet(Set aJavaClasses)
|
||||
{
|
||||
mReferenceDAO =
|
||||
new ReferenceDAO(aJavaClasses, mFieldScopes, mMethodScopes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reference DAO.
|
||||
* @return the reference DAO.
|
||||
*/
|
||||
public ReferenceDAO getReferenceDAO() {
|
||||
public ReferenceDAO getReferenceDAO()
|
||||
{
|
||||
return mReferenceDAO;
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
|
||||
public void visitObject(Object aObject) {
|
||||
public void visitObject(Object aObject)
|
||||
{
|
||||
final JavaClass javaClass = (JavaClass) aObject;
|
||||
final ConstantPool pool = javaClass.getConstantPool();
|
||||
mCurrentPoolGen = new ConstantPoolGen(pool);
|
||||
|
|
@ -143,7 +169,26 @@ public final class ReferenceVisitor extends EmptyDeepVisitor {
|
|||
* @param aJavaClass the JavaClass.
|
||||
* @return the JavaClassDefinition for aJavaClass.
|
||||
*/
|
||||
public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass) {
|
||||
public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass)
|
||||
{
|
||||
return getReferenceDAO().findJavaClassDef(aJavaClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes a scope in the scope for checking field references.
|
||||
* @param aScope the scope to include.
|
||||
*/
|
||||
public void addFieldScope(Scope aScope)
|
||||
{
|
||||
mFieldScopes.add(aScope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Includes a scope in the scope for checking method references.
|
||||
* @param aScope the scope to include.
|
||||
*/
|
||||
public void addMethodScope(Scope aScope)
|
||||
{
|
||||
mMethodScopes.add(aScope);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -51,12 +51,12 @@ public abstract class AbstractReferenceCheck
|
|||
{
|
||||
mScope = Scope.getInstance(aScopeName);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Determines whether a class name and field or method should be ignored.
|
||||
* @param aClassName the class name.
|
||||
* @param aName the name.
|
||||
* @return true if aClassName and aName should be ignored.
|
||||
* Determines whether a class name, and field or method should be ignored.
|
||||
* @param aClassName the class name to consider.
|
||||
* @param aFieldOrMethod the field or method to consider.
|
||||
* @return true if aClassName, and field or method should be ignored.
|
||||
*/
|
||||
protected boolean ignore(String aClassName, FieldOrMethod aFieldOrMethod)
|
||||
{
|
||||
|
|
@ -65,7 +65,7 @@ public abstract class AbstractReferenceCheck
|
|||
|| mIgnoreClassNameRegexp.match(aClassName)
|
||||
|| mIgnoreNameRegexp.match(fieldOrMethodName));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Tests whether the scope of a field or method is compatible
|
||||
* with the scope of this check. References for compatible
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import java.util.Set;
|
|||
import org.apache.bcel.classfile.Field;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Scope;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.ReferenceVisitor;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.FieldDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
|
||||
|
|
@ -19,6 +21,14 @@ import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
|||
public class UnreadFieldCheck
|
||||
extends AbstractReferenceCheck
|
||||
{
|
||||
/** @see AbstractReferenceCheck */
|
||||
public void setScope(String aFrom)
|
||||
{
|
||||
super.setScope(aFrom);
|
||||
((ReferenceVisitor) getVisitor()).addFieldScope(
|
||||
Scope.getInstance(aFrom));
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aJavaClasses)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import java.util.Set;
|
|||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Scope;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.ReferenceVisitor;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.MethodDefinition;
|
||||
|
||||
|
|
@ -19,6 +21,14 @@ import com.puppycrawl.tools.checkstyle.bcel.classfile.MethodDefinition;
|
|||
public class UnusedMethodCheck
|
||||
extends AbstractReferenceCheck
|
||||
{
|
||||
/** @see AbstractReferenceCheck */
|
||||
public void setScope(String aScopeName)
|
||||
{
|
||||
super.setScope(aScopeName);
|
||||
((ReferenceVisitor) getVisitor()).addMethodScope(
|
||||
Scope.getInstance(aScopeName));
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aJavaClasses)
|
||||
{
|
||||
|
|
@ -32,8 +42,7 @@ public class UnusedMethodCheck
|
|||
if (!classDef.hasReference(methodDefs[i], getReferenceDAO())) {
|
||||
final String methodName = methodDefs[i].getName();
|
||||
final Method method = methodDefs[i].getMethod();
|
||||
if (!ignore(className, method))
|
||||
{
|
||||
if (!ignore(className, method)) {
|
||||
log(
|
||||
0,
|
||||
"unused.method",
|
||||
|
|
|
|||
|
|
@ -4,7 +4,9 @@
|
|||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.Field;
|
||||
|
|
@ -30,29 +32,46 @@ public class JavaClassDefinition
|
|||
private Map mFieldDefs;
|
||||
|
||||
/**
|
||||
* Creates a JavaClassDefinition from a JavaClass.
|
||||
* Creates a JavaClassDefinition from a JavaClass. The fields and
|
||||
* methods of the JavaClassDefinition are those whose scopes are
|
||||
* in restricted sets of Scopes.
|
||||
* @param aJavaClass the JavaClass for the definition.
|
||||
* @param aFieldScopes the restricted set of field scopes.
|
||||
* @param aMethodScopes the restriced set of method scopes.
|
||||
*/
|
||||
public JavaClassDefinition(JavaClass aJavaClass)
|
||||
public JavaClassDefinition(
|
||||
JavaClass aJavaClass,
|
||||
Set aFieldScopes,
|
||||
Set aMethodScopes)
|
||||
{
|
||||
mJavaClass = aJavaClass;
|
||||
|
||||
// store method definitions
|
||||
// create method definitions, restricted by scope
|
||||
final Method[] methods = aJavaClass.getMethods();
|
||||
final Set methodSet = new HashSet();
|
||||
mMethodDefs = new MethodDefinition[methods.length];
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
mMethodDefs[i] = new MethodDefinition(methods[i]);
|
||||
if (Utils.inScope(methods[i], aMethodScopes)) {
|
||||
methodSet.add(new MethodDefinition(methods[i]));
|
||||
}
|
||||
}
|
||||
mMethodDefs =
|
||||
(MethodDefinition[]) methodSet.toArray(
|
||||
new MethodDefinition[methodSet.size()]);
|
||||
|
||||
// store field definitions
|
||||
// create field definitions, restricted by scope
|
||||
final Field[] fields = aJavaClass.getFields();
|
||||
mFieldDefs = new HashMap(fields.length);
|
||||
for (int i = 0; i < fields.length; i++) {
|
||||
mFieldDefs.put(fields[i].getName(), new FieldDefinition(fields[i]));
|
||||
if (Utils.inScope(fields[i], aFieldScopes)) {
|
||||
mFieldDefs.put(
|
||||
fields[i].getName(),
|
||||
new FieldDefinition(fields[i]));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Gets the JavaClass for this definition.
|
||||
* @return the JavaClass
|
||||
*/
|
||||
|
|
@ -135,31 +154,31 @@ public class JavaClassDefinition
|
|||
public boolean hasReference(
|
||||
MethodDefinition aMethodDef,
|
||||
ReferenceDAO aReferenceDAO)
|
||||
{
|
||||
final String methodName = aMethodDef.getName();
|
||||
final Type[] argTypes = aMethodDef.getArgumentTypes();
|
||||
|
||||
// search the inheritance hierarchy
|
||||
JavaClass currentJavaClass = getJavaClass();
|
||||
while (currentJavaClass != null) {
|
||||
final JavaClassDefinition javaClassDef =
|
||||
aReferenceDAO.findJavaClassDef(currentJavaClass);
|
||||
if (javaClassDef != null) {
|
||||
final MethodDefinition methodDef =
|
||||
javaClassDef.findNarrowestMethod(
|
||||
getJavaClass().getClassName(),
|
||||
methodName,
|
||||
argTypes);
|
||||
if ((methodDef != null)
|
||||
{
|
||||
final String methodName = aMethodDef.getName();
|
||||
final Type[] argTypes = aMethodDef.getArgumentTypes();
|
||||
|
||||
// search the inheritance hierarchy
|
||||
JavaClass currentJavaClass = getJavaClass();
|
||||
while (currentJavaClass != null) {
|
||||
final JavaClassDefinition javaClassDef =
|
||||
aReferenceDAO.findJavaClassDef(currentJavaClass);
|
||||
if (javaClassDef != null) {
|
||||
final MethodDefinition methodDef =
|
||||
javaClassDef.findNarrowestMethod(
|
||||
getJavaClass().getClassName(),
|
||||
methodName,
|
||||
argTypes);
|
||||
if ((methodDef != null)
|
||||
&& (methodDef.hasReference(getJavaClass())))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
currentJavaClass = currentJavaClass.getSuperClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
currentJavaClass = currentJavaClass.getSuperClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/** @see java.lang.Object#toString() */
|
||||
public String toString()
|
||||
|
|
|
|||
|
|
@ -21,25 +21,27 @@ import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference;
|
|||
*/
|
||||
public class ReferenceDAO
|
||||
{
|
||||
/** maps a JavaClass to a JavaClassDefinition */
|
||||
private Map mJavaClasses = null;
|
||||
|
||||
/**
|
||||
* Creates a <code>ReferenceDAO</code> from a set of JavaClasses.
|
||||
* @param aJavaClasses the set of JavaClasses for this DAO.
|
||||
* @param aFieldScopes the scopes for field references.
|
||||
* @param aMethodScopes the scopes for method references.
|
||||
*/
|
||||
public ReferenceDAO(Set aJavaClasses)
|
||||
public ReferenceDAO(Set aJavaClasses, Set aFieldScopes, Set aMethodScopes)
|
||||
{
|
||||
mJavaClasses = new HashMap(aJavaClasses.size());
|
||||
final Iterator it = aJavaClasses.iterator();
|
||||
while (it.hasNext()) {
|
||||
final JavaClass javaClass = (JavaClass) it.next();
|
||||
final JavaClassDefinition javaClassDef =
|
||||
new JavaClassDefinition(javaClass);
|
||||
new JavaClassDefinition(javaClass, aFieldScopes, aMethodScopes);
|
||||
mJavaClasses.put(javaClass, javaClassDef);
|
||||
}
|
||||
}
|
||||
|
||||
/** maps a JavaClass to a JavaClassDefinition */
|
||||
private Map mJavaClasses = null;
|
||||
|
||||
/**
|
||||
* Finds the JavaClassDefinition for a given JavaClass.
|
||||
* @param aJavaClass the JavaClass.
|
||||
|
|
|
|||
|
|
@ -0,0 +1,39 @@
|
|||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.FieldOrMethod;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Scope;
|
||||
|
||||
/**
|
||||
* Utility methods for BCEL classfile package
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class Utils
|
||||
{
|
||||
/**
|
||||
* Determines whether the declared scope of a field or method is in
|
||||
* a set of scopes.
|
||||
* @param aFieldOrMethod the field or method to test.
|
||||
* @param aScopes the set of scopes to test against.
|
||||
* @return true if the declared scope of aFieldOrMethod is in aScopes.
|
||||
*/
|
||||
public static boolean inScope(FieldOrMethod aFieldOrMethod, Set aScopes)
|
||||
{
|
||||
if (aFieldOrMethod.isPrivate()) {
|
||||
return (aScopes.contains(Scope.PRIVATE));
|
||||
}
|
||||
else if (aFieldOrMethod.isProtected()) {
|
||||
return (aScopes.contains(Scope.PROTECTED));
|
||||
}
|
||||
else if (aFieldOrMethod.isPublic()) {
|
||||
return (aScopes.contains(Scope.PUBLIC));
|
||||
}
|
||||
else {
|
||||
return (aScopes.contains(Scope.PACKAGE));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Loading…
Reference in New Issue