Issue #3667: fixed documentation and tests for checkstyle modules

This commit is contained in:
rnveach 2016-12-18 22:50:45 -05:00 committed by Roman Ivanov
parent bbfe5a1b69
commit ce54507376
5 changed files with 149 additions and 202 deletions

View File

@ -1,103 +0,0 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2016 the original author or authors.
//
// 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.grammars.comments;
import org.junit.Assert;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
class CompareTreesWithComments extends AbstractCheck {
private static DetailAST expectedTree;
@Override
public boolean isCommentNodesRequired() {
return true;
}
@Override
public int[] getDefaultTokens() {
return CommonUtils.EMPTY_INT_ARRAY;
}
@Override
public int[] getAcceptableTokens() {
return CommonUtils.EMPTY_INT_ARRAY;
}
@Override
public int[] getRequiredTokens() {
return CommonUtils.EMPTY_INT_ARRAY;
}
@Override
public void beginTree(DetailAST rootAST) {
if (!isAstEquals(expectedTree, rootAST)) {
Assert.assertEquals(expectedTree, rootAST);
}
}
private static boolean isAstEquals(DetailAST expected, DetailAST actual) {
final boolean result;
if (expected == actual) {
result = true;
}
else if (actual == null || expected == null) {
result = false;
}
else {
result = isAstEqualsSafe(expected, actual);
}
return result;
}
private static boolean isAstEqualsSafe(DetailAST expected, DetailAST actual) {
boolean result = false;
if (expected.getType() == actual.getType()
&& expected.getLineNo() == actual.getLineNo()
&& expected.getColumnNo() == actual.getColumnNo()) {
if (expected.getText() == null) {
result = actual.getText() == null;
}
else if (expected.getText().equals(actual.getText())) {
result = true;
}
}
if (result) {
final DetailAST childExpected = expected.getFirstChild();
final DetailAST childActual = actual.getFirstChild();
result = isAstEquals(childExpected, childActual);
if (result) {
final DetailAST nextSiblingExpected = expected.getNextSibling();
final DetailAST nextSiblingActual = actual.getNextSibling();
result = isAstEquals(nextSiblingExpected, nextSiblingActual);
}
}
return result;
}
public static void setExpectedTree(DetailAST expectedTree) {
CompareTreesWithComments.expectedTree = expectedTree;
}
}

View File

@ -147,11 +147,11 @@ public class AllChecksTest extends BaseCheckTestSupport {
}
@Test
public void testAllChecksAreReferencedInConfigFile() throws Exception {
final Set<String> checksReferencedInConfig = CheckUtil.getConfigCheckStyleChecks();
final Set<String> checksNames = getSimpleNames(CheckUtil.getCheckstyleChecks());
public void testAllModulesAreReferencedInConfigFile() throws Exception {
final Set<String> modulesReferencedInConfig = CheckUtil.getConfigCheckStyleModules();
final Set<String> moduleNames = getSimpleNames(CheckUtil.getCheckstyleModules());
checksNames.stream().filter(check -> !checksReferencedInConfig.contains(check))
moduleNames.stream().filter(check -> !modulesReferencedInConfig.contains(check))
.forEach(check -> {
final String errorMessage = String.format(Locale.ROOT,
"%s is not referenced in checkstyle_checks.xml", check);
@ -164,6 +164,10 @@ public class AllChecksTest extends BaseCheckTestSupport {
final Set<String> checkstyleModulesNames = getSimpleNames(CheckUtil.getCheckstyleModules());
final Set<String> modulesNamesWhichHaveXdocs = XDocUtil.getModulesNamesWhichHaveXdoc();
// these are documented on non-'config_' pages
checkstyleModulesNames.remove("TreeWalker");
checkstyleModulesNames.remove("Checker");
checkstyleModulesNames.stream()
.filter(moduleName -> !modulesNamesWhichHaveXdocs.contains(moduleName))
.forEach(moduleName -> {
@ -176,7 +180,7 @@ public class AllChecksTest extends BaseCheckTestSupport {
@Test
public void testAllCheckstyleModulesInCheckstyleConfig() throws Exception {
final Set<String> configChecks = CheckUtil.getConfigCheckStyleChecks();
final Set<String> configChecks = CheckUtil.getConfigCheckStyleModules();
for (String moduleName : getSimpleNames(CheckUtil.getCheckstyleModules())) {
Assert.assertTrue("checkstyle_checks.xml is missing module: " + moduleName,
@ -185,11 +189,20 @@ public class AllChecksTest extends BaseCheckTestSupport {
}
@Test
public void testAllCheckstyleModulesHaveMessage() throws Exception {
public void testAllCheckstyleChecksHaveMessage() throws Exception {
for (Class<?> module : CheckUtil.getCheckstyleChecks()) {
Assert.assertFalse(module.getSimpleName()
+ " should have atleast one 'MSG_*' field for error messages", CheckUtil
.getCheckMessages(module).isEmpty());
final String name = module.getSimpleName();
if ("FileContentsHolder".equals(name)) {
Assert.assertTrue(name
+ " should not have any 'MSG_*' field for error messages", CheckUtil
.getCheckMessages(module).isEmpty());
}
else {
Assert.assertFalse(name
+ " should have atleast one 'MSG_*' field for error messages", CheckUtil
.getCheckMessages(module).isEmpty());
}
}
}
@ -197,7 +210,7 @@ public class AllChecksTest extends BaseCheckTestSupport {
public void testAllCheckstyleMessages() throws Exception {
final Map<String, List<String>> usedMessages = new TreeMap<>();
// test validity of messages from checks
// test validity of messages from modules
for (Class<?> module : CheckUtil.getCheckstyleModules()) {
for (Field message : CheckUtil.getCheckMessages(module)) {
Assert.assertEquals(module.getSimpleName() + "." + message.getName()
@ -288,12 +301,20 @@ public class AllChecksTest extends BaseCheckTestSupport {
}
/**
* Removes 'Check' suffix from each class name in the set.
* Retrieves a list of class names, removing 'Check' from the end if the class is
* a checkstyle check.
* @param checks class instances.
* @return a set of simple names.
*/
private static Set<String> getSimpleNames(Set<Class<?>> checks) {
return checks.stream().map(check -> check.getSimpleName().replace("Check", ""))
.collect(Collectors.toSet());
return checks.stream().map(check -> {
String name = check.getSimpleName();
if (name.endsWith("Check")) {
name = name.substring(0, name.length() - 5);
}
return name;
}).collect(Collectors.toSet());
}
}

View File

@ -40,9 +40,12 @@ import org.w3c.dom.NodeList;
import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
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.BeforeExecutionFileFilter;
import com.puppycrawl.tools.checkstyle.api.Filter;
import com.puppycrawl.tools.checkstyle.api.RootModule;
import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpMultilineCheck;
import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineCheck;
import com.puppycrawl.tools.checkstyle.checks.regexp.RegexpSinglelineJavaCheck;
@ -53,16 +56,16 @@ public final class CheckUtil {
private CheckUtil() {
}
public static Set<String> getConfigCheckStyleChecks() {
return getCheckStyleChecksReferencedInConfig("config/checkstyle_checks.xml");
public static Set<String> getConfigCheckStyleModules() {
return getCheckStyleModulesReferencedInConfig("config/checkstyle_checks.xml");
}
public static Set<String> getConfigSunStyleChecks() {
return getCheckStyleChecksReferencedInConfig("src/main/resources/sun_checks.xml");
public static Set<String> getConfigSunStyleModules() {
return getCheckStyleModulesReferencedInConfig("src/main/resources/sun_checks.xml");
}
public static Set<String> getConfigGoogleStyleChecks() {
return getCheckStyleChecksReferencedInConfig("src/main/resources/google_checks.xml");
public static Set<String> getConfigGoogleStyleModules() {
return getCheckStyleModulesReferencedInConfig("src/main/resources/google_checks.xml");
}
/**
@ -72,7 +75,7 @@ public final class CheckUtil {
* file path of checkstyle_checks.xml.
* @return names of checkstyle's checks which are referenced in checkstyle_checks.xml.
*/
private static Set<String> getCheckStyleChecksReferencedInConfig(String configFilePath) {
private static Set<String> getCheckStyleModulesReferencedInConfig(String configFilePath) {
try {
final DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
@ -104,9 +107,7 @@ public final class CheckUtil {
if (currentNode.getNodeType() == Node.ELEMENT_NODE) {
final Element module = (Element) currentNode;
final String checkName = module.getAttribute("name");
if (!"Checker".equals(checkName) && !"TreeWalker".equals(checkName)) {
checksReferencedInCheckstyleChecksXml.add(checkName);
}
checksReferencedInCheckstyleChecksXml.add(checkName);
}
}
return checksReferencedInCheckstyleChecksXml;
@ -117,9 +118,11 @@ public final class CheckUtil {
}
/**
* Gets the checkstyle's non abstract checks.
* @return the set of checkstyle's non abstract check classes.
* Gets all checkstyle's non-abstract checks.
* @return the set of checkstyle's non-abstract check classes.
* @throws IOException if the attempt to read class path resources failed.
* @see #isValidCheckstyleClass(Class, String)
* @see #isCheckstyleCheck(Class)
*/
public static Set<Class<?>> getCheckstyleChecks() throws IOException {
final Set<Class<?>> checkstyleChecks = new HashSet<>();
@ -134,7 +137,8 @@ public final class CheckUtil {
for (ClassPath.ClassInfo clazz : checkstyleClasses) {
final String className = clazz.getSimpleName();
final Class<?> loadedClass = clazz.load();
if (isCheckstyleNonAbstractCheck(loadedClass, className)) {
if (isValidCheckstyleClass(loadedClass, className)
&& isCheckstyleCheck(loadedClass)) {
checkstyleChecks.add(loadedClass);
}
}
@ -142,12 +146,10 @@ public final class 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<Class<?>> getCheckstyleModules() throws IOException {
final Set<Class<?>> checkstyleModules = new HashSet<>();
@ -169,62 +171,83 @@ public final class CheckUtil {
}
/**
* Checks whether a class may be considered as the checkstyle check.
* Checkstyle's checks are nonabstract classes which names end with 'Check',
* do not contain 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 as the checkstyle check.
*/
private static boolean isCheckstyleNonAbstractCheck(Class<?> loadedClass, String className) {
return !Modifier.isAbstract(loadedClass.getModifiers())
&& className.endsWith("Check")
&& !className.contains("Input");
}
/**
* Checks whether a class may be considered as the checkstyle module.
* Checkstyle's modules are nonabstract classes which names end with 'Check',
* do not contain the word 'Input' (are not input files for UTs),
* checkstyle's filters, checkstyle's file filters and SuppressWarningsHolder class.
* 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 isCheckstyleNonAbstractCheck(loadedClass, className)
|| isFilterModule(loadedClass, className)
|| isFileFilterModule(loadedClass, className)
|| "SuppressWarningsHolder".equals(className)
|| "FileContentsHolder".equals(className);
return isValidCheckstyleClass(loadedClass, className)
&& (isCheckstyleCheck(loadedClass)
|| isFileSetModule(loadedClass)
|| isFilterModule(loadedClass)
|| isFileFilterModule(loadedClass)
|| isRootModule(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 are subclasses of AutomaticBean,
* implement 'Filter' interface, and which names end with 'Filter'.
* Checkstyle's filters are classes which implement 'Filter' interface.
* @param loadedClass class to check.
* @param className class name to check.
* @return true if a class may be considered as the checkstyle filter.
*/
private static boolean isFilterModule(Class<?> loadedClass, String className) {
return Filter.class.isAssignableFrom(loadedClass)
&& AutomaticBean.class.isAssignableFrom(loadedClass)
&& className.endsWith("Filter");
public static boolean isFilterModule(Class<?> loadedClass) {
return Filter.class.isAssignableFrom(loadedClass);
}
/**
* Checks whether a class may be considered as the checkstyle file filter.
* Checkstyle's file filters are classes which are subclasses of AutomaticBean,
* implement 'BeforeExecutionFileFilter' interface, and which names end with 'FileFilter'.
* Checkstyle's file filters are classes which implement 'BeforeExecutionFileFilter' interface.
* @param loadedClass class to check.
* @param className class name to check.
* @return true if a class may be considered as the checkstyle file filter.
*/
private static boolean isFileFilterModule(Class<?> loadedClass, String className) {
return BeforeExecutionFileFilter.class.isAssignableFrom(loadedClass)
&& AutomaticBean.class.isAssignableFrom(loadedClass)
&& className.endsWith("FileFilter");
public static boolean isFileFilterModule(Class<?> loadedClass) {
return BeforeExecutionFileFilter.class.isAssignableFrom(loadedClass);
}
/**
* Checks whether a class may be considered as the checkstyle root module.
* Checkstyle's root modules are classes which implement 'RootModule' interface.
* @param loadedClass class to check.
* @return true if a class may be considered as the checkstyle root module.
*/
public static boolean isRootModule(Class<?> loadedClass) {
return RootModule.class.isAssignableFrom(loadedClass);
}
/**

View File

@ -73,7 +73,7 @@ public class XDocsPagesTest {
private static final String LINK_TEMPLATE =
"(?s).*<a href=\"config_\\w+\\.html#%1$s\">%1$s</a>.*";
private static final List<String> CHECKS_ON_PAGE_IGNORE_LIST = Arrays.asList(
private static final List<String> MODULES_ON_PAGE_IGNORE_LIST = Arrays.asList(
"AbstractAccessControlNameCheck.java",
"AbstractCheck.java",
"AbstractClassCouplingCheck.java",
@ -134,10 +134,10 @@ public class XDocsPagesTest {
"SuppressionCommentFilter.fileContents"
);
private static final Set<String> SUN_CHECKS = Collections.unmodifiableSet(
new HashSet<>(CheckUtil.getConfigSunStyleChecks()));
private static final Set<String> GOOGLE_CHECKS = Collections.unmodifiableSet(
new HashSet<>(CheckUtil.getConfigGoogleStyleChecks()));
private static final Set<String> SUN_MODULES = Collections.unmodifiableSet(
new HashSet<>(CheckUtil.getConfigSunStyleModules()));
private static final Set<String> GOOGLE_MODULES = Collections.unmodifiableSet(
new HashSet<>(CheckUtil.getConfigGoogleStyleModules()));
@Test
public void testAllChecksPresentOnAvailableChecksPage() throws IOException {
@ -145,7 +145,7 @@ public class XDocsPagesTest {
Files.walk(JAVA_SOURCES_DIRECTORY).forEach(filePath -> {
final String fileName = filePath.getFileName().toString();
if (fileName.matches(CHECK_FILE_NAME)
&& !CHECKS_ON_PAGE_IGNORE_LIST.contains(fileName)) {
&& !MODULES_ON_PAGE_IGNORE_LIST.contains(fileName)) {
final String checkName = fileName.replace(CHECK_SUFFIX, "");
if (!isPresent(availableChecks, checkName)) {
Assert.fail(checkName + " is not correctly listed on Available Checks page"
@ -557,8 +557,8 @@ public class XDocsPagesTest {
propertyName);
final Class<?> clss = descriptor.getPropertyType();
final String expectedTypeName =
getCheckPropertyExpectedTypeName(clss, instance, propertyName);
final String expectedValue = getCheckPropertyExpectedValue(clss, instance,
getModulePropertyExpectedTypeName(clss, instance, propertyName);
final String expectedValue = getModulePropertyExpectedValue(clss, instance,
propertyName);
if (expectedTypeName != null) {
@ -613,7 +613,7 @@ public class XDocsPagesTest {
}
/** @noinspection IfStatementWithTooManyBranches */
private static String getCheckPropertyExpectedTypeName(Class<?> clss, Object instance,
private static String getModulePropertyExpectedTypeName(Class<?> clss, Object instance,
String propertyName) {
final String instanceName = instance.getClass().getSimpleName();
String result = null;
@ -665,7 +665,7 @@ public class XDocsPagesTest {
return result;
}
private static String getCheckPropertyExpectedValue(Class<?> clss, Object instance,
private static String getModulePropertyExpectedValue(Class<?> clss, Object instance,
String propertyName) throws Exception {
final Field field = getField(instance.getClass(), propertyName);
String result = null;
@ -829,7 +829,7 @@ public class XDocsPagesTest {
Assert.assertTrue(fileName + " section '" + sectionName
+ "' should be in google_checks.xml or not reference 'Google Style'",
GOOGLE_CHECKS.contains(sectionName));
GOOGLE_MODULES.contains(sectionName));
}
else if ("Sun Style".equals(linkText)) {
hasSun = true;
@ -840,7 +840,7 @@ public class XDocsPagesTest {
Assert.assertTrue(fileName + " section '" + sectionName
+ "' should be in sun_checks.xml or not reference 'Sun Style'",
SUN_CHECKS.contains(sectionName));
SUN_MODULES.contains(sectionName));
}
Assert.assertEquals(fileName + " section '" + sectionName
@ -851,10 +851,10 @@ public class XDocsPagesTest {
+ "' should have a checkstyle section", hasCheckstyle);
Assert.assertTrue(fileName + " section '" + sectionName
+ "' should have a google section since it is in it's config", hasGoogle
|| !GOOGLE_CHECKS.contains(sectionName));
|| !GOOGLE_MODULES.contains(sectionName));
Assert.assertTrue(fileName + " section '" + sectionName
+ "' should have a sun section since it is in it's config",
hasSun || !SUN_CHECKS.contains(sectionName));
hasSun || !SUN_MODULES.contains(sectionName));
}
private static void validatePackageSection(String fileName, String sectionName,
@ -918,7 +918,7 @@ public class XDocsPagesTest {
Set<String> styleChecks = null;
if (path.toFile().getName().contains("google")) {
styleChecks = new HashSet<>(GOOGLE_CHECKS);
styleChecks = new HashSet<>(GOOGLE_MODULES);
}
else if (path.toFile().getName().contains("sun")) {
styleChecks = new HashSet<>();
@ -950,13 +950,17 @@ public class XDocsPagesTest {
fileName, ruleName);
}
validateStyleChecks(XmlUtil.findChildElementsByTag(columns.get(2), "a"),
validateStyleModules(XmlUtil.findChildElementsByTag(columns.get(2), "a"),
XmlUtil.findChildElementsByTag(columns.get(3), "a"), styleChecks, fileName,
ruleName);
lastRuleName = ruleName;
}
// these modules aren't documented, but are added to the config
styleChecks.remove("TreeWalker");
styleChecks.remove("Checker");
Assert.assertTrue(fileName + " requires the following check(s) to appear: "
+ styleChecks, styleChecks.isEmpty());
}
@ -995,24 +999,24 @@ public class XDocsPagesTest {
}
}
private static void validateStyleChecks(Set<Node> checks, Set<Node> configs,
private static void validateStyleModules(Set<Node> checks, Set<Node> configs,
Set<String> styleChecks, String fileName, String ruleName) {
final Iterator<Node> itrChecks = checks.iterator();
final Iterator<Node> itrConfigs = configs.iterator();
while (itrChecks.hasNext()) {
final Node check = itrChecks.next();
final String checkName = check.getTextContent().trim();
final Node module = itrChecks.next();
final String moduleName = module.getTextContent().trim();
if (!check.getAttributes().getNamedItem("href").getTextContent()
if (!module.getAttributes().getNamedItem("href").getTextContent()
.startsWith("config_")) {
continue;
}
Assert.assertTrue(fileName + " rule '" + ruleName + "' check '" + checkName
+ "' shouldn't end with 'Check'", !checkName.endsWith("Check"));
Assert.assertTrue(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' shouldn't end with 'Check'", !moduleName.endsWith("Check"));
styleChecks.remove(checkName);
styleChecks.remove(moduleName);
for (String configName : new String[] {"config", "test"}) {
Node config = null;
@ -1021,11 +1025,11 @@ public class XDocsPagesTest {
config = itrConfigs.next();
}
catch (NoSuchElementException ignore) {
Assert.fail(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.fail(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' is missing the config link: " + configName);
}
Assert.assertEquals(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.assertEquals(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' has mismatched config/test links", configName, config.getTextContent()
.trim());
@ -1035,22 +1039,22 @@ public class XDocsPagesTest {
if ("config".equals(configName)) {
final String expectedUrl = "https://github.com/search?q="
+ "path%3Asrc%2Fmain%2Fresources+filename%3Agoogle_checks.xml+"
+ "repo%3Acheckstyle%2Fcheckstyle+" + checkName;
+ "repo%3Acheckstyle%2Fcheckstyle+" + moduleName;
Assert.assertEquals(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.assertEquals(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' should have matching " + configName + " url", expectedUrl,
configUrl);
}
else if ("test".equals(configName)) {
Assert.assertTrue(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.assertTrue(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' should have matching " + configName + " url",
configUrl.startsWith("https://github.com/checkstyle/checkstyle/"
+ "blob/master/src/it/java/com/google/checkstyle/test/"));
Assert.assertTrue(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.assertTrue(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' should have matching " + configName + " url",
configUrl.endsWith("/" + checkName + "Test.java"));
configUrl.endsWith("/" + moduleName + "Test.java"));
Assert.assertTrue(fileName + " rule '" + ruleName + "' check '" + checkName
Assert.assertTrue(fileName + " rule '" + ruleName + "' module '" + moduleName
+ "' should have a test that exists", new File(configUrl.substring(53)
.replace('/', File.separatorChar)).exists());
}

View File

@ -274,6 +274,8 @@
files.</li>
<li><em>Filter</em> children: modules that filter audit
events.</li>
<li><em>FileFilter</em> children: modules that filter files
for Checkstyle to process.</li>
<li><em>AuditListener</em> children: modules that report
filtered events.</li>
</ul>