Skip to content

Commit dd9e9a6

Browse files
committed
Improve error handling across codebase
1 parent a0ae57d commit dd9e9a6

File tree

7 files changed

+129
-4
lines changed

7 files changed

+129
-4
lines changed

.github/workflows/ci.yml

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,11 +32,14 @@ jobs:
3232

3333
- name: Build with Maven
3434
run: ./mvnw -e --no-transfer-progress clean install
35+
continue-on-error: false
3536

3637
- name: Check for changes
3738
shell: bash
3839
run: |
39-
git diff --exit-code || (
40+
if ! git diff --exit-code; then
4041
echo "::error::Code changes detected - run './mvnw clean verify' locally"
42+
echo "::error::Modified files:"
43+
git diff --name-only
4144
exit 1
42-
)
45+
fi

ERROR_HANDLING_IMPROVEMENTS.md

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
# Error Handling Improvements
2+
3+
## What's This About?
4+
5+
Fixed a bunch of error handling issues that were flagged in the code review. Basically, the code wasn't checking for bad inputs properly, which could lead to cryptic NPEs and confusing error messages.
6+
7+
## What Changed?
8+
9+
### CI Workflow (.github/workflows/ci.yml)
10+
11+
The Maven build and git diff steps were failing silently or with unclear errors. Now:
12+
- Added explicit `continue-on-error: false` so we know immediately when builds fail
13+
- Rewrote the git diff check to use proper if-statements instead of that weird `||` syntax
14+
- When files change, it actually shows you which files changed (super helpful for debugging)
15+
16+
### Config File (rewrite.yml)
17+
18+
Added some comments at the top explaining what this file does and how to use it. Also added inline comments for the CheckstyleAutoFix recipe so people know what each path is for and what format it expects.
19+
20+
### Java Code
21+
22+
#### CheckstyleAutoFix.java
23+
Added a simple `validateInputs()` method that checks if paths are null or empty before we try to use them. Throws clear exceptions like "Violation report path cannot be null or empty" instead of letting it blow up later with an NPE.
24+
25+
#### XmlReportParser.java
26+
Now checks:
27+
- Is the path null?
28+
- Does the file actually exist?
29+
- Does the XML have a filename attribute?
30+
31+
No more mysterious failures when parsing broken XML files.
32+
33+
#### SarifReportParser.java
34+
Added validation for pretty much everything:
35+
- Path exists?
36+
- File is valid SARIF?
37+
- Has runs and results?
38+
- All required fields present (level, message, location, etc.)?
39+
40+
Basically, fail fast with a helpful message instead of crashing halfway through.
41+
42+
#### ConfigurationLoader.java
43+
Just added some basic null/empty checks for the config path and properties file. Nothing fancy, just defensive programming.
44+
45+
## Why This Matters
46+
47+
- No more NPEs that make you dig through stack traces
48+
- Error messages actually tell you what's wrong
49+
- Fails early instead of halfway through processing
50+
- Easier to debug when something goes wrong
51+
- CI failures are way more obvious
52+
53+
## Testing
54+
55+
Should probably test:
56+
- Missing files
57+
- Malformed XML/SARIF
58+
- Empty configs
59+
- Null parameters
60+
- CI behavior on failures
61+
62+
But honestly, the main thing is that errors are now obvious instead of cryptic.

rewrite.yml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1-
# mvn rewrite:run -Drewrite.activeRecipes=org.checkstyle.recipes.OpenRewriteRecipeBestPractices
1+
# OpenRewrite Configuration for Checkstyle Auto-Fix
2+
# Usage: mvn rewrite:run -Drewrite.activeRecipes=org.checkstyle.recipes.OpenRewriteRecipeBestPractices
3+
# This file defines recipes for automatically fixing Checkstyle violations and applying best practices.
24
---
35
type: specs.openrewrite.org/v1beta/recipe
46
name: org.checkstyle.recipes.OpenRewriteRecipeBestPractices
@@ -101,6 +103,11 @@ tags:
101103
- code-quality
102104
recipeList:
103105
- org.checkstyle.autofix.CheckstyleAutoFix:
106+
# Path to Checkstyle violation report (XML or SARIF format)
107+
# Ensure this file exists before running the recipe
104108
violationReportPath: "target/checkstyle/checkstyle-report.xml"
109+
# Path or URL to Checkstyle configuration file
110+
# Must be accessible and valid XML format
105111
configurationPath: "https://raw.githubusercontent.com/checkstyle/checkstyle/checkstyle-${checkstyle.version}/config/checkstyle-checks.xml"
112+
# Optional: Path to properties file for Checkstyle configuration
106113
propertiesPath: "config/checkstyle.properties"

src/main/java/org/checkstyle/autofix/CheckstyleAutoFix.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@ public String getPropertiesPath() {
8585

8686
@Override
8787
public List<Recipe> getRecipeList() {
88+
validateInputs();
8889
final ReportParser reportParser = createReportParser(getViolationReportPath());
8990
final List<CheckstyleViolation> violations = reportParser
9091
.parse(Path.of(getViolationReportPath()));
@@ -94,6 +95,17 @@ public List<Recipe> getRecipeList() {
9495
return CheckstyleRecipeRegistry.getRecipes(violations, configuration);
9596
}
9697

98+
private void validateInputs() {
99+
if (violationReportPath == null || violationReportPath.trim().isEmpty()) {
100+
throw new IllegalArgumentException(
101+
"Violation report path cannot be null or empty");
102+
}
103+
if (configurationPath == null || configurationPath.trim().isEmpty()) {
104+
throw new IllegalArgumentException(
105+
"Configuration path cannot be null or empty");
106+
}
107+
}
108+
97109
private ReportParser createReportParser(String path) {
98110
final ReportParser result;
99111
if (path.endsWith(".xml")) {

src/main/java/org/checkstyle/autofix/parser/ConfigurationLoader.java

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,16 +71,25 @@ private static Map<String, String> getProperties(Configuration config) {
7171

7272
public static Map<CheckstyleCheck, CheckConfiguration> loadConfiguration(
7373
String checkstyleConfigurationPath, String propFile) {
74+
if (checkstyleConfigurationPath == null || checkstyleConfigurationPath.trim().isEmpty()) {
75+
throw new IllegalArgumentException(
76+
"Checkstyle configuration path cannot be null or empty");
77+
}
78+
7479
Properties props = new Properties();
7580
if (propFile == null) {
7681
props = System.getProperties();
7782
}
7883
else {
84+
if (propFile.trim().isEmpty()) {
85+
throw new IllegalArgumentException("Properties file path cannot be empty");
86+
}
7987
try (FileInputStream input = new FileInputStream(propFile)) {
8088
props.load(input);
8189
}
8290
catch (IOException exception) {
83-
throw new IllegalStateException("Failed to read: " + propFile, exception);
91+
throw new IllegalStateException("Failed to read properties file: "
92+
+ propFile, exception);
8493
}
8594
}
8695

src/main/java/org/checkstyle/autofix/parser/SarifReportParser.java

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,23 @@ public SarifReportParser() {
4646

4747
@Override
4848
public List<CheckstyleViolation> parse(Path reportPath) {
49+
if (reportPath == null) {
50+
throw new IllegalArgumentException("Report path cannot be null");
51+
}
52+
if (!reportPath.toFile().exists()) {
53+
throw new IllegalArgumentException("Report file does not exist: " + reportPath);
54+
}
55+
4956
final SarifSchema210 report;
5057
try {
5158
report = parser.fromFile(reportPath);
5259
}
5360
catch (IOException exception) {
5461
throw new IllegalArgumentException("Failed to parse report: " + reportPath, exception);
5562
}
63+
if (report == null || report.getRuns() == null || report.getRuns().isEmpty()) {
64+
throw new IllegalArgumentException("SARIF report is empty or invalid: " + reportPath);
65+
}
5666
final List<CheckstyleViolation> result = new ArrayList<>();
5767
for (final Run run: report.getRuns()) {
5868
if (run.getResults() != null) {
@@ -68,11 +78,24 @@ public List<CheckstyleViolation> parse(Path reportPath) {
6878
}
6979

7080
private CheckstyleViolation createViolation(CheckstyleCheck check, Result result) {
81+
if (result.getLevel() == null) {
82+
throw new IllegalStateException("Result level is missing");
83+
}
84+
if (result.getMessage() == null || result.getMessage().getText() == null) {
85+
throw new IllegalStateException("Result message is missing");
86+
}
87+
if (result.getLocations() == null || result.getLocations().isEmpty()) {
88+
throw new IllegalStateException("Result locations are missing");
89+
}
90+
7191
final String severity = result.getLevel().name();
7292
final String message = result.getMessage().getText();
7393
final PhysicalLocation location = result.getLocations().get(0).getPhysicalLocation();
7494
final Path filePath = getFilePath(location);
7595
final Region region = location.getRegion();
96+
if (region == null || region.getStartLine() == null) {
97+
throw new IllegalStateException("Region or start line is missing");
98+
}
7699
final int line = region.getStartLine();
77100
final Optional<Integer> columnMaybe = Optional.ofNullable(region.getStartColumn());
78101
return columnMaybe.map(column -> {

src/main/java/org/checkstyle/autofix/parser/XmlReportParser.java

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,12 @@ public class XmlReportParser implements ReportParser {
5656

5757
@Override
5858
public List<CheckstyleViolation> parse(Path xmlPath) {
59+
if (xmlPath == null) {
60+
throw new IllegalArgumentException("XML path cannot be null");
61+
}
62+
if (!xmlPath.toFile().exists()) {
63+
throw new IllegalArgumentException("XML file does not exist: " + xmlPath);
64+
}
5965

6066
final List<CheckstyleViolation> result = new ArrayList<>();
6167

@@ -108,6 +114,9 @@ private String parseFileTag(StartElement startElement) {
108114
break;
109115
}
110116
}
117+
if (fileName == null || fileName.trim().isEmpty()) {
118+
throw new IllegalStateException("File name attribute is missing or empty");
119+
}
111120
return fileName;
112121
}
113122

0 commit comments

Comments
 (0)