//////////////////////////////////////////////////////////////////////////////// // 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; import static com.puppycrawl.tools.checkstyle.checks.naming.AbstractNameCheck.MSG_INVALID_PATTERN; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.BufferedWriter; import java.io.File; import java.io.FileOutputStream; import java.io.OutputStreamWriter; import java.io.Writer; import java.nio.charset.StandardCharsets; import java.util.ArrayList; import java.util.HashSet; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import com.puppycrawl.tools.checkstyle.api.AbstractCheck; import com.puppycrawl.tools.checkstyle.api.CheckstyleException; import com.puppycrawl.tools.checkstyle.api.TokenTypes; import com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck; import com.puppycrawl.tools.checkstyle.checks.javadoc.JavadocPackageCheck; import com.puppycrawl.tools.checkstyle.checks.naming.ConstantNameCheck; import com.puppycrawl.tools.checkstyle.checks.naming.TypeNameCheck; import com.puppycrawl.tools.checkstyle.utils.CommonUtils; public class TreeWalkerTest extends BaseCheckTestSupport { @Rule public final TemporaryFolder temporaryFolder = new TemporaryFolder(); @Test public void testProperFileExtension() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(ConstantNameCheck.class); final File file = temporaryFolder.newFile("file.java"); try (Writer writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { final String content = "public class Main { public static final int k = 5 + 4; }"; writer.write(content); } final String[] expected1 = { "1:45: " + getCheckMessage(ConstantNameCheck.class, MSG_INVALID_PATTERN, "k", "^[A-Z][A-Z0-9]*(_[A-Z0-9]+)*$"), }; verify(checkConfig, file.getPath(), expected1); } @Test public void testImproperFileExtension() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(ConstantNameCheck.class); final File file = temporaryFolder.newFile("file.pdf"); try (BufferedWriter writer = new BufferedWriter( new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8))) { final String content = "public class Main { public static final int k = 5 + 4; }"; writer.write(content); } final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, file.getPath(), expected); } @Test public void testAcceptableTokens() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(HiddenFieldCheck.class); checkConfig.addAttribute("tokens", "VARIABLE_DEF, ENUM_DEF, CLASS_DEF, METHOD_DEF," + "IMPORT"); try { final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, getPath("InputMain.java"), expected); fail("CheckstyleException is expected"); } catch (CheckstyleException ex) { final String errorMsg = ex.getMessage(); final Pattern expected = Pattern.compile(Pattern.quote("cannot initialize module" + " com.puppycrawl.tools.checkstyle.TreeWalker - Token ") + "\"(ENUM_DEF|CLASS_DEF|METHOD_DEF|IMPORT)\"" + Pattern.quote(" was not found in Acceptable tokens list in check" + " com.puppycrawl.tools.checkstyle.checks.coding.HiddenFieldCheck")); final Matcher errorMsgMatcher = expected.matcher(errorMsg); assertTrue("Failure for: " + errorMsg, errorMsgMatcher.matches()); } } @Test public void testOnEmptyFile() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(HiddenFieldCheck.class); final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath(); final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, pathToEmptyFile, expected); } @Test public void testWithCheckNotHavingTreeWalkerAsParent() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(JavadocPackageCheck.class); try { final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, temporaryFolder.newFile().getPath(), expected); fail("CheckstyleException is expected"); } catch (CheckstyleException exception) { assertTrue(exception.getMessage().contains("TreeWalker is not allowed as a parent of")); } } @Test public void testSettersForParameters() throws Exception { final TreeWalker treeWalker = new TreeWalker(); treeWalker.setTabWidth(1); treeWalker.configure(new DefaultConfiguration("default config")); treeWalker.setCacheFile(temporaryFolder.newFile().getPath()); } @Test public void testForInvalidCheckImplementation() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(BadJavaDocCheck.class); final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath(); try { final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, pathToEmptyFile, expected); } catch (CheckstyleException ex) { assertTrue(ex.getMessage().contains("isCommentNodesRequired")); } } @Test public void testProcessNonJavaFiles() throws Exception { final TreeWalker treeWalker = new TreeWalker(); treeWalker.setTabWidth(1); treeWalker.configure(new DefaultConfiguration("default config")); final File file = new File("src/main/resources/checkstyle_packages.xml"); treeWalker.processFiltered(file, new ArrayList<>()); } @Test public void testWithCacheWithNoViolation() throws Exception { final TreeWalker treeWalker = new TreeWalker(); treeWalker.configure(createCheckConfig(TypeNameCheck.class)); final PackageObjectFactory factory = new PackageObjectFactory( new HashSet<>(), Thread.currentThread().getContextClassLoader()); treeWalker.setModuleFactory(factory); treeWalker.setupChild(createCheckConfig(TypeNameCheck.class)); final File file = temporaryFolder.newFile("file.java"); final List<String> lines = new ArrayList<>(); lines.add(" class a {} "); treeWalker.processFiltered(file, lines); } @Test public void testProcessWithParserThrowable() throws Exception { final TreeWalker treeWalker = new TreeWalker(); treeWalker.configure(createCheckConfig(TypeNameCheck.class)); final PackageObjectFactory factory = new PackageObjectFactory( new HashSet<>(), Thread.currentThread().getContextClassLoader()); treeWalker.setModuleFactory(factory); treeWalker.setupChild(createCheckConfig(TypeNameCheck.class)); final File file = temporaryFolder.newFile("file.java"); final List<String> lines = new ArrayList<>(); lines.add(" classD a {} "); try { treeWalker.processFiltered(file, lines); } catch (CheckstyleException exception) { assertTrue(exception.getMessage().contains( "occurred during the analysis of file")); } } @Test public void testProcessWithRecognitionException() throws Exception { final TreeWalker treeWalker = new TreeWalker(); treeWalker.configure(createCheckConfig(TypeNameCheck.class)); final PackageObjectFactory factory = new PackageObjectFactory( new HashSet<>(), Thread.currentThread().getContextClassLoader()); treeWalker.setModuleFactory(factory); treeWalker.setupChild(createCheckConfig(TypeNameCheck.class)); final File file = temporaryFolder.newFile("file.java"); final List<String> lines = new ArrayList<>(); lines.add(" class a%$# {} "); try { treeWalker.processFiltered(file, lines); } catch (CheckstyleException exception) { assertTrue(exception.getMessage().contains( "TokenStreamRecognitionException occurred during the analysis of file")); } } @Test public void testRequiredTokenIsNotInDefaultTokens() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(RequiredTokenIsNotInDefaultsCheck.class); final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath(); try { final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, pathToEmptyFile, expected); fail("CheckstyleException is expected"); } catch (CheckstyleException ex) { assertTrue(ex.getMessage().startsWith("cannot initialize module" + " com.puppycrawl.tools.checkstyle.TreeWalker - Token \"" + TokenTypes.ASSIGN + "\" from required" + " tokens was not found in default tokens list in check")); } } @Test public void testRequiredTokenIsEmptyIntArray() throws Exception { final DefaultConfiguration checkConfig = createCheckConfig(RequiredTokenIsEmptyIntArray.class); final String pathToEmptyFile = temporaryFolder.newFile("file.java").getPath(); try { final String[] expected = CommonUtils.EMPTY_STRING_ARRAY; verify(checkConfig, pathToEmptyFile, expected); } catch (CheckstyleException ignored) { // unexpected fail("CheckstyleException is NOT expected"); } } private static class BadJavaDocCheck extends AbstractCheck { @Override public int[] getDefaultTokens() { return getAcceptableTokens(); } @Override public int[] getAcceptableTokens() { return new int[] {TokenTypes.SINGLE_LINE_COMMENT}; } @Override public int[] getRequiredTokens() { return getAcceptableTokens(); } } private static class RequiredTokenIsNotInDefaultsCheck extends AbstractCheck { @Override public int[] getRequiredTokens() { return new int[] {TokenTypes.ASSIGN}; } @Override public int[] getDefaultTokens() { return new int[] {TokenTypes.ANNOTATION}; } @Override public int[] getAcceptableTokens() { return CommonUtils.EMPTY_INT_ARRAY; } } private static class RequiredTokenIsEmptyIntArray extends AbstractCheck { @Override public int[] getRequiredTokens() { return CommonUtils.EMPTY_INT_ARRAY; } @Override public int[] getDefaultTokens() { return new int[] {TokenTypes.ANNOTATION}; } @Override public int[] getAcceptableTokens() { return CommonUtils.EMPTY_INT_ARRAY; } } }