java-decompiler: cleanups

- better signatures
- accurate suppression
- unused symbols
- typos
master
Roman Shevchenko 10 years ago
parent 646f1c3f21
commit f4f9e8be28
  1. 2
      src/org/jetbrains/java/decompiler/main/AssertProcessor.java
  2. 4
      src/org/jetbrains/java/decompiler/main/ClassReference14Processor.java
  3. 6
      src/org/jetbrains/java/decompiler/main/ClassWriter.java
  4. 20
      src/org/jetbrains/java/decompiler/main/ClassesProcessor.java
  5. 6
      src/org/jetbrains/java/decompiler/main/EnumProcessor.java
  6. 55
      src/org/jetbrains/java/decompiler/main/Fernflower.java
  7. 4
      src/org/jetbrains/java/decompiler/main/decompiler/ConsoleDecompiler.java
  8. 2
      src/org/jetbrains/java/decompiler/main/decompiler/IdeDecompiler.java
  9. 5
      src/org/jetbrains/java/decompiler/main/extern/IFernflowerPreferences.java
  10. 19
      src/org/jetbrains/java/decompiler/main/rels/ClassWrapper.java
  11. 4
      src/org/jetbrains/java/decompiler/main/rels/NestedClassProcessor.java
  12. 2
      src/org/jetbrains/java/decompiler/main/rels/NestedMemberAccess.java
  13. 2
      src/org/jetbrains/java/decompiler/modules/decompiler/exps/AssignmentExprent.java
  14. 23
      src/org/jetbrains/java/decompiler/util/InterpreterUtil.java

@ -60,7 +60,7 @@ public class AssertProcessor {
if (res) { if (res) {
// hide the helper field // hide the helper field
wrapper.getHideMembers().add(key); wrapper.getHiddenMembers().add(key);
} }
} }
} }

@ -114,7 +114,7 @@ public class ClassReference14Processor {
if (!setFound.isEmpty()) { if (!setFound.isEmpty()) {
for (ClassWrapper wrp : setFound) { for (ClassWrapper wrp : setFound) {
StructMethod mt = mapClassMeths.get(wrp).methodStruct; StructMethod mt = mapClassMeths.get(wrp).methodStruct;
wrp.getHideMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor())); wrp.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()));
} }
} }
} }
@ -276,7 +276,7 @@ public class ClassReference14Processor {
invexpr.getStringDescriptor().equals(meth.methodStruct.getDescriptor())) { invexpr.getStringDescriptor().equals(meth.methodStruct.getDescriptor())) {
if (invexpr.getLstParameters().get(0).type == Exprent.EXPRENT_CONST) { if (invexpr.getLstParameters().get(0).type == Exprent.EXPRENT_CONST) {
wrapper.getHideMembers() wrapper.getHiddenMembers()
.add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); // hide synthetic field .add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); // hide synthetic field
return ((ConstExprent)invexpr.getLstParameters().get(0)).getValue().toString(); return ((ConstExprent)invexpr.getLstParameters().get(0)).getValue().toString();
} }

@ -239,7 +239,7 @@ public class ClassWriter {
if ((!isSynthetic || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC)) && if ((!isSynthetic || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC)) &&
(!isBridge || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_BRIDGE)) && (!isBridge || !DecompilerContext.getOption(IFernflowerPreferences.REMOVE_BRIDGE)) &&
!wrapper.getHideMembers().contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()))) { !wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(mt.getName(), mt.getDescriptor()))) {
if (!mthidden && (!firstmt || node.type != ClassNode.CLASS_ANONYMOUS)) { if (!mthidden && (!firstmt || node.type != ClassNode.CLASS_ANONYMOUS)) {
bufstrwriter.write(DecompilerContext.getNewLineSeparator()); bufstrwriter.write(DecompilerContext.getNewLineSeparator());
firstmt = false; firstmt = false;
@ -260,7 +260,7 @@ public class ClassWriter {
// fields // fields
for (StructField fd : cl.getFields()) { for (StructField fd : cl.getFields()) {
boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || boolean hide = fd.isSynthetic() && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) ||
wrapper.getHideMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
if (!hide) { if (!hide) {
boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM); boolean isEnum = fd.hasModifier(CodeConstants.ACC_ENUM) && DecompilerContext.getOption(IFernflowerPreferences.DECOMPILE_ENUM);
if (isEnum) { if (isEnum) {
@ -308,7 +308,7 @@ public class ClassWriter {
StructClass innerCl = inner.classStruct; StructClass innerCl = inner.classStruct;
boolean isSynthetic = (inner.access & CodeConstants.ACC_SYNTHETIC) != 0 || innerCl.isSynthetic(); boolean isSynthetic = (inner.access & CodeConstants.ACC_SYNTHETIC) != 0 || innerCl.isSynthetic();
boolean hide = isSynthetic && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) || boolean hide = isSynthetic && DecompilerContext.getOption(IFernflowerPreferences.REMOVE_SYNTHETIC) ||
wrapper.getHideMembers().contains(innerCl.qualifiedName); wrapper.getHiddenMembers().contains(innerCl.qualifiedName);
if (!hide) { if (!hide) {
writer.write(DecompilerContext.getNewLineSeparator()); writer.write(DecompilerContext.getNewLineSeparator());
classToJava(inner, writer, indent + 1); classToJava(inner, writer, indent + 1);

@ -235,7 +235,7 @@ public class ClassesProcessor {
} }
public void writeClass(StructContext context, StructClass cl, BufferedWriter outwriter) throws IOException { public void writeClass(StructClass cl, BufferedWriter writer) throws IOException {
ClassNode root = mapRootClasses.get(cl.qualifiedName); ClassNode root = mapRootClasses.get(cl.qualifiedName);
if (root.type != ClassNode.CLASS_ROOT) { if (root.type != ClassNode.CLASS_ROOT) {
@ -270,20 +270,20 @@ public class ClassesProcessor {
int index = cl.qualifiedName.lastIndexOf("/"); int index = cl.qualifiedName.lastIndexOf("/");
if (index >= 0) { if (index >= 0) {
String packageName = cl.qualifiedName.substring(0, index).replace('/', '.'); String packageName = cl.qualifiedName.substring(0, index).replace('/', '.');
outwriter.write("package "); writer.write("package ");
outwriter.write(packageName); writer.write(packageName);
outwriter.write(";"); writer.write(";");
outwriter.write(DecompilerContext.getNewLineSeparator()); writer.write(DecompilerContext.getNewLineSeparator());
outwriter.write(DecompilerContext.getNewLineSeparator()); writer.write(DecompilerContext.getNewLineSeparator());
} }
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, root); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS_NODE, root);
DecompilerContext.getImportCollector().writeImports(outwriter); DecompilerContext.getImportCollector().writeImports(writer);
outwriter.write(DecompilerContext.getNewLineSeparator()); writer.write(DecompilerContext.getNewLineSeparator());
outwriter.write(strwriter.toString()); writer.write(strwriter.toString());
outwriter.flush(); writer.flush();
} }
finally { finally {
destroyWrappers(root); destroyWrappers(root);

@ -40,12 +40,12 @@ public class EnumProcessor {
if ("values".equals(name)) { if ("values".equals(name)) {
if (descriptor.equals("()[L" + cl.qualifiedName + ";")) { if (descriptor.equals("()[L" + cl.qualifiedName + ";")) {
wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor)); wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor));
} }
} }
else if ("valueOf".equals(name)) { else if ("valueOf".equals(name)) {
if (descriptor.equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";")) { if (descriptor.equals("(Ljava/lang/String;)L" + cl.qualifiedName + ";")) {
wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor)); wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(name, descriptor));
} }
} }
else if ("<init>".equals(name)) { else if ("<init>".equals(name)) {
@ -66,7 +66,7 @@ public class EnumProcessor {
for (StructField fd : cl.getFields()) { for (StructField fd : cl.getFields()) {
String descriptor = fd.getDescriptor(); String descriptor = fd.getDescriptor();
if (fd.isSynthetic() && descriptor.equals("[L" + cl.qualifiedName + ";")) { if (fd.isSynthetic() && descriptor.equals("[L" + cl.qualifiedName + ";")) {
wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), descriptor)); wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), descriptor));
} }
} }
} }

@ -28,81 +28,66 @@ import org.jetbrains.java.decompiler.struct.lazy.LazyLoader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.StringWriter; import java.io.StringWriter;
import java.util.HashMap; import java.util.Map;
public class Fernflower implements IDecompiledData { public class Fernflower implements IDecompiledData {
public static final String version = "v0.8.4"; private StructContext structContext;
private ClassesProcessor classesProcessor;
private StructContext structcontext;
private ClassesProcessor clprocessor;
public Fernflower(IBytecodeProvider provider, IDecompilatSaver saver, HashMap<String, Object> propertiesCustom) {
structcontext = new StructContext(saver, this, new LazyLoader(provider));
public Fernflower(IBytecodeProvider provider, IDecompilatSaver saver, Map<String, Object> propertiesCustom) {
structContext = new StructContext(saver, this, new LazyLoader(provider));
DecompilerContext.initContext(propertiesCustom); DecompilerContext.initContext(propertiesCustom);
DecompilerContext.setCounterContainer(new CounterContainer()); DecompilerContext.setCounterContainer(new CounterContainer());
} }
public void decompileContext() { public void decompileContext() {
if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) {
new IdentifierConverter().rename(structcontext); new IdentifierConverter().rename(structContext);
} }
clprocessor = new ClassesProcessor(structcontext); classesProcessor = new ClassesProcessor(structContext);
DecompilerContext.setClassProcessor(clprocessor); DecompilerContext.setClassProcessor(classesProcessor);
DecompilerContext.setStructContext(structcontext); DecompilerContext.setStructContext(structContext);
structcontext.saveContext(); structContext.saveContext();
} }
public void clearContext() { public void clearContext() {
DecompilerContext.setCurrentContext(null); DecompilerContext.setCurrentContext(null);
} }
public String getClassEntryName(StructClass cl, String entryname) { public String getClassEntryName(StructClass cl, String entryName) {
ClassNode node = classesProcessor.getMapRootClasses().get(cl.qualifiedName);
ClassNode node = clprocessor.getMapRootClasses().get(cl.qualifiedName);
if (node.type != ClassNode.CLASS_ROOT) { if (node.type != ClassNode.CLASS_ROOT) {
return null; return null;
} }
else { else {
if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) { if (DecompilerContext.getOption(IFernflowerPreferences.RENAME_ENTITIES)) {
String simple_classname = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1); String simple_classname = cl.qualifiedName.substring(cl.qualifiedName.lastIndexOf('/') + 1);
return entryname.substring(0, entryname.lastIndexOf('/') + 1) + simple_classname + ".java"; return entryName.substring(0, entryName.lastIndexOf('/') + 1) + simple_classname + ".java";
} }
else { else {
return entryname.substring(0, entryname.lastIndexOf(".class")) + ".java"; return entryName.substring(0, entryName.lastIndexOf(".class")) + ".java";
} }
} }
} }
public StructContext getStructcontext() { public StructContext getStructContext() {
return structcontext; return structContext;
} }
public String getClassContent(StructClass cl) { public String getClassContent(StructClass cl) {
String res = null;
try { try {
StringWriter strwriter = new StringWriter(); StringWriter writer = new StringWriter();
clprocessor.writeClass(structcontext, cl, new BufferedWriter(strwriter)); classesProcessor.writeClass(cl, new BufferedWriter(writer));
return writer.toString();
res = strwriter.toString();
}
catch (ThreadDeath ex) {
throw ex;
} }
catch (Throwable ex) { catch (Throwable ex) {
DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex); DecompilerContext.getLogger().writeMessage("Class " + cl.qualifiedName + " couldn't be fully decompiled.", ex);
return null;
} }
return res;
} }
} }

@ -128,7 +128,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver {
} }
public void addSpace(File file, boolean isOwn) throws IOException { public void addSpace(File file, boolean isOwn) throws IOException {
fernflower.getStructcontext().addSpace(file, isOwn); fernflower.getStructContext().addSpace(file, isOwn);
} }
public void decompileContext(File root) { public void decompileContext(File root) {
@ -213,7 +213,7 @@ public class ConsoleDecompiler implements IBytecodeProvider, IDecompilatSaver {
ZipOutputStream out = mapArchiveStreams.get(filename); ZipOutputStream out = mapArchiveStreams.get(filename);
out.putNextEntry(new ZipEntry(entryName)); out.putNextEntry(new ZipEntry(entryName));
InterpreterUtil.copyInputStream(in, out); InterpreterUtil.copyStream(in, out);
in.close(); in.close();
} }
} }

@ -40,7 +40,7 @@ public class IdeDecompiler {
} }
public void addSpace(File file, boolean isOwn) throws IOException { public void addSpace(File file, boolean isOwn) throws IOException {
fernflower.getStructcontext().addSpace(file, isOwn); fernflower.getStructContext().addSpace(file, isOwn);
} }
public void decompileContext() { public void decompileContext() {

@ -15,6 +15,8 @@
*/ */
package org.jetbrains.java.decompiler.main.extern; package org.jetbrains.java.decompiler.main.extern;
import org.jetbrains.java.decompiler.util.InterpreterUtil;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@ -75,10 +77,9 @@ public interface IFernflowerPreferences {
put(IDEA_NOT_NULL_ANNOTATION, "1"); put(IDEA_NOT_NULL_ANNOTATION, "1");
put(LAMBDA_TO_ANONYMOUS_CLASS, "0"); put(LAMBDA_TO_ANONYMOUS_CLASS, "0");
boolean win = System.getProperty("os.name", "").startsWith("Windows");
put(MAX_PROCESSING_METHOD, "0"); put(MAX_PROCESSING_METHOD, "0");
put(RENAME_ENTITIES, "0"); put(RENAME_ENTITIES, "0");
put(NEW_LINE_SEPARATOR, (win ? "0" : "1")); put(NEW_LINE_SEPARATOR, (InterpreterUtil.IS_WINDOWS ? "0" : "1"));
put(INDENT_STRING, " "); put(INDENT_STRING, " ");
}}); }});
} }

@ -36,17 +36,14 @@ import org.jetbrains.java.decompiler.util.VBStyleCollection;
import java.io.IOException; import java.io.IOException;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set;
public class ClassWrapper { public class ClassWrapper {
private StructClass classStruct; private StructClass classStruct;
private Set<String> hiddenMembers = new HashSet<String>();
private HashSet<String> hideMembers = new HashSet<String>();
private VBStyleCollection<Exprent, String> staticFieldInitializers = new VBStyleCollection<Exprent, String>(); private VBStyleCollection<Exprent, String> staticFieldInitializers = new VBStyleCollection<Exprent, String>();
private VBStyleCollection<Exprent, String> dynamicFieldInitializers = new VBStyleCollection<Exprent, String>(); private VBStyleCollection<Exprent, String> dynamicFieldInitializers = new VBStyleCollection<Exprent, String>();
private VBStyleCollection<MethodWrapper, String> methods = new VBStyleCollection<MethodWrapper, String>(); private VBStyleCollection<MethodWrapper, String> methods = new VBStyleCollection<MethodWrapper, String>();
@ -54,7 +51,6 @@ public class ClassWrapper {
this.classStruct = classStruct; this.classStruct = classStruct;
} }
@SuppressWarnings("deprecation")
public void init() throws IOException { public void init() throws IOException {
DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS, classStruct); DecompilerContext.setProperty(DecompilerContext.CURRENT_CLASS, classStruct);
@ -111,7 +107,7 @@ public class ClassWrapper {
if (System.currentTimeMillis() >= stopAt) { if (System.currentTimeMillis() >= stopAt) {
String message = "Processing time limit exceeded for method " + mt.getName() + ", execution interrupted."; String message = "Processing time limit exceeded for method " + mt.getName() + ", execution interrupted.";
DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.ERROR); DecompilerContext.getLogger().writeMessage(message, IFernflowerLogger.ERROR);
mtthread.stop(); killThread(mtthread);
isError = true; isError = true;
break; break;
} }
@ -180,6 +176,11 @@ public class ClassWrapper {
DecompilerContext.getLogger().endClass(); DecompilerContext.getLogger().endClass();
} }
@SuppressWarnings("deprecation")
private static void killThread(Thread thread) {
thread.stop();
}
public MethodWrapper getMethodWrapper(String name, String descriptor) { public MethodWrapper getMethodWrapper(String name, String descriptor) {
return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor)); return methods.getWithKey(InterpreterUtil.makeUniqueKey(name, descriptor));
} }
@ -192,8 +193,8 @@ public class ClassWrapper {
return methods; return methods;
} }
public HashSet<String> getHideMembers() { public Set<String> getHiddenMembers() {
return hideMembers; return hiddenMembers;
} }
public VBStyleCollection<Exprent, String> getStaticFieldInitializers() { public VBStyleCollection<Exprent, String> getStaticFieldInitializers() {

@ -50,7 +50,7 @@ public class NestedClassProcessor {
if (node.type == ClassNode.CLASS_LAMBDA && !node.lambda_information.is_method_reference) { if (node.type == ClassNode.CLASS_LAMBDA && !node.lambda_information.is_method_reference) {
ClassNode node_content = DecompilerContext.getClassProcessor().getMapRootClasses().get(node.classStruct.qualifiedName); ClassNode node_content = DecompilerContext.getClassProcessor().getMapRootClasses().get(node.classStruct.qualifiedName);
if (node_content != null && node_content.wrapper != null) { if (node_content != null && node_content.wrapper != null) {
node_content.wrapper.getHideMembers().add(node.lambda_information.content_method_key); node_content.wrapper.getHiddenMembers().add(node.lambda_information.content_method_key);
} }
} }
@ -528,7 +528,7 @@ public class NestedClassProcessor {
// hide synthetic field // hide synthetic field
if (clnode == child) { // fields higher up the chain were already handled with their classes if (clnode == child) { // fields higher up the chain were already handled with their classes
StructField fd = child.classStruct.getFields().getWithKey(entr.getKey()); StructField fd = child.classStruct.getFields().getWithKey(entr.getKey());
child.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor())); child.wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()));
} }
} }
} }

@ -440,7 +440,7 @@ public class NestedMemberAccess {
} }
} }
if (hide) { if (hide) {
node.wrapper.getHideMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor())); node.wrapper.getHiddenMembers().add(InterpreterUtil.makeUniqueKey(invexpr.getName(), invexpr.getStringDescriptor()));
} }
} }

@ -117,7 +117,7 @@ public class AssignmentExprent extends Exprent {
if (field.isStatic() && fd.hasModifier(CodeConstants.ACC_FINAL)) { if (field.isStatic() && fd.hasModifier(CodeConstants.ACC_FINAL)) {
fieldInClassInit = true; fieldInClassInit = true;
} }
if (node.wrapper.getHideMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()))) { if (node.wrapper.getHiddenMembers().contains(InterpreterUtil.makeUniqueKey(fd.getName(), fd.getDescriptor()))) {
hiddenField = true; hiddenField = true;
} }
} }

@ -25,6 +25,10 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
public class InterpreterUtil { public class InterpreterUtil {
public static final boolean IS_WINDOWS = System.getProperty("os.name", "").startsWith("Windows");
private static final int CHANNEL_WINDOW_SIZE = IS_WINDOWS ? 64 * 1024 * 1024 - (32 * 1024) : 64 * 1024 * 1024; // magic number for Windows
private static final int BUFFER_SIZE = 16* 1024;
public static void copyFile(File in, File out) throws IOException { public static void copyFile(File in, File out) throws IOException {
FileInputStream inStream = new FileInputStream(in); FileInputStream inStream = new FileInputStream(in);
@ -33,12 +37,9 @@ public class InterpreterUtil {
try { try {
FileChannel inChannel = inStream.getChannel(); FileChannel inChannel = inStream.getChannel();
FileChannel outChannel = outStream.getChannel(); FileChannel outChannel = outStream.getChannel();
// magic number for Windows, 64Mb - 32Kb) long size = inChannel.size(), position = 0;
int maxCount = (64 * 1024 * 1024) - (32 * 1024);
long size = inChannel.size();
long position = 0;
while (position < size) { while (position < size) {
position += inChannel.transferTo(position, maxCount, outChannel); position += inChannel.transferTo(position, CHANNEL_WINDOW_SIZE, outChannel);
} }
} }
finally { finally {
@ -50,11 +51,9 @@ public class InterpreterUtil {
} }
} }
public static void copyInputStream(InputStream in, OutputStream out) throws IOException { public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[BUFFER_SIZE];
byte[] buffer = new byte[1024];
int len; int len;
while ((len = in.read(buffer)) >= 0) { while ((len = in.read(buffer)) >= 0) {
out.write(buffer, 0, len); out.write(buffer, 0, len);
} }
@ -69,9 +68,7 @@ public class InterpreterUtil {
return buf.toString(); return buf.toString();
} }
public static boolean equalSets(Collection<?> c1, Collection<?> c2) { public static boolean equalSets(Collection<?> c1, Collection<?> c2) {
if (c1 == null) { if (c1 == null) {
return c2 == null; return c2 == null;
} }
@ -93,7 +90,6 @@ public class InterpreterUtil {
} }
public static boolean equalObjectArrays(Object[] first, Object[] second) { public static boolean equalObjectArrays(Object[] first, Object[] second) {
if (first == null || second == null) { if (first == null || second == null) {
return equalObjects(first, second); return equalObjects(first, second);
} }
@ -113,12 +109,11 @@ public class InterpreterUtil {
} }
public static boolean equalLists(List<?> first, List<?> second) { public static boolean equalLists(List<?> first, List<?> second) {
if (first == null) { if (first == null) {
return second == null; return second == null;
} }
else if (second == null) { else if (second == null) {
return first == null; return false;
} }
if (first.size() == second.size()) { if (first.size() == second.size()) {

Loading…
Cancel
Save