From 5fc3ff2bfbed94f88e1af95f38e970a832e4dbe6 Mon Sep 17 00:00:00 2001 From: Oliver Burn Date: Wed, 6 Nov 2002 03:57:58 +0000 Subject: [PATCH] Please ensure you thoroughly test code before committing it. As a sanity test, ensure that the target "checkstyle.checkstyle" will run! If in doubt, do not commit, but instead said a patch to the devel mailing list for a review. Finished the port of the ClassResolver code. Even though it compiled, it had no chance of working due to class casting problems. They have not been fixed. Also needed to ensure the correct class loader is being used. --- docs/checkstyle_checks.xml | 6 +- .../puppycrawl/tools/checkstyle/Checker.java | 2 +- .../tools/checkstyle/ClassResolver.java | 144 ------------------ .../tools/checkstyle/TreeWalker.java | 9 +- .../tools/checkstyle/api/Check.java | 20 +++ .../checkstyle/checks/ClassResolver.java | 6 +- .../checkstyle/checks/JavadocMethodCheck.java | 15 +- .../{ => checks}/ClassResolverTest.java | 10 +- 8 files changed, 46 insertions(+), 166 deletions(-) delete mode 100644 src/checkstyle/com/puppycrawl/tools/checkstyle/ClassResolver.java rename src/tests/com/puppycrawl/tools/checkstyle/{ => checks}/ClassResolverTest.java (82%) diff --git a/docs/checkstyle_checks.xml b/docs/checkstyle_checks.xml index 4f12c5c63..840315221 100644 --- a/docs/checkstyle_checks.xml +++ b/docs/checkstyle_checks.xml @@ -17,11 +17,11 @@ - + - + - + diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java index 9cfe07a8a..3eae11b8f 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/Checker.java @@ -398,7 +398,7 @@ public class Checker final String[] lines = Utils.getLines(aFileName); final FileContents contents = new FileContents(aFileName, lines); final DetailAST rootAST = parse(contents); - mWalker.walk(rootAST, contents); + mWalker.walk(rootAST, contents, mConfig.getClassLoader()); } catch (FileNotFoundException fnfe) { mMessages.add(new LocalizedMessage(0, Defn.CHECKSTYLE_BUNDLE, diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/ClassResolver.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/ClassResolver.java deleted file mode 100644 index d80d8b9f0..000000000 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/ClassResolver.java +++ /dev/null @@ -1,144 +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 java.util.Set; -import java.util.Iterator; - -/** - * Utility class to resolve a class name to an actual class. Note that loaded - * classes are not initialized. - *

Limitations: this does not handle inner classes very well.

- * - * @author Oliver Burn - * @version 1.0 - */ -class ClassResolver -{ - /** name of the package to check if the class belongs to **/ - private final String mPkg; - /** set of imports to check against **/ - private final Set mImports; - /** use to load classes **/ - private final ClassLoader mLoader; - - /** - * Creates a new ClassResolver instance. - * - * @param aLoader the ClassLoader to load classes with. - * @param aPkg the name of the package the class may belong to - * @param aImports set of imports to check if the class belongs to - */ - ClassResolver(ClassLoader aLoader, String aPkg, Set aImports) - { - mLoader = aLoader; - mPkg = aPkg; - mImports = aImports; - } - - /** - * Attempts to resolve the Class for a specified name. The algorithm is - * to check: - * - fully qualified name - * - explicit imports - * - enclosing package - * - star imports - * @param aName name of the class to resolve - * @return the resolved class - * @throws ClassNotFoundException if unable to resolve the class - */ - Class resolve(String aName) throws ClassNotFoundException - { - // See if the class is full qualified - if (isLoadable(aName)) { - return safeLoad(aName); - } - - // try matching explicit imports - Iterator it = mImports.iterator(); - while (it.hasNext()) { - final String imp = ((LineText) it.next()).getText(); - if (imp.endsWith(aName) && isLoadable(imp)) { - return safeLoad(imp); - } - } - - // See if in the package - if (mPkg != null) { - final String fqn = mPkg + "." + aName; - if (isLoadable(fqn)) { - return safeLoad(fqn); - } - } - - // try "java.lang." - final String langClass = "java.lang." + aName; - if (isLoadable(langClass)) { - return safeLoad(langClass); - } - - // try star imports - it = mImports.iterator(); - while (it.hasNext()) { - final String imp = ((LineText) it.next()).getText(); - if (imp.endsWith(".*")) { - final String fqn = imp.substring(0, imp.lastIndexOf('.') + 1) - + aName; - if (isLoadable(fqn)) { - return safeLoad(fqn); - } - } - } - - // Giving up, the type is unknown, so load the class to generate an - // exception - return safeLoad(aName); - } - - /** - * @return whether a specified class is loadable with safeLoad(). - * @param aName name of the class to check - */ - boolean isLoadable(String aName) - { - try { - safeLoad(aName); - return true; - } - catch (ClassNotFoundException e) { - return false; - } - } - - /** - * Will load a specified class is such a way that it will NOT be - * initialised. - * @param aName name of the class to load - * @return the Class for the specified class - * @throws ClassNotFoundException if an error occurs - */ - Class safeLoad(String aName) - throws ClassNotFoundException - { - // The next line will load the class using the specified class - // loader. The magic is having the "false" parameter. This means the - // class will not be initialised. Very, very important. - return Class.forName(aName, false, mLoader); - } -} diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java index f2b391865..5e8710f21 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/TreeWalker.java @@ -125,11 +125,12 @@ class TreeWalker * Initiates the walk of an AST. * @param aAST the root AST * @param aContents the contents of the file the AST was generated from + * @param aLoader the class loader for resolving classes */ - void walk(DetailAST aAST, FileContents aContents) + void walk(DetailAST aAST, FileContents aContents, ClassLoader aLoader) { mMessages.reset(); - notifyBegin(aContents); + notifyBegin(aContents, aLoader); // empty files are not flagged by javac, will yield aAST == null if (aAST != null) { @@ -143,8 +144,9 @@ class TreeWalker /** * Notify interested checks that about to begin walking a tree. * @param aContents the contents of the file the AST was generated from + * @param aLoader the class loader for resolving classes */ - private void notifyBegin(FileContents aContents) + private void notifyBegin(FileContents aContents, ClassLoader aLoader) { // TODO: do not track Context properly for token final Iterator it = mAllChecks.iterator(); @@ -153,6 +155,7 @@ class TreeWalker final HashMap treeContext = new HashMap(); check.setTreeContext(treeContext); check.setFileContents(aContents); + check.setClassLoader(aLoader); check.beginTree(); } } diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java index 1ca3e777d..ebd1e3b21 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/api/Check.java @@ -33,6 +33,8 @@ public abstract class Check /** name to store file contents under */ private static final String FILE_CONTENTS_ATTRIBUTE = "fILEcONTENTS"; + /** name to store class loader under */ + private static final String CLASS_LOADER_ATTRIBUTE = "cLaSsLoAdEr"; /** the global context for the check */ private Map mGlobalContext; @@ -224,6 +226,24 @@ public abstract class Check return (FileContents) getTreeContext().get(FILE_CONTENTS_ATTRIBUTE); } + /** + * Set the class loader associated with the tree. + * @param aLoader the class loader + */ + public final void setClassLoader(ClassLoader aLoader) + { + getTreeContext().put(CLASS_LOADER_ATTRIBUTE, aLoader); + } + + /** + * Returns the class loader associated with the tree. + * @return the class loader + */ + public final ClassLoader getClassLoader() + { + return (ClassLoader) getTreeContext().get(CLASS_LOADER_ATTRIBUTE); + } + /** @return the tab width to report errors with */ protected final int getTabWidth() { diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ClassResolver.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ClassResolver.java index d5c7420a3..3ad213f6b 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ClassResolver.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/ClassResolver.java @@ -21,8 +21,6 @@ package com.puppycrawl.tools.checkstyle.checks; import java.util.Set; import java.util.Iterator; -import com.puppycrawl.tools.checkstyle.api.DetailAST; - /** * Utility class to resolve a class name to an actual class. Note that loaded * classes are not initialized. @@ -75,7 +73,7 @@ class ClassResolver // try matching explicit imports Iterator it = mImports.iterator(); while (it.hasNext()) { - final String imp = ((DetailAST) it.next()).getText(); + final String imp = (String) it.next(); if (imp.endsWith(aName) && isLoadable(imp)) { return safeLoad(imp); } @@ -98,7 +96,7 @@ class ClassResolver // try star imports it = mImports.iterator(); while (it.hasNext()) { - final String imp = ((DetailAST) it.next()).getText(); + final String imp = (String) it.next(); if (imp.endsWith(".*")) { final String fqn = imp.substring(0, imp.lastIndexOf('.') + 1) + aName; diff --git a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/JavadocMethodCheck.java b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/JavadocMethodCheck.java index a0d0108b5..fb54c195d 100644 --- a/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/JavadocMethodCheck.java +++ b/src/checkstyle/com/puppycrawl/tools/checkstyle/checks/JavadocMethodCheck.java @@ -179,7 +179,7 @@ public class JavadocMethodCheck { final FullIdent name = getImportText(aAST); if (name != null) { - mImports.add(name); + mImports.add(name.getText()); } } @@ -473,13 +473,16 @@ public class JavadocMethodCheck if (!found) { boolean reqd = true; if (mCheckUnusedThrows) { - final ClassResolver cr = new ClassResolver( - Thread.currentThread().getContextClassLoader(), - mPackageFullIdent.getText(), mImports); + final ClassResolver cr = + new ClassResolver( + getClassLoader(), + mPackageFullIdent.getText(), + mImports); try { final Class clazz = cr.resolve(tag.getArg1()); - reqd = !RuntimeException.class.isAssignableFrom(clazz) - && !Error.class.isAssignableFrom(clazz); + reqd = + !RuntimeException.class.isAssignableFrom(clazz) + && !Error.class.isAssignableFrom(clazz); } catch (ClassNotFoundException e) { log(tag.getLineNo(), "javadoc.classInfo", diff --git a/src/tests/com/puppycrawl/tools/checkstyle/ClassResolverTest.java b/src/tests/com/puppycrawl/tools/checkstyle/checks/ClassResolverTest.java similarity index 82% rename from src/tests/com/puppycrawl/tools/checkstyle/ClassResolverTest.java rename to src/tests/com/puppycrawl/tools/checkstyle/checks/ClassResolverTest.java index be5339767..88eaaf834 100644 --- a/src/tests/com/puppycrawl/tools/checkstyle/ClassResolverTest.java +++ b/src/tests/com/puppycrawl/tools/checkstyle/checks/ClassResolverTest.java @@ -1,4 +1,4 @@ -package com.puppycrawl.tools.checkstyle; +package com.puppycrawl.tools.checkstyle.checks; import junit.framework.TestCase; @@ -16,9 +16,9 @@ public class ClassResolverTest public void testMisc() throws ClassNotFoundException { final Set imps = new HashSet(); - imps.add(new LineText(666, "java.io.File")); - imps.add(new LineText(666, "nothing.will.match.*")); - imps.add(new LineText(666, "java.applet.*")); + imps.add("java.io.File"); + imps.add("nothing.will.match.*"); + imps.add("java.applet.*"); ClassResolver cr = new ClassResolver(Thread.currentThread().getContextClassLoader(), null, imps); @@ -40,7 +40,7 @@ public class ClassResolverTest catch (ClassNotFoundException e) { } - imps.add(new LineText(324, "java.text.ChoiceFormat")); + imps.add("java.text.ChoiceFormat"); cr.resolve("ChoiceFormat"); cr = new ClassResolver(Thread.currentThread().getContextClassLoader(),