From e198cda518fdcb2e8ecf7b4e7e5d4558caa7ccdc Mon Sep 17 00:00:00 2001 From: Mikhail Pyltsin Date: Thu, 30 May 2024 16:14:38 +0200 Subject: [PATCH] [java-decompiler] IDEA-353923 Wrap return statements into braces in switch expression GitOrigin-RevId: 169162fe9d0483a39b151cbbe4a54352cc78daa0 --- .../decompiler/stats/SwitchStatement.java | 21 ++++-- .../java/decompiler/SingleClassesTest.java | 1 + .../classes/pkg/TestSwitchWrapReturn.class | Bin 0 -> 1698 bytes .../pkg/TestSwitchWrapReturnJavac$S$A.class | Bin 0 -> 1300 bytes .../pkg/TestSwitchWrapReturnJavac$S$B.class | Bin 0 -> 1300 bytes .../pkg/TestSwitchWrapReturnJavac$S$C.class | Bin 0 -> 1300 bytes .../pkg/TestSwitchWrapReturnJavac$S.class | Bin 0 -> 373 bytes .../pkg/TestSwitchWrapReturnJavac.class | Bin 0 -> 1758 bytes .../results/TestSwitchWrapReturnJavac.dec | 61 ++++++++++++++++++ .../src/pkg/TestSwitchWrapReturnJavac.java | 30 +++++++++ 10 files changed, 108 insertions(+), 5 deletions(-) create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturn.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S$A.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S$B.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S$C.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S.class create mode 100644 plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac.class create mode 100644 plugins/java-decompiler/engine/testData/results/TestSwitchWrapReturnJavac.dec create mode 100644 plugins/java-decompiler/engine/testData/src/pkg/TestSwitchWrapReturnJavac.java diff --git a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java index c56d003ed64f..168d3f01b86a 100644 --- a/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java +++ b/plugins/java-decompiler/engine/src/org/jetbrains/java/decompiler/modules/decompiler/stats/SwitchStatement.java @@ -14,10 +14,7 @@ import org.jetbrains.java.decompiler.modules.decompiler.StatEdge; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge.EdgeDirection; import org.jetbrains.java.decompiler.modules.decompiler.StatEdge.EdgeType; import org.jetbrains.java.decompiler.modules.decompiler.SwitchHelper; -import org.jetbrains.java.decompiler.modules.decompiler.exps.ConstExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.Exprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.FieldExprent; -import org.jetbrains.java.decompiler.modules.decompiler.exps.SwitchExprent; +import org.jetbrains.java.decompiler.modules.decompiler.exps.*; import org.jetbrains.java.decompiler.struct.gen.VarType; import org.jetbrains.java.decompiler.util.TextBuffer; @@ -228,7 +225,21 @@ public final class SwitchStatement extends Statement { tracer.incrementCurrentSourceLine(); } else { - buf.append(ExprProcessor.jmpWrapper(stat, canBeRule ? 0 : indent + 2, false, tracer)); + if (canBeRule && stat instanceof BasicBlockStatement blockStatement && blockStatement.getExprents() != null && + (blockStatement.getExprents().size() > 1 || + (blockStatement.getExprents().size() == 1 && + blockStatement.getExprents().get(0) instanceof ExitExprent exitExprent && + exitExprent.getExitType() == ExitExprent.EXIT_RETURN))) { + TextBuffer buffer = ExprProcessor.jmpWrapper(stat, indent + 2, false, tracer); + buf.append("{").appendLineSeparator(); + tracer.incrementCurrentSourceLine(); + buf.append(buffer).appendIndent(indent + 1).append("}").appendLineSeparator(); + tracer.incrementCurrentSourceLine(); + } + else { + TextBuffer buffer = ExprProcessor.jmpWrapper(stat, canBeRule ? 0 : indent + 2, false, tracer); + buf.append(buffer); + } } } buf.appendIndent(indent).append("}").appendLineSeparator(); diff --git a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java index 8566e2e845c9..9bebc5388e8a 100644 --- a/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/plugins/java-decompiler/engine/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -164,6 +164,7 @@ public class SingleClassesTest { @Test public void testComplexInstanceOfRecordPatternJavac() { doTest("pkg/TestComplexInstanceOfRecordPatternJavac"); } @Test public void testSwitchWithDeconstructionsWithoutNestedJavac() { doTest("pkg/TestSwitchWithDeconstructionsWithoutNestedJavac"); } @Test public void testSwitchNestedDeconstructionJavac() { doTest("pkg/TestSwitchNestedDeconstructionsJavac"); } + @Test public void testSwitchWrapReturnJavac() { doTest("pkg/TestSwitchWrapReturnJavac"); } // TODO: fix all below //@Test public void testUnionType() { doTest("pkg/TestUnionType"); } diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturn.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturn.class new file mode 100644 index 0000000000000000000000000000000000000000..c30eedbd8f3ee53325b6870b0204ec914263d8ed GIT binary patch literal 1698 zcmaJ?+j0{}5ItjE)?QY&WrM-s7~%*=7mOeYxp;v@R!mTk1VKVB7f)+>%38eIRaPS| zKah_}@sd2m6jUWV=bw_w8A%mOh3u`G?U|nLGu>x;d;k9T?VkXO*fBAMh=Hhu7~%r+ z&z$E@-gEqe{KLIxvZ(~(w_V>=cLgHpOk)Pqm@!~lI0I|Uy!NWAWSdq&k51>xeIPf; zKMGx6)l?{*wryZm;6hz?RqchVnysDC={%OI7y7AMs$e34h>0W?3@lnWi*o{JCm9Pw z6)^-ZrOT7{Q#CtNGI1Uk3@lr?h)V*C6XFptIyySfCt|vkX_)v3s|GGxxPp%bl6{|^ za=jrLU4hw9{@imzSq=PZ&+`P<(}Pq;II}Y!suoE1Cl*q;DqyNt9XVh?VCBRdN|};@ zPf6JEom3pMw*9gxJIW1w6YI$6i^~dRN5df9u76;UL{V>r!3$^4lXj+I;M&Qzuw~%- z$-6}oRSfo}z+Bn&WwqDdlVM%s3M`a^rsFl7(ADdqGOAiGSzDTTPd3roj!X8J(oaW% z9fqH2aNh|J=)X8&TVTq$DR6Njw5}(@i@j3}wzNU>6oaBRaLC39M{qk)Q%>`+;&l4? z8rWhklS`7p7+DDwlz`;Ncw$!@9~1c$xOXqkLi zIAe}=)~!8y6@wlzR_{ZHqT_irS4nbYm3&`@MbGJWCF2q`jsgd{5=8@CUOmod?7Z8V;YLFGb;3Qj{ej*%fZVFpGK2jesTbCBCBG)NO4D_8w6l3skbZ zZ?Ljcj@-$uyu}*uE0ug!2BMF*&iMw%t#?@872*i#zjE)9s77B?`FNn37IR6@S(FA@^P@P*81xA^p**&f`jXw}JLCpqX^l>p-BvFk|Q(M48 ThLWRvM7crv6Xj#n(ZKS59j2R| literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S$A.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S$A.class new file mode 100644 index 0000000000000000000000000000000000000000..f841dd6f31b69e62ecc6c55c1b8b2ffa28cc9ce4 GIT binary patch literal 1300 zcma)5+iuf95Ivil-Qbc-FAz#wC@CZxnuH5f@V;@x z4Oz;6R4~i1IJR^J^9&1PLKq@m<%z0k@xAUzgWGkz(IzeFsxb8Sfo_}b*>^@{%cOdj zCv=QqHaDbe{V`M+=5oXIFfie!9W>jQ$`G%Ku5Iu)rdyc$`fF?54WjKH4Q^LBQo$-i zW~5MR_4$oRz7#?_lE(aw%a&+5D)J0S#IP2}eLPUGuAzvBByv!Q-L<57!i!!(K9FIm zan8kX7Sv=~r{b6wy}(`FYPPwPtqO76?UVxg{L2*Z_`v$N4u8cR!!|oo*g;6StvgQ8 z;d6ZYpCp+5pF4cfR;^-L-0o9ynkuW&x1-=O!|Fi$7%d8(GAxY`rPh1Gv4I(SuQYvn z0THtFW@)`fry^OJ0iuPUU}v-m;X1AEZy<~et(q5r8(5%IiXQPz^0?p)vTmGG=s^K~ z&~_ADxqwe&aR~eh@cmNo6qbDWHYE!YMlG!MkQjxZ_hS6?6pdxvB8Dh#_w%jbPTyv6 mw{L-aWaAW3Amj{kq!NSN5NA-Os7u?lju^IcwFY-&{j({J_Iq3J9&p*Stv5tw zWb4^-DPJ2Bd!Uj_rD>SORibL^PP-ynoMCM$RniDOg-fSqoBF}(C3>$IW#{&hM8j5&GB8P?8JxiLWyyz9=0~uzT z7hDYIK~1K0CQf+K3*6JKR);&;nh+)c>OY1c{70J>J5H0)wJEu(u*J*WsyK9D4%?rQ{EYT@NkN75eT<{iIH%=+^p#a}$ zI}WZ~!e_BO0)7Sf_FwQ6R($v_B?}QoEo}6W7>8f{z-DoG lV1avN;}lUK^DSa z=Ii-NxmX(#`=GK%rD>SPRibJeZo48{oMGiss;Y-fYser=)$va~qvJAcU4{!)@UD5p zO<68}P%z7|II(mE^9&0ULKtFx<*Axw^S$0llRFKg*&!|2nlO#df#F!*IdH~g+oF1x zFX3)tC0V7ew1V8r-gMrGiz4 z+*qO1>hl|sekp`>C5`zlmu=B@!gar(0LU=a zJm+FK3v06MQ*q37KXBKuTOID^YeF3Ny5*3*;4+0g0kHA4%XheII#yQ-Ck&}{4A%`i z0*;UWl7zGWb%!t7s#R^9I|E8iQ)PAfDheJmtPZtL(4yce!_wqXYP~NU82D?+ke3`SPJ0Vlq^CRwY1hpY8-yvj|tLKG?sCT7~;4+$hU$!1DnU) lfd%f7O;SXOkTWQdN)S3q&CBCaLM7iEHmNgPc!Foh{Q(0LGF<=w literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac$S.class new file mode 100644 index 0000000000000000000000000000000000000000..c6a5637819cda76ad3d365602b4575c2c27d9416 GIT binary patch literal 373 zcmah_%TB{U3>=q|4Q+w)lp@3hAw|0z%C~Xg1NbP^DV(cX zvd53HE&J#9>l;9UQ-zk`?8$|w7iF~5XK&sgU2J@PYd(z4wL)9apD`FzrhXmVPiD?W zK}XLUZ{4`8oFKjWoL;UtbniIpdLE*}jv!k*S#b2={975Ld(q9rRwe`&6ncX5wN1Is zhYEWeC?kdb21+65-PE=7#s6M`Xe!e(q7D;4u*Daxq>XLb780mGOwl2xtaq`CeH<{l WAdAQ2FiDx=amZK`922|56J$#>(^-H3 literal 0 HcmV?d00001 diff --git a/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac.class b/plugins/java-decompiler/engine/testData/classes/pkg/TestSwitchWrapReturnJavac.class new file mode 100644 index 0000000000000000000000000000000000000000..5a7dc82400ba7b5e9cdcc1ba4c62a91d588d51dc GIT binary patch literal 1758 zcmah~TXWM!7(E+bln6PAlM+Y?0aBCtLNK(YmxxOpHxz?yD0ZF6^ht4cVi8$#z#`rG01^m}zoi6tsxk3I> z==!RrLg}<^1JeTM>$0nA&s^1PZG}$fu~fa#zt6DER4r97kwC;m5_1OTEqsF00*gml z2t*aV30zEaJprSmll6SMO_wqa6X&sP;DUvVxFnG5 z+w_#{4Y}zGOo#H}W1L0@vTOM^dS`!r+;+<4HTyFmUCB zli4tE^#n+fycL68DKJxZeOc|bcVt-C5d`MSLDTUXPU!0OP#IM%mn5D$`s{4FY&$Mb zWFh^_NbbXGG7auK;U1mLe`H%=!nrPR;b{N59~l*Bx=fO z?pK^np9ljRB;lC;WslT?Uf7g(UCrg>=JVE7-2eios%-y?)I^hm*^MAjUB$1eB2_Ec z?ast;&qN9L4Ls1@Ru)(}?3}RYE4MB4gWmh!mX3ZK?Ht#C8tlvbz~w#1-}PiSRStsv zUT3tOK5Vct!#bPX9zCPM{WA7(3=N8o=ha*#Nt9LceHj)#r`wgxOVl_D93)H>4RCq+ zu%5Aa$-~C7-2%==)pce2wGA8?0^%ae(wcxwlAEqc16P>(Q8& zYwNN2OM)W(ik4w;KF7fGuo?Ci7WlI`gH0^r0dG)UX_hJ24Dc7Vwa% {// 20 + return 1; + } + case S.B var4 -> {// 23 + return 2; + } + case S.C var5 -> {// 26 + return 3; + } + } + } + + sealed interface S { + public static record C() implements S { + } + + public static record B() implements S { + } + + public static record A() implements S { + } + } +} + +class 'TestSwitchWrapReturnJavac' { + method 'main ([Ljava/lang/String;)V' { + 0 2 + a 2 + d 2 + 10 3 + } + + method 'test (LTestSwitchWrapReturnJavac$S;)I' { + 10 6 + 3b 7 + 3c 7 + 43 10 + 44 10 + 4b 13 + 4c 13 + } +} + +Lines mapping: +14 <-> 3 +15 <-> 4 +18 <-> 7 +20 <-> 8 +23 <-> 11 +26 <-> 14 +Not mapped: +19 +22 +25 diff --git a/plugins/java-decompiler/engine/testData/src/pkg/TestSwitchWrapReturnJavac.java b/plugins/java-decompiler/engine/testData/src/pkg/TestSwitchWrapReturnJavac.java new file mode 100644 index 000000000000..f71438e1603e --- /dev/null +++ b/plugins/java-decompiler/engine/testData/src/pkg/TestSwitchWrapReturnJavac.java @@ -0,0 +1,30 @@ +class TestSwitchWrapReturnJavac { + sealed interface S { + record A() implements S { + } + + record B() implements S { + } + + record C() implements S { + } + } + + public static void main(String[] args) { + System.out.println(test(new S.A())); + } + + private static int test(S a) { + switch (a) { + case S.A a1 -> { + return 1; + } + case S.B b -> { + return 2; + } + case S.C c -> { + return 3; + } + } + } +}