Skip to content

Add support for multiline query formatting in Query annotations#1763

Merged
BoykoAlex merged 8 commits intospring-projects:mainfrom
catturtle123:feature/multiline-text-blocks
Feb 9, 2026
Merged

Add support for multiline query formatting in Query annotations#1763
BoykoAlex merged 8 commits intospring-projects:mainfrom
catturtle123:feature/multiline-text-blocks

Conversation

@catturtle123
Copy link
Contributor

@catturtle123 catturtle123 commented Jan 23, 2026

This PR addresses issue #1726

Summary

  • Default Data Query Style Change: Changed the default query generation style to compact (single line) to ensure broader compatibility across Java versions.

  • Architectural Refinement (Interface Separation): Decoupled the query formatting logic by introducing the QueryFormatter interface with dedicated implementations (JpqlQueryFormatter, MongoQueryFormatter). This allows for repository-specific formatting strategies.

  • Robust String Escaping & Formatting:

  • Integrated StringEscapeUtils.escapeJava() to safe-guard generated queries against syntax errors.

  • Multiline Indentation: Improved Text Block generation by adding proper indentation/alignment to ensure the generated query is visually consistent with the surrounding Java code.

  • Configuration & Fallback: Updated logic to use compact and multiline keywords from UserSettings. Implemented a fallback mechanism that defaults to compact and triggers a log.warn for invalid or null inputs.

Key Changes

  • Refactoring & Logic:

  • QueryFormatter.java, JpqlQueryFormatter.java, MongoQueryFormatter.java: Separated formatting logic into an interface-based structure.

  • BootJavaConfig.java: Updated style selection and added validation/fallback logic.

  • DataRepositoryAotMetadataCodeLensProvider.java: Refactored to prioritize safety and proper indentation.

  • Test Suite Updates:

  • QueryMethodCodeActionProviderJpaTest.java & QueryMethodCodeActionProviderMongoDbTest.java: Updated to verify the output specifically for the compact style.

  • DataRepositoryAotMetadataCodeLensProviderTest.java: Added comprehensive test cases for both compact and multiline styles, verifying correct indentation.

Resolved Issues

  • Fixed Syntax Errors: Resolved IndexOutOfBoundsException by properly escaping special characters.
  • Visual Alignment: Multiline queries now include appropriate leading spaces, improving the aesthetics of the generated code.
  • Error Resilience: Prevents IDE tool failure by falling back to a safe default when configuration is missing or malformed.

Discussion Points

  • Test Coverage Asymmetry: Currently, DataRepositoryAotMetadataCodeLensProviderTest provides full coverage for both styles. However, QueryMethodCodeActionProviderJpaTest and QueryMethodCodeActionProviderMongoDbTest are currently limited to verifying the compact style. Should I expand these two classes to include multiline test cases as well to maintain consistency?
  • Fallback Strategy: Is the use of log.warn followed by a fallback to compact an acceptable approach for handling unexpected user configuration values? (Silent fallback to compact for null cases (no log.warn).)

Test

스크린샷 2026-01-24 오전 12 23 56 스크린샷 2026-01-24 오전 12 10 43 스크린샷 2026-01-24 오전 12 10 51 스크린샷 2026-01-24 오전 12 10 59 스크린샷 2026-01-24 오전 12 11 10

catturtle123 and others added 4 commits January 21, 2026 00:55
Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
- Introduce QueryFormatter interface and implementations for JPQL and MongoDB queries
- Add BootJavaConfig option to select query style (compact or multiline)
- Update code lens and code action providers to use configurable query formatting
- Enhance tests to verify multiline and compact query styles

Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
…related tests

- Remove extra indentation from multiline JPQL and Mongo query formatting
- Adjust test assertions to match new formatting without leading spaces
- Update text block generation to align closing triple quotes without indentation
- Add configuration option for data query style in package.json
- Enhance code action provider to include fix data for refactorings

Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
@martinlippert
Copy link
Member

I tried the latest version here and I do see the multiline preference working and slitting up the query statement nicely into multiple lines. But I do not see (yet) the correct formatting. Am I missing something?

@catturtle123
Copy link
Contributor Author

catturtle123 commented Feb 6, 2026

I tried the latest version here and I do see the multiline preference working and slitting up the query statement nicely into multiple lines. But I do not see (yet) the correct formatting. Am I missing something?

Thanks for trying it out! Yes, the multiline splitting itself is working — the query string gets broken into multiple lines correctly.

The formatting (indentation) issue is what I'm working on now. I actually got it working in VSCode first — the "Add Query" CodeAction triggers IDE auto-formatting, so the indentation comes out correctly there.

But then I realized this approach doesn't carry over to Eclipse. So I'm rethinking the approach — specifically how to handle formatting for the "Turn into Query" CodeLens path, since that uses workspace/applyEdit which doesn't automatically trigger IDE formatting on either side. I've got the Eclipse preference/settings wired up, but now I need to figure out how to trigger the IDE's formatter after the edit is applied so the indentation gets properly adjusted.

Working on it — will update once I have a solution that works for both VSCode and Eclipse.

@BoykoAlex
Copy link
Contributor

@catturtle123 For the IDE formatting I'd chain another command to the code action: the first add a query and the second performs the formatting. See package org.springframework.tooling.ls.eclipse.commons.commands in the org.springframework.tooling.ls.eclipse.commons plugin project in the spring-tools. It has examples of commands we've introduced for the eclipse side that we can execute from the LS. The plugin.xml has contributions of these commands into eclipse command/handler framework. There is definitely a command to format selection in the editor in Eclipse that exists already... you'd haveto find a way to bridge to it properly.
Another way to solve this would be from the OpenRewrite recipe side. The AddAnnotationOverMethod has autoFormat call however it uses the default (intelij style) formatting. Instead it should use the same formatting as the file uses. I heard OpenRewrite is able to detect the formatting of the code base and have it as marker somewhere to use in autoFormat calls. The format detection bit is missing at the moment... (I'd like to have a look at why it is missing as well)

@BoykoAlex
Copy link
Contributor

BoykoAlex commented Feb 7, 2026

@catturtle123 I've tried formatting via OpenRewrite snippet auto-format (#1775) via the recipe used to add a query. Added styling markers to parsed sources. The version of Rewrite we used didn't format string block. I've upgraded to the latest version of OpenRewrite and there is block string formatting but it's somewhat unexpected.
Therefore the command for Eclipse remains to do... There seems to be org.eclipse.ui.edit.format command but it needs a selection in the editor... Formatting should be available on the via the eclipse SourceViewer class via operation API (but I'd have to refresh my memory on that) and that likely takes the range rather than the selection.

@BoykoAlex
Copy link
Contributor

(Or maybe rebase and see how it looks. I can see the rationale behind rewrite's string block formatting)

@BoykoAlex
Copy link
Contributor

@martinlippert @catturtle123 I think I like the Rewrite's formatting for block string literals. I think it is better than what JDT produces actually. Maybe we can stop here with query split into multiple lines as Rewrite's recipe would format the string block quite well. We can continue looking into the formatting on the client but it'd mean another command which means 2. commands to undo... The formatting on the client would make more sense once we drop Rewrite in favour of JDT for quick fixes which is not too far out actually... so not sure...

Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
@catturtle123
Copy link
Contributor Author

@BoykoAlex
Sounds good — I agree that OpenRewrite's formatting is sufficient for now, and it makes sense to defer client-side formatting until the JDT transition.

I'll rebase on main (which includes #1775) and verify how the query splitting looks with the updated OpenRewrite formatting.

@catturtle123
Copy link
Contributor Author

catturtle123 commented Feb 8, 2026

I've rebased on main (which includes #1775) and tested the multiline query formatting. (I haven't pushed it yet)

Results:

  • Query splitting into multiple lines works correctly on both VSCode and Eclipse.
  • However, the text block indentation only works properly in VSCode. In Eclipse, the query is split into multiple lines but the indentation is not applied.
  • MongoDB Repository turn into query error (only multiline)

VSCode:
스크린샷 2026-02-09 오전 3 05 57
스크린샷 2026-02-09 오전 3 09 40

Eclipse:
스크린샷 2026-02-09 오전 3 06 03
스크린샷 2026-02-09 오전 3 09 30

MongoDB:
스크린샷 2026-02-09 오전 3 12 26

It seems that VSCode applies additional formatting after the edit, while Eclipse does not. This aligns with what @BoykoAlex mentioned earlier about needing a format command on the Eclipse side.

Should I look into the Eclipse format command (org.eclipse.ui.edit.format or SourceViewer operation API), or is the current state acceptable for now?

@BoykoAlex
Copy link
Contributor

BoykoAlex commented Feb 8, 2026

@catturtle123 did you rebase your branch on the latest from main? Doesn't look like you did... if you rebase on the latest commits in main I'm pretty sure the text block in Eclipse would be formatted quite nicely.

Copy link
Contributor

@BoykoAlex BoykoAlex left a comment

Choose a reason for hiding this comment

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

I'm going to push the query formatters into jpql module with #1776. I've created those formatters using AI based on the ANTLR parse tree. There are tests for the formatters. I think it'd be great if we use these formatters for the query.
I'd simplify things for now and would just do a switch on the module in the code lens class where the module is the property of aot repo metadata, an enum which is either mongo or jpa or jdbc. I'd use PostgreSqlQueryFormatter for JDBC, HQL formatter for JPA and just inline the json things for Mongo DB.
I think we can get the decent formatting from OpenRewrite.
I'd use BooleanFieldEditor for the preference UI and use boolean for multiline query on/off. There are 2 options only: single or block, i.e. text block or not.
Please rebase your PR on the latest from the main branch

CodeAction ca = new CodeAction();
ca.setCommand(refactorings.createFixCommand(TITLE, DataRepositoryAotMetadataCodeLensProvider.createFixDescriptor(mb, docUri.toASCIIString(), metadata.module(), method)));
FixDescriptor fixDescriptor = DataRepositoryAotMetadataCodeLensProvider.createFixDescriptor(mb, docUri.toASCIIString(), metadata.module(), method, config);
ca.setData(refactorings.createFixData(fixDescriptor));
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd remove the setData(...) call - it's unnecessary.

…ext-blocks

# Conflicts:
#	headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/QueryMethodCodeActionProviderJpaTest.java
Signed-off-by: Junhwan Kim <musoyou1085@gmail.com>
@catturtle123
Copy link
Contributor Author

@BoykoAlex
I've rebased my branch on the latest main and fully incorporated all your feedback. As you predicted, the text block formatting in Eclipse is now working beautifully after the rebase. I integrated the new formatters from the jpql module for JDBC, JPA, and MongoDB, and simplified the logic by switching on the module enum as suggested. I also updated the preference UI to a BooleanFieldEditor and cleaned up the unnecessary setData calls. Everything is working perfectly on my end now, so please take another look when you have a chance.

@BoykoAlex BoykoAlex marked this pull request as ready for review February 9, 2026 18:35
@BoykoAlex BoykoAlex merged commit af24404 into spring-projects:main Feb 9, 2026
1 check passed
@BoykoAlex
Copy link
Contributor

LGTM. Merging

@martinlippert
Copy link
Member

Thanks a lot @catturtle123 for working on this, for submitting the PR, and for taking all the feedback into account. Very much appreciated. Great work.

@catturtle123
Copy link
Contributor Author

catturtle123 commented Feb 10, 2026

Thank you @BoykoAlex @martinlippert! Your detailed feedback helped me improve a lot through this PR. There were many areas where my code fell short, but thanks to your patient guidance, I was able to see it through. It was a great experience contributing to Spring Tools.

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

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants