Skip to content

Parse more checkstyle rules into OpenRewrite styles.#6761

Merged
sambsnyd merged 5 commits intomainfrom
checkstyle-more
Feb 19, 2026
Merged

Parse more checkstyle rules into OpenRewrite styles.#6761
sambsnyd merged 5 commits intomainfrom
checkstyle-more

Conversation

@sambsnyd
Copy link
Copy Markdown
Member

@sambsnyd sambsnyd commented Feb 18, 2026

This ended up being a larger, more impactful change than I expected.

I started off implementing support for checkstyle rules we did not previously support.
In the process I noticed that some of our existing checkstyle defaults did not match checkstyle's documented defaults, so I fixed those discrepancies.
Then I saw that an OSS contributor added a CustomImportOrder rule... but none of our formatting recipes knew it existed so it was completely pointless. So I converted that into the ImportLayoutStyle.
Then I wondered if the import layout style we loaded from checkstyle configuration would correctly take precedence over the autodetected import layout style and discovered it would not.

So I dug into how Styles are loaded and merged together and found that we had inadvertently implemented "first wins" rather than "last wins" semantics. Which meant that autodetected styles would supersede configured styles, oops. Perhaps it is a testament to the usefulness of Autodetect that we didn't get more complaints about this before now.

Also correct a few defaults which were wrong according to checkstyle's documentation.
@sambsnyd sambsnyd marked this pull request as draft February 18, 2026 19:29
…the formatting recipes, into ImportOrderStyle.

Also fix how Styles are merged. In looking at this I discovered a long-standing bug which gave earlier styles precedence over later styles. This means that "weaker" styles like those we autodetect would win over "stronger" styles like those parsed from checkstyle configuration, or explicitly specified by the user. It is perhaps a testament to teh quality of Autodetect that this wasn't a bigger problem before now.

There are still some test failures relating to fixing this serious bug that I need to work through.
@sambsnyd sambsnyd marked this pull request as ready for review February 19, 2026 20:43
@sambsnyd sambsnyd merged commit bb0e54c into main Feb 19, 2026
1 check passed
@sambsnyd sambsnyd deleted the checkstyle-more branch February 19, 2026 21:40
@github-project-automation github-project-automation Bot moved this from In Progress to Done in OpenRewrite Feb 19, 2026
Copy link
Copy Markdown
Contributor

@pstreef pstreef left a comment

Choose a reason for hiding this comment

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

Great change so far! Just a few more details for a potential follow up.

/**
* Merge many NamedStyles into one NamedStyle.
*
* @param styles The styles to be merged. Styles earlier in the list take precedence over styles later in the list.
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.

This says “Styles earlier in the list take precedence over styles later in the list” but the other merge() overload above (line 64) says the opposite: “gives precedence to non-null values from styles which appear later in the list.” Looking at the code, the new comment seems correct.

// OK to return a style with nullable non-null fields, if Autodetections doesn't provide Style.applyDefaults() will
//noinspection DataFlowIssue
return moduleList.stream()
.map(module -> new TabsAndIndentsStyle(false, null, null, null, null))
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 was a little confused about this, but it seems FileTabCharacter means tabs are violations so this is correct.

Maybe a comment on the meaning of the rule would be useful though.

inc = tokens.contains("INC");
dec = tokens.contains("DEC");
bnoc = tokens.contains("BNOC");
bnoc = tokens.contains("BNOT");
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.

nit: should this also be renamed to bnot?

parenPadStyle(conf))
.filter(Objects::nonNull)
.flatMap(Set::stream)
.collect(toSet()));
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.

Nice catch converting CustomImportOrderStyle into something actually used!

customImportOrderStyle(), avoidStarImportStyle(), and importOrderStyle() can all produce ImportLayoutStyle instances. Since they're collected into a HashSet and ImportLayoutStyle.merge() does last-wins, the result depends on iteration order — which is non-deterministic for HashSet. Should this be a LinkedHashSet to make the stream ordering deterministic?

Longer term, it might be cleaner to not emit a full ImportLayoutStyle from AvoidStarImport and instead only influence the star import thresholds on whatever layout is already configured.

sambsnyd added a commit to openrewrite/rewrite-static-analysis that referenced this pull request Feb 20, 2026
Since openrewrite/rewrite#6761 the CustomImportOrder rule is parsed into the ImportLayout style which is understood and acted upon by OrderImports.
timtebeek added a commit to openrewrite/rewrite-maven-plugin that referenced this pull request Feb 26, 2026
With openrewrite/rewrite#6761 changing style merging to "last wins"
semantics, configured styles must be applied after auto-detected styles
so they take precedence. Previously configured styles were set on the
parser (applied first) and auto-detected styles were added after parsing
(applied last), meaning auto-detected styles would unintentionally
override user configuration.

Remove the now-unnecessary styles parameter from
MavenMojoProjectParser#listSourceFiles and instead apply both
auto-detected and configured styles in the correct order within
AbstractRewriteBaseRunMojo.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Archived in project

Development

Successfully merging this pull request may close these issues.

2 participants