//////////////////////////////////////////////////////////////////////////////// // 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.github.sevntu.checkstyle.internal; import static java.nio.charset.StandardCharsets.UTF_8; import java.io.File; import java.nio.file.Files; import java.nio.file.StandardOpenOption; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.Set; import org.junit.Test; public class CheckstyleRegressionTest { /** List of checks to suppress if we dynamically add it to the configuration. */ private static final List<String> ADD_CHECK_SUPPRESSIONS = Arrays .asList("ReturnCountExtendedCheck"); // -@cs[CyclomaticComplexity] Can't split @Test public void setupFiles() throws Exception { final String regressionPath = System.getProperty("regression-path"); if (regressionPath != null) { final File path = new File(regressionPath); if (!path.exists()) { throw new IllegalStateException("Invalid path: " + path.getAbsolutePath()); } System.out.println("Working Path: " + path.getCanonicalPath()); final File project = new File(path, "checkstyle"); if (!project.exists() || !project.isDirectory()) { throw new IllegalStateException("Can't find project: " + project.getAbsolutePath()); } final File config = new File(project, "config/checkstyle_sevntu_checks.xml"); if (!config.exists() || !config.isFile() || !config.canRead() || !config.canWrite()) { throw new IllegalStateException("Can't read config: " + config.getAbsolutePath()); } System.out.println("Config Path: " + config.getCanonicalPath()); final File suppression = new File(project, "config/sevntu_suppressions.xml"); if (!suppression.exists() || !suppression.isFile() || !suppression.canRead() || !suppression.canWrite()) { throw new IllegalStateException("Can't read suppression: " + suppression.getAbsolutePath()); } System.out.println("Suppression Path: " + suppression.getCanonicalPath()); work(config, suppression); System.out.println("Done"); } } private static void work(File config, File suppression) throws Exception { final Set<String> configChecks = CheckUtil.getCheckStyleChecksReferencedInConfig(config .getAbsolutePath()); final List<Class<?>> sevntuChecks = new ArrayList<>(CheckUtil.getCheckstyleModules()); trimSevntuChecksNotReferenced(configChecks, sevntuChecks); String configContents = new String(Files.readAllBytes(config.toPath()), UTF_8); String suppressionContents = new String(Files.readAllBytes(suppression.toPath()), UTF_8); if (sevntuChecks.size() > 0) { System.out.println("Adding " + sevntuChecks.size() + " missing check(s)"); String configAdditions = ""; String suppressionAdditions = ""; for (Class<?> sevntuCheck : sevntuChecks) { final String name = sevntuCheck.getName(); final String simpleName = sevntuCheck.getSimpleName(); System.out.println("-- Adding Check: " + name); configAdditions += "<module name=\"" + name + "\"></module>\r\n"; if (ADD_CHECK_SUPPRESSIONS.contains(simpleName)) { System.out.println("-- Adding Suppression: " + simpleName); suppressionAdditions += "<suppress checks=\"" + simpleName + "\" files=\".*\"/>\r\n"; } } int treeWalkerPosition = configContents.lastIndexOf("<module name=\"TreeWalker\">"); treeWalkerPosition = configContents.indexOf('\n', treeWalkerPosition) + 1; configContents = configContents.substring(0, treeWalkerPosition) + configAdditions + configContents.substring(treeWalkerPosition); Files.write(config.toPath(), configContents.getBytes(UTF_8), StandardOpenOption.CREATE); if (!suppressionAdditions.isEmpty()) { final int position = suppressionContents.lastIndexOf("</suppressions"); suppressionContents = suppressionContents.substring(0, position) + suppressionAdditions + suppressionContents.substring(position); Files.write(suppression.toPath(), suppressionContents.getBytes(UTF_8), StandardOpenOption.CREATE); } } else { System.out.println("All sevntu checks listed in config"); } } private static void trimSevntuChecksNotReferenced(Set<String> configChecks, List<Class<?>> sevntuChecks) { for (String configCheck : configChecks) { final int position = findCheck(sevntuChecks, configCheck); if (position == -1) { System.err.println("Found module not in sevntu: " + configCheck); } else { sevntuChecks.remove(position); } } } // -@cs[ReturnCount] Not simple to reduce returns private static int findCheck(Collection<Class<?>> checks, String findCheck) { int position = 0; for (Class<?> check : checks) { final String simpleName = check.getSimpleName(); if (findCheck.endsWith("Check")) { if (simpleName.equals(findCheck) || check.getName().equals(findCheck)) { return position; } } else { if (simpleName.replaceAll("Check$", "").equals(findCheck) || check.getName().replaceAll("Check$", "").equals(findCheck)) { return position; } } position++; } return -1; } }