Materialize method descriptors when instantiating method objects.

Previously, when comparing method descriptors, one had to piecewise
compare the leaves of a method structure for equality.

With this change a flat method descriptor is computed and associated
to an object.  This will simplify comparisons for descriptor equality
used during verification and reflective method retrieval.

Change-Id: I91e5ac76fb3816a36716b34fe43d05cd7364897b
diff --git a/src/dex_file_test.cc b/src/dex_file_test.cc
index a6b5bd5..33c43c9 100644
--- a/src/dex_file_test.cc
+++ b/src/dex_file_test.cc
@@ -54,4 +54,70 @@
   EXPECT_STREQ("LNested;", raw->GetClassDescriptor(c1));
 }
 
+TEST(DexFileTest, CreateMethodDescriptor) {
+  scoped_ptr<DexFile> raw(OpenDexFileBase64(kCreateMethodDescriptorDex));
+  ASSERT_TRUE(raw != NULL);
+  EXPECT_EQ(1U, raw->NumClassDefs());
+
+  const DexFile::ClassDef& class_def = raw->GetClassDef(0);
+  ASSERT_STREQ("LCreateMethodDescriptor;", raw->GetClassDescriptor(class_def));
+
+  const byte* class_data = raw->GetClassData(class_def);
+  ASSERT_TRUE(class_data != NULL);
+  DexFile::ClassDataHeader header = raw->ReadClassDataHeader(&class_data);
+
+  EXPECT_EQ(1u, header.direct_methods_size_);
+
+  // Check the descriptor for the static initializer.
+  {
+    uint32_t last_idx = 0;
+    ASSERT_EQ(1U, header.direct_methods_size_);
+    DexFile::Method method;
+    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
+    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+    uint32_t proto_idx = method_id.proto_idx_;
+    const char* name = raw->dexStringById(method_id.name_idx_);
+    ASSERT_STREQ("<init>", name);
+    int32_t length;
+    scoped_ptr<const char> descriptor(raw->CreateMethodDescriptor(proto_idx,
+                                                                  &length));
+    ASSERT_STREQ("()V", descriptor.get());
+  }
+
+  // Check both virtual methods.
+  ASSERT_EQ(2U, header.virtual_methods_size_);
+  uint32_t last_idx = 0;
+
+  {
+    DexFile::Method method;
+    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
+    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+
+    const char* name = raw->dexStringById(method_id.name_idx_);
+    ASSERT_STREQ("m1", name);
+
+    uint32_t proto_idx = method_id.proto_idx_;
+    int32_t length;
+    scoped_ptr<const char> descriptor(raw->CreateMethodDescriptor(proto_idx,
+                                                                  &length));
+    ASSERT_STREQ("(IDJLjava/lang/Object;)Ljava/lang/Float;", descriptor.get());
+  }
+
+  {
+    DexFile::Method method;
+    raw->dexReadClassDataMethod(&class_data, &method, &last_idx);
+    const DexFile::MethodId& method_id = raw->GetMethodId(method.method_idx_);
+
+    const char* name = raw->dexStringById(method_id.name_idx_);
+    ASSERT_STREQ("m2", name);
+
+    uint32_t proto_idx = method_id.proto_idx_;
+    int32_t length;
+    scoped_ptr<const char> descriptor(raw->CreateMethodDescriptor(proto_idx,
+                                                                  &length));
+    ASSERT_STREQ("(ZSC)LCreateMethodDescriptor;", descriptor.get());
+  }
+
+}
+
 }  // namespace art