Skip to content

Commit

Permalink
Issue #4714: Make SuppressionCommentFilter and SuppressWithNearbyComm…
Browse files Browse the repository at this point in the history
…entFilter children of TreeWalker
  • Loading branch information
timurt committed Jul 20, 2017
1 parent 538e7a6 commit fbd55d0
Show file tree
Hide file tree
Showing 10 changed files with 260 additions and 66 deletions.
28 changes: 14 additions & 14 deletions config/checkstyle_checks.xml
Expand Up @@ -31,24 +31,10 @@
<property name="severity" value="ignore"/>
<property name="acceptOnMatch" value="false"/>
</module>
<module name="SuppressionCommentFilter">
<!--
Use suppressions.xml for suppressions, this is only example.
checkFormat will prevent suppression comments from being valid.
-->
<property name="checkFormat" value="IGNORETHIS"/>
<property name="offCommentFormat" value="CSOFF\: .*"/>
<property name="onCommentFormat" value="CSON\: .*"/>
</module>
<module name="SuppressionFilter">
<property name="file" value="${checkstyle.suppressions.file}"/>
</module>
<module name="SuppressWarningsFilter"/>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="-@cs\[(\w{8,}(\|\w{8,})*)\] \w[\(\)\-\.\'\`\,\:\;\w ]{10,}"/>
<property name="checkFormat" value="$1"/>
<property name="influenceFormat" value="3"/>
</module>

<!-- Headers -->
<module name="Header">
Expand Down Expand Up @@ -155,6 +141,20 @@
value="The warning ''{0}'' cannot be suppressed at this location. Only few javac warnings are allowed to suppress. If try to suppress checkstyle/pmd/..... violation please do this in their config file. If you try to suppress IntelliJ IDEA inspection, please use javadoc block tag @noinspection"
/>
</module>
<module name="SuppressionCommentFilter">
<!--
Use suppressions.xml for suppressions, this is only example.
checkFormat will prevent suppression comments from being valid.
-->
<property name="checkFormat" value="IGNORETHIS"/>
<property name="offCommentFormat" value="CSOFF\: .*"/>
<property name="onCommentFormat" value="CSON\: .*"/>
</module>
<module name="SuppressWithNearbyCommentFilter">
<property name="commentFormat" value="-@cs\[(\w{8,}(\|\w{8,})*)\] \w[\(\)\-\.\'\`\,\:\;\w ]{10,}"/>
<property name="checkFormat" value="$1"/>
<property name="influenceFormat" value="3"/>
</module>
<module name="SuppressWarningsHolder"/>

<!-- Block Checks -->
Expand Down
74 changes: 61 additions & 13 deletions src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java
Expand Up @@ -29,6 +29,8 @@
import java.util.Locale;
import java.util.Map.Entry;
import java.util.Set;
import java.util.SortedSet;
import java.util.TreeSet;

import antlr.CommonHiddenStreamToken;
import antlr.RecognitionException;
Expand All @@ -40,14 +42,18 @@
import com.google.common.collect.Multimap;
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
import com.puppycrawl.tools.checkstyle.api.AbstractFileSetCheck;
import com.puppycrawl.tools.checkstyle.api.AstFilter;
import com.puppycrawl.tools.checkstyle.api.AutomaticBean;
import com.puppycrawl.tools.checkstyle.api.CheckstyleException;
import com.puppycrawl.tools.checkstyle.api.Configuration;
import com.puppycrawl.tools.checkstyle.api.Context;
import com.puppycrawl.tools.checkstyle.api.DetailAST;
import com.puppycrawl.tools.checkstyle.api.ExternalResourceHolder;
import com.puppycrawl.tools.checkstyle.api.FileContents;
import com.puppycrawl.tools.checkstyle.api.FileText;
import com.puppycrawl.tools.checkstyle.api.LocalizedMessage;
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
import com.puppycrawl.tools.checkstyle.api.TreeWalkerAuditEvent;
import com.puppycrawl.tools.checkstyle.grammars.GeneratedJavaLexer;
import com.puppycrawl.tools.checkstyle.grammars.GeneratedJavaRecognizer;
import com.puppycrawl.tools.checkstyle.utils.CommonUtils;
Expand All @@ -59,6 +65,7 @@
*
* @author Oliver Burn
*/
// -@cs[ClassFanOutComplexity] Number of classes current class relies on exceeds 25.
public final class TreeWalker extends AbstractFileSetCheck implements ExternalResourceHolder {

/** Default distance between tab stops. */
Expand All @@ -78,6 +85,12 @@ public final class TreeWalker extends AbstractFileSetCheck implements ExternalRe
/** Registered comment checks. */
private final Set<AbstractCheck> commentChecks = new HashSet<>();

/** The ast filters. */
private final Set<AstFilter> filters = new HashSet<>();

/** The sorted set of messages. */
private final SortedSet<LocalizedMessage> messages = new TreeSet<>();

/** The distance between tab stops. */
private int tabWidth = DEFAULT_TAB_WIDTH;

Expand Down Expand Up @@ -149,18 +162,26 @@ public void setupChild(Configuration childConf)
throws CheckstyleException {
final String name = childConf.getName();
final Object module = moduleFactory.createModule(name);
if (!(module instanceof AbstractCheck)) {
if (module instanceof AbstractCheck || module instanceof AstFilter) {
final AutomaticBean bean = (AutomaticBean) module;
bean.contextualize(childContext);
bean.configure(childConf);
if (module instanceof AbstractCheck) {
final AbstractCheck check = (AbstractCheck) module;
check.init();
registerCheck(check);
}
else {
final AstFilter filter = (AstFilter) module;
filters.add(filter);
}
}
else {
throw new CheckstyleException(
"TreeWalker is not allowed as a parent of " + name
+ " Please review 'Parent Module' section for this Check in web"
+ " documentation if Check is standard.");
"TreeWalker is not allowed as a parent of " + name
+ " Please review 'Parent Module' section for this Check in web"
+ " documentation if Check is standard.");
}
final AbstractCheck check = (AbstractCheck) module;
check.contextualize(childContext);
check.configure(childConf);
check.init();

registerCheck(check);
}

@Override
Expand All @@ -169,21 +190,26 @@ protected void processFiltered(File file, FileText fileText) throws CheckstyleEx
if (CommonUtils.matchesFileExtension(file, getFileExtensions())) {
final String msg = "%s occurred during the analysis of file %s.";
final String fileName = file.getPath();
final FileContents contents = new FileContents(fileText);

try {
if (!ordinaryChecks.isEmpty()
|| !commentChecks.isEmpty()) {
final FileContents contents = new FileContents(fileText);
final DetailAST rootAST = parse(contents);

if (!ordinaryChecks.isEmpty()) {
walk(rootAST, contents, AstState.ORDINARY);
}
if (!commentChecks.isEmpty()) {
final DetailAST astWithComments = appendHiddenCommentNodes(rootAST);

walk(astWithComments, contents, AstState.WITH_COMMENTS);
}
}

final SortedSet<LocalizedMessage> filteredMessages = getFilteredMessages(fileName,
contents);
addMessages(filteredMessages);
messages.clear();
}
catch (final TokenStreamRecognitionException tre) {
final String exceptionMsg = String.format(Locale.ROOT, msg,
Expand All @@ -198,6 +224,28 @@ protected void processFiltered(File file, FileText fileText) throws CheckstyleEx
}
}

/**
* Returns filtered set of {@link LocalizedMessage}.
* @param fileName path to the file
* @param fileContents the contents of the file
* @return filtered set of messages
*/
private SortedSet<LocalizedMessage> getFilteredMessages(String fileName,
FileContents fileContents) {
final SortedSet<LocalizedMessage> result = new TreeSet<>(messages);
for (final LocalizedMessage element : messages) {
final TreeWalkerAuditEvent event = new TreeWalkerAuditEvent(fileContents, fileName,
element);
for (final AstFilter filter : filters) {
if (!filter.accept(event)) {
result.remove(element);
break;
}
}
}
return result;
}

/**
* Register a check for a given configuration.
* @param check the check to register
Expand Down Expand Up @@ -350,7 +398,7 @@ private void notifyEnd(DetailAST rootAST, AstState astState) {

for (AbstractCheck check : checks) {
check.finishTree(rootAST);
addMessages(check.getMessages());
messages.addAll(check.getMessages());
}
}

Expand Down
34 changes: 34 additions & 0 deletions src/main/java/com/puppycrawl/tools/checkstyle/api/AstFilter.java
@@ -0,0 +1,34 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 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.api;

/**
* An interface for filtering {@code TreeWalkerAuditEvent}.
*
* @author Timur Tibeyev.
*/
public interface AstFilter {
/**
* Determines whether or not a filtered {@code TreeWalkerAuditEvent} is accepted.
* @param auditEvent the AuditEvent to filter.
* @return true if the event is accepted.
*/
boolean accept(TreeWalkerAuditEvent auditEvent);
}
@@ -0,0 +1,115 @@
////////////////////////////////////////////////////////////////////////////////
// checkstyle: Checks Java source code for adherence to a set of rules.
// Copyright (C) 2001-2017 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.api;

/**
* Raw {@code TreeWalker} event for audit.
*
* @author Timur Tibeyev
*/
public class TreeWalkerAuditEvent {
/** Filename event associated with. **/
private final String fileName;
/** The file contents. */
private final FileContents fileContents;
/** Message associated with the event. **/
private final LocalizedMessage localizedMessage;

/**
* Creates a new {@code AuditEvent} instance.
*
* @param fileContents contents of the file associated with the event
* @param fileName file associated with the event
* @param localizedMessage the actual message
*/
public TreeWalkerAuditEvent(FileContents fileContents, String fileName,
LocalizedMessage localizedMessage) {
this.fileContents = fileContents;
this.fileName = fileName;
this.localizedMessage = localizedMessage;
}

/**
* Returns name of file being audited.
* @return the file name currently being audited or null if there is
* no relation to a file.
*/
public String getFileName() {
return fileName;
}

/**
* Returns contents of the file.
* @return contents of the file.
*/
public FileContents getFileContents() {
return fileContents;
}

/**
* Gets the localized message.
* @return the localized message
*/
public LocalizedMessage getLocalizedMessage() {
return localizedMessage;
}

/**
* Return the line number on the source file where the event occurred.
* This may be 0 if there is no relation to a file content.
* @return an integer representing the line number in the file source code.
*/
public int getLine() {
return localizedMessage.getLineNo();
}

/**
* Return the message associated to the event.
* @return the event message
*/
public String getMessage() {
return localizedMessage.getMessage();
}

/**
* Gets the column associated with the message.
* @return the column associated with the message
*/
public int getColumn() {
return localizedMessage.getColumnNo();
}

/**
* Returns id of module.
* @return the identifier of the module that generated the event. Can return
* null.
*/
public String getModuleId() {
return localizedMessage.getModuleId();
}

/**
* Gets the name of the source for the message.
* @return the name of the source for the message
*/
public String getSourceName() {
return localizedMessage.getSourceName();
}
}

0 comments on commit fbd55d0

Please sign in to comment.