Skip to content

Commit

Permalink
Issue #12542: new TreeWalker property to skip exceptions
Browse files Browse the repository at this point in the history
  • Loading branch information
Lmh-java committed Apr 14, 2024
1 parent 542db1d commit e84dc9c
Show file tree
Hide file tree
Showing 6 changed files with 122 additions and 15 deletions.
5 changes: 4 additions & 1 deletion config/ant-phase-verify.xml
Expand Up @@ -166,7 +166,8 @@
<exclude name="**/InputMainFrameModelIncorrectClass.java"/>
<exclude name="**/InputBeforeExecutionExclusionFileFilterIncorrectClass.java"/>
<exclude name="**/InputJavaParser.java"/>

<exclude name="**/InputTreeWalkerSkipParsingException.java"/>
<exclude name="**/InputTreeWalkerSkipParsingExceptionConfig.java"/>
</fileset>
</path>
<formatter type="plain"/>
Expand Down Expand Up @@ -203,6 +204,8 @@
<exclude name="**/InputMainFrameModelIncorrectClass.java"/>
<exclude name="**/InputBeforeExecutionExclusionFileFilterIncorrectClass.java"/>
<exclude name="**/InputJavaParser.java"/>
<exclude name="**/InputTreeWalkerSkipParsingException.java"/>
<exclude name="**/InputTreeWalkerSkipParsingExceptionConfig.java"/>
<!-- This check does not apply to grammar input files -->
<exclude name="**/grammar/**/*"/>
<!-- No need to check xpathmapper files -->
Expand Down
58 changes: 44 additions & 14 deletions src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java
Expand Up @@ -79,6 +79,9 @@ public final class TreeWalker extends AbstractFileSetCheck implements ExternalRe
/** A factory for creating submodules (i.e. the Checks) */
private ModuleFactory moduleFactory;

/** Control whether to skip files with Java parsing errors. */
private boolean skipFileOnJavaParseException;

/**
* Creates a new {@code TreeWalker} instance.
*/
Expand All @@ -95,6 +98,16 @@ public void setModuleFactory(ModuleFactory moduleFactory) {
this.moduleFactory = moduleFactory;
}

/**
* Setter to control whether to skip files with Java parsing errors.
*
* @param skipFileOnJavaParseException whether to always check for a trailing comma.
* @since 10.16.0
*/
public void setSkipFileOnJavaParseException(boolean skipFileOnJavaParseException) {
this.skipFileOnJavaParseException = skipFileOnJavaParseException;
}

@Override
public void finishLocalSetup() {
final DefaultContext checkContext = new DefaultContext();
Expand Down Expand Up @@ -149,23 +162,40 @@ protected void processFiltered(File file, FileText fileText) throws CheckstyleEx
// check if already checked and passed the file
if (!ordinaryChecks.isEmpty() || !commentChecks.isEmpty()) {
final FileContents contents = getFileContents();
final DetailAST rootAST = JavaParser.parse(contents);
if (!ordinaryChecks.isEmpty()) {
walk(rootAST, contents, AstState.ORDINARY);
}
if (!commentChecks.isEmpty()) {
final DetailAST astWithComments = JavaParser.appendHiddenCommentNodes(rootAST);
walk(astWithComments, contents, AstState.WITH_COMMENTS);
DetailAST rootAST = null;
// whether skip the procedure after parsing Java files.
boolean skip = false;

try {
rootAST = JavaParser.parse(contents);
}
if (filters.isEmpty()) {
addViolations(violations);
catch (CheckstyleException ex) {
if (skipFileOnJavaParseException) {
skip = true;
}
else {
throw ex;
}
}
else {
final SortedSet<Violation> filteredViolations =
getFilteredViolations(file.getAbsolutePath(), contents, rootAST);
addViolations(filteredViolations);

if (!skip) {
if (!ordinaryChecks.isEmpty()) {
walk(rootAST, contents, AstState.ORDINARY);
}
if (!commentChecks.isEmpty()) {
final DetailAST astWithComments = JavaParser.appendHiddenCommentNodes(rootAST);
walk(astWithComments, contents, AstState.WITH_COMMENTS);
}
if (filters.isEmpty()) {
addViolations(violations);
}
else {
final SortedSet<Violation> filteredViolations =
getFilteredViolations(file.getAbsolutePath(), contents, rootAST);
addViolations(filteredViolations);
}
violations.clear();
}
violations.clear();
}
}

Expand Down
53 changes: 53 additions & 0 deletions src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java
Expand Up @@ -35,8 +35,10 @@
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.regex.Matcher;
Expand Down Expand Up @@ -673,6 +675,57 @@ public void testOrderOfCheckExecution() throws Exception {
}
}

@Test
public void testSkipFileOnJavaParseExceptionTrue() throws Exception {
final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
config.addProperty("skipFileOnJavaParseException", "true");
config.addChild(createModuleConfig(ConstantNameCheck.class));

final File[] files = {
new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
new File(getPath("InputTreeWalkerProperFileExtension.java")),
new File(getNonCompilablePath("InputTreeWalkerSkipParsingException.java")),
};

final Checker checker = createChecker(config);
final Map<String, List<String>> expectedViolation = new HashMap<>();
expectedViolation.put(getPath("InputTreeWalkerProperFileExtension.java"),
Collections.singletonList(
"10:27: " + getCheckMessage(ConstantNameCheck.class,
MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$")));
verify(checker, files, expectedViolation);
}

@Test
public void testSkipFileOnJavaParseExceptionFalse() throws Exception {
final DefaultConfiguration config = createModuleConfig(TreeWalker.class);
config.addProperty("skipFileOnJavaParseException", "false");
config.addChild(createModuleConfig(ConstantNameCheck.class));

final String[] files = {
getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
getPath("InputTreeWalkerProperFileExtension.java"),
getNonCompilablePath("InputTreeWalkerSkipParsingException.java"),
};

try {
execute(config, files);
assertWithMessage("Exception is expected").fail();
}
catch (CheckstyleException exception) {
assertWithMessage("Error message is unexpected")
.that(exception.getMessage())
.contains("Exception was thrown while processing ");
}
}

@Test
public void testSkipFileOnJavaParseExceptionConfig() throws Exception {
final String path = getNonCompilablePath("InputTreeWalkerSkipParsingExceptionConfig.java");
final String[] expected = {};
verifyWithInlineXmlConfig(path, expected);
}

public static class BadJavaDocCheck extends AbstractCheck {

@Override
Expand Down
@@ -0,0 +1,3 @@
//non-compiled syntax: bad file for testing

public clazz InputTreeWalkerSkipParsingException {}
@@ -0,0 +1,11 @@
/*xml
<module name="Checker">
<module name="TreeWalker">
<property name="skipFileOnJavaParseException" value="true"/>
<module name="ConstantName"/>
</module>
</module>
*/

//non-compiled syntax: bad file for testing
public clazz InputTreeWalkerSkipParsingExceptionConfig {}
7 changes: 7 additions & 0 deletions src/xdocs/config.xml
Expand Up @@ -539,6 +539,13 @@
<td><code>.java</code></td>
<td>3.0</td>
</tr>
<tr>
<td>skipFileOnJavaParseException</td>
<td>Control whether to skip files with Java parsing errors.</td>
<td><a href="property_types.html#boolean">boolean</a></td>
<td><code>false</code></td>
<td>10.16.0</td>
</tr>
</table>
</div>
</subsection>
Expand Down

0 comments on commit e84dc9c

Please sign in to comment.