diff --git a/checkstyle-sonar-plugin/pom.xml b/checkstyle-sonar-plugin/pom.xml
index b496c4eb..fcb103ee 100644
--- a/checkstyle-sonar-plugin/pom.xml
+++ b/checkstyle-sonar-plugin/pom.xml
@@ -94,6 +94,13 @@
test
+
+ org.apache.ant
+ ant
+ 1.9.7
+ test
+
+
diff --git a/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/CheckUtil.java b/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/CheckUtil.java
index 7c1befcd..ad7a6013 100644
--- a/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/CheckUtil.java
+++ b/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/CheckUtil.java
@@ -22,40 +22,103 @@
import java.io.IOException;
import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
import java.text.MessageFormat;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
+import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
+import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
+import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
+import com.puppycrawl.tools.checkstyle.api.Filter;
+import com.puppycrawl.tools.checkstyle.guava.collect.ImmutableSet;
+import com.puppycrawl.tools.checkstyle.guava.reflect.ClassPath;
+import com.puppycrawl.tools.checkstyle.guava.reflect.ClassPath.ClassInfo;
+
public final class CheckUtil {
private CheckUtil() {
}
/**
- * Gets the checkstyle's modules. Checkstyle's modules are nonabstract
- * classes from com.puppycrawl.tools.checkstyle package which names end with
- * 'Check', do not contain the word 'Input' (are not input files for UTs),
- * checkstyle's filters and SuppressWarningsHolder class.
- *
- * @return a set of checkstyle's modules names.
+ * Gets all checkstyle's modules.
+ * @return the set of checkstyle's module classes.
* @throws IOException if the attempt to read class path resources failed.
+ * @see #isCheckstyleModule(Class)
*/
public static Set> getCheckstyleModules() throws IOException {
final Set> checkstyleModules = new HashSet<>();
-// final ClassLoader loader = Thread.currentThread().getContextClassLoader();
-// final ClassPath classpath = ClassPath.from(loader);
-// final String packageName = "com.puppycrawl.tools.checkstyle.checks";
-// final ImmutableSet checkstyleClasses = classpath
-// .getTopLevelClassesRecursive(packageName);
-//
-// for (ClassPath.ClassInfo clazz : checkstyleClasses) {
-// final Class> loadedClass = clazz.load();
-// if (isCheckstyleModule(loadedClass)) {
-// checkstyleModules.add(loadedClass);
-// }
-// }
+ final ClassLoader loader = Thread.currentThread()
+ .getContextClassLoader();
+ final ClassPath classpath = ClassPath.from(loader);
+ final String packageName = "com.puppycrawl.tools.checkstyle";
+ final ImmutableSet checkstyleClasses = classpath
+ .getTopLevelClassesRecursive(packageName);
+
+ for (ClassPath.ClassInfo clazz : checkstyleClasses) {
+ final Class> loadedClass = clazz.load();
+ if (isCheckstyleModule(loadedClass)) {
+ checkstyleModules.add(loadedClass);
+ }
+ }
return checkstyleModules;
+ } /**
+ * Checks whether a class may be considered as a checkstyle module. Checkstyle's modules are
+ * non-abstract classes, which names do not start with the word 'Input' (are not input files for
+ * UTs), and are either checkstyle's checks, file sets, filters, file filters, or root module.
+ * @param loadedClass class to check.
+ * @return true if the class may be considered as the checkstyle module.
+ */
+ private static boolean isCheckstyleModule(Class> loadedClass) {
+ final String className = loadedClass.getSimpleName();
+ return isValidCheckstyleClass(loadedClass, className)
+ && (isCheckstyleCheck(loadedClass)
+ || isFileSetModule(loadedClass)
+ || isFilterModule(loadedClass));
+ }
+
+ /**
+ * Checks whether a class extends 'AutomaticBean', is non-abstract, and doesn't start with the
+ * word 'Input' (are not input files for UTs).
+ * @param loadedClass class to check.
+ * @param className class name to check.
+ * @return true if a class may be considered a valid production class.
+ */
+ public static boolean isValidCheckstyleClass(Class> loadedClass, String className) {
+ return AutomaticBean.class.isAssignableFrom(loadedClass)
+ && !Modifier.isAbstract(loadedClass.getModifiers())
+ && !className.contains("Input");
+ }
+
+ /**
+ * Checks whether a class may be considered as the checkstyle check.
+ * Checkstyle's checks are classes which implement 'AbstractCheck' interface.
+ * @param loadedClass class to check.
+ * @return true if a class may be considered as the checkstyle check.
+ */
+ public static boolean isCheckstyleCheck(Class> loadedClass) {
+ return AbstractCheck.class.isAssignableFrom(loadedClass);
+ }
+
+ /**
+ * Checks whether a class may be considered as the checkstyle file set.
+ * Checkstyle's file sets are classes which implement 'AbstractFileSetCheck' interface.
+ * @param loadedClass class to check.
+ * @return true if a class may be considered as the checkstyle file set.
+ */
+ public static boolean isFileSetModule(Class> loadedClass) {
+ return AbstractFileSetCheck.class.isAssignableFrom(loadedClass);
+ }
+
+ /**
+ * Checks whether a class may be considered as the checkstyle filter.
+ * Checkstyle's filters are classes which implement 'Filter' interface.
+ * @param loadedClass class to check.
+ * @return true if a class may be considered as the checkstyle filter.
+ */
+ public static boolean isFilterModule(Class> loadedClass) {
+ return Filter.class.isAssignableFrom(loadedClass);
}
/**
diff --git a/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/ChecksTest.java b/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/ChecksTest.java
index e649d7f1..7863ff8e 100644
--- a/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/ChecksTest.java
+++ b/checkstyle-sonar-plugin/src/test/java/org/sonar/plugins/checkstyle/internal/ChecksTest.java
@@ -33,13 +33,13 @@
import org.apache.commons.beanutils.PropertyUtils;
import org.junit.Assert;
-import org.junit.Ignore;
import org.junit.Test;
import org.w3c.dom.Document;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
+import com.puppycrawl.tools.checkstyle.TreeWalker;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.checks.javadoc.AbstractJavadocCheck;
@@ -65,7 +65,6 @@ public final class ChecksTest {
);
@SuppressWarnings("static-method")
- @Ignore
@Test
public void verifyTestConfigurationFiles() throws Exception {
final Set> modules = CheckUtil.getCheckstyleModules();
@@ -95,6 +94,10 @@ private static void validateSonarFile(Document document, Set> modules)
final String key = rule.getAttributes().getNamedItem("key").getTextContent();
final Class> module = findModule(modules, key);
+
+ if (CheckUtil.isFilterModule(module))
+ Assert.fail("Module should not be in sonar rules: " + module.getCanonicalName());
+
modules.remove(module);
Assert.assertNotNull("Unknown class found in sonar: " + key, module);
@@ -114,7 +117,7 @@ private static void validateSonarFile(Document document, Set> modules)
expectedConfigKey = "Checker/TreeWalker/" + moduleSimpleName.replaceAll("Check$", "");
}
else {
- expectedConfigKey = "Checker/" + moduleSimpleName.replaceAll("Check$", "");;
+ expectedConfigKey = "Checker/" + moduleSimpleName.replaceAll("Check$", "");
}
Assert.assertNotNull(moduleName + " requires a configKey in sonar", configKey);
@@ -125,7 +128,8 @@ private static void validateSonarFile(Document document, Set> modules)
}
for (Class> module : modules) {
- Assert.fail("Module not found in sonar: " + module.getCanonicalName());
+ if (!CheckUtil.isFilterModule(module) && module != TreeWalker.class)
+ Assert.fail("Module not found in sonar: " + module.getCanonicalName());
}
}