Skip to content

Commit

Permalink
Issue checkstyle#5879: Suppression xpath single filter
Browse files Browse the repository at this point in the history
  • Loading branch information
tsunghanjacktsai committed Nov 27, 2018
1 parent 7ea6a08 commit a450c60
Show file tree
Hide file tree
Showing 8 changed files with 281 additions and 0 deletions.
1 change: 1 addition & 0 deletions .ci/jsoref-spellchecker/whitelist.words
Expand Up @@ -1182,6 +1182,7 @@ suppressionfilter
suppressionsloader
suppressionsstringprinter
suppressionxpathfilter
suppressionxpathsinglefilter
suppresswarnings
suppresswarningsfilter
suppresswarningsholder
Expand Down
5 changes: 5 additions & 0 deletions config/checkstyle_checks.xml
Expand Up @@ -350,6 +350,11 @@
<module name="SuppressionXpathFilter">
<property name="file" value="${checkstyle.suppressions-xpath.file}"/>
</module>
<module name="SuppressionXpathSingleFilter">
<property name="files" value=".*"/>
<property name="checks" value=".*"/>
<property name="message" value=".*"/>
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat"
value="-@cs\[(\w{8,}(\|\w{8,})*)\] \w[\(\)\-\.\'\`\,\:\;\w ]{10,}"/>
Expand Down
Expand Up @@ -850,6 +850,8 @@ private static void fillModulesFromFiltersPackage() {
BASE_PACKAGE + ".filters.SuppressionFilter");
NAME_TO_FULL_MODULE_NAME.put("SuppressionXpathFilter",
BASE_PACKAGE + ".filters.SuppressionXpathFilter");
NAME_TO_FULL_MODULE_NAME.put("SuppressionXpathSingleFilter",
BASE_PACKAGE + ".filters.SuppressionXpathSingleFilter");
NAME_TO_FULL_MODULE_NAME.put("SuppressWarningsFilter",
BASE_PACKAGE + ".filters.SuppressWarningsFilter");
NAME_TO_FULL_MODULE_NAME.put("SuppressWithNearbyCommentFilter",
Expand Down
@@ -0,0 +1,71 @@
package com.puppycrawl.tools.checkstyle.filters;

import java.util.regex.Pattern;

import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
import com.puppycrawl.tools.checkstyle.TreeWalkerFilter;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;

/**
* This filter processes {@link TreeWalkerAuditEvent}
* objects based on the criteria of files, checks, message, module id, xpathQuery.
*/
public class SuppressionXpathSingleFilter extends AutomaticBean implements
TreeWalkerFilter {
/**
* Default check format to suppress. By default the filter suppress all checks.
*/
private static final String DEFAULT_CHECK_FORMAT = ".*";
/**
* The pattern for file names.
*/
private Pattern files = Pattern.compile(DEFAULT_CHECK_FORMAT);
/**
* The pattern for check class names.
*/
private Pattern checks = Pattern.compile(DEFAULT_CHECK_FORMAT);
/**
* The pattern for message names.
*/
private Pattern message = Pattern.compile(DEFAULT_CHECK_FORMAT);
/**
* Module id filter.
*/
private String id;
/**
* Xpath query.
*/
private String query;

public void setFiles(String files) {
this.files = Pattern.compile(files);
}

public void setChecks(String checks) {
this.checks = Pattern.compile(checks);
}

public void setMessage(String message) {
this.message = Pattern.compile(message);
}

public void setId(String id) {
this.id = id;
}

public void setQuery(String query) {
this.query = query;
}

@Override
public boolean accept(TreeWalkerAuditEvent treeWalkerAuditEvent) {
XpathFilter xpathFilter = new XpathFilter(files, checks, message, id, query);
return xpathFilter.accept(treeWalkerAuditEvent);
}

@Override
protected void finishLocalSetup() throws CheckstyleException {
// No code by default
}
}
Expand Up @@ -115,6 +115,45 @@ public XpathFilter(String files, String checks,
}
}

public XpathFilter(Pattern files, Pattern checks,
Pattern message, String moduleId, String query) {
filePattern = files.pattern();
if (files == null) {
fileRegexp = null;
}
else {
fileRegexp = files;
}
checkPattern = checks.pattern();
if (checks == null) {
checkRegexp = null;
}
else {
checkRegexp = checks;
}
messagePattern = message.pattern();
if (message == null) {
messageRegexp = null;
}
else {
messageRegexp = message;
}
this.moduleId = moduleId;
xpathQuery = query;
if (xpathQuery == null) {
xpathExpression = null;
}
else {
final XPathEvaluator xpathEvaluator = new XPathEvaluator();
try {
xpathExpression = xpathEvaluator.createExpression(xpathQuery);
}
catch (XPathException ex) {
throw new IllegalStateException("Unexpected xpath query: " + xpathQuery, ex);
}
}
}

@Override
public boolean accept(TreeWalkerAuditEvent event) {
return !isFileNameAndModuleAndCheckNameMatching(event)
Expand Down
@@ -0,0 +1,74 @@
package com.puppycrawl.tools.checkstyle.filters;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.File;
import java.nio.charset.StandardCharsets;

import com.puppycrawl.tools.checkstyle.AbstractModuleTestSupport;
import com.puppycrawl.tools.checkstyle.JavaParser;
import com.puppycrawl.tools.checkstyle.TreeWalkerAuditEvent;
import com.puppycrawl.tools.checkstyle.api.*;
import org.junit.Before;
import org.junit.Test;

public class SuppressionXpathSingleFilterTest
extends AbstractModuleTestSupport {
private File file;
private FileContents fileContents;

@Before
public void setUp() throws Exception {
file = new File(getPath("InputSuppressionXpathSingleFilter.java"));
fileContents = new FileContents(new FileText(file,
StandardCharsets.UTF_8.name()));
}

@Override
protected String getPackageLocation() {
return "com/puppycrawl/tools/checkstyle/filters/suppressionxpathsinglefilter";
}

@Test
public void testDefault() throws Exception {
final String xpath = "/CLASS_DEF[@text='InputTest']" +
"//METHOD_DEF[@text='changeAge']//ASSIGN[@text='age']/IDENT";
final SuppressionXpathSingleFilter filter = createSuppressionXpathSingleFilter(
"InputSuppressionXpathSingleFilter", ".*", ".*", null, null);
final TreeWalkerAuditEvent ev = getEvent(3, 8, TokenTypes.VARIABLE_DEF);
assertFalse("Event should be rejected", filter.accept(ev));
}

@Test
public void testRequireThis() throws Exception {
final String xpath = "/CLASS_DEF[@text='InputTest']" +
"//METHOD_DEF[@text='changeAge']//ASSIGN[@text='age']/IDENT";
final SuppressionXpathSingleFilter filter = createSuppressionXpathSingleFilter(
"InputSuppressionXpathSingleFilter", "RequireThis", ".*", null, xpath);
final TreeWalkerAuditEvent ev = getEvent(3, 8, TokenTypes.VARIABLE_DEF);
assertTrue("Event should be accepted", filter.accept(ev));
}

private static SuppressionXpathSingleFilter createSuppressionXpathSingleFilter(
String files, String checks, String message, String id, String query)
throws CheckstyleException {
final SuppressionXpathSingleFilter filter = new SuppressionXpathSingleFilter();
filter.setFiles(files);
filter.setChecks(checks);
filter.setMessage(message);
filter.setId(id);
filter.setQuery(query);
filter.finishLocalSetup();
return filter;
}

private TreeWalkerAuditEvent getEvent(int line, int column, int tokenType)
throws Exception {
final LocalizedMessage message =
new LocalizedMessage(line, column, tokenType, "", "", null, null, null,
getClass(), null);
return new TreeWalkerAuditEvent(fileContents, file.getName(), message,
JavaParser.parseFile(file, JavaParser.Options.WITHOUT_COMMENTS));
}
}
@@ -0,0 +1,9 @@
package com.puppycrawl.tools.checkstyle.filters.suppressionxpathsinglefilter;

public class InputSuppressionXpathSingleFilter {
private int age = 23;

public void changeAge() {
age = 24;
}
}
80 changes: 80 additions & 0 deletions src/xdocs/config_filters.xml
Expand Up @@ -985,6 +985,86 @@ public class InputTest {
</subsection>
</section>

<section name="SuppressionXpathSingleFilter">
<subsection name="Description" id="SuppressionXpathSingleFilter_Description">
<p>Since Checkstyle 8.15</p>
</subsection>
<subsection name="Properties" id="SuppressionXpathSingleFilter_Properties">
<table>
<tr>
<th>name</th>
<th>description</th>
<th>type</th>
<th>default value</th>
<th>since</th>
</tr>
<tr>
<td>files</td>
<td>a Regular Expression matched against the file name associated
with an audit event. It is optional.</td>
<td><a href="property_types.html#regexp">Regular Expression</a></td>
<td><code>".*"</code></td>
<td>8.15</td>
</tr>
<tr>
<td>checks</td>
<td>a Regular Expression matched against the name of the check
associated with an audit event. Optional as long as id or message
is specified.</td>
<td><a href="property_types.html#regexp">Regular Expression</a></td>
<td><code>".*"</code></td>
<td>8.15</td>
</tr>
<tr>
<td>message</td>
<td>a Regular Expression matched against the message of the check associated
with an audit event. Optional as long as checks or id is specified.</td>
<td><a href="property_types.html#regexp">Regular Expression</a></td>
<td><code>".*"</code></td>
<td>8.15</td>
</tr>
<tr>
<td>id</td>
<td>a string matched against the ID of the check associated with an audit event.
Optional as long as checks or message is specified.</td>
<td><a href="property_types.html#string">String</a></td>
<td><code>null</code></td>
<td>8.15</td>
</tr>
<tr>
<td>query</td>
<td>a string xpath query. It is optional.</td>
<td><a href="property_types.html#string">String</a></td>
<td><code>null</code></td>
<td>8.15</td>
</tr>
</table>
</subsection>
<subsection name="Examples" id="SuppressionXpathSingleFilter_Examples">
<p>
The following suppressions XML document directs a SuppressionXpathFilter to
reject CyclomaticComplexity errors for all methods with name sayHelloWorld
inside FileOne classes:
</p>
<pre>
</pre>
</subsection>
<subsection name="Example of Usage" id="SuppressionXpathSingleFilter_Example_of_Usage">
<ul>
<li>
<a href="https://github.com/search?q=path%3Aconfig+filename%3Acheckstyle_checks.xml+repo%3Acheckstyle%2Fcheckstyle+SuppressionXpathSingleFilter">
Checkstyle Style</a>
</li>
</ul>
</subsection>
<subsection name="Package" id="SuppressionXpathSingleFilter_Package">
<p> com.puppycrawl.tools.checkstyle.filters </p>
</subsection>
<subsection name="Parent Module" id="SuppressionXpathSingleFilter_Parent_Module">
<p> <a href="config.html#TreeWalker">TreeWalker</a> </p>
</subsection>
</section>

<section name="SuppressWarningsFilter">
<subsection name="Description" id="SuppressWarningsFilter_Description">
<p>Since Checkstyle 5.7</p>
Expand Down

0 comments on commit a450c60

Please sign in to comment.