Package jadx.core.codegen

Source Code of jadx.core.codegen.NameGen

package jadx.core.codegen;

import jadx.core.Consts;
import jadx.core.deobf.NameMapper;
import jadx.core.dex.attributes.nodes.LoopLabelAttr;
import jadx.core.dex.info.ClassInfo;
import jadx.core.dex.instructions.InvokeNode;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.instructions.args.InsnArg;
import jadx.core.dex.instructions.args.InsnWrapArg;
import jadx.core.dex.instructions.args.NamedArg;
import jadx.core.dex.instructions.args.RegisterArg;
import jadx.core.dex.instructions.args.SSAVar;
import jadx.core.dex.instructions.mods.ConstructorInsn;
import jadx.core.dex.nodes.InsnNode;
import jadx.core.utils.Utils;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

public class NameGen {

  private static final Map<String, String> OBJ_ALIAS;

  private final Set<String> varNames = new HashSet<String>();
  private final boolean fallback;

  static {
    OBJ_ALIAS = new HashMap<String, String>();
    OBJ_ALIAS.put(Consts.CLASS_STRING, "str");
    OBJ_ALIAS.put(Consts.CLASS_CLASS, "cls");
    OBJ_ALIAS.put(Consts.CLASS_THROWABLE, "th");
    OBJ_ALIAS.put(Consts.CLASS_OBJECT, "obj");
    OBJ_ALIAS.put("java.util.Iterator", "it");
    OBJ_ALIAS.put("java.lang.Boolean", "bool");
    OBJ_ALIAS.put("java.lang.Short", "sh");
    OBJ_ALIAS.put("java.lang.Integer", "num");
    OBJ_ALIAS.put("java.lang.Character", "ch");
    OBJ_ALIAS.put("java.lang.Byte", "b");
    OBJ_ALIAS.put("java.lang.Float", "f");
    OBJ_ALIAS.put("java.lang.Long", "l");
    OBJ_ALIAS.put("java.lang.Double", "d");
  }

  public NameGen(boolean fallback) {
    this.fallback = fallback;
  }

  public String assignArg(RegisterArg arg) {
    String name = makeArgName(arg);
    if (fallback) {
      return name;
    }
    name = getUniqueVarName(name);
    arg.setName(name);
    return name;
  }

  public String assignNamedArg(NamedArg arg) {
    String name = arg.getName();
    if (fallback) {
      return name;
    }
    name = getUniqueVarName(name);
    arg.setName(name);
    return name;
  }

  public String useArg(RegisterArg arg) {
    String name = arg.getName();
    if (name == null || fallback) {
      return getFallbackName(arg);
    }
    return name;
  }

  // TODO: avoid name collision with variables names
  public String getLoopLabel(LoopLabelAttr attr) {
    String name = "loop" + attr.getLoop().getId();
    varNames.add(name);
    return name;
  }

  private String getUniqueVarName(String name) {
    String r = name;
    int i = 2;
    while (varNames.contains(r)) {
      r = name + i;
      i++;
    }
    varNames.add(r);
    return r;
  }

  private String makeArgName(RegisterArg arg) {
    if (fallback) {
      return getFallbackName(arg);
    }
    String name = arg.getName();
    String varName;
    if (name != null) {
      if ("this".equals(name)) {
        return name;
      }
      varName = name;
    } else {
      varName = makeNameForType(arg.getType());
    }
    if (NameMapper.isReserved(varName)) {
      return varName + "R";
    }
    return varName;
  }

  private String getFallbackName(RegisterArg arg) {
    String name = arg.getName();
    String base = "r" + arg.getRegNum();
    return name != null ? base + "_" + name : base;
  }

  private static String makeNameForType(ArgType type) {
    if (type.isPrimitive()) {
      return makeNameForPrimitive(type);
    } else if (type.isArray()) {
      return makeNameForType(type.getArrayRootElement()) + "Arr";
    } else {
      return makeNameForObject(type);
    }
  }

  private static String makeNameForPrimitive(ArgType type) {
    return type.getPrimitiveType().getShortName().toLowerCase();
  }

  private static String makeNameForObject(ArgType type) {
    if (type.isObject()) {
      String alias = getAliasForObject(type.getObject());
      if (alias != null) {
        return alias;
      }
      ClassInfo clsInfo = ClassInfo.fromType(type);
      String shortName = clsInfo.getShortName();
      String vName = fromName(shortName);
      if (vName != null) {
        return vName;
      }
    }
    return Utils.escape(type.toString());
  }

  private static String fromName(String name) {
    if (name == null || name.isEmpty()) {
      return null;
    }
    if (name.toUpperCase().equals(name)) {
      // all characters are upper case
      return name.toLowerCase();
    }
    String v1 = Character.toLowerCase(name.charAt(0)) + name.substring(1);
    if (!v1.equals(name)) {
      return v1;
    }
    if (name.length() < 3) {
      return name + "Var";
    }
    return null;
  }

  public static void guessName(RegisterArg arg) {
    SSAVar sVar = arg.getSVar();
    if (sVar == null || sVar.getName() != null) {
      return;
    }
    RegisterArg assignArg = sVar.getAssign();
    InsnNode assignInsn = assignArg.getParentInsn();
    String name = makeNameFromInsn(assignInsn);
    if (name != null && !NameMapper.isReserved(name)) {
      assignArg.setName(name);
    }
  }

  private static String getAliasForObject(String name) {
    return OBJ_ALIAS.get(name);
  }

  private static String makeNameFromInsn(InsnNode insn) {
    switch (insn.getType()) {
      case INVOKE:
        InvokeNode inv = (InvokeNode) insn;
        String name = inv.getCallMth().getName();
        if (name.startsWith("get") || name.startsWith("set")) {
          return fromName(name.substring(3));
        }
        if ("iterator".equals(name)) {
          return "it";
        }
        return name;

      case CONSTRUCTOR:
        ConstructorInsn co = (ConstructorInsn) insn;
        return makeNameForObject(co.getClassType().getType());

      case ARRAY_LENGTH:
        return "length";

      case ARITH:
      case TERNARY:
      case CAST:
        for (InsnArg arg : insn.getArguments()) {
          if (arg.isInsnWrap()) {
            InsnNode wrapInsn = ((InsnWrapArg) arg).getWrapInsn();
            String wName = makeNameFromInsn(wrapInsn);
            if (wName != null) {
              return wName;
            }
          }
        }
        break;

      default:
        break;
    }
    return null;
  }
}
TOP

Related Classes of jadx.core.codegen.NameGen

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.