Skip to content

Improving reindenter and code completion behavior for Java compact source files (JEP 512).#8676

Merged
ebarboni merged 1 commit intoapache:deliveryfrom
lahodaj:improve-compact-source-files-behavior
Jul 29, 2025
Merged

Improving reindenter and code completion behavior for Java compact source files (JEP 512).#8676
ebarboni merged 1 commit intoapache:deliveryfrom
lahodaj:improve-compact-source-files-behavior

Conversation

@lahodaj
Copy link
Contributor

@lahodaj lahodaj commented Jul 24, 2025

I was writing some compact source file (JEP 512[1]) and the reindenter was really struggling with that. Looking into it, it turned out it is because of the positions - there's a synthetic class generated, which has -1 as the end position, and moreover, even the whole CompilationUnitTree has consequently -1 as the end position(!!).

I have filled this to re-evaluate the positions for javac for the synthetic class positions:
https://bugs.openjdk.org/browse/JDK-8364015

but here, the proposal is to start with some "workarounds":

  • the start position of the synthetic class is either 0, or the end pos of the last import (a bit vaguely speaking). This allows the code completion to provide the "inside class" code completion results on more or less all relevant places in the file.
  • the end position of the CompilationUnitTree with the synthetic class is the end of the last token
  • the TreeUtilities.pathFor is adjusted to also consider the end of the last token as the end pos of the synthetic class
  • the Reindenter similarly now special-cases the end position of the synthetic class

I am a bit on the fence whether (try to) put this into NB27 or not. Suggestions welcome.

[1] https://openjdk.org/jeps/512


^Add meaningful description above

Click to collapse/expand PR instructions

By opening a pull request you confirm that, unless explicitly stated otherwise, the changes -

  • are all your own work, and you have the right to contribute them.
  • are contributed solely under the terms and conditions of the Apache License 2.0 (see section 5 of the license for more information).

Please make sure (eg. git log) that all commits have a valid name and email address for you in the Author field.

If you're a first time contributor, see the Contributing guidelines for more information.

If you're a committer, please label the PR before pressing "Create pull request" so that the right test jobs can run.

PR approval and merge checklist:

  1. Was this PR correctly labeled, did the right tests run? When did they run?
  2. Is this PR squashed?
  3. Are author name / email address correct? Are co-authors correctly listed? Do the commit messages need updates?
  4. Does the PR title and description still fit after the Nth iteration? Is the description sufficient to appear in the release notes?

If this PR targets the delivery branch: don't merge. (full wiki article)

@lahodaj lahodaj added this to the NB27 milestone Jul 24, 2025
@lahodaj lahodaj requested review from dbalek and mbien July 24, 2025 13:03
@lahodaj lahodaj added the Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form) label Jul 24, 2025
@mbien
Copy link
Member

mbien commented Jul 24, 2025

NBParserFactoryTest found a problem.

edit:

this fixes the test:

diff --git a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
index 543146d..6b47586 100644
--- a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
+++ b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
@@ -125,6 +125,7 @@
 
         Context context = new Context();
         NBParserFactory.preRegister(context);
+        NBTreeMaker.preRegister(context);
         final JavacTaskImpl ct = (JavacTaskImpl) ((JavacTool)tool).getTask(null, std, null, Arrays.asList("-source", "21"), null, Arrays.asList(new MyFileObject(code)), context);
 
         CompilationUnitTree cut = ct.parse().iterator().next();
Details
java.lang.IllegalStateException: java.lang.ClassCastException: class com.sun.tools.javac.tree.TreeMaker cannot be cast to class org.netbeans.lib.nbjavac.services.NBTreeMaker (com.sun.tools.javac.tree.TreeMaker and org.netbeans.lib.nbjavac.services.NBTreeMaker are in unnamed module of loader 'app')
  at com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:252)
  at org.netbeans.lib.nbjavac.services.NBParserFactoryTest.compile(NBParserFactoryTest.java:130)
  at org.netbeans.lib.nbjavac.services.NBParserFactoryTest.testErrorRecoveryCompactSourceFilePackage(NBParserFactoryTest.java:89)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:77)
  at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at org.netbeans.junit.NbTestCase.access$200(NbTestCase.java:84)
  at org.netbeans.junit.NbTestCase$2.doSomething(NbTestCase.java:489)
  at org.netbeans.junit.NbTestCase$1Guard.run(NbTestCase.java:410)
  at java.base/java.lang.Thread.run(Thread.java:840)
Caused by: java.lang.ClassCastException: class com.sun.tools.javac.tree.TreeMaker cannot be cast to class org.netbeans.lib.nbjavac.services.NBTreeMaker (com.sun.tools.javac.tree.TreeMaker and org.netbeans.lib.nbjavac.services.NBTreeMaker are in unnamed module of loader 'app')
  at org.netbeans.lib.nbjavac.services.NBParserFactory.<init>(NBParserFactory.java:68)
  at org.netbeans.lib.nbjavac.services.NBParserFactory$1.make(NBParserFactory.java:56)
  at org.netbeans.lib.nbjavac.services.NBParserFactory$1.make(NBParserFactory.java:53)
  at com.sun.tools.javac.util.Context.get(Context.java:149)
  at com.sun.tools.javac.parser.ParserFactory.instance(ParserFactory.java:56)
  at com.sun.tools.javac.main.JavaCompiler.<init>(JavaCompiler.java:405)
  at com.sun.tools.javac.main.JavaCompiler.instance(JavaCompiler.java:129)
  at com.sun.tools.javac.processing.JavacProcessingEnvironment.<init>(JavacProcessingEnvironment.java:213)
  at com.sun.tools.javac.processing.JavacProcessingEnvironment.instance(JavacProcessingEnvironment.java:198)
  at com.sun.tools.javac.api.BasicJavacTask.initPlugins(BasicJavacTask.java:219)
  at com.sun.tools.javac.api.JavacTaskImpl.prepareCompiler(JavacTaskImpl.java:204)
  at com.sun.tools.javac.api.JavacTaskImpl.parseInternal(JavacTaskImpl.java:257)
  at com.sun.tools.javac.api.JavacTaskImpl.invocationHelper(JavacTaskImpl.java:152)
  at com.sun.tools.javac.api.JavacTaskImpl.parse(JavacTaskImpl.java:248)

@mbien mbien added the ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) label Jul 24, 2025
@mbien
Copy link
Member

mbien commented Jul 25, 2025

I am a bit on the fence whether (try to) put this into NB27 or not. Suggestions welcome.

I think this is a good candidate for NB 27 since compact java files are now final and many will likely give them now a try if they haven't yet. This would also qualify as regression since I don't think javac 24 did use the synthetic class wrapper - so we wouldn't break our own rules by including this fix.

@lahodaj
Copy link
Contributor Author

lahodaj commented Jul 25, 2025

NBParserFactoryTest found a problem.

edit:

this fixes the test:

diff --git a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
index 543146d..6b47586 100644
--- a/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
+++ b/java/lib.nbjavac/test/unit/src/org/netbeans/lib/nbjavac/services/NBParserFactoryTest.java
@@ -125,6 +125,7 @@
 
         Context context = new Context();
         NBParserFactory.preRegister(context);
+        NBTreeMaker.preRegister(context);
         final JavacTaskImpl ct = (JavacTaskImpl) ((JavacTool)tool).getTask(null, std, null, Arrays.asList("-source", "21"), null, Arrays.asList(new MyFileObject(code)), context);
 
         CompilationUnitTree cut = ct.parse().iterator().next();

Right, sorry for that. Thanks!

FWIW, I believe even JDK 24 and before where using synthetic class for the previous round of the current compact source files, although sometimes details differed.

Copy link
Member

@mbien mbien left a comment

Choose a reason for hiding this comment

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

forgot to approve. Please squash and leave PR open as always since it targets delivery.

@lahodaj lahodaj force-pushed the improve-compact-source-files-behavior branch from 64884a6 to 0041c7c Compare July 28, 2025 05:00
@ebarboni ebarboni merged commit 1fab9a1 into apache:delivery Jul 29, 2025
36 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

ci:dev-build [ci] produce a dev-build zip artifact (7 days expiration, see link on workflow summary page) Java [ci] enable extra Java tests (java.completion, java.source.base, java.hints, refactoring.java, form)

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants