Package jadx.core.codegen

Source Code of jadx.core.codegen.AnnotationGen

package jadx.core.codegen;

import jadx.core.Consts;
import jadx.core.dex.attributes.AType;
import jadx.core.dex.attributes.IAttributeNode;
import jadx.core.dex.attributes.annotations.Annotation;
import jadx.core.dex.attributes.annotations.AnnotationsList;
import jadx.core.dex.attributes.annotations.MethodParameters;
import jadx.core.dex.info.FieldInfo;
import jadx.core.dex.instructions.args.ArgType;
import jadx.core.dex.nodes.ClassNode;
import jadx.core.dex.nodes.FieldNode;
import jadx.core.dex.nodes.MethodNode;
import jadx.core.utils.StringUtils;
import jadx.core.utils.exceptions.JadxRuntimeException;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

public class AnnotationGen {

  private final ClassNode cls;
  private final ClassGen classGen;

  public AnnotationGen(ClassNode cls, ClassGen classGen) {
    this.cls = cls;
    this.classGen = classGen;
  }

  public void addForClass(CodeWriter code) {
    add(cls, code);
  }

  public void addForMethod(CodeWriter code, MethodNode mth) {
    add(mth, code);
  }

  public void addForField(CodeWriter code, FieldNode field) {
    add(field, code);
  }

  public void addForParameter(CodeWriter code, MethodParameters paramsAnnotations, int n) {
    AnnotationsList aList = paramsAnnotations.getParamList().get(n);
    if (aList == null || aList.isEmpty()) {
      return;
    }
    for (Annotation a : aList.getAll()) {
      formatAnnotation(code, a);
      code.add(' ');
    }
  }

  private void add(IAttributeNode node, CodeWriter code) {
    AnnotationsList aList = node.get(AType.ANNOTATION_LIST);
    if (aList == null || aList.isEmpty()) {
      return;
    }
    for (Annotation a : aList.getAll()) {
      String aCls = a.getAnnotationClass();
      if (aCls.startsWith(Consts.DALVIK_ANNOTATION_PKG)) {
        // skip
        if (Consts.DEBUG) {
          code.startLine("// " + a);
        }
      } else {
        code.startLine();
        formatAnnotation(code, a);
      }
    }
  }

  private void formatAnnotation(CodeWriter code, Annotation a) {
    code.add('@');
    classGen.useType(code, a.getType());
    Map<String, Object> vl = a.getValues();
    if (!vl.isEmpty()) {
      code.add('(');
      if (vl.size() == 1 && vl.containsKey("value")) {
        encodeValue(code, vl.get("value"));
      } else {
        for (Iterator<Entry<String, Object>> it = vl.entrySet().iterator(); it.hasNext(); ) {
          Entry<String, Object> e = it.next();
          code.add(e.getKey());
          code.add(" = ");
          encodeValue(code, e.getValue());
          if (it.hasNext()) {
            code.add(", ");
          }
        }
      }
      code.add(')');
    }
  }

  @SuppressWarnings("unchecked")
  public void addThrows(MethodNode mth, CodeWriter code) {
    Annotation an = mth.getAnnotation(Consts.DALVIK_THROWS);
    if (an != null) {
      Object exs = an.getDefaultValue();
      code.add(" throws ");
      for (Iterator<ArgType> it = ((List<ArgType>) exs).iterator(); it.hasNext(); ) {
        ArgType ex = it.next();
        classGen.useType(code, ex);
        if (it.hasNext()) {
          code.add(", ");
        }
      }
    }
  }

  public Object getAnnotationDefaultValue(String name) {
    Annotation an = cls.getAnnotation(Consts.DALVIK_ANNOTATION_DEFAULT);
    if (an != null) {
      Annotation defAnnotation = (Annotation) an.getDefaultValue();
      return defAnnotation.getValues().get(name);
    }
    return null;
  }

  // TODO: refactor this boilerplate code
  public void encodeValue(CodeWriter code, Object val) {
    if (val == null) {
      code.add("null");
      return;
    }
    if (val instanceof String) {
      code.add(StringUtils.unescapeString((String) val));
    } else if (val instanceof Integer) {
      code.add(TypeGen.formatInteger((Integer) val));
    } else if (val instanceof Character) {
      code.add(StringUtils.unescapeChar((Character) val));
    } else if (val instanceof Boolean) {
      code.add(Boolean.TRUE.equals(val) ? "true" : "false");
    } else if (val instanceof Float) {
      code.add(TypeGen.formatFloat((Float) val));
    } else if (val instanceof Double) {
      code.add(TypeGen.formatDouble((Double) val));
    } else if (val instanceof Long) {
      code.add(TypeGen.formatLong((Long) val));
    } else if (val instanceof Short) {
      code.add(TypeGen.formatShort((Short) val));
    } else if (val instanceof Byte) {
      code.add(TypeGen.formatByte((Byte) val));
    } else if (val instanceof ArgType) {
      classGen.useType(code, (ArgType) val);
      code.add(".class");
    } else if (val instanceof FieldInfo) {
      // must be a static field
      FieldInfo field = (FieldInfo) val;
      InsnGen.makeStaticFieldAccess(code, field, classGen);
    } else if (val instanceof Iterable) {
      code.add('{');
      Iterator<?> it = ((Iterable) val).iterator();
      while (it.hasNext()) {
        Object obj = it.next();
        encodeValue(code, obj);
        if (it.hasNext()) {
          code.add(", ");
        }
      }
      code.add('}');
    } else if (val instanceof Annotation) {
      formatAnnotation(code, (Annotation) val);
    } else {
      // TODO: also can be method values
      throw new JadxRuntimeException("Can't decode value: " + val + " (" + val.getClass() + ")");
    }
  }
}
TOP

Related Classes of jadx.core.codegen.AnnotationGen

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.