From e4e72404dcca533c0cbaece10624414ea3586bf1 Mon Sep 17 00:00:00 2001 From: Sebastian Zarnekow Date: Tue, 9 Jun 2015 15:34:08 +0300 Subject: [PATCH] Fixed Fernflower decompiler output for generic nested types (IDEA-141230) https://github.com/JetBrains/intellij-community/pull/273 --- .../struct/gen/generics/GenericMain.java | 92 ++++++++++-------- .../java/decompiler/SingleClassesTest.java | 1 + .../pkg/TestParameterizedTypes$Inner.class | Bin 0 -> 642 bytes .../classes/pkg/TestParameterizedTypes.class | Bin 0 -> 776 bytes testData/results/TestParameterizedTypes.dec | 11 +++ testData/src/pkg/TestParameterizedTypes.java | 26 +++++ 6 files changed, 89 insertions(+), 41 deletions(-) create mode 100644 testData/classes/pkg/TestParameterizedTypes$Inner.class create mode 100644 testData/classes/pkg/TestParameterizedTypes.class create mode 100644 testData/results/TestParameterizedTypes.dec create mode 100644 testData/src/pkg/TestParameterizedTypes.java diff --git a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java index 2992078..0a3f9d3 100644 --- a/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java +++ b/src/org/jetbrains/java/decompiler/struct/gen/generics/GenericMain.java @@ -1,5 +1,5 @@ /* - * Copyright 2000-2014 JetBrains s.r.o. + * Copyright 2000-2015 JetBrains s.r.o. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -18,7 +18,6 @@ package org.jetbrains.java.decompiler.struct.gen.generics; import org.jetbrains.java.decompiler.code.CodeConstants; import org.jetbrains.java.decompiler.main.DecompilerContext; import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger; -import org.jetbrains.java.decompiler.struct.StructClass; import java.util.ArrayList; import java.util.List; @@ -193,57 +192,68 @@ public class GenericMain { } else if (tp == CodeConstants.TYPE_OBJECT) { StringBuilder buffer = new StringBuilder(); - buffer.append(DecompilerContext.getImportCollector().getShortName(buildJavaClassName(type))); + appendClassName(type, buffer); + return buffer.toString(); + } - if (!type.getArguments().isEmpty()) { - buffer.append("<"); - for (int i = 0; i < type.getArguments().size(); i++) { - if (i > 0) { - buffer.append(", "); - } - int wildcard = type.getWildcards().get(i); - if (wildcard != GenericType.WILDCARD_NO) { - buffer.append("?"); - - switch (wildcard) { - case GenericType.WILDCARD_EXTENDS: - buffer.append(" extends "); - break; - case GenericType.WILDCARD_SUPER: - buffer.append(" super "); - } - } + throw new RuntimeException("Invalid type: " + type); + } - GenericType genPar = type.getArguments().get(i); - if (genPar != null) { - buffer.append(getGenericCastTypeName(genPar)); - } + private static void appendClassName(GenericType type, StringBuilder buffer) { + List enclosingClasses = type.getEnclosingClasses(); + + if (enclosingClasses.isEmpty()) { + String name = type.value.replace('/', '.'); + buffer.append(DecompilerContext.getImportCollector().getShortName(name)); + } + else { + for (GenericType tp : enclosingClasses) { + if (buffer.length() == 0) { + buffer.append(DecompilerContext.getImportCollector().getShortName(tp.value)); + } + else { + buffer.append(tp.value); } - buffer.append(">"); + + appendTypeArguments(tp, buffer); + buffer.append('.'); } - return buffer.toString(); + buffer.append(type.value); } - throw new RuntimeException("Invalid type: " + type); + appendTypeArguments(type, buffer); } - private static String buildJavaClassName(GenericType type) { - String name = ""; - for (GenericType tp : type.getEnclosingClasses()) { - name += tp.value + "$"; - } - name += type.value; + private static void appendTypeArguments(GenericType type, StringBuilder buffer) { + if (!type.getArguments().isEmpty()) { + buffer.append('<'); + + for (int i = 0; i < type.getArguments().size(); i++) { + if (i > 0) { + buffer.append(", "); + } - String res = name.replace('/', '.'); + int wildcard = type.getWildcards().get(i); + switch (wildcard) { + case GenericType.WILDCARD_UNBOUND: + buffer.append('?'); + break; + case GenericType.WILDCARD_EXTENDS: + buffer.append("? extends "); + break; + case GenericType.WILDCARD_SUPER: + buffer.append("? super "); + break; + } - if (res.contains("$")) { - StructClass cl = DecompilerContext.getStructContext().getClass(name); - if (cl == null || !cl.isOwn()) { - res = res.replace('$', '.'); + GenericType genPar = type.getArguments().get(i); + if (genPar != null) { + buffer.append(getGenericCastTypeName(genPar)); + } } - } - return res; + buffer.append(">"); + } } } diff --git a/test/org/jetbrains/java/decompiler/SingleClassesTest.java b/test/org/jetbrains/java/decompiler/SingleClassesTest.java index d8f6bee..e85cd67 100644 --- a/test/org/jetbrains/java/decompiler/SingleClassesTest.java +++ b/test/org/jetbrains/java/decompiler/SingleClassesTest.java @@ -60,4 +60,5 @@ public class SingleClassesTest extends SingleClassesTestBase { @Test public void testInnerLocal() { doTest("pkg/TestInnerLocal"); } @Test public void testInnerLocalPkg() { doTest("pkg/TestInnerLocalPkg"); } @Test public void testInnerSignature() { doTest("pkg/TestInnerSignature"); } + @Test public void testParameterizedTypes() { doTest("pkg/TestParameterizedTypes"); } } diff --git a/testData/classes/pkg/TestParameterizedTypes$Inner.class b/testData/classes/pkg/TestParameterizedTypes$Inner.class new file mode 100644 index 0000000000000000000000000000000000000000..55f1d4cd6538a1400040bba8710b1dc2aa630390 GIT binary patch literal 642 zcmaJ;O;5r=5PeGvm0AT+Q32yeI3ODE;K??#|?`2TFWGFe)he6#HLD=Fx zAB#}<@>%rVr>O``;#ty@q0MkqSw%eSFsO}5Uod1G>51FfxGQ{@cSqF8Ig=hAb+|7h zylASC0fuDL^Mub}#JMrzK_IAoy5h2OOeJsmpSt9Dp?$Gp+HzZ_U5h0ww`tm>lWxm_ z$HSRVUMp7f+8OdkULSF9P`~RAMK3h%zbyv6J(>AEaU-KQ7XRO1Es`>jM9P4MqJ|Q~ z@$!YwpT>~=?SMh4L_01lpH)xjlU4d}md!>NMim_mYZTLjT1e0V^y>L5SoIBw7eWej xiYej%J6NZfpR-^fLx}jX8kwTnhDt&63QwwUN&c{1_f2l!FO zX-gtRX%9P{nfK<+%38%>1a zwYz^q45~g`IEJ{E{>_yCUwqRaBZCyS7)qP(havYnZ>Y&|x)~oXSE(XK@5}$^Q zY4WbfGO~%Ycd)l0t { + abstract TestParameterizedTypes

.Inner getUnspecificInner(); + + abstract TestParameterizedTypes.Inner getSpecificInner(); + + public abstract class Inner { + } +} + diff --git a/testData/src/pkg/TestParameterizedTypes.java b/testData/src/pkg/TestParameterizedTypes.java new file mode 100644 index 0000000..490869e --- /dev/null +++ b/testData/src/pkg/TestParameterizedTypes.java @@ -0,0 +1,26 @@ +/* + * Copyright 2000-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package pkg; + +public abstract class TestParameterizedTypes

{ + + public abstract class Inner { } + + abstract Inner getUnspecificInner(); + + abstract TestParameterizedTypes.Inner getSpecificInner(); + +} \ No newline at end of file