diff --git a/config/ant-phase-verify.xml b/config/ant-phase-verify.xml index 818b84cbaeb..fb5fc039b4c 100644 --- a/config/ant-phase-verify.xml +++ b/config/ant-phase-verify.xml @@ -166,7 +166,8 @@ - + + @@ -203,6 +204,8 @@ + + diff --git a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java index df4fcfd078a..2f3b900dddf 100644 --- a/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java +++ b/src/main/java/com/puppycrawl/tools/checkstyle/TreeWalker.java @@ -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. */ @@ -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(); @@ -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 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 filteredViolations = + getFilteredViolations(file.getAbsolutePath(), contents, rootAST); + addViolations(filteredViolations); + } + violations.clear(); } - violations.clear(); } } diff --git a/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java b/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java index 470e7971360..0e91c9ce101 100644 --- a/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java +++ b/src/test/java/com/puppycrawl/tools/checkstyle/TreeWalkerTest.java @@ -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; @@ -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> 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 diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingException.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingException.java new file mode 100644 index 00000000000..27535652499 --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingException.java @@ -0,0 +1,3 @@ +//non-compiled syntax: bad file for testing + +public clazz InputTreeWalkerSkipParsingException {} diff --git a/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingExceptionConfig.java b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingExceptionConfig.java new file mode 100644 index 00000000000..f346a895330 --- /dev/null +++ b/src/test/resources-noncompilable/com/puppycrawl/tools/checkstyle/treewalker/InputTreeWalkerSkipParsingExceptionConfig.java @@ -0,0 +1,11 @@ +/*xml + + + + + + +*/ + +//non-compiled syntax: bad file for testing +public clazz InputTreeWalkerSkipParsingExceptionConfig {} diff --git a/src/xdocs/config.xml b/src/xdocs/config.xml index 1aeb721ca16..97f696bdba5 100644 --- a/src/xdocs/config.xml +++ b/src/xdocs/config.xml @@ -539,6 +539,13 @@ .java 3.0 + + skipFileOnJavaParseException + Control whether to skip files with Java parsing errors. + boolean + false + 10.16.0 +