From 3a3fd48628f38e0f0f5ebf49191c5977236df457 Mon Sep 17 00:00:00 2001 From: Jan Lahoda Date: Tue, 27 Jan 2026 16:15:21 +0100 Subject: [PATCH] Cleanup: using fragments as suggested. --- .../com/sun/tools/javac/comp/Flow.java | 26 +++++++++++++-- .../tools/javac/resources/compiler.properties | 14 ++++++-- .../util/AbstractDiagnosticFormatter.java | 12 ------- .../javac/util/RichDiagnosticFormatter.java | 12 ------- .../ExhaustivenessConvenientErrors.java | 32 +++++++++---------- 5 files changed, 51 insertions(+), 45 deletions(-) diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java index 045a91d107e..f75c028dfb5 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/comp/Flow.java @@ -50,10 +50,15 @@ import static com.sun.tools.javac.code.Flags.BLOCK; import static com.sun.tools.javac.code.Kinds.Kind.*; import static com.sun.tools.javac.code.TypeTag.BOOLEAN; import static com.sun.tools.javac.code.TypeTag.VOID; +import com.sun.tools.javac.comp.ExhaustivenessComputer.BindingPattern; +import com.sun.tools.javac.comp.ExhaustivenessComputer.EnumConstantPattern; import com.sun.tools.javac.comp.ExhaustivenessComputer.ExhaustivenessResult; +import com.sun.tools.javac.comp.ExhaustivenessComputer.PatternDescription; +import com.sun.tools.javac.comp.ExhaustivenessComputer.RecordPattern; import com.sun.tools.javac.resources.CompilerProperties.Fragments; import static com.sun.tools.javac.tree.JCTree.Tag.*; import com.sun.tools.javac.util.JCDiagnostic.Fragment; +import java.util.Arrays; /** This pass implements dataflow analysis for Java programs though * different AST visitor steps. Liveness analysis (see AliveAnalyzer) checks that @@ -768,14 +773,31 @@ public class Flow { List details = exhaustivenessResult.notExhaustiveDetails() .stream() - .sorted((pd1, pd2) -> pd1.toString().compareTo(pd2.toString())) - .map(detail -> diags.fragment(Fragments.NotExhaustiveDetail(detail))) + .map(this::patternToDiagnostic) + .sorted((d1, d2) -> d1.toString() + .compareTo(d2.toString())) .collect(List.collector()); JCDiagnostic main = diags.error(null, log.currentSource(), pos, errorKey); JCDiagnostic d = new JCDiagnostic.MultilineDiagnostic(main, details); log.report(d); } + private JCDiagnostic patternToDiagnostic(PatternDescription desc) { + Type patternType = types.erasure(desc.type()); + return diags.fragment(switch (desc) { + case BindingPattern _ -> + Fragments.BindingPattern(patternType); + case RecordPattern rp -> + Fragments.RecordPattern(patternType, + Arrays.stream(rp.nested()) + .map(this::patternToDiagnostic) + .toList()); + case EnumConstantPattern ep -> + Fragments.EnumConstantPattern(patternType, + ep.enumConstant()); + }); + } + public void visitTry(JCTry tree) { ListBuffer prevPendingExits = pendingExits; pendingExits = new ListBuffer<>(); diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties index 20f5ef09dc4..b9b1825292b 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/resources/compiler.properties @@ -1485,9 +1485,17 @@ compiler.err.not.exhaustive.statement.details=\ the switch statement does not cover all possible input values\n\ missing patterns: -# 0: pattern -compiler.misc.not.exhaustive.detail=\ - {0} +# 0: type +compiler.misc.binding.pattern=\ + {0} _ + +# 0: type, 1: list of diagnostic +compiler.misc.record.pattern=\ + {0}({1}) + +# 0: type, 1: name +compiler.misc.enum.constant.pattern=\ + {0}.{1} compiler.err.initializer.must.be.able.to.complete.normally=\ initializer must be able to complete normally diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java index de0949351dc..56aa86dea86 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/AbstractDiagnosticFormatter.java @@ -234,18 +234,6 @@ public abstract class AbstractDiagnosticFormatter implements DiagnosticFormatter return messages.getLocalizedString(l, "compiler.misc.tree.tag." + StringUtils.toLowerCase(tag.name())); } - else if (arg instanceof BindingPattern bp) { - return formatArgument(d, bp.type(), l) + " _"; - } - else if (arg instanceof RecordPattern rp) { - return formatArgument(d, rp.type(), l) + - Arrays.stream(rp.nested()) - .map(pd -> formatArgument(d, pd, l)) - .collect(Collectors.joining(", ", "(", ")")); - } - else if (arg instanceof EnumConstantPattern ep) { - return formatArgument(d, ep.type(), l) + "." + ep.enumConstant(); - } else { return String.valueOf(arg); } diff --git a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java index e44d99e7188..23c87c9310f 100644 --- a/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java +++ b/src/jdk.compiler/share/classes/com/sun/tools/javac/util/RichDiagnosticFormatter.java @@ -212,7 +212,6 @@ public class RichDiagnosticFormatter extends * @param arg the argument to be translated */ protected void preprocessArgument(Object arg) { - //TODO: preprocess for patterns if (arg instanceof Type type) { preprocessType(type); } @@ -230,17 +229,6 @@ public class RichDiagnosticFormatter extends preprocessArgument(o); } } - else if (arg instanceof BindingPattern bp) { - preprocessArgument(bp.type()); - } - else if (arg instanceof RecordPattern rp) { - preprocessArgument(rp.type()); - Arrays.stream(rp.nested()) - .forEach(this::preprocessArgument); - } - else if (arg instanceof EnumConstantPattern ep) { - preprocessArgument(ep.type()); - } } /** diff --git a/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java b/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java index 32b1d6eab55..16a5a97c59c 100644 --- a/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java +++ b/test/langtools/tools/javac/patterns/ExhaustivenessConvenientErrors.java @@ -206,8 +206,8 @@ public class ExhaustivenessConvenientErrors extends TestRunner { } } """, - "lib.R(lib.A _, lib.A _)", - "lib.R(lib.B _, lib.B _)"); + "lib.R(lib.A _,lib.A _)", + "lib.R(lib.B _,lib.B _)"); } @Test @@ -230,8 +230,8 @@ public class ExhaustivenessConvenientErrors extends TestRunner { record Root(Base b1, Base b2, Base b3) {} } """, - "test.Test.Root(test.Test.R2 _, test.Test.Base _, test.Test.Base _)", - "test.Test.Root(test.Test.R3 _, test.Test.Base _, test.Test.Base _)"); + "test.Test.Root(test.Test.R2 _,test.Test.Base _,test.Test.Base _)", + "test.Test.Root(test.Test.R3 _,test.Test.Base _,test.Test.Base _)"); } @Test @@ -271,7 +271,7 @@ public class ExhaustivenessConvenientErrors extends TestRunner { record Root(Base b1, Base b2, Base b3) {} } """, - "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.R2 _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.R2 _))"); + "test.Test.Root(test.Test.R2 _,test.Test.R2(test.Test.R2 _,test.Test.R2 _),test.Test.R2(test.Test.R2 _,test.Test.R2 _))"); } @Test @@ -308,7 +308,7 @@ public class ExhaustivenessConvenientErrors extends TestRunner { record NestedBaseC() implements NestedBase {} } """, - "test.Test.Triple(test.Test.A _, test.Test.C(test.Test.Nested _, test.Test.NestedBaseC _), test.Test.C(test.Test.Nested _, test.Test.NestedBaseC _))"); + "test.Test.Triple(test.Test.A _,test.Test.C(test.Test.Nested _,test.Test.NestedBaseC _),test.Test.C(test.Test.Nested _,test.Test.NestedBaseC _))"); } @Test @@ -348,10 +348,10 @@ public class ExhaustivenessConvenientErrors extends TestRunner { record Root(Base b1, Base b2, Base b3) {} } """, - "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.Base _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.Base _))"); - //ideally, the result would be as follow, but it is difficult to split Base on two distinct places: -// "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.R1 _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.R1 _))", -// "test.Test.Root(test.Test.R2 _, test.Test.R2(test.Test.R2 _, test.Test.R2 _), test.Test.R2(test.Test.R2 _, test.Test.R2 _))"); + "test.Test.Root(test.Test.R2 _,test.Test.R2(test.Test.Base _,test.Test.R2 _),test.Test.R2(test.Test.R2 _,test.Test.Base _))"); + //ideally,the result would be as follow,but it is difficult to split Base on two distinct places: +// "test.Test.Root(test.Test.R2 _,test.Test.R2(test.Test.R1 _,test.Test.R2 _),test.Test.R2(test.Test.R2 _,test.Test.R1 _))", +// "test.Test.Root(test.Test.R2 _,test.Test.R2(test.Test.R2 _,test.Test.R2 _),test.Test.R2(test.Test.R2 _,test.Test.R2 _))"); } @Test @@ -388,10 +388,10 @@ public class ExhaustivenessConvenientErrors extends TestRunner { record NestedBaseC() implements NestedBase {} } """, - "test.Test.Triple(test.Test.A _, test.Test.C(test.Test.Nested _, test.Test.NestedBaseA _), test.Test.C _)", + "test.Test.Triple(test.Test.A _,test.Test.C(test.Test.Nested _,test.Test.NestedBaseA _),test.Test.C _)", //the following could be: - //test.Test.Triple(test.Test.A _, test.Test.C(test.Test.Nested _, test.Test.NestedBaseC _), test.Test.C(test.Test.Nested _, test.Test.NestedBaseC _)) - "test.Test.Triple(test.Test.A _, test.Test.C(test.Test.Nested _, test.Test.NestedBaseC _), test.Test.C _)"); + //test.Test.Triple(test.Test.A _,test.Test.C(test.Test.Nested _,test.Test.NestedBaseC _),test.Test.C(test.Test.Nested _,test.Test.NestedBaseC _)) + "test.Test.Triple(test.Test.A _,test.Test.C(test.Test.Nested _,test.Test.NestedBaseC _),test.Test.C _)"); } @Test @@ -410,7 +410,7 @@ public class ExhaustivenessConvenientErrors extends TestRunner { } public record R(R r1, R r2, R r3, Object o) {} """, - "test.R(test.R _, test.R _, test.R(test.R _, test.R _, test.R _, java.lang.Object _), java.lang.Object _)"); + "test.R(test.R _,test.R _,test.R(test.R _,test.R _,test.R _,java.lang.Object _),java.lang.Object _)"); } @Test @@ -527,7 +527,7 @@ public class ExhaustivenessConvenientErrors extends TestRunner { } } """, - "Test.Pair(Test.Pair(Test.Pair _, Test.Base _), Test.Pair(Test.Pair(Test.Pair _, Test.Base _), Test.Base _))"); + "Test.Pair(Test.Pair(Test.Pair _,Test.Base _),Test.Pair(Test.Pair(Test.Pair _,Test.Base _),Test.Base _))"); } private void doTest(Path base, String[] libraryCode, String testCode, String... expectedMissingPatterns) throws IOException { @@ -576,7 +576,7 @@ public class ExhaustivenessConvenientErrors extends TestRunner { if (d instanceof JCDiagnostic.MultilineDiagnostic diag) { diag.getSubdiagnostics() .stream() - .map(fragment -> fragment.getArgs()[0].toString()) + .map(fragment -> fragment.toString()) .forEach(missingPatterns::add); } }