diff options
| -rw-r--r-- | src/utils.cc | 46 | ||||
| -rw-r--r-- | src/utils_test.cc | 83 | ||||
| -rw-r--r-- | test/034-call-null/expected.txt | 2 | ||||
| -rw-r--r-- | test/034-call-null/src/Main.java | 4 | ||||
| -rw-r--r-- | test/038-inner-null/expected.txt | 2 |
5 files changed, 92 insertions, 45 deletions
diff --git a/src/utils.cc b/src/utils.cc index c9a6e7e752..389c280ed3 100644 --- a/src/utils.cc +++ b/src/utils.cc @@ -184,6 +184,7 @@ std::string PrettyDescriptor(const std::string& descriptor) { case 'J': c = "long;"; break; case 'S': c = "short;"; break; case 'Z': c = "boolean;"; break; + case 'V': c = "void;"; break; // Used when decoding return types. default: return descriptor; } } @@ -227,6 +228,41 @@ std::string PrettyField(const Field* f, bool with_type) { return result; } +std::string PrettyArguments(const char* signature) { + std::string result; + result += '('; + CHECK_EQ(*signature, '('); + ++signature; // Skip the '('. + while (*signature != ')') { + size_t argument_length = 0; + while (signature[argument_length] == '[') { + ++argument_length; + } + if (signature[argument_length] == 'L') { + argument_length = (strchr(signature, ';') - signature + 1); + } else { + ++argument_length; + } + std::string argument_descriptor(signature, argument_length); + result += PrettyDescriptor(argument_descriptor); + if (signature[argument_length] != ')') { + result += ", "; + } + signature += argument_length; + } + CHECK_EQ(*signature, ')'); + ++signature; // Skip the ')'. + result += ')'; + return result; +} + +std::string PrettyReturnType(const char* signature) { + const char* return_type = strchr(signature, ')'); + CHECK(return_type != NULL); + ++return_type; // Skip ')'. + return PrettyDescriptor(return_type); +} + std::string PrettyMethod(const Method* m, bool with_signature) { if (m == NULL) { return "null"; @@ -236,9 +272,8 @@ std::string PrettyMethod(const Method* m, bool with_signature) { result += '.'; result += mh.GetName(); if (with_signature) { - // TODO: iterate over the signature's elements and pass them all to - // PrettyDescriptor? We'd need to pull out the return type specially, too. - result += mh.GetSignature(); + std::string signature(mh.GetSignature()); + result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str()); } return result; } @@ -249,9 +284,8 @@ std::string PrettyMethod(uint32_t method_idx, const DexFile& dex_file, bool with result += '.'; result += dex_file.GetMethodName(method_id); if (with_signature) { - // TODO: iterate over the signature's elements and pass them all to - // PrettyDescriptor? We'd need to pull out the return type specially, too. - result += dex_file.GetMethodSignature(method_id); + std::string signature(dex_file.GetMethodSignature(method_id)); + result = PrettyReturnType(signature.c_str()) + " " + result + PrettyArguments(signature.c_str()); } return result; } diff --git a/src/utils_test.cc b/src/utils_test.cc index 31fccc506d..3228bb6d12 100644 --- a/src/utils_test.cc +++ b/src/utils_test.cc @@ -20,54 +20,67 @@ namespace art { +std::string PrettyArguments(const char* signature); +std::string PrettyReturnType(const char* signature); + class UtilsTest : public CommonTest { }; -#define EXPECT_DESCRIPTOR(pretty_descriptor, descriptor) \ - do { \ - SirtRef<String> s(String::AllocFromModifiedUtf8(descriptor)); \ - std::string result(PrettyDescriptor(s.get())); \ - EXPECT_EQ(pretty_descriptor, result); \ - } while (false) - TEST_F(UtilsTest, PrettyDescriptor_ArrayReferences) { - EXPECT_DESCRIPTOR("java.lang.Class[]", "[Ljava/lang/Class;"); - EXPECT_DESCRIPTOR("java.lang.Class[][]", "[[Ljava/lang/Class;"); + EXPECT_EQ("java.lang.Class[]", PrettyDescriptor("[Ljava/lang/Class;")); + EXPECT_EQ("java.lang.Class[][]", PrettyDescriptor("[[Ljava/lang/Class;")); } TEST_F(UtilsTest, PrettyDescriptor_ScalarReferences) { - EXPECT_DESCRIPTOR("java.lang.String", "Ljava.lang.String;"); - EXPECT_DESCRIPTOR("java.lang.String", "Ljava/lang/String;"); + EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava.lang.String;")); + EXPECT_EQ("java.lang.String", PrettyDescriptor("Ljava/lang/String;")); } TEST_F(UtilsTest, PrettyDescriptor_PrimitiveArrays) { - EXPECT_DESCRIPTOR("boolean[]", "[Z"); - EXPECT_DESCRIPTOR("boolean[][]", "[[Z"); - EXPECT_DESCRIPTOR("byte[]", "[B"); - EXPECT_DESCRIPTOR("byte[][]", "[[B"); - EXPECT_DESCRIPTOR("char[]", "[C"); - EXPECT_DESCRIPTOR("char[][]", "[[C"); - EXPECT_DESCRIPTOR("double[]", "[D"); - EXPECT_DESCRIPTOR("double[][]", "[[D"); - EXPECT_DESCRIPTOR("float[]", "[F"); - EXPECT_DESCRIPTOR("float[][]", "[[F"); - EXPECT_DESCRIPTOR("int[]", "[I"); - EXPECT_DESCRIPTOR("int[][]", "[[I"); - EXPECT_DESCRIPTOR("long[]", "[J"); - EXPECT_DESCRIPTOR("long[][]", "[[J"); - EXPECT_DESCRIPTOR("short[]", "[S"); - EXPECT_DESCRIPTOR("short[][]", "[[S"); + EXPECT_EQ("boolean[]", PrettyDescriptor("[Z")); + EXPECT_EQ("boolean[][]", PrettyDescriptor("[[Z")); + EXPECT_EQ("byte[]", PrettyDescriptor("[B")); + EXPECT_EQ("byte[][]", PrettyDescriptor("[[B")); + EXPECT_EQ("char[]", PrettyDescriptor("[C")); + EXPECT_EQ("char[][]", PrettyDescriptor("[[C")); + EXPECT_EQ("double[]", PrettyDescriptor("[D")); + EXPECT_EQ("double[][]", PrettyDescriptor("[[D")); + EXPECT_EQ("float[]", PrettyDescriptor("[F")); + EXPECT_EQ("float[][]", PrettyDescriptor("[[F")); + EXPECT_EQ("int[]", PrettyDescriptor("[I")); + EXPECT_EQ("int[][]", PrettyDescriptor("[[I")); + EXPECT_EQ("long[]", PrettyDescriptor("[J")); + EXPECT_EQ("long[][]", PrettyDescriptor("[[J")); + EXPECT_EQ("short[]", PrettyDescriptor("[S")); + EXPECT_EQ("short[][]", PrettyDescriptor("[[S")); } TEST_F(UtilsTest, PrettyDescriptor_PrimitiveScalars) { - EXPECT_DESCRIPTOR("boolean", "Z"); - EXPECT_DESCRIPTOR("byte", "B"); - EXPECT_DESCRIPTOR("char", "C"); - EXPECT_DESCRIPTOR("double", "D"); - EXPECT_DESCRIPTOR("float", "F"); - EXPECT_DESCRIPTOR("int", "I"); - EXPECT_DESCRIPTOR("long", "J"); - EXPECT_DESCRIPTOR("short", "S"); + EXPECT_EQ("boolean", PrettyDescriptor("Z")); + EXPECT_EQ("byte", PrettyDescriptor("B")); + EXPECT_EQ("char", PrettyDescriptor("C")); + EXPECT_EQ("double", PrettyDescriptor("D")); + EXPECT_EQ("float", PrettyDescriptor("F")); + EXPECT_EQ("int", PrettyDescriptor("I")); + EXPECT_EQ("long", PrettyDescriptor("J")); + EXPECT_EQ("short", PrettyDescriptor("S")); +} + +TEST_F(UtilsTest, PrettyArguments) { + EXPECT_EQ("()", PrettyArguments("()V")); + EXPECT_EQ("(int)", PrettyArguments("(I)V")); + EXPECT_EQ("(int, int)", PrettyArguments("(II)V")); + EXPECT_EQ("(int, int, int[][])", PrettyArguments("(II[[I)V")); + EXPECT_EQ("(int, int, int[][], java.lang.Poop)", PrettyArguments("(II[[ILjava/lang/Poop;)V")); + EXPECT_EQ("(int, int, int[][], java.lang.Poop, java.lang.Poop[][])", PrettyArguments("(II[[ILjava/lang/Poop;[[Ljava/lang/Poop;)V")); +} + +TEST_F(UtilsTest, PrettyReturnType) { + EXPECT_EQ("void", PrettyReturnType("()V")); + EXPECT_EQ("int", PrettyReturnType("()I")); + EXPECT_EQ("int[][]", PrettyReturnType("()[[I")); + EXPECT_EQ("java.lang.Poop", PrettyReturnType("()Ljava/lang/Poop;")); + EXPECT_EQ("java.lang.Poop[][]", PrettyReturnType("()[[Ljava/lang/Poop;")); } TEST_F(UtilsTest, PrettyTypeOf) { diff --git a/test/034-call-null/expected.txt b/test/034-call-null/expected.txt index 7ed221575a..343226f705 100644 --- a/test/034-call-null/expected.txt +++ b/test/034-call-null/expected.txt @@ -1,2 +1,2 @@ -java.lang.NullPointerException: Attempt to invoke direct method 'Main.doStuff()V' on a null object reference +java.lang.NullPointerException: Attempt to invoke direct method 'void Main.doStuff(int, int[][], java.lang.String, java.lang.String[][])' on a null object reference at Main.main(Main.java:26) diff --git a/test/034-call-null/src/Main.java b/test/034-call-null/src/Main.java index 5b60c71817..cc89bb4fc3 100644 --- a/test/034-call-null/src/Main.java +++ b/test/034-call-null/src/Main.java @@ -17,12 +17,12 @@ public class Main { int mFoo = 27; - private void doStuff() { + private void doStuff(int i, int[][] is, String s, String[][] ss) { System.out.println("mFoo is " + mFoo); } public static void main(String[] args) { Main instance = null; - instance.doStuff(); + instance.doStuff(0, null, null, null); } } diff --git a/test/038-inner-null/expected.txt b/test/038-inner-null/expected.txt index 37f984c295..ba411f030c 100644 --- a/test/038-inner-null/expected.txt +++ b/test/038-inner-null/expected.txt @@ -1,4 +1,4 @@ new Special() -java.lang.NullPointerException: Attempt to invoke virtual method 'Main$Blort.repaint()V' on a null object reference +java.lang.NullPointerException: Attempt to invoke virtual method 'void Main$Blort.repaint()' on a null object reference at Main$Special.callInner(Main.java:31) at Main.main(Main.java:20) |