Fix nested parcelable class name
am: d17c58babb

Change-Id: Ia82d7f904e2b4a7497d6ffedc3e3bff5a884a3f8
diff --git a/aidl_language.h b/aidl_language.h
index e27cd10..7982e76 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -278,6 +278,7 @@
   const std::vector<std::string>& GetTerms() const { return terms_; }
   const std::string& GetComments() const { return comments_; }
   std::string GetDotName() const { return android::base::Join(terms_, '.'); }
+  std::string GetColonName() const { return android::base::Join(terms_, "::"); }
 
   void AddTerm(const std::string& term);
 
@@ -296,6 +297,8 @@
   virtual ~AidlParcelable() = default;
 
   std::string GetName() const { return name_->GetDotName(); }
+  // C++ uses "::" instead of "." to refer to a inner class.
+  std::string GetCppName() const { return name_->GetColonName(); }
   unsigned GetLine() const { return line_; }
   std::string GetPackage() const;
   const std::vector<std::string>& GetSplitPackage() const { return package_; }
diff --git a/aidl_unittest.cpp b/aidl_unittest.cpp
index 0d2ba53..22ad1bd 100644
--- a/aidl_unittest.cpp
+++ b/aidl_unittest.cpp
@@ -332,6 +332,23 @@
   EXPECT_EQ(-1, cpp_int_constants[0]->GetValue());
 }
 
+TEST_F(AidlTest, UnderstandsNestedParcelables) {
+  io_delegate_.SetFileContents(
+      "p/Outer.aidl",
+      "package p; parcelable Outer.Inner cpp_header \"baz/header\";");
+  import_paths_.push_back("");
+  const string input_path = "p/IFoo.aidl";
+  const string input = "package p; import p.Outer; interface IFoo"
+                       " { Outer.Inner get(); }";
+
+  auto cpp_parse_result = Parse(input_path, input, &cpp_types_);
+  EXPECT_NE(nullptr, cpp_parse_result);
+  auto cpp_type = cpp_types_.FindTypeByCanonicalName("p.Outer.Inner");
+  ASSERT_NE(nullptr, cpp_type);
+  // C++ uses "::" instead of "." to refer to a inner class.
+  EXPECT_EQ("::p::Outer::Inner", cpp_type->CppType());
+}
+
 TEST_F(AidlTest, UnderstandsNativeParcelables) {
   io_delegate_.SetFileContents(
       "p/Bar.aidl",
diff --git a/type_cpp.cpp b/type_cpp.cpp
index 2c0552d..e20f603 100644
--- a/type_cpp.cpp
+++ b/type_cpp.cpp
@@ -235,7 +235,7 @@
  private:
   static string GetCppName(const AidlParcelable& parcelable) {
     return "::std::unique_ptr<::" + Join(parcelable.GetSplitPackage(), "::") +
-        "::" + parcelable.GetName() + ">";
+        "::" + parcelable.GetCppName() + ">";
   }
 };
 
@@ -261,7 +261,7 @@
  private:
   static string GetCppName(const AidlParcelable& parcelable) {
     return "::" + Join(parcelable.GetSplitPackage(), "::") +
-        "::" + parcelable.GetName();
+        "::" + parcelable.GetCppName();
   }
 };
 
diff --git a/type_cpp_unittest.cpp b/type_cpp_unittest.cpp
index 35fc3d5..46b5db8 100644
--- a/type_cpp_unittest.cpp
+++ b/type_cpp_unittest.cpp
@@ -15,15 +15,26 @@
  */
 
 #include <memory>
+#include <string>
 
 #include <gtest/gtest.h>
 
 #include "type_cpp.h"
 
+using std::string;
+using std::unique_ptr;
+
 namespace android {
 namespace aidl {
 namespace cpp {
 
+namespace {
+
+string kParcelableDotName = "Outer.Inner";
+string kParcelableColonName = "Outer::Inner";
+
+}  // namespace
+
 class CppTypeNamespaceTest : public ::testing::Test {
  protected:
   void SetUp() override {
@@ -48,6 +59,14 @@
       types_.HasTypeByCanonicalName("java.util.List<java.lang.String>"));
 }
 
+TEST_F(CppTypeNamespaceTest, SupportsNestedParcelableClass) {
+  unique_ptr<AidlParcelable> parcelable(
+      new AidlParcelable(new AidlQualifiedName(kParcelableDotName, ""),
+                         0,
+                         {"a", "goog"}));
+  EXPECT_EQ(parcelable->GetCppName(), kParcelableColonName);
+}
+
 }  // namespace cpp
 }  // namespace android
 }  // namespace aidl