|
|
|
/*
|
|
|
|
* 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.util;
|
|
|
|
|
|
|
|
import org.jetbrains.java.decompiler.code.CodeConstants;
|
|
|
|
import org.jetbrains.java.decompiler.main.ClassesProcessor;
|
|
|
|
import org.jetbrains.java.decompiler.main.DecompilerContext;
|
|
|
|
import org.jetbrains.java.decompiler.main.extern.IFernflowerPreferences;
|
|
|
|
import org.jetbrains.java.decompiler.modules.decompiler.ExprProcessor;
|
|
|
|
|
|
|
|
import java.util.Arrays;
|
|
|
|
import java.util.HashSet;
|
|
|
|
|
|
|
|
public class TextUtil {
|
|
|
|
private static final HashSet<String> KEYWORDS = new HashSet<>(Arrays.asList(
|
|
|
|
"abstract", "default", "if", "private", "this", "boolean", "do", "implements", "protected", "throw", "break", "double", "import",
|
|
|
|
"public", "throws", "byte", "else", "instanceof", "return", "transient", "case", "extends", "int", "short", "try", "catch", "final",
|
|
|
|
"interface", "static", "void", "char", "finally", "long", "strictfp", "volatile", "class", "float", "native", "super", "while",
|
|
|
|
"const", "for", "new", "switch", "continue", "goto", "package", "synchronized", "true", "false", "null", "assert"));
|
|
|
|
|
|
|
|
public static void writeQualifiedSuper(TextBuffer buf, String qualifier) {
|
|
|
|
ClassesProcessor.ClassNode classNode = (ClassesProcessor.ClassNode)DecompilerContext.getProperty(DecompilerContext.CURRENT_CLASS_NODE);
|
|
|
|
if (!qualifier.equals(classNode.classStruct.qualifiedName)) {
|
|
|
|
buf.append(DecompilerContext.getImportCollector().getShortName(ExprProcessor.buildJavaClassName(qualifier))).append('.');
|
|
|
|
}
|
|
|
|
buf.append("super");
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getIndentString(int length) {
|
|
|
|
if (length == 0) return "";
|
|
|
|
StringBuilder buf = new StringBuilder();
|
|
|
|
String indent = (String)DecompilerContext.getProperty(IFernflowerPreferences.INDENT_STRING);
|
|
|
|
append(buf, indent, length);
|
|
|
|
return buf.toString();
|
|
|
|
}
|
|
|
|
|
|
|
|
public static void append(StringBuilder buf, String string, int times) {
|
|
|
|
while (times-- > 0) buf.append(string);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isPrintableUnicode(char c) {
|
|
|
|
int t = Character.getType(c);
|
|
|
|
return t != Character.UNASSIGNED && t != Character.LINE_SEPARATOR && t != Character.PARAGRAPH_SEPARATOR &&
|
|
|
|
t != Character.CONTROL && t != Character.FORMAT && t != Character.PRIVATE_USE && t != Character.SURROGATE;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String charToUnicodeLiteral(int value) {
|
|
|
|
String sTemp = Integer.toHexString(value);
|
|
|
|
sTemp = ("0000" + sTemp).substring(sTemp.length());
|
|
|
|
return "\\u" + sTemp;
|
|
|
|
}
|
|
|
|
|
|
|
|
public static boolean isValidIdentifier(String id, int version) {
|
|
|
|
return isJavaIdentifier(id) && !isKeyword(id, version);
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isJavaIdentifier(String id) {
|
|
|
|
if (id.isEmpty() || !Character.isJavaIdentifierStart(id.charAt(0))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i = 1; i < id.length(); i++) {
|
|
|
|
if (!Character.isJavaIdentifierPart(id.charAt(i))) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
private static boolean isKeyword(String id, int version) {
|
|
|
|
return KEYWORDS.contains(id) || version >= CodeConstants.BYTECODE_JAVA_5 && "enum".equals(id);
|
|
|
|
}
|
|
|
|
|
|
|
|
public static String getInstructionName(int opcode) {
|
|
|
|
return opcodeNames[opcode];
|
|
|
|
}
|
|
|
|
|
|
|
|
private static final String[] opcodeNames = {
|
|
|
|
"nop",
|
|
|
|
"aconst_null",
|
|
|
|
"iconst_m1",
|
|
|
|
"iconst_0",
|
|
|
|
"iconst_1",
|
|
|
|
"iconst_2",
|
|
|
|
"iconst_3",
|
|
|
|
"iconst_4",
|
|
|
|
"iconst_5",
|
|
|
|
"lconst_0",
|
|
|
|
"lconst_1",
|
|
|
|
"fconst_0",
|
|
|
|
"fconst_1",
|
|
|
|
"fconst_2",
|
|
|
|
"dconst_0",
|
|
|
|
"dconst_1",
|
|
|
|
"bipush",
|
|
|
|
"sipush",
|
|
|
|
"ldc",
|
|
|
|
"ldc_w",
|
|
|
|
"ldc2_w",
|
|
|
|
"iload",
|
|
|
|
"lload",
|
|
|
|
"fload",
|
|
|
|
"dload",
|
|
|
|
"aload",
|
|
|
|
"iload_0",
|
|
|
|
"iload_1",
|
|
|
|
"iload_2",
|
|
|
|
"iload_3",
|
|
|
|
"lload_0",
|
|
|
|
"lload_1",
|
|
|
|
"lload_2",
|
|
|
|
"lload_3",
|
|
|
|
"fload_0",
|
|
|
|
"fload_1",
|
|
|
|
"fload_2",
|
|
|
|
"fload_3",
|
|
|
|
"dload_0",
|
|
|
|
"dload_1",
|
|
|
|
"dload_2",
|
|
|
|
"dload_3",
|
|
|
|
"aload_0",
|
|
|
|
"aload_1",
|
|
|
|
"aload_2",
|
|
|
|
"aload_3",
|
|
|
|
"iaload",
|
|
|
|
"laload",
|
|
|
|
"faload",
|
|
|
|
"daload",
|
|
|
|
"aaload",
|
|
|
|
"baload",
|
|
|
|
"caload",
|
|
|
|
"saload",
|
|
|
|
"istore",
|
|
|
|
"lstore",
|
|
|
|
"fstore",
|
|
|
|
"dstore",
|
|
|
|
"astore",
|
|
|
|
"istore_0",
|
|
|
|
"istore_1",
|
|
|
|
"istore_2",
|
|
|
|
"istore_3",
|
|
|
|
"lstore_0",
|
|
|
|
"lstore_1",
|
|
|
|
"lstore_2",
|
|
|
|
"lstore_3",
|
|
|
|
"fstore_0",
|
|
|
|
"fstore_1",
|
|
|
|
"fstore_2",
|
|
|
|
"fstore_3",
|
|
|
|
"dstore_0",
|
|
|
|
"dstore_1",
|
|
|
|
"dstore_2",
|
|
|
|
"dstore_3",
|
|
|
|
"astore_0",
|
|
|
|
"astore_1",
|
|
|
|
"astore_2",
|
|
|
|
"astore_3",
|
|
|
|
"iastore",
|
|
|
|
"lastore",
|
|
|
|
"fastore",
|
|
|
|
"dastore",
|
|
|
|
"aastore",
|
|
|
|
"bastore",
|
|
|
|
"castore",
|
|
|
|
"sastore",
|
|
|
|
"pop",
|
|
|
|
"pop2",
|
|
|
|
"dup",
|
|
|
|
"dup_x1",
|
|
|
|
"dup_x2",
|
|
|
|
"dup2",
|
|
|
|
"dup2_x1",
|
|
|
|
"dup2_x2",
|
|
|
|
"swap",
|
|
|
|
"iadd",
|
|
|
|
"ladd",
|
|
|
|
"fadd",
|
|
|
|
"dadd",
|
|
|
|
"isub",
|
|
|
|
"lsub",
|
|
|
|
"fsub",
|
|
|
|
"dsub",
|
|
|
|
"imul",
|
|
|
|
"lmul",
|
|
|
|
"fmul",
|
|
|
|
"dmul",
|
|
|
|
"idiv",
|
|
|
|
"ldiv",
|
|
|
|
"fdiv",
|
|
|
|
"ddiv",
|
|
|
|
"irem",
|
|
|
|
"lrem",
|
|
|
|
"frem",
|
|
|
|
"drem",
|
|
|
|
"ineg",
|
|
|
|
"lneg",
|
|
|
|
"fneg",
|
|
|
|
"dneg",
|
|
|
|
"ishl",
|
|
|
|
"lshl",
|
|
|
|
"ishr",
|
|
|
|
"lshr",
|
|
|
|
"iushr",
|
|
|
|
"lushr",
|
|
|
|
"iand",
|
|
|
|
"land",
|
|
|
|
"ior",
|
|
|
|
"lor",
|
|
|
|
"ixor",
|
|
|
|
"lxor",
|
|
|
|
"iinc",
|
|
|
|
"i2l",
|
|
|
|
"i2f",
|
|
|
|
"i2d",
|
|
|
|
"l2i",
|
|
|
|
"l2f",
|
|
|
|
"l2d",
|
|
|
|
"f2i",
|
|
|
|
"f2l",
|
|
|
|
"f2d",
|
|
|
|
"d2i",
|
|
|
|
"d2l",
|
|
|
|
"d2f",
|
|
|
|
"i2b",
|
|
|
|
"i2c",
|
|
|
|
"i2s",
|
|
|
|
"lcmp",
|
|
|
|
"fcmpl",
|
|
|
|
"fcmpg",
|
|
|
|
"dcmpl",
|
|
|
|
"dcmpg",
|
|
|
|
"ifeq",
|
|
|
|
"ifne",
|
|
|
|
"iflt",
|
|
|
|
"ifge",
|
|
|
|
"ifgt",
|
|
|
|
"ifle",
|
|
|
|
"if_icmpeq",
|
|
|
|
"if_icmpne",
|
|
|
|
"if_icmplt",
|
|
|
|
"if_icmpge",
|
|
|
|
"if_icmpgt",
|
|
|
|
"if_icmple",
|
|
|
|
"if_acmpeq",
|
|
|
|
"if_acmpne",
|
|
|
|
"goto",
|
|
|
|
"jsr",
|
|
|
|
"ret",
|
|
|
|
"tableswitch",
|
|
|
|
"lookupswitch",
|
|
|
|
"ireturn",
|
|
|
|
"lreturn",
|
|
|
|
"freturn",
|
|
|
|
"dreturn",
|
|
|
|
"areturn",
|
|
|
|
"return",
|
|
|
|
"getstatic",
|
|
|
|
"putstatic",
|
|
|
|
"getfield",
|
|
|
|
"putfield",
|
|
|
|
"invokevirtual",
|
|
|
|
"invokespecial",
|
|
|
|
"invokestatic",
|
|
|
|
"invokeinterface",
|
|
|
|
"invokedynamic", // since Java 7
|
|
|
|
"new",
|
|
|
|
"newarray",
|
|
|
|
"anewarray",
|
|
|
|
"arraylength",
|
|
|
|
"athrow",
|
|
|
|
"checkcast",
|
|
|
|
"instanceof",
|
|
|
|
"monitorenter",
|
|
|
|
"monitorexit",
|
|
|
|
"wide",
|
|
|
|
"multianewarray",
|
|
|
|
"ifnull",
|
|
|
|
"ifnonnull",
|
|
|
|
"goto_w",
|
|
|
|
"jsr_w"
|
|
|
|
};
|
|
|
|
}
|