summaryrefslogtreecommitdiff
path: root/plugins/java-decompiler
diff options
context:
space:
mode:
Diffstat (limited to 'plugins/java-decompiler')
-rw-r--r--plugins/java-decompiler/java-decompiler.iml28
-rw-r--r--plugins/java-decompiler/lib/fernflower.jarbin0 -> 273276 bytes
-rw-r--r--plugins/java-decompiler/src/META-INF/plugin.xml20
-rw-r--r--plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaDecompiler.java205
-rw-r--r--plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaLogger.java81
-rw-r--r--plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java160
-rw-r--r--plugins/java-decompiler/testData/Anonymous$1.classbin0 -> 672 bytes
-rw-r--r--plugins/java-decompiler/testData/Anonymous.classbin0 -> 407 bytes
-rw-r--r--plugins/java-decompiler/testData/Anonymous.java13
-rw-r--r--plugins/java-decompiler/testData/Anonymous.txt24
-rw-r--r--plugins/java-decompiler/testData/Constants$A.classbin0 -> 273 bytes
-rw-r--r--plugins/java-decompiler/testData/Constants.classbin0 -> 1640 bytes
-rw-r--r--plugins/java-decompiler/testData/Constants.java47
-rw-r--r--plugins/java-decompiler/testData/Constants.txt82
-rw-r--r--plugins/java-decompiler/testData/Deprecations$ByAnno.classbin0 -> 347 bytes
-rw-r--r--plugins/java-decompiler/testData/Deprecations$ByComment.classbin0 -> 288 bytes
-rw-r--r--plugins/java-decompiler/testData/Deprecations.classbin0 -> 548 bytes
-rw-r--r--plugins/java-decompiler/testData/Deprecations.java19
-rw-r--r--plugins/java-decompiler/testData/Deprecations.txt42
-rw-r--r--plugins/java-decompiler/testData/Enum$1.classbin0 -> 335 bytes
-rw-r--r--plugins/java-decompiler/testData/Enum$2.classbin0 -> 392 bytes
-rw-r--r--plugins/java-decompiler/testData/Enum.classbin0 -> 1407 bytes
-rw-r--r--plugins/java-decompiler/testData/Enum.java19
-rw-r--r--plugins/java-decompiler/testData/Enum.txt33
-rw-r--r--plugins/java-decompiler/testData/ExtendsList.classbin0 -> 510 bytes
-rw-r--r--plugins/java-decompiler/testData/ExtendsList.java9
-rw-r--r--plugins/java-decompiler/testData/ExtendsList.txt19
-rw-r--r--plugins/java-decompiler/testData/Parameters$1Local.classbin0 -> 501 bytes
-rw-r--r--plugins/java-decompiler/testData/Parameters$C1.classbin0 -> 453 bytes
-rw-r--r--plugins/java-decompiler/testData/Parameters$C2.classbin0 -> 445 bytes
-rw-r--r--plugins/java-decompiler/testData/Parameters.classbin0 -> 563 bytes
-rw-r--r--plugins/java-decompiler/testData/Parameters.java23
-rw-r--r--plugins/java-decompiler/testData/Parameters.txt50
33 files changed, 874 insertions, 0 deletions
diff --git a/plugins/java-decompiler/java-decompiler.iml b/plugins/java-decompiler/java-decompiler.iml
new file mode 100644
index 000000000000..cf37a2991f2f
--- /dev/null
+++ b/plugins/java-decompiler/java-decompiler.iml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<module type="JAVA_MODULE" version="4">
+ <component name="NewModuleRootManager" inherit-compiler-output="true">
+ <exclude-output />
+ <content url="file://$MODULE_DIR$">
+ <sourceFolder url="file://$MODULE_DIR$/src" isTestSource="false" />
+ <sourceFolder url="file://$MODULE_DIR$/test" isTestSource="true" />
+ </content>
+ <orderEntry type="inheritedJdk" />
+ <orderEntry type="sourceFolder" forTests="false" />
+ <orderEntry type="module" module-name="lang-api" />
+ <orderEntry type="module" module-name="java-psi-api" />
+ <orderEntry type="module" module-name="java-psi-impl" />
+ <orderEntry type="module" module-name="util" />
+ <orderEntry type="module" module-name="testFramework-java" scope="TEST" />
+ <orderEntry type="module-library">
+ <library>
+ <CLASSES>
+ <root url="jar://$MODULE_DIR$/lib/fernflower.jar!/" />
+ </CLASSES>
+ <JAVADOC />
+ <SOURCES />
+ </library>
+ </orderEntry>
+ <orderEntry type="library" name="asm5" level="project" />
+ </component>
+</module>
+
diff --git a/plugins/java-decompiler/lib/fernflower.jar b/plugins/java-decompiler/lib/fernflower.jar
new file mode 100644
index 000000000000..85b1c40002b5
--- /dev/null
+++ b/plugins/java-decompiler/lib/fernflower.jar
Binary files differ
diff --git a/plugins/java-decompiler/src/META-INF/plugin.xml b/plugins/java-decompiler/src/META-INF/plugin.xml
new file mode 100644
index 000000000000..2eacf248c370
--- /dev/null
+++ b/plugins/java-decompiler/src/META-INF/plugin.xml
@@ -0,0 +1,20 @@
+<idea-plugin version="2">
+
+ <id>org.jetbrains.java.decompiler</id>
+ <name>Java Bytecode Decompiler</name>
+ <description>
+ The plugin extends standard IDEA .class file viewer with powerful Fernflower decompiler -
+ no more dull "{ /* compiled code */ }" in method bodies!
+ </description>
+ <version>0.1</version>
+ <vendor email="support@jetbrains.com" url="http://www.jetbrains.com">JetBrains</vendor>
+
+ <idea-version since-build="135"/>
+
+ <module value="com.intellij.modules.java"/>
+
+ <extensions defaultExtensionNs="com.intellij">
+ <psi.classFileDecompiler implementation="org.jetbrains.java.decompiler.IdeaDecompiler" order="last"/>
+ </extensions>
+
+</idea-plugin> \ No newline at end of file
diff --git a/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaDecompiler.java b/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
new file mode 100644
index 000000000000..bf0454fd6670
--- /dev/null
+++ b/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaDecompiler.java
@@ -0,0 +1,205 @@
+/*
+ * Copyright 2000-2014 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 org.jetbrains.java.decompiler;
+
+import com.intellij.ide.highlighter.JavaFileType;
+import com.intellij.openapi.diagnostic.Logger;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.project.DefaultProjectFactory;
+import com.intellij.openapi.project.Project;
+import com.intellij.openapi.util.Ref;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.psi.codeStyle.CodeStyleSettings;
+import com.intellij.psi.codeStyle.CodeStyleSettingsManager;
+import com.intellij.psi.codeStyle.CommonCodeStyleSettings;
+import com.intellij.psi.compiled.ClassFileDecompilers;
+import com.intellij.psi.impl.compiled.ClsFileImpl;
+import com.intellij.util.containers.ContainerUtil;
+import de.fernflower.main.decompiler.IdeDecompiler;
+import de.fernflower.main.extern.IBytecodeProvider;
+import de.fernflower.main.extern.IDecompilatSaver;
+import de.fernflower.main.extern.IFernflowerLogger;
+import de.fernflower.main.extern.IFernflowerPreferences;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.org.objectweb.asm.ClassReader;
+import org.jetbrains.org.objectweb.asm.ClassVisitor;
+import org.jetbrains.org.objectweb.asm.Opcodes;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.jar.Manifest;
+
+public class IdeaDecompiler extends ClassFileDecompilers.Light {
+ private static final Logger LOG = Logger.getInstance(IdeaDecompiler.class);
+
+ private static final String BANNER =
+ "//\n" +
+ "// Source code recreated from a .class file by IntelliJ IDEA\n" +
+ "// (powered by Fernflower decompiler)\n" +
+ "//\n\n";
+
+ private final IFernflowerLogger myLogger = new IdeaLogger();
+ private final HashMap<String, Object> myOptions = new HashMap<String, Object>();
+
+ public IdeaDecompiler() {
+ myOptions.put(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR, "0");
+ myOptions.put(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES, "1");
+ myOptions.put(IFernflowerPreferences.REMOVE_SYNTHETIC, "1");
+ myOptions.put(IFernflowerPreferences.REMOVE_BRIDGE, "1");
+ myOptions.put(IFernflowerPreferences.LITERALS_AS_IS, "1");
+ myOptions.put(IFernflowerPreferences.NEW_LINE_SEPARATOR, "1");
+
+ Project project = DefaultProjectFactory.getInstance().getDefaultProject();
+ CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(project).getCurrentSettings();
+ CommonCodeStyleSettings.IndentOptions options = settings.getIndentOptions(JavaFileType.INSTANCE);
+ myOptions.put(IFernflowerPreferences.INDENT_STRING, StringUtil.repeat(" ", options.INDENT_SIZE));
+ }
+
+ @Override
+ public boolean accepts(@NotNull VirtualFile file) {
+ return true;
+ }
+
+ @NotNull
+ @Override
+ public CharSequence getText(@NotNull VirtualFile file) {
+ if (!canHandle(file)) {
+ return ClsFileImpl.decompile(file);
+ }
+
+ try {
+ Map<String, VirtualFile> files = ContainerUtil.newLinkedHashMap();
+ files.put(file.getPath(), file);
+ String mask = file.getNameWithoutExtension() + "$";
+ for (VirtualFile child : file.getParent().getChildren()) {
+ if (child.getNameWithoutExtension().startsWith(mask) && file.getFileType() == StdFileTypes.CLASS) {
+ files.put(child.getPath(), child);
+ }
+ }
+ MyByteCodeProvider provider = new MyByteCodeProvider(files);
+ MyResultSaver saver = new MyResultSaver();
+
+ IdeDecompiler decompiler = new IdeDecompiler(provider, saver, myLogger, myOptions);
+ for (String path : files.keySet()) {
+ decompiler.addSpace(new File(path), true);
+ }
+ decompiler.decompileContext();
+
+ return BANNER + saver.myResult;
+ }
+ catch (Exception e) {
+ LOG.error(file.getUrl(), e);
+ return ClsFileImpl.decompile(file);
+ }
+ }
+
+ private static boolean canHandle(VirtualFile file) {
+ if ("package-info.class".equals(file.getName())) {
+ LOG.info("skipped: " + file.getUrl());
+ return false;
+ }
+
+ final Ref<Boolean> isGroovy = Ref.create(false);
+ try {
+ new ClassReader(file.contentsToByteArray()).accept(new ClassVisitor(Opcodes.ASM5) {
+ @Override
+ public void visit(int version, int access, String name, String signature, String superName, String[] interfaces) {
+ for (String anInterface : interfaces) {
+ if ("groovy/lang/GroovyObject".equals(anInterface)) {
+ isGroovy.set(true);
+ break;
+ }
+ }
+ }
+
+ @Override
+ public void visitSource(String source, String debug) {
+ if (source != null && source.endsWith(".groovy")) {
+ isGroovy.set(true);
+ }
+ }
+ }, ClassReader.SKIP_CODE);
+ }
+ catch (IOException ignore) { }
+ if (isGroovy.get()) {
+ LOG.info("skipped Groovy class: " + file.getUrl());
+ return false;
+ }
+
+ return true;
+ }
+
+ private static class MyByteCodeProvider implements IBytecodeProvider {
+ private final Map<String, VirtualFile> myFiles;
+
+ private MyByteCodeProvider(@NotNull Map<String, VirtualFile> files) {
+ myFiles = files;
+ }
+
+ @Override
+ public InputStream getBytecodeStream(String externalPath, String internalPath) {
+ try {
+ String path = FileUtil.toSystemIndependentName(externalPath);
+ VirtualFile file = myFiles.get(path);
+ assert file != null : path;
+ return file.getInputStream();
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static class MyResultSaver implements IDecompilatSaver {
+ private String myResult = "";
+
+ @Override
+ public void saveClassFile(String path, String qualifiedName, String entryName, String content) {
+ if (myResult.isEmpty()) {
+ myResult = content;
+ }
+ }
+
+ @Override
+ public void copyFile(String source, String destPath, String destFileName) { }
+
+ @Override
+ public void saveFolder(String path) { }
+
+ @Override
+ public void saveFile(String path, String filename, String content) { }
+
+ @Override
+ public void createArchive(String path, String archiveName, Manifest manifest) { }
+
+ @Override
+ public void saveClassEntry(String path, String archiveName, String qualifiedName, String entryName, String content) { }
+
+ @Override
+ public void saveEntry(String path, String archiveName, String entryName, String content) { }
+
+ @Override
+ public void copyEntry(String source, String destPath, String archiveName, String entry) { }
+
+ @Override
+ public void closeArchive(String path, String archiveName) { }
+ }
+}
diff --git a/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaLogger.java b/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaLogger.java
new file mode 100644
index 000000000000..904af9bf31b3
--- /dev/null
+++ b/plugins/java-decompiler/src/org/jetbrains/java/decompiler/IdeaLogger.java
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2000-2014 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 org.jetbrains.java.decompiler;
+
+import com.intellij.openapi.diagnostic.Logger;
+import de.fernflower.main.extern.IFernflowerLogger;
+
+public class IdeaLogger implements IFernflowerLogger {
+ private final static Logger LOG = Logger.getInstance(IdeaDecompiler.class);
+
+ public static class InternalException extends RuntimeException {
+ public InternalException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ }
+
+ @Override
+ public void writeMessage(String message, int severity) {
+ if (severity >= ERROR) LOG.error(message);
+ else if (severity == WARNING) LOG.warn(message);
+ else if (severity == INFO) LOG.info(message);
+ else LOG.debug(message);
+ }
+
+ @Override
+ public void writeMessage(String message, Throwable t) {
+ if (t instanceof InternalException) throw (InternalException)t;
+ else throw new InternalException(message, t);
+ }
+
+ @Override
+ public void startClass(String className) {
+ LOG.debug("processing class " + className);
+ }
+
+ @Override
+ public void endClass() {
+ LOG.debug("... class processed");
+ }
+
+ @Override
+ public void startWriteClass(String className) {
+ LOG.debug("writing class " + className);
+ }
+
+ @Override
+ public void endWriteClass() {
+ LOG.debug("... class written");
+ }
+
+ @Override
+ public void startMethod(String method) {
+ LOG.debug("processing method " + method);
+ }
+
+ @Override
+ public void endMethod() {
+ LOG.debug("... method processed");
+ }
+
+ @Override
+ public int getSeverity() {
+ return WARNING;
+ }
+
+ @Override
+ public void setSeverity(int ignore) { }
+}
diff --git a/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java b/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java
new file mode 100644
index 000000000000..9367fc066f30
--- /dev/null
+++ b/plugins/java-decompiler/test/org/jetbrains/java/decompiler/IdeaDecompilerTest.java
@@ -0,0 +1,160 @@
+/*
+ * Copyright 2000-2014 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 org.jetbrains.java.decompiler;
+
+import com.intellij.openapi.application.PathManager;
+import com.intellij.openapi.application.PluginPathManager;
+import com.intellij.openapi.fileTypes.StdFileTypes;
+import com.intellij.openapi.util.io.FileUtil;
+import com.intellij.openapi.util.text.StringUtil;
+import com.intellij.openapi.vfs.StandardFileSystems;
+import com.intellij.openapi.vfs.VfsUtilCore;
+import com.intellij.openapi.vfs.VirtualFile;
+import com.intellij.openapi.vfs.VirtualFileVisitor;
+import com.intellij.psi.*;
+import com.intellij.psi.impl.compiled.ClsFileImpl;
+import com.intellij.testFramework.PlatformTestUtil;
+import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase;
+import org.jetbrains.annotations.NotNull;
+import org.jetbrains.annotations.Nullable;
+
+import java.io.File;
+import java.io.IOException;
+
+public class IdeaDecompilerTest extends LightCodeInsightFixtureTestCase {
+ public void testSimple() {
+ String path = PlatformTestUtil.getRtJarPath() + "!/java/lang/String.class";
+ VirtualFile file = StandardFileSystems.jar().findFileByPath(path);
+ assertNotNull(path, file);
+
+ CharSequence text = new IdeaDecompiler().getText(file);
+ assertNotNull(text);
+
+ String decompiled = text.toString();
+ assertTrue(decompiled, decompiled.contains("public final class String"));
+ assertTrue(decompiled, decompiled.contains("@deprecated"));
+ assertTrue(decompiled, decompiled.contains("private static class CaseInsensitiveComparator"));
+ assertFalse(decompiled, decompiled.contains("{ /* compiled code */ }"));
+ assertFalse(decompiled, decompiled.contains("synthetic"));
+ }
+
+ public void testEnum() { doTestDecompiler(); }
+ public void testDeprecations() { doTestDecompiler(); }
+ public void testExtendsList() { doTestDecompiler(); }
+ public void testParameters() { doTestDecompiler(); }
+ public void testConstants() { doTestDecompiler(); }
+ public void testAnonymous() { doTestDecompiler(); }
+
+ private void doTestDecompiler() {
+ String name = PluginPathManager.getPluginHomePath("java-decompiler") + "/testData/" + getName().substring(4);
+ String path = name + ".class";
+ VirtualFile file = StandardFileSystems.local().findFileByPath(path);
+ assertNotNull(path, file);
+ file.getParent().getChildren();
+ file.getParent().refresh(false, true);
+
+ try {
+ CharSequence text = new IdeaDecompiler().getText(file);
+ assertNotNull(text);
+ String expected = FileUtil.loadFile(new File(name + ".txt"), "UTF-8");
+ assertEquals(StringUtil.convertLineSeparators(expected), text.toString());
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ public void testStubCompatibilityRt() {
+ String path = PlatformTestUtil.getRtJarPath() + "!/";
+ VirtualFile dir = StandardFileSystems.jar().findFileByPath(path);
+ assertNotNull(path, dir);
+ doTestStubCompatibility(dir);
+ }
+
+ public void testStubCompatibilityIdea() {
+ String path = PathManager.getHomePath() + "/out/production";
+ if (!new File(path).exists()) path = PathManager.getHomePath() + "/out/classes/production";
+ VirtualFile dir = StandardFileSystems.local().refreshAndFindFileByPath(path);
+ assertNotNull(path, dir);
+ doTestStubCompatibility(dir);
+ }
+
+ private void doTestStubCompatibility(VirtualFile root) {
+ doTestStubCompatibility(root, null);
+ }
+
+ private void doTestStubCompatibility(VirtualFile root, @Nullable final String textPath) {
+ final int pathStart = root.getPath().length();
+ final boolean compare = textPath != null && new File(textPath).exists();
+
+ VfsUtilCore.visitChildrenRecursively(root, new VirtualFileVisitor() {
+ @Override
+ public boolean visitFile(@NotNull VirtualFile file) {
+ if (file.getName().equals("Jps.class")) return true; // temp. fix
+ if (!file.isDirectory() && file.getFileType() == StdFileTypes.CLASS && !file.getName().contains("$")) {
+ PsiFile clsFile = getPsiManager().findFile(file);
+ assertNotNull(file.getPath(), clsFile);
+
+ PsiElement mirror = ((ClsFileImpl)clsFile).getMirror().copy();
+ if (textPath != null) {
+ collapseCodeBlocks(mirror);
+ }
+ String decompiled = mirror.getText();
+ assertTrue(file.getPath(), decompiled.contains(file.getNameWithoutExtension()));
+
+ if (textPath != null) {
+ try {
+ File txtFile = new File(textPath, file.getPath().substring(pathStart));
+ if (!compare) {
+ FileUtil.writeToFile(txtFile, decompiled.getBytes("UTF-8"));
+ }
+ else {
+ String expected = FileUtil.loadFile(txtFile, "UTF-8");
+ assertEquals(file.getPath(), expected, decompiled);
+ }
+ }
+ catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+ return true;
+ }
+ });
+ }
+
+ private static void collapseCodeBlocks(PsiElement original) {
+ final PsiElementFactory factory = PsiElementFactory.SERVICE.getInstance(original.getProject());
+ original.accept(new JavaRecursiveElementWalkingVisitor() {
+ @Override
+ public void visitMethod(PsiMethod method) {
+ PsiCodeBlock body = method.getBody();
+ if (body != null) {
+ body.replace(factory.createCodeBlockFromText("{ /* collapsed */}", null));
+ }
+ }
+
+ @Override
+ public void visitClass(PsiClass aClass) {
+ for (PsiClassInitializer initializer : aClass.getInitializers()) {
+ PsiCodeBlock body = initializer.getBody();
+ body.replace(factory.createCodeBlockFromText("{ /* collapsed */}", null));
+ }
+ super.visitClass(aClass);
+ }
+ });
+ }
+}
diff --git a/plugins/java-decompiler/testData/Anonymous$1.class b/plugins/java-decompiler/testData/Anonymous$1.class
new file mode 100644
index 000000000000..338c04840be2
--- /dev/null
+++ b/plugins/java-decompiler/testData/Anonymous$1.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Anonymous.class b/plugins/java-decompiler/testData/Anonymous.class
new file mode 100644
index 000000000000..df67a5858753
--- /dev/null
+++ b/plugins/java-decompiler/testData/Anonymous.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Anonymous.java b/plugins/java-decompiler/testData/Anonymous.java
new file mode 100644
index 000000000000..6f4a89389a27
--- /dev/null
+++ b/plugins/java-decompiler/testData/Anonymous.java
@@ -0,0 +1,13 @@
+public class Anonymous {
+ private int count = 0;
+
+ public Object produce() {
+ final int id = count++;
+ return new Object() {
+ @Override
+ public String toString() {
+ return "anonymous_" + id;
+ }
+ };
+ }
+} \ No newline at end of file
diff --git a/plugins/java-decompiler/testData/Anonymous.txt b/plugins/java-decompiler/testData/Anonymous.txt
new file mode 100644
index 000000000000..a7cea92713b7
--- /dev/null
+++ b/plugins/java-decompiler/testData/Anonymous.txt
@@ -0,0 +1,24 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+
+public class Anonymous {
+
+ private int count = 0;
+
+
+ public Anonymous() {
+ }
+
+ public Object produce() {
+ ++this.count;
+ final int var1 = this.count;
+ return new Object() {
+ public String toString() {
+ return "anonymous_" + var1;
+ }
+ };
+ }
+}
diff --git a/plugins/java-decompiler/testData/Constants$A.class b/plugins/java-decompiler/testData/Constants$A.class
new file mode 100644
index 000000000000..d4d8df39443a
--- /dev/null
+++ b/plugins/java-decompiler/testData/Constants$A.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Constants.class b/plugins/java-decompiler/testData/Constants.class
new file mode 100644
index 000000000000..a8ad40e7b158
--- /dev/null
+++ b/plugins/java-decompiler/testData/Constants.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Constants.java b/plugins/java-decompiler/testData/Constants.java
new file mode 100644
index 000000000000..b2b59a5728c6
--- /dev/null
+++ b/plugins/java-decompiler/testData/Constants.java
@@ -0,0 +1,47 @@
+public class Constants {
+ static final boolean T = true;
+ static final boolean F = false;
+
+ static final char C0 = '\n';
+ static final char C1 = 'a';
+ static final char C2 = 512;
+
+ static final byte BMin = Byte.MIN_VALUE;
+ static final byte BMax = Byte.MAX_VALUE;
+
+ static final short SMin = Short.MIN_VALUE;
+ static final short SMax = Short.MAX_VALUE;
+
+ static final int IMin = Integer.MIN_VALUE;
+ static final int IMax = Integer.MAX_VALUE;
+
+ static final long LMin = Long.MIN_VALUE;
+ static final long LMax = Long.MAX_VALUE;
+
+ static final float FNan = Float.NaN;
+ static final float FNeg = Float.NEGATIVE_INFINITY;
+ static final float FPos = Float.POSITIVE_INFINITY;
+ static final float FMin = Float.MIN_VALUE;
+ static final float FMax = Float.MAX_VALUE;
+
+ static final double DNan = Double.NaN;
+ static final double DNeg = Double.NEGATIVE_INFINITY;
+ static final double DPos = Double.POSITIVE_INFINITY;
+ static final double DMin = Double.MIN_VALUE;
+ static final double DMax = Double.MAX_VALUE;
+
+ static @interface A {
+ Class<?> value();
+ }
+
+ @A(byte.class) void m1() { }
+ @A(char.class) void m2() { }
+ @A(double.class) void m3() { }
+ @A(float.class) void m4() { }
+ @A(int.class) void m5() { }
+ @A(long.class) void m6() { }
+ @A(short.class) void m7() { }
+ @A(boolean.class) void m8() { }
+ @A(void.class) void m9() { }
+ @A(java.util.Date.class) void m10() { }
+} \ No newline at end of file
diff --git a/plugins/java-decompiler/testData/Constants.txt b/plugins/java-decompiler/testData/Constants.txt
new file mode 100644
index 000000000000..9665582396c0
--- /dev/null
+++ b/plugins/java-decompiler/testData/Constants.txt
@@ -0,0 +1,82 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+import java.util.Date;
+
+public class Constants {
+
+ static final boolean T = true;
+ static final boolean F = false;
+ static final char C0 = '\n';
+ static final char C1 = 'a';
+ static final char C2 = 'Ȁ';
+ static final byte BMin = -128;
+ static final byte BMax = 127;
+ static final short SMin = -32768;
+ static final short SMax = 32767;
+ static final int IMin = -2147483648;
+ static final int IMax = 2147483647;
+ static final long LMin = -9223372036854775808L;
+ static final long LMax = 9223372036854775807L;
+ static final float FNan = 0.0F / 0.0;
+ static final float FNeg = -1.0F / 0.0;
+ static final float FPos = 1.0F / 0.0;
+ static final float FMin = 1.4E-45F;
+ static final float FMax = 3.4028235E38F;
+ static final double DNan = 0.0D / 0.0;
+ static final double DNeg = -1.0D / 0.0;
+ static final double DPos = 1.0D / 0.0;
+ static final double DMin = 4.9E-324D;
+ static final double DMax = 1.7976931348623157E308D;
+
+
+ public Constants() {
+ }
+
+ @Constants(byte.class)
+ void m1() {
+ }
+
+ @Constants(char.class)
+ void m2() {
+ }
+
+ @Constants(double.class)
+ void m3() {
+ }
+
+ @Constants(float.class)
+ void m4() {
+ }
+
+ @Constants(int.class)
+ void m5() {
+ }
+
+ @Constants(long.class)
+ void m6() {
+ }
+
+ @Constants(short.class)
+ void m7() {
+ }
+
+ @Constants(boolean.class)
+ void m8() {
+ }
+
+ @Constants(void.class)
+ void m9() {
+ }
+
+ @Constants(Date.class)
+ void m10() {
+ }
+
+ @interface A {
+
+ Class<?> value();
+ }
+}
diff --git a/plugins/java-decompiler/testData/Deprecations$ByAnno.class b/plugins/java-decompiler/testData/Deprecations$ByAnno.class
new file mode 100644
index 000000000000..4fcd96c2259e
--- /dev/null
+++ b/plugins/java-decompiler/testData/Deprecations$ByAnno.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Deprecations$ByComment.class b/plugins/java-decompiler/testData/Deprecations$ByComment.class
new file mode 100644
index 000000000000..e04dcf79a0f2
--- /dev/null
+++ b/plugins/java-decompiler/testData/Deprecations$ByComment.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Deprecations.class b/plugins/java-decompiler/testData/Deprecations.class
new file mode 100644
index 000000000000..aa6de359a4aa
--- /dev/null
+++ b/plugins/java-decompiler/testData/Deprecations.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Deprecations.java b/plugins/java-decompiler/testData/Deprecations.java
new file mode 100644
index 000000000000..838ff68131de
--- /dev/null
+++ b/plugins/java-decompiler/testData/Deprecations.java
@@ -0,0 +1,19 @@
+public class Deprecations {
+ /** @deprecated */
+ public int byComment;
+
+ @Deprecated
+ public int byAnno;
+
+ /** @deprecated */
+ public void byComment() { }
+
+ @Deprecated
+ public void byAnno() { }
+
+ /** @deprecated */
+ public static class ByComment { }
+
+ @Deprecated
+ public static class ByAnno { }
+} \ No newline at end of file
diff --git a/plugins/java-decompiler/testData/Deprecations.txt b/plugins/java-decompiler/testData/Deprecations.txt
new file mode 100644
index 000000000000..bb1340e83799
--- /dev/null
+++ b/plugins/java-decompiler/testData/Deprecations.txt
@@ -0,0 +1,42 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+
+public class Deprecations {
+
+ /** @deprecated */
+ public int byComment;
+ /** @deprecated */
+ @Deprecated
+ public int byAnno;
+
+
+ public Deprecations() {
+ }
+
+ /** @deprecated */
+ public void byComment() {
+ }
+
+ /** @deprecated */
+ @Deprecated
+ public void byAnno() {
+ }
+
+ /** @deprecated */
+ @Deprecated
+ public static class ByAnno {
+
+ public ByAnno() {
+ }
+ }
+
+ /** @deprecated */
+ public static class ByComment {
+
+ public ByComment() {
+ }
+ }
+}
diff --git a/plugins/java-decompiler/testData/Enum$1.class b/plugins/java-decompiler/testData/Enum$1.class
new file mode 100644
index 000000000000..e52b1899a716
--- /dev/null
+++ b/plugins/java-decompiler/testData/Enum$1.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Enum$2.class b/plugins/java-decompiler/testData/Enum$2.class
new file mode 100644
index 000000000000..c86cdd2a95d1
--- /dev/null
+++ b/plugins/java-decompiler/testData/Enum$2.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Enum.class b/plugins/java-decompiler/testData/Enum.class
new file mode 100644
index 000000000000..45123e255eab
--- /dev/null
+++ b/plugins/java-decompiler/testData/Enum.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Enum.java b/plugins/java-decompiler/testData/Enum.java
new file mode 100644
index 000000000000..b61c069e0e19
--- /dev/null
+++ b/plugins/java-decompiler/testData/Enum.java
@@ -0,0 +1,19 @@
+public enum Enum {
+ E1,
+ E2() {
+ @Override
+ public void m() { }
+ },
+ E3("-"),
+ E4("+") {
+ @Override
+ public void m() { }
+ };
+
+ public void m() { }
+
+ private String s;
+
+ private Enum() { this("?"); }
+ private Enum(@Deprecated String s) { this.s = s; }
+}
diff --git a/plugins/java-decompiler/testData/Enum.txt b/plugins/java-decompiler/testData/Enum.txt
new file mode 100644
index 000000000000..1156c8214d78
--- /dev/null
+++ b/plugins/java-decompiler/testData/Enum.txt
@@ -0,0 +1,33 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+
+public enum Enum {
+
+ E1,
+ E2 {
+ public void m() {
+ }
+ },
+ E3("-"),
+ E4("+") {
+ public void m() {
+ }
+ };
+ private String s;
+
+
+ public void m() {
+ }
+
+ private Enum() {
+ this((String)"?");
+ }
+
+ private Enum(@Deprecated String var3) {
+ this.s = var3;
+ }
+
+}
diff --git a/plugins/java-decompiler/testData/ExtendsList.class b/plugins/java-decompiler/testData/ExtendsList.class
new file mode 100644
index 000000000000..7d4eb9c69265
--- /dev/null
+++ b/plugins/java-decompiler/testData/ExtendsList.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/ExtendsList.java b/plugins/java-decompiler/testData/ExtendsList.java
new file mode 100644
index 000000000000..19fbe6d66705
--- /dev/null
+++ b/plugins/java-decompiler/testData/ExtendsList.java
@@ -0,0 +1,9 @@
+public class ExtendsList {
+ static <T extends Comparable<? super T>> T m1(T t) {
+ return null;
+ }
+
+ static <T extends Object & Comparable<? super T>> T m2(T t) {
+ return null;
+ }
+} \ No newline at end of file
diff --git a/plugins/java-decompiler/testData/ExtendsList.txt b/plugins/java-decompiler/testData/ExtendsList.txt
new file mode 100644
index 000000000000..6996123b6a3d
--- /dev/null
+++ b/plugins/java-decompiler/testData/ExtendsList.txt
@@ -0,0 +1,19 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+
+public class ExtendsList {
+
+ public ExtendsList() {
+ }
+
+ static <T extends Comparable<? super T>> T m1(T var0) {
+ return null;
+ }
+
+ static <T extends Object & Comparable<? super T>> T m2(T var0) {
+ return null;
+ }
+}
diff --git a/plugins/java-decompiler/testData/Parameters$1Local.class b/plugins/java-decompiler/testData/Parameters$1Local.class
new file mode 100644
index 000000000000..a9c187cc05d7
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters$1Local.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Parameters$C1.class b/plugins/java-decompiler/testData/Parameters$C1.class
new file mode 100644
index 000000000000..882226ceb63c
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters$C1.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Parameters$C2.class b/plugins/java-decompiler/testData/Parameters$C2.class
new file mode 100644
index 000000000000..85a98c6f72dd
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters$C2.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Parameters.class b/plugins/java-decompiler/testData/Parameters.class
new file mode 100644
index 000000000000..f29432cf1fd0
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters.class
Binary files differ
diff --git a/plugins/java-decompiler/testData/Parameters.java b/plugins/java-decompiler/testData/Parameters.java
new file mode 100644
index 000000000000..be18b4e6e06f
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters.java
@@ -0,0 +1,23 @@
+public class Parameters {
+ Parameters(@Deprecated int p01) { }
+ void m1(@Deprecated int p02) { }
+ static void m2(@Deprecated int p03) { }
+
+ class C1 {
+ C1(@Deprecated int p11) { }
+ void m(@Deprecated int p12) { }
+ }
+
+ static class C2 {
+ C2(@Deprecated int p21) { }
+ void m1(@Deprecated int p22) { }
+ static void m2(@Deprecated int p23) { }
+ }
+
+ void local() {
+ class Local {
+ Local(@Deprecated int p31) { }
+ void m(@Deprecated int p32) { }
+ }
+ }
+} \ No newline at end of file
diff --git a/plugins/java-decompiler/testData/Parameters.txt b/plugins/java-decompiler/testData/Parameters.txt
new file mode 100644
index 000000000000..45a856abdd89
--- /dev/null
+++ b/plugins/java-decompiler/testData/Parameters.txt
@@ -0,0 +1,50 @@
+//
+// Source code recreated from a .class file by IntelliJ IDEA
+// (powered by Fernflower decompiler)
+//
+
+
+public class Parameters {
+
+ Parameters(@Deprecated int var1) {
+ }
+
+ void m1(@Deprecated int var1) {
+ }
+
+ static void m2(@Deprecated int var0) {
+ }
+
+ void local() {
+ class Local {
+
+ Local(@Deprecated int var2) {
+ }
+
+ void m(@Deprecated int var1) {
+ }
+ }
+
+ }
+
+ static class C2 {
+
+ C2(@Deprecated int var1) {
+ }
+
+ void m1(@Deprecated int var1) {
+ }
+
+ static void m2(@Deprecated int var0) {
+ }
+ }
+
+ class C1 {
+
+ C1(@Deprecated int var2) {
+ }
+
+ void m(@Deprecated int var1) {
+ }
+ }
+}