1717
1818package org .checkstyle .autofix ;
1919
20+ import java .io .File ;
21+ import java .io .FileInputStream ;
22+ import java .io .FileNotFoundException ;
23+ import java .io .IOException ;
2024import java .nio .file .Path ;
2125import java .util .List ;
26+ import java .util .Properties ;
2227
2328import org .checkstyle .autofix .parser .CheckstyleReportParser ;
2429import org .checkstyle .autofix .parser .CheckstyleViolation ;
2530import org .openrewrite .Option ;
2631import org .openrewrite .Recipe ;
2732
33+ import com .puppycrawl .tools .checkstyle .ConfigurationLoader ;
34+ import com .puppycrawl .tools .checkstyle .PropertiesExpander ;
35+ import com .puppycrawl .tools .checkstyle .api .CheckstyleException ;
36+ import com .puppycrawl .tools .checkstyle .api .Configuration ;
37+
2838/**
2939 * Main recipe that automatically fixes all supported Checkstyle violations.
3040 */
@@ -35,6 +45,22 @@ public class CheckstyleAutoFix extends Recipe {
3545 example = "target/checkstyle/checkstyle-report.xml" )
3646 private String violationReportPath ;
3747
48+ @ Option (displayName = "Checkstyle config path" ,
49+ description = "Path to the file containing Checkstyle configuration." ,
50+ example = "config/checkstyle.xml" )
51+ private String checkstyleConfigurationPath ;
52+
53+ @ Option (displayName = "Checkstyle properties file path" ,
54+ description = "Path to the file containing the Checkstyle Properties." ,
55+ example = "config/checkstyle.properties" )
56+ private String propertiesPath ;
57+
58+ private Configuration cachedConfig ;
59+
60+ public CheckstyleAutoFix () {
61+ // Constructor is now clean
62+ }
63+
3864 @ Override
3965 public String getDisplayName () {
4066 return "Checkstyle autoFix" ;
@@ -49,12 +75,69 @@ public String getViolationReportPath() {
4975 return violationReportPath ;
5076 }
5177
78+ public String getCheckstyleConfigurationPath () {
79+ return checkstyleConfigurationPath ;
80+ }
81+
82+ public String getPropertiesPath () {
83+ return propertiesPath ;
84+ }
85+
5286 @ Override
5387 public List <Recipe > getRecipeList () {
88+ try {
89+ final Configuration config = loadCheckstyleConfiguration ();
90+
91+ final List <CheckstyleViolation > violations = CheckstyleReportParser
92+ .parse (Path .of (getViolationReportPath ()));
5493
55- final List <CheckstyleViolation > violations = CheckstyleReportParser
56- .parse (Path .of (getViolationReportPath ()));
94+ return CheckstyleRecipeRegistry .getRecipes (violations , config );
5795
58- return CheckstyleRecipeRegistry .getRecipes (violations );
96+ }
97+ catch (CheckstyleException | IOException exception ) {
98+ throw new IllegalArgumentException ("Failed to load Checkstyle"
99+ + " configuration or parse violations" , exception );
100+ }
59101 }
102+
103+ private Configuration loadCheckstyleConfiguration () throws CheckstyleException , IOException {
104+ final Configuration config ;
105+
106+ if (cachedConfig == null ) {
107+ final Properties props = new Properties ();
108+ final String propFile = getPropertiesPath ();
109+
110+ try (FileInputStream input = new FileInputStream (propFile )) {
111+ props .load (input );
112+ }
113+ catch (FileNotFoundException exception ) {
114+ throw new IllegalArgumentException ("Failed to read: " + propFile , exception );
115+ }
116+
117+ final String configPath = getCheckstyleConfigurationPath ();
118+
119+ if (isRemoteUrl (configPath )) {
120+ config = ConfigurationLoader .loadConfiguration (
121+ configPath ,
122+ new PropertiesExpander (props )
123+ );
124+ }
125+ else {
126+ final File configFile = new File (configPath );
127+ config = ConfigurationLoader .loadConfiguration (
128+ configFile .toURI ().toString (),
129+ new PropertiesExpander (props )
130+ );
131+ }
132+
133+ cachedConfig = config ;
134+ }
135+
136+ return cachedConfig ;
137+ }
138+
139+ private boolean isRemoteUrl (String path ) {
140+ return path != null && (path .startsWith ("http://" ) || path .startsWith ("https://" ));
141+ }
142+
60143}
0 commit comments