From 860978af2e67c0052742db33a7e0159205b2f9c5 Mon Sep 17 00:00:00 2001 From: piyush kumar sadangi Date: Wed, 15 Jan 2025 14:05:03 +0530 Subject: [PATCH] Issue #219: Support of config bundles with extra configuration files --- Header/Example2/java.header | 18 +++ Header/Example4/java.header | 18 +++ .../src/main/resources/pom_template.xml | 4 + extractor/config/pmd/pmd-ruleset.xml | 16 +++ .../extractor/CheckstyleExampleExtractor.java | 134 +++++++++++++----- extractor/src/main/resources/java.header | 18 +++ 6 files changed, 170 insertions(+), 38 deletions(-) create mode 100644 Header/Example2/java.header create mode 100644 Header/Example4/java.header create mode 100644 extractor/src/main/resources/java.header diff --git a/Header/Example2/java.header b/Header/Example2/java.header new file mode 100644 index 000000000..646d81274 --- /dev/null +++ b/Header/Example2/java.header @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code and other text files for adherence to a set of rules. +// Copyright (C) 2001-2025 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 +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/Header/Example4/java.header b/Header/Example4/java.header new file mode 100644 index 000000000..646d81274 --- /dev/null +++ b/Header/Example4/java.header @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code and other text files for adherence to a set of rules. +// Copyright (C) 2001-2025 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 +/////////////////////////////////////////////////////////////////////////////////////////////// diff --git a/diff-java-tool/src/main/resources/pom_template.xml b/diff-java-tool/src/main/resources/pom_template.xml index c8ba431bc..3c28fca6d 100644 --- a/diff-java-tool/src/main/resources/pom_template.xml +++ b/diff-java-tool/src/main/resources/pom_template.xml @@ -16,6 +16,7 @@ 1.44.1 https://raw.githubusercontent.com/checkstyle/checkstyle/master/src/main/resources/google_checks.xml true + ${project.basedir}/config @@ -62,6 +63,9 @@ false ${checkstyle.failsOnError} + + config.folder=${config.folder} + diff --git a/extractor/config/pmd/pmd-ruleset.xml b/extractor/config/pmd/pmd-ruleset.xml index 79e0c4798..1bb86b705 100644 --- a/extractor/config/pmd/pmd-ruleset.xml +++ b/extractor/config/pmd/pmd-ruleset.xml @@ -48,15 +48,31 @@ + + + + + + + + + diff --git a/extractor/src/main/java/com/example/extractor/CheckstyleExampleExtractor.java b/extractor/src/main/java/com/example/extractor/CheckstyleExampleExtractor.java index de2ff56d1..e0e6a2baa 100644 --- a/extractor/src/main/java/com/example/extractor/CheckstyleExampleExtractor.java +++ b/extractor/src/main/java/com/example/extractor/CheckstyleExampleExtractor.java @@ -72,47 +72,45 @@ public final class CheckstyleExampleExtractor { private static final String PROJ_YML_PROP_FILE_PATH = "src/main/resources/" + PROJ_YML_PROP_FILENAME; - /** The regular expression pattern for excluded file paths. */ - private static final String EXCLUDED_FILE_PATTERN = - "src/xdocs-examples/resources/com/puppycrawl/tools/checkstyle/checks/regexp/" - + "regexpmultiline/Example7.txt"; - /** The regular expression pattern for example files. */ private static final String EXAMPLE_FILE_PATTERN = "Example\\d+\\.(java|txt)"; /** The subfolder name for all-in-one examples. */ private static final String ALL_IN_ONE_SUBFOLDER = "all-examples-in-one"; - /** - * Number of expected arguments when processing a single input file. - */ + /** The filename for the Java header file. */ + private static final String JAVA_HEADER_FILENAME = "java.header"; + + /** The name of the Example2 directory. */ + private static final String EXAMPLE2_DIR = "Example2"; + + /** The name of the Example4 directory. */ + private static final String EXAMPLE4_DIR = "Example4"; + + /** The name of the Header directory. */ + private static final String HEADER_DIR = "Header"; + + /** Number of expected arguments when processing a single input file. */ private static final int SINGLE_INPUT_FILE_ARG_COUNT = 5; - /** - * Index of the "--input-file" flag in the argument array. - */ + /** Index of the "--input-file" flag in the argument array. */ private static final int INPUT_FILE_FLAG_INDEX = 1; - /** - * Index of the input file path in the argument array. - */ + /** Index of the input file path in the argument array. */ private static final int INPUT_FILE_PATH_INDEX = 2; - /** - * Index of the output file path in the argument array. - */ + /** Index of the output file path in the argument array. */ private static final int OUTPUT_FILE_PATH_INDEX = 3; - /** - * Index of the output file path in the argument array. - */ + /** Index of the output file path in the argument array. */ private static final int PROJECT_OUTPUT_PATH_INDEX = 4; - /** - * The buffer size for reading and writing files. - */ + /** The buffer size for reading and writing files. */ private static final int BUFFER_SIZE = 1024; + /** The constant for header path. */ + private static final String JAVA_HEADER_PATH = "config/java.header"; + /** * Private constructor to prevent instantiation of this utility class. */ @@ -156,7 +154,8 @@ public static void main(final String[] args) throws Exception { final Properties props = System.getProperties(); props.setProperty("config.folder", "${config.folder}"); - final Map> moduleExamples = processExampleDirs(allExampleDirs); + final Map> moduleExamples = + processExampleDirs(allExampleDirs, checkstyleRepoPath); YamlParserAndProjectHandler.processProjectsForExamples(PROJECT_ROOT.toString()); @@ -305,15 +304,16 @@ private static List findAllExampleDirs(final String checkstyleRepoPath) * Processes example directories to map module names to their corresponding directories. * * @param allExampleDirs A list of paths to example directories. + * @param checkstyleRepoPath The path to the Checkstyle repository. * @return A map associating module names with their example directories. * @throws Exception If an unexpected error occurs. */ private static Map> processExampleDirs( - final List allExampleDirs) + final List allExampleDirs, final String checkstyleRepoPath) throws Exception { final Map> moduleExamples = new ConcurrentHashMap<>(); for (final Path dir : allExampleDirs) { - final String moduleName = processDirectory(dir.toString()); + final String moduleName = processDirectory(dir.toString(), checkstyleRepoPath); if (moduleName != null) { moduleExamples.computeIfAbsent(moduleName, moduleKey -> new ArrayList<>()).add(dir); } @@ -365,10 +365,12 @@ private static boolean containsExampleFile(final Path path) { * Process a directory containing example files. * * @param inputDir Input directory path + * @param checkstyleRepoPath The path to the Checkstyle repository. * @return Module name if processing was successful, null otherwise * @throws Exception If an I/O error occurs */ - public static String processDirectory(final String inputDir) throws Exception { + public static String processDirectory(final String inputDir, + final String checkstyleRepoPath) throws Exception { String moduleName = null; final Path inputPath = Paths.get(inputDir); @@ -376,7 +378,6 @@ public static String processDirectory(final String inputDir) throws Exception { final List exampleFiles = paths .filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().matches(EXAMPLE_FILE_PATTERN)) - .filter(path -> !path.toString().endsWith(EXCLUDED_FILE_PATTERN)) .collect(Collectors.toList()); if (!exampleFiles.isEmpty()) { @@ -387,7 +388,7 @@ public static String processDirectory(final String inputDir) throws Exception { Files.createDirectories(outputPath); for (final Path exampleFile : exampleFiles) { - processExampleFile(exampleFile, outputPath); + processExampleFile(exampleFile, outputPath, checkstyleRepoPath); } } } @@ -400,36 +401,40 @@ public static String processDirectory(final String inputDir) throws Exception { * Processes an example file and creates a corresponding subfolder in the output path. * * @param exampleFile The example file to process. + * @param checkstyleRepoPath The path to the Checkstyle repository. * @param outputPath The path where the processed file's subfolder will be created. * @throws Exception If an unexpected error occurs. */ private static void processExampleFile( final Path exampleFile, - final Path outputPath) + final Path outputPath, + final String checkstyleRepoPath) throws Exception { final Path fileName = exampleFile.getFileName(); if (fileName != null) { final String fileNameStr = fileName.toString().replaceFirst("\\.(java|txt)$", ""); final Path subfolderPath = outputPath.resolve(fileNameStr); Files.createDirectories(subfolderPath); - processFile(exampleFile.toString(), subfolderPath); + processFile(exampleFile.toString(), subfolderPath, checkstyleRepoPath); } } /** * Processes an example file and generates its configuration, properties, and README. + * Also copies any known extra files if present in the same folder. * - * @param exampleFile The path to the example file. - * @param outputPath The path where the generated content will be stored. + * @param exampleFile The path to the example file (.java or .txt). + * @param checkstyleRepoPath The path to the Checkstyle repository. + * @param outputPath The path where the generated content (config.xml, etc.) will be stored. * @throws Exception If an unexpected error occurs. */ private static void processFile( final String exampleFile, - final Path outputPath) + final Path outputPath, + final String checkstyleRepoPath) throws Exception { if (exampleFile != null - && outputPath != null - && !exampleFile.endsWith(EXCLUDED_FILE_PATTERN)) { + && outputPath != null) { try { final String templateFilePath = getTemplateFilePathForExamples(exampleFile); if (templateFilePath != null) { @@ -438,6 +443,7 @@ private static void processFile( writeConfigFile(outputPath, generatedContent); copyPropertiesFile(outputPath); generateReadme(outputPath); + handleHeaderFileIfNeeded(outputPath, checkstyleRepoPath); } else { LOGGER.log(Level.WARNING, @@ -453,6 +459,60 @@ private static void processFile( } } + /** + * Copies java.header from Checkstyle repository into the output folder + * (next to config.xml) if it exists. + * + * @param outputPath The folder where config.xml is placed. + * @param checkstyleRepoPath The path to Checkstyle repository + * @throws IOException if an I/O error occurs. + */ + private static void copyJavaHeaderIfNeeded(final Path outputPath, + final String checkstyleRepoPath) + throws IOException { + final Path source = + Paths.get(checkstyleRepoPath, JAVA_HEADER_PATH); + + if (Files.exists(source)) { + Files.copy(source, + outputPath.resolve(JAVA_HEADER_FILENAME), + StandardCopyOption.REPLACE_EXISTING); + LOGGER.info("Copied " + JAVA_HEADER_FILENAME + + " from " + source + " to " + outputPath); + } + else { + LOGGER.warning("No " + JAVA_HEADER_FILENAME + + " found at " + source + ". Skipping."); + } + } + + /** + * Checks if the output path requires a java.header file and copies it if needed. + * + * @param outputPath The path where config.xml is placed + * @param checkstyleRepoPath The path to Checkstyle repository + * @throws IOException if an I/O error occurs + */ + private static void handleHeaderFileIfNeeded(final Path outputPath, + final String checkstyleRepoPath) + throws IOException { + final Path parentDir = outputPath.getParent(); + final String parentName = Optional.ofNullable(parentDir) + .map(Path::getFileName) + .map(Path::toString) + .orElse(""); + + final String folderName = Optional.ofNullable(outputPath.getFileName()) + .map(Path::toString) + .orElse(""); + + if (HEADER_DIR.equals(parentName) + && (EXAMPLE2_DIR.equals(folderName) + || EXAMPLE4_DIR.equals(folderName))) { + copyJavaHeaderIfNeeded(outputPath, checkstyleRepoPath); + } + } + /** * Writes the serialized configuration content to a config.xml. * @@ -554,7 +614,6 @@ private static List getAllExampleFiles(final List exampleDirs) paths.filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().matches(EXAMPLE_FILE_PATTERN)) .map(Path::toString) - .filter(file -> !file.endsWith(EXCLUDED_FILE_PATTERN)) .forEach(allExampleFiles::add); } } @@ -709,7 +768,6 @@ private static void generateReadmes( try (Stream paths = Files.list(dir)) { paths.filter(Files::isRegularFile) .filter(path -> path.getFileName().toString().matches(EXAMPLE_FILE_PATTERN)) - .filter(path -> !path.toString().endsWith(EXCLUDED_FILE_PATTERN)) .forEach(exampleFile -> { generateIndividualReadme(exampleFile, outputPath, moduleName); }); diff --git a/extractor/src/main/resources/java.header b/extractor/src/main/resources/java.header new file mode 100644 index 000000000..d232cb402 --- /dev/null +++ b/extractor/src/main/resources/java.header @@ -0,0 +1,18 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle: Checks Java source code and other text files for adherence to a set of rules. +// Copyright (C) 2001-2025 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 +/////////////////////////////////////////////////////////////////////////////////////////////// \ No newline at end of file