Skip to content

Commit 5f8fd42

Browse files
authored
Merge pull request #522 from Bl3nd/go-to-enhancement
Inner classes and a few additions to the parser
2 parents edadceb + 9356ebf commit 5f8fd42

File tree

10 files changed

+507
-77
lines changed

10 files changed

+507
-77
lines changed

src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/FernFlowerDecompiler.java

+138-24
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,23 @@
2222
import org.apache.commons.lang3.ArrayUtils;
2323
import org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler;
2424
import org.objectweb.asm.tree.ClassNode;
25+
import org.objectweb.asm.tree.InnerClassNode;
2526
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
2627
import the.bytecode.club.bytecodeviewer.Constants;
28+
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
2729
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
2830
import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler;
2931
import the.bytecode.club.bytecodeviewer.resources.ExternalResources;
32+
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
3033
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
3134
import the.bytecode.club.bytecodeviewer.util.ExceptionUtils;
3235
import the.bytecode.club.bytecodeviewer.util.ProcessUtils;
3336
import the.bytecode.club.bytecodeviewer.util.TempFile;
3437

3538
import java.io.*;
39+
import java.util.ArrayList;
40+
import java.util.List;
41+
import java.util.concurrent.atomic.AtomicReference;
3642

3743
import static the.bytecode.club.bytecodeviewer.Constants.*;
3844
import static the.bytecode.club.bytecodeviewer.translation.TranslatedStrings.*;
@@ -51,12 +57,67 @@ public FernFlowerDecompiler()
5157
super("FernFlower Decompiler", "fernflower");
5258
}
5359

60+
private String[] inners;
61+
private final List<File> innerFiles = new ArrayList<>();
62+
5463
@Override
5564
public String decompileClassNode(ClassNode cn, byte[] bytes)
5665
{
5766
TempFile tempFile = null;
5867
String exception;
5968

69+
List<InnerClassNode> innerClasses = cn.innerClasses;
70+
List<TempFile> innerTempFiles = new ArrayList<>();
71+
AtomicReference<TempFile> innerTempFile = new AtomicReference<>();
72+
if (BytecodeViewer.viewer.din.isSelected())
73+
{
74+
inners = new String[innerClasses.size()];
75+
for (int i = 0; i < innerClasses.size(); i++)
76+
{
77+
if (innerClasses.get(i).outerName != null && innerClasses.get(i).outerName.equals(cn.name))
78+
{
79+
inners[i] = innerClasses.get(i).name;
80+
}
81+
else if (innerClasses.get(i).outerName == null)
82+
{
83+
String name = innerClasses.get(i).name;
84+
name = name.substring(name.lastIndexOf('/') + 1);
85+
if (name.contains(cn.name.substring(cn.name.lastIndexOf('/') + 1)))
86+
{
87+
inners[i] = innerClasses.get(i).name;
88+
}
89+
}
90+
}
91+
92+
for (ResourceContainer container : BytecodeViewer.resourceContainers.values())
93+
{
94+
container.resourceClasses.forEach((s, classNode) -> {
95+
for (String innerClassName : inners)
96+
{
97+
if (s.equals(innerClassName))
98+
{
99+
innerTempFile.set(TempFile.createTemporaryFile(true, ".class"));
100+
File tempInputClassFile2 = innerTempFile.get().getFile();
101+
try (FileOutputStream fos = new FileOutputStream(tempInputClassFile2))
102+
{
103+
fos.write(ASMUtil.nodeToBytes(classNode));
104+
}
105+
catch (IOException e)
106+
{
107+
throw new RuntimeException(e);
108+
}
109+
finally
110+
{
111+
innerFiles.add(tempInputClassFile2);
112+
innerTempFile.get().markAsCreatedFile(tempInputClassFile2);
113+
innerTempFiles.add(innerTempFile.get());
114+
}
115+
}
116+
}
117+
});
118+
}
119+
}
120+
60121
try
61122
{
62123
//create the temporary files
@@ -85,7 +146,12 @@ public String decompileClassNode(ClassNode cn, byte[] bytes)
85146
}
86147
else
87148
{
88-
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(generateMainMethod(tempInputClassFile.getAbsolutePath(), new File(TEMP_DIRECTORY).getAbsolutePath()));
149+
List<String> strings = generate(tempInputClassFile.getAbsolutePath(),
150+
new File(TEMP_DIRECTORY).getAbsolutePath());
151+
152+
String[] args = strings.toArray(new String[0]);
153+
154+
org.jetbrains.java.decompiler.main.decompiler.ConsoleDecompiler.main(args);
89155
}
90156

91157
//if rename is enabled the file name will be the actual class name
@@ -110,8 +176,23 @@ public String decompileClassNode(ClassNode cn, byte[] bytes)
110176
finally
111177
{
112178
//cleanup temp files
113-
if(tempFile != null)
179+
if (tempFile != null)
114180
tempFile.cleanup();
181+
182+
if (innerTempFile.get() != null)
183+
innerTempFile.get().cleanup();
184+
185+
for (TempFile file : innerTempFiles)
186+
{
187+
file.cleanup();
188+
File file1 = new File(TEMP_DIRECTORY + file.getUniqueName() + ".java");
189+
if (file1.exists())
190+
{
191+
file1.delete();
192+
}
193+
}
194+
195+
innerFiles.clear();
115196
}
116197

117198
return FERNFLOWER + " " + ERROR + "! " + ExceptionUI.SEND_STACKTRACE_TO + NL + NL
@@ -140,31 +221,64 @@ public void decompileToZip(String sourceJar, String zipName)
140221

141222
}
142223

224+
private List<String> generate(String className, String folder)
225+
{
226+
List<String> strings = new ArrayList<>();
227+
strings.add("-rbr=" + ffOnValue(BytecodeViewer.viewer.rbr.isSelected()));
228+
strings.add("-rsy=" + ffOnValue(BytecodeViewer.viewer.rsy.isSelected()));
229+
strings.add("-din=" + ffOnValue(BytecodeViewer.viewer.din.isSelected()));
230+
strings.add("-dc4=" + ffOnValue(BytecodeViewer.viewer.dc4.isSelected()));
231+
strings.add("-das=" + ffOnValue(BytecodeViewer.viewer.das.isSelected()));
232+
strings.add("-hes=" + ffOnValue(BytecodeViewer.viewer.hes.isSelected()));
233+
strings.add("-hdc=" + ffOnValue(BytecodeViewer.viewer.hdc.isSelected()));
234+
strings.add("-dgs=" + ffOnValue(BytecodeViewer.viewer.dgs.isSelected()));
235+
strings.add("-ner=" + ffOnValue(BytecodeViewer.viewer.ner.isSelected()));
236+
strings.add("-den=" + ffOnValue(BytecodeViewer.viewer.den.isSelected()));
237+
strings.add("-rgn=" + ffOnValue(BytecodeViewer.viewer.rgn.isSelected()));
238+
strings.add("-bto=" + ffOnValue(BytecodeViewer.viewer.bto.isSelected()));
239+
strings.add("-nns=" + ffOnValue(BytecodeViewer.viewer.nns.isSelected()));
240+
strings.add("-uto=" + ffOnValue(BytecodeViewer.viewer.uto.isSelected()));
241+
strings.add("-udv=" + ffOnValue(BytecodeViewer.viewer.udv.isSelected()));
242+
strings.add("-rer=" + ffOnValue(BytecodeViewer.viewer.rer.isSelected()));
243+
strings.add("-fdi=" + ffOnValue(BytecodeViewer.viewer.fdi.isSelected()));
244+
strings.add("-asc=" + ffOnValue(BytecodeViewer.viewer.asc.isSelected()));
245+
strings.add("-ren=" + ffOnValue(BytecodeViewer.viewer.ren.isSelected()));
246+
strings.add(className);
247+
if (BytecodeViewer.viewer.din.isSelected())
248+
{
249+
for (File file : innerFiles)
250+
strings.add(file.getAbsolutePath());
251+
}
252+
253+
strings.add(folder);
254+
return strings;
255+
}
256+
143257
private String[] generateMainMethod(String className, String folder)
144258
{
145259
return new String[]
146-
{
147-
"-rbr=" + ffOnValue(BytecodeViewer.viewer.rbr.isSelected()),
148-
"-rsy=" + ffOnValue(BytecodeViewer.viewer.rsy.isSelected()),
149-
"-din=" + ffOnValue(BytecodeViewer.viewer.din.isSelected()),
150-
"-dc4=" + ffOnValue(BytecodeViewer.viewer.dc4.isSelected()),
151-
"-das=" + ffOnValue(BytecodeViewer.viewer.das.isSelected()),
152-
"-hes=" + ffOnValue(BytecodeViewer.viewer.hes.isSelected()),
153-
"-hdc=" + ffOnValue(BytecodeViewer.viewer.hdc.isSelected()),
154-
"-dgs=" + ffOnValue(BytecodeViewer.viewer.dgs.isSelected()),
155-
"-ner=" + ffOnValue(BytecodeViewer.viewer.ner.isSelected()),
156-
"-den=" + ffOnValue(BytecodeViewer.viewer.den.isSelected()),
157-
"-rgn=" + ffOnValue(BytecodeViewer.viewer.rgn.isSelected()),
158-
"-bto=" + ffOnValue(BytecodeViewer.viewer.bto.isSelected()),
159-
"-nns=" + ffOnValue(BytecodeViewer.viewer.nns.isSelected()),
160-
"-uto=" + ffOnValue(BytecodeViewer.viewer.uto.isSelected()),
161-
"-udv=" + ffOnValue(BytecodeViewer.viewer.udv.isSelected()),
162-
"-rer=" + ffOnValue(BytecodeViewer.viewer.rer.isSelected()),
163-
"-fdi=" + ffOnValue(BytecodeViewer.viewer.fdi.isSelected()),
164-
"-asc=" + ffOnValue(BytecodeViewer.viewer.asc.isSelected()),
165-
"-ren=" + ffOnValue(BytecodeViewer.viewer.ren.isSelected()),
166-
className, folder
167-
};
260+
{
261+
"-rbr=" + ffOnValue(BytecodeViewer.viewer.rbr.isSelected()),
262+
"-rsy=" + ffOnValue(BytecodeViewer.viewer.rsy.isSelected()),
263+
"-din=" + ffOnValue(BytecodeViewer.viewer.din.isSelected()),
264+
"-dc4=" + ffOnValue(BytecodeViewer.viewer.dc4.isSelected()),
265+
"-das=" + ffOnValue(BytecodeViewer.viewer.das.isSelected()),
266+
"-hes=" + ffOnValue(BytecodeViewer.viewer.hes.isSelected()),
267+
"-hdc=" + ffOnValue(BytecodeViewer.viewer.hdc.isSelected()),
268+
"-dgs=" + ffOnValue(BytecodeViewer.viewer.dgs.isSelected()),
269+
"-ner=" + ffOnValue(BytecodeViewer.viewer.ner.isSelected()),
270+
"-den=" + ffOnValue(BytecodeViewer.viewer.den.isSelected()),
271+
"-rgn=" + ffOnValue(BytecodeViewer.viewer.rgn.isSelected()),
272+
"-bto=" + ffOnValue(BytecodeViewer.viewer.bto.isSelected()),
273+
"-nns=" + ffOnValue(BytecodeViewer.viewer.nns.isSelected()),
274+
"-uto=" + ffOnValue(BytecodeViewer.viewer.uto.isSelected()),
275+
"-udv=" + ffOnValue(BytecodeViewer.viewer.udv.isSelected()),
276+
"-rer=" + ffOnValue(BytecodeViewer.viewer.rer.isSelected()),
277+
"-fdi=" + ffOnValue(BytecodeViewer.viewer.fdi.isSelected()),
278+
"-asc=" + ffOnValue(BytecodeViewer.viewer.asc.isSelected()),
279+
"-ren=" + ffOnValue(BytecodeViewer.viewer.ren.isSelected()),
280+
className, folder
281+
};
168282
}
169283

170284
private String ffOnValue(boolean b)

src/main/java/the/bytecode/club/bytecodeviewer/decompilers/impl/JDGUIDecompiler.java

+51-1
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,26 @@
1919
package the.bytecode.club.bytecodeviewer.decompilers.impl;
2020

2121
import com.konloch.disklib.DiskReader;
22+
import org.apache.commons.io.FilenameUtils;
2223
import org.jd.core.v1.ClassFileToJavaSourceDecompiler;
2324
import org.objectweb.asm.tree.ClassNode;
25+
import org.objectweb.asm.tree.InnerClassNode;
26+
import the.bytecode.club.bytecodeviewer.BytecodeViewer;
2427
import the.bytecode.club.bytecodeviewer.Constants;
28+
import the.bytecode.club.bytecodeviewer.api.ASMUtil;
2529
import the.bytecode.club.bytecodeviewer.api.ExceptionUI;
2630
import the.bytecode.club.bytecodeviewer.decompilers.AbstractDecompiler;
2731
import the.bytecode.club.bytecodeviewer.decompilers.jdgui.CommonPreferences;
2832
import the.bytecode.club.bytecodeviewer.decompilers.jdgui.DirectoryLoader;
2933
import the.bytecode.club.bytecodeviewer.decompilers.jdgui.JDGUIClassFileUtil;
3034
import the.bytecode.club.bytecodeviewer.decompilers.jdgui.PlainTextPrinter;
35+
import the.bytecode.club.bytecodeviewer.resources.ResourceContainer;
3136
import the.bytecode.club.bytecodeviewer.translation.TranslatedStrings;
3237
import the.bytecode.club.bytecodeviewer.util.ExceptionUtils;
3338
import the.bytecode.club.bytecodeviewer.util.TempFile;
3439

3540
import java.io.*;
41+
import java.util.List;
3642

3743
import static the.bytecode.club.bytecodeviewer.Constants.FS;
3844
import static the.bytecode.club.bytecodeviewer.Constants.NL;
@@ -59,6 +65,26 @@ public String decompileClassNode(ClassNode cn, byte[] bytes)
5965
TempFile tempFile = null;
6066
String exception;
6167

68+
List<InnerClassNode> innerClasses = cn.innerClasses;
69+
String[] inners = new String[innerClasses.size()];
70+
for (int i = 0; i < innerClasses.size(); i++)
71+
{
72+
if (innerClasses.get(i).name.equals(cn.name))
73+
break;
74+
75+
if (innerClasses.get(i).outerName != null && innerClasses.get(i).outerName.equals(cn.name))
76+
{
77+
inners[i] = innerClasses.get(i).name;
78+
}
79+
else if (innerClasses.get(i).outerName == null)
80+
{
81+
String name = innerClasses.get(i).name;
82+
name = name.substring(name.lastIndexOf('/') + 1);
83+
if (name.contains(cn.name.substring(cn.name.lastIndexOf('/') + 1)))
84+
inners[i] = innerClasses.get(i).name;
85+
}
86+
}
87+
6288
try
6389
{
6490
//create the temporary files
@@ -75,9 +101,33 @@ public String decompileClassNode(ClassNode cn, byte[] bytes)
75101
fos.write(bytes);
76102
}
77103

104+
// create the inner class temp files
105+
File innerTempFile;
106+
for (ResourceContainer container : BytecodeViewer.resourceContainers.values())
107+
{
108+
for (String s : container.resourceClasses.keySet())
109+
{
110+
for (String innerClassName : inners)
111+
{
112+
if (s.equals(innerClassName))
113+
{
114+
ClassNode cn2 = container.resourceClasses.get(innerClassName);
115+
tempFile.setUniqueName(cn2.name);
116+
innerTempFile = tempFile.createFileFromExtension(false, false, ".class");
117+
try (FileOutputStream fos = new FileOutputStream(innerTempFile))
118+
{
119+
fos.write(ASMUtil.nodeToBytes(cn2));
120+
}
121+
}
122+
}
123+
}
124+
}
125+
78126
String pathToClass = tempClassFile.getAbsolutePath().replace('/', File.separatorChar).replace('\\', File.separatorChar);
79127
String directoryPath = JDGUIClassFileUtil.ExtractDirectoryPath(pathToClass);
80-
String internalPath = JDGUIClassFileUtil.ExtractInternalPath(directoryPath, pathToClass);
128+
String internalPath = FilenameUtils.removeExtension(JDGUIClassFileUtil.ExtractInternalPath(directoryPath,
129+
pathToClass));
130+
81131

82132
CommonPreferences preferences = new CommonPreferences()
83133
{

src/main/java/the/bytecode/club/bytecodeviewer/decompilers/jdgui/DirectoryLoader.java

+4-1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,9 @@ public DirectoryLoader(File file) throws LoaderException
4646
@Override
4747
public byte[] load(String internalPath) throws LoaderException
4848
{
49+
if (!internalPath.endsWith(".class"))
50+
internalPath = internalPath + ".class";
51+
4952
File file = new File(this.codebase, internalPath);
5053

5154
try (FileInputStream fis = new FileInputStream(file); BufferedInputStream bis = new BufferedInputStream(fis))
@@ -61,7 +64,7 @@ public byte[] load(String internalPath) throws LoaderException
6164
@Override
6265
public boolean canLoad(String internalPath)
6366
{
64-
File file = new File(this.codebase, internalPath);
67+
File file = new File(this.codebase, internalPath + ".class");
6568
return file.exists() && file.isFile();
6669
}
6770
}

src/main/java/the/bytecode/club/bytecodeviewer/gui/components/MyErrorStripe.java

+2-3
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ private int yToLine(int y)
8686
if (y < h)
8787
{
8888
float at = y / (float) h;
89-
line = Math.round((Math.max(lineCount, linesPerVisibleRect) - 1) * at);
89+
line = Math.round((float) (Math.max(lineCount, linesPerVisibleRect) - 1) * at);
9090
}
9191

9292
return line;
@@ -199,7 +199,6 @@ public void removeNotify()
199199

200200
private class Listener extends MouseAdapter
201201
{
202-
private final Rectangle r = new Rectangle();
203202

204203
@Override
205204
public void mouseClicked(@NotNull MouseEvent e)
@@ -219,7 +218,7 @@ public void mouseClicked(@NotNull MouseEvent e)
219218
{
220219
try
221220
{
222-
int offset = textArea.getLineOfOffset(line);
221+
int offset = textArea.getLineStartOffset(line);
223222
textArea.setCaretPosition(offset);
224223
RSyntaxUtilities.selectAndPossiblyCenter(textArea, new DocumentRange(offset, offset), false);
225224
}

0 commit comments

Comments
 (0)