• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 package org.robolectric.internal.bytecode;
2 
3 import static org.objectweb.asm.Type.ARRAY;
4 import static org.objectweb.asm.Type.OBJECT;
5 
6 import java.util.HashMap;
7 import java.util.Map;
8 import org.objectweb.asm.Type;
9 
10 class TypeMapper {
11   private final Map<String, String> classesToRemap;
12 
TypeMapper(Map<String, String> classNameToClassNameMap)13   public TypeMapper(Map<String, String> classNameToClassNameMap) {
14     classesToRemap = convertToSlashes(classNameToClassNameMap);
15   }
16 
convertToSlashes(Map<String, String> map)17   private static Map<String, String> convertToSlashes(Map<String, String> map) {
18     HashMap<String, String> newMap = new HashMap<>();
19     for (Map.Entry<String, String> entry : map.entrySet()) {
20       String key = internalize(entry.getKey());
21       String value = internalize(entry.getValue());
22       newMap.put(key, value);
23       newMap.put("L" + key + ";", "L" + value + ";"); // also the param reference form
24     }
25     return newMap;
26   }
27 
internalize(String className)28   private static String internalize(String className) {
29     return className.replace('.', '/');
30   }
31 
32   // remap android/Foo to android/Bar
mappedTypeName(String internalName)33   String mappedTypeName(String internalName) {
34     String remappedInternalName = classesToRemap.get(internalName);
35     if (remappedInternalName != null) {
36       return remappedInternalName;
37     } else {
38       return internalName;
39     }
40   }
41 
mappedType(Type type)42   Type mappedType(Type type) {
43     String internalName = type.getInternalName();
44     String remappedInternalName = classesToRemap.get(internalName);
45     if (remappedInternalName != null) {
46       return Type.getObjectType(remappedInternalName);
47     } else {
48       return type;
49     }
50   }
51 
remapParams(String desc)52   String remapParams(String desc) {
53     StringBuilder buf = new StringBuilder();
54     buf.append("(");
55     for (Type type : Type.getArgumentTypes(desc)) {
56       buf.append(remapParamType(type));
57     }
58     buf.append(")");
59     buf.append(remapParamType(Type.getReturnType(desc)));
60     return buf.toString();
61   }
62 
63   // remap Landroid/Foo; to Landroid/Bar;
remapParamType(String desc)64   String remapParamType(String desc) {
65     return remapParamType(Type.getType(desc));
66   }
67 
remapParamType(Type type)68   private String remapParamType(Type type) {
69     String remappedName;
70     String internalName;
71 
72     switch (type.getSort()) {
73       case ARRAY:
74         internalName = type.getInternalName();
75         int count = 0;
76         while (internalName.charAt(count) == '[') count++;
77 
78         remappedName = remapParamType(internalName.substring(count));
79         if (remappedName != null) {
80           return Type.getObjectType(internalName.substring(0, count) + remappedName).getDescriptor();
81         }
82         break;
83 
84       case OBJECT:
85         type = mappedType(type);
86         break;
87 
88       default:
89         break;
90     }
91     return type.getDescriptor();
92   }
93 }
94