diff --git a/pom.xml b/pom.xml
index 340282c..8941020 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,37 +13,20 @@
-
- org.spigotmc
- eclipse-formatter
- 3.14.0-spigotmc-SNAPSHOT
-
+
./src
-
- net.md-5
- determiner
- 0.1
-
-
- process-classes
-
- transform
-
-
-
-
org.apache.maven.plugins
maven-compiler-plugin
3.2
-
- 1.6
+
+ 9
diff --git a/src/org/jetbrains/java/decompiler/code/CodeConstants.java b/src/org/jetbrains/java/decompiler/code/CodeConstants.java
index 4a7ef0f..2c5cb42 100644
--- a/src/org/jetbrains/java/decompiler/code/CodeConstants.java
+++ b/src/org/jetbrains/java/decompiler/code/CodeConstants.java
@@ -1,31 +1,22 @@
-/*
- * 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.
- */
+// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
+@SuppressWarnings({"unused", "SpellCheckingInspection"})
public interface CodeConstants {
-
// ----------------------------------------------------------------------
// BYTECODE VERSIONS
// ----------------------------------------------------------------------
- int BYTECODE_JAVA_LE_4 = 1;
- int BYTECODE_JAVA_5 = 2;
- int BYTECODE_JAVA_6 = 3;
- int BYTECODE_JAVA_7 = 4;
- int BYTECODE_JAVA_8 = 5;
+ int BYTECODE_JAVA_LE_4 = 48;
+ int BYTECODE_JAVA_5 = 49;
+ int BYTECODE_JAVA_6 = 50;
+ int BYTECODE_JAVA_7 = 51;
+ int BYTECODE_JAVA_8 = 52;
+ int BYTECODE_JAVA_9 = 53;
+ int BYTECODE_JAVA_10 = 54;
+ int BYTECODE_JAVA_11 = 55;
+ int BYTECODE_JAVA_12 = 56;
+ int BYTECODE_JAVA_13 = 57;
// ----------------------------------------------------------------------
// VARIABLE TYPES
@@ -63,20 +54,6 @@ public interface CodeConstants {
int TYPE_FAMILY_DOUBLE = 5;
int TYPE_FAMILY_OBJECT = 6;
- // ----------------------------------------------------------------------
- // MODULE CONSTANTS
- // ----------------------------------------------------------------------
-
- int STACKSIZE_SIMPLE = 1;
- int STACKSIZE_DOUBLE = 2;
-
- int VAR_LOCAL = 0;
- int VAR_STACK = 1;
-
- int VAR_WRITE = 0;
- int VAR_READ = 1;
-
-
// ----------------------------------------------------------------------
// ACCESS FLAGS
// ----------------------------------------------------------------------
@@ -87,6 +64,7 @@ public interface CodeConstants {
int ACC_STATIC = 0x0008;
int ACC_FINAL = 0x0010;
int ACC_SYNCHRONIZED = 0x0020;
+ int ACC_OPEN = 0x0020;
int ACC_NATIVE = 0x0100;
int ACC_ABSTRACT = 0x0400;
int ACC_STRICT = 0x0800;
@@ -97,6 +75,8 @@ public interface CodeConstants {
int ACC_SYNTHETIC = 0x1000;
int ACC_ANNOTATION = 0x2000;
int ACC_ENUM = 0x4000;
+ int ACC_MANDATED = 0x8000;
+ int ACC_MODULE = 0x8000;
// ----------------------------------------------------------------------
// CLASS FLAGS
@@ -105,17 +85,6 @@ public interface CodeConstants {
int ACC_SUPER = 0x0020;
int ACC_INTERFACE = 0x0200;
-
- // ----------------------------------------------------------------------
- // DEPENDENCY CONSTANTS
- // ----------------------------------------------------------------------
-
- int DEP_CONSTANT = 0;
- int DEP_UNKNOWN = 1;
- int DEP_GENERAL = 2;
- int DEP_PARAMS = 4;
- int DEP_STATIC = 8;
-
// ----------------------------------------------------------------------
// INSTRUCTION GROUPS
// ----------------------------------------------------------------------
@@ -145,6 +114,8 @@ public interface CodeConstants {
int CONSTANT_MethodHandle = 15;
int CONSTANT_MethodType = 16;
int CONSTANT_InvokeDynamic = 18;
+ int CONSTANT_Module = 19;
+ int CONSTANT_Package = 20;
// ----------------------------------------------------------------------
// MethodHandle reference_kind values
@@ -351,7 +322,6 @@ public interface CodeConstants {
int opc_invokestatic = 184;
int opc_invokeinterface = 185;
int opc_invokedynamic = 186;
- int opc_xxxunusedxxx = 186;
int opc_new = 187;
int opc_newarray = 188;
int opc_anewarray = 189;
@@ -367,4 +337,7 @@ public interface CodeConstants {
int opc_ifnonnull = 199;
int opc_goto_w = 200;
int opc_jsr_w = 201;
-}
+
+ String CLINIT_NAME = "";
+ String INIT_NAME = "";
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/ConstantsUtil.java b/src/org/jetbrains/java/decompiler/code/ConstantsUtil.java
deleted file mode 100644
index 79eecdf..0000000
--- a/src/org/jetbrains/java/decompiler/code/ConstantsUtil.java
+++ /dev/null
@@ -1,482 +0,0 @@
-/*
- * 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.code;
-
-import org.jetbrains.java.decompiler.code.optinstructions.*;
-
-public class ConstantsUtil {
-
- public static String getName(int opcode) {
- return opcodeNames[opcode];
- }
-
- public static Instruction getInstructionInstance(int opcode, boolean wide, int group, int bytecode_version, int[] operands) {
-
- Instruction instr = getInstructionInstance(opcode, bytecode_version);
- instr.wide = wide;
- instr.group = group;
- instr.bytecode_version = bytecode_version;
- instr.setOperands(operands);
-
- return instr;
- }
-
- private static Instruction getInstructionInstance(int opcode, int bytecode_version) {
- try {
- Instruction instr;
-
- if ((opcode >= CodeConstants.opc_ifeq &&
- opcode <= CodeConstants.opc_if_acmpne) ||
- opcode == CodeConstants.opc_ifnull ||
- opcode == CodeConstants.opc_ifnonnull) {
- instr = new IfInstruction();
- }
- else {
-
- Class cl = opcodeClasses[opcode];
-
- if (opcode == CodeConstants.opc_invokedynamic && bytecode_version < CodeConstants.BYTECODE_JAVA_7) {
- cl = null; // instruction unused in Java 6 and before
- }
-
- if (cl == null) {
- instr = new Instruction();
- }
- else {
- instr = (Instruction)cl.newInstance();
- }
- }
-
- instr.opcode = opcode;
- return instr;
- }
- catch (Exception ex) {
- return null;
- }
- }
-
-
- private static String[] opcodeNames = {
- "nop", // "nop",
- "aconst_null", // "aconst_null",
- "iconst_m1", // "iconst_m1",
- "iconst_0", // "iconst_0",
- "iconst_1", // "iconst_1",
- "iconst_2", // "iconst_2",
- "iconst_3", // "iconst_3",
- "iconst_4", // "iconst_4",
- "iconst_5", // "iconst_5",
- "lconst_0", // "lconst_0",
- "lconst_1", // "lconst_1",
- "fconst_0", // "fconst_0",
- "fconst_1", // "fconst_1",
- "fconst_2", // "fconst_2",
- "dconst_0", // "dconst_0",
- "dconst_1", // "dconst_1",
- "bipush", // "bipush",
- "sipush", // "sipush",
- "ldc", // "ldc",
- "ldc_w", // "ldc_w",
- "ldc2_w", // "ldc2_w",
- "iload", // "iload",
- "lload", // "lload",
- "fload", // "fload",
- "dload", // "dload",
- "aload", // "aload",
- "iload_0", // "iload_0",
- "iload_1", // "iload_1",
- "iload_2", // "iload_2",
- "iload_3", // "iload_3",
- "lload_0", // "lload_0",
- "lload_1", // "lload_1",
- "lload_2", // "lload_2",
- "lload_3", // "lload_3",
- "fload_0", // "fload_0",
- "fload_1", // "fload_1",
- "fload_2", // "fload_2",
- "fload_3", // "fload_3",
- "dload_0", // "dload_0",
- "dload_1", // "dload_1",
- "dload_2", // "dload_2",
- "dload_3", // "dload_3",
- "aload_0", // "aload_0",
- "aload_1", // "aload_1",
- "aload_2", // "aload_2",
- "aload_3", // "aload_3",
- "iaload", // "iaload",
- "laload", // "laload",
- "faload", // "faload",
- "daload", // "daload",
- "aaload", // "aaload",
- "baload", // "baload",
- "caload", // "caload",
- "saload", // "saload",
- "istore", // "istore",
- "lstore", // "lstore",
- "fstore", // "fstore",
- "dstore", // "dstore",
- "astore", // "astore",
- "istore_0", // "istore_0",
- "istore_1", // "istore_1",
- "istore_2", // "istore_2",
- "istore_3", // "istore_3",
- "lstore_0", // "lstore_0",
- "lstore_1", // "lstore_1",
- "lstore_2", // "lstore_2",
- "lstore_3", // "lstore_3",
- "fstore_0", // "fstore_0",
- "fstore_1", // "fstore_1",
- "fstore_2", // "fstore_2",
- "fstore_3", // "fstore_3",
- "dstore_0", // "dstore_0",
- "dstore_1", // "dstore_1",
- "dstore_2", // "dstore_2",
- "dstore_3", // "dstore_3",
- "astore_0", // "astore_0",
- "astore_1", // "astore_1",
- "astore_2", // "astore_2",
- "astore_3", // "astore_3",
- "iastore", // "iastore",
- "lastore", // "lastore",
- "fastore", // "fastore",
- "dastore", // "dastore",
- "aastore", // "aastore",
- "bastore", // "bastore",
- "castore", // "castore",
- "sastore", // "sastore",
- "pop", // "pop",
- "pop2", // "pop2",
- "dup", // "dup",
- "dup_x1", // "dup_x1",
- "dup_x2", // "dup_x2",
- "dup2", // "dup2",
- "dup2_x1", // "dup2_x1",
- "dup2_x2", // "dup2_x2",
- "swap", // "swap",
- "iadd", // "iadd",
- "ladd", // "ladd",
- "fadd", // "fadd",
- "dadd", // "dadd",
- "isub", // "isub",
- "lsub", // "lsub",
- "fsub", // "fsub",
- "dsub", // "dsub",
- "imul", // "imul",
- "lmul", // "lmul",
- "fmul", // "fmul",
- "dmul", // "dmul",
- "idiv", // "idiv",
- "ldiv", // "ldiv",
- "fdiv", // "fdiv",
- "ddiv", // "ddiv",
- "irem", // "irem",
- "lrem", // "lrem",
- "frem", // "frem",
- "drem", // "drem",
- "ineg", // "ineg",
- "lneg", // "lneg",
- "fneg", // "fneg",
- "dneg", // "dneg",
- "ishl", // "ishl",
- "lshl", // "lshl",
- "ishr", // "ishr",
- "lshr", // "lshr",
- "iushr", // "iushr",
- "lushr", // "lushr",
- "iand", // "iand",
- "land", // "land",
- "ior", // "ior",
- "lor", // "lor",
- "ixor", // "ixor",
- "lxor", // "lxor",
- "iinc", // "iinc",
- "i2l", // "i2l",
- "i2f", // "i2f",
- "i2d", // "i2d",
- "l2i", // "l2i",
- "l2f", // "l2f",
- "l2d", // "l2d",
- "f2i", // "f2i",
- "f2l", // "f2l",
- "f2d", // "f2d",
- "d2i", // "d2i",
- "d2l", // "d2l",
- "d2f", // "d2f",
- "i2b", // "i2b",
- "i2c", // "i2c",
- "i2s", // "i2s",
- "lcmp", // "lcmp",
- "fcmpl", // "fcmpl",
- "fcmpg", // "fcmpg",
- "dcmpl", // "dcmpl",
- "dcmpg", // "dcmpg",
- "ifeq", // "ifeq",
- "ifne", // "ifne",
- "iflt", // "iflt",
- "ifge", // "ifge",
- "ifgt", // "ifgt",
- "ifle", // "ifle",
- "if_icmpeq", // "if_icmpeq",
- "if_icmpne", // "if_icmpne",
- "if_icmplt", // "if_icmplt",
- "if_icmpge", // "if_icmpge",
- "if_icmpgt", // "if_icmpgt",
- "if_icmple", // "if_icmple",
- "if_acmpeq", // "if_acmpeq",
- "if_acmpne", // "if_acmpne",
- "goto", // "goto",
- "jsr", // "jsr",
- "ret", // "ret",
- "tableswitch", // "tableswitch",
- "lookupswitch", // "lookupswitch",
- "ireturn", // "ireturn",
- "lreturn", // "lreturn",
- "freturn", // "freturn",
- "dreturn", // "dreturn",
- "areturn", // "areturn",
- "return", // "return",
- "getstatic", // "getstatic",
- "putstatic", // "putstatic",
- "getfield", // "getfield",
- "putfield", // "putfield",
- "invokevirtual", // "invokevirtual",
- "invokespecial", // "invokespecial",
- "invokestatic", // "invokestatic",
- "invokeinterface", // "invokeinterface",
- //"xxxunusedxxx", // "xxxunusedxxx", Java 6 and before
- "invokedynamic", // "invokedynamic", Java 7 and later
- "new", // "new",
- "newarray", // "newarray",
- "anewarray", // "anewarray",
- "arraylength", // "arraylength",
- "athrow", // "athrow",
- "checkcast", // "checkcast",
- "instanceof", // "instanceof",
- "monitorenter", // "monitorenter",
- "monitorexit", // "monitorexit",
- "wide", // "wide",
- "multianewarray", // "multianewarray",
- "ifnull", // "ifnull",
- "ifnonnull", // "ifnonnull",
- "goto_w", // "goto_w",
- "jsr_w" // "jsr_w"
- };
-
- private static Class[] opcodeClasses = {
- null, // "nop",
- null, // "aconst_null",
- null, // "iconst_m1",
- null, // "iconst_0",
- null, // "iconst_1",
- null, // "iconst_2",
- null, // "iconst_3",
- null, // "iconst_4",
- null, // "iconst_5",
- null, // "lconst_0",
- null, // "lconst_1",
- null, // "fconst_0",
- null, // "fconst_1",
- null, // "fconst_2",
- null, // "dconst_0",
- null, // "dconst_1",
- BIPUSH.class, // "bipush",
- SIPUSH.class, // "sipush",
- LDC.class, // "ldc",
- LDC_W.class, // "ldc_w",
- LDC2_W.class, // "ldc2_w",
- ILOAD.class, // "iload",
- LLOAD.class, // "lload",
- FLOAD.class, // "fload",
- DLOAD.class, // "dload",
- ALOAD.class, // "aload",
- null, // "iload_0",
- null, // "iload_1",
- null, // "iload_2",
- null, // "iload_3",
- null, // "lload_0",
- null, // "lload_1",
- null, // "lload_2",
- null, // "lload_3",
- null, // "fload_0",
- null, // "fload_1",
- null, // "fload_2",
- null, // "fload_3",
- null, // "dload_0",
- null, // "dload_1",
- null, // "dload_2",
- null, // "dload_3",
- null, // "aload_0",
- null, // "aload_1",
- null, // "aload_2",
- null, // "aload_3",
- null, // "iaload",
- null, // "laload",
- null, // "faload",
- null, // "daload",
- null, // "aaload",
- null, // "baload",
- null, // "caload",
- null, // "saload",
- ISTORE.class, // "istore",
- LSTORE.class, // "lstore",
- FSTORE.class, // "fstore",
- DSTORE.class, // "dstore",
- ASTORE.class, // "astore",
- null, // "istore_0",
- null, // "istore_1",
- null, // "istore_2",
- null, // "istore_3",
- null, // "lstore_0",
- null, // "lstore_1",
- null, // "lstore_2",
- null, // "lstore_3",
- null, // "fstore_0",
- null, // "fstore_1",
- null, // "fstore_2",
- null, // "fstore_3",
- null, // "dstore_0",
- null, // "dstore_1",
- null, // "dstore_2",
- null, // "dstore_3",
- null, // "astore_0",
- null, // "astore_1",
- null, // "astore_2",
- null, // "astore_3",
- null, // "iastore",
- null, // "lastore",
- null, // "fastore",
- null, // "dastore",
- null, // "aastore",
- null, // "bastore",
- null, // "castore",
- null, // "sastore",
- null, // "pop",
- null, // "pop2",
- null, // "dup",
- null, // "dup_x1",
- null, // "dup_x2",
- null, // "dup2",
- null, // "dup2_x1",
- null, // "dup2_x2",
- null, // "swap",
- null, // "iadd",
- null, // "ladd",
- null, // "fadd",
- null, // "dadd",
- null, // "isub",
- null, // "lsub",
- null, // "fsub",
- null, // "dsub",
- null, // "imul",
- null, // "lmul",
- null, // "fmul",
- null, // "dmul",
- null, // "idiv",
- null, // "ldiv",
- null, // "fdiv",
- null, // "ddiv",
- null, // "irem",
- null, // "lrem",
- null, // "frem",
- null, // "drem",
- null, // "ineg",
- null, // "lneg",
- null, // "fneg",
- null, // "dneg",
- null, // "ishl",
- null, // "lshl",
- null, // "ishr",
- null, // "lshr",
- null, // "iushr",
- null, // "lushr",
- null, // "iand",
- null, // "land",
- null, // "ior",
- null, // "lor",
- null, // "ixor",
- null, // "lxor",
- IINC.class, // "iinc",
- null, // "i2l",
- null, // "i2f",
- null, // "i2d",
- null, // "l2i",
- null, // "l2f",
- null, // "l2d",
- null, // "f2i",
- null, // "f2l",
- null, // "f2d",
- null, // "d2i",
- null, // "d2l",
- null, // "d2f",
- null, // "i2b",
- null, // "i2c",
- null, // "i2s",
- null, // "lcmp",
- null, // "fcmpl",
- null, // "fcmpg",
- null, // "dcmpl",
- null, // "dcmpg",
- null, // "ifeq",
- null, // "ifne",
- null, // "iflt",
- null, // "ifge",
- null, // "ifgt",
- null, // "ifle",
- null, // "if_icmpeq",
- null, // "if_icmpne",
- null, // "if_icmplt",
- null, // "if_icmpge",
- null, // "if_icmpgt",
- null, // "if_icmple",
- null, // "if_acmpeq",
- null, // "if_acmpne",
- GOTO.class, // "goto",
- JSR.class, // "jsr",
- RET.class, // "ret",
- TABLESWITCH.class, // "tableswitch",
- LOOKUPSWITCH.class, // "lookupswitch",
- null, // "ireturn",
- null, // "lreturn",
- null, // "freturn",
- null, // "dreturn",
- null, // "areturn",
- null, // "return",
- GETSTATIC.class, // "getstatic",
- PUTSTATIC.class, // "putstatic",
- GETFIELD.class, // "getfield",
- PUTFIELD.class, // "putfield",
- INVOKEVIRTUAL.class, // "invokevirtual",
- INVOKESPECIAL.class, // "invokespecial",
- INVOKESTATIC.class, // "invokestatic",
- INVOKEINTERFACE.class, // "invokeinterface",
- INVOKEDYNAMIC.class, // "xxxunusedxxx" Java 6 and before, "invokedynamic" Java 7 and later
- NEW.class, // "new",
- NEWARRAY.class, // "newarray",
- ANEWARRAY.class, // "anewarray",
- null, // "arraylength",
- null, // "athrow",
- CHECKCAST.class, // "checkcast",
- INSTANCEOF.class, // "instanceof",
- null, // "monitorenter",
- null, // "monitorexit",
- null, // "wide",
- MULTIANEWARRAY.class, // "multianewarray",
- null, // "ifnull",
- null, // "ifnonnull",
- GOTO_W.class, // "goto_w",
- JSR_W.class // "jsr_w"
- };
-}
diff --git a/src/org/jetbrains/java/decompiler/code/ExceptionHandler.java b/src/org/jetbrains/java/decompiler/code/ExceptionHandler.java
index 2927294..0d20726 100644
--- a/src/org/jetbrains/java/decompiler/code/ExceptionHandler.java
+++ b/src/org/jetbrains/java/decompiler/code/ExceptionHandler.java
@@ -1,27 +1,9 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.main.DecompilerContext;
-import java.io.DataOutputStream;
-import java.io.IOException;
-
public class ExceptionHandler {
-
public int from = 0;
public int to = 0;
public int handler = 0;
@@ -30,32 +12,12 @@ public class ExceptionHandler {
public int to_instr = 0;
public int handler_instr = 0;
- public int class_index = 0;
public String exceptionClass = null;
- public ExceptionHandler() {
- }
-
- public ExceptionHandler(int from_raw, int to_raw, int handler_raw, String exceptionClass) {
- this.from = from_raw;
- this.to = to_raw;
- this.handler = handler_raw;
- this.exceptionClass = exceptionClass;
- }
-
- public void writeToStream(DataOutputStream out) throws IOException {
- out.writeShort(from);
- out.writeShort(to);
- out.writeShort(handler);
- out.writeShort(class_index);
- }
-
public String toString() {
-
String new_line_separator = DecompilerContext.getNewLineSeparator();
-
return "from: " + from + " to: " + to + " handler: " + handler + new_line_separator +
"from_instr: " + from_instr + " to_instr: " + to_instr + " handler_instr: " + handler_instr + new_line_separator +
"exceptionClass: " + exceptionClass + new_line_separator;
}
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/ExceptionTable.java b/src/org/jetbrains/java/decompiler/code/ExceptionTable.java
index e828a7f..7416623 100644
--- a/src/org/jetbrains/java/decompiler/code/ExceptionTable.java
+++ b/src/org/jetbrains/java/decompiler/code/ExceptionTable.java
@@ -1,58 +1,19 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
-import org.jetbrains.java.decompiler.code.interpreter.Util;
-import org.jetbrains.java.decompiler.struct.StructContext;
-
-import java.util.ArrayList;
+import java.util.Collections;
import java.util.List;
public class ExceptionTable {
+ public static final ExceptionTable EMPTY = new ExceptionTable(Collections.emptyList());
- private List handlers = new ArrayList();
-
- public ExceptionTable() {
- }
+ private final List handlers;
public ExceptionTable(List handlers) {
this.handlers = handlers;
}
-
- public ExceptionHandler getHandlerByClass(StructContext context, int line, String valclass, boolean withany) {
-
- ExceptionHandler res = null; // no handler found
-
- for (ExceptionHandler handler : handlers) {
- if (handler.from <= line && handler.to > line) {
- String name = handler.exceptionClass;
-
- if ((withany && name == null) || // any -> finally or synchronized handler
- (name != null && Util.instanceOf(context, valclass, name))) {
- res = handler;
- break;
- }
- }
- }
-
- return res;
- }
-
public List getHandlers() {
return handlers;
}
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/FullInstructionSequence.java b/src/org/jetbrains/java/decompiler/code/FullInstructionSequence.java
index eb8f819..b568a24 100644
--- a/src/org/jetbrains/java/decompiler/code/FullInstructionSequence.java
+++ b/src/org/jetbrains/java/decompiler/code/FullInstructionSequence.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
@@ -25,7 +11,7 @@ public class FullInstructionSequence extends InstructionSequence {
// *****************************************************************************
public FullInstructionSequence(VBStyleCollection collinstr, ExceptionTable extable) {
- this.collinstr = collinstr;
+ super(collinstr);
this.exceptionTable = extable;
// translate raw exception handlers to instr
diff --git a/src/org/jetbrains/java/decompiler/code/IfInstruction.java b/src/org/jetbrains/java/decompiler/code/IfInstruction.java
deleted file mode 100644
index 1d4bf6c..0000000
--- a/src/org/jetbrains/java/decompiler/code/IfInstruction.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.code;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-/*
- * opc_ifeq, opc_ifne, opc_iflt, opc_ifge, opc_ifgt, opc_ifle, opc_if_icmpeq, opc_if_icmpne, opc_if_icmplt,
- * opc_if_icmpge, opc_if_icmpgt, opc_if_icmple, opc_if_acmpeq, opc_if_acmpne, opc_ifnull, opc_ifnonnull
- */
-
-public class IfInstruction extends JumpInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opcode);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/Instruction.java b/src/org/jetbrains/java/decompiler/code/Instruction.java
index d77f3b4..1a260f2 100644
--- a/src/org/jetbrains/java/decompiler/code/Instruction.java
+++ b/src/org/jetbrains/java/decompiler/code/Instruction.java
@@ -1,126 +1,87 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
-import java.io.DataOutputStream;
-import java.io.IOException;
+import org.jetbrains.java.decompiler.util.TextUtil;
public class Instruction implements CodeConstants {
-
- // *****************************************************************************
- // public fields
- // *****************************************************************************
-
- public int opcode;
-
- public int group = CodeConstants.GROUP_GENERAL;
-
- public boolean wide = false;
-
- public int bytecode_version = BYTECODE_JAVA_LE_4;
-
- // *****************************************************************************
- // private fields
- // *****************************************************************************
-
- private int[] operands = null;
-
- // *****************************************************************************
- // public methods
- // *****************************************************************************
-
- public Instruction() {
+ public static Instruction create(int opcode, boolean wide, int group, int bytecodeVersion, int[] operands) {
+ if (opcode >= opc_ifeq && opcode <= opc_if_acmpne ||
+ opcode == opc_ifnull || opcode == opc_ifnonnull ||
+ opcode == opc_jsr || opcode == opc_jsr_w ||
+ opcode == opc_goto || opcode == opc_goto_w) {
+ return new JumpInstruction(opcode, group, wide, bytecodeVersion, operands);
+ }
+ else if (opcode == opc_tableswitch || opcode == opc_lookupswitch) {
+ return new SwitchInstruction(opcode, group, wide, bytecodeVersion, operands);
+ }
+ else {
+ return new Instruction(opcode, group, wide, bytecodeVersion, operands);
+ }
}
- public int length() {
- return 1;
+ public static boolean equals(Instruction i1, Instruction i2) {
+ return i1 != null && i2 != null &&
+ (i1 == i2 ||
+ i1.opcode == i2.opcode &&
+ i1.wide == i2.wide &&
+ i1.operandsCount() == i2.operandsCount());
}
+ public final int opcode;
+ public final int group;
+ public final boolean wide;
+ public final int bytecodeVersion;
+
+ protected final int[] operands;
+
+ public Instruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
+ this.opcode = opcode;
+ this.group = group;
+ this.wide = wide;
+ this.bytecodeVersion = bytecodeVersion;
+ this.operands = operands;
+ }
+
+ public void initInstruction(InstructionSequence seq) { }
+
public int operandsCount() {
- return (operands == null) ? 0 : operands.length;
+ return operands == null ? 0 : operands.length;
}
- public int getOperand(int index) {
+ public int operand(int index) {
return operands[index];
}
- public Instruction clone() {
- return ConstantsUtil.getInstructionInstance(opcode, wide, group, bytecode_version, operands == null ? null : operands.clone());
+ public boolean canFallThrough() {
+ return opcode != opc_goto && opcode != opc_goto_w && opcode != opc_ret &&
+ !(opcode >= opc_ireturn && opcode <= opc_return) &&
+ opcode != opc_athrow &&
+ opcode != opc_jsr && opcode != opc_tableswitch && opcode != opc_lookupswitch;
}
+ @Override
public String toString() {
-
- String res = wide ? "@wide " : "";
- res += "@" + ConstantsUtil.getName(opcode);
+ StringBuilder res = new StringBuilder();
+ if (wide) res.append("@wide ");
+ res.append("@").append(TextUtil.getInstructionName(opcode));
int len = operandsCount();
for (int i = 0; i < len; i++) {
int op = operands[i];
if (op < 0) {
- res += " -" + Integer.toHexString(-op);
+ res.append(" -").append(Integer.toHexString(-op));
}
else {
- res += " " + Integer.toHexString(op);
+ res.append(" ").append(Integer.toHexString(op));
}
}
- return res;
+ return res.toString();
}
- public boolean canFallthrough() {
- return opcode != opc_goto && opcode != opc_goto_w && opcode != opc_ret &&
- !(opcode >= opc_ireturn && opcode <= opc_return) && opcode != opc_athrow
- && opcode != opc_jsr && opcode != opc_tableswitch && opcode != opc_lookupswitch;
+ @Override
+ @SuppressWarnings("MethodDoesntCallSuperMethod")
+ public Instruction clone() {
+ return create(opcode, wide, group, bytecodeVersion, operands == null ? null : operands.clone());
}
-
- public boolean equalsInstruction(Instruction instr) {
- if (opcode != instr.opcode || wide != instr.wide
- || operandsCount() != instr.operandsCount()) {
- return false;
- }
-
- if (operands != null) {
- for (int i = 0; i < operands.length; i++) {
- if (operands[i] != instr.getOperand(i)) {
- return false;
- }
- }
- }
-
- return true;
- }
-
- // should be overwritten by subclasses
- public void initInstruction(InstructionSequence seq) {
- }
-
- // should be overwritten by subclasses
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opcode);
- }
-
- // *****************************************************************************
- // getter and setter methods
- // *****************************************************************************
-
- public int[] getOperands() {
- return operands;
- }
-
- public void setOperands(int[] operands) {
- this.operands = operands;
- }
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/InstructionSequence.java b/src/org/jetbrains/java/decompiler/code/InstructionSequence.java
index 709a85d..3d0cab0 100644
--- a/src/org/jetbrains/java/decompiler/code/InstructionSequence.java
+++ b/src/org/jetbrains/java/decompiler/code/InstructionSequence.java
@@ -1,50 +1,36 @@
-/*
- * 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.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
-import org.jetbrains.java.decompiler.code.interpreter.Util;
import org.jetbrains.java.decompiler.main.DecompilerContext;
-import org.jetbrains.java.decompiler.struct.StructContext;
-import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import org.jetbrains.java.decompiler.util.TextUtil;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.List;
-
-
public abstract class InstructionSequence {
// *****************************************************************************
// private fields
// *****************************************************************************
- protected VBStyleCollection collinstr = new VBStyleCollection();
+ protected final VBStyleCollection collinstr;
protected int pointer = 0;
- protected ExceptionTable exceptionTable = new ExceptionTable();
+ protected ExceptionTable exceptionTable = ExceptionTable.EMPTY;
+
+ protected InstructionSequence() {
+ this(new VBStyleCollection<>());
+ }
+
+ protected InstructionSequence(VBStyleCollection collinstr) {
+ this.collinstr = collinstr;
+ }
// *****************************************************************************
// public methods
// *****************************************************************************
// to nbe overwritten
+ @Override
public InstructionSequence clone() {
return null;
}
@@ -52,7 +38,7 @@ public abstract class InstructionSequence {
public void clear() {
collinstr.clear();
pointer = 0;
- exceptionTable = new ExceptionTable();
+ exceptionTable = ExceptionTable.EMPTY;
}
public void addInstruction(Instruction inst, int offset) {
@@ -73,8 +59,10 @@ public abstract class InstructionSequence {
collinstr.remove(index);
}
- public Instruction getCurrentInstr() {
- return collinstr.get(pointer);
+ public void removeLast() {
+ if (!collinstr.isEmpty()) {
+ collinstr.remove(collinstr.size() - 1);
+ }
}
public Instruction getInstr(int index) {
@@ -85,16 +73,12 @@ public abstract class InstructionSequence {
return collinstr.getLast();
}
- public int getCurrentOffset() {
- return collinstr.getKey(pointer).intValue();
- }
-
-public int getOffset(int index) {
- return collinstr.getKey(index).intValue();
+ public int getOffset(int index) {
+ return collinstr.getKey(index);
}
public int getPointerByAbsOffset(int offset) {
- Integer absoffset = new Integer(offset);
+ Integer absoffset = offset;
if (collinstr.containsKey(absoffset)) {
return collinstr.getIndexByKey(absoffset);
}
@@ -104,7 +88,7 @@ public int getOffset(int index) {
}
public int getPointerByRelOffset(int offset) {
- Integer absoffset = new Integer(collinstr.getKey(pointer).intValue() + offset);
+ Integer absoffset = collinstr.getKey(pointer) + offset;
if (collinstr.containsKey(absoffset)) {
return collinstr.getIndexByKey(absoffset);
}
@@ -113,13 +97,6 @@ public int getOffset(int index) {
}
}
- public void setPointerByAbsOffset(int offset) {
- Integer absoffset = new Integer(collinstr.getKey(pointer).intValue() + offset);
- if (collinstr.containsKey(absoffset)) {
- pointer = collinstr.getIndexByKey(absoffset);
- }
- }
-
public int length() {
return collinstr.size();
}
@@ -143,7 +120,7 @@ public int getOffset(int index) {
StringBuilder buf = new StringBuilder();
for (int i = 0; i < collinstr.size(); i++) {
- buf.append(InterpreterUtil.getIndentString(indent));
+ buf.append(TextUtil.getIndentString(indent));
buf.append(collinstr.getKey(i).intValue());
buf.append(": ");
buf.append(collinstr.get(i).toString());
@@ -153,58 +130,6 @@ public int getOffset(int index) {
return buf.toString();
}
- public void writeCodeToStream(DataOutputStream out) throws IOException {
-
- for (int i = 0; i < collinstr.size(); i++) {
- collinstr.get(i).writeToStream(out, collinstr.getKey(i).intValue());
- }
- }
-
- public void writeExceptionsToStream(DataOutputStream out) throws IOException {
-
- List handlers = exceptionTable.getHandlers();
-
- out.writeShort(handlers.size());
- for (int i = 0; i < handlers.size(); i++) {
- handlers.get(i).writeToStream(out);
- }
- }
-
- public void sortHandlers(final StructContext context) {
-
- Collections.sort(exceptionTable.getHandlers(), new Comparator() {
-
- public int compare(ExceptionHandler handler0, ExceptionHandler handler1) {
-
- if (handler0.to == handler1.to) {
- if (handler0.exceptionClass == null) {
- return 1;
- }
- else {
- if (handler1.exceptionClass == null) {
- return -1;
- }
- else if (handler0.exceptionClass.equals(handler1.exceptionClass)) {
- return (handler0.from > handler1.from) ? -1 : 1; // invalid code
- }
- else {
- if (Util.instanceOf(context, handler0.exceptionClass, handler1.exceptionClass)) {
- return -1;
- }
- else {
- return 1;
- }
- }
- }
- }
- else {
- return (handler0.to > handler1.to) ? 1 : -1;
- }
- }
- });
- }
-
-
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
@@ -220,8 +145,4 @@ public int getOffset(int index) {
public ExceptionTable getExceptionTable() {
return exceptionTable;
}
-
- public void setExceptionTable(ExceptionTable exceptionTable) {
- this.exceptionTable = exceptionTable;
- }
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/JumpInstruction.java b/src/org/jetbrains/java/decompiler/code/JumpInstruction.java
index 44f4ff9..129df62 100644
--- a/src/org/jetbrains/java/decompiler/code/JumpInstruction.java
+++ b/src/org/jetbrains/java/decompiler/code/JumpInstruction.java
@@ -1,42 +1,22 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
-/*
- * opc_ifeq, opc_ifne, opc_iflt, opc_ifge, opc_ifgt, opc_ifle, opc_if_icmpeq, opc_if_icmpne, opc_if_icmplt,
- * opc_if_icmpge, opc_if_icmpgt, opc_if_icmple, opc_if_acmpeq, opc_if_acmpne, opc_ifnull, opc_ifnonnull
- * opc_goto, opc_jsr, opc_goto_w, opc_jsr_w
- */
-
-
public class JumpInstruction extends Instruction {
-
public int destination;
- public JumpInstruction() {
+ public JumpInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
+ super(opcode, group, wide, bytecodeVersion, operands);
}
+ @Override
public void initInstruction(InstructionSequence seq) {
- destination = seq.getPointerByRelOffset(this.getOperand(0));
+ destination = seq.getPointerByRelOffset(this.operand(0));
}
+ @Override
public JumpInstruction clone() {
- JumpInstruction newinstr = (JumpInstruction)super.clone();
-
- newinstr.destination = destination;
- return newinstr;
+ JumpInstruction copy = (JumpInstruction)super.clone();
+ copy.destination = destination;
+ return copy;
}
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java b/src/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java
index bcc3c4a..0b62c51 100644
--- a/src/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java
+++ b/src/org/jetbrains/java/decompiler/code/SimpleInstructionSequence.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
import org.jetbrains.java.decompiler.util.VBStyleCollection;
@@ -23,17 +9,14 @@ public class SimpleInstructionSequence extends InstructionSequence {
}
public SimpleInstructionSequence(VBStyleCollection collinstr) {
- this.collinstr = collinstr;
+ super(collinstr);
}
+ @Override
public SimpleInstructionSequence clone() {
SimpleInstructionSequence newseq = new SimpleInstructionSequence(collinstr.clone());
newseq.setPointer(this.getPointer());
return newseq;
}
-
- public void removeInstruction(int index) {
- collinstr.remove(index);
- }
}
diff --git a/src/org/jetbrains/java/decompiler/code/SwitchInstruction.java b/src/org/jetbrains/java/decompiler/code/SwitchInstruction.java
index 6aa6a7f..61810d9 100644
--- a/src/org/jetbrains/java/decompiler/code/SwitchInstruction.java
+++ b/src/org/jetbrains/java/decompiler/code/SwitchInstruction.java
@@ -1,97 +1,61 @@
-/*
- * 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.
- */
+// Copyright 2000-2017 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code;
-/*
- * opc_tableswitch, lookupswitch
- */
-
public class SwitchInstruction extends Instruction {
-
private int[] destinations;
-
private int[] values;
+ private int defaultDestination;
- private int defaultdest;
-
- public SwitchInstruction() {
+ public SwitchInstruction(int opcode, int group, boolean wide, int bytecodeVersion, int[] operands) {
+ super(opcode, group, wide, bytecodeVersion, operands);
}
-
+ @Override
public void initInstruction(InstructionSequence seq) {
+ defaultDestination = seq.getPointerByRelOffset(operands[0]);
- int pref = (opcode == CodeConstants.opc_tableswitch ? 3 : 2);
- int len = this.getOperands().length - pref;
- defaultdest = seq.getPointerByRelOffset(this.getOperand(0));
-
+ int prefix = opcode == CodeConstants.opc_tableswitch ? 3 : 2;
+ int len = operands.length - prefix;
int low = 0;
-
if (opcode == CodeConstants.opc_lookupswitch) {
len /= 2;
}
else {
- low = this.getOperand(1);
+ low = operands[1];
}
destinations = new int[len];
values = new int[len];
-
for (int i = 0, k = 0; i < len; i++, k++) {
if (opcode == CodeConstants.opc_lookupswitch) {
- values[i] = this.getOperand(pref + k);
+ values[i] = operands[prefix + k];
k++;
}
else {
values[i] = low + k;
}
- destinations[i] = seq.getPointerByRelOffset(this.getOperand(pref + k));
+ destinations[i] = seq.getPointerByRelOffset(operands[prefix + k]);
}
}
- public SwitchInstruction clone() {
- SwitchInstruction newinstr = (SwitchInstruction)super.clone();
-
- newinstr.defaultdest = defaultdest;
- newinstr.destinations = destinations.clone();
- newinstr.values = values.clone();
-
- return newinstr;
- }
-
public int[] getDestinations() {
return destinations;
}
- public void setDestinations(int[] destinations) {
- this.destinations = destinations;
- }
-
- public int getDefaultdest() {
- return defaultdest;
- }
-
- public void setDefaultdest(int defaultdest) {
- this.defaultdest = defaultdest;
- }
-
public int[] getValues() {
return values;
}
- public void setValues(int[] values) {
- this.values = values;
+ public int getDefaultDestination() {
+ return defaultDestination;
}
-}
+
+ @Override
+ public SwitchInstruction clone() {
+ SwitchInstruction copy = (SwitchInstruction)super.clone();
+ copy.defaultDestination = defaultDestination;
+ copy.destinations = destinations.clone();
+ copy.values = values.clone();
+ return copy;
+ }
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java b/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java
index 28e0ae8..265ffca 100644
--- a/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java
+++ b/src/org/jetbrains/java/decompiler/code/cfg/BasicBlock.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code.cfg;
import org.jetbrains.java.decompiler.code.Instruction;
@@ -30,8 +16,7 @@ public class BasicBlock implements IGraphNode {
// public fields
// *****************************************************************************
- public int id = 0;
-
+ public int id;
public int mark = 0;
// *****************************************************************************
@@ -40,19 +25,11 @@ public class BasicBlock implements IGraphNode {
private InstructionSequence seq = new SimpleInstructionSequence();
- private List preds = new ArrayList();
-
- private List succs = new ArrayList();
-
- private List instrOldOffsets = new ArrayList();
-
- private List predExceptions = new ArrayList();
-
- private List succExceptions = new ArrayList();
-
-
- public BasicBlock() {
- }
+ private final List preds = new ArrayList<>();
+ private final List succs = new ArrayList<>();
+ private final List instrOldOffsets = new ArrayList<>();
+ private final List predExceptions = new ArrayList<>();
+ private final List succExceptions = new ArrayList<>();
public BasicBlock(int id) {
this.id = id;
@@ -62,24 +39,17 @@ public class BasicBlock implements IGraphNode {
// public methods
// *****************************************************************************
- public Object clone() {
+ @Override
+ @SuppressWarnings("MethodDoesntCallSuperMethod")
+ public BasicBlock clone() {
+ BasicBlock block = new BasicBlock(id);
- BasicBlock block = new BasicBlock();
- block.id = id;
block.setSeq(seq.clone());
- block.setInstrOldOffsets(new ArrayList(instrOldOffsets));
+ block.instrOldOffsets.addAll(instrOldOffsets);
return block;
}
- public void free() {
- preds.clear();
- succs.clear();
- instrOldOffsets.clear();
- succExceptions.clear();
- seq = new SimpleInstructionSequence();
- }
-
public Instruction getInstruction(int index) {
return seq.getInstr(index);
}
@@ -110,7 +80,7 @@ public class BasicBlock implements IGraphNode {
}
public void removePredecessor(BasicBlock block) {
- while (preds.remove(block)) ;
+ while (preds.remove(block)) /**/;
}
public void addSuccessor(BasicBlock block) {
@@ -119,11 +89,11 @@ public class BasicBlock implements IGraphNode {
}
public void removeSuccessor(BasicBlock block) {
- while (succs.remove(block)) ;
+ while (succs.remove(block)) /**/;
block.removePredecessor(this);
}
- // FIXME: unify block comparisons: id or direkt equality
+ // FIXME: unify block comparisons: id or direct equality
public void replaceSuccessor(BasicBlock oldBlock, BasicBlock newBlock) {
for (int i = 0; i < succs.size(); i++) {
if (succs.get(i).id == oldBlock.id) {
@@ -147,7 +117,7 @@ public class BasicBlock implements IGraphNode {
}
public void removePredecessorException(BasicBlock block) {
- while (predExceptions.remove(block)) ;
+ while (predExceptions.remove(block)) /**/;
}
public void addSuccessorException(BasicBlock block) {
@@ -158,7 +128,7 @@ public class BasicBlock implements IGraphNode {
}
public void removeSuccessorException(BasicBlock block) {
- while (succExceptions.remove(block)) ;
+ while (succExceptions.remove(block)) /**/;
block.removePredecessorException(this);
}
@@ -173,27 +143,6 @@ public class BasicBlock implements IGraphNode {
return id + ":" + new_line_separator + seq.toString(indent);
}
- public String toStringOldIndices() {
-
- String new_line_separator = DecompilerContext.getNewLineSeparator();
-
- StringBuilder buf = new StringBuilder();
-
- for (int i = 0; i < seq.length(); i++) {
- if (i < instrOldOffsets.size()) {
- buf.append(instrOldOffsets.get(i));
- }
- else {
- buf.append("-1");
- }
- buf.append(": ");
- buf.append(seq.getInstr(i).toString());
- buf.append(new_line_separator);
- }
-
- return buf.toString();
- }
-
public boolean isSuccessor(BasicBlock block) {
for (BasicBlock succ : succs) {
if (succ.id == block.id) {
@@ -203,15 +152,6 @@ public class BasicBlock implements IGraphNode {
return false;
}
- public boolean isPredecessor(BasicBlock block) {
- for (int i = 0; i < preds.size(); i++) {
- if (preds.get(i).id == block.id) {
- return true;
- }
- }
- return false;
- }
-
// *****************************************************************************
// getter and setter methods
// *****************************************************************************
@@ -220,12 +160,9 @@ public class BasicBlock implements IGraphNode {
return instrOldOffsets;
}
- public void setInstrOldOffsets(List instrInds) {
- this.instrOldOffsets = instrInds;
- }
-
+ @Override
public List extends IGraphNode> getPredecessors() {
- List lst = new ArrayList(preds);
+ List lst = new ArrayList<>(preds);
lst.addAll(predExceptions);
return lst;
}
@@ -234,10 +171,6 @@ public class BasicBlock implements IGraphNode {
return preds;
}
- public void setPreds(List preds) {
- this.preds = preds;
- }
-
public InstructionSequence getSeq() {
return seq;
}
@@ -250,25 +183,11 @@ public class BasicBlock implements IGraphNode {
return succs;
}
- public void setSuccs(List succs) {
- this.succs = succs;
- }
-
-
public List getSuccExceptions() {
return succExceptions;
}
-
- public void setSuccExceptions(List succExceptions) {
- this.succExceptions = succExceptions;
- }
-
public List getPredExceptions() {
return predExceptions;
}
-
- public void setPredExceptions(List predExceptions) {
- this.predExceptions = predExceptions;
- }
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java b/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java
index 44c58f0..f060fbd 100644
--- a/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java
+++ b/src/org/jetbrains/java/decompiler/code/cfg/ControlFlowGraph.java
@@ -1,24 +1,11 @@
-/*
- * 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.
- */
+// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code.cfg;
import org.jetbrains.java.decompiler.code.*;
import org.jetbrains.java.decompiler.code.interpreter.InstructionImpact;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import org.jetbrains.java.decompiler.modules.code.DeadCodeHelper;
+import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructMethod;
import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
import org.jetbrains.java.decompiler.struct.gen.DataPoint;
@@ -47,7 +34,7 @@ public class ControlFlowGraph implements CodeConstants {
private Map subroutines;
- private Set finallyExits = new HashSet();
+ private final Set finallyExits = new HashSet<>();
// *****************************************************************************
// constructors
@@ -62,19 +49,6 @@ public class ControlFlowGraph implements CodeConstants {
// public methods
// *****************************************************************************
- public void free() {
-
- for (BasicBlock block : blocks) {
- block.free();
- }
-
- blocks.clear();
- first = null;
- last = null;
- exceptions.clear();
- finallyExits.clear();
- }
-
public void removeMarkers() {
for (BasicBlock block : blocks) {
block.mark = 0;
@@ -82,6 +56,7 @@ public class ControlFlowGraph implements CodeConstants {
}
public String toString() {
+ if (blocks == null) return "Empty";
String new_line_separator = DecompilerContext.getNewLineSeparator();
@@ -93,12 +68,11 @@ public class ControlFlowGraph implements CodeConstants {
buf.append("----- Edges -----").append(new_line_separator);
List suc = block.getSuccs();
- for (int j = 0; j < suc.size(); j++) {
- buf.append(">>>>>>>>(regular) Block ").append(suc.get(j).id).append(new_line_separator);
+ for (BasicBlock aSuc : suc) {
+ buf.append(">>>>>>>>(regular) Block ").append(aSuc.id).append(new_line_separator);
}
suc = block.getSuccExceptions();
- for (int j = 0; j < suc.size(); j++) {
- BasicBlock handler = suc.get(j);
+ for (BasicBlock handler : suc) {
ExceptionRangeCFG range = getExceptionRange(handler, block);
if (range == null) {
@@ -123,9 +97,9 @@ public class ControlFlowGraph implements CodeConstants {
return buf.toString();
}
- public void inlineJsr(StructMethod mt) {
+ public void inlineJsr(StructClass cl, StructMethod mt) {
processJsr();
- removeJsr(mt);
+ removeJsr(cl, mt);
removeMarkers();
@@ -169,13 +143,7 @@ public class ControlFlowGraph implements CodeConstants {
}
}
- Iterator> it = subroutines.entrySet().iterator();
- while (it.hasNext()) {
- Entry ent = it.next();
- if (ent.getKey() == block || ent.getValue() == block) {
- it.remove();
- }
- }
+ subroutines.entrySet().removeIf(ent -> ent.getKey() == block || ent.getValue() == block);
}
public ExceptionRangeCFG getExceptionRange(BasicBlock handler, BasicBlock block) {
@@ -224,7 +192,7 @@ public class ControlFlowGraph implements CodeConstants {
short[] states = findStartInstructions(instrseq);
- Map mapInstrBlocks = new HashMap();
+ Map mapInstrBlocks = new HashMap<>();
VBStyleCollection colBlocks = createBasicBlocks(states, instrseq, mapInstrBlocks);
blocks = colBlocks;
@@ -243,7 +211,7 @@ public class ControlFlowGraph implements CodeConstants {
int len = seq.length();
short[] inststates = new short[len];
- Set excSet = new HashSet();
+ Set excSet = new HashSet<>();
for (ExceptionHandler handler : seq.getExceptionTable().getHandlers()) {
excSet.add(handler.from_instr);
@@ -255,7 +223,7 @@ public class ControlFlowGraph implements CodeConstants {
for (int i = 0; i < len; i++) {
// exception blocks
- if (excSet.contains(new Integer(i))) {
+ if (excSet.contains(i)) {
inststates[i] = 1;
}
@@ -274,7 +242,7 @@ public class ControlFlowGraph implements CodeConstants {
for (int j = dests.length - 1; j >= 0; j--) {
inststates[dests[j]] = 1;
}
- inststates[swinstr.getDefaultdest()] = 1;
+ inststates[swinstr.getDefaultDestination()] = 1;
if (i + 1 < len) {
inststates[i + 1] = 1;
}
@@ -292,10 +260,10 @@ public class ControlFlowGraph implements CodeConstants {
InstructionSequence instrseq,
Map mapInstrBlocks) {
- VBStyleCollection col = new VBStyleCollection();
+ VBStyleCollection col = new VBStyleCollection<>();
InstructionSequence currseq = null;
- ArrayList lstOffs = null;
+ List lstOffs = null;
int len = startblock.length;
short counter = 0;
@@ -305,14 +273,11 @@ public class ControlFlowGraph implements CodeConstants {
for (int i = 0; i < len; i++) {
if (startblock[i] == 1) {
- currentBlock = new BasicBlock();
- currentBlock.id = ++counter;
+ currentBlock = new BasicBlock(++counter);
- currseq = new SimpleInstructionSequence();
- lstOffs = new ArrayList();
+ currseq = currentBlock.getSeq();
+ lstOffs = currentBlock.getInstrOldOffsets();
- currentBlock.setSeq(currseq);
- currentBlock.setInstrOldOffsets(lstOffs);
col.addWithKey(currentBlock, currentBlock.id);
blockoffset = instrseq.getOffset(i);
@@ -338,7 +303,7 @@ public class ControlFlowGraph implements CodeConstants {
BasicBlock block = lstbb.get(i);
Instruction instr = block.getLastInstruction();
- boolean fallthrough = instr.canFallthrough();
+ boolean fallthrough = instr.canFallThrough();
BasicBlock bTemp;
switch (instr.group) {
@@ -352,10 +317,10 @@ public class ControlFlowGraph implements CodeConstants {
SwitchInstruction sinstr = (SwitchInstruction)instr;
int[] dests = sinstr.getDestinations();
- bTemp = mapInstrBlocks.get(((SwitchInstruction)instr).getDefaultdest());
+ bTemp = mapInstrBlocks.get(((SwitchInstruction)instr).getDefaultDestination());
block.addSuccessor(bTemp);
- for (int j = 0; j < dests.length; j++) {
- bTemp = mapInstrBlocks.get(dests[j]);
+ for (int dest1 : dests) {
+ bTemp = mapInstrBlocks.get(dest1);
block.addSuccessor(bTemp);
}
}
@@ -369,9 +334,9 @@ public class ControlFlowGraph implements CodeConstants {
private void setExceptionEdges(InstructionSequence instrseq, Map instrBlocks) {
- exceptions = new ArrayList();
+ exceptions = new ArrayList<>();
- Map mapRanges = new HashMap();
+ Map mapRanges = new HashMap<>();
for (ExceptionHandler handler : instrseq.getExceptionTable().getHandlers()) {
@@ -387,7 +352,7 @@ public class ControlFlowGraph implements CodeConstants {
}
else {
- List protectedRange = new ArrayList();
+ List protectedRange = new ArrayList<>();
for (int j = from.id; j < to.id; j++) {
BasicBlock block = blocks.getWithKey(j);
protectedRange.add(block);
@@ -396,7 +361,7 @@ public class ControlFlowGraph implements CodeConstants {
ExceptionRangeCFG range = new ExceptionRangeCFG(protectedRange, handle, handler.exceptionClass == null
? null
- : Arrays.asList(handler.exceptionClass));
+ : Collections.singletonList(handler.exceptionClass));
mapRanges.put(key, range);
exceptions.add(range);
@@ -406,19 +371,19 @@ public class ControlFlowGraph implements CodeConstants {
private void setSubroutineEdges() {
- final Map subroutines = new HashMap();
+ final Map subroutines = new LinkedHashMap<>();
for (BasicBlock block : blocks) {
if (block.getSeq().getLastInstr().opcode == CodeConstants.opc_jsr) {
- LinkedList stack = new LinkedList();
- LinkedList> stackJsrStacks = new LinkedList>();
+ LinkedList stack = new LinkedList<>();
+ LinkedList> stackJsrStacks = new LinkedList<>();
- Set setVisited = new HashSet();
+ Set setVisited = new HashSet<>();
stack.add(block);
- stackJsrStacks.add(new LinkedList());
+ stackJsrStacks.add(new LinkedList<>());
while (!stack.isEmpty()) {
@@ -451,7 +416,7 @@ public class ControlFlowGraph implements CodeConstants {
for (BasicBlock succ : node.getSuccs()) {
if (!setVisited.contains(succ)) {
stack.add(succ);
- stackJsrStacks.add(new LinkedList(jsrstack));
+ stackJsrStacks.add(new LinkedList<>(jsrstack));
}
}
}
@@ -468,7 +433,7 @@ public class ControlFlowGraph implements CodeConstants {
}
}
- private static class JsrRecord {
+ private static final class JsrRecord {
private final BasicBlock jsr;
private final Set range;
private final BasicBlock ret;
@@ -482,7 +447,7 @@ public class ControlFlowGraph implements CodeConstants {
private int processJsrRanges() {
- List lstJsrAll = new ArrayList();
+ List lstJsrAll = new ArrayList<>();
// get all jsr ranges
for (Entry ent : subroutines.entrySet()) {
@@ -494,7 +459,7 @@ public class ControlFlowGraph implements CodeConstants {
// sort ranges
// FIXME: better sort order
- List lstJsr = new ArrayList();
+ List lstJsr = new ArrayList<>();
for (JsrRecord arr : lstJsrAll) {
int i = 0;
for (; i < lstJsr.size(); i++) {
@@ -516,7 +481,7 @@ public class ControlFlowGraph implements CodeConstants {
Set set1 = arr1.range;
if (!set.contains(arr1.jsr) && !set1.contains(arr.jsr)) { // rang 0 doesn't contain entry 1 and vice versa
- Set setc = new HashSet(set);
+ Set setc = new HashSet<>(set);
setc.retainAll(set1);
if (!setc.isEmpty()) {
@@ -532,9 +497,9 @@ public class ControlFlowGraph implements CodeConstants {
private Set getJsrRange(BasicBlock jsr, BasicBlock ret) {
- Set blocks = new HashSet();
+ Set blocks = new HashSet<>();
- List lstNodes = new LinkedList();
+ List lstNodes = new LinkedList<>();
lstNodes.add(jsr);
BasicBlock dom = jsr.getSuccs().get(0);
@@ -596,8 +561,8 @@ public class ControlFlowGraph implements CodeConstants {
private void splitJsrRange(BasicBlock jsr, BasicBlock ret, Set common_blocks) {
- List lstNodes = new LinkedList();
- Map mapNewNodes = new HashMap();
+ List lstNodes = new LinkedList<>();
+ Map mapNewNodes = new HashMap<>();
lstNodes.add(jsr);
mapNewNodes.put(jsr.id, jsr);
@@ -633,9 +598,8 @@ public class ControlFlowGraph implements CodeConstants {
node.replaceSuccessor(child, mapNewNodes.get(childid));
}
else if (common_blocks.contains(child)) {
-
// make a copy of the current block
- BasicBlock copy = (BasicBlock)child.clone();
+ BasicBlock copy = child.clone();
copy.id = ++last_id;
// copy all successors
if (copy.getLastInstruction().opcode == CodeConstants.opc_ret &&
@@ -682,14 +646,14 @@ public class ControlFlowGraph implements CodeConstants {
ExceptionRangeCFG range = exceptions.get(i);
List lstRange = range.getProtectedRange();
- HashSet setBoth = new HashSet(common_blocks);
+ HashSet setBoth = new HashSet<>(common_blocks);
setBoth.retainAll(lstRange);
if (setBoth.size() > 0) {
List lstNewRange;
if (setBoth.size() == lstRange.size()) {
- lstNewRange = new ArrayList();
+ lstNewRange = new ArrayList<>();
ExceptionRangeCFG newRange = new ExceptionRangeCFG(lstNewRange,
mapNewNodes.get(range.getHandler().id), range.getExceptionTypes());
exceptions.add(newRange);
@@ -705,8 +669,8 @@ public class ControlFlowGraph implements CodeConstants {
}
}
- private void removeJsr(StructMethod mt) {
- removeJsrInstructions(mt.getClassStruct().getPool(), first, DataPoint.getInitialDataPoint(mt));
+ private void removeJsr(StructClass cl, StructMethod mt) {
+ removeJsrInstructions(cl.getPool(), first, DataPoint.getInitialDataPoint(mt));
}
private static void removeJsrInstructions(ConstantPool pool, BasicBlock block, DataPoint data) {
@@ -753,7 +717,7 @@ public class ControlFlowGraph implements CodeConstants {
if (suc.mark != 1) {
DataPoint point = new DataPoint();
- point.setLocalVariables(new ArrayList(data.getLocalVariables()));
+ point.setLocalVariables(new ArrayList<>(data.getLocalVariables()));
point.getStack().push(new VarType(CodeConstants.TYPE_OBJECT, 0, null));
removeJsrInstructions(pool, suc, point);
@@ -765,9 +729,7 @@ public class ControlFlowGraph implements CodeConstants {
first = blocks.get(0);
- last = new BasicBlock();
- last.id = ++last_id;
- last.setSeq(new SimpleInstructionSequence());
+ last = new BasicBlock(++last_id);
for (BasicBlock block : blocks) {
if (block.getSuccs().isEmpty()) {
@@ -778,18 +740,18 @@ public class ControlFlowGraph implements CodeConstants {
public List getReversePostOrder() {
- List res = new LinkedList();
+ List res = new LinkedList<>();
addToReversePostOrderListIterative(first, res);
return res;
}
- private static void addToReversePostOrderListIterative(BasicBlock root, List lst) {
+ private static void addToReversePostOrderListIterative(BasicBlock root, List super BasicBlock> lst) {
- LinkedList stackNode = new LinkedList();
- LinkedList stackIndex = new LinkedList();
+ LinkedList stackNode = new LinkedList<>();
+ LinkedList stackIndex = new LinkedList<>();
- Set setVisited = new HashSet();
+ Set setVisited = new HashSet<>();
stackNode.add(root);
stackIndex.add(0);
@@ -801,7 +763,7 @@ public class ControlFlowGraph implements CodeConstants {
setVisited.add(node);
- List lstSuccs = new ArrayList(node.getSuccs());
+ List lstSuccs = new ArrayList<>(node.getSuccs());
lstSuccs.addAll(node.getSuccExceptions());
for (; index < lstSuccs.size(); index++) {
@@ -834,10 +796,6 @@ public class ControlFlowGraph implements CodeConstants {
return blocks;
}
- public void setBlocks(VBStyleCollection blocks) {
- this.blocks = blocks;
- }
-
public BasicBlock getFirst() {
return first;
}
@@ -846,39 +804,15 @@ public class ControlFlowGraph implements CodeConstants {
this.first = first;
}
- public List getEndBlocks() {
- return last.getPreds();
- }
-
public List getExceptions() {
return exceptions;
}
- public void setExceptions(List exceptions) {
- this.exceptions = exceptions;
- }
-
public BasicBlock getLast() {
return last;
}
- public void setLast(BasicBlock last) {
- this.last = last;
- }
-
- public Map getSubroutines() {
- return subroutines;
- }
-
- public void setSubroutines(Map subroutines) {
- this.subroutines = subroutines;
- }
-
public Set getFinallyExits() {
return finallyExits;
}
-
- public void setFinallyExits(HashSet finallyExits) {
- this.finallyExits = finallyExits;
- }
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java b/src/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java
index 47e0e21..395d03d 100644
--- a/src/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java
+++ b/src/org/jetbrains/java/decompiler/code/cfg/ExceptionRangeCFG.java
@@ -1,33 +1,15 @@
-/*
- * 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.
- */
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code.cfg;
import org.jetbrains.java.decompiler.main.DecompilerContext;
import java.util.ArrayList;
-import java.util.HashSet;
import java.util.List;
-import java.util.Set;
+import java.util.stream.Collectors;
public class ExceptionRangeCFG {
-
- private List protectedRange = new ArrayList(); // FIXME: replace with set
-
+ private final List protectedRange; // FIXME: replace with set
private BasicBlock handler;
-
private List exceptionTypes;
public ExceptionRangeCFG(List protectedRange, BasicBlock handler, List exceptionType) {
@@ -35,7 +17,7 @@ public class ExceptionRangeCFG {
this.handler = handler;
if (exceptionType != null) {
- this.exceptionTypes = new ArrayList(exceptionType);
+ this.exceptionTypes = new ArrayList<>(exceptionType);
}
}
@@ -43,22 +25,28 @@ public class ExceptionRangeCFG {
return protectedRange.contains(handler);
}
+ @Override
public String toString() {
-
String new_line_separator = DecompilerContext.getNewLineSeparator();
-
StringBuilder buf = new StringBuilder();
buf.append("exceptionType:");
- for (String exception_type : exceptionTypes) {
- buf.append(" ").append(exception_type);
+
+ if (exceptionTypes == null) {
+ buf.append(" null");
}
+ else {
+ for (String exception_type : exceptionTypes) {
+ buf.append(" ").append(exception_type);
+ }
+ }
+
buf.append(new_line_separator);
buf.append("handler: ").append(handler.id).append(new_line_separator);
buf.append("range: ");
- for (int i = 0; i < protectedRange.size(); i++) {
- buf.append(protectedRange.get(i).id).append(" ");
+ for (BasicBlock block : protectedRange) {
+ buf.append(block.id).append(" ");
}
buf.append(new_line_separator);
@@ -77,16 +65,11 @@ public class ExceptionRangeCFG {
return protectedRange;
}
- public void setProtectedRange(List protectedRange) {
- this.protectedRange = protectedRange;
- }
-
public List getExceptionTypes() {
return this.exceptionTypes;
}
public void addExceptionType(String exceptionType) {
-
if (this.exceptionTypes == null) {
return;
}
@@ -100,30 +83,6 @@ public class ExceptionRangeCFG {
}
public String getUniqueExceptionsString() {
-
- if (exceptionTypes == null) {
- return null;
- }
-
- Set setExceptionStrings = new HashSet();
-
- for (String exceptionType : exceptionTypes) { // normalize order
- setExceptionStrings.add(exceptionType);
- }
-
- String ret = "";
- for (String exception : setExceptionStrings) {
- if (!ret.isEmpty()) {
- ret += ":";
- }
- ret += exception;
- }
-
- return ret;
+ return exceptionTypes != null ? exceptionTypes.stream().distinct().collect(Collectors.joining(":")) : null;
}
-
-
- // public void setExceptionType(String exceptionType) {
- // this.exceptionType = exceptionType;
- // }
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java b/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java
index 1af23a4..aeafe5c 100644
--- a/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java
+++ b/src/org/jetbrains/java/decompiler/code/interpreter/InstructionImpact.java
@@ -1,31 +1,18 @@
-/*
- * 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.
- */
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.code.interpreter;
import org.jetbrains.java.decompiler.code.CodeConstants;
import org.jetbrains.java.decompiler.code.Instruction;
import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
import org.jetbrains.java.decompiler.struct.consts.LinkConstant;
+import org.jetbrains.java.decompiler.struct.consts.PooledConstant;
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
import org.jetbrains.java.decompiler.struct.gen.DataPoint;
import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.ListStack;
-public class InstructionImpact {
+public final class InstructionImpact {
// {read, write}
private static final int[][][] stack_impact = {
@@ -338,7 +325,6 @@ public class InstructionImpact {
public static void stepTypes(DataPoint data, Instruction instr, ConstantPool pool) {
-
ListStack stack = data.getStack();
int[][] arr = stack_impact[instr.opcode];
@@ -350,8 +336,7 @@ public class InstructionImpact {
if (read != null) {
int depth = 0;
- for (int i = 0; i < read.length; i++) {
- int type = read[i];
+ for (int type : read) {
depth++;
if (type == CodeConstants.TYPE_LONG ||
type == CodeConstants.TYPE_DOUBLE) {
@@ -363,8 +348,7 @@ public class InstructionImpact {
}
if (write != null) {
- for (int i = 0; i < write.length; i++) {
- int type = write[i];
+ for (int type : write) {
stack.push(new VarType(type));
if (type == CodeConstants.TYPE_LONG ||
type == CodeConstants.TYPE_DOUBLE) {
@@ -394,8 +378,8 @@ public class InstructionImpact {
case CodeConstants.opc_ldc:
case CodeConstants.opc_ldc_w:
case CodeConstants.opc_ldc2_w:
- cn = pool.getPrimitiveConstant(instr.getOperand(0));
- switch (cn.type) {
+ PooledConstant constant = pool.getConstant(instr.operand(0));
+ switch (constant.type) {
case CodeConstants.CONSTANT_Integer:
stack.push(new VarType(CodeConstants.TYPE_INT));
break;
@@ -416,10 +400,13 @@ public class InstructionImpact {
case CodeConstants.CONSTANT_Class:
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/Class"));
break;
+ case CodeConstants.CONSTANT_MethodHandle:
+ stack.push(new VarType(((LinkConstant)constant).descriptor));
+ break;
}
break;
case CodeConstants.opc_aload:
- var1 = data.getVariable(instr.getOperand(0));
+ var1 = data.getVariable(instr.operand(0));
if (var1 != null) {
stack.push(var1);
}
@@ -429,10 +416,10 @@ public class InstructionImpact {
break;
case CodeConstants.opc_aaload:
var1 = stack.pop(2);
- stack.push(new VarType(var1.type, var1.arraydim - 1, var1.value));
+ stack.push(new VarType(var1.type, var1.arrayDim - 1, var1.value));
break;
case CodeConstants.opc_astore:
- data.setVariable(instr.getOperand(0), stack.pop());
+ data.setVariable(instr.operand(0), stack.pop());
break;
case CodeConstants.opc_dup:
case CodeConstants.opc_dup_x1:
@@ -454,19 +441,19 @@ public class InstructionImpact {
case CodeConstants.opc_getfield:
stack.pop();
case CodeConstants.opc_getstatic:
- ck = pool.getLinkConstant(instr.getOperand(0));
+ ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
stack.push(var1);
- if (var1.stack_size == 2) {
+ if (var1.stackSize == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
break;
case CodeConstants.opc_putfield:
stack.pop();
case CodeConstants.opc_putstatic:
- ck = pool.getLinkConstant(instr.getOperand(0));
+ ck = pool.getLinkConstant(instr.operand(0));
var1 = new VarType(ck.descriptor);
- stack.pop(var1.stack_size);
+ stack.pop(var1.stackSize);
break;
case CodeConstants.opc_invokevirtual:
case CodeConstants.opc_invokespecial:
@@ -474,29 +461,27 @@ public class InstructionImpact {
stack.pop();
case CodeConstants.opc_invokestatic:
case CodeConstants.opc_invokedynamic:
- if (instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecode_version >= CodeConstants.BYTECODE_JAVA_7) {
- ck = pool.getLinkConstant(instr.getOperand(0));
+ if (instr.opcode != CodeConstants.opc_invokedynamic || instr.bytecodeVersion >= CodeConstants.BYTECODE_JAVA_7) {
+ ck = pool.getLinkConstant(instr.operand(0));
MethodDescriptor md = MethodDescriptor.parseDescriptor(ck.descriptor);
for (int i = 0; i < md.params.length; i++) {
- stack.pop(md.params[i].stack_size);
+ stack.pop(md.params[i].stackSize);
}
if (md.ret.type != CodeConstants.TYPE_VOID) {
stack.push(md.ret);
- if (md.ret.stack_size == 2) {
+ if (md.ret.stackSize == 2) {
stack.push(new VarType(CodeConstants.TYPE_GROUP2EMPTY));
}
}
}
break;
case CodeConstants.opc_new:
- cn = pool.getPrimitiveConstant(instr.getOperand(0));
+ cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_newarray:
stack.pop();
- var1 = new VarType(arr_type[instr.getOperand(0) - 4]);
- var1.arraydim = 1;
- stack.push(var1);
+ stack.push(new VarType(arr_type[instr.operand(0) - 4], 1).resizeArrayDim(1));
break;
case CodeConstants.opc_athrow:
var1 = stack.pop();
@@ -506,17 +491,17 @@ public class InstructionImpact {
case CodeConstants.opc_checkcast:
case CodeConstants.opc_instanceof:
stack.pop();
- cn = pool.getPrimitiveConstant(instr.getOperand(0));
+ cn = pool.getPrimitiveConstant(instr.operand(0));
stack.push(new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString()));
break;
case CodeConstants.opc_anewarray:
case CodeConstants.opc_multianewarray:
- int dimensions = (instr.opcode == CodeConstants.opc_anewarray) ? 1 : instr.getOperand(1);
+ int dimensions = (instr.opcode == CodeConstants.opc_anewarray) ? 1 : instr.operand(1);
stack.pop(dimensions);
- cn = pool.getPrimitiveConstant(instr.getOperand(0));
+ cn = pool.getPrimitiveConstant(instr.operand(0));
if (cn.isArray) {
var1 = new VarType(CodeConstants.TYPE_OBJECT, 0, cn.getString());
- var1.arraydim += dimensions;
+ var1 = var1.resizeArrayDim(var1.arrayDim + dimensions);
stack.push(var1);
}
else {
diff --git a/src/org/jetbrains/java/decompiler/code/interpreter/Util.java b/src/org/jetbrains/java/decompiler/code/interpreter/Util.java
deleted file mode 100644
index bf1e5eb..0000000
--- a/src/org/jetbrains/java/decompiler/code/interpreter/Util.java
+++ /dev/null
@@ -1,286 +0,0 @@
-/*
- * 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.code.interpreter;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-import org.jetbrains.java.decompiler.struct.StructClass;
-import org.jetbrains.java.decompiler.struct.StructContext;
-
-
-// FIXME: move to StructContext
-public class Util {
-
- private static final String[][] runtime_exceptions = {
-
- null, // public final static int opc_nop = 0;
- null, // public final static int opc_aconst_null = 1;
- null, // public final static int opc_iconst_m1 = 2;
- null, // public final static int opc_iconst_0 = 3;
- null, // public final static int opc_iconst_1 = 4;
- null, // public final static int opc_iconst_2 = 5;
- null, // public final static int opc_iconst_3 = 6;
- null, // public final static int opc_iconst_4 = 7;
- null, // public final static int opc_iconst_5 = 8;
- null, // public final static int opc_lconst_0 = 9;
- null, // public final static int opc_lconst_1 = 10;
- null, // public final static int opc_fconst_0 = 11;
- null, // public final static int opc_fconst_1 = 12;
- null, // public final static int opc_fconst_2 = 13;
- null, // public final static int opc_dconst_0 = 14;
- null, // public final static int opc_dconst_1 = 15;
- null, // public final static int opc_bipush = 16;
- null, // public final static int opc_sipush = 17;
- null, // public final static int opc_ldc = 18;
- null, // public final static int opc_ldc_w = 19;
- null, // public final static int opc_ldc2_w = 20;
- null, // public final static int opc_iload = 21;
- null, // public final static int opc_lload = 22;
- null, // public final static int opc_fload = 23;
- null, // public final static int opc_dload = 24;
- null, // public final static int opc_aload = 25;
- null, // public final static int opc_iload_0 = 26;
- null, // public final static int opc_iload_1 = 27;
- null, // public final static int opc_iload_2 = 28;
- null, // public final static int opc_iload_3 = 29;
- null, // public final static int opc_lload_0 = 30;
- null, // public final static int opc_lload_1 = 31;
- null, // public final static int opc_lload_2 = 32;
- null, // public final static int opc_lload_3 = 33;
- null, // public final static int opc_fload_0 = 34;
- null, // public final static int opc_fload_1 = 35;
- null, // public final static int opc_fload_2 = 36;
- null, // public final static int opc_fload_3 = 37;
- null, // public final static int opc_dload_0 = 38;
- null, // public final static int opc_dload_1 = 39;
- null, // public final static int opc_dload_2 = 40;
- null, // public final static int opc_dload_3 = 41;
- null, // public final static int opc_aload_0 = 42;
- null, // public final static int opc_aload_1 = 43;
- null, // public final static int opc_aload_2 = 44;
- null, // public final static int opc_aload_3 = 45;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_iaload = 46;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_laload = 47;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_faload = 48;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_daload = 49;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_aaload = 50;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_baload = 51;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_caload = 52;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_saload = 53;
- null, // public final static int opc_istore = 54;
- null, // public final static int opc_lstore = 55;
- null, // public final static int opc_fstore = 56;
- null, // public final static int opc_dstore = 57;
- null, // public final static int opc_astore = 58;
- null, // public final static int opc_istore_0 = 59;
- null, // public final static int opc_istore_1 = 60;
- null, // public final static int opc_istore_2 = 61;
- null, // public final static int opc_istore_3 = 62;
- null, // public final static int opc_lstore_0 = 63;
- null, // public final static int opc_lstore_1 = 64;
- null, // public final static int opc_lstore_2 = 65;
- null, // public final static int opc_lstore_3 = 66;
- null, // public final static int opc_fstore_0 = 67;
- null, // public final static int opc_fstore_1 = 68;
- null, // public final static int opc_fstore_2 = 69;
- null, // public final static int opc_fstore_3 = 70;
- null, // public final static int opc_dstore_0 = 71;
- null, // public final static int opc_dstore_1 = 72;
- null, // public final static int opc_dstore_2 = 73;
- null, // public final static int opc_dstore_3 = 74;
- null, // public final static int opc_astore_0 = 75;
- null, // public final static int opc_astore_1 = 76;
- null, // public final static int opc_astore_2 = 77;
- null, // public final static int opc_astore_3 = 78;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_iastore = 79;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_lastore = 80;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_fastore = 81;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_dastore = 82;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException", "java/lang/ArrayStoreException"},
- // public final static int opc_aastore = 83;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_bastore = 84;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_castore = 85;
- {"java/lang/NullPointerException", "java/lang/ArrayIndexOutOfBoundsException"},
- // public final static int opc_sastore = 86;
- null, // public final static int opc_pop = 87;
- null, // public final static int opc_pop2 = 88;
- null, // public final static int opc_dup = 89;
- null, // public final static int opc_dup_x1 = 90;
- null, // public final static int opc_dup_x2 = 91;
- null, // public final static int opc_dup2 = 92;
- null, // public final static int opc_dup2_x1 = 93;
- null, // public final static int opc_dup2_x2 = 94;
- null, // public final static int opc_swap = 95;
- null, // public final static int opc_iadd = 96;
- null, // public final static int opc_ladd = 97;
- null, // public final static int opc_fadd = 98;
- null, // public final static int opc_dadd = 99;
- null, // public final static int opc_isub = 100;
- null, // public final static int opc_lsub = 101;
- null, // public final static int opc_fsub = 102;
- null, // public final static int opc_dsub = 103;
- null, // public final static int opc_imul = 104;
- null, // public final static int opc_lmul = 105;
- null, // public final static int opc_fmul = 106;
- null, // public final static int opc_dmul = 107;
- {"java/lang/ArithmeticException"}, // public final static int opc_idiv = 108;
- {"java/lang/ArithmeticException"}, // public final static int opc_ldiv = 109;
- null, // public final static int opc_fdiv = 110;
- null, // public final static int opc_ddiv = 111;
- {"java/lang/ArithmeticException"}, // public final static int opc_irem = 112;
- {"java/lang/ArithmeticException"}, // public final static int opc_lrem = 113;
- null, // public final static int opc_frem = 114;
- null, // public final static int opc_drem = 115;
- null, // public final static int opc_ineg = 116;
- null, // public final static int opc_lneg = 117;
- null, // public final static int opc_fneg = 118;
- null, // public final static int opc_dneg = 119;
- null, // public final static int opc_ishl = 120;
- null, // public final static int opc_lshl = 121;
- null, // public final static int opc_ishr = 122;
- null, // public final static int opc_lshr = 123;
- null, // public final static int opc_iushr = 124;
- null, // public final static int opc_lushr = 125;
- null, // public final static int opc_iand = 126;
- null, // public final static int opc_land = 127;
- null, // public final static int opc_ior = 128;
- null, // public final static int opc_lor = 129;
- null, // public final static int opc_ixor = 130;
- null, // public final static int opc_lxor = 131;
- null, // public final static int opc_iinc = 132;
- null, // public final static int opc_i2l = 133;
- null, // public final static int opc_i2f = 134;
- null, // public final static int opc_i2d = 135;
- null, // public final static int opc_l2i = 136;
- null, // public final static int opc_l2f = 137;
- null, // public final static int opc_l2d = 138;
- null, // public final static int opc_f2i = 139;
- null, // public final static int opc_f2l = 140;
- null, // public final static int opc_f2d = 141;
- null, // public final static int opc_d2i = 142;
- null, // public final static int opc_d2l = 143;
- null, // public final static int opc_d2f = 144;
- null, // public final static int opc_i2b = 145;
- null, // public final static int opc_i2c = 146;
- null, // public final static int opc_i2s = 147;
- null, // public final static int opc_lcmp = 148;
- null, // public final static int opc_fcmpl = 149;
- null, // public final static int opc_fcmpg = 150;
- null, // public final static int opc_dcmpl = 151;
- null, // public final static int opc_dcmpg = 152;
- null, // public final static int opc_ifeq = 153;
- null, // public final static int opc_ifne = 154;
- null, // public final static int opc_iflt = 155;
- null, // public final static int opc_ifge = 156;
- null, // public final static int opc_ifgt = 157;
- null, // public final static int opc_ifle = 158;
- null, // public final static int opc_if_icmpeq = 159;
- null, // public final static int opc_if_icmpne = 160;
- null, // public final static int opc_if_icmplt = 161;
- null, // public final static int opc_if_icmpge = 162;
- null, // public final static int opc_if_icmpgt = 163;
- null, // public final static int opc_if_icmple = 164;
- null, // public final static int opc_if_acmpeq = 165;
- null, // public final static int opc_if_acmpne = 166;
- null, // public final static int opc_goto = 167;
- null, // public final static int opc_jsr = 168;
- null, // public final static int opc_ret = 169;
- null, // public final static int opc_tableswitch = 170;
- null, // public final static int opc_lookupswitch = 171;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_ireturn = 172;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_lreturn = 173;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_freturn = 174;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_dreturn = 175;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_areturn = 176;
- {"java/lang/IllegalMonitorStateException"}, // public final static int opc_return = 177;
- null, // public final static int opc_getstatic = 178;
- null, // public final static int opc_putstatic = 179;
- {"java/lang/NullPointerException"}, // public final static int opc_getfield = 180;
- {"java/lang/NullPointerException"}, // public final static int opc_putfield = 181;
- {"java/lang/NullPointerException", "java/lang/AbstractMethodError", "java/lang/UnsatisfiedLinkError"},
- // public final static int opc_invokevirtual = 182;
- {"java/lang/NullPointerException", "java/lang/UnsatisfiedLinkError"},
- // public final static int opc_invokespecial = 183;
- {"java/lang/UnsatisfiedLinkError"}, // public final static int opc_invokestatic = 184;
- {"java/lang/NullPointerException", "java/lang/IncompatibleClassChangeError", "java/lang/IllegalAccessError",
- "java/lang/java/lang/AbstractMethodError", "java/lang/UnsatisfiedLinkError"},
- // public final static int opc_invokeinterface = 185;
- null, // public final static int opc_xxxunusedxxx = 186;
- null, // public final static int opc_new = 187;
- {"java/lang/NegativeArraySizeException"}, // public final static int opc_newarray = 188;
- {"java/lang/NegativeArraySizeException"}, // public final static int opc_anewarray = 189;
- {"java/lang/NullPointerException"}, // public final static int opc_arraylength = 190;
- {"java/lang/NullPointerException", "java/lang/IllegalMonitorStateException"},
- // public final static int opc_athrow = 191;
- {"java/lang/ClassCastException"}, // public final static int opc_checkcast = 192;
- null, // public final static int opc_instanceof = 193;
- {"java/lang/NullPointerException"}, // public final static int opc_monitorenter = 194;
- {"java/lang/NullPointerException", "java/lang/IllegalMonitorStateException"},
- // public final static int opc_monitorexit = 195;
- null, // public final static int opc_wide = 196;
- {"java/lang/NegativeArraySizeException"}, // public final static int opc_multianewarray = 197;
- null, // public final static int opc_ifnull = 198;
- null, // public final static int opc_ifnonnull = 199;
- null, // public final static int opc_goto_w = 200;
- null, // public final static int opc_jsr_w = 201;
- };
-
-
- public static boolean instanceOf(StructContext context, String valclass, String refclass) {
-
- if (valclass.equals(refclass)) {
- return true;
- }
-
- StructClass cl = context.getClass(valclass);
- if (cl == null) {
- return false;
- }
-
- if (cl.superClass != null && instanceOf(context, cl.superClass.getString(), refclass)) {
- return true;
- }
-
- int[] interfaces = cl.getInterfaces();
- for (int i = 0; i < interfaces.length; i++) {
- String intfc = cl.getPool().getPrimitiveConstant(interfaces[i]).getString();
-
- if (instanceOf(context, intfc, refclass)) {
- return true;
- }
- }
-
- return false;
- }
-
-
- public static String[] getRuntimeExceptions(Instruction instr) {
- return runtime_exceptions[instr.opcode];
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/ALOAD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/ALOAD.java
deleted file mode 100644
index 788795e..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/ALOAD.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ALOAD extends Instruction {
-
- private static int[] opcodes = new int[]{opc_aload_0, opc_aload_1, opc_aload_2, opc_aload_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_aload);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/ANEWARRAY.java b/src/org/jetbrains/java/decompiler/code/optinstructions/ANEWARRAY.java
deleted file mode 100644
index d514ffe..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/ANEWARRAY.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ANEWARRAY extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_anewarray);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/ASTORE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/ASTORE.java
deleted file mode 100644
index 40336f4..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/ASTORE.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ASTORE extends Instruction {
-
- private static int[] opcodes = new int[]{opc_astore_0, opc_astore_1, opc_astore_2, opc_astore_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_astore);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/BIPUSH.java b/src/org/jetbrains/java/decompiler/code/optinstructions/BIPUSH.java
deleted file mode 100644
index 4686051..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/BIPUSH.java
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class BIPUSH extends Instruction {
-
- private static int[] opcodes =
- new int[]{opc_iconst_m1, opc_iconst_0, opc_iconst_1, opc_iconst_2, opc_iconst_3, opc_iconst_4, opc_iconst_5};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int value = getOperand(0);
- if (value < -1 || value > 5) {
- out.writeByte(opc_bipush);
- out.writeByte(value);
- }
- else {
- out.writeByte(opcodes[value + 1]);
- }
- }
-
- public int length() {
- int value = getOperand(0);
- if (value < -1 || value > 5) {
- return 2;
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/CHECKCAST.java b/src/org/jetbrains/java/decompiler/code/optinstructions/CHECKCAST.java
deleted file mode 100644
index 9a42f65..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/CHECKCAST.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class CHECKCAST extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_checkcast);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
-
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/DLOAD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/DLOAD.java
deleted file mode 100644
index 7630185..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/DLOAD.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class DLOAD extends Instruction {
-
- private static int[] opcodes = new int[]{opc_dload_0, opc_dload_1, opc_dload_2, opc_dload_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_dload);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/DSTORE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/DSTORE.java
deleted file mode 100644
index 2bdb749..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/DSTORE.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class DSTORE extends Instruction {
-
- private static int[] opcodes = new int[]{opc_dstore_0, opc_dstore_1, opc_dstore_2, opc_dstore_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_dstore);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/FLOAD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/FLOAD.java
deleted file mode 100644
index 8a89dff..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/FLOAD.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class FLOAD extends Instruction {
-
- private static int[] opcodes = new int[]{opc_fload_0, opc_fload_1, opc_fload_2, opc_fload_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_fload);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/FSTORE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/FSTORE.java
deleted file mode 100644
index 9061913..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/FSTORE.java
+++ /dev/null
@@ -1,60 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class FSTORE extends Instruction {
-
- private static int[] opcodes = new int[]{opc_fstore_0, opc_fstore_1, opc_fstore_2, opc_fstore_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_fstore);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- return 4;
- }
- else {
- return 2;
- }
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/GETFIELD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/GETFIELD.java
deleted file mode 100644
index 6b95aaf..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/GETFIELD.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class GETFIELD extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_getfield);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/GETSTATIC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/GETSTATIC.java
deleted file mode 100644
index c1401a6..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/GETSTATIC.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class GETSTATIC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_getstatic);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO.java b/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO.java
deleted file mode 100644
index 97374c0..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.JumpInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class GOTO extends JumpInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int operand = getOperand(0);
- if (operand < -32768 || operand > 32767) {
- out.writeByte(opc_goto_w);
- out.writeInt(operand);
- }
- else {
- out.writeByte(opc_goto);
- out.writeShort(operand);
- }
- }
-
- public int length() {
- int operand = getOperand(0);
- if (operand < -32768 || operand > 32767) {
- return 5;
- }
- else {
- return 3;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO_W.java b/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO_W.java
deleted file mode 100644
index 56ba9e8..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/GOTO_W.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.JumpInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class GOTO_W extends JumpInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_goto_w);
- out.writeInt(getOperand(0));
- }
-
- public int length() {
- return 5;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/IINC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/IINC.java
deleted file mode 100644
index 05b446c..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/IINC.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class IINC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_iinc);
- if (wide) {
- out.writeShort(getOperand(0));
- out.writeShort(getOperand(1));
- }
- else {
- out.writeByte(getOperand(0));
- out.writeByte(getOperand(1));
- }
- }
-
- public int length() {
- return wide ? 6 : 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/ILOAD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/ILOAD.java
deleted file mode 100644
index 24b95ff..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/ILOAD.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ILOAD extends Instruction {
-
- private static int[] opcodes = new int[]{opc_iload_0, opc_iload_1, opc_iload_2, opc_iload_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_iload);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- return wide ? 4 : 2;
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INSTANCEOF.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INSTANCEOF.java
deleted file mode 100644
index f93d5b8..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INSTANCEOF.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INSTANCEOF extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_instanceof);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEDYNAMIC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEDYNAMIC.java
deleted file mode 100644
index 917c5bd..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEDYNAMIC.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INVOKEDYNAMIC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_invokedynamic);
- out.writeShort(getOperand(0));
- out.writeByte(0);
- out.writeByte(0);
- }
-
- public int length() {
- return 5;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEINTERFACE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEINTERFACE.java
deleted file mode 100644
index 51259ff..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEINTERFACE.java
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INVOKEINTERFACE extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_invokeinterface);
- out.writeShort(getOperand(0));
- out.writeByte(getOperand(1));
- out.writeByte(0);
- }
-
- public int length() {
- return 5;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESPECIAL.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESPECIAL.java
deleted file mode 100644
index 2436803..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESPECIAL.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INVOKESPECIAL extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_invokespecial);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESTATIC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESTATIC.java
deleted file mode 100644
index f036a1d..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKESTATIC.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INVOKESTATIC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_invokestatic);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEVIRTUAL.java b/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEVIRTUAL.java
deleted file mode 100644
index ca3bcd3..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/INVOKEVIRTUAL.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class INVOKEVIRTUAL extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_invokevirtual);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/ISTORE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/ISTORE.java
deleted file mode 100644
index 5907538..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/ISTORE.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class ISTORE extends Instruction {
-
- private static int[] opcodes = new int[]{opc_istore_0, opc_istore_1, opc_istore_2, opc_istore_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_istore);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- return wide ? 4 : 2;
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/JSR.java b/src/org/jetbrains/java/decompiler/code/optinstructions/JSR.java
deleted file mode 100644
index bb000a7..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/JSR.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.JumpInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class JSR extends JumpInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int operand = getOperand(0);
- if (operand < -32768 || operand > 32767) {
- out.writeByte(opc_jsr_w);
- out.writeInt(operand);
- }
- else {
- out.writeByte(opc_jsr);
- out.writeShort(operand);
- }
- }
-
- public int length() {
- int operand = getOperand(0);
- if (operand < -32768 || operand > 32767) {
- return 5;
- }
- else {
- return 3;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/JSR_W.java b/src/org/jetbrains/java/decompiler/code/optinstructions/JSR_W.java
deleted file mode 100644
index fb04ed9..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/JSR_W.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.JumpInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class JSR_W extends JumpInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_jsr_w);
- out.writeInt(getOperand(0));
- }
-
- public int length() {
- return 5;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LDC.java
deleted file mode 100644
index ae7b3c6..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LDC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_ldc);
- out.writeByte(getOperand(0));
- }
-
- public int length() {
- return 2;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC2_W.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LDC2_W.java
deleted file mode 100644
index 6ba1964..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC2_W.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LDC2_W extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_ldc2_w);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC_W.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LDC_W.java
deleted file mode 100644
index 71e5fe0..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LDC_W.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LDC_W extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_ldc_w);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LLOAD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LLOAD.java
deleted file mode 100644
index 6e50659..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LLOAD.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LLOAD extends Instruction {
-
- private static int[] opcodes = new int[]{opc_lload_0, opc_lload_1, opc_lload_2, opc_lload_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_lload);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- return wide ? 4 : 2;
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LOOKUPSWITCH.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LOOKUPSWITCH.java
deleted file mode 100644
index 4183168..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LOOKUPSWITCH.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.SwitchInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LOOKUPSWITCH extends SwitchInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
-
- out.writeByte(opc_lookupswitch);
-
- int padding = 3 - (offset % 4);
- for (int i = 0; i < padding; i++) {
- out.writeByte(0);
- }
-
- for (int i = 0; i < operandsCount(); i++) {
- out.writeInt(getOperand(i));
- }
- }
-
- public int length() {
- return 1 + operandsCount() * 4;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/LSTORE.java b/src/org/jetbrains/java/decompiler/code/optinstructions/LSTORE.java
deleted file mode 100644
index 9095f04..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/LSTORE.java
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class LSTORE extends Instruction {
-
- private static int[] opcodes = new int[]{opc_lstore_0, opc_lstore_1, opc_lstore_2, opc_lstore_3};
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- int index = getOperand(0);
- if (index > 3) {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_lstore);
- if (wide) {
- out.writeShort(index);
- }
- else {
- out.writeByte(index);
- }
- }
- else {
- out.writeByte(opcodes[index]);
- }
- }
-
- public int length() {
- int index = getOperand(0);
- if (index > 3) {
- return wide ? 4 : 2;
- }
- else {
- return 1;
- }
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/MULTIANEWARRAY.java b/src/org/jetbrains/java/decompiler/code/optinstructions/MULTIANEWARRAY.java
deleted file mode 100644
index b6835e8..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/MULTIANEWARRAY.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class MULTIANEWARRAY extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_multianewarray);
- out.writeShort(getOperand(0));
- out.writeByte(getOperand(1));
- }
-
- public int length() {
- return 4;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/NEW.java b/src/org/jetbrains/java/decompiler/code/optinstructions/NEW.java
deleted file mode 100644
index 2e8854f..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/NEW.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class NEW extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_new);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/NEWARRAY.java b/src/org/jetbrains/java/decompiler/code/optinstructions/NEWARRAY.java
deleted file mode 100644
index f2f8e4d..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/NEWARRAY.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class NEWARRAY extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_newarray);
- out.writeByte(getOperand(0));
- }
-
- public int length() {
- return 2;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/PUTFIELD.java b/src/org/jetbrains/java/decompiler/code/optinstructions/PUTFIELD.java
deleted file mode 100644
index c1e3e92..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/PUTFIELD.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class PUTFIELD extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_putfield);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/PUTSTATIC.java b/src/org/jetbrains/java/decompiler/code/optinstructions/PUTSTATIC.java
deleted file mode 100644
index 0fe0240..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/PUTSTATIC.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class PUTSTATIC extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_putstatic);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/RET.java b/src/org/jetbrains/java/decompiler/code/optinstructions/RET.java
deleted file mode 100644
index 93f62ff..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/RET.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class RET extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- if (wide) {
- out.writeByte(opc_wide);
- }
- out.writeByte(opc_ret);
- if (wide) {
- out.writeShort(getOperand(0));
- }
- else {
- out.writeByte(getOperand(0));
- }
- }
-
- public int length() {
- return wide ? 4 : 2;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/SIPUSH.java b/src/org/jetbrains/java/decompiler/code/optinstructions/SIPUSH.java
deleted file mode 100644
index 08b10a5..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/SIPUSH.java
+++ /dev/null
@@ -1,33 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.Instruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class SIPUSH extends Instruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
- out.writeByte(opc_sipush);
- out.writeShort(getOperand(0));
- }
-
- public int length() {
- return 3;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/code/optinstructions/TABLESWITCH.java b/src/org/jetbrains/java/decompiler/code/optinstructions/TABLESWITCH.java
deleted file mode 100644
index 0b41ecf..0000000
--- a/src/org/jetbrains/java/decompiler/code/optinstructions/TABLESWITCH.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.code.optinstructions;
-
-import org.jetbrains.java.decompiler.code.SwitchInstruction;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-
-public class TABLESWITCH extends SwitchInstruction {
-
- public void writeToStream(DataOutputStream out, int offset) throws IOException {
-
- out.writeByte(opc_tableswitch);
-
- int padding = 3 - (offset % 4);
- for (int i = 0; i < padding; i++) {
- out.writeByte(0);
- }
-
- for (int i = 0; i < operandsCount(); i++) {
- out.writeInt(getOperand(i));
- }
- }
-
- public int length() {
- return 1 + operandsCount() * 4;
- }
-}
diff --git a/src/org/jetbrains/java/decompiler/main/AssertProcessor.java b/src/org/jetbrains/java/decompiler/main/AssertProcessor.java
index a58b689..a8863c5 100644
--- a/src/org/jetbrains/java/decompiler/main/AssertProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/AssertProcessor.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -35,13 +21,13 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
-public class AssertProcessor {
+public final class AssertProcessor {
private static final VarType CLASS_ASSERTION_ERROR = new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/AssertionError");
public static void buildAssertions(ClassNode node) {
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
StructField field = findAssertionField(node);
@@ -67,7 +53,7 @@ public class AssertProcessor {
private static StructField findAssertionField(ClassNode node) {
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
@@ -89,7 +75,7 @@ public class AssertProcessor {
if (initializer.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)initializer;
- if (fexpr.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT &&
+ if (fexpr.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_INVOCATION) {
InvocationExprent invexpr = (InvocationExprent)fexpr.getLstOperands().get(0);
@@ -101,11 +87,11 @@ public class AssertProcessor {
invexpr.getLstParameters().isEmpty()) {
ConstExprent cexpr = (ConstExprent)invexpr.getInstance();
- if (VarType.VARTYPE_CLASS.equals(cexpr.getConsttype())) {
+ if (VarType.VARTYPE_CLASS.equals(cexpr.getConstType())) {
ClassNode nd = node;
while (nd != null) {
- if (nd.wrapper.getClassStruct().qualifiedName.equals(cexpr.getValue())) {
+ if (nd.getWrapper().getClassStruct().qualifiedName.equals(cexpr.getValue())) {
break;
}
nd = nd.parent;
@@ -157,26 +143,42 @@ public class AssertProcessor {
private static boolean replaceAssertion(Statement parent, IfStatement stat, String classname, String key) {
+ boolean throwInIf = true;
Statement ifstat = stat.getIfstat();
InvocationExprent throwError = isAssertionError(ifstat);
if (throwError == null) {
- return false;
+ //check else:
+ Statement elsestat = stat.getElsestat();
+ throwError = isAssertionError(elsestat);
+ if (throwError == null) {
+ return false;
+ }
+ else {
+ throwInIf = false;
+ }
}
- Object[] exprres = getAssertionExprent(stat.getHeadexprent().getCondition().copy(), classname, key);
+
+ Object[] exprres = getAssertionExprent(stat.getHeadexprent().getCondition().copy(), classname, key, throwInIf);
if (!(Boolean)exprres[1]) {
return false;
}
- List lstParams = new ArrayList();
+ List lstParams = new ArrayList<>();
Exprent ascond = null, retcond = null;
- if (exprres[0] != null) {
- ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOLNOT,
- Arrays.asList(new Exprent[]{(Exprent)exprres[0]}));
- retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond);
+ if (throwInIf) {
+ if (exprres[0] != null) {
+ ascond = new FunctionExprent(FunctionExprent.FUNCTION_BOOL_NOT, (Exprent)exprres[0], throwError.bytecode);
+ retcond = SecondaryFunctionsHelper.propagateBoolNot(ascond);
+ }
}
+ else {
+ ascond = (Exprent) exprres[0];
+ retcond = ascond;
+ }
+
lstParams.add(retcond == null ? ascond : retcond);
if (!throwError.getLstParameters().isEmpty()) {
@@ -197,13 +199,18 @@ public class AssertProcessor {
first.removeSuccessor(stat.getIfEdge());
first.removeSuccessor(stat.getElseEdge());
- List lstStatements = new ArrayList();
+ List lstStatements = new ArrayList<>();
if (first.getExprents() != null && !first.getExprents().isEmpty()) {
lstStatements.add(first);
}
lstStatements.add(newstat);
if (stat.iftype == IfStatement.IFTYPE_IFELSE) {
- lstStatements.add(stat.getElsestat());
+ if (throwInIf) {
+ lstStatements.add(stat.getElsestat());
+ }
+ else {
+ lstStatements.add(stat.getIfstat());
+ }
}
SequenceStatement sequence = new SequenceStatement(lstStatements);
@@ -214,10 +221,16 @@ public class AssertProcessor {
sequence.getStats().get(i), sequence.getStats().get(i + 1)));
}
- if (stat.iftype == IfStatement.IFTYPE_IFELSE) {
- Statement ifelse = stat.getElsestat();
+ if (stat.iftype == IfStatement.IFTYPE_IFELSE || !throwInIf) {
+ Statement stmts;
+ if (throwInIf) {
+ stmts = stat.getElsestat();
+ }
+ else {
+ stmts = stat.getIfstat();
+ }
- List lstSuccs = ifelse.getAllSuccessorEdges();
+ List lstSuccs = stmts.getAllSuccessorEdges();
if (!lstSuccs.isEmpty()) {
StatEdge endedge = lstSuccs.get(0);
if (endedge.closure == stat) {
@@ -245,9 +258,9 @@ public class AssertProcessor {
if (expr.type == Exprent.EXPRENT_EXIT) {
ExitExprent exexpr = (ExitExprent)expr;
- if (exexpr.getExittype() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_NEW) {
+ if (exexpr.getExitType() == ExitExprent.EXIT_THROW && exexpr.getValue().type == Exprent.EXPRENT_NEW) {
NewExprent nexpr = (NewExprent)exexpr.getValue();
- if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewtype()) && nexpr.getConstructor() != null) {
+ if (CLASS_ASSERTION_ERROR.equals(nexpr.getNewType()) && nexpr.getConstructor() != null) {
return nexpr.getConstructor();
}
}
@@ -256,16 +269,21 @@ public class AssertProcessor {
return null;
}
- private static Object[] getAssertionExprent(Exprent exprent, String classname, String key) {
+ private static Object[] getAssertionExprent(Exprent exprent, String classname, String key, boolean throwInIf) {
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
+ int desiredOperation = FunctionExprent.FUNCTION_CADD;
+ if (!throwInIf) {
+ desiredOperation = FunctionExprent.FUNCTION_COR;
+ }
+
FunctionExprent fexpr = (FunctionExprent)exprent;
- if (fexpr.getFunctype() == FunctionExprent.FUNCTION_CADD) {
+ if (fexpr.getFuncType() == desiredOperation) {
for (int i = 0; i < 2; i++) {
Exprent param = fexpr.getLstOperands().get(i);
- if (isAssertionField(param, classname, key)) {
+ if (isAssertionField(param, classname, key, throwInIf)) {
return new Object[]{fexpr.getLstOperands().get(1 - i), true};
}
}
@@ -273,7 +291,7 @@ public class AssertProcessor {
for (int i = 0; i < 2; i++) {
Exprent param = fexpr.getLstOperands().get(i);
- Object[] res = getAssertionExprent(param, classname, key);
+ Object[] res = getAssertionExprent(param, classname, key, throwInIf);
if ((Boolean)res[1]) {
if (param != res[0]) {
fexpr.getLstOperands().set(i, (Exprent)res[0]);
@@ -282,7 +300,7 @@ public class AssertProcessor {
}
}
}
- else if (isAssertionField(fexpr, classname, key)) {
+ else if (isAssertionField(fexpr, classname, key, throwInIf)) {
// assert false;
return new Object[]{null, true};
}
@@ -291,20 +309,25 @@ public class AssertProcessor {
return new Object[]{exprent, false};
}
- private static boolean isAssertionField(Exprent exprent, String classname, String key) {
-
- if (exprent.type == Exprent.EXPRENT_FUNCTION) {
- FunctionExprent fparam = (FunctionExprent)exprent;
- if (fparam.getFunctype() == FunctionExprent.FUNCTION_BOOLNOT &&
- fparam.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
- FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0);
- if (classname.equals(fdparam.getClassname())
- && key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString))) {
- return true;
+ private static boolean isAssertionField(Exprent exprent, String classname, String key, boolean throwInIf) {
+ if (throwInIf) {
+ if (exprent.type == Exprent.EXPRENT_FUNCTION) {
+ FunctionExprent fparam = (FunctionExprent)exprent;
+ if (fparam.getFuncType() == FunctionExprent.FUNCTION_BOOL_NOT &&
+ fparam.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD) {
+ FieldExprent fdparam = (FieldExprent)fparam.getLstOperands().get(0);
+ return classname.equals(fdparam.getClassname()) &&
+ key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString));
}
}
}
-
+ else {
+ if (exprent.type == Exprent.EXPRENT_FIELD) {
+ FieldExprent fdparam = (FieldExprent) exprent;
+ return classname.equals(fdparam.getClassname()) &&
+ key.equals(InterpreterUtil.makeUniqueKey(fdparam.getName(), fdparam.getDescriptor().descriptorString));
+ }
+ }
return false;
}
}
diff --git a/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java b/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
index 3807d2e..e082267 100644
--- a/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
+++ b/src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2020 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -36,79 +22,48 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.util.*;
import java.util.Map.Entry;
-public class ClassReference14Processor {
+public final class ClassReference14Processor {
+ private static final ExitExprent BODY_EXPR;
+ private static final ExitExprent HANDLER_EXPR;
- public ExitExprent bodyexprent;
+ static {
+ InvocationExprent invFor = new InvocationExprent();
+ invFor.setName("forName");
+ invFor.setClassname("java/lang/Class");
+ invFor.setStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;");
+ invFor.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"));
+ invFor.setStatic(true);
+ invFor.setLstParameters(Collections.singletonList(new VarExprent(0, VarType.VARTYPE_STRING, null)));
+ BODY_EXPR = new ExitExprent(ExitExprent.EXIT_RETURN, invFor, VarType.VARTYPE_CLASS, null);
- public ExitExprent handlerexprent;
-
-
- public ClassReference14Processor() {
-
- InvocationExprent invfor = new InvocationExprent();
- invfor.setName("forName");
- invfor.setClassname("java/lang/Class");
- invfor.setStringDescriptor("(Ljava/lang/String;)Ljava/lang/Class;");
- invfor.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/String;)Ljava/lang/Class;"));
- invfor.setStatic(true);
- invfor.setLstParameters(Arrays.asList(new Exprent[]{new VarExprent(0, VarType.VARTYPE_STRING, null)}));
-
- bodyexprent = new ExitExprent(ExitExprent.EXIT_RETURN,
- invfor,
- VarType.VARTYPE_CLASS);
-
- InvocationExprent constr = new InvocationExprent();
- constr.setName("");
- constr.setClassname("java/lang/NoClassDefFoundError");
- constr.setStringDescriptor("()V");
- constr.setFunctype(InvocationExprent.TYP_INIT);
- constr.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
-
- NewExprent newexpr =
- new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList());
- newexpr.setConstructor(constr);
-
- InvocationExprent invcause = new InvocationExprent();
- invcause.setName("initCause");
- invcause.setClassname("java/lang/NoClassDefFoundError");
- invcause.setStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
- invcause.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"));
- invcause.setInstance(newexpr);
- invcause.setLstParameters(
- Arrays.asList(new Exprent[]{new VarExprent(2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null)}));
-
- handlerexprent = new ExitExprent(ExitExprent.EXIT_THROW,
- invcause,
- null);
+ InvocationExprent ctor = new InvocationExprent();
+ ctor.setName(CodeConstants.INIT_NAME);
+ ctor.setClassname("java/lang/NoClassDefFoundError");
+ ctor.setStringDescriptor("()V");
+ ctor.setFunctype(InvocationExprent.TYP_INIT);
+ ctor.setDescriptor(MethodDescriptor.parseDescriptor("()V"));
+ NewExprent newExpr = new NewExprent(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/NoClassDefFoundError"), new ArrayList<>(), null);
+ newExpr.setConstructor(ctor);
+ InvocationExprent invCause = new InvocationExprent();
+ invCause.setName("initCause");
+ invCause.setClassname("java/lang/NoClassDefFoundError");
+ invCause.setStringDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;");
+ invCause.setDescriptor(MethodDescriptor.parseDescriptor("(Ljava/lang/Throwable;)Ljava/lang/Throwable;"));
+ invCause.setInstance(newExpr);
+ invCause.setLstParameters(
+ Collections.singletonList(new VarExprent(2, new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"), null)));
+ HANDLER_EXPR = new ExitExprent(ExitExprent.EXIT_THROW, invCause, null, null);
}
-
- public void processClassReferences(ClassNode node) {
-
- ClassWrapper wrapper = node.wrapper;
-
- // int major_version = wrapper.getClassStruct().major_version;
- // int minor_version = wrapper.getClassStruct().minor_version;
- //
- // if(major_version > 48 || (major_version == 48 && minor_version > 0)) {
- // // version 1.5 or above
- // return;
- // }
-
- if (wrapper.getClassStruct().isVersionGE_1_5()) {
- // version 1.5 or above
- return;
- }
-
+ public static void processClassReferences(ClassNode node) {
// find the synthetic method Class class$(String) if present
- HashMap mapClassMeths = new HashMap();
+ Map mapClassMeths = new HashMap<>();
mapClassMethods(node, mapClassMeths);
-
if (mapClassMeths.isEmpty()) {
return;
}
- HashSet setFound = new HashSet();
+ Set setFound = new HashSet<>();
processClassRec(node, mapClassMeths, setFound);
if (!setFound.isEmpty()) {
@@ -119,29 +74,21 @@ public class ClassReference14Processor {
}
}
- private static void processClassRec(ClassNode node,
- final HashMap mapClassMeths,
- final HashSet setFound) {
-
- final ClassWrapper wrapper = node.wrapper;
+ private static void processClassRec(ClassNode node, Map mapClassMeths, Set super ClassWrapper> setFound) {
+ ClassWrapper wrapper = node.getWrapper();
// search code
for (MethodWrapper meth : wrapper.getMethods()) {
-
RootStatement root = meth.root;
if (root != null) {
-
DirectGraph graph = meth.getOrBuildGraph();
-
- graph.iterateExprents(new DirectGraph.ExprentIterator() {
- public int processExprent(Exprent exprent) {
- for (Entry ent : mapClassMeths.entrySet()) {
- if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
- setFound.add(ent.getKey());
- }
+ graph.iterateExprents(exprent -> {
+ for (Entry ent : mapClassMeths.entrySet()) {
+ if (replaceInvocations(exprent, ent.getKey(), ent.getValue())) {
+ setFound.add(ent.getKey());
}
- return 0;
}
+ return 0;
});
}
}
@@ -160,7 +107,7 @@ public class ClassReference14Processor {
String cl = isClass14Invocation(exprent, ent.getKey(), ent.getValue());
if (cl != null) {
- initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
+ initializers.set(i, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'), exprent.bytecode));
setFound.add(ent.getKey());
}
}
@@ -173,10 +120,10 @@ public class ClassReference14Processor {
}
}
- private void mapClassMethods(ClassNode node, Map map) {
+ private static void mapClassMethods(ClassNode node, Map map) {
boolean noSynthFlag = DecompilerContext.getOption(IFernflowerPreferences.SYNTHETIC_NOT_SET);
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
for (MethodWrapper method : wrapper.getMethods()) {
StructMethod mt = method.methodStruct;
@@ -190,14 +137,14 @@ public class ClassReference14Processor {
CatchStatement cst = (CatchStatement)root.getFirst();
if (cst.getStats().size() == 2 && cst.getFirst().type == Statement.TYPE_BASICBLOCK &&
cst.getStats().get(1).type == Statement.TYPE_BASICBLOCK &&
- cst.getVars().get(0).getVartype().equals(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"))) {
+ cst.getVars().get(0).getVarType().equals(new VarType(CodeConstants.TYPE_OBJECT, 0, "java/lang/ClassNotFoundException"))) {
BasicBlockStatement body = (BasicBlockStatement)cst.getFirst();
BasicBlockStatement handler = (BasicBlockStatement)cst.getStats().get(1);
if (body.getExprents().size() == 1 && handler.getExprents().size() == 1) {
- if (bodyexprent.equals(body.getExprents().get(0)) &&
- handlerexprent.equals(handler.getExprents().get(0))) {
+ if (BODY_EXPR.equals(body.getExprents().get(0)) &&
+ HANDLER_EXPR.equals(handler.getExprents().get(0))) {
map.put(wrapper, method);
break;
}
@@ -213,19 +160,16 @@ public class ClassReference14Processor {
}
}
-
private static boolean replaceInvocations(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
-
boolean res = false;
while (true) {
-
boolean found = false;
for (Exprent expr : exprent.getAllExprents()) {
String cl = isClass14Invocation(expr, wrapper, meth);
if (cl != null) {
- exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/')));
+ exprent.replaceExprent(expr, new ConstExprent(VarType.VARTYPE_CLASS, cl.replace('.', '/'), expr.bytecode));
found = true;
res = true;
break;
@@ -242,18 +186,16 @@ public class ClassReference14Processor {
return res;
}
-
private static String isClass14Invocation(Exprent exprent, ClassWrapper wrapper, MethodWrapper meth) {
-
if (exprent.type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent fexpr = (FunctionExprent)exprent;
- if (fexpr.getFunctype() == FunctionExprent.FUNCTION_IIF) {
+ if (fexpr.getFuncType() == FunctionExprent.FUNCTION_IIF) {
if (fexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FUNCTION) {
FunctionExprent headexpr = (FunctionExprent)fexpr.getLstOperands().get(0);
- if (headexpr.getFunctype() == FunctionExprent.FUNCTION_EQ) {
+ if (headexpr.getFuncType() == FunctionExprent.FUNCTION_EQ) {
if (headexpr.getLstOperands().get(0).type == Exprent.EXPRENT_FIELD &&
headexpr.getLstOperands().get(1).type == Exprent.EXPRENT_CONST &&
- ((ConstExprent)headexpr.getLstOperands().get(1)).getConsttype().equals(VarType.VARTYPE_NULL)) {
+ ((ConstExprent)headexpr.getLstOperands().get(1)).getConstType().equals(VarType.VARTYPE_NULL)) {
FieldExprent field = (FieldExprent)headexpr.getLstOperands().get(0);
ClassNode fieldnode = DecompilerContext.getClassProcessor().getMapRootClasses().get(field.getClassname());
@@ -293,4 +235,4 @@ public class ClassReference14Processor {
return null;
}
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/main/ClassWriter.java b/src/org/jetbrains/java/decompiler/main/ClassWriter.java
index 6d08a90..72c215b 100644
--- a/src/org/jetbrains/java/decompiler/main/ClassWriter.java
+++ b/src/org/jetbrains/java/decompiler/main/ClassWriter.java
@@ -1,18 +1,4 @@
-/*
- * 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.
- */
+// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants;
@@ -23,18 +9,12 @@ import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
import org.jetbrains.java.decompiler.main.rels.ClassWrapper;
import org.jetbrains.java.decompiler.main.rels.MethodWrapper;
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
-import org.jetbrains.java.decompiler.modules.decompiler.exps.AnnotationExprent;
-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.NewExprent;
+import org.jetbrains.java.decompiler.modules.decompiler.exps.*;
import org.jetbrains.java.decompiler.modules.decompiler.stats.RootStatement;
import org.jetbrains.java.decompiler.modules.decompiler.vars.VarTypeProcessor;
-import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
+import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
-import org.jetbrains.java.decompiler.struct.StructClass;
-import org.jetbrains.java.decompiler.struct.StructField;
-import org.jetbrains.java.decompiler.struct.StructMember;
-import org.jetbrains.java.decompiler.struct.StructMethod;
+import org.jetbrains.java.decompiler.struct.*;
import org.jetbrains.java.decompiler.struct.attr.*;
import org.jetbrains.java.decompiler.struct.consts.PrimitiveConstant;
import org.jetbrains.java.decompiler.struct.gen.FieldDescriptor;
@@ -42,30 +22,29 @@ import org.jetbrains.java.decompiler.struct.gen.MethodDescriptor;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.struct.gen.generics.*;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
-import org.jetbrains.java.decompiler.util.Util;
+import org.jetbrains.java.decompiler.util.TextBuffer;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
public class ClassWriter {
-
- private ClassReference14Processor ref14processor;
- private PoolInterceptor interceptor;
+ private final PoolInterceptor interceptor;
public ClassWriter() {
- ref14processor = new ClassReference14Processor();
interceptor = DecompilerContext.getPoolInterceptor();
}
- private void invokeProcessors(ClassNode node) {
- ClassWrapper wrapper = node.wrapper;
+ private static void invokeProcessors(ClassNode node) {
+ ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
InitializerProcessor.extractInitializers(wrapper);
- if (node.type == ClassNode.CLASS_ROOT && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4)) {
- ref14processor.processClassReferences(node);
+ if (node.type == ClassNode.CLASS_ROOT &&
+ !cl.isVersion5() &&
+ DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_CLASS_1_4)) {
+ ClassReference14Processor.processClassReferences(node);
}
if (cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM)) {
@@ -77,13 +56,9 @@ public class ClassWriter {
}
}
- public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent) {
- // get the class node with the content method
- ClassNode classNode = node;
- while (classNode != null && classNode.type == ClassNode.CLASS_LAMBDA) {
- classNode = classNode.parent;
- }
- if (classNode == null) {
+ public void classLambdaToJava(ClassNode node, TextBuffer buffer, Exprent method_object, int indent, BytecodeMappingTracer origTracer) {
+ ClassWrapper wrapper = node.getWrapper();
+ if (wrapper == null) {
return;
}
@@ -92,39 +67,38 @@ public class ClassWriter {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
- BytecodeMappingTracer tracer = new BytecodeMappingTracer();
+ BytecodeMappingTracer tracer = new BytecodeMappingTracer(origTracer.getCurrentSourceLine());
try {
- ClassWrapper wrapper = classNode.wrapper;
StructClass cl = wrapper.getClassStruct();
DecompilerContext.getLogger().startWriteClass(node.simpleName);
- if (node.lambda_information.is_method_reference) {
- if (!node.lambda_information.is_content_method_static && method_object != null) {
+ if (node.lambdaInformation.is_method_reference) {
+ if (!node.lambdaInformation.is_content_method_static && method_object != null) {
// reference to a virtual method
buffer.append(method_object.toJava(indent, tracer));
}
else {
// reference to a static method
- buffer.append(ExprProcessor.getCastTypeName(new VarType(node.lambda_information.content_class_name, false)));
+ buffer.append(ExprProcessor.getCastTypeName(new VarType(node.lambdaInformation.content_class_name, true)));
}
- buffer.append("::");
- buffer.append("".equals(node.lambda_information.content_method_name) ? "new" : node.lambda_information.content_method_name);
+ buffer.append("::")
+ .append(CodeConstants.INIT_NAME.equals(node.lambdaInformation.content_method_name) ? "new" : node.lambdaInformation.content_method_name);
}
else {
// lambda method
- StructMethod mt = cl.getMethod(node.lambda_information.content_method_key);
+ StructMethod mt = cl.getMethod(node.lambdaInformation.content_method_key);
MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
- MethodDescriptor md_content = MethodDescriptor.parseDescriptor(node.lambda_information.content_method_descriptor);
- MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(node.lambda_information.method_descriptor);
+ MethodDescriptor md_content = MethodDescriptor.parseDescriptor(node.lambdaInformation.content_method_descriptor);
+ MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(node.lambdaInformation.method_descriptor);
if (!lambdaToAnonymous) {
buffer.append('(');
boolean firstParameter = true;
- int index = node.lambda_information.is_content_method_static ? 0 : 1;
+ int index = node.lambdaInformation.is_content_method_static ? 0 : 1;
int start_index = md_content.params.length - md_lambda.params.length;
for (int i = 0; i < md_content.params.length; i++) {
@@ -133,30 +107,26 @@ public class ClassWriter {
buffer.append(", ");
}
- String typeName = ExprProcessor.getCastTypeName(md_content.params[i].copy());
- if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName)
- && DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
- typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
- }
-
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, false));
+ String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0));
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
firstParameter = false;
}
- index += md_content.params[i].stack_size;
+ index += md_content.params[i].stackSize;
}
buffer.append(") ->");
}
- buffer.append(" {");
- buffer.append(DecompilerContext.getNewLineSeparator());
+ buffer.append(" {").appendLineSeparator();
+ tracer.incrementCurrentSourceLine();
- methodLambdaToJava(node, classNode, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);
+ methodLambdaToJava(node, wrapper, mt, buffer, indent + 1, !lambdaToAnonymous, tracer);
buffer.appendIndent(indent).append("}");
+
+ addTracer(cl, mt, tracer);
}
}
finally {
@@ -166,89 +136,72 @@ public class ClassWriter {
DecompilerContext.getLogger().endWriteClass();
}
- public void classToJava(ClassNode node, TextBuffer buffer, int indent) {
+ public void classToJava(ClassNode node, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
ClassNode outerNode = (ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, node);
- int total_offset_lines = 0;
- BytecodeMappingTracer dummy_tracer = new BytecodeMappingTracer();
+ int startLine = tracer != null ? tracer.getCurrentSourceLine() : 0;
+ BytecodeMappingTracer dummy_tracer = new BytecodeMappingTracer(startLine);
try {
// last minute processing
invokeProcessors(node);
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
DecompilerContext.getLogger().startWriteClass(cl.qualifiedName);
- String lineSeparator = DecompilerContext.getNewLineSeparator();
-
// write class definition
int start_class_def = buffer.length();
- boolean empty = cl.getFields().isEmpty() && cl.getMethods().isEmpty();
- if (cl.hasModifier(CodeConstants.ACC_ENUM)) {
- empty = true;
- for (StructField fd : cl.getFields()) {
- if (fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM)) {
- empty = false;
- break;
- }
- }
- }
- writeClassDefinition(node, buffer, indent, empty);
-
-// // count lines in class definition the easiest way
-// total_offset_lines = buffer.substring(start_class_def).toString().split(lineSeparator, -1).length - 1;
+ writeClassDefinition(node, buffer, indent);
boolean hasContent = false;
-
- // fields
boolean enumFields = false;
- boolean endEnumWritten = false; // Spigot
- boolean firstEnum = true;
+
+ dummy_tracer.incrementCurrentSourceLine(buffer.countLines(start_class_def));
+
+ List components = cl.getRecordComponents();
for (StructField fd : cl.getFields()) {
boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) ||
wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
if (hide) continue;
+ if (components != null && fd.getAccessFlags() == (CodeConstants.ACC_FINAL | CodeConstants.ACC_PRIVATE) &&
+ components.stream().anyMatch(c -> c.getName().equals(fd.getName()) && c.getDescriptor().equals(fd.getDescriptor()))) {
+ // Record component field: skip it
+ continue;
+ }
+
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isEnum) {
if (enumFields) {
- buffer.append(", ");
+ buffer.append(',').appendLineSeparator();
+ dummy_tracer.incrementCurrentSourceLine();
}
enumFields = true;
}
- else if (enumFields && !endEnumWritten) { // Spigot
+ else if (enumFields) {
buffer.append(';');
- buffer.append(lineSeparator);
- buffer.append(lineSeparator);
- endEnumWritten = true; // Spigot
+ buffer.appendLineSeparator();
+ buffer.appendLineSeparator();
+ dummy_tracer.incrementCurrentSourceLine(2);
+ enumFields = false;
}
- int ind = indent + 1;
- if (isEnum) {
- if (!firstEnum) {
- ind = 0;
- }
- firstEnum = false;
- }
- fieldToJava(wrapper, cl, fd, buffer, ind, dummy_tracer); // FIXME: insert real tracer
+ fieldToJava(wrapper, cl, fd, buffer, indent + 1, dummy_tracer); // FIXME: insert real tracer
hasContent = true;
}
- // Spigot Start
- int flags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access;
- boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0;
- if (isEnum && !endEnumWritten) {
- // Spigot End
- buffer.append(';');
- buffer.append(lineSeparator);
+
+ if (enumFields) {
+ buffer.append(';').appendLineSeparator();
+ dummy_tracer.incrementCurrentSourceLine();
}
// FIXME: fields don't matter at the moment
- total_offset_lines = buffer.count(lineSeparator, start_class_def);
+ startLine += buffer.countLines(start_class_def);
// methods
for (StructMethod mt : cl.getMethods()) {
@@ -258,19 +211,21 @@ public class ClassWriter {
if (hide) continue;
int position = buffer.length();
+ int storedLine = startLine;
if (hasContent) {
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
+ startLine++;
}
- BytecodeMappingTracer method_tracer = new BytecodeMappingTracer(total_offset_lines);
+ BytecodeMappingTracer method_tracer = new BytecodeMappingTracer(startLine);
boolean methodSkipped = !methodToJava(node, mt, buffer, indent + 1, method_tracer);
if (!methodSkipped) {
hasContent = true;
- DecompilerContext.getBytecodeSourceMapper().addTracer(cl.qualifiedName,
- InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()), method_tracer);
- total_offset_lines = (method_tracer.getCurrentSourceLine() + 1); // zero-based line index
+ addTracer(cl, mt, method_tracer);
+ startLine = method_tracer.getCurrentSourceLine();
}
else {
buffer.setLength(position);
+ startLine = storedLine;
}
}
@@ -284,9 +239,12 @@ public class ClassWriter {
if (hide) continue;
if (hasContent) {
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
+ startLine++;
}
- classToJava(inner, buffer, indent + 1);
+ BytecodeMappingTracer class_tracer = new BytecodeMappingTracer(startLine);
+ classToJava(inner, buffer, indent + 1, class_tracer);
+ startLine = buffer.countLines();
hasContent = true;
}
@@ -295,7 +253,7 @@ public class ClassWriter {
buffer.appendIndent(indent).append('}');
if (node.type != ClassNode.CLASS_ANONYMOUS) {
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
}
}
finally {
@@ -305,39 +263,154 @@ public class ClassWriter {
DecompilerContext.getLogger().endWriteClass();
}
- private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent, boolean empty) {
- String lineSeparator = DecompilerContext.getNewLineSeparator();
+ @SuppressWarnings("SpellCheckingInspection")
+ private static boolean isSyntheticRecordMethod(StructClass cl, StructMethod mt, TextBuffer code) {
+ //if (cl.getRecordComponents() != null) {
+ String name = mt.getName(), descriptor = mt.getDescriptor();
+ if (name.equals("equals") && descriptor.equals("(Ljava/lang/Object;)Z") ||
+ name.equals("hashCode") && descriptor.equals("()I") ||
+ name.equals("toString") && descriptor.equals("()Ljava/lang/String;")) {
+ if (code.countLines() == 1) {
+ String str = code.toString().trim();
+ return str.contains("return this." + name + "(this");
+ }
+ }
+ //}
+ return false;
+ }
+ public static void packageInfoToJava(StructClass cl, TextBuffer buffer) {
+ appendAnnotations(buffer, 0, cl, -1);
+
+ int index = cl.qualifiedName.lastIndexOf('/');
+ String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
+ buffer.append("package ").append(packageName).append(';').appendLineSeparator().appendLineSeparator();
+ }
+
+ public static void moduleInfoToJava(StructClass cl, TextBuffer buffer) {
+ appendAnnotations(buffer, 0, cl, -1);
+
+ StructModuleAttribute moduleAttribute = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);
+
+ if ((moduleAttribute.moduleFlags & CodeConstants.ACC_OPEN) != 0) {
+ buffer.append("open ");
+ }
+
+ buffer.append("module ").append(moduleAttribute.moduleName).append(" {").appendLineSeparator();
+
+ writeModuleInfoBody(buffer, moduleAttribute);
+
+ buffer.append('}').appendLineSeparator();
+ }
+
+ private static void writeModuleInfoBody(TextBuffer buffer, StructModuleAttribute moduleAttribute) {
+ boolean newLineNeeded = false;
+
+ List requiresEntries = moduleAttribute.requires;
+ if (!requiresEntries.isEmpty()) {
+ for (StructModuleAttribute.RequiresEntry requires : requiresEntries) {
+ if (!isGenerated(requires.flags)) {
+ buffer.appendIndent(1).append("requires ").append(requires.moduleName.replace('/', '.')).append(';').appendLineSeparator();
+ newLineNeeded = true;
+ }
+ }
+ }
+
+ List exportsEntries = moduleAttribute.exports;
+ if (!exportsEntries.isEmpty()) {
+ if (newLineNeeded) buffer.appendLineSeparator();
+ for (StructModuleAttribute.ExportsEntry exports : exportsEntries) {
+ if (!isGenerated(exports.flags)) {
+ buffer.appendIndent(1).append("exports ").append(exports.packageName.replace('/', '.'));
+ List exportToModules = exports.exportToModules;
+ if (exportToModules.size() > 0) {
+ buffer.append(" to").appendLineSeparator();
+ appendFQClassNames(buffer, exportToModules);
+ }
+ buffer.append(';').appendLineSeparator();
+ newLineNeeded = true;
+ }
+ }
+ }
+
+ List opensEntries = moduleAttribute.opens;
+ if (!opensEntries.isEmpty()) {
+ if (newLineNeeded) buffer.appendLineSeparator();
+ for (StructModuleAttribute.OpensEntry opens : opensEntries) {
+ if (!isGenerated(opens.flags)) {
+ buffer.appendIndent(1).append("opens ").append(opens.packageName.replace('/', '.'));
+ List opensToModules = opens.opensToModules;
+ if (opensToModules.size() > 0) {
+ buffer.append(" to").appendLineSeparator();
+ appendFQClassNames(buffer, opensToModules);
+ }
+ buffer.append(';').appendLineSeparator();
+ newLineNeeded = true;
+ }
+ }
+ }
+
+ List usesEntries = moduleAttribute.uses;
+ if (!usesEntries.isEmpty()) {
+ if (newLineNeeded) buffer.appendLineSeparator();
+ for (String uses : usesEntries) {
+ buffer.appendIndent(1).append("uses ").append(ExprProcessor.buildJavaClassName(uses)).append(';').appendLineSeparator();
+ }
+ newLineNeeded = true;
+ }
+
+ List providesEntries = moduleAttribute.provides;
+ if (!providesEntries.isEmpty()) {
+ if (newLineNeeded) buffer.appendLineSeparator();
+ for (StructModuleAttribute.ProvidesEntry provides : providesEntries) {
+ buffer.appendIndent(1).append("provides ").append(ExprProcessor.buildJavaClassName(provides.interfaceName)).append(" with").appendLineSeparator();
+ appendFQClassNames(buffer, provides.implementationNames.stream().map(ExprProcessor::buildJavaClassName).collect(Collectors.toList()));
+ buffer.append(';').appendLineSeparator();
+ }
+ }
+ }
+
+ private static boolean isGenerated(int flags) {
+ return (flags & (CodeConstants.ACC_SYNTHETIC | CodeConstants.ACC_MANDATED)) != 0;
+ }
+
+ private static void addTracer(StructClass cls, StructMethod method, BytecodeMappingTracer tracer) {
+ StructLineNumberTableAttribute table = method.getAttribute(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
+ tracer.setLineNumberTable(table);
+ String key = InterpreterUtil.makeUniqueKey(method.getName(), method.getDescriptor());
+ DecompilerContext.getBytecodeSourceMapper().addTracer(cls.qualifiedName, key, tracer);
+ }
+
+ private void writeClassDefinition(ClassNode node, TextBuffer buffer, int indent) {
if (node.type == ClassNode.CLASS_ANONYMOUS) {
- buffer.append(" {");
- if (!empty) buffer.append(lineSeparator);
+ buffer.append(" {").appendLineSeparator();
return;
}
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
int flags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access;
- boolean isDeprecated = cl.getAttributes().containsKey("Deprecated");
- boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.getAttributes().containsKey("Synthetic");
+ boolean isDeprecated = cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_DEPRECATED);
+ boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_SYNTHETIC);
boolean isEnum = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM) && (flags & CodeConstants.ACC_ENUM) != 0;
boolean isInterface = (flags & CodeConstants.ACC_INTERFACE) != 0;
boolean isAnnotation = (flags & CodeConstants.ACC_ANNOTATION) != 0;
if (isDeprecated) {
- appendDeprecation(buffer, indent, lineSeparator);
+ appendDeprecation(buffer, indent);
}
if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName);
- appendRenameComment(buffer, oldName, MType.CLASS, indent, lineSeparator);
+ appendRenameComment(buffer, oldName, MType.CLASS, indent);
}
if (isSynthetic) {
- appendComment(buffer, "synthetic class", indent, lineSeparator);
+ appendComment(buffer, "synthetic class", indent);
}
- appendAnnotations(buffer, cl, indent, lineSeparator);
+ appendAnnotations(buffer, indent, cl, -1);
buffer.appendIndent(indent);
@@ -347,6 +420,13 @@ public class ClassWriter {
flags &= ~CodeConstants.ACC_FINAL;
}
+ List components = cl.getRecordComponents();
+
+ if (components != null) {
+ // records are implicitly final
+ flags &= ~CodeConstants.ACC_FINAL;
+ }
+
appendModifiers(buffer, flags, CLASS_ALLOWED, isInterface, CLASS_EXCLUDED);
if (isEnum) {
@@ -358,87 +438,123 @@ public class ClassWriter {
}
buffer.append("interface ");
}
+ else if (components != null) {
+ buffer.append("record ");
+ }
else {
buffer.append("class ");
}
-
- GenericClassDescriptor descriptor = null;
- if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
- StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)cl.getAttributes().getWithKey("Signature");
- if (attr != null) {
- descriptor = GenericMain.parseClassSignature(attr.getSignature());
- }
- }
-
buffer.append(node.simpleName);
+ GenericClassDescriptor descriptor = getGenericClassDescriptor(cl);
if (descriptor != null && !descriptor.fparameters.isEmpty()) {
appendTypeParameters(buffer, descriptor.fparameters, descriptor.fbounds);
}
+ if (components != null) {
+ buffer.append('(');
+ for (int i = 0; i < components.size(); i++) {
+ StructRecordComponent cd = components.get(i);
+ if (i > 0) {
+ buffer.append(", ");
+ }
+ boolean varArgComponent = i == components.size() - 1 && isVarArgRecord(cl);
+ recordComponentToJava(cd, buffer, varArgComponent);
+ }
+ buffer.append(')');
+ }
+
buffer.append(' ');
- if (!isEnum && !isInterface && cl.superClass != null) {
+ if (!isEnum && !isInterface && components == null && cl.superClass != null) {
VarType supertype = new VarType(cl.superClass.getString(), true);
if (!VarType.VARTYPE_OBJECT.equals(supertype)) {
- buffer.append("extends ");
+ String name;
if (descriptor != null) {
- buffer.append(GenericMain.getGenericCastTypeName(descriptor.superclass));
+ name = GenericMain.getGenericCastTypeName(descriptor.superclass);
}
else {
- buffer.append(ExprProcessor.getCastTypeName(supertype));
+ name = ExprProcessor.getCastTypeName(supertype);
+ }
+ if (!name.equals("Record"))
+ {
+ buffer.append("extends ");
+ buffer.append(name);
+ buffer.append(' ');
}
- buffer.append(' ');
}
}
if (!isAnnotation) {
int[] interfaces = cl.getInterfaces();
if (interfaces.length > 0) {
- buffer.append(isInterface ? "extends " : "implements ");
- for (int i = 0; i < interfaces.length; i++) {
- if (i > 0) {
+
+ boolean seenOne = false;
+ for (int i = 0; i < interfaces.length; i++)
+ {
+ if (seenOne)
+ {
buffer.append(", ");
}
- if (descriptor != null) {
- buffer.append(GenericMain.getGenericCastTypeName(descriptor.superinterfaces.get(i)));
+
+ String name;
+ if (descriptor != null)
+ {
+ name = GenericMain.getGenericCastTypeName(descriptor.superinterfaces.get(i));
}
- else {
- buffer.append(ExprProcessor.getCastTypeName(new VarType(cl.getInterface(i), true)));
+ else
+ {
+ name = ExprProcessor.getCastTypeName(new VarType(cl.getInterface(i), true));
}
+
+ // TODO: evil
+ if (name.equals("Record"))
+ {
+ continue;
+ }
+
+ if (!seenOne)
+ {
+ buffer.append(isInterface ? "extends " : "implements ");
+ }
+
+ buffer.append(name);
+ seenOne = true;
}
buffer.append(' ');
}
}
- buffer.append('{');
- if (!empty) {
- buffer.append(lineSeparator);
- buffer.append(lineSeparator); // Spigot
- }
+ buffer.append('{').appendLineSeparator();
+ }
+
+ private static boolean isVarArgRecord(StructClass cl) {
+ String canonicalConstructorDescriptor =
+ cl.getRecordComponents().stream().map(c -> c.getDescriptor()).collect(Collectors.joining("", "(", ")V"));
+ StructMethod init = cl.getMethod(CodeConstants.INIT_NAME, canonicalConstructorDescriptor);
+ return init != null && init.hasModifier(CodeConstants.ACC_VARARGS);
}
private void fieldToJava(ClassWrapper wrapper, StructClass cl, StructField fd, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
- String lineSeparator = DecompilerContext.getNewLineSeparator();
-
+ int start = buffer.length();
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
- boolean isDeprecated = fd.getAttributes().containsKey("Deprecated");
+ boolean isDeprecated = fd.hasAttribute(StructGeneralAttribute.ATTRIBUTE_DEPRECATED);
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isDeprecated) {
- appendDeprecation(buffer, indent, lineSeparator);
+ appendDeprecation(buffer, indent);
}
if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName + " " + fd.getName() + " " + fd.getDescriptor());
- appendRenameComment(buffer, oldName, MType.FIELD, indent, lineSeparator);
+ appendRenameComment(buffer, oldName, MType.FIELD, indent);
}
if (fd.isSynthetic()) {
- appendComment(buffer, "synthetic field", indent, lineSeparator);
+ appendComment(buffer, "synthetic field", indent);
}
- appendAnnotations(buffer, fd, indent, lineSeparator);
+ appendAnnotations(buffer, indent, fd, TypeAnnotation.FIELD);
buffer.appendIndent(indent);
@@ -446,15 +562,9 @@ public class ClassWriter {
appendModifiers(buffer, fd.getAccessFlags(), FIELD_ALLOWED, isInterface, FIELD_EXCLUDED);
}
- VarType fieldType = new VarType(fd.getDescriptor(), false);
-
- GenericFieldDescriptor descriptor = null;
- if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
- StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)fd.getAttributes().getWithKey("Signature");
- if (attr != null) {
- descriptor = GenericMain.parseFieldSignature(attr.getSignature());
- }
- }
+ Map.Entry fieldTypeData = getFieldTypeData(fd);
+ VarType fieldType = fieldTypeData.getKey();
+ GenericFieldDescriptor descriptor = fieldTypeData.getValue();
if (!isEnum) {
if (descriptor != null) {
@@ -468,6 +578,8 @@ public class ClassWriter {
buffer.append(fd.getName());
+ tracer.incrementCurrentSourceLine(buffer.countLines(start));
+
Exprent initializer;
if (fd.hasModifier(CodeConstants.ACC_STATIC)) {
initializer = wrapper.getStaticFieldInitializers().getWithKey(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
@@ -477,48 +589,72 @@ public class ClassWriter {
}
if (initializer != null) {
if (isEnum && initializer.type == Exprent.EXPRENT_NEW) {
- NewExprent nexpr = (NewExprent)initializer;
- nexpr.setEnumconst(true);
- buffer.append(nexpr.toJava(indent, tracer));
+ NewExprent expr = (NewExprent)initializer;
+ expr.setEnumConst(true);
+ buffer.append(expr.toJava(indent, tracer));
}
else {
buffer.append(" = ");
- // FIXME: special case field initializer. Can map to more than one method (constructor) and bytecode intruction.
+
+ if (initializer.type == Exprent.EXPRENT_CONST) {
+ ((ConstExprent) initializer).adjustConstType(fieldType);
+ }
+
+ // FIXME: special case field initializer. Can map to more than one method (constructor) and bytecode instruction
buffer.append(initializer.toJava(indent, tracer));
}
}
else if (fd.hasModifier(CodeConstants.ACC_FINAL) && fd.hasModifier(CodeConstants.ACC_STATIC)) {
- StructConstantValueAttribute attr =
- (StructConstantValueAttribute)fd.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE);
+ StructConstantValueAttribute attr = fd.getAttribute(StructGeneralAttribute.ATTRIBUTE_CONSTANT_VALUE);
if (attr != null) {
PrimitiveConstant constant = cl.getPool().getPrimitiveConstant(attr.getIndex());
buffer.append(" = ");
- buffer.append(new ConstExprent(fieldType, constant.value).toJava(indent, tracer));
+ buffer.append(new ConstExprent(fieldType, constant.value, null).toJava(indent, tracer));
}
}
if (!isEnum) {
- buffer.append(";");
- buffer.append(lineSeparator);
+ buffer.append(";").appendLineSeparator();
+ tracer.incrementCurrentSourceLine();
}
}
+ private static void recordComponentToJava(StructRecordComponent cd, TextBuffer buffer, boolean varArgComponent) {
+ appendAnnotations(buffer, -1, cd, TypeAnnotation.FIELD);
+
+ Map.Entry fieldTypeData = getFieldTypeData(cd);
+ VarType fieldType = fieldTypeData.getKey();
+ GenericFieldDescriptor descriptor = fieldTypeData.getValue();
+
+ if (descriptor != null) {
+ buffer.append(GenericMain.getGenericCastTypeName(varArgComponent ? descriptor.type.decreaseArrayDim() : descriptor.type));
+ }
+ else {
+ buffer.append(ExprProcessor.getCastTypeName(varArgComponent ? fieldType.decreaseArrayDim() : fieldType));
+ }
+ if (varArgComponent) {
+ buffer.append("...");
+ }
+ buffer.append(' ');
+
+ buffer.append(cd.getName());
+ }
+
private static void methodLambdaToJava(ClassNode lambdaNode,
- ClassNode classNode,
+ ClassWrapper classWrapper,
StructMethod mt,
TextBuffer buffer,
int indent,
boolean codeOnly, BytecodeMappingTracer tracer) {
- ClassWrapper classWrapper = classNode.wrapper;
MethodWrapper methodWrapper = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper);
try {
- String method_name = lambdaNode.lambda_information.method_name;
- MethodDescriptor md_content = MethodDescriptor.parseDescriptor(lambdaNode.lambda_information.content_method_descriptor);
- MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(lambdaNode.lambda_information.method_descriptor);
+ String method_name = lambdaNode.lambdaInformation.method_name;
+ MethodDescriptor md_content = MethodDescriptor.parseDescriptor(lambdaNode.lambdaInformation.content_method_descriptor);
+ MethodDescriptor md_lambda = MethodDescriptor.parseDescriptor(lambdaNode.lambdaInformation.method_descriptor);
if (!codeOnly) {
buffer.appendIndent(indent);
@@ -527,7 +663,7 @@ public class ClassWriter {
buffer.append("(");
boolean firstParameter = true;
- int index = lambdaNode.lambda_information.is_content_method_static ? 0 : 1;
+ int index = lambdaNode.lambdaInformation.is_content_method_static ? 0 : 1;
int start_index = md_content.params.length - md_lambda.params.length;
for (int i = 0; i < md_content.params.length; i++) {
@@ -545,29 +681,29 @@ public class ClassWriter {
buffer.append(typeName);
buffer.append(" ");
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, false)); // Spigot
+ String parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0));
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
firstParameter = false;
}
- index += md_content.params[i].stack_size;
+ index += md_content.params[i].stackSize;
}
- buffer.append(") {");
- buffer.append(DecompilerContext.getNewLineSeparator());
+ buffer.append(") {").appendLineSeparator();
indent += 1;
}
+ RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
if (!methodWrapper.decompiledWithErrors) {
- RootStatement root = classWrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
if (root != null) { // check for existence
try {
buffer.append(root.toJava(indent, tracer));
}
- catch (Throwable ex) {
- DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.", ex);
+ catch (Throwable t) {
+ String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t);
methodWrapper.decompiledWithErrors = true;
}
}
@@ -576,15 +712,16 @@ public class ClassWriter {
if (methodWrapper.decompiledWithErrors) {
buffer.appendIndent(indent);
buffer.append("// $FF: Couldn't be decompiled");
- buffer.append(DecompilerContext.getNewLineSeparator());
+ buffer.appendLineSeparator();
+ }
+
+ if (root != null) {
+ tracer.addMapping(root.getDummyExit().bytecode);
}
if (!codeOnly) {
indent -= 1;
-
- buffer.appendIndent(indent);
- buffer.append('}');
- buffer.append(DecompilerContext.getNewLineSeparator());
+ buffer.appendIndent(indent).append('}').appendLineSeparator();
}
}
finally {
@@ -592,16 +729,36 @@ public class ClassWriter {
}
}
+ private static String toValidJavaIdentifier(String name) {
+ if (name == null || name.isEmpty()) return name;
+
+ boolean changed = false;
+ StringBuilder res = new StringBuilder(name.length());
+ for (int i = 0; i < name.length(); i++) {
+ char c = name.charAt(i);
+ if ((i == 0 && !Character.isJavaIdentifierStart(c))
+ || (i > 0 && !Character.isJavaIdentifierPart(c))) {
+ changed = true;
+ res.append("_");
+ }
+ else {
+ res.append(c);
+ }
+ }
+ if (!changed) {
+ return name;
+ }
+ return res.append("/* $FF was: ").append(name).append("*/").toString();
+ }
+
private boolean methodToJava(ClassNode node, StructMethod mt, TextBuffer buffer, int indent, BytecodeMappingTracer tracer) {
- ClassWrapper wrapper = node.wrapper;
+ ClassWrapper wrapper = node.getWrapper();
StructClass cl = wrapper.getClassStruct();
MethodWrapper methodWrapper = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor());
boolean hideMethod = false;
int start_index_method = buffer.length();
- String lineSeparator = DecompilerContext.getNewLineSeparator();
-
MethodWrapper outerWrapper = (MethodWrapper)DecompilerContext.getProperty(DecompilerContext.CURRENT_METHOD_WRAPPER);
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, methodWrapper);
@@ -609,17 +766,8 @@ public class ClassWriter {
boolean isInterface = cl.hasModifier(CodeConstants.ACC_INTERFACE);
boolean isAnnotation = cl.hasModifier(CodeConstants.ACC_ANNOTATION);
boolean isEnum = cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
- boolean isDeprecated = mt.getAttributes().containsKey("Deprecated");
- boolean clinit = false, init = false, dinit = false;
-
- int startLine = -1;
- if (DecompilerContext.getOption(IFernflowerPreferences.USE_DEBUG_LINE_NUMBERS)) {
- StructLineNumberTableAttribute lineNumberTable =
- (StructLineNumberTableAttribute)mt.getAttributes().getWithKey(StructGeneralAttribute.ATTRIBUTE_LINE_NUMBER_TABLE);
- if (lineNumberTable != null) {
- startLine = lineNumberTable.getFirstLine();
- }
- }
+ boolean isDeprecated = mt.hasAttribute(StructGeneralAttribute.ATTRIBUTE_DEPRECATED);
+ boolean clInit = false, init = false, dInit = false;
MethodDescriptor md = MethodDescriptor.parseDescriptor(mt.getDescriptor());
@@ -627,65 +775,72 @@ public class ClassWriter {
if ((flags & CodeConstants.ACC_NATIVE) != 0) {
flags &= ~CodeConstants.ACC_STRICT; // compiler bug: a strictfp class sets all methods to strictfp
}
- if ("".equals(mt.getName())) {
+ if (CodeConstants.CLINIT_NAME.equals(mt.getName())) {
flags &= CodeConstants.ACC_STATIC; // ignore all modifiers except 'static' in a static initializer
}
if (isDeprecated) {
- appendDeprecation(buffer, indent, lineSeparator);
+ appendDeprecation(buffer, indent);
}
if (interceptor != null) {
String oldName = interceptor.getOldName(cl.qualifiedName + " " + mt.getName() + " " + mt.getDescriptor());
- appendRenameComment(buffer, oldName, MType.METHOD, indent, lineSeparator);
+ appendRenameComment(buffer, oldName, MType.METHOD, indent);
}
- boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.getAttributes().containsKey("Synthetic");
+ boolean isSynthetic = (flags & CodeConstants.ACC_SYNTHETIC) != 0 || mt.hasAttribute(StructGeneralAttribute.ATTRIBUTE_SYNTHETIC);
boolean isBridge = (flags & CodeConstants.ACC_BRIDGE) != 0;
if (isSynthetic) {
- appendComment(buffer, "synthetic method", indent, lineSeparator);
+ return false;
+ //appendComment(buffer, "synthetic method", indent);
}
if (isBridge) {
- appendComment(buffer, "bridge method", indent, lineSeparator);
+ appendComment(buffer, "bridge method", indent);
}
- appendAnnotations(buffer, mt, indent, lineSeparator);
+ appendAnnotations(buffer, indent, mt, TypeAnnotation.METHOD_RETURN_TYPE);
buffer.appendIndent(indent);
appendModifiers(buffer, flags, METHOD_ALLOWED, isInterface, METHOD_EXCLUDED);
- if (isInterface && mt.containsCode()) {
+ if (isInterface && !mt.hasModifier(CodeConstants.ACC_STATIC) && mt.containsCode()) {
// 'default' modifier (Java 8)
buffer.append("default ");
}
String name = mt.getName();
- if ("".equals(name)) {
+ if (CodeConstants.INIT_NAME.equals(name)) {
if (node.type == ClassNode.CLASS_ANONYMOUS) {
name = "";
- dinit = true;
+ dInit = true;
}
else {
name = node.simpleName;
init = true;
}
}
- else if ("".equals(name)) {
+ else if (CodeConstants.CLINIT_NAME.equals(name)) {
name = "";
- clinit = true;
+ clInit = true;
}
GenericMethodDescriptor descriptor = null;
if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
- StructGenericSignatureAttribute attr = (StructGenericSignatureAttribute)mt.getAttributes().getWithKey("Signature");
+ StructGenericSignatureAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_SIGNATURE);
if (attr != null) {
descriptor = GenericMain.parseMethodSignature(attr.getSignature());
if (descriptor != null) {
- int actualParams = md.params.length;
- if (isEnum && init) actualParams -= 2;
- if (actualParams != descriptor.params.size()) {
- String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor();
+ long actualParams = md.params.length;
+ List mask = methodWrapper.synthParameters;
+ if (mask != null) {
+ actualParams = mask.stream().filter(Objects::isNull).count();
+ }
+ else if (isEnum && init) {
+ actualParams -= 2;
+ }
+ if (actualParams != descriptor.parameterTypes.size()) {
+ String message = "Inconsistent generic signature in method " + mt.getName() + " " + mt.getDescriptor() + " in " + cl.qualifiedName;
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
descriptor = null;
}
@@ -696,17 +851,17 @@ public class ClassWriter {
boolean throwsExceptions = false;
int paramCount = 0;
- if (!clinit && !dinit) {
+ if (!clInit && !dInit) {
boolean thisVar = !mt.hasModifier(CodeConstants.ACC_STATIC);
- if (descriptor != null && !descriptor.fparameters.isEmpty()) {
- appendTypeParameters(buffer, descriptor.fparameters, descriptor.fbounds);
+ if (descriptor != null && !descriptor.typeParameters.isEmpty()) {
+ appendTypeParameters(buffer, descriptor.typeParameters, descriptor.typeParameterBounds);
buffer.append(' ');
}
if (!init) {
if (descriptor != null) {
- buffer.append(GenericMain.getGenericCastTypeName(descriptor.ret));
+ buffer.append(GenericMain.getGenericCastTypeName(descriptor.returnType));
}
else {
buffer.append(ExprProcessor.getCastTypeName(md.ret));
@@ -714,95 +869,93 @@ public class ClassWriter {
buffer.append(' ');
}
- buffer.append(name);
+ buffer.append(toValidJavaIdentifier(name));
buffer.append('(');
- // parameters
- List signFields = methodWrapper.signatureFields;
+ List mask = methodWrapper.synthParameters;
int lastVisibleParameterIndex = -1;
for (int i = 0; i < md.params.length; i++) {
- if (signFields == null || signFields.get(i) == null) {
+ if (mask == null || mask.get(i) == null) {
lastVisibleParameterIndex = i;
}
}
- boolean firstParameter = true;
+ List methodParameters = null;
+ if (DecompilerContext.getOption(IFernflowerPreferences.USE_METHOD_PARAMETERS)) {
+ StructMethodParametersAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_METHOD_PARAMETERS);
+ if (attr != null) {
+ methodParameters = attr.getEntries();
+ }
+ }
+
int index = isEnum && init ? 3 : thisVar ? 1 : 0;
- int start = isEnum && init && descriptor == null ? 2 : 0;
- int params = descriptor == null ? md.params.length : descriptor.params.size();
- for (int i = start; i < params; i++) {
- // Spigot Start
- String typeName;
- boolean isVarArg;
- // Spigot end
- if (signFields == null || signFields.get(i) == null) {
- if (!firstParameter) {
+ int start = isEnum && init ? 2 : 0;
+ for (int i = start; i < md.params.length; i++) {
+ if (mask == null || mask.get(i) == null) {
+ if (paramCount > 0) {
buffer.append(", ");
}
appendParameterAnnotations(buffer, mt, paramCount);
- if (methodWrapper.varproc.getVarFinal(new VarVersionPaar(index, 0)) == VarTypeProcessor.VAR_FINALEXPLICIT) {
+ if (methodParameters != null && i < methodParameters.size()) {
+ appendModifiers(buffer, methodParameters.get(i).myAccessFlags, CodeConstants.ACC_FINAL, isInterface, 0);
+ }
+ else if (methodWrapper.varproc.getVarFinal(new VarVersionPair(index, 0)) == VarTypeProcessor.VAR_EXPLICIT_FINAL) {
buffer.append("final ");
}
+ String typeName;
+ boolean isVarArg = i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS);
+
if (descriptor != null) {
- GenericType parameterType = descriptor.params.get(i);
-
- isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); // Spigot
+ GenericType parameterType = descriptor.parameterTypes.get(paramCount);
+ isVarArg &= parameterType.arrayDim > 0;
if (isVarArg) {
- parameterType.arraydim--;
- }
-
- typeName = GenericMain.getGenericCastTypeName(parameterType); // Spigot
- if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName) &&
- DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
- typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
- }
-
- buffer.append(typeName);
-
- if (isVarArg) {
- buffer.append("...");
+ parameterType = parameterType.decreaseArrayDim();
}
+ typeName = GenericMain.getGenericCastTypeName(parameterType);
}
else {
- VarType parameterType = md.params[i].copy();
-
- isVarArg = (i == lastVisibleParameterIndex && mt.hasModifier(CodeConstants.ACC_VARARGS) && parameterType.arraydim > 0); // Spigot
+ VarType parameterType = md.params[i];
+ isVarArg &= parameterType.arrayDim > 0;
if (isVarArg) {
- parameterType.decArrayDim();
+ parameterType = parameterType.decreaseArrayDim();
}
+ typeName = ExprProcessor.getCastTypeName(parameterType);
+ }
- typeName = ExprProcessor.getCastTypeName(parameterType); // Spigot
- if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName) &&
- DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
- typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
- }
-
- buffer.append(typeName);
-
- if (isVarArg) {
- buffer.append("...");
- }
+ if (ExprProcessor.UNDEFINED_TYPE_STRING.equals(typeName) &&
+ DecompilerContext.getOption(IFernflowerPreferences.UNDEFINED_PARAM_TYPE_OBJECT)) {
+ typeName = ExprProcessor.getCastTypeName(VarType.VARTYPE_OBJECT);
+ }
+ buffer.append(typeName);
+ if (isVarArg) {
+ buffer.append("...");
}
buffer.append(' ');
- String parameterName = methodWrapper.varproc.getVarName(new VarVersionPaar(index, 0, typeName, isVarArg)); // Spigot
+
+ String parameterName;
+ if (methodParameters != null && i < methodParameters.size()) {
+ parameterName = methodParameters.get(i).myName;
+ }
+ else {
+ parameterName = methodWrapper.varproc.getVarName(new VarVersionPair(index, 0));
+ }
buffer.append(parameterName == null ? "param" + index : parameterName); // null iff decompiled with errors
- firstParameter = false;
paramCount++;
}
- index += md.params[i].stack_size;
+ index += md.params[i].stackSize;
}
buffer.append(')');
- StructExceptionsAttribute attr = (StructExceptionsAttribute)mt.getAttributes().getWithKey("Exceptions");
- if ((descriptor != null && !descriptor.exceptions.isEmpty()) || attr != null) {
+ StructExceptionsAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_EXCEPTIONS);
+ if ((descriptor != null && !descriptor.exceptionTypes.isEmpty()) || attr != null) {
throwsExceptions = true;
buffer.append(" throws ");
@@ -810,8 +963,8 @@ public class ClassWriter {
if (i > 0) {
buffer.append(", ");
}
- if (descriptor != null && !descriptor.exceptions.isEmpty()) {
- GenericType type = descriptor.exceptions.get(i);
+ if (descriptor != null && !descriptor.exceptionTypes.isEmpty()) {
+ GenericType type = descriptor.exceptionTypes.get(i);
buffer.append(GenericMain.getGenericCastTypeName(type));
}
else {
@@ -822,49 +975,48 @@ public class ClassWriter {
}
}
+ tracer.incrementCurrentSourceLine(buffer.countLines(start_index_method));
+
if ((flags & (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_NATIVE)) != 0) { // native or abstract method (explicit or interface)
if (isAnnotation) {
- StructAnnDefaultAttribute attr = (StructAnnDefaultAttribute)mt.getAttributes().getWithKey("AnnotationDefault");
+ StructAnnDefaultAttribute attr = mt.getAttribute(StructGeneralAttribute.ATTRIBUTE_ANNOTATION_DEFAULT);
if (attr != null) {
buffer.append(" default ");
- buffer.append(attr.getDefaultValue().toJava(indent + 1, new BytecodeMappingTracer())); // dummy tracer
+ buffer.append(attr.getDefaultValue().toJava(0, BytecodeMappingTracer.DUMMY));
}
}
buffer.append(';');
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
}
else {
- if (!clinit && !dinit) {
+ if (!clInit && !dInit) {
buffer.append(' ');
}
- //TODO: for now only start line set
- buffer.setCurrentLine(startLine);
- buffer.append('{');
+ // We do not have line information for method start, lets have it here for now
+ buffer.append('{').appendLineSeparator();
+ tracer.incrementCurrentSourceLine();
RootStatement root = wrapper.getMethodWrapper(mt.getName(), mt.getDescriptor()).root;
- boolean empty = false;
- if (root != null && !methodWrapper.decompiledWithErrors) { // check for existence
+ if (root != null ) { // check for existence
try {
- tracer.incrementCurrentSourceLine(buffer.count(lineSeparator, start_index_method));
+ // to restore in case of an exception
+ BytecodeMappingTracer codeTracer = new BytecodeMappingTracer(tracer.getCurrentSourceLine());
+ TextBuffer code = root.toJava(indent + 1, codeTracer);
- String code = root.toJava(indent + 1, tracer);
+ hideMethod = code.length() == 0 && (clInit || dInit || hideConstructor(node, init, throwsExceptions, paramCount, flags)) ||
+ isSyntheticRecordMethod(cl, mt, code);
- if (Util.rtrim(code).isEmpty()) code = "";
-
- hideMethod = (clinit || dinit || hideConstructor(wrapper, init, throwsExceptions, paramCount)) && code.length() == 0;
-
- if (!code.isEmpty()) {
- buffer.appendLineSeparator();
- } else {
- empty = true;
- }
buffer.append(code);
+
+ tracer.setCurrentSourceLine(codeTracer.getCurrentSourceLine());
+ tracer.addTracer(codeTracer);
}
- catch (Throwable ex) {
- DecompilerContext.getLogger().writeMessage("Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.", ex);
+ catch (Throwable t) {
+ String message = "Method " + mt.getName() + " " + mt.getDescriptor() + " couldn't be written.";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN, t);
methodWrapper.decompiledWithErrors = true;
}
}
@@ -872,14 +1024,16 @@ public class ClassWriter {
if (methodWrapper.decompiledWithErrors) {
buffer.appendIndent(indent + 1);
buffer.append("// $FF: Couldn't be decompiled");
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
+ tracer.incrementCurrentSourceLine();
}
-
- if (!empty) {
- buffer.appendIndent(indent);
+ else if (root != null) {
+ tracer.addMapping(root.getDummyExit().bytecode);
}
- buffer.append('}').appendLineSeparator();
+ buffer.appendIndent(indent).append('}').appendLineSeparator();
}
+
+ tracer.incrementCurrentSourceLine();
}
finally {
DecompilerContext.setProperty(DecompilerContext.CURRENT_METHOD_WRAPPER, outerWrapper);
@@ -887,19 +1041,30 @@ public class ClassWriter {
// save total lines
// TODO: optimize
- tracer.setCurrentSourceLine(buffer.count(lineSeparator, start_index_method));
+ //tracer.setCurrentSourceLine(buffer.countLines(start_index_method));
return !hideMethod;
}
- private static boolean hideConstructor(ClassWrapper wrapper, boolean init, boolean throwsExceptions, int paramCount) {
+ private static boolean hideConstructor(ClassNode node, boolean init, boolean throwsExceptions, int paramCount, int methodAccessFlags) {
if (!init || throwsExceptions || paramCount > 0 || !DecompilerContext.getOption(IFernflowerPreferences.HIDE_DEFAULT_CONSTRUCTOR)) {
return false;
}
+ ClassWrapper wrapper = node.getWrapper();
+ StructClass cl = wrapper.getClassStruct();
+
+ int classAccessFlags = node.type == ClassNode.CLASS_ROOT ? cl.getAccessFlags() : node.access;
+ boolean isEnum = cl.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
+
+ // default constructor requires same accessibility flags. Exception: enum constructor which is always private
+ if(!isEnum && ((classAccessFlags & ACCESSIBILITY_FLAGS) != (methodAccessFlags & ACCESSIBILITY_FLAGS))) {
+ return false;
+ }
+
int count = 0;
- for (StructMethod mt : wrapper.getClassStruct().getMethods()) {
- if ("".equals(mt.getName())) {
+ for (StructMethod mt : cl.getMethods()) {
+ if (CodeConstants.INIT_NAME.equals(mt.getName())) {
if (++count > 1) {
return false;
}
@@ -909,13 +1074,27 @@ public class ClassWriter {
return true;
}
- private static void appendDeprecation(TextBuffer buffer, int indent, String lineSeparator) {
- buffer.appendIndent(indent).append("/** @deprecated */").append(lineSeparator);
+ private static Map.Entry getFieldTypeData(StructField fd) {
+ VarType fieldType = new VarType(fd.getDescriptor(), false);
+
+ GenericFieldDescriptor descriptor = null;
+ if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
+ StructGenericSignatureAttribute attr = fd.getAttribute(StructGeneralAttribute.ATTRIBUTE_SIGNATURE);
+ if (attr != null) {
+ descriptor = GenericMain.parseFieldSignature(attr.getSignature());
+ }
+ }
+
+ return new AbstractMap.SimpleImmutableEntry<>(fieldType, descriptor);
+ }
+
+ private static void appendDeprecation(TextBuffer buffer, int indent) {
+ buffer.appendIndent(indent).append("/** @deprecated */").appendLineSeparator();
}
private enum MType {CLASS, FIELD, METHOD}
- private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent, String lineSeparator) {
+ private static void appendRenameComment(TextBuffer buffer, String oldName, MType type, int indent) {
if (oldName == null) return;
buffer.appendIndent(indent);
@@ -951,7 +1130,7 @@ public class ClassWriter {
buffer.append(getTypePrintOut(md.ret));
}
- buffer.append(lineSeparator);
+ buffer.appendLineSeparator();
}
private static String getTypePrintOut(VarType type) {
@@ -963,60 +1142,97 @@ public class ClassWriter {
return typeText;
}
- private static void appendComment(TextBuffer buffer, String comment, int indent, String lineSeparator) {
- // buffer.appendIndent(indent).append("// $FF: ").append(comment).append(lineSeparator); // Spigot: Squash comments
+ private static void appendComment(TextBuffer buffer, String comment, int indent) {
+ buffer.appendIndent(indent).append("// $FF: ").append(comment).appendLineSeparator();
}
- private static final String[] ANNOTATION_ATTRIBUTES = {
+ private static final StructGeneralAttribute.Key>[] ANNOTATION_ATTRIBUTES = {
StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_ANNOTATIONS};
+ private static final StructGeneralAttribute.Key>[] PARAMETER_ANNOTATION_ATTRIBUTES = {
+ StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
+ private static final StructGeneralAttribute.Key>[] TYPE_ANNOTATION_ATTRIBUTES = {
+ StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_TYPE_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_TYPE_ANNOTATIONS};
- private static void appendAnnotations(TextBuffer buffer, StructMember mb, int indent, String lineSeparator) {
+ private static void appendAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType) {
+ Set filter = new HashSet<>();
- BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
-
- for (String name : ANNOTATION_ATTRIBUTES) {
- StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttributes().getWithKey(name);
+ for (StructGeneralAttribute.Key> key : ANNOTATION_ATTRIBUTES) {
+ StructAnnotationAttribute attribute = (StructAnnotationAttribute)mb.getAttribute(key);
if (attribute != null) {
for (AnnotationExprent annotation : attribute.getAnnotations()) {
- buffer.append(annotation.toJava(indent, tracer_dummy)).append(lineSeparator);
+ String text = annotation.toJava(indent, BytecodeMappingTracer.DUMMY).toString();
+ filter.add(text);
+ buffer.append(text);
+ if (indent < 0) {
+ buffer.append(' ');
+ }
+ else {
+ buffer.appendLineSeparator();
+ }
}
}
}
+
+ appendTypeAnnotations(buffer, indent, mb, targetType, -1, filter);
}
- private static final String[] PARAMETER_ANNOTATION_ATTRIBUTES = {
- StructGeneralAttribute.ATTRIBUTE_RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS, StructGeneralAttribute.ATTRIBUTE_RUNTIME_INVISIBLE_PARAMETER_ANNOTATIONS};
-
private static void appendParameterAnnotations(TextBuffer buffer, StructMethod mt, int param) {
+ Set filter = new HashSet<>();
- BytecodeMappingTracer tracer_dummy = new BytecodeMappingTracer(); // FIXME: replace with a real one
-
- for (String name : PARAMETER_ANNOTATION_ATTRIBUTES) {
- StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttributes().getWithKey(name);
+ for (StructGeneralAttribute.Key> key : PARAMETER_ANNOTATION_ATTRIBUTES) {
+ StructAnnotationParameterAttribute attribute = (StructAnnotationParameterAttribute)mt.getAttribute(key);
if (attribute != null) {
List> annotations = attribute.getParamAnnotations();
if (param < annotations.size()) {
for (AnnotationExprent annotation : annotations.get(param)) {
- buffer.append(annotation.toJava(0, tracer_dummy)).append(' ');
+ String text = annotation.toJava(-1, BytecodeMappingTracer.DUMMY).toString();
+ filter.add(text);
+ buffer.append(text).append(' ');
+ }
+ }
+ }
+ }
+
+ appendTypeAnnotations(buffer, -1, mt, TypeAnnotation.METHOD_PARAMETER, param, filter);
+ }
+
+ private static void appendTypeAnnotations(TextBuffer buffer, int indent, StructMember mb, int targetType, int index, Set filter) {
+ for (StructGeneralAttribute.Key> key : TYPE_ANNOTATION_ATTRIBUTES) {
+ StructTypeAnnotationAttribute attribute = (StructTypeAnnotationAttribute)mb.getAttribute(key);
+ if (attribute != null) {
+ for (TypeAnnotation annotation : attribute.getAnnotations()) {
+ if (annotation.isTopLevel() && annotation.getTargetType() == targetType && (index < 0 || annotation.getIndex() == index)) {
+ String text = annotation.getAnnotation().toJava(indent, BytecodeMappingTracer.DUMMY).toString();
+ if (!filter.contains(text)) {
+ buffer.append(text);
+ if (indent < 0) {
+ buffer.append(' ');
+ }
+ else {
+ buffer.appendLineSeparator();
+ }
+ }
}
}
}
}
}
- private static final Map MODIFIERS = new LinkedHashMap() {{
- put(CodeConstants.ACC_PUBLIC, "public");
- put(CodeConstants.ACC_PROTECTED, "protected");
- put(CodeConstants.ACC_PRIVATE, "private");
- put(CodeConstants.ACC_ABSTRACT, "abstract");
- put(CodeConstants.ACC_STATIC, "static");
- put(CodeConstants.ACC_FINAL, "final");
- put(CodeConstants.ACC_STRICT, "strictfp");
- put(CodeConstants.ACC_TRANSIENT, "transient");
- put(CodeConstants.ACC_VOLATILE, "volatile");
- put(CodeConstants.ACC_SYNCHRONIZED, "synchronized");
- put(CodeConstants.ACC_NATIVE, "native");
- }};
+ private static final Map MODIFIERS;
+ static {
+ MODIFIERS = new LinkedHashMap<>();
+ MODIFIERS.put(CodeConstants.ACC_PUBLIC, "public");
+ MODIFIERS.put(CodeConstants.ACC_PROTECTED, "protected");
+ MODIFIERS.put(CodeConstants.ACC_PRIVATE, "private");
+ MODIFIERS.put(CodeConstants.ACC_ABSTRACT, "abstract");
+ MODIFIERS.put(CodeConstants.ACC_STATIC, "static");
+ MODIFIERS.put(CodeConstants.ACC_FINAL, "final");
+ MODIFIERS.put(CodeConstants.ACC_STRICT, "strictfp");
+ MODIFIERS.put(CodeConstants.ACC_TRANSIENT, "transient");
+ MODIFIERS.put(CodeConstants.ACC_VOLATILE, "volatile");
+ MODIFIERS.put(CodeConstants.ACC_SYNCHRONIZED, "synchronized");
+ MODIFIERS.put(CodeConstants.ACC_NATIVE, "native");
+ }
private static final int CLASS_ALLOWED =
CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE | CodeConstants.ACC_ABSTRACT |
@@ -1026,12 +1242,15 @@ public class ClassWriter {
CodeConstants.ACC_FINAL | CodeConstants.ACC_TRANSIENT | CodeConstants.ACC_VOLATILE;
private static final int METHOD_ALLOWED =
CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE | CodeConstants.ACC_ABSTRACT |
- CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL | CodeConstants.ACC_SYNCHRONIZED | CodeConstants.ACC_NATIVE | CodeConstants.ACC_STRICT;
+ CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL | CodeConstants.ACC_SYNCHRONIZED | CodeConstants.ACC_NATIVE |
+ CodeConstants.ACC_STRICT;
private static final int CLASS_EXCLUDED = CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_STATIC;
private static final int FIELD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_STATIC | CodeConstants.ACC_FINAL;
private static final int METHOD_EXCLUDED = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_ABSTRACT;
+ private static final int ACCESSIBILITY_FLAGS = CodeConstants.ACC_PUBLIC | CodeConstants.ACC_PROTECTED | CodeConstants.ACC_PRIVATE;
+
private static void appendModifiers(TextBuffer buffer, int flags, int allowed, boolean isInterface, int excluded) {
flags &= allowed;
if (!isInterface) excluded = 0;
@@ -1042,7 +1261,17 @@ public class ClassWriter {
}
}
- private static void appendTypeParameters(TextBuffer buffer, List parameters, List> bounds) {
+ public static GenericClassDescriptor getGenericClassDescriptor(StructClass cl) {
+ if (DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_GENERIC_SIGNATURES)) {
+ StructGenericSignatureAttribute attr = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_SIGNATURE);
+ if (attr != null) {
+ return GenericMain.parseClassSignature(attr.getSignature());
+ }
+ }
+ return null;
+ }
+
+ public static void appendTypeParameters(TextBuffer buffer, List parameters, List extends List> bounds) {
buffer.append('<');
for (int i = 0; i < parameters.size(); i++) {
@@ -1065,4 +1294,14 @@ public class ClassWriter {
buffer.append('>');
}
-}
+
+ private static void appendFQClassNames(TextBuffer buffer, List names) {
+ for (int i = 0; i < names.size(); i++) {
+ String name = names.get(i);
+ buffer.appendIndent(2).append(name);
+ if (i < names.size() - 1) {
+ buffer.append(',').appendLineSeparator();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
index 987c1a5..7bb50aa 100644
--- a/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
+++ b/src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
@@ -1,23 +1,10 @@
-/*
- * 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.
- */
+// Copyright 2000-2021 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.code.CodeConstants;
+import org.jetbrains.java.decompiler.code.Instruction;
+import org.jetbrains.java.decompiler.code.InstructionSequence;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
-import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
@@ -27,109 +14,103 @@ import org.jetbrains.java.decompiler.main.rels.LambdaProcessor;
import org.jetbrains.java.decompiler.main.rels.NestedClassProcessor;
import org.jetbrains.java.decompiler.main.rels.NestedMemberAccess;
import org.jetbrains.java.decompiler.modules.decompiler.exps.InvocationExprent;
-import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPaar;
+import org.jetbrains.java.decompiler.modules.decompiler.vars.VarVersionPair;
import org.jetbrains.java.decompiler.struct.StructClass;
import org.jetbrains.java.decompiler.struct.StructContext;
import org.jetbrains.java.decompiler.struct.StructMethod;
+import org.jetbrains.java.decompiler.struct.attr.StructEnclosingMethodAttribute;
+import org.jetbrains.java.decompiler.struct.attr.StructGeneralAttribute;
import org.jetbrains.java.decompiler.struct.attr.StructInnerClassesAttribute;
+import org.jetbrains.java.decompiler.struct.consts.ConstantPool;
import org.jetbrains.java.decompiler.struct.gen.VarType;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
+import org.jetbrains.java.decompiler.util.TextBuffer;
import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;
-public class ClassesProcessor {
-
+public class ClassesProcessor implements CodeConstants {
public static final int AVERAGE_CLASS_SIZE = 16 * 1024;
- private Map mapRootClasses = new HashMap();
+ private final StructContext context;
+ private final Map mapRootClasses = new HashMap<>();
+
+ private static class Inner {
+ private String simpleName;
+ private int type;
+ private int accessFlags;
+
+ private static boolean equal(Inner o1, Inner o2) {
+ return o1.type == o2.type && o1.accessFlags == o2.accessFlags && InterpreterUtil.equalObjects(o1.simpleName, o2.simpleName);
+ }
+ }
public ClassesProcessor(StructContext context) {
+ this.context = context;
+ }
- HashMap mapInnerClasses = new HashMap();
- HashMap> mapNestedClassReferences = new HashMap>();
- HashMap> mapEnclosingClassReferences = new HashMap>();
- HashMap mapNewSimpleNames = new HashMap();
+ public void loadClasses(IIdentifierRenamer renamer) {
+ Map mapInnerClasses = new HashMap<>();
+ Map> mapNestedClassReferences = new HashMap<>();
+ Map> mapEnclosingClassReferences = new HashMap<>();
+ Map mapNewSimpleNames = new HashMap<>();
boolean bDecompileInner = DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_INNER);
+ boolean verifyAnonymousClasses = DecompilerContext.getOption(IFernflowerPreferences.VERIFY_ANONYMOUS_CLASSES);
// create class nodes
for (StructClass cl : context.getClasses().values()) {
if (cl.isOwn() && !mapRootClasses.containsKey(cl.qualifiedName)) {
-
if (bDecompileInner) {
- StructInnerClassesAttribute inner = (StructInnerClassesAttribute)cl.getAttributes().getWithKey("InnerClasses");
+ StructInnerClassesAttribute inner = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_INNER_CLASSES);
+
if (inner != null) {
-
- for (int i = 0; i < inner.getClassEntries().size(); i++) {
-
- int[] entry = inner.getClassEntries().get(i);
- String[] strentry = inner.getStringEntries().get(i);
-
- Object[] arr = new Object[4]; // arr[0] not used
-
- String innername = strentry[0];
-
- // nested class type
- arr[2] = entry[1] == 0 ? (entry[2] == 0 ? ClassNode.CLASS_ANONYMOUS : ClassNode.CLASS_LOCAL) : ClassNode.CLASS_MEMBER;
+ for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
+ String innerName = entry.innerName;
// original simple name
- String simpleName = strentry[2];
- String savedName = mapNewSimpleNames.get(innername);
-
+ String simpleName = entry.simpleName;
+ String savedName = mapNewSimpleNames.get(innerName);
if (savedName != null) {
simpleName = savedName;
}
- else if (simpleName != null && DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) {
- IIdentifierRenamer renamer = DecompilerContext.getPoolInterceptor().getHelper();
- if (renamer.toBeRenamed(IIdentifierRenamer.ELEMENT_CLASS, simpleName, null, null)) {
- simpleName = renamer.getNextClassname(innername, simpleName);
- mapNewSimpleNames.put(innername, simpleName);
- }
+ else if (simpleName != null &&
+ renamer != null &&
+ renamer.toBeRenamed(IIdentifierRenamer.Type.ELEMENT_CLASS, simpleName, null, null)) {
+ simpleName = renamer.getNextClassName(innerName, simpleName);
+ mapNewSimpleNames.put(innerName, simpleName);
}
- arr[1] = simpleName;
-
- // original access flags
- arr[3] = entry[3];
+ Inner rec = new Inner();
+ rec.simpleName = simpleName;
+ rec.type = entry.simpleNameIdx == 0 ? ClassNode.CLASS_ANONYMOUS : entry.outerNameIdx == 0 ? ClassNode.CLASS_LOCAL : ClassNode.CLASS_MEMBER;
+ rec.accessFlags = entry.accessFlags;
// enclosing class
- String enclClassName;
- if (entry[1] != 0) {
- enclClassName = strentry[1];
+ String enclClassName = entry.outerNameIdx != 0 ? entry.enclosingName : cl.qualifiedName;
+ if (enclClassName == null || innerName.equals(enclClassName)) {
+ continue; // invalid name or self reference
}
- else {
- enclClassName = cl.qualifiedName;
+ if (rec.type == ClassNode.CLASS_MEMBER && !innerName.equals(enclClassName + '$' + entry.simpleName)) {
+ continue; // not a real inner class
}
- if (!innername.equals(enclClassName)) { // self reference
- StructClass enclosing_class = context.getClasses().get(enclClassName);
- if (enclosing_class != null && enclosing_class.isOwn()) { // own classes only
-
- Object[] arrold = mapInnerClasses.get(innername);
- if (arrold == null) {
- mapInnerClasses.put(innername, arr);
- }
- else if (!InterpreterUtil.equalObjectArrays(arrold, arr)) {
- String message = "Inconsistent inner class entries for " + innername + "!";
- DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
- }
-
- // reference to the nested class
- HashSet set = mapNestedClassReferences.get(enclClassName);
- if (set == null) {
- mapNestedClassReferences.put(enclClassName, set = new HashSet());
- }
- set.add(innername);
-
- // reference to the enclosing class
- set = mapEnclosingClassReferences.get(innername);
- if (set == null) {
- mapEnclosingClassReferences.put(innername, set = new HashSet());
- }
- set.add(enclClassName);
+ StructClass enclosingClass = context.getClasses().get(enclClassName);
+ if (enclosingClass != null && enclosingClass.isOwn()) { // own classes only
+ Inner existingRec = mapInnerClasses.get(innerName);
+ if (existingRec == null) {
+ mapInnerClasses.put(innerName, rec);
}
+ else if (!Inner.equal(existingRec, rec)) {
+ String message = "Inconsistent inner class entries for " + innerName + "!";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ }
+
+ // reference to the nested class
+ mapNestedClassReferences.computeIfAbsent(enclClassName, k -> new HashSet<>()).add(innerName);
+ // reference to the enclosing class
+ mapEnclosingClassReferences.computeIfAbsent(innerName, k -> new HashSet<>()).add(enclClassName);
}
}
}
@@ -142,30 +123,32 @@ public class ClassesProcessor {
}
if (bDecompileInner) {
-
// connect nested classes
for (Entry ent : mapRootClasses.entrySet()) {
// root class?
if (!mapInnerClasses.containsKey(ent.getKey())) {
-
- HashSet setVisited = new HashSet();
- LinkedList stack = new LinkedList();
+ Set setVisited = new HashSet<>();
+ LinkedList stack = new LinkedList<>();
stack.add(ent.getKey());
setVisited.add(ent.getKey());
while (!stack.isEmpty()) {
-
String superClass = stack.removeFirst();
- ClassNode supernode = mapRootClasses.get(superClass);
+ ClassNode superNode = mapRootClasses.get(superClass);
- HashSet setNestedClasses = mapNestedClassReferences.get(superClass);
+ Set setNestedClasses = mapNestedClassReferences.get(superClass);
if (setNestedClasses != null) {
+ StructClass scl = superNode.classStruct;
+ StructInnerClassesAttribute inner = scl.getAttribute(StructGeneralAttribute.ATTRIBUTE_INNER_CLASSES);
- StructClass scl = supernode.classStruct;
- StructInnerClassesAttribute inner = (StructInnerClassesAttribute)scl.getAttributes().getWithKey("InnerClasses");
- for (int i = 0; i < inner.getStringEntries().size(); i++) {
- String nestedClass = inner.getStringEntries().get(i)[0];
+ if (inner == null || inner.getEntries().isEmpty()) {
+ DecompilerContext.getLogger().writeMessage(superClass + " does not contain inner classes!", IFernflowerLogger.Severity.WARN);
+ continue;
+ }
+
+ for (StructInnerClassesAttribute.Entry entry : inner.getEntries()) {
+ String nestedClass = entry.innerName;
if (!setNestedClasses.contains(nestedClass)) {
continue;
}
@@ -174,52 +157,49 @@ public class ClassesProcessor {
continue;
}
- ClassNode nestednode = mapRootClasses.get(nestedClass);
- if (nestednode == null) {
+ ClassNode nestedNode = mapRootClasses.get(nestedClass);
+ if (nestedNode == null) {
DecompilerContext.getLogger().writeMessage("Nested class " + nestedClass + " missing!", IFernflowerLogger.Severity.WARN);
continue;
}
- Object[] arr = mapInnerClasses.get(nestedClass);
+ Inner rec = mapInnerClasses.get(nestedClass);
//if ((Integer)arr[2] == ClassNode.CLASS_MEMBER) {
// FIXME: check for consistent naming
//}
- nestednode.type = (Integer)arr[2];
- nestednode.simpleName = (String)arr[1];
- nestednode.access = (Integer)arr[3];
+ nestedNode.simpleName = rec.simpleName;
+ nestedNode.type = rec.type;
+ nestedNode.access = rec.accessFlags;
- if (nestednode.type == ClassNode.CLASS_ANONYMOUS) {
- StructClass cl = nestednode.classStruct;
+ // sanity checks of the class supposed to be anonymous
+ if (verifyAnonymousClasses && nestedNode.type == ClassNode.CLASS_ANONYMOUS && !isAnonymous(nestedNode.classStruct, scl)) {
+ nestedNode.type = ClassNode.CLASS_LOCAL;
+ }
- // remove static if anonymous class
- // a common compiler bug
- nestednode.access &= ~CodeConstants.ACC_STATIC;
+ if (nestedNode.type == ClassNode.CLASS_ANONYMOUS) {
+ StructClass cl = nestedNode.classStruct;
+ // remove static if anonymous class (a common compiler bug)
+ nestedNode.access &= ~CodeConstants.ACC_STATIC;
int[] interfaces = cl.getInterfaces();
-
if (interfaces.length > 0) {
- if (interfaces.length > 1) {
- String message = "Inconsistent anonymous class definition: " + cl.qualifiedName;
- DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
- }
- nestednode.anonymousClassType = new VarType(cl.getInterface(0), true);
+ nestedNode.anonymousClassType = new VarType(cl.getInterface(0), true);
}
else {
- nestednode.anonymousClassType = new VarType(cl.superClass.getString(), true);
+ nestedNode.anonymousClassType = new VarType(cl.superClass.getString(), true);
}
}
- else if (nestednode.type == ClassNode.CLASS_LOCAL) {
- // only abstract and final are permitted
- // a common compiler bug
- nestednode.access &= (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_FINAL);
+ else if (nestedNode.type == ClassNode.CLASS_LOCAL) {
+ // only abstract and final are permitted (a common compiler bug)
+ nestedNode.access &= (CodeConstants.ACC_ABSTRACT | CodeConstants.ACC_FINAL);
}
- supernode.nested.add(nestednode);
- nestednode.parent = supernode;
+ superNode.nested.add(nestedNode);
+ nestedNode.parent = superNode;
- nestednode.enclosingClasses.addAll(mapEnclosingClassReferences.get(nestedClass));
+ nestedNode.enclosingClasses.addAll(mapEnclosingClassReferences.get(nestedClass));
stack.add(nestedClass);
}
@@ -230,64 +210,158 @@ public class ClassesProcessor {
}
}
+ private static boolean isAnonymous(StructClass cl, StructClass enclosingCl) {
+ // checking super class and interfaces
+ int[] interfaces = cl.getInterfaces();
+ if (interfaces.length > 0) {
+ boolean hasNonTrivialSuperClass = cl.superClass != null && !VarType.VARTYPE_OBJECT.equals(new VarType(cl.superClass.getString(), true));
+ if (hasNonTrivialSuperClass || interfaces.length > 1) { // can't have multiple 'sources'
+ String message = "Inconsistent anonymous class definition: '" + cl.qualifiedName + "'. Multiple interfaces and/or super class defined.";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ return false;
+ }
+ }
+ else if (cl.superClass == null) { // neither interface nor super class defined
+ String message = "Inconsistent anonymous class definition: '" + cl.qualifiedName + "'. Neither interface nor super class defined.";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ return false;
+ }
+
+ // FIXME: check constructors
+ // FIXME: check enclosing class/method
+
+ ConstantPool pool = enclosingCl.getPool();
+
+ int refCounter = 0;
+ boolean refNotNew = false;
+
+ StructEnclosingMethodAttribute attribute = cl.getAttribute(StructGeneralAttribute.ATTRIBUTE_ENCLOSING_METHOD);
+ String enclosingMethod = attribute != null ? attribute.getMethodName() : null;
+
+ // checking references in the enclosing class
+ for (StructMethod mt : enclosingCl.getMethods()) {
+ if (enclosingMethod != null && !enclosingMethod.equals(mt.getName())) {
+ continue;
+ }
+
+ try {
+ mt.expandData(enclosingCl);
+
+ InstructionSequence seq = mt.getInstructionSequence();
+ if (seq != null) {
+ int len = seq.length();
+ for (int i = 0; i < len; i++) {
+ Instruction instr = seq.getInstr(i);
+ switch (instr.opcode) {
+ case opc_checkcast:
+ case opc_instanceof:
+ if (cl.qualifiedName.equals(pool.getPrimitiveConstant(instr.operand(0)).getString())) {
+ refCounter++;
+ refNotNew = true;
+ }
+ break;
+ case opc_new:
+ case opc_anewarray:
+ case opc_multianewarray:
+ if (cl.qualifiedName.equals(pool.getPrimitiveConstant(instr.operand(0)).getString())) {
+ refCounter++;
+ }
+ break;
+ case opc_getstatic:
+ case opc_putstatic:
+ if (cl.qualifiedName.equals(pool.getLinkConstant(instr.operand(0)).classname)) {
+ refCounter++;
+ refNotNew = true;
+ }
+ }
+ }
+ }
+
+ mt.releaseResources();
+ }
+ catch (IOException ex) {
+ String message = "Could not read method while checking anonymous class definition: '" + enclosingCl.qualifiedName + "', '" +
+ InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()) + "'";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ return false;
+ }
+
+ if (refCounter > 1 || refNotNew) {
+ String message = "Inconsistent references to the class '" + cl.qualifiedName + "' which is supposed to be anonymous";
+ DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.Severity.WARN);
+ return false;
+ }
+ }
+
+ return true;
+ }
+
public void writeClass(StructClass cl, TextBuffer buffer) throws IOException {
ClassNode root = mapRootClasses.get(cl.qualifiedName);
if (root.type != ClassNode.CLASS_ROOT) {
return;
}
+ boolean packageInfo = cl.isSynthetic() && "package-info".equals(root.simpleName);
+ boolean moduleInfo = cl.hasModifier(CodeConstants.ACC_MODULE) && cl.hasAttribute(StructGeneralAttribute.ATTRIBUTE_MODULE);
+
DecompilerContext.getLogger().startReadingClass(cl.qualifiedName);
try {
ImportCollector importCollector = new ImportCollector(root);
- DecompilerContext.setImportCollector(importCollector);
- DecompilerContext.setCounterContainer(new CounterContainer());
- DecompilerContext.setBytecodeSourceMapper(new BytecodeSourceMapper());
+ DecompilerContext.startClass(importCollector);
- new LambdaProcessor().processClass(root);
+ if (packageInfo) {
+ ClassWriter.packageInfoToJava(cl, buffer);
- // add simple class names to implicit import
- addClassnameToImport(root, importCollector);
-
- // build wrappers for all nested classes (that's where actual processing takes place)
- initWrappers(root);
-
- new NestedClassProcessor().processClass(root, root);
-
- new NestedMemberAccess().propagateMemberAccess(root);
-
- TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
- new ClassWriter().classToJava(root, classBuffer, 0);
-
- String lineSeparator = DecompilerContext.getNewLineSeparator();
- int total_offset_lines = 0;
-
- int index = cl.qualifiedName.lastIndexOf("/");
- if (index >= 0) {
- total_offset_lines+=2;
- String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
-
- buffer.append("package ");
- buffer.append(packageName);
- buffer.append(";");
- buffer.append(lineSeparator);
- buffer.append(lineSeparator);
+ importCollector.writeImports(buffer, false);
}
+ else if (moduleInfo) {
+ TextBuffer moduleBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
+ ClassWriter.moduleInfoToJava(cl, moduleBuffer);
- int import_lines_written = importCollector.writeImports(buffer);
- if (import_lines_written > 0) {
- buffer.append(lineSeparator);
- total_offset_lines += import_lines_written + 1;
+ importCollector.writeImports(buffer, true);
+
+ buffer.append(moduleBuffer);
}
- //buffer.append(lineSeparator);
+ else {
+ new LambdaProcessor().processClass(root);
- buffer.append(classBuffer);
+ // add simple class names to implicit import
+ addClassNameToImport(root, importCollector);
- if(DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
- BytecodeSourceMapper mapper = DecompilerContext.getBytecodeSourceMapper();
- mapper.addTotalOffset(total_offset_lines);
+ // build wrappers for all nested classes (that's where actual processing takes place)
+ initWrappers(root);
- buffer.append(lineSeparator);
- mapper.dumpMapping(buffer);
+ new NestedClassProcessor().processClass(root, root);
+
+ new NestedMemberAccess().propagateMemberAccess(root);
+
+ TextBuffer classBuffer = new TextBuffer(AVERAGE_CLASS_SIZE);
+ new ClassWriter().classToJava(root, classBuffer, 0, null);
+
+ int index = cl.qualifiedName.lastIndexOf('/');
+ if (index >= 0) {
+ String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
+ buffer.append("package ").append(packageName).append(';').appendLineSeparator().appendLineSeparator();
+ }
+
+ importCollector.writeImports(buffer, true);
+
+ int offsetLines = buffer.countLines();
+
+ buffer.append(classBuffer);
+
+ if (DecompilerContext.getOption(IFernflowerPreferences.BYTECODE_SOURCE_MAPPING)) {
+ BytecodeSourceMapper mapper = DecompilerContext.getBytecodeSourceMapper();
+ mapper.addTotalOffset(offsetLines);
+ if (DecompilerContext.getOption(IFernflowerPreferences.DUMP_ORIGINAL_LINES)) {
+ buffer.dumpOriginalLineNumbers(mapper.getOriginalLinesMapping());
+ }
+ if (DecompilerContext.getOption(IFernflowerPreferences.UNIT_TEST_MODE)) {
+ buffer.appendLineSeparator();
+ mapper.dumpMapping(buffer, true);
+ }
+ }
}
}
finally {
@@ -296,8 +370,7 @@ public class ClassesProcessor {
}
}
- private static void initWrappers(ClassNode node) throws IOException {
-
+ private static void initWrappers(ClassNode node) {
if (node.type == ClassNode.CLASS_LAMBDA) {
return;
}
@@ -312,19 +385,17 @@ public class ClassesProcessor {
}
}
- private static void addClassnameToImport(ClassNode node, ImportCollector imp) {
-
+ private static void addClassNameToImport(ClassNode node, ImportCollector imp) {
if (node.simpleName != null && node.simpleName.length() > 0) {
imp.getShortName(node.type == ClassNode.CLASS_ROOT ? node.classStruct.qualifiedName : node.simpleName, false);
}
for (ClassNode nd : node.nested) {
- addClassnameToImport(nd, imp);
+ addClassNameToImport(nd, imp);
}
}
private static void destroyWrappers(ClassNode node) {
-
node.wrapper = null;
node.classStruct.releaseResources();
@@ -339,7 +410,6 @@ public class ClassesProcessor {
public static class ClassNode {
-
public static final int CLASS_ROOT = 0;
public static final int CLASS_MEMBER = 1;
public static final int CLASS_ANONYMOUS = 2;
@@ -347,30 +417,18 @@ public class ClassesProcessor {
public static final int CLASS_LAMBDA = 8;
public int type;
-
public int access;
-
public String simpleName;
-
- public StructClass classStruct;
-
- public ClassWrapper wrapper;
-
+ public final StructClass classStruct;
+ private ClassWrapper wrapper;
public String enclosingMethod;
-
public InvocationExprent superInvocation;
-
- public HashMap mapFieldsToVars = new HashMap();
-
+ public final Map mapFieldsToVars = new HashMap<>();
public VarType anonymousClassType;
-
- public List nested = new ArrayList();
-
- public Set enclosingClasses = new HashSet();
-
+ public final List nested = new ArrayList<>();
+ public final Set enclosingClasses = new HashSet<>();
public ClassNode parent;
-
- public LambdaInformation lambda_information;
+ public LambdaInformation lambdaInformation;
public ClassNode(String content_class_name,
String content_method_name,
@@ -383,19 +441,18 @@ public class ClassesProcessor {
this.type = CLASS_LAMBDA;
this.classStruct = classStruct; // 'parent' class containing the static function
- lambda_information = new LambdaInformation();
+ lambdaInformation = new LambdaInformation();
- lambda_information.class_name = lambda_class_name;
- lambda_information.method_name = lambda_method_name;
- lambda_information.method_descriptor = lambda_method_descriptor;
+ lambdaInformation.method_name = lambda_method_name;
+ lambdaInformation.method_descriptor = lambda_method_descriptor;
- lambda_information.content_class_name = content_class_name;
- lambda_information.content_method_name = content_method_name;
- lambda_information.content_method_descriptor = content_method_descriptor;
- lambda_information.content_method_invocation_type = content_method_invocation_type;
+ lambdaInformation.content_class_name = content_class_name;
+ lambdaInformation.content_method_name = content_method_name;
+ lambdaInformation.content_method_descriptor = content_method_descriptor;
+ lambdaInformation.content_method_invocation_type = content_method_invocation_type;
- lambda_information.content_method_key =
- InterpreterUtil.makeUniqueKey(lambda_information.content_method_name, lambda_information.content_method_descriptor);
+ lambdaInformation.content_method_key =
+ InterpreterUtil.makeUniqueKey(lambdaInformation.content_method_name, lambdaInformation.content_method_descriptor);
anonymousClassType = new VarType(lambda_class_name, true);
@@ -405,9 +462,9 @@ public class ClassesProcessor {
is_method_reference = !mt.isSynthetic(); // if not synthetic -> method reference
}
- lambda_information.is_method_reference = is_method_reference;
- lambda_information.is_content_method_static =
- (lambda_information.content_method_invocation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); // FIXME: redundant?
+ lambdaInformation.is_method_reference = is_method_reference;
+ lambdaInformation.is_content_method_static =
+ (lambdaInformation.content_method_invocation_type == CodeConstants.CONSTANT_MethodHandle_REF_invokeStatic); // FIXME: redundant?
}
public ClassNode(int type, StructClass classStruct) {
@@ -426,8 +483,15 @@ public class ClassesProcessor {
return null;
}
+ public ClassWrapper getWrapper() {
+ ClassNode node = this;
+ while (node.type == CLASS_LAMBDA) {
+ node = node.parent;
+ }
+ return node.wrapper;
+ }
+
public static class LambdaInformation {
- public String class_name;
public String method_name;
public String method_descriptor;
@@ -435,11 +499,10 @@ public class ClassesProcessor {
public String content_method_name;
public String content_method_descriptor;
public int content_method_invocation_type; // values from CONSTANT_MethodHandle_REF_*
-
public String content_method_key;
public boolean is_method_reference;
public boolean is_content_method_static;
}
}
-}
+}
\ No newline at end of file
diff --git a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java
index f1fddac..e293635 100644
--- a/src/org/jetbrains/java/decompiler/main/DecompilerContext.java
+++ b/src/org/jetbrains/java/decompiler/main/DecompilerContext.java
@@ -1,64 +1,57 @@
-/*
- * 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.
- */
+// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
package org.jetbrains.java.decompiler.main;
import org.jetbrains.java.decompiler.main.collectors.BytecodeSourceMapper;
import org.jetbrains.java.decompiler.main.collectors.CounterContainer;
import org.jetbrains.java.decompiler.main.collectors.ImportCollector;
-import org.jetbrains.java.decompiler.main.collectors.VarNamesCollector;
import org.jetbrains.java.decompiler.main.extern.IFernflowerLogger;
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
+import org.jetbrains.java.decompiler.modules.decompiler.vars.VarProcessor;
import org.jetbrains.java.decompiler.modules.renamer.PoolInterceptor;
import org.jetbrains.java.decompiler.struct.StructContext;
-import java.util.HashMap;
-import java.util.Locale;
import java.util.Map;
+import java.util.Objects;
public class DecompilerContext {
public static final String CURRENT_CLASS = "CURRENT_CLASS";
+ public static final String CURRENT_CLASS_WRAPPER = "CURRENT_CLASS_WRAPPER";
public static final String CURRENT_CLASS_NODE = "CURRENT_CLASS_NODE";
- public static final String CURRENT_METHOD = "CURRENT_METHOD";
- public static final String CURRENT_METHOD_DESCRIPTOR = "CURRENT_METHOD_DESCRIPTOR";
public static final String CURRENT_METHOD_WRAPPER = "CURRENT_METHOD_WRAPPER";
- public static final String CURRENT_VAR_PROCESSOR = "CURRENT_VAR_PROCESSOR";
-
- private static ThreadLocal currentContext = new ThreadLocal();
private final Map properties;
- private StructContext structContext;
+ private final IFernflowerLogger logger;
+ private final StructContext structContext;
+ private final ClassesProcessor classProcessor;
+ private final PoolInterceptor poolInterceptor;
private ImportCollector importCollector;
- private VarNamesCollector varNamescollector;
+ private VarProcessor varProcessor;
private CounterContainer counterContainer;
- private ClassesProcessor classProcessor;
- private PoolInterceptor poolInterceptor;
- private IFernflowerLogger logger;
private BytecodeSourceMapper bytecodeSourceMapper;
- private DecompilerContext(Map properties) {
+ public DecompilerContext(Map