avalonization
This commit is contained in:
parent
65ca7775ba
commit
6ffc8dd260
|
|
@ -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++) {
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Reference in New Issue