Issue #3462: Implement 'path' property for ImportControlCheck

This commit is contained in:
Jochen Van de Velde 2017-01-13 07:04:35 +01:00 committed by Roman Ivanov
parent 0cee0939c9
commit b57e4d3df6
3 changed files with 96 additions and 15 deletions

View File

@ -22,6 +22,7 @@ package com.puppycrawl.tools.checkstyle.checks.imports;
import java.net.URI;
import java.util.Collections;
import java.util.Set;
import java.util.regex.Pattern;
import org.apache.commons.beanutils.ConversionException;
@ -73,6 +74,11 @@ public class ImportControlCheck extends AbstractCheck implements ExternalResourc
/** Location of import control file. */
private String fileLocation;
/** The filepath pattern this check applies to. */
private Pattern path = Pattern.compile(".*");
/** Whether to process the current file. */
private boolean processCurrentFile;
/** The root package controller. */
private ImportControl root;
/** The package doing the import. */
@ -103,27 +109,31 @@ public class ImportControlCheck extends AbstractCheck implements ExternalResourc
@Override
public void beginTree(final DetailAST rootAST) {
currentImportControl = null;
processCurrentFile = path.matcher(getFileContents().getFileName()).find();
}
@Override
public void visitToken(final DetailAST ast) {
if (ast.getType() == TokenTypes.PACKAGE_DEF) {
if (root == null) {
log(ast, MSG_MISSING_FILE);
}
else {
packageName = getPackageText(ast);
currentImportControl = root.locateFinest(packageName);
if (currentImportControl == null) {
log(ast, MSG_UNKNOWN_PKG);
if (processCurrentFile) {
if (ast.getType() == TokenTypes.PACKAGE_DEF) {
if (root == null) {
log(ast, MSG_MISSING_FILE);
}
else {
packageName = getPackageText(ast);
currentImportControl = root.locateFinest(packageName);
if (currentImportControl == null) {
log(ast, MSG_UNKNOWN_PKG);
}
}
}
}
else if (currentImportControl != null) {
final String importText = getImportText(ast);
final AccessResult access = currentImportControl.checkAccess(packageName, importText);
if (access != AccessResult.ALLOWED) {
log(ast, MSG_DISALLOWED, importText);
else if (currentImportControl != null) {
final String importText = getImportText(ast);
final AccessResult access =
currentImportControl.checkAccess(packageName, importText);
if (access != AccessResult.ALLOWED) {
log(ast, MSG_DISALLOWED, importText);
}
}
}
}
@ -181,6 +191,14 @@ public class ImportControlCheck extends AbstractCheck implements ExternalResourc
}
}
/**
* Set the file path pattern that this check applies to.
* @param pattern the file path regex this check should apply to.
*/
public void setPath(Pattern pattern) {
path = pattern;
}
/**
* Set the parameter for the url containing the import control
* configuration. It will cause the url to be loaded.

View File

@ -356,6 +356,46 @@ public class ImportControlCheckTest extends BaseCheckTestSupport {
verify(checker, pathToEmptyFile, pathToEmptyFile, expected);
}
@Test
public void testPathRegexMatches() throws Exception {
final DefaultConfiguration checkConfig = createCheckConfig(ImportControlCheck.class);
checkConfig.addAttribute("file", getResourcePath("import-control_one.xml"));
checkConfig.addAttribute("path", "^.*[\\\\/]src[\\\\/]test[\\\\/].*$");
final String[] expected = {"5:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
verify(checkConfig, getPath("InputImportControl.java"), expected);
}
@Test
public void testPathRegexMatchesPartially() throws Exception {
final DefaultConfiguration checkConfig = createCheckConfig(ImportControlCheck.class);
checkConfig.addAttribute("file", getResourcePath("import-control_one.xml"));
checkConfig.addAttribute("path", "[\\\\/]InputImportControl\\.java");
final String[] expected = {"5:1: " + getCheckMessage(MSG_DISALLOWED, "java.io.File")};
verify(checkConfig, getPath("InputImportControl.java"), expected);
}
@Test
public void testPathRegexDoesntMatch() throws Exception {
final DefaultConfiguration checkConfig = createCheckConfig(ImportControlCheck.class);
checkConfig.addAttribute("file", getResourcePath("import-control_one.xml"));
checkConfig.addAttribute("path", "^.*[\\\\/]src[\\\\/]main[\\\\/].*$");
final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
verify(checkConfig, getPath("InputImportControl.java"), expected);
}
@Test
public void testPathRegexDoesntMatchPartially() throws Exception {
final DefaultConfiguration checkConfig = createCheckConfig(ImportControlCheck.class);
checkConfig.addAttribute("file", getResourcePath("import-control_one.xml"));
checkConfig.addAttribute("path", "[\\\\/]NoMatch\\.java");
final String[] expected = CommonUtils.EMPTY_STRING_ARRAY;
verify(checkConfig, getPath("InputImportControl.java"), expected);
}
private Checker createMockCheckerWithCache(DefaultConfiguration checkConfig)
throws IOException, CheckstyleException {
final DefaultConfiguration treeWalkerConfig = createCheckConfig(TreeWalker.class);

View File

@ -723,6 +723,16 @@ import android.*;
<td><a href="property_types.html#uri">URI</a></td>
<td><code>null</code></td>
</tr>
<tr>
<td>path</td>
<td>
Regular expression of file paths to which this check should apply. Files that
don't match the pattern will not be checked. The pattern will be matched against
the full absolute file path.
</td>
<td><a href="property_types.html#regexp">Regular Expression</a></td>
<td><code>".*"</code></td>
</tr>
</table>
</subsection>
@ -738,6 +748,19 @@ import android.*;
&lt;/module&gt;
</source>
<p>
To configure the check to only check the &quot;src/main&quot; directory
using an import control file called &quot;config/import-control.xml&quot;,
then have the following:
</p>
<source>
&lt;module name=&quot;ImportControl&quot;&gt;
&lt;property name=&quot;file&quot; value=&quot;config/import-control.xml&quot;/&gt;
&lt;property name=&quot;path&quot; value=&quot;^.*[\\/]src[\\/]main[\\/].*$&quot;/&gt;
&lt;/module&gt;
</source>
<p>
In the example below access to package
<code>com.puppycrawl.tools.checkstyle.checks</code> and its subpackages is