Skip to content

Commit ea59e39

Browse files
committed
fix(core): 支持Fragment override getContext方法
redirectMethodCallToStatic方法复用了TransformCall的匹配逻辑, 即`if (c == INVOKEINTERFACE || c == INVOKESPECIAL || c == INVOKESTATIC || c == INVOKEVIRTUAL)` 其中INVOKESPECIAL即包含super调用。而我们在替换fragmentGetContext方法时,并不需要对super调用进行转换。 如果转换会导致fragmentGetContext静态方法中对fragment的getContext调用循环回自身。 因此对这种情况忽略INVOKESPECIAL调用,添加新方法redirectMethodCallExceptSuperCallToStatic。 fix #647
1 parent 80bc328 commit ea59e39

File tree

4 files changed

+79
-2
lines changed

4 files changed

+79
-2
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
package javassist;
2+
3+
import javassist.convert.TransformCallExceptSuperCallToStatic;
4+
5+
public class EnhancedCodeConverter extends CodeConverter {
6+
7+
public void redirectMethodCallExceptSuperCallToStatic(CtMethod origMethod, CtMethod substMethod) throws CannotCompileException {
8+
transformers = new TransformCallExceptSuperCallToStatic(transformers, origMethod,
9+
substMethod);
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
package javassist.convert;
2+
3+
import javassist.ClassPool;
4+
import javassist.CtClass;
5+
import javassist.CtMethod;
6+
import javassist.NotFoundException;
7+
import javassist.bytecode.BadBytecode;
8+
import javassist.bytecode.CodeIterator;
9+
import javassist.bytecode.ConstPool;
10+
11+
public class TransformCallExceptSuperCallToStatic extends TransformCallToStatic {
12+
public TransformCallExceptSuperCallToStatic(Transformer next, CtMethod origMethod, CtMethod substMethod) {
13+
super(next, origMethod, substMethod);
14+
}
15+
16+
// COPY FROM TransformCall
17+
@Override
18+
public int transform(CtClass clazz, int pos, CodeIterator iterator, ConstPool cp) throws BadBytecode {
19+
int c = iterator.byteAt(pos);
20+
if (c == INVOKEINTERFACE || c == INVOKESTATIC || c == INVOKEVIRTUAL) { // THE ONLY DIFFERENCE WITH TransformCall
21+
int index = iterator.u16bitAt(pos + 1);
22+
String cname = cp.eqMember(methodname, methodDescriptor, index);
23+
if (cname != null && matchClass(cname, clazz.getClassPool())) {
24+
int ntinfo = cp.getMemberNameAndType(index);
25+
pos = match(c, pos, iterator,
26+
cp.getNameAndTypeDescriptor(ntinfo), cp);
27+
}
28+
}
29+
30+
return pos;
31+
}
32+
33+
// COPY FROM TransformCall
34+
private boolean matchClass(String name, ClassPool pool) {
35+
if (classname.equals(name))
36+
return true;
37+
38+
try {
39+
CtClass clazz = pool.get(name);
40+
CtClass declClazz = pool.get(classname);
41+
if (clazz.subtypeOf(declClazz))
42+
try {
43+
CtMethod m = clazz.getMethod(methodname, methodDescriptor);
44+
return m.getDeclaringClass().getName().equals(classname);
45+
} catch (NotFoundException e) {
46+
// maybe the original method has been removed.
47+
return true;
48+
}
49+
} catch (NotFoundException e) {
50+
return false;
51+
}
52+
53+
return false;
54+
}
55+
}

projects/sdk/core/transform/src/main/kotlin/com/tencent/shadow/core/transform/specific/FragmentSupportTransform.kt

+5-2
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,15 @@ class FragmentSupportTransform : SpecificTransform() {
104104

105105
override fun transform(ctClass: CtClass) {
106106
ctClass.defrost()
107-
val codeConverter = CodeConverter()
107+
val codeConverter = EnhancedCodeConverter()
108108
codeConverter.redirectMethodCallToStatic(
109109
getActivityMethod,
110110
fragmentGetActivityMethod
111111
)
112-
codeConverter.redirectMethodCallToStatic(getContextMethod, fragmentGetContextMethod)
112+
codeConverter.redirectMethodCallExceptSuperCallToStatic(
113+
getContextMethod,
114+
fragmentGetContextMethod
115+
)
113116
codeConverter.redirectMethodCallToStatic(getHostMethod, fragmentGetHostMethod)
114117
codeConverter.redirectMethodCallToStatic(
115118
startActivityMethod1,

projects/test/plugin/general-cases/general-cases-lib/src/main/java/com/tencent/shadow/test/plugin/general_cases/lib/usecases/fragment/TestNormalFragment.java

+8
Original file line numberDiff line numberDiff line change
@@ -91,4 +91,12 @@ public void onInflate(Activity activity, AttributeSet attrs, Bundle savedInstanc
9191
super.onInflate(activity, attrs, savedInstanceState);
9292
commonLogic.onInflate(activity, attrs, savedInstanceState);
9393
}
94+
95+
/**
96+
* 测试Fragment override getContext的场景
97+
*/
98+
@Override
99+
public Context getContext() {
100+
return super.getContext();
101+
}
94102
}

0 commit comments

Comments
 (0)