avalonization

This commit is contained in:
Lars Kühne 2002-11-30 18:29:44 +00:00
parent 65ca7775ba
commit 6ffc8dd260
11 changed files with 282 additions and 289 deletions

View File

@ -40,6 +40,8 @@ import java.util.List;
import java.util.Properties;
import java.util.Iterator;
import com.puppycrawl.tools.checkstyle.api.Configuration;
/**
* An implementation of a ANT task for calling checkstyle. See the documentation
* of the task for usage.
@ -319,9 +321,15 @@ public class CheckStyleTask
final Configuration config =
ConfigurationLoader.loadConfiguration(
mConfigFile.getAbsolutePath(), props);
config.setClassLoader(new AntClassLoader(getProject(),
mClasspath));
c = new Checker(config);
DefaultContext context = new DefaultContext();
ClassLoader loader = new AntClassLoader(getProject(), mClasspath);
context.add("classloader", loader);
c = new Checker();
c.contextualize(context);
c.configure(config);
// setup the listeners
AuditListener[] listeners = getListeners();
for (int i = 0; i < listeners.length; i++) {

View File

@ -18,22 +18,25 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import java.io.File;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Locale;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
/**
* This class provides the functionality to check a set of files.
* @author <a href="mailto:oliver@puppycrawl.com">Oliver Burn</a>
* @author <a href="mailto:stephane.bailliez@wanadoo.fr">Stephane Bailliez</a>
* @author lkuehne
*/
public class Checker
public class Checker extends AutomaticBean
implements Defn, MessageDispatcher
{
/**
@ -89,73 +92,81 @@ public class Checker
/** maintains error count */
private final ErrorCounter mCounter = new ErrorCounter();
/** configuration */
private final GlobalProperties mConfig;
/** vector of listeners */
private final ArrayList mListeners = new ArrayList();
/** vector of fileset checks */
private final ArrayList mFileSetChecks = new ArrayList();
/**
* Creates a new <code>Checker</code> instance.
*
* @param aConfig the configuration to use
* @throws CheckstyleException if an error occurs
*/
public Checker(Configuration aConfig)
throws CheckstyleException
/** class loader to resolve classes with. **/
private ClassLoader mLoader =
Thread.currentThread().getContextClassLoader();
/** the basedir to strip off in filenames */
private String mBasedir;
public void setLocaleCountry(String aLocaleCountry)
{
this(aConfig.getGlobalProperties(), aConfig.getCheckConfigurations());
mLocaleCountry = aLocaleCountry;
}
public void setLocaleLanguage(String aLocaleLanguage)
{
mLocaleLanguage = aLocaleLanguage;
}
/** locale country to report messages **/
private String mLocaleCountry = Locale.getDefault().getCountry();
/** locale language to report messages **/
private String mLocaleLanguage = Locale.getDefault().getLanguage();
/**
* Creates a new <code>Checker</code> instance.
* The instance needs to be contextualized and configured.
*
* @param aConfig the configuration to use
* @param aConfigs the configuation of the checks to use
* @throws CheckstyleException if an error occurs
*/
public Checker(GlobalProperties aConfig, CheckConfiguration[] aConfigs)
public Checker()
throws CheckstyleException
{
mConfig = aConfig;
LocalizedMessage.setLocale(new Locale(mConfig.getLocaleLanguage(),
mConfig.getLocaleCountry()));
// TODO: create, configure and register the FileSetChecks from config
// file instead of hardcoding it here in the Checker constructor.
// Probably the addFileSetCheck mthod must be called from outside
// the checker, just like the TreeWalker is not concerned with
// finding all the checks it has to execute (IOC principle).
// TODO: uncommenting the addFileSetCheck calls breaks the tests
// because the packageHtml check is always executed and yields
// additional errors that are not expected in the current test code
// (which should stay like it currently is!)
//FileSetCheck translationCheck = new TranslationCheck();
// addFileSetCheck(translationCheck);
//FileSetCheck packageHtmlCheck = new PackageHtmlCheck();
// addFileSetCheck(packageHtmlCheck);
final TreeWalker walker = new TreeWalker(mConfig);
// TODO: improve the error handing
for (int i = 0; i < aConfigs.length; i++) {
final CheckConfiguration config = aConfigs[i];
// IMPORTANT! Need to use the same class loader that created this
// class. Otherwise can get ClassCastException problems.
walker.registerCheck(
config.createInstance(this.getClass().getClassLoader()),
config);
}
addFileSetCheck(walker);
this.addListener(mCounter);
}
/** @see AutomaticBean */
public void configure(Configuration aConfiguration)
throws CheckstyleException
{
super.configure(aConfiguration);
final Locale locale = new Locale(mLocaleLanguage, mLocaleCountry);
LocalizedMessage.setLocale(locale);
DefaultContext context = new DefaultContext();
context.add("classLoader", this.getClassLoader());
Configuration[] fileSetChecks = aConfiguration.getChildren();
for (int i = 0; i < fileSetChecks.length; i++) {
Configuration fscConf = fileSetChecks[i];
String className = fscConf.getAttribute("classname");
try {
Class clazz = Class.forName(className);
FileSetCheck fsc = (FileSetCheck) clazz.newInstance();
fsc.contextualize(context);
fsc.configure(fscConf);
addFileSetCheck(fsc);
}
catch (Exception ex) {
// TODO i18n
throw new CheckstyleException(
"cannot initialize filesetcheck of class " + className);
}
}
}
private ClassLoader getClassLoader()
{
return mLoader;
}
/**
* Adds a FileSetCheck to the list of FileSetChecks
* that is executed in process().
@ -211,18 +222,21 @@ public class Checker
private String getStrippedFileName(final String aFileName)
{
final String stripped;
final String basedir = mConfig.getBasedir();
if ((basedir == null) || !aFileName.startsWith(basedir)) {
if ((mBasedir == null) || !aFileName.startsWith(mBasedir)) {
stripped = aFileName;
}
else {
// making the assumption that there is text after basedir
final int skipSep = basedir.endsWith(File.separator) ? 0 : 1;
stripped = aFileName.substring(basedir.length() + skipSep);
final int skipSep = mBasedir.endsWith(File.separator) ? 0 : 1;
stripped = aFileName.substring(mBasedir.length() + skipSep);
}
return stripped;
}
public void setBasedir(String aBasedir)
{
mBasedir = aBasedir;
}
/** notify all listeners about the audit start */
protected void fireAuditStarted()

View File

@ -21,14 +21,12 @@ package com.puppycrawl.tools.checkstyle;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Properties;
import java.util.Stack;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParserFactory;
import org.apache.regexp.RESyntaxException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
@ -51,20 +49,10 @@ class ConfigurationLoader
private Properties mOverrideProps = new Properties();
/** parser to read XML files **/
private final XMLReader mParser;
/** the loaded global properties **/
private final Properties mProps = new Properties();
/** the loaded configurations **/
private final ArrayList mCheckConfigs = new ArrayList();
/** the loaded configuration **/
private Configuration mConfig = null;
/** the current check configuration being created **/
private CheckConfiguration mCurrent;
/** buffer for collecting text **/
private final StringBuffer mBuf = new StringBuffer();
/** in global element **/
private boolean mIsInGlobalElement = false;
/** started processing check configurations **/
private boolean mIsInCheckMode = false;
private Stack mConfigStack = new Stack();
/** the Configuration that is beeing built */
private Configuration mConfiguration = null;
/**
* Creates a new <code>ConfigurationLoader</code> instance.
@ -91,71 +79,50 @@ class ConfigurationLoader
mParser.parse(new InputSource(new FileReader(aFilename)));
}
/**
* Returns the configuration information in the last file parsed.
* @return list of CheckConfiguration objects
*/
CheckConfiguration[] getConfigs()
{
return (CheckConfiguration[]) mCheckConfigs.toArray(
new CheckConfiguration[mCheckConfigs.size()]);
}
///////////////////////////////////////////////////////////////////////////
// Document handler methods
///////////////////////////////////////////////////////////////////////////
/** @see org.xml.sax.helpers.DefaultHandler **/
public void characters(char[] aChars, int aStart, int aLength)
{
mBuf.append(String.valueOf(aChars, aStart, aLength));
}
/** @see org.xml.sax.helpers.DefaultHandler **/
public void startElement(String aNamespaceURI,
String aLocalName,
String aQName,
Attributes aAtts)
throws SAXException
{
mBuf.setLength(0);
if ("global".equals(aQName)) {
mIsInGlobalElement = true;
}
else if ("check".equals(aQName)) {
//first apply overriding properties
if (!mIsInCheckMode) {
mIsInCheckMode = true;
for (Enumeration enum = mOverrideProps.keys();
enum.hasMoreElements();)
{
final String key = (String) enum.nextElement();
final String value = (String) mOverrideProps.get(key);
mProps.setProperty(key, value);
// TODO: debug logging for support puposes
DefaultConfiguration conf = new DefaultConfiguration(aQName);
System.out.println("aQName = " + aQName);
final int attCount = aAtts.getLength();
for (int i = 0; i < attCount; i++) {
String name = aAtts.getQName(i);
String value = aAtts.getValue(i);
System.out.println(" value of " + name + " is " + value);
// expand properties
if (value.startsWith("${") && value.endsWith("}")) {
String propName = value.substring(2, value.length() - 1);
value = mOverrideProps.getProperty(propName);
if (value == null) {
throw new SAXException("missing external property " + propName);
}
System.out.println(" propName = " + propName);
System.out.println(" new value = " + value);
}
mCurrent = new CheckConfiguration();
mCurrent.setClassname(aAtts.getValue("classname"));
}
else if ("property".equals(aQName)) {
final String name = aAtts.getValue("name");
String value = aAtts.getValue("value");
if (value == null) {
//try global
String globalKey = aAtts.getValue("from-global");
value = (String) mProps.get(globalKey);
}
if (mIsInGlobalElement) {
mProps.setProperty(name, value);
}
else {
mCurrent.addProperty(name, value);
}
conf.addAttribute(name, value);
}
if (mConfiguration == null) {
mConfiguration = conf;
}
if (!mConfigStack.isEmpty()) {
DefaultConfiguration top = (DefaultConfiguration) mConfigStack.peek();
top.addChild(conf);
}
mConfigStack.push(conf);
}
/** @see org.xml.sax.helpers.DefaultHandler **/
@ -163,44 +130,7 @@ class ConfigurationLoader
String aLocalName,
String aQName)
{
if ("global".equals(aQName)) {
mIsInGlobalElement = false;
}
else if ("check".equals(aQName)) {
mCheckConfigs.add(mCurrent);
mCurrent = null;
}
else if ("tokens".equals(aQName)) {
mCurrent.addTokens(mBuf.toString());
}
}
/**
* Returns the check configurations in a specified file.
* @param aConfigFname name of config file
* @return the check configurations
* @throws CheckstyleException if an error occurs
*/
public static CheckConfiguration[] loadConfigs(String aConfigFname)
throws CheckstyleException
{
try {
final ConfigurationLoader loader = new ConfigurationLoader();
loader.parseFile(aConfigFname);
return loader.getConfigs();
}
catch (FileNotFoundException e) {
throw new CheckstyleException("unable to find " + aConfigFname);
}
catch (ParserConfigurationException e) {
throw new CheckstyleException("unable to parse " + aConfigFname);
}
catch (SAXException e) {
throw new CheckstyleException("unable to parse " + aConfigFname);
}
catch (IOException e) {
throw new CheckstyleException("unable to read " + aConfigFname);
}
mConfigStack.pop();
}
/**
@ -227,32 +157,20 @@ class ConfigurationLoader
throw new CheckstyleException("unable to parse " + aConfigFname);
}
catch (SAXException e) {
throw new CheckstyleException("unable to parse " + aConfigFname);
throw new CheckstyleException("unable to parse "
+ aConfigFname + " - " + e.getMessage());
}
catch (IOException e) {
throw new CheckstyleException("unable to read " + aConfigFname);
}
catch (RESyntaxException e) {
throw new CheckstyleException(
"A regular expression error exists in " + aConfigFname);
}
}
/**
* Returns the configuration in the last file parsed.
* @return Configuration object
* @throws RESyntaxException if an error occurs
* @throws FileNotFoundException if an error occurs
* @throws IOException if an error occurs
*/
private Configuration getConfiguration()
throws IOException, FileNotFoundException, RESyntaxException
{
final GlobalProperties globalProps =
new GlobalProperties(mProps, System.out);
final CheckConfiguration[] checkConfigs =
(CheckConfiguration[]) mCheckConfigs.toArray(
new CheckConfiguration[mCheckConfigs.size()]);
return new Configuration(globalProps, checkConfigs);
return mConfiguration;
}
}

View File

@ -28,32 +28,4 @@ public interface Defn
// TODO: Change to a class - follow the advice of Bloch.
/** name of resource bundle for Checkstyle */
String CHECKSTYLE_BUNDLE = "com.puppycrawl.tools.checkstyle.messages";
/** property name for allowing protected data **/
String TAB_WIDTH_PROP = "checkstyle.tab.width";
/** property name for cache file **/
String CACHE_FILE_PROP = "checkstyle.cache.file";
/** property name for the base directory **/
String BASEDIR_PROP = "checkstyle.basedir";
/** property name for the locale language for reporting **/
String LOCALE_LANGUAGE_PROP = "checkstyle.locale.language";
/** property name for the locale country for reporting **/
String LOCALE_COUNTRY_PROP = "checkstyle.locale.country";
/** All the integer properties */
String[] ALL_INT_PROPS = new String[]
{
TAB_WIDTH_PROP,
};
/** All the String properties */
String[] ALL_STRING_PROPS = new String[]
{
BASEDIR_PROP,
CACHE_FILE_PROP,
LOCALE_COUNTRY_PROP,
LOCALE_LANGUAGE_PROP,
};
}

View File

@ -34,6 +34,7 @@ import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
import org.apache.commons.cli.PosixParser;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
@ -86,24 +87,11 @@ public final class Main
usage();
}
// Load the config file
// CheckConfiguration[] checkConfigs = null;
// try {
// checkConfigs =
// ConfigurationLoader.loadConfigs(line.getOptionValue("c"));
// }
// catch (CheckstyleException e) {
// System.out.println("Error loading configuration file");
// e.printStackTrace(System.out);
// System.exit(1);
// }
// Load the config file
Configuration config = null;
try {
config =
ConfigurationLoader.loadConfiguration(line.getOptionValue("c"),
props);
config = ConfigurationLoader.loadConfiguration(
line.getOptionValue("c"), props);
}
catch (CheckstyleException e) {
System.out.println("Error loading configuration file");
@ -166,24 +154,11 @@ public final class Main
usage();
}
// // create the checker
// Checker c = null;
// try {
// c = new Checker(new GlobalProperties(props, System.out),
// checkConfigs);
// c.addListener(listener);
// }
// catch (Exception e) {
// System.out.println("Unable to create Checker: "
// + e.getMessage());
// e.printStackTrace(System.out);
// System.exit(1);
// }
// create the checker
Checker c = null;
try {
c = new Checker(config);
c = new Checker();
c.configure(config);
c.addListener(listener);
}
catch (Exception e) {

View File

@ -24,13 +24,16 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ByteArrayOutputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.Properties;
import java.security.MessageDigest;
import com.puppycrawl.tools.checkstyle.api.Configuration;
/**
* This class maintains a persistent store of the files that have
* checked ok and their associated timestamp. It uses a property file
* for storage. A hashcode of the GlobalProperties is stored in the
* for storage. A hashcode of the Configuration is stored in the
* cache file to ensure the cache is invalidated when the
* configuration has changed.
*
@ -56,10 +59,10 @@ class PropertyCacheFile
*
* @param aCurrentConfig the current configuration, not null
*/
PropertyCacheFile(GlobalProperties aCurrentConfig)
PropertyCacheFile(Configuration aCurrentConfig, String aFileName)
{
boolean setInActive = true;
final String fileName = aCurrentConfig.getCacheFile();
final String fileName = aFileName;
if (fileName != null) {
try {
mDetails.load(new FileInputStream(fileName));
@ -79,6 +82,7 @@ class PropertyCacheFile
setInActive = false;
}
catch (IOException e) {
// TODO: use logger
System.out.println("Unable to open cache file, ignoring.");
e.printStackTrace(System.out);
}
@ -128,10 +132,10 @@ class PropertyCacheFile
* @param aConfiguration the GlobalProperties
* @return the hashcode for <code>aConfiguration</code>
*/
private String getConfigHashCode(GlobalProperties aConfiguration)
private String getConfigHashCode(Serializable aConfiguration)
{
try {
// im-memory serialization of GlobalProperties
// im-memory serialization of Configuration
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);

View File

@ -18,29 +18,30 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle;
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.api.FileContents;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.checks.AbstractFileSetCheck;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.Reader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import java.util.Arrays;
import java.io.Reader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import antlr.RecognitionException;
import antlr.TokenStreamException;
import com.puppycrawl.tools.checkstyle.api.Check;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.FileContents;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessages;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.api.Utils;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.checks.AbstractFileSetCheck;
/**
* Responsible for walking an abstract syntax tree and notifying interested
@ -105,27 +106,72 @@ public final class TreeWalker
private final Set mAllChecks = new HashSet();
/** collects the error messages */
private final LocalizedMessages mMessages;
/** the tab width for error reporting */
private final int mTabWidth;
/** the distance between tab stops */
private int mTabWidth = 8;
/** cache file **/
private final PropertyCacheFile mCache;
private PropertyCacheFile mCache = new PropertyCacheFile(null, null);
/**
* the global configuration.
* TODO: should only know the treewalker part of the config
*/
private final GlobalProperties mConfig;
private Configuration mConfig;
private ClassLoader mClassLoader;
/**
* Creates a new <code>TreeWalker</code> instance.
*
* @param aConfig the configuration to use
*/
public TreeWalker(GlobalProperties aConfig)
public TreeWalker()
{
mMessages = new LocalizedMessages();
mConfig = aConfig;
mTabWidth = aConfig.getTabWidth();
mCache = new PropertyCacheFile(aConfig);
}
/** sets the distance between tab stops */
public void setTabWidth(int aTabWidth)
{
mTabWidth = aTabWidth;
}
public void setCacheFile(String aFileName)
{
mCache = new PropertyCacheFile(mConfig, aFileName);
}
// TODO: Call from contextualize
public void setClassLoader(ClassLoader aClassLoader)
{
mClassLoader = aClassLoader;
}
public void configure(Configuration aConfiguration)
throws CheckstyleException
{
super.configure(aConfiguration);
mConfig = aConfiguration;
DefaultContext checkContext = new DefaultContext();
checkContext.add("classLoader", mClassLoader);
checkContext.add("messages", mMessages);
// TODO: hmmm.. this looks less than elegant
checkContext.add("tabWidth", String.valueOf(mTabWidth));
// TODO: improve the error handing
Configuration[] checkConfigs = aConfiguration.getChildren();
for (int i = 0; i < checkConfigs.length; i++) {
final Configuration config = checkConfigs[i];
// IMPORTANT! Need to use the same class loader that created this
// class. Otherwise can get ClassCastException problems.
final String className = config.getAttribute("classname");
final Check check = createCheck(
this.getClass().getClassLoader(), className);
check.contextualize(checkContext);
check.configure(config);
registerCheck(check);
}
}
/**
@ -147,7 +193,7 @@ public final class TreeWalker
final String[] lines = Utils.getLines(fileName);
final FileContents contents = new FileContents(fileName, lines);
final DetailAST rootAST = TreeWalker.parse(contents);
walk(rootAST, contents, mConfig.getClassLoader());
walk(rootAST, contents);
}
catch (FileNotFoundException fnfe) {
mMessages.add(new LocalizedMessage(0, Defn.CHECKSTYLE_BUNDLE,
@ -184,16 +230,15 @@ public final class TreeWalker
/**
* Register a check for a given configuration.
* @param aCheck the check to register
* @param aConfig the configuration to use
*/
void registerCheck(Check aCheck, CheckConfiguration aConfig)
void registerCheck(Check aCheck)
throws CheckstyleException
{
aCheck.setMessages(mMessages);
aCheck.setTabWidth(mTabWidth);
if (!aConfig.getTokens().isEmpty()) {
final Set checkTokens = aCheck.getTokens();
if (!checkTokens.isEmpty()) {
int acceptableTokens[] = aCheck.getAcceptableTokens();
Arrays.sort(acceptableTokens);
final Iterator it = aConfig.getTokens().iterator();
final Iterator it = checkTokens.iterator();
while (it.hasNext()) {
String token = (String) it.next();
int tokenId = TokenTypes.getTokenId(token);
@ -242,12 +287,11 @@ public final 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, ClassLoader aLoader)
private void walk(DetailAST aAST, FileContents aContents)
{
mMessages.reset();
notifyBegin(aContents, aLoader);
notifyBegin(aContents);
// empty files are not flagged by javac, will yield aAST == null
if (aAST != null) {
@ -261,9 +305,8 @@ public final 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, ClassLoader aLoader)
private void notifyBegin(FileContents aContents)
{
// TODO: do not track Context properly for token
final Iterator it = mAllChecks.iterator();
@ -272,7 +315,6 @@ public final class TreeWalker
final HashMap treeContext = new HashMap();
check.setTreeContext(treeContext);
check.setFileContents(aContents);
check.setClassLoader(aLoader);
check.beginTree();
}
}
@ -355,7 +397,7 @@ public final class TreeWalker
}
/**
*
* Static helper method to parses a Java source file.
* @param aContents contains the contents of the file
* @return the root of the AST
* @throws TokenStreamException if lexing failed
@ -418,4 +460,37 @@ public final class TreeWalker
super.destroy();
mCache.destroy();
}
/**
* Create an instance of the check that is properly initialised.
*
* @param aLoader the <code>ClassLoader</code> to create the instance with
* @return the created check
* @throws CheckstyleException if an error occurs
*/
private Check createCheck(
ClassLoader aLoader, String aClassName)
throws CheckstyleException
{
try {
final Class clazz = Class.forName(aClassName, true, aLoader);
final Check check = (Check) clazz.newInstance();
return check;
}
catch (ClassNotFoundException e) {
throw new CheckstyleException(
"Unable to find class for " + aClassName);
}
catch (InstantiationException e) {
throw new CheckstyleException(
"Unable to instantiate " + aClassName);
}
catch (IllegalAccessException e) {
throw new CheckstyleException(
"Unable to instantiate " + aClassName);
}
}
}

View File

@ -18,7 +18,9 @@
////////////////////////////////////////////////////////////////////////////////
package com.puppycrawl.tools.checkstyle.api;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* The base class for checks.
@ -26,18 +28,18 @@ import java.util.Map;
* @author <a href="mailto:checkstyle@puppycrawl.com">Oliver Burn</a>
* @version 1.0
*/
public abstract class Check
public abstract class Check extends AutomaticBean
{
/** resuable constant for message formating */
private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
/** 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;
/** the tokens the check is interested in */
private final Set mTokens = new HashSet();
/**
* the object for collecting messages. decided to not put in the global
* context for performance and ease of use.
@ -50,6 +52,8 @@ public abstract class Check
/** the tab with for column reporting */
private int mTabWidth = 8; // meaningful default
private ClassLoader mLoader = Thread.currentThread().getContextClassLoader();
/**
* Returns the default token a check is interested in. Only used if the
* configuration for a check does not define the tokens.
@ -84,6 +88,27 @@ public abstract class Check
//
// Lets worry about it when it becomes a problem.
/**
* Adds a set of tokens the check is interested in.
* @param aStrRep the string representation of the tokens interested in
*/
final public void setTokens(String[] aStrRep)
{
for (int i = 0; i < aStrRep.length; i++) {
String s = aStrRep[i];
mTokens.add(s);
}
}
/**
* Returns the tokens registered for the check.
* @return the set of token names
*/
final public Set getTokens()
{
return mTokens;
}
/**
* Return the global context object for check. This context is valid for
@ -231,7 +256,7 @@ public abstract class Check
*/
public final void setClassLoader(ClassLoader aLoader)
{
getTreeContext().put(CLASS_LOADER_ATTRIBUTE, aLoader);
mLoader = aLoader;
}
/**
@ -240,7 +265,7 @@ public abstract class Check
*/
public final ClassLoader getClassLoader()
{
return (ClassLoader) getTreeContext().get(CLASS_LOADER_ATTRIBUTE);
return mLoader;
}
/** @return the tab width to report errors with */

View File

@ -25,7 +25,7 @@ import java.io.File;
*
* @author lkuehne
*/
public interface FileSetCheck
public interface FileSetCheck extends Configurable, Contextualizable
{
/**
* Sets the MessageDispatcher that is used to dispatch error

View File

@ -24,6 +24,7 @@ import java.io.File;
import com.puppycrawl.tools.checkstyle.api.FileSetCheck;
import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
/**
* Provides common functionality for many FileSetChecks.
@ -34,7 +35,8 @@ import com.puppycrawl.tools.checkstyle.api.MessageDispatcher;
*
* @author lkuehne
*/
public abstract class AbstractFileSetCheck implements FileSetCheck
public abstract class AbstractFileSetCheck
extends AutomaticBean implements FileSetCheck
{
/** The dispatcher errors are fired to. */
private MessageDispatcher mDispatcher = null;

View File

@ -210,7 +210,7 @@ public class TranslationCheck extends AbstractFileSetCheck
for (Iterator it = keysClone.iterator(); it.hasNext();) {
Object[] key = new Object[]{it.next()};
LocalizedMessage[] errors = new LocalizedMessage[1];
final String bundle = getClass().getName() + ".messages";
final String bundle = getClass().getPackage().getName() + ".messages";
errors[0] = new LocalizedMessage(
0, bundle, "translation.missingKey", key);
getMessageDispatcher().fireErrors(path, errors);