Skip to content

SONARJAVA-6198 S1451 should accept an empty headerFormat as the absence of any line#5576

Open
NoemieBenard wants to merge 6 commits intomasterfrom
sonarjava-6198
Open

SONARJAVA-6198 S1451 should accept an empty headerFormat as the absence of any line#5576
NoemieBenard wants to merge 6 commits intomasterfrom
sonarjava-6198

Conversation

@NoemieBenard
Copy link
Copy Markdown
Contributor

Modify S1451 to recognize an empty headerFormat as the absence of any line.

@hashicorp-vault-sonar-prod
Copy link
Copy Markdown
Contributor

hashicorp-vault-sonar-prod bot commented Apr 16, 2026

SONARJAVA-6198

@sonar-review-alpha
Copy link
Copy Markdown
Contributor

sonar-review-alpha bot commented Apr 16, 2026

Summary

This PR fixes rule S1451 (file header check) to correctly handle an empty headerFormat parameter as meaning "no header required."

The problem: When headerFormat was empty, splitting it produced an array with one empty string element, causing the check to incorrectly flag files as non-compliant even when no header was expected.

The fix: In FileHeaderCheck.java, explicitly check if headerFormat is empty before splitting. If empty, set expectedLines to an empty array, so files with no header are considered compliant.

Tests added: Two new test classes demonstrate both cases—files with and without a leading blank line—and confirm no issues are reported when using the default (empty) header format.

Cleanup: Removed unrelated code formatting issues in test files.

What reviewers should know

Where to start: Review the core logic change in FileHeaderCheck.java (lines 67–75) where the empty check is added.

Key points:

  • The fix is minimal and defensive: it just checks isEmpty() before calling split().
  • The new test cases (ClassBlankLine.java, ClassNoBlankLine.java) both pass with default settings (empty headerFormat), verifying that no header is required when the parameter is empty.
  • The changes to JavaSensorTest.java are mostly formatting/cleanup and removal of S1451 from expected checks in specific test contexts—not directly related to the core fix but included in this commit.

Watch for: Make sure the getHeaderFormat() method (line 80) is safe when called with empty headerFormat—the current code assumes format.charAt(0) exists, so ensure the empty case is handled before reaching that point (it is, as the split is skipped when empty).


  • Generate Walkthrough
  • Generate Diagram

🗣️ Give feedback

sonar-review-alpha[bot]

This comment was marked as resolved.

sonar-review-alpha[bot]

This comment was marked as outdated.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see that the existing samples do not use descriptive names, but I think this should not stop us here. How about a name like ClassBlankLine.java or something similar?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ClassNoHeader.java ?

private String getHeaderFormat() {
String format = headerFormat;
if(format.charAt(0) != '^') {
if (format.charAt(0) != '^') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's avoid reformatting unchanged code.

}
} else {
expectedLines = headerFormat.split("(?:\r)?\n|\r");
if (headerFormat.isEmpty()) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Conditional expression is IMO more readable:

expectedLines = headerFormat.isEmpty())
    ? new String[] {}
    :  headerFormat.split("(?:\r)?\n|\r");
``

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I ended up handling the empty case before as it is also necessary to handle it when headerFormat is a regular expression (see #5577)

sonar-review-alpha[bot]

This comment was marked as outdated.

@sonarqube-next
Copy link
Copy Markdown

Copy link
Copy Markdown
Contributor

@sonar-review-alpha sonar-review-alpha bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The non-regex fix is logically sound: matches() short-circuits correctly when expectedLines.length == 0, and the removal of java:S1451 from the contains() assertion in JavaSensorTest correctly reflects the changed behavior. However, there is an asymmetry in the fix that leaves the regex path broken for the same empty-format input.

🗣️ Give feedback

private String getHeaderFormat() {
String format = headerFormat;
if(format.charAt(0) != '^') {
if (format.charAt(0) != '^') {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

When isRegularExpression = true and headerFormat is empty, getHeaderFormat() is still called and will throw StringIndexOutOfBoundsException at format.charAt(0) on an empty string.

The PR fixes the non-regex path for empty headerFormat but leaves the regex path unguarded. A user who enables the regex mode and leaves headerFormat empty (the default) will get a runtime exception instead of the "no header required" behaviour.

Consider guarding the same way as the non-regex path, or at minimum returning "^" (match-everything) when the format is empty:

Suggested change
if (format.charAt(0) != '^') {
private String getHeaderFormat() {
String format = headerFormat;
if (format.isEmpty() || format.charAt(0) != '^') {
format = "^" + format;
}
return format;
}
  • Mark as noise

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants