Skip to content

Syntax updates#6239

Draft
duncdrum wants to merge 9 commits intoeXist-db:developfrom
duncdrum:dp-syntax-fixes
Draft

Syntax updates#6239
duncdrum wants to merge 9 commits intoeXist-db:developfrom
duncdrum:dp-syntax-fixes

Conversation

@duncdrum
Copy link
Copy Markdown
Contributor

Large Changeset, supersedes #6226

use a number of open rewrite recipes for syntax updates, mainly

mod run . --recipe org.openrewrite.java.migrate.UpgradeToJava21

These are applied in the whole codebase, not just within files directly affected by the lucene update. I planned this as a separate PR, to facilitate review.

@duncdrum duncdrum requested a review from a team as a code owner April 14, 2026 09:35
@duncdrum
Copy link
Copy Markdown
Contributor Author

P.S.: the larger number of codacy issues, is to be expected. This PR liberally modifies legacy files, so all old issues resurface.

Copy link
Copy Markdown
Member

@dizzzz dizzzz left a comment

Choose a reason for hiding this comment

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

LGTM

- Added .moderne directory to .gitignore while excluding context and moderne.yml files to ensure proper handling of prethink output.
mod run . --recipe org.openrewrite.java.migrate.UpgradeToJava21
mostly unsorted imports, low hanging fruit to combat linter noise
- Introduced new instruction files for analyzing impact, creating organizations, creating recipes, and running recipes with OpenRewrite.
- Each file includes prerequisites, workflows, and detailed steps to guide users through various tasks related to Moderne.
- Enhanced documentation aims to improve user experience and streamline the process of utilizing Moderne tools effectively.
- Replaced traditional instanceof checks with pattern matching in several classes, including Backup, ExtArrayNodeSet, NewArrayNodeSet, and RemoteCollection, improving code readability and conciseness.
- Updated BinaryValue to ensure proper stream closure and resource management.
- Refactored ArrayType and FunHigherOrderFun for cleaner syntax and better handling of sequences.
- Enhanced error handling in various classes by utilizing try-with-resources for automatic resource management.
- Adjusted property references in the exist-installer and other modules to use prefixes.
- Cleaned up unused properties.
- consistent order of POM elements
bump outdated actions
@duncdrum duncdrum requested a review from a team April 15, 2026 11:07
Copy link
Copy Markdown
Member

@reinhapa reinhapa left a comment

Choose a reason for hiding this comment

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

There are a couple of points that need some rework:

  • Still a lot of static String constants that could be converted to text blocks in order to be better readable.
  • We need to define how he handle imports in general, as there are some places, where single imports were replaced with start imports and vice-versa.
  • There are static code validation errors, that can be solved by moving the constructor in relation of the field definition or using local variables instead of fields...

Comment on lines +303 to +308
if (aceTarget == ACLPermission.ACE_TARGET.USER) {
cmbGroupName.setEnabled(false);
cmbUsername.setEnabled(true);
} else if (aceTarget == ACLPermission.ACE_TARGET.GROUP) {
cmbUsername.setEnabled(false);
cmbGroupName.setEnabled(true);
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

All fine and good as long we have only two options. Using this way, we will silently miss a potential implementation space if an enum value is added later...

Copy link
Copy Markdown
Contributor Author

@duncdrum duncdrum Apr 17, 2026

Choose a reason for hiding this comment

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

I don't see it. The poorly formed switch without a default doesn't anticipate anything other than group or user . The if-else-if is functionally identical, removes linter noise, and is shorter. If we ever get trustees other than group or users, this code section will have to be modified one way or the other.

Comment on lines +79 to +84
if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
hitBackspace = true;
hitBackspaceOnSelection = editor.getSelectionStart() != editor.getSelectionEnd();
} else if (e.getKeyCode() == KeyEvent.VK_DELETE) {
e.consume();
comboBox.getToolkit().beep();
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I know the the default "behavior" for only two options is to go with if-else-if constructs but for my taste the new switch expression seem easier to read...

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.

s.b. we could tweak that setting, but it strikes me as a personal preference. Not sure what others think. One problem with j21 minimal switches (which I like) is that the codacy cli (on Mac) cannot parse them properly yet, so you loose analysis locally, and have to wait for CI to tell you about errors in the file.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

If Codacy on desktop can parse them or not is much less relevant than the points @reinhapa raised.
I am in favour of switching to the construct that will give us static checks if all options were handled wherever possible.

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.

my comment was about switch statements with less then two switches. @line-o happy to review your PR.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Less than two would be one or zero. I think when switching on enums the current number of options is less relevant.

Copy link
Copy Markdown
Contributor Author

@duncdrum duncdrum Apr 17, 2026

Choose a reason for hiding this comment

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

@line-o you're missing the point. I'm evaluating recipes. If the output of a recipes, will lead into an infinite cycle because our manual or automated review undoes the output that is exactly the relevant information I'm looking for.

I seem to remember you arguing for switch statements with defaults in the past. But thanks for the hints about counting.

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

the change from octal to decimal makes the code less readable in this special case of umask

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.

agreed, this is something we should try to filter from the recipe

Comment on lines +443 to +444
boolean canModify = userSelected && !SecurityManager.SYSTEM.equals(selectedUsername);
boolean canDelete = userSelected && !(SecurityManager.SYSTEM.equals(selectedUsername) || SecurityManager.DBA_USER.equals(selectedUsername) || SecurityManager.GUEST_USER.equals(selectedUsername));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe using static imports would make it even more readable

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.

It would, but that applies to both before and after. So essentially something for a future refactor.

final String selectedGroup = getSelectedGroup();

boolean canDelete = groupSelected && !(selectedGroup.equals(SecurityManager.DBA_GROUP) || selectedGroup.equals(SecurityManager.GUEST_GROUP));
boolean canDelete = groupSelected && !(SecurityManager.DBA_GROUP.equals(selectedGroup) || SecurityManager.GUEST_GROUP.equals(selectedGroup));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe using static imports would make it even more readable

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.

s.a

Comment on lines -84 to -86
// async release of collection lock
collection.close();

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Maybe this was removed unintentionally?

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.

yup static analysis

@duncdrum
Copy link
Copy Markdown
Contributor Author

@reinhapa thank you for looking into this. The idea was to get a sense of the capabilities of open rewrite and to see existing recipes in action against our code base.

The points you raise are valid. However we should clarify what our expectations are. From the time I spent with this tool I can say that the collaborative and iterative tooling for refactorings works well in principle, and is something I want to further explore and make use of (e.g. for migrating apps from exist v6 to v7).

When it comes to the output of any specific recipe run, there are a number of questions. (each commit above is a different recipe sometimes run repeatedly). The point is less that it promises to catch-em-all in a single run, but to quickly perform safe ones. It's not yet clear to me when the tool determines a textblock refactor to be safe. It clearly skips some. Generally, I don't mind that some are missed, as long as the ones which are found are actually implemented properly.

If the java21 recipe does not meet our expectations we have in principle three options.

  • we can try to figure out why and send a PR to update the recipe.
  • We can create private or public recipes that do what we want,
  • in some cases we can tweak the parameters when invoking a recipe.

The question for me really is about, is this recipe worth applying or not? To me it looks to do more good than bad overall.

as for a policy for imports, agreed. Let's discuss this in a community call, and depending on outcome we can see if we want a refractor at all, and the direction. I had to rebase this multiple times it's also possible that that introduces some regressions with star imports. The common static recipe was the least convincing and most error prone.

From a practical point of view rewrite recipes compete with other modes of enforcing code style. It's certainly not the only or best option for everything. But I see the value of having reproducible shareable and composable refactor recipes doing the heavy lifting. I'm more curious to see if I'm the only one feeling that way, or if this is something we want to explore as a group.

I m happy to drop commits from this PR, to make it a smaller change set. The gitignore and formatting commits however are important to actually use the tool without error. The pom changes seems also good. Would that be a way forward, any of the others you think are safe to pull in?

@duncdrum
Copy link
Copy Markdown
Contributor Author

duncdrum commented Apr 16, 2026

in case anybody is curious, fresh run of java21 recipe against develop:

Co-authored-by: Patrick Reinhart <patrick@reini.net>
@duncdrum duncdrum marked this pull request as draft April 17, 2026 13:43
@duncdrum
Copy link
Copy Markdown
Contributor Author

ok I want through all the comments and suggestions. The main takeaway for me is that the java21 changes are fundamentally sound. Which is good, as they are part of the upcoming java25 changes we want to tackle in the not so distant future.

The static analysis recipe is not a good match for our code. Not even going to try to adjust it to do what we want.

the instanceOf recipe is similarly sound, but has room for improvement. I think sequence matters here. It should have run before the java21 updates. Good to know.

I m going to split the work from this PR into smaller chunks.

This was referenced Apr 17, 2026
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.

4 participants