diff --git a/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java b/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java index 733bbbe..85deb3a 100644 --- a/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java +++ b/src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java @@ -20,8 +20,10 @@ import java.nio.file.Path; import java.util.List; +import org.checkstyle.autofix.parser.CheckConfiguration; import org.checkstyle.autofix.parser.CheckstyleReportParser; import org.checkstyle.autofix.parser.CheckstyleViolation; +import org.checkstyle.autofix.parser.ConfigurationLoader; import org.openrewrite.Option; import org.openrewrite.Recipe; @@ -35,6 +37,11 @@ public class CheckstyleAutoFix extends Recipe { example = "target/checkstyle/checkstyle-report.xml") private String violationReportPath; + @Option(displayName = "Checkstyle config path", + description = "Path to the file containing Checkstyle configuration.", + example = "config/checkstyle.xml") + private String configurationPath; + @Override public String getDisplayName() { return "Checkstyle autoFix"; @@ -49,12 +56,19 @@ public String getViolationReportPath() { return violationReportPath; } + public String getConfigurationPath() { + return configurationPath; + } + @Override public List getRecipeList() { - final List violations = CheckstyleReportParser .parse(Path.of(getViolationReportPath())); return CheckstyleRecipeRegistry.getRecipes(violations); } + + private CheckConfiguration loadCheckstyleConfiguration() { + return ConfigurationLoader.loadConfiguration(getConfigurationPath()); + } } diff --git a/src/main/java/org/checkstyle/autofix/parser/CheckConfiguration.java b/src/main/java/org/checkstyle/autofix/parser/CheckConfiguration.java new file mode 100644 index 0000000..2daf412 --- /dev/null +++ b/src/main/java/org/checkstyle/autofix/parser/CheckConfiguration.java @@ -0,0 +1,91 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle-openrewrite-recipes: Automatically fix Checkstyle violations with OpenRewrite. +// Copyright (C) 2025 The Checkstyle OpenRewrite Recipes Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/////////////////////////////////////////////////////////////////////////////////////////////// + +package org.checkstyle.autofix.parser; + +import java.util.List; +import java.util.Map; + +public final class CheckConfiguration { + private final String name; + private final Map properties; + private final List children; + private CheckConfiguration parent; + + public CheckConfiguration(String name, + Map properties, List children) { + this.name = name; + this.properties = properties; + this.children = children; + + for (CheckConfiguration child : children) { + child.setParent(this); + } + } + + public String getName() { + return name; + } + + public Map getProperties() { + return properties; + } + + public List getChildren() { + return children; + } + + public String getProperty(String key) { + return properties.get(key); + } + + public int[] getIntArray(String propertyName) { + final String value = properties.get(propertyName); + final int[] result; + final String[] parts = value.split(","); + result = new int[parts.length]; + for (int index = 0; index < parts.length; index++) { + try { + result[index] = Integer.parseInt(parts[index].trim()); + } + catch (NumberFormatException exception) { + throw new IllegalArgumentException("Property '" + propertyName + + "' has an invalid integer value: " + parts[index].trim(), exception); + } + } + return result; + } + + public CheckConfiguration getChild(String childName) { + CheckConfiguration result = null; + for (CheckConfiguration child : children) { + if (childName.equals(child.getName())) { + result = child; + break; + } + } + return result; + } + + public CheckConfiguration getParent() { + return parent; + } + + private void setParent(CheckConfiguration parent) { + this.parent = parent; + } +} diff --git a/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java b/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java new file mode 100644 index 0000000..b0b4b97 --- /dev/null +++ b/src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java @@ -0,0 +1,76 @@ +/////////////////////////////////////////////////////////////////////////////////////////////// +// checkstyle-openrewrite-recipes: Automatically fix Checkstyle violations with OpenRewrite. +// Copyright (C) 2025 The Checkstyle OpenRewrite Recipes Authors +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +/////////////////////////////////////////////////////////////////////////////////////////////// + +package org.checkstyle.autofix.parser; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import com.puppycrawl.tools.checkstyle.PropertiesExpander; +import com.puppycrawl.tools.checkstyle.api.CheckstyleException; +import com.puppycrawl.tools.checkstyle.api.Configuration; + +public final class ConfigurationLoader { + + private ConfigurationLoader() { + // utility class + } + + private static CheckConfiguration mapConfiguration(Configuration config) { + final Map properties = new HashMap<>(); + final String[] propertyNames = config.getPropertyNames(); + for (String propertyName : propertyNames) { + try { + final String value = config.getProperty(propertyName); + properties.put(propertyName, value); + + } + catch (CheckstyleException exception) { + throw new IllegalStateException("Error getting property " + propertyName, + exception); + } + } + + final Configuration[] checkstyleChildren = config.getChildren(); + final CheckConfiguration[] simpleChildren = + new CheckConfiguration[checkstyleChildren.length]; + for (int index = 0; index < checkstyleChildren.length; index++) { + simpleChildren[index] = mapConfiguration(checkstyleChildren[index]); + } + + return new CheckConfiguration(config.getName(), properties, List.of(simpleChildren)); + } + + public static CheckConfiguration loadConfiguration(String checkstyleConfigurationPath) { + + final Configuration checkstyleConfig; + try { + checkstyleConfig = com.puppycrawl.tools.checkstyle.ConfigurationLoader + .loadConfiguration(checkstyleConfigurationPath, + new PropertiesExpander(new Properties())); + } + catch (CheckstyleException exception) { + throw new IllegalStateException("Failed to load configuration:" + + checkstyleConfigurationPath, exception); + } + + return mapConfiguration(checkstyleConfig); + } + +} diff --git a/src/main/resources/META-INF/rewrite/recipes.yml b/src/main/resources/META-INF/rewrite/recipes.yml index 76b2c72..ae1b7de 100644 --- a/src/main/resources/META-INF/rewrite/recipes.yml +++ b/src/main/resources/META-INF/rewrite/recipes.yml @@ -15,3 +15,4 @@ tags: recipeList: - org.checkstyle.autofix.CheckstyleAutoFix: violationReportPath: "target/checkstyle/checkstyle-report.xml" + configurationPath: "https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-${checkstyle.version}/config/checkstyle-checks.xml"