From 392b3405eb28d5af5790ebfa8d5052b485f556d2 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Mon, 1 Jun 2026 12:24:08 +0100 Subject: [PATCH 1/2] Fix reformatting to keep empty body records. Special case reformatting of empty body records without whitespace (eg. record Foo(int x) {} ) to not insert lines and keep body as is. The behaviour is only changed for default same-line brace handling. --- .../modules/java/source/save/Reformatter.java | 66 ++-- .../java/source/save/FormatingTest.java | 325 +++++++++--------- 2 files changed, 197 insertions(+), 194 deletions(-) diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java index 0070d2581374..c116cbc57242 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java @@ -1363,7 +1363,39 @@ private Boolean scanRecord(ClassTree node, Void p) { int oldLastIndent = lastIndent; int lastMaxPreservedBlankLines = maxPreservedBlankLines; maxPreservedBlankLines = cs.getMaximumBlankLinesInDeclarations(); - classLeftBracePlacement(); + + CodeStyle.BracePlacement bracePlacement = cs.getClassDeclBracePlacement(); + boolean spaceBeforeLeftBrace = cs.spaceBeforeClassDeclLeftBrace(); + switch (bracePlacement) { + case SAME_LINE: + spaces(spaceBeforeLeftBrace ? 1 : 0, tokens.offset() < startOffset); + accept(LBRACE); + if (tokens.token().id() == RBRACE) { + accept(RBRACE); + indent = oldIndent; + lastIndent = oldLastIndent; + return true; + } + indent = lastIndent + indentSize; + break; + case NEW_LINE: + newline(); + accept(LBRACE); + indent = lastIndent + indentSize; + break; + case NEW_LINE_HALF_INDENTED: + int oldLast = lastIndent; + indent = lastIndent + (indentSize >> 1); + newline(); + accept(LBRACE); + indent = oldLast + indentSize; + break; + case NEW_LINE_INDENTED: + indent = lastIndent + indentSize; + newline(); + accept(LBRACE); + break; + } continuationIndent = old; try { @@ -1414,38 +1446,6 @@ private Boolean scanRecord(ClassTree node, Void p) { return true; } - private void classLeftBracePlacement() { - CodeStyle.BracePlacement bracePlacement = cs.getClassDeclBracePlacement(); - boolean spaceBeforeLeftBrace = cs.spaceBeforeClassDeclLeftBrace(); - int old = indent = lastIndent; - int halfIndent = lastIndent; - switch (bracePlacement) { - case SAME_LINE: - spaces(spaceBeforeLeftBrace ? 1 : 0, tokens.offset() < startOffset); - accept(LBRACE); - indent = lastIndent + indentSize; - break; - case NEW_LINE: - newline(); - accept(LBRACE); - indent = lastIndent + indentSize; - break; - case NEW_LINE_HALF_INDENTED: - int oldLast = lastIndent; - indent = lastIndent + (indentSize >> 1); - halfIndent = indent; - newline(); - accept(LBRACE); - indent = oldLast + indentSize; - break; - case NEW_LINE_INDENTED: - indent = lastIndent + indentSize; - halfIndent = indent; - newline(); - accept(LBRACE); - break; - } - } @Override public Boolean visitMethod(MethodTree node, Void p) { diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java index 513a2132b962..26d43b136fbc 100644 --- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java +++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java @@ -3429,33 +3429,33 @@ public void testNormalRecordPattern() throws Exception { EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); - String content = "package test;\n" - + "record Point(int x, int y){}\n" - + "public class Test {\n" - + " private void test(Object o) {\n" - + " if (o instanceof Point\n" - + " (int x, int \n" - + " y) ) {\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}"; + String content = """ + package test; + record Point(int x, int y){} + public class Test { + private void test(Object o) { + if (o instanceof Point + (int x, int + y) ) { + System.out.println("Hello"); + } + } + }"""; - String golden = "package test;\n" - + "\n" - + "record Point(int x, int y) {\n" - + "\n" - + "}\n" - + "\n" - + "public class Test {\n" - + "\n" - + " private void test(Object o) {\n" - + " if (o instanceof Point(int x, int y)) {\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}" - + "\n"; + String golden = """ + package test; + + record Point(int x, int y) {} + + public class Test { + + private void test(Object o) { + if (o instanceof Point(int x, int y)) { + System.out.println("Hello"); + } + } + } + """; reformat(doc, content, golden); } @@ -3473,54 +3473,50 @@ public void testNestedRecordPattern() throws Exception { EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); - String content = "package test;\n" - + "\n" - + "record Rect(ColoredPoint ul,ColoredPoint lr) {}\n" - + "enum Color {RED,GREEN,BLUE}\n" - + "record ColoredPoint(Point p, Color c) {}\n" - + "record Point(int x, int y) {}\n" - + "\n" - + "public class Test {\n" - + "\n" - + " private void test(Object o) {\n" - + " if (o instanceof\n" - + " Rect\n" - + " ( ColoredPoint ul, ColoredPoint\n" - + " lr) ) {\n" - + " Point p = ul.p();\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}"; + String content = """ + package test; + + record Rect(ColoredPoint ul,ColoredPoint lr) {} + enum Color {RED,GREEN,BLUE} + record ColoredPoint(Point p, Color c) {} + record Point(int x, int y) {} + + public class Test { + + private void test(Object o) { + if (o instanceof + Rect + ( ColoredPoint ul, ColoredPoint + lr) ) { + Point p = ul.p(); + System.out.println("Hello"); + } + } + }"""; - String golden = "package test;\n" - + "\n" - + "record Rect(ColoredPoint ul, ColoredPoint lr) {\n" - + "\n" - + "}\n" - + "\n" - + "enum Color {\n" - + " RED, GREEN, BLUE\n" - + "}\n" - + "\n" - + "record ColoredPoint(Point p, Color c) {\n" - + "\n" - + "}\n" - + "\n" - + "record Point(int x, int y) {\n" - + "\n" - + "}\n" - + "\n" - + "public class Test {\n" - + "\n" - + " private void test(Object o) {\n" - + " if (o instanceof Rect(ColoredPoint ul, ColoredPoint lr)) {\n" - + " Point p = ul.p();\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}" - + "\n"; + String golden = """ + package test; + + record Rect(ColoredPoint ul, ColoredPoint lr) {} + + enum Color { + RED, GREEN, BLUE + } + + record ColoredPoint(Point p, Color c) {} + + record Point(int x, int y) {} + + public class Test { + + private void test(Object o) { + if (o instanceof Rect(ColoredPoint ul, ColoredPoint lr)) { + Point p = ul.p(); + System.out.println("Hello"); + } + } + } + """; reformat(doc, content, golden); } @@ -3538,58 +3534,54 @@ public void testMultipleNestingRecordPattern() throws Exception { EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); - String content = "package test;\n" - + "\n" - + "record Rect(ColoredPoint ul,ColoredPoint lr) {}\n" - + "enum Color {RED,GREEN,BLUE}\n" - + "record ColoredPoint(Point p, Color c) {}\n" - + "record Point(int x, int y) {}\n" - + "\n" - + "public class Test {\n" - + "\n" - + " private void test(Object o) {\n" - + " if (o instanceof\n" - + " Rect\n" - + " ( ColoredPoint(Point \n" - + " p, Color \n" - + " c\n" - + " ) , ColoredPoint\n" - + " lr) \n" - + " ) {\n" - + " int x = p.x();\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}"; + String content = """ + package test; + + record Rect(ColoredPoint ul,ColoredPoint lr) {} + enum Color {RED,GREEN,BLUE} + record ColoredPoint(Point p, Color c) {} + record Point(int x, int y) {} + + public class Test { + + private void test(Object o) { + if (o instanceof + Rect + ( ColoredPoint(Point + p, Color + c + ) , ColoredPoint + lr) + ) { + int x = p.x(); + System.out.println("Hello"); + } + } + }"""; - String golden = "package test;\n" - + "\n" - + "record Rect(ColoredPoint ul, ColoredPoint lr) {\n" - + "\n" - + "}\n" - + "\n" - + "enum Color {\n" - + " RED, GREEN, BLUE\n" - + "}\n" - + "\n" - + "record ColoredPoint(Point p, Color c) {\n" - + "\n" - + "}\n" - + "\n" - + "record Point(int x, int y) {\n" - + "\n" - + "}\n" - + "\n" - + "public class Test {\n" - + "\n" - + " private void test(Object o) {\n" - + " if (o instanceof Rect(ColoredPoint(Point p, Color c), ColoredPoint lr)) {\n" - + " int x = p.x();\n" - + " System.out.println(\"Hello\");\n" - + " }\n" - + " }\n" - + "}" - + "\n"; + String golden = """ + package test; + + record Rect(ColoredPoint ul, ColoredPoint lr) {} + + enum Color { + RED, GREEN, BLUE + } + + record ColoredPoint(Point p, Color c) {} + + record Point(int x, int y) {} + + public class Test { + + private void test(Object o) { + if (o instanceof Rect(ColoredPoint(Point p, Color c), ColoredPoint lr)) { + int x = p.x(); + System.out.println("Hello"); + } + } + } + """; reformat(doc, content, golden); } @@ -3607,26 +3599,24 @@ public void testAnnotatedRecord() throws Exception { EditorCookie ec = (EditorCookie) testSourceDO.getLookup().lookup(EditorCookie.class); final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); - String content = - "package test;\n" - + "\n" - + "/**\n" - + " * @author duke\n" - + " */\n" - + "@Deprecated public record DeprecatedRecord(int a) {}" - + "\n"; + String content = """ + package test; + + /** + * @author duke + */ + @Deprecated public record DeprecatedRecord(int a) {} + """; - String golden = - "package test;\n" - + "\n" - + "/**\n" - + " * @author duke\n" - + " */\n" - + "@Deprecated\n" - + "public record DeprecatedRecord(int a) {\n" - + "\n" - + "}" - + "\n"; + String golden = """ + package test; + + /** + * @author duke + */ + @Deprecated + public record DeprecatedRecord(int a) {} + """; reformat(doc, content, golden); } @@ -6754,16 +6744,22 @@ public void testRecord3() throws Exception { final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); String content - = "package hierbas.del.litoral;\n\n" - + "public class Test {\n\n" - + "public record g3(){}}"; - + = """ + package hierbas.del.litoral; + + public class Test { + + public record g3(){}}"""; + String golden - = "package hierbas.del.litoral;\n\n" - + "public class Test {\n\n" - + " public record g3() {\n" - + " }\n" - + "}\n"; + = """ + package hierbas.del.litoral; + + public class Test { + + public record g3() {} + } + """; reformat(doc, content, golden); } @@ -6784,15 +6780,22 @@ public void testRecord4() throws Exception { EditorCookie ec = (EditorCookie) testSourceDO.getCookie(EditorCookie.class); final Document doc = ec.openDocument(); doc.putProperty(Language.class, JavaTokenId.language()); - String content = "package hierbas.del.litoral;\n\n" - + "public class Test {\n\n" - + "public record g3(@Override int a, @Override int b){}}"; - String golden - = "package hierbas.del.litoral;\n\n" - + "public class Test {\n\n" - + " public record g3(@Override int a, @Override int b) {\n\n" - + " }\n" - + "}\n"; + String content = """ + package hierbas.del.litoral; + + public class Test { + + public record g3(@Override int a, @Override int b){ }}"""; + String golden = """ + package hierbas.del.litoral; + + public class Test { + + public record g3(@Override int a, @Override int b) { + + } + } + """; reformat(doc, content, golden); } From 5dcc7267c511b3ffeece7b57b2f3e1f6f7fb58a7 Mon Sep 17 00:00:00 2001 From: Neil C Smith Date: Mon, 1 Jun 2026 12:45:30 +0100 Subject: [PATCH 2/2] Fix continuation indenting with nested lambdas. Fix continuation indenting with nested lambdas being the same by not specifying a specific indent. This already works correctly when wrapAfterLambdaArrow is set. This fixes the default behaviour. --- .../modules/java/source/save/Reformatter.java | 2 +- .../java/source/save/FormatingTest.java | 43 +++++++++++++++++++ 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java index c116cbc57242..973cedecb9b4 100644 --- a/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java +++ b/java/java.source.base/src/org/netbeans/modules/java/source/save/Reformatter.java @@ -2220,7 +2220,7 @@ public Boolean visitLambdaExpression(LambdaExpressionTree node, Void p) { } } try { - wrapOperatorAndTree(cs.wrapLambdaArrow(), -1, cs.spaceAroundLambdaArrow() ? 1 : 0, cs.spaceAroundLambdaArrow() ? 1 : 0, lastIndent, node.getBody()); + wrapOperatorAndTree(cs.wrapLambdaArrow(), -1, cs.spaceAroundLambdaArrow() ? 1 : 0, cs.spaceAroundLambdaArrow() ? 1 : 0, -1, node.getBody()); } finally { continuationIndent = old; indent = oldIndent; diff --git a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java index 26d43b136fbc..fb1dbcf5dac4 100644 --- a/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java +++ b/java/java.source.base/test/unit/src/org/netbeans/modules/java/source/save/FormatingTest.java @@ -6200,6 +6200,49 @@ public void test231874() throws Exception { reformat(doc, content, golden); } + public void testLambdaNesting() throws Exception { + testFile = new File(getWorkDir(), "Test.java"); + TestUtilities.copyStringToFile(testFile, ""); + FileObject testSourceFO = FileUtil.toFileObject(testFile); + DataObject testSourceDO = DataObject.find(testSourceFO); + EditorCookie ec = (EditorCookie)testSourceDO.getCookie(EditorCookie.class); + final Document doc = ec.openDocument(); + doc.putProperty(Language.class, JavaTokenId.language()); + String content = + """ + package hierbas.del.litoral; + + public class Test { + + public static void main(String[] args) { + List lines = Stream.of(args) + .flatMap(s -> s.lines() + .filter(l -> !l.isBlank()) + ).toList(); + } + } + """; + + String golden = + """ + package hierbas.del.litoral; + + public class Test { + + public static void main(String[] args) { + List lines = Stream.of(args) + .flatMap(s -> s.lines() + .filter(l -> !l.isBlank()) + ).toList(); + } + } + """; + reformat(doc, content, golden); + reformat(doc, golden, golden); + + + } + public void testLambdaParameterWithInferredType() throws Exception { testFile = new File(getWorkDir(), "Test.java"); TestUtilities.copyStringToFile(testFile, "");