BCEL .class file checks
This commit is contained in:
parent
db5ec5f654
commit
54f09ae36c
|
|
@ -0,0 +1,15 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_1.dtd">
|
||||
<module name="Checker">
|
||||
<metadata name="com.atlas-sw.eclipse" value="I like Sydney"/>
|
||||
<property name="severity" value="error"/>
|
||||
|
||||
<module name="bcel.ClassFileSet">
|
||||
<module name="bcel.checks.UnusedMethod">
|
||||
</module>
|
||||
<module name="bcel.checks.UnreadPrivateField">
|
||||
</module>
|
||||
</module>
|
||||
</module>
|
||||
|
|
@ -0,0 +1,115 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter;
|
||||
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
|
||||
import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
|
||||
|
||||
/**
|
||||
* Abstract class for checks with visitors.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
//TODO: Refactor with class Check
|
||||
public abstract class AbstractCheckVisitor
|
||||
extends AbstractViolationReporter
|
||||
implements IObjectSetVisitor
|
||||
{
|
||||
/** the object for collecting messages. */
|
||||
private LocalizedMessages mMessages;
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IParserCheck */
|
||||
public org.apache.bcel.classfile.Visitor getClassFileVisitor()
|
||||
{
|
||||
return new EmptyClassFileVisitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IParserCheck
|
||||
*/
|
||||
public org.apache.bcel.generic.Visitor getGenericVisitor()
|
||||
{
|
||||
return new EmptyGenericVisitor();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialse the check. This is the time to verify that the check has
|
||||
* everything required to perform it job.
|
||||
*/
|
||||
public void init()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Destroy the check. It is being retired from service.
|
||||
*/
|
||||
public void destroy()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the global object used to collect messages.
|
||||
* @param aMessages the messages to log with
|
||||
*/
|
||||
public final void setMessages(LocalizedMessages aMessages)
|
||||
{
|
||||
mMessages = aMessages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Log an error message.
|
||||
*
|
||||
* @param aLine the line number where the error was found
|
||||
* @param aKey the message that describes the error
|
||||
* @param aArgs the details of the message
|
||||
*
|
||||
* @see java.text.MessageFormat
|
||||
*/
|
||||
protected final void log(int aLine, String aKey, Object aArgs[])
|
||||
{
|
||||
mMessages.add(
|
||||
new LocalizedMessage(
|
||||
aLine,
|
||||
getMessageBundle(),
|
||||
aKey,
|
||||
aArgs,
|
||||
getSeverityLevel(),
|
||||
this.getClass().getName()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.api.AbstractViolationReporter
|
||||
*/
|
||||
protected void log(int aLine, int aCol, String aKey, Object[] aArgs)
|
||||
{
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void visitObject(Object aObject)
|
||||
{
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveObject(Object aObject)
|
||||
{
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void visitSet(Set aJavaClassDefs)
|
||||
{
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aJavaClassDefs)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the deep BCEL visitor.
|
||||
* @return the deep BCEL visitor for this check.
|
||||
*/
|
||||
public abstract IDeepVisitor getVisitor();
|
||||
}
|
||||
|
|
@ -0,0 +1,304 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.ClassParser;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Visitor;
|
||||
import org.apache.bcel.util.ClassLoaderRepository;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.DefaultContext;
|
||||
import com.puppycrawl.tools.checkstyle.ModuleFactory;
|
||||
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
|
||||
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
|
||||
import com.puppycrawl.tools.checkstyle.api.Configuration;
|
||||
import com.puppycrawl.tools.checkstyle.api.Context;
|
||||
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
|
||||
|
||||
/**
|
||||
* Checks a set of class files using BCEL
|
||||
* @author Rick Giles
|
||||
*/
|
||||
//TODO: Refactor with AbstractFileSetCheck and TreeWalker
|
||||
public class ClassFileSetCheck
|
||||
extends AbstractFileSetCheck
|
||||
implements IObjectSetVisitor
|
||||
{
|
||||
/** visitors for BCEL parse tree walk */
|
||||
private final Set mTreeVisitors = new HashSet();
|
||||
|
||||
/** all the registered checks */
|
||||
private final Set mAllChecks = new HashSet();
|
||||
|
||||
/** all visitors for IObjectSetVisitor visits */
|
||||
private final Set mObjectSetVisitors = new HashSet();
|
||||
|
||||
/** class loader to resolve classes with. **/
|
||||
private ClassLoader mClassLoader;
|
||||
|
||||
/** context of child components */
|
||||
private Context mChildContext;
|
||||
|
||||
/** a factory for creating submodules (i.e. the Checks) */
|
||||
private ModuleFactory mModuleFactory;
|
||||
|
||||
/**
|
||||
* Creates a new <code>ClassFileSetCheck</code> instance.
|
||||
* Initializes the acceptable file extensions.
|
||||
*/
|
||||
public ClassFileSetCheck()
|
||||
{
|
||||
setFileExtensions(new String[]{"class", "jar", "zip"});
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the class loader and makes it the Repository's class loader.
|
||||
* @param aClassLoader class loader to resolve classes with.
|
||||
*/
|
||||
public void setClassLoader(ClassLoader aClassLoader)
|
||||
{
|
||||
Repository.setRepository(new ClassLoaderRepository(aClassLoader));
|
||||
mClassLoader = aClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the module factory for creating child modules (Checks).
|
||||
* @param aModuleFactory the factory
|
||||
*/
|
||||
public void setModuleFactory(ModuleFactory aModuleFactory)
|
||||
{
|
||||
mModuleFactory = aModuleFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates, configures and registers a Check that is specified
|
||||
* in the provided configuration.
|
||||
* @see com.puppycrawl.tools.checkstyle.api.AutomaticBean
|
||||
*/
|
||||
public void setupChild(Configuration aChildConf)
|
||||
throws CheckstyleException
|
||||
{
|
||||
// TODO: improve the error handing
|
||||
final String name = aChildConf.getName();
|
||||
final Object module = mModuleFactory.createModule(name);
|
||||
if (!(module instanceof AbstractCheckVisitor)) {
|
||||
throw new CheckstyleException(
|
||||
"ClassFileSet is not allowed as a parent of " + name);
|
||||
}
|
||||
final AbstractCheckVisitor c = (AbstractCheckVisitor) module;
|
||||
c.contextualize(mChildContext);
|
||||
c.configure(aChildConf);
|
||||
c.init();
|
||||
|
||||
registerCheck(c);
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.api.Configurable */
|
||||
public void finishLocalSetup()
|
||||
{
|
||||
DefaultContext checkContext = new DefaultContext();
|
||||
checkContext.add("classLoader", mClassLoader);
|
||||
checkContext.add("messages", getMessageCollector());
|
||||
checkContext.add("severity", getSeverity());
|
||||
|
||||
mChildContext = checkContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Register a check.
|
||||
* @param aCheck the check to register
|
||||
*/
|
||||
private void registerCheck(AbstractCheckVisitor aCheck)
|
||||
{
|
||||
mAllChecks.add(aCheck);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.api.FileSetCheck
|
||||
*/
|
||||
public void process(File[] aFiles)
|
||||
{
|
||||
registerVisitors();
|
||||
|
||||
// get all the JavaClasses in the files
|
||||
final Set javaClasses = extractJavaClasses(aFiles);
|
||||
|
||||
visitSet(javaClasses);
|
||||
|
||||
// walk each Java class parse tree
|
||||
final JavaClassWalker walker = JavaClassWalker.getInstance();
|
||||
walker.setVisitor(getTreeVisitor());
|
||||
final Iterator it = javaClasses.iterator();
|
||||
while (it.hasNext()) {
|
||||
final JavaClass clazz = (JavaClass) it.next();
|
||||
visitObject(clazz);
|
||||
walker.walk(clazz);
|
||||
leaveObject(clazz);
|
||||
}
|
||||
|
||||
leaveSet(javaClasses);
|
||||
fireErrors();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the visitor for a parse tree walk.
|
||||
* @return the visitor for a parse tree walk.
|
||||
*/
|
||||
private Visitor getTreeVisitor()
|
||||
{
|
||||
return new VisitorSet(mTreeVisitors);
|
||||
}
|
||||
|
||||
/**
|
||||
* Registers all the visitors for IObjectSetVisitor visits, and for
|
||||
* tree walk visits.
|
||||
*/
|
||||
private void registerVisitors()
|
||||
{
|
||||
mObjectSetVisitors.addAll(mAllChecks);
|
||||
final Iterator it = mAllChecks.iterator();
|
||||
while (it.hasNext()) {
|
||||
final AbstractCheckVisitor check = (AbstractCheckVisitor) it.next();
|
||||
final IDeepVisitor visitor = check.getVisitor();
|
||||
mObjectSetVisitors.add(visitor);
|
||||
mTreeVisitors.add(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of all visitors for all the checks.
|
||||
* @return the set of all visitors for all the checks.
|
||||
*/
|
||||
private Set getObjectSetVisitors()
|
||||
{
|
||||
return mObjectSetVisitors;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the set of all JavaClasses within a set of Files.
|
||||
* @param aFiles the set of files to extract from.
|
||||
* @return the set of all JavaClasses within aFiles.
|
||||
*/
|
||||
private Set extractJavaClasses(File[] aFiles)
|
||||
{
|
||||
final Set result = new HashSet();
|
||||
final File[] classFiles = filter(aFiles);
|
||||
// get Java classes from each filtered file
|
||||
for (int i = 0; i < classFiles.length; i++) {
|
||||
try {
|
||||
final Set extracted = extractJavaClasses(classFiles[i]);
|
||||
result.addAll(extracted);
|
||||
}
|
||||
catch (IOException e) {
|
||||
// TODO Auto-generated catch block
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void visitSet(Set aSet)
|
||||
{
|
||||
// register the JavaClasses in the Repository
|
||||
Repository.clearCache();
|
||||
Iterator it = aSet.iterator();
|
||||
while (it.hasNext()) {
|
||||
final JavaClass javaClass = (JavaClass) it.next();
|
||||
Repository.addClass(javaClass);
|
||||
}
|
||||
|
||||
// visit the visitors
|
||||
it = getObjectSetVisitors().iterator();
|
||||
while (it.hasNext()) {
|
||||
final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
|
||||
visitor.visitSet(aSet);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void visitObject(Object aObject)
|
||||
{
|
||||
final Iterator it = getObjectSetVisitors().iterator();
|
||||
while (it.hasNext()) {
|
||||
final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
|
||||
visitor.visitObject(aObject);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveObject(Object aObject)
|
||||
{
|
||||
final Iterator it = getObjectSetVisitors().iterator();
|
||||
while (it.hasNext()) {
|
||||
final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
|
||||
visitor.leaveObject(aObject);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aSet)
|
||||
{
|
||||
final Iterator it = getObjectSetVisitors().iterator();
|
||||
while (it.hasNext()) {
|
||||
final IObjectSetVisitor visitor = (IObjectSetVisitor) it.next();
|
||||
visitor.leaveSet(aSet);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Extracts the JavaClasses from .class, .zip, and .jar files.
|
||||
* @param aFile the file to extract from.
|
||||
* @return the set of JavaClasses from aFile.
|
||||
* @throws IOException if there is an error.
|
||||
*/
|
||||
private Set extractJavaClasses(File aFile)
|
||||
throws IOException
|
||||
{
|
||||
final Set result = new HashSet();
|
||||
final String fileName = aFile.getPath();
|
||||
if (fileName.endsWith(".jar") || fileName.endsWith(".zip")) {
|
||||
final ZipFile zipFile = new ZipFile(fileName);
|
||||
final Enumeration entries = zipFile.entries();
|
||||
while (entries.hasMoreElements()) {
|
||||
final ZipEntry entry = (ZipEntry) entries.nextElement();
|
||||
final String entryName = entry.getName();
|
||||
if (entryName.endsWith(".class")) {
|
||||
final InputStream in = zipFile.getInputStream(entry);
|
||||
final JavaClass javaClass =
|
||||
new ClassParser(in, entryName).parse();
|
||||
result.add(javaClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
final JavaClass javaClass = new ClassParser(fileName).parse();
|
||||
result.add(javaClass);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify all listeners about the errors in a file.
|
||||
* Calls <code>MessageDispatcher.fireErrors()</code> with
|
||||
* all logged errors and than clears errors' list.
|
||||
*/
|
||||
private void fireErrors()
|
||||
{
|
||||
final LocalizedMessage[] errors = getMessageCollector().getMessages();
|
||||
getMessageCollector().reset();
|
||||
getMessageDispatcher().fireErrors("", errors);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,17 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
/**
|
||||
* Default classfile visitor.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class EmptyClassFileVisitor
|
||||
extends org.apache.bcel.classfile.EmptyVisitor
|
||||
{
|
||||
/** restrict client creation */
|
||||
protected EmptyClassFileVisitor()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
* Default deep visitor
|
||||
* @author Rick Giles
|
||||
* @version 17-Jun-2003
|
||||
*/
|
||||
public class EmptyDeepVisitor
|
||||
implements IDeepVisitor
|
||||
{
|
||||
/** the classfile visitor */
|
||||
private org.apache.bcel.classfile.Visitor mClassFileVisitor =
|
||||
new EmptyClassFileVisitor();
|
||||
|
||||
/** the generic visitor */
|
||||
private org.apache.bcel.generic.Visitor mGenericVisitor =
|
||||
new EmptyGenericVisitor();
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor
|
||||
*/
|
||||
public org.apache.bcel.classfile.Visitor getClassFileVisitor()
|
||||
{
|
||||
return mClassFileVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor
|
||||
*/
|
||||
public org.apache.bcel.generic.Visitor getGenericVisitor()
|
||||
{
|
||||
return mGenericVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the classfile visitor.
|
||||
* @param aVisitor the classfile visitor.
|
||||
*/
|
||||
public void setClassFileVisitor(org.apache.bcel.classfile.Visitor aVisitor)
|
||||
{
|
||||
mClassFileVisitor = aVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the generic visitor.
|
||||
* @param aVisitor the generic visitor.
|
||||
*/
|
||||
public void setGenericVisitor(org.apache.bcel.generic.Visitor aVisitor)
|
||||
{
|
||||
mGenericVisitor = aVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor
|
||||
*/
|
||||
public void visitObject(Object aObject)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor
|
||||
*/
|
||||
public void leaveObject(Object aObject)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor
|
||||
*/
|
||||
public void visitSet(Set aSet)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor
|
||||
*/
|
||||
public void leaveSet(Set aSet)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,18 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
/**
|
||||
* Default generic visitor
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class EmptyGenericVisitor
|
||||
extends org.apache.bcel.generic.EmptyVisitor
|
||||
{
|
||||
/** Restrict client creation */
|
||||
protected EmptyGenericVisitor()
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
/**
|
||||
* Deep visitor for classfile and generic traversals. A ClassFile traversal
|
||||
* visits all classfile and all generic nodes.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public interface IDeepVisitor
|
||||
extends IObjectSetVisitor
|
||||
{
|
||||
/**
|
||||
* Returns the classfile visitor.
|
||||
* @return the classfile visitor.
|
||||
*/
|
||||
org.apache.bcel.classfile.Visitor getClassFileVisitor();
|
||||
|
||||
/**
|
||||
* Returns the generic visitor.
|
||||
* @return the generic visitor.
|
||||
*/
|
||||
org.apache.bcel.generic.Visitor getGenericVisitor();
|
||||
}
|
||||
|
|
@ -0,0 +1,37 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Object set visitor for a general set.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public interface IObjectSetVisitor
|
||||
{
|
||||
/**
|
||||
* Visit a set itself.
|
||||
* @param aSet the set.
|
||||
*/
|
||||
void visitSet(Set aSet);
|
||||
|
||||
/**
|
||||
* Finish the visit of a set.
|
||||
* @param aSet the set.
|
||||
*/
|
||||
void leaveSet(Set aSet);
|
||||
|
||||
/**
|
||||
* Visit an object. Normally this is an object of the set.
|
||||
* @param aObject the object.
|
||||
*/
|
||||
void visitObject(Object aObject);
|
||||
|
||||
/**
|
||||
* Finish the visit an object. Normally this is an object of the set.
|
||||
* @param aObject the object.
|
||||
*/
|
||||
void leaveObject(Object aObject);
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import org.apache.bcel.classfile.DescendingVisitor;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Visitor;
|
||||
|
||||
/**
|
||||
* Walks a JavaClass parse tree.
|
||||
* @author Rick Giles
|
||||
* @version 15-Jun-2003
|
||||
*/
|
||||
public final class JavaClassWalker
|
||||
{
|
||||
/** singleton */
|
||||
private static JavaClassWalker sInstance = new JavaClassWalker();
|
||||
|
||||
/** visitor to be accepted during a traversal */
|
||||
private Visitor mVisitor = new EmptyClassFileVisitor();
|
||||
|
||||
/** prevent client creation */
|
||||
private JavaClassWalker()
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Accesses the singleton JavaClassWalker.
|
||||
* @return the singleton JavaClassWalker.
|
||||
*/
|
||||
public static JavaClassWalker getInstance()
|
||||
{
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a visitor to be accepted during a traversal.
|
||||
* @param aVisitor the visitor to be accepted during a traversal.
|
||||
*/
|
||||
public void setVisitor(Visitor aVisitor)
|
||||
{
|
||||
mVisitor = aVisitor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Traverses a JavaClass parse tree and accepts all registered
|
||||
* visitors.
|
||||
* @param aJavaClass the root of the tree.
|
||||
*/
|
||||
public void walk(JavaClass aJavaClass)
|
||||
{
|
||||
DescendingVisitor visitor =
|
||||
new DescendingVisitor(aJavaClass, mVisitor);
|
||||
aJavaClass.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,149 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.GETFIELD;
|
||||
import org.apache.bcel.generic.GETSTATIC;
|
||||
import org.apache.bcel.generic.INVOKESPECIAL;
|
||||
import org.apache.bcel.generic.INVOKESTATIC;
|
||||
import org.apache.bcel.generic.INVOKEVIRTUAL;
|
||||
import org.apache.bcel.generic.PUTFIELD;
|
||||
import org.apache.bcel.generic.PUTSTATIC;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.ReferenceDAO;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.GETFIELDReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.GETSTATICReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.PUTFIELDReference;
|
||||
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 {
|
||||
/** singleton */
|
||||
private static ReferenceVisitor sInstance = new ReferenceVisitor();
|
||||
|
||||
/** maps a JavaClass to a JavaClassDefinition */
|
||||
private ReferenceDAO mReferenceDAO;
|
||||
|
||||
/** access to current constant pool */
|
||||
private ConstantPoolGen mCurrentPoolGen;
|
||||
|
||||
/**
|
||||
* Adds a reference when it visits an instruction that invokes
|
||||
* a method or references a field.
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
private class GenericVisitor extends org.apache.bcel.generic.EmptyVisitor {
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKESPECIAL(INVOKESPECIAL aINVOKESPECIAL) {
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKESPECIAL, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKESTATIC(INVOKESTATIC aINVOKESTATIC) {
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKESTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitINVOKEVIRTUAL(INVOKEVIRTUAL aINVOKEVIRTUAL) {
|
||||
addInvokeReference(
|
||||
new InvokeReference(aINVOKEVIRTUAL, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitGETSTATIC(GETSTATIC aGETSTATIC) {
|
||||
addFieldReference(
|
||||
new GETSTATICReference(aGETSTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitGETFIELD(GETFIELD aGETFIELD) {
|
||||
addFieldReference(
|
||||
new GETFIELDReference(aGETFIELD, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitPUTSTATIC(PUTSTATIC aPUTSTATIC) {
|
||||
addFieldReference(
|
||||
new PUTSTATICReference(aPUTSTATIC, mCurrentPoolGen));
|
||||
}
|
||||
|
||||
/** @see org.apache.bcel.generic.Visitor */
|
||||
public void visitPUTFIELD(PUTFIELD aPUTFIELD) {
|
||||
addFieldReference(
|
||||
new PUTFIELDReference(aPUTFIELD, mCurrentPoolGen));
|
||||
}
|
||||
}
|
||||
|
||||
/** prevent client construction */
|
||||
private ReferenceVisitor() {
|
||||
setGenericVisitor(new GenericVisitor());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the singleton ReferencesVisitor
|
||||
* @return the singleton
|
||||
*/
|
||||
public static ReferenceVisitor getInstance() {
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an invoke reference to the reference DAO.
|
||||
* @param aReference the reference.
|
||||
*/
|
||||
private void addInvokeReference(InvokeReference aReference) {
|
||||
getReferenceDAO().addInvokeReference(aReference);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds an field reference to the reference DAO.
|
||||
* @param aReference the reference.
|
||||
*/
|
||||
private void addFieldReference(FieldReference aReference) {
|
||||
getReferenceDAO().addFieldReference(aReference);
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
|
||||
public void visitSet(Set aJavaClasses) {
|
||||
mReferenceDAO = new ReferenceDAO(aJavaClasses);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the reference DAO.
|
||||
* @return the reference DAO.
|
||||
*/
|
||||
public ReferenceDAO getReferenceDAO() {
|
||||
return mReferenceDAO;
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor */
|
||||
public void visitObject(Object aObject) {
|
||||
final JavaClass javaClass = (JavaClass) aObject;
|
||||
final ConstantPool pool = javaClass.getConstantPool();
|
||||
mCurrentPoolGen = new ConstantPoolGen(pool);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the JavaClassDefinition for a given JavaClass.
|
||||
* @param aJavaClass the JavaClass.
|
||||
* @return the JavaClassDefinition for aJavaClass.
|
||||
*/
|
||||
public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass) {
|
||||
return getReferenceDAO().findJavaClassDef(aJavaClass);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,130 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.Code;
|
||||
import org.apache.bcel.classfile.ConstantPool;
|
||||
import org.apache.bcel.classfile.EmptyVisitor;
|
||||
import org.apache.bcel.classfile.Field;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.LocalVariable;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
import org.apache.bcel.classfile.Visitor;
|
||||
import org.apache.bcel.generic.InstructionHandle;
|
||||
import org.apache.bcel.generic.InstructionList;
|
||||
|
||||
/**
|
||||
* Manages a set of visitors that are accepted by nodes visited by
|
||||
* a VisitorSet. Any visit to this object is passed on to its managed
|
||||
* visitors.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
// TODO: review visitXXX
|
||||
public class VisitorSet
|
||||
extends EmptyVisitor
|
||||
{
|
||||
/** the managed visitors */
|
||||
private Set mVisitors = new HashSet();
|
||||
|
||||
/** Creates a <code>VisitorSet</code> for a set of visitors.
|
||||
* @param aVisitors the set of managed visitors.
|
||||
*/
|
||||
public VisitorSet(Set aVisitors)
|
||||
{
|
||||
mVisitors = aVisitors;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor#visitCode
|
||||
*/
|
||||
public void visitCode(Code aCode)
|
||||
{
|
||||
// perform a deep visit
|
||||
final byte[] code = aCode.getCode();
|
||||
final InstructionList list = new InstructionList(code);
|
||||
final Iterator it = list.iterator();
|
||||
for (Iterator iter = list.iterator(); iter.hasNext();) {
|
||||
InstructionHandle instruction = (InstructionHandle) iter.next();
|
||||
visitInstructionHandle(instruction);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Deep visit of an InstructionHandle
|
||||
* @param aInstruction the InstructionHandle
|
||||
*/
|
||||
private void visitInstructionHandle(InstructionHandle aInstruction)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
final IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
org.apache.bcel.generic.Visitor v =
|
||||
visitor.getGenericVisitor();
|
||||
aInstruction.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor
|
||||
*/
|
||||
public void visitConstantPool(ConstantPool aConstantPool)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
Visitor v = visitor.getClassFileVisitor();
|
||||
aConstantPool.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor
|
||||
*/
|
||||
public void visitField(Field aField)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
Visitor v = visitor.getClassFileVisitor();
|
||||
aField.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor
|
||||
*/
|
||||
public void visitJavaClass(JavaClass aJavaClass)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
Visitor v = visitor.getClassFileVisitor();
|
||||
aJavaClass.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor
|
||||
*/
|
||||
public void visitLocalVariable(LocalVariable aLocalVariable)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
Visitor v = visitor.getClassFileVisitor();
|
||||
aLocalVariable.accept(v);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.apache.bcel.classfile.Visitor
|
||||
*/
|
||||
public void visitMethod(Method aMethod)
|
||||
{
|
||||
for (Iterator iter = mVisitors.iterator(); iter.hasNext();) {
|
||||
IDeepVisitor visitor = (IDeepVisitor) iter.next();
|
||||
Visitor v = visitor.getClassFileVisitor();
|
||||
aMethod.accept(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,109 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.checks;
|
||||
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.commons.beanutils.ConversionException;
|
||||
import org.apache.regexp.RE;
|
||||
import org.apache.regexp.RESyntaxException;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.api.Utils;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.AbstractCheckVisitor;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.IDeepVisitor;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.ReferenceVisitor;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.ReferenceDAO;
|
||||
|
||||
/**
|
||||
* Abstract class for checks that require reference information.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public abstract class AbstractReferenceCheck
|
||||
extends AbstractCheckVisitor
|
||||
{
|
||||
/** the regexp to match class names against */
|
||||
private RE mIgnoreClassNameRegexp;
|
||||
|
||||
/** the regexp to match names against */
|
||||
private RE mIgnoreNameRegexp;
|
||||
|
||||
/**
|
||||
* Creates a <code>AbstractReferenceCheck</code>.
|
||||
*
|
||||
*/
|
||||
public AbstractReferenceCheck()
|
||||
{
|
||||
setIgnoreClassName("^$");
|
||||
setIgnoreName("^$");
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a class name and name should be ignored.
|
||||
* @param aClassName the class name.
|
||||
* @param aName the name.
|
||||
* @return true if aClassName and aName should be ignored.
|
||||
*/
|
||||
protected boolean ignore(String aClassName, String aName)
|
||||
{
|
||||
return (mIgnoreClassNameRegexp.match(aClassName)
|
||||
|| mIgnoreNameRegexp.match(aName));
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ignore class name to the specified regular expression.
|
||||
* @param aFormat a <code>String</code> value
|
||||
* @throws ConversionException unable to parse aFormat
|
||||
*/
|
||||
public void setIgnoreClassName(String aFormat)
|
||||
throws ConversionException
|
||||
{
|
||||
try {
|
||||
mIgnoreClassNameRegexp = Utils.getRE(aFormat);
|
||||
}
|
||||
catch (RESyntaxException e) {
|
||||
throw new ConversionException("unable to parse " + aFormat, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the ignore name format to the specified regular expression.
|
||||
* @param aFormat a <code>String</code> value
|
||||
* @throws ConversionException unable to parse aFormat
|
||||
*/
|
||||
public void setIgnoreName(String aFormat)
|
||||
throws ConversionException
|
||||
{
|
||||
try {
|
||||
mIgnoreNameRegexp = Utils.getRE(aFormat);
|
||||
}
|
||||
catch (RESyntaxException e) {
|
||||
throw new ConversionException("unable to parse " + aFormat, e);
|
||||
}
|
||||
}
|
||||
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.AbstractCheckVisitor */
|
||||
public IDeepVisitor getVisitor()
|
||||
{
|
||||
return ReferenceVisitor.getInstance();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the DAO that manages references for this check.
|
||||
* @return the the DAO that manages references for this check.
|
||||
*/
|
||||
public ReferenceDAO getReferenceDAO()
|
||||
{
|
||||
return ((ReferenceVisitor) getVisitor()).getReferenceDAO();
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a JavaClassDefinition for a JavaClass.
|
||||
* @param aJavaClass the JavaClass.
|
||||
* @return the JavaClassDefinition for aJavaClass.
|
||||
*/
|
||||
protected JavaClassDefinition findJavaClassDef(JavaClass aJavaClass)
|
||||
{
|
||||
return getReferenceDAO().findJavaClassDef(aJavaClass);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.checks;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.Field;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.FieldDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
|
||||
/**
|
||||
* Checks for unread, non-final fields
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class UnreadFieldCheck
|
||||
extends AbstractReferenceCheck
|
||||
{
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aJavaClasses)
|
||||
{
|
||||
final Iterator it = aJavaClasses.iterator();
|
||||
while (it.hasNext()) {
|
||||
final JavaClass javaClass = (JavaClass) it.next();
|
||||
final String className = javaClass.getClassName();
|
||||
final JavaClassDefinition classDef = findJavaClassDef(javaClass);
|
||||
final FieldDefinition[] fieldDefs = classDef.getFieldDefs();
|
||||
for (int i = 0; i < fieldDefs.length; i++) {
|
||||
if (fieldDefs[i].getReadReferenceCount() == 0) {
|
||||
final Field field = fieldDefs[i].getField();
|
||||
if (!field.isFinal()
|
||||
&& (!ignore(className, field)))
|
||||
{
|
||||
log(
|
||||
0,
|
||||
"unread.field",
|
||||
new Object[] {className, fieldDefs[i]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a class name and Field should be ignored.
|
||||
* Normally the Field is a Field of the named class.
|
||||
* @param aClassName the class name.
|
||||
* @param aField the Field.
|
||||
* @return true if aClassName and aField should be ignored.
|
||||
*/
|
||||
protected boolean ignore(String aClassName, Field aField)
|
||||
{
|
||||
return ignore(aClassName, aField.getName());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.checks;
|
||||
|
||||
import org.apache.bcel.classfile.Field;
|
||||
|
||||
/**
|
||||
* Checks for unread, non-final private fields
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class UnreadPrivateFieldCheck
|
||||
extends UnreadFieldCheck
|
||||
{
|
||||
/** @see UnreadFieldCheck */
|
||||
protected boolean ignore(String aClassName, Field aField)
|
||||
{
|
||||
return (!aField.isPrivate() || super.ignore(aClassName, aField));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.checks;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.JavaClassDefinition;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.classfile.MethodDefinition;
|
||||
|
||||
/**
|
||||
* Checks for unused methods
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class UnusedMethodCheck
|
||||
extends AbstractReferenceCheck
|
||||
{
|
||||
/** @see com.puppycrawl.tools.checkstyle.bcel.IObjectSetVisitor */
|
||||
public void leaveSet(Set aJavaClasses)
|
||||
{
|
||||
final Iterator it = aJavaClasses.iterator();
|
||||
while (it.hasNext()) {
|
||||
final JavaClass javaClass = (JavaClass) it.next();
|
||||
final String className = javaClass.getClassName();
|
||||
final JavaClassDefinition classDef = findJavaClassDef(javaClass);
|
||||
final MethodDefinition[] methodDefs = classDef.getMethodDefs();
|
||||
for (int i = 0; i < methodDefs.length; i++) {
|
||||
if (!classDef.hasReference(methodDefs[i], getReferenceDAO())) {
|
||||
final String methodName = methodDefs[i].getName();
|
||||
final Method method = methodDefs[i].getMethod();
|
||||
if (!ignore(className, method))
|
||||
{
|
||||
log(
|
||||
0,
|
||||
"unused.method",
|
||||
new Object[] {className, methodDefs[i]});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a class name and Method should be ignored.
|
||||
* Normally the Method is a Method of the named class.
|
||||
* @param aClassName the class name.
|
||||
* @param aMethod the Method.
|
||||
* @return true if aClassName and aMethod should be ignored.
|
||||
*/
|
||||
protected boolean ignore(String aClassName, Method aMethod)
|
||||
{
|
||||
return ignore(aClassName, aMethod.getName());
|
||||
}
|
||||
|
||||
/** @see AbstractReferenceCheck */
|
||||
public boolean ignore(String aClassName, String aMethodName)
|
||||
{
|
||||
return (super.ignore(aClassName, aMethodName)
|
||||
|| aMethodName.equals("<init>")
|
||||
|| aMethodName.equals("<clinit>"));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.checks;
|
||||
|
||||
import org.apache.bcel.classfile.Method;
|
||||
|
||||
/**
|
||||
* Checks for unused private methods
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class UnusedPrivateMethodCheck
|
||||
extends UnusedMethodCheck
|
||||
{
|
||||
/** @see UnusedMethodCheck */
|
||||
protected boolean ignore(String aClassName, Method aMethod)
|
||||
{
|
||||
return (!aMethod.isPrivate() || super.ignore(aClassName, aMethod));
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,2 @@
|
|||
unread.field=Class ''{0}'', unread field ''{1}''.
|
||||
unused.method=Class ''{0}'', unused method ''{1}''.
|
||||
|
|
@ -0,0 +1,89 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.classfile.Field;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.PUTFIELDReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.PUTSTATICReference;
|
||||
|
||||
/**
|
||||
* Contains the definition of a Field and its references.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class FieldDefinition
|
||||
extends FieldOrMethodDefinition
|
||||
{
|
||||
/** the GET references for the Field */
|
||||
private final Set mGetReferences = new HashSet();
|
||||
|
||||
/** the PUT references for the FSield */
|
||||
private final Set mPutReferences = new HashSet();
|
||||
|
||||
/**
|
||||
* Creates a <code>FieldDefinition</code> for a Field.
|
||||
* @param aField the Field.
|
||||
*/
|
||||
public FieldDefinition(Field aField)
|
||||
{
|
||||
super(aField);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Field for this definition.
|
||||
* @return the Field for this definition.
|
||||
*/
|
||||
public Field getField()
|
||||
{
|
||||
return (Field) getFieldOrMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of read, or GET, references to the Field.
|
||||
* @return the number of read references to the Field.
|
||||
*/
|
||||
public int getReadReferenceCount()
|
||||
{
|
||||
return mGetReferences.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of write, or PUT, references to the Field.
|
||||
* @return the number of write references to the Field.
|
||||
*/
|
||||
public int getWriteReferenceCount()
|
||||
{
|
||||
return mPutReferences.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the total number of references to the Field.
|
||||
* @return the number of references to the Field.
|
||||
*/
|
||||
public int getReferenceCount()
|
||||
{
|
||||
return getReadReferenceCount() + getWriteReferenceCount();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reference to the Field.
|
||||
* @param aFieldRef the reference.
|
||||
*/
|
||||
public void addReference(FieldReference aFieldRef)
|
||||
{
|
||||
// TODO Polymorphize
|
||||
if ((aFieldRef instanceof PUTFIELDReference)
|
||||
|| (aFieldRef instanceof PUTSTATICReference))
|
||||
{
|
||||
mPutReferences.add(aFieldRef);
|
||||
}
|
||||
else {
|
||||
mGetReferences.add(aFieldRef);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import org.apache.bcel.classfile.FieldOrMethod;
|
||||
|
||||
/**
|
||||
* Contains the definition of a Field or a Method.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class FieldOrMethodDefinition
|
||||
{
|
||||
/** the Field or Method */
|
||||
private FieldOrMethod mFieldOrMethod;
|
||||
|
||||
/**
|
||||
* Constructs a <code>FieldOrMethodDefinition</code> for a Field
|
||||
* or a Method.
|
||||
* @param aFieldOrMethod the Field or Method
|
||||
*/
|
||||
protected FieldOrMethodDefinition(FieldOrMethod aFieldOrMethod)
|
||||
{
|
||||
mFieldOrMethod = aFieldOrMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the FieldOrMethod.
|
||||
* @return the FieldOrMethod.
|
||||
*/
|
||||
protected FieldOrMethod getFieldOrMethod()
|
||||
{
|
||||
return mFieldOrMethod;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the name of the Field or Method.
|
||||
* @return the name of the Field or Method.
|
||||
*/
|
||||
public String getName()
|
||||
{
|
||||
return mFieldOrMethod.getName();
|
||||
}
|
||||
|
||||
/** @see java.lang.Object#toString() */
|
||||
public String toString()
|
||||
{
|
||||
return mFieldOrMethod.toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,168 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.Field;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
import org.apache.bcel.generic.Type;
|
||||
|
||||
|
||||
/**
|
||||
* Contains the definition of a org.apache.bcel.classfile.JavaClass and
|
||||
* the definitions of Methods and Fields of the JavaClass
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class JavaClassDefinition
|
||||
{
|
||||
/** the JavaClass */
|
||||
private JavaClass mJavaClass;
|
||||
|
||||
/** the method definitions */
|
||||
private MethodDefinition[] mMethodDefs;
|
||||
|
||||
/** field definitions, keyed on field name */
|
||||
private Map mFieldDefs;
|
||||
|
||||
/**
|
||||
* Creates a JavaClassDefinition from a JavaClass.
|
||||
* @param aJavaClass the JavaClass for the definition.
|
||||
*/
|
||||
public JavaClassDefinition(JavaClass aJavaClass)
|
||||
{
|
||||
mJavaClass = aJavaClass;
|
||||
|
||||
// store method definitions
|
||||
final Method[] methods = aJavaClass.getMethods();
|
||||
mMethodDefs = new MethodDefinition[methods.length];
|
||||
for (int i = 0; i < methods.length; i++) {
|
||||
mMethodDefs[i] = new MethodDefinition(methods[i]);
|
||||
}
|
||||
|
||||
// store field definitions
|
||||
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]));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the JavaClass for this definition.
|
||||
* @return the JavaClass
|
||||
*/
|
||||
public JavaClass getJavaClass()
|
||||
{
|
||||
return mJavaClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the method definitions for Methods of the JavaClass.
|
||||
* @return the method definitions for Methods of the JavaClass.
|
||||
*/
|
||||
public MethodDefinition[] getMethodDefs()
|
||||
{
|
||||
return mMethodDefs;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the field definitions for Fields of the JavaClass.
|
||||
* @return the method definitions for Fields of the JavaClass.
|
||||
*/
|
||||
public FieldDefinition[] getFieldDefs()
|
||||
{
|
||||
return (FieldDefinition[]) mFieldDefs.values().toArray(
|
||||
new FieldDefinition[mFieldDefs.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the narrowest method that is compatible with a method.
|
||||
* An invocation of the given method can be resolved as an invocation
|
||||
* of the narrowest method.
|
||||
* @param aClassName the class for the method.
|
||||
* @param aMethodName the name of the method.
|
||||
* @param aArgTypes the types for the method.
|
||||
* @return the narrowest compatible method.
|
||||
*/
|
||||
public MethodDefinition findNarrowestMethod(
|
||||
String aClassName,
|
||||
String aMethodName,
|
||||
Type[] aArgTypes)
|
||||
{
|
||||
MethodDefinition result = null;
|
||||
final String javaClassName = mJavaClass.getClassName();
|
||||
if (Repository.instanceOf(aClassName, javaClassName)) {
|
||||
// check all
|
||||
for (int i = 0; i < mMethodDefs.length; i++) {
|
||||
// TODO: check access privileges
|
||||
if (mMethodDefs[i].isCompatible(aMethodName, aArgTypes)) {
|
||||
if (result == null) {
|
||||
result = mMethodDefs[i];
|
||||
}
|
||||
//else if (mMethodDefs[i].isAsNarrow(result)) {
|
||||
else if (result.isCompatible(mMethodDefs[i])) {
|
||||
result = mMethodDefs[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a field definition.
|
||||
* @param aFieldName the name of the field.
|
||||
* @return the field definition named aFieldName.
|
||||
*/
|
||||
public FieldDefinition findFieldDef(String aFieldName)
|
||||
{
|
||||
return (FieldDefinition) mFieldDefs.get(aFieldName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether there is reference to a given Method in this JavaClass
|
||||
* definition or a definition in a superclass.
|
||||
* @param aMethodDef the Method to check.
|
||||
* @param aReferenceDAO reference DAO.
|
||||
* @return true if there is a reference to the method of aMethodDef in
|
||||
* this JavaClass or a superclass.
|
||||
*/
|
||||
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)
|
||||
&& (methodDef.hasReference(getJavaClass())))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
currentJavaClass = currentJavaClass.getSuperClass();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
/** @see comp.lang.Object#toString() */
|
||||
public String toString()
|
||||
{
|
||||
return getJavaClass().toString();
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,175 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.classfile.Method;
|
||||
import org.apache.bcel.generic.Type;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.Utils;
|
||||
|
||||
/**
|
||||
* Contains the definition of a Method and its references.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
public class MethodDefinition
|
||||
extends FieldOrMethodDefinition
|
||||
{
|
||||
/** the references to the Method */
|
||||
private Set mReferences = new HashSet();
|
||||
|
||||
/**
|
||||
* Creates a <code>MethodDefinition</code> for a Method.
|
||||
* @param aMethod the Method.
|
||||
*/
|
||||
public MethodDefinition(Method aMethod)
|
||||
{
|
||||
super(aMethod);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the references to the Method.
|
||||
* @return the references to the Method.
|
||||
*/
|
||||
public Set getReferences()
|
||||
{
|
||||
return mReferences;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the number of references to the Method.
|
||||
* @return the number of references to the Method.
|
||||
*/
|
||||
public int getReferenceCount()
|
||||
{
|
||||
return mReferences.size();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Method for this definition.
|
||||
* @return the Method for this definition.
|
||||
*/
|
||||
public Method getMethod()
|
||||
{
|
||||
return (Method) getFieldOrMethod();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reference to the Method.
|
||||
* @param aRef the reference.
|
||||
*/
|
||||
|
||||
public void addReference(InvokeReference aRef)
|
||||
{
|
||||
mReferences.add(aRef);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the Types of the Method's arguments.
|
||||
* @return the argument Types.
|
||||
*/
|
||||
public Type[] getArgumentTypes()
|
||||
{
|
||||
return getMethod().getArgumentTypes();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a Method is compatible with the
|
||||
* Method of this definition.
|
||||
* @param aMethod the Method to check.
|
||||
* @return true if aMethod is compatible with the Method
|
||||
* of this definition.
|
||||
*/
|
||||
public boolean isCompatible(Method aMethod)
|
||||
{
|
||||
return isCompatible(aMethod.getName(), aMethod.getArgumentTypes());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a MethodDefinition is compatible with the
|
||||
* Method of this definition.
|
||||
* @param aMethodDef the Method definition to check.
|
||||
* @return true if aMethod is compatible with the Method
|
||||
* of this definition.
|
||||
*/
|
||||
public boolean isCompatible(MethodDefinition aMethodDef)
|
||||
{
|
||||
return isCompatible(aMethodDef.getMethod());
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the Method of a MethodDefinition is as narrow
|
||||
* as the method for this definition.
|
||||
* Precondition: the method for this has the same name and the same
|
||||
* number of arguments as the Method for the given MethodDefinition.
|
||||
* @param aMethodDef the MethodDefinition to check.
|
||||
* @return true if the Method of aMethodDef is as narrow
|
||||
* as the method for this definition.
|
||||
*/
|
||||
public boolean isAsNarrow(MethodDefinition aMethodDef)
|
||||
{
|
||||
return aMethodDef.isCompatible(this);
|
||||
// final Type[] types1 = getArgumentTypes();
|
||||
// final Type[] types2 = aMethodDef.getArgumentTypes();
|
||||
// for (int i = 0; i < types2.length; i++) {
|
||||
// if (!Utils.isCompatible(types1[i], types2[i])) {
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
// return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether a method is compatible with the Method of
|
||||
* this definition.
|
||||
* @param aMethodName the name of the method to check.
|
||||
* @param aArgTypes the method argument types.
|
||||
* @return true if the method is compatible with the Method of
|
||||
* this definition.
|
||||
*/
|
||||
public boolean isCompatible(String aMethodName, Type[] aArgTypes)
|
||||
{
|
||||
// same name?
|
||||
if (!getName().equals(aMethodName)) {
|
||||
return false;
|
||||
}
|
||||
// compatible argument types?
|
||||
final Type[] methodTypes = getArgumentTypes();
|
||||
if (methodTypes.length != aArgTypes.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < aArgTypes.length; i++) {
|
||||
if (!Utils.isCompatible(aArgTypes[i], methodTypes[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether this method definition has a reference from a class or
|
||||
* a superclass.
|
||||
* @param aJavaClass the JavaClass to check against.
|
||||
* @return true if there is a reference to this method definition from a
|
||||
* aJavaClass or a superclass of aJavaClass.
|
||||
*/
|
||||
public boolean hasReference(JavaClass aJavaClass)
|
||||
{
|
||||
final Iterator it = getReferences().iterator();
|
||||
while (it.hasNext()) {
|
||||
final InvokeReference invokeRef = (InvokeReference) it.next();
|
||||
final String invokeClassName = invokeRef.getClassName();
|
||||
if (Repository.instanceOf(aJavaClass, invokeClassName)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,138 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.classfile;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.bcel.Repository;
|
||||
import org.apache.bcel.classfile.JavaClass;
|
||||
import org.apache.bcel.generic.Type;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.FieldReference;
|
||||
import com.puppycrawl.tools.checkstyle.bcel.generic.InvokeReference;
|
||||
|
||||
/**
|
||||
* Accesses Method and Field references for a set of JavaClasses.
|
||||
* @author Rick Giles
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
public ReferenceDAO(Set aJavaClasses)
|
||||
{
|
||||
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);
|
||||
mJavaClasses.put(javaClass, javaClassDef);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the JavaClassDefinition for a given JavaClass.
|
||||
* @param aJavaClass the JavaClass.
|
||||
* @return the JavaClassDefinition keyed on aJavaClass.
|
||||
*/
|
||||
public JavaClassDefinition findJavaClassDef(JavaClass aJavaClass)
|
||||
{
|
||||
return (JavaClassDefinition) mJavaClasses.get(aJavaClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reference for an invocation in the invoked method definition.
|
||||
* The invocation is of the form class.method(args).
|
||||
* @param aInvokeRef the invocation reference.
|
||||
*/
|
||||
public void addInvokeReference(InvokeReference aInvokeRef)
|
||||
{
|
||||
// find the class for the instruction
|
||||
final String className = aInvokeRef.getClassName();
|
||||
JavaClass javaClass = Repository.lookupClass(className);
|
||||
final String methodName = aInvokeRef.getName();
|
||||
final Type[] argTypes = aInvokeRef.getArgTypes();
|
||||
|
||||
// search up the class hierarchy for the class containing the
|
||||
// method definition.
|
||||
MethodDefinition narrowest = null;
|
||||
while ((javaClass != null) && (narrowest == null)) {
|
||||
final JavaClassDefinition javaClassDef =
|
||||
(JavaClassDefinition) mJavaClasses.get(javaClass);
|
||||
if (javaClassDef != null) {
|
||||
// find narrowest compatible in the current class
|
||||
narrowest =
|
||||
javaClassDef.findNarrowestMethod(
|
||||
className,
|
||||
methodName,
|
||||
argTypes);
|
||||
if (narrowest != null) {
|
||||
narrowest.addReference(aInvokeRef);
|
||||
}
|
||||
}
|
||||
// search the parent
|
||||
javaClass = javaClass.getSuperClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a reference to a field.
|
||||
* @param aFieldRef the field reference.
|
||||
*/
|
||||
public void addFieldReference(FieldReference aFieldRef)
|
||||
{
|
||||
final String className = aFieldRef.getClassName();
|
||||
JavaClass javaClass = Repository.lookupClass(className);
|
||||
final String fieldName = aFieldRef.getName();
|
||||
// search up the class hierarchy for the class containing the
|
||||
// method definition.
|
||||
FieldDefinition fieldDef = null;
|
||||
while ((javaClass != null) && (fieldDef == null)) {
|
||||
final JavaClassDefinition javaClassDef =
|
||||
(JavaClassDefinition) mJavaClasses.get(javaClass);
|
||||
if (javaClassDef != null) {
|
||||
fieldDef = javaClassDef.findFieldDef(fieldName);
|
||||
if (fieldDef != null) {
|
||||
fieldDef.addReference(aFieldRef);
|
||||
}
|
||||
}
|
||||
//search the parent
|
||||
javaClass = javaClass.getSuperClass();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the definition of the field of a field reference.
|
||||
* @param aFieldRef the reference to a field.
|
||||
* @return the definition of the field for aFieldRef.
|
||||
*/
|
||||
public FieldDefinition findFieldDef(FieldReference aFieldRef)
|
||||
{
|
||||
final String className = aFieldRef.getClassName();
|
||||
JavaClass javaClass = Repository.lookupClass(className);
|
||||
final String fieldName = aFieldRef.getName();
|
||||
// search up the class hierarchy for the class containing the
|
||||
// method definition.
|
||||
FieldDefinition result = null;
|
||||
while ((javaClass != null) && (result == null)) {
|
||||
final JavaClassDefinition javaClassDef =
|
||||
(JavaClassDefinition) mJavaClasses.get(javaClass);
|
||||
if (javaClassDef != null) {
|
||||
result = javaClassDef.findFieldDef(fieldName);
|
||||
}
|
||||
//search the parent
|
||||
javaClass = javaClass.getSuperClass();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,61 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.FieldOrMethod;
|
||||
import org.apache.bcel.generic.ObjectType;
|
||||
|
||||
/**
|
||||
* Describe class InstructionReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class FieldOrMethodReference
|
||||
{
|
||||
protected FieldOrMethod mInstruction;
|
||||
|
||||
protected ConstantPoolGen mPoolGen;
|
||||
|
||||
protected FieldOrMethodReference(
|
||||
FieldOrMethod aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
mInstruction = aInstruction;
|
||||
mPoolGen = aPoolGen;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public FieldOrMethod getInstruction()
|
||||
{
|
||||
return mInstruction;
|
||||
}
|
||||
|
||||
public String getClassName()
|
||||
{
|
||||
return mInstruction.getClassName(mPoolGen);
|
||||
}
|
||||
|
||||
public ObjectType getClassType()
|
||||
{
|
||||
return mInstruction.getClassType(mPoolGen);
|
||||
}
|
||||
|
||||
public ObjectType getLoadClassType()
|
||||
{
|
||||
return mInstruction.getLoadClassType(mPoolGen);
|
||||
}
|
||||
|
||||
public String getName()
|
||||
{
|
||||
return mInstruction.getName(mPoolGen);
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return mInstruction.toString(mPoolGen.getConstantPool());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,22 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.FieldInstruction;
|
||||
|
||||
/**
|
||||
* Describe class FieldReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class FieldReference extends FieldOrMethodReference
|
||||
{
|
||||
protected FieldReference(
|
||||
FieldInstruction aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.GETFIELD;
|
||||
|
||||
/**
|
||||
* Describe class GETFIELDReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class GETFIELDReference
|
||||
extends FieldReference
|
||||
{
|
||||
|
||||
/**
|
||||
* @param aInstruction
|
||||
* @param aPoolGen
|
||||
*/
|
||||
public GETFIELDReference(
|
||||
GETFIELD aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.GETSTATIC;
|
||||
|
||||
/**
|
||||
* Describe class GETSTATICReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class GETSTATICReference
|
||||
extends FieldReference
|
||||
{
|
||||
|
||||
/**
|
||||
* @param aInstruction
|
||||
* @param aPoolGen
|
||||
*/
|
||||
public GETSTATICReference(
|
||||
GETSTATIC aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,38 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.InvokeInstruction;
|
||||
import org.apache.bcel.generic.Type;
|
||||
|
||||
|
||||
/**
|
||||
* Describe class MethodReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class InvokeReference
|
||||
extends FieldOrMethodReference
|
||||
{
|
||||
|
||||
/**
|
||||
* @param aInstruction
|
||||
* @param aPoolGen
|
||||
*/
|
||||
public InvokeReference(
|
||||
InvokeInstruction aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
*/
|
||||
public Type[] getArgTypes()
|
||||
{
|
||||
return ((InvokeInstruction) mInstruction).getArgumentTypes(mPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.PUTFIELD;
|
||||
|
||||
/**
|
||||
* Describe class GETFIELDReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class PUTFIELDReference
|
||||
extends FieldReference
|
||||
{
|
||||
|
||||
/**
|
||||
* @param aInstruction
|
||||
* @param aPoolGen
|
||||
*/
|
||||
public PUTFIELDReference(
|
||||
PUTFIELD aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,28 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ConstantPoolGen;
|
||||
import org.apache.bcel.generic.PUTSTATIC;
|
||||
|
||||
/**
|
||||
* Describe class GETSTATICReference
|
||||
* @author Rick Giles
|
||||
* @version 18-Jun-2003
|
||||
*/
|
||||
public class PUTSTATICReference
|
||||
extends FieldReference
|
||||
{
|
||||
|
||||
/**
|
||||
* @param aInstruction
|
||||
* @param aPoolGen
|
||||
*/
|
||||
public PUTSTATICReference(
|
||||
PUTSTATIC aInstruction,
|
||||
ConstantPoolGen aPoolGen)
|
||||
{
|
||||
super(aInstruction, aPoolGen);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,71 @@
|
|||
//Tested with BCEL-5.1
|
||||
//http://jakarta.apache.org/builds/jakarta-bcel/release/v5.1/
|
||||
|
||||
package com.puppycrawl.tools.checkstyle.bcel.generic;
|
||||
|
||||
import org.apache.bcel.generic.ReferenceType;
|
||||
import org.apache.bcel.generic.Type;
|
||||
|
||||
/**
|
||||
* Utility methods.
|
||||
* @author Rick Giles
|
||||
* @version 17-Jun-2003
|
||||
*/
|
||||
public class Utils
|
||||
{
|
||||
/**
|
||||
* Tests whether one type is compatible with another for method
|
||||
* invocation conversion. This includes assignment conversion,
|
||||
* except the implicit narrowing of integer constants.
|
||||
* JLS Section 5.2
|
||||
* @param aSubType the type to be converted.
|
||||
* @param aSuperType the converted type.
|
||||
* @return true if aSubType can be converted to aSuperType.
|
||||
*/
|
||||
public static boolean isCompatible(Type aSubType, Type aSuperType)
|
||||
{
|
||||
boolean result = false;
|
||||
|
||||
if (aSubType.equals(aSuperType)) {
|
||||
// identity conversion
|
||||
result = true;
|
||||
}
|
||||
else if ((aSubType instanceof ReferenceType)
|
||||
&& (aSuperType instanceof ReferenceType))
|
||||
{
|
||||
// widening reference conversion?
|
||||
final ReferenceType aSubRefType = (ReferenceType) aSubType;
|
||||
result = aSubRefType.isAssignmentCompatibleWith(aSuperType);
|
||||
}
|
||||
// widening primitive conversion?
|
||||
else if (aSubType.equals(Type.BYTE)) {
|
||||
result =
|
||||
aSuperType.equals(Type.SHORT)
|
||||
|| aSuperType.equals(Type.INT)
|
||||
|| aSuperType.equals(Type.LONG)
|
||||
|| aSuperType.equals(Type.FLOAT)
|
||||
|| aSuperType.equals(Type.DOUBLE);
|
||||
}
|
||||
else if (aSubType.equals(Type.SHORT)) {
|
||||
result =
|
||||
aSuperType.equals(Type.INT)
|
||||
|| aSuperType.equals(Type.LONG)
|
||||
|| aSuperType.equals(Type.FLOAT)
|
||||
|| aSuperType.equals(Type.DOUBLE);
|
||||
}
|
||||
else if (aSubType.equals(Type.INT)) {
|
||||
result =
|
||||
aSuperType.equals(Type.LONG)
|
||||
|| aSuperType.equals(Type.FLOAT)
|
||||
|| aSuperType.equals(Type.DOUBLE);
|
||||
}
|
||||
else if (aSubType.equals(Type.LONG)) {
|
||||
result =
|
||||
aSuperType.equals(Type.FLOAT) || aSuperType.equals(Type.DOUBLE);
|
||||
}
|
||||
else if (aSubType.equals(Type.DOUBLE)) {
|
||||
result = aSuperType.equals(Type.DOUBLE);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue