Add support for multiline query formatting in Query annotations#1763
Conversation
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>
|
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. |
|
@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 |
|
@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. |
|
(Or maybe rebase and see how it looks. I can see the rationale behind rewrite's string block formatting) |
|
@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>
|
@BoykoAlex I'll rebase on main (which includes #1775) and verify how the query splitting looks with the updated OpenRewrite formatting. |
|
I've rebased on main (which includes #1775) and tested the multiline query formatting. (I haven't pushed it yet) Results:
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? |
|
@catturtle123 did you rebase your branch on the latest from |
There was a problem hiding this comment.
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
...rver/src/main/java/org/springframework/ide/vscode/boot/java/rewrite/RewriteRefactorings.java
Show resolved
Hide resolved
| 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)); |
There was a problem hiding this comment.
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>
|
@BoykoAlex |
|
LGTM. Merging |
|
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. |
|
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. |





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
QueryFormatterinterface 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
compactandmultilinekeywords fromUserSettings. Implemented a fallback mechanism that defaults tocompactand triggers alog.warnfor invalid ornullinputs.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 thecompactstyle.DataRepositoryAotMetadataCodeLensProviderTest.java: Added comprehensive test cases for bothcompactandmultilinestyles, verifying correct indentation.Resolved Issues
IndexOutOfBoundsExceptionby properly escaping special characters.Discussion Points
DataRepositoryAotMetadataCodeLensProviderTestprovides full coverage for both styles. However,QueryMethodCodeActionProviderJpaTestandQueryMethodCodeActionProviderMongoDbTestare currently limited to verifying thecompactstyle. Should I expand these two classes to includemultilinetest cases as well to maintain consistency?log.warnfollowed by a fallback tocompactan acceptable approach for handling unexpected user configuration values? (Silent fallback to compact for null cases (no log.warn).)Test