From 2976ca0211e3147e27d593e6d743b7d0f2c35eaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=87=91=E6=88=9F?= Date: Fri, 26 Feb 2021 14:02:58 +0800 Subject: [PATCH] print diagnose descriptor in java-like format --- .../agent/handler/MockClassHandler.java | 3 +-- .../agent/handler/SourceClassHandler.java | 12 ++++++---- .../agent/transformer/MockClassParser.java | 19 ++++++++++++--- .../testable/agent/util/AnnotationUtil.java | 2 +- .../testable/agent/util/MethodUtil.java | 24 +++++++++++++++++++ 5 files changed, 49 insertions(+), 11 deletions(-) diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java index 3dc7db4..e6215ef 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/MockClassHandler.java @@ -175,8 +175,7 @@ public class MockClassHandler extends BaseClassWithContextHandler { if (VOID_RES.equals(returnType)) { il.add(new InsnNode(POP)); il.add(new InsnNode(RETURN)); - } else if (returnType.startsWith(String.valueOf(TYPE_ARRAY)) || - returnType.startsWith(String.valueOf(TYPE_CLASS))) { + } else if (returnType.charAt(0) == TYPE_ARRAY ||returnType.charAt(0) == TYPE_CLASS) { il.add(new TypeInsnNode(CHECKCAST, returnType)); il.add(new InsnNode(ARETURN)); } else { diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java index fda55e2..31a22e5 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/handler/SourceClassHandler.java @@ -67,8 +67,8 @@ public class SourceClassHandler extends BaseClassHandler { if (invokeOps.contains(instructions[i].getOpcode())) { MethodInsnNode node = (MethodInsnNode)instructions[i]; if (CONSTRUCTOR.equals(node.name)) { - LogUtil.verbose(" Line %d, constructing \"%s\" as \"%s\"", getLineNum(instructions, i), - node.owner, node.desc); + LogUtil.verbose(" Line %d, constructing \"%s\"", getLineNum(instructions, i), + MethodUtil.toJavaDesc(node.owner, node.desc)); MethodInfo newOperatorInjectMethod = getNewOperatorInjectMethod(newOperatorInjectMethods, node); if (newOperatorInjectMethod != null) { // it's a new operation and an inject method for it exist @@ -79,14 +79,16 @@ public class SourceClassHandler extends BaseClassHandler { } } } else { - LogUtil.verbose(" Line %d, invoking \"%s\" as \"%s\"", getLineNum(instructions, i), - node.name, node.desc); + LogUtil.verbose(" Line %d, invoking \"%s\"", getLineNum(instructions, i), + MethodUtil.toJavaDesc(node.owner, node.name, node.desc)); MethodInfo mockMethod = getMemberInjectMethodName(memberInjectMethods, node); if (mockMethod != null) { // it's a member or static method and an inject method for it exist int rangeStart = getMemberMethodStart(instructions, i); if (rangeStart >= 0) { - handleFrameStackChange(mn, mockMethod, rangeStart, i); + if (rangeStart < i) { + handleFrameStackChange(mn, mockMethod, rangeStart, i); + } instructions = replaceMemberCallOps(mn, mockMethod, instructions, node.owner, node.getOpcode(), rangeStart, i); i = rangeStart; diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/MockClassParser.java b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/MockClassParser.java index f88b863..fc1da9e 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/MockClassParser.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/transformer/MockClassParser.java @@ -87,11 +87,12 @@ public class MockClassParser { for (AnnotationNode an : mn.visibleAnnotations) { String fullClassName = toDotSeparateFullClassName(an.desc); if (fullClassName.equals(ConstPool.MOCK_CONSTRUCTOR)) { - LogUtil.verbose(" Mock constructor \"%s\" as \"(%s)V\" for \"%s\"", mn.name, - MethodUtil.extractParameters(mn.desc), MethodUtil.getReturnType(mn.desc)); + LogUtil.verbose(" Mock constructor \"%s\" as \"%s\"", mn.name, + MethodUtil.toJavaDesc(MethodUtil.getReturnType(mn.desc), mn.desc)); addMockConstructor(methodInfos, cn, mn); } else if (fullClassName.equals(ConstPool.MOCK_METHOD) && AnnotationUtil.isValidMockMethod(mn, an)) { - LogUtil.verbose(" Mock method \"%s\" as \"%s\"", mn.name, getTargetMethodDesc(mn, an)); + LogUtil.verbose(" Mock method \"%s\" as \"%s\"", mn.name, MethodUtil.toJavaDesc( + getTargetMethodOwner(mn, an), getTargetMethodName(mn, an), getTargetMethodDesc(mn, an))); String targetMethod = AnnotationUtil.getAnnotationParameter( an, ConstPool.FIELD_TARGET_METHOD, mn.name, String.class); if (CONSTRUCTOR.equals(targetMethod)) { @@ -107,6 +108,18 @@ public class MockClassParser { } } + private String getTargetMethodOwner(MethodNode mn, AnnotationNode mockMethodAnnotation) { + Type type = AnnotationUtil.getAnnotationParameter(mockMethodAnnotation, ConstPool.FIELD_TARGET_CLASS, + null, Type.class); + return type == null ? MethodUtil.getFirstParameter(mn.desc) : type.getClassName(); + } + + private String getTargetMethodName(MethodNode mn, AnnotationNode mockMethodAnnotation) { + String name = AnnotationUtil.getAnnotationParameter(mockMethodAnnotation, ConstPool.FIELD_TARGET_METHOD, + null, String.class); + return name == null ? mn.name : name; + } + private String getTargetMethodDesc(MethodNode mn, AnnotationNode mockMethodAnnotation) { Type type = AnnotationUtil.getAnnotationParameter(mockMethodAnnotation, ConstPool.FIELD_TARGET_CLASS, null, Type.class); diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/util/AnnotationUtil.java b/testable-agent/src/main/java/com/alibaba/testable/agent/util/AnnotationUtil.java index b8e708f..12342f4 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/util/AnnotationUtil.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/util/AnnotationUtil.java @@ -74,6 +74,6 @@ public class AnnotationUtil { public static boolean isValidMockMethod(MethodNode mn, AnnotationNode an) { Type targetClass = AnnotationUtil.getAnnotationParameter(an, ConstPool.FIELD_TARGET_CLASS, null, Type.class); String firstParameter = MethodUtil.getFirstParameter(mn.desc); - return targetClass != null || firstParameter.startsWith(String.valueOf(TYPE_CLASS)); + return targetClass != null || firstParameter.charAt(0) == TYPE_CLASS; } } diff --git a/testable-agent/src/main/java/com/alibaba/testable/agent/util/MethodUtil.java b/testable-agent/src/main/java/com/alibaba/testable/agent/util/MethodUtil.java index d1013b6..c059f8b 100644 --- a/testable-agent/src/main/java/com/alibaba/testable/agent/util/MethodUtil.java +++ b/testable-agent/src/main/java/com/alibaba/testable/agent/util/MethodUtil.java @@ -105,4 +105,28 @@ public class MethodUtil { return b == TYPE_BYTE || b == TYPE_CHAR || b == TYPE_DOUBLE || b == TYPE_FLOAT || b == TYPE_INT || b == TYPE_LONG || b == TYPE_SHORT || b == TYPE_BOOL; } + + /** + * format to java style constructor descriptor + * @param owner class of method belongs to + * @param desc method constructor in bytecode format + * @return java style constructor descriptor + */ + public static String toJavaDesc(String owner, String desc) { + String parameters = MethodUtil.extractParameters(desc); + return String.format("%s(%s)", owner, parameters); + } + + /** + * format to java style method descriptor + * @param owner class of method belongs to + * @param name method name + * @param desc method descriptor in bytecode format + * @return java style method descriptor + */ + public static String toJavaDesc(String owner, String name, String desc) { + String returnType = MethodUtil.getReturnType(desc); + String parameters = MethodUtil.extractParameters(desc); + return String.format("%s %s::%s(%s)", returnType, owner, name, parameters); + } }