C++/NDK backends reorder nested type decls.

In the following example, C is declared before B.

  parcelabe A {
    parcelabe B {
      C c;
    }
    parcelable C {}
  }

Otherwise, C++ compiler will complain about undefined symbols.

Still we can't define nested types with cyclic references because decl
order is not determined for C++/NDK backends.

Bug: 201376182
Test: golden_test.sh check
Test: aidl_unittests
Change-Id: I8340dc33e3f745aa51dca038af0ad55893c3aa05
diff --git a/aidl_language.h b/aidl_language.h
index 52fabf9..a920dab 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -1272,3 +1272,68 @@
 T* AidlCast(AidlNode& node) {
   return const_cast<T*>(AidlCast<T>(const_cast<const AidlNode&>(node)));
 }
+
+template <typename AidlNodeType>
+vector<const AidlNodeType*> Collect(const AidlNode& root) {
+  vector<const AidlNodeType*> result;
+  std::function<void(const AidlNode&)> top_down = [&](const AidlNode& n) {
+    if (auto cast = AidlCast<AidlNodeType>(n); cast) {
+      result.push_back(cast);
+    }
+    n.TraverseChildren(top_down);
+  };
+  top_down(root);
+  return result;
+}
+
+template <typename VisitFn>
+bool TopologicalVisit(const vector<unique_ptr<AidlDefinedType>>& nested_types, VisitFn visit) {
+  // 1. Maps deeply nested types to one of nested_types
+  map<const AidlDefinedType*, const AidlDefinedType*> roots;
+  for (const auto& nested : nested_types) {
+    for (const auto& t : Collect<AidlDefinedType>(*nested)) {
+      roots[t] = nested.get();
+    }
+  }
+  // 2. Collect sibling types referenced within each nested type.
+  map<const AidlDefinedType*, vector<const AidlDefinedType*>> required_types;
+  for (const auto& nested : nested_types) {
+    for (const auto& t : Collect<AidlTypeSpecifier>(*nested)) {
+      if (auto defined_type = t->GetDefinedType(); defined_type) {
+        auto sibling = roots[defined_type];
+        if (sibling && sibling != nested.get()) {
+          required_types[nested.get()].push_back(sibling);
+        }
+      }
+    }
+  };
+  // 3. Run DFS
+  enum { NOT_STARTED = 0, STARTED = 1, FINISHED = 2 };
+  map<const AidlDefinedType*, int> visited;
+  std::function<bool(const AidlDefinedType&)> dfs = [&](const AidlDefinedType& type) {
+    if (visited[&type] == FINISHED) {
+      return true;
+    } else if (visited[&type] == STARTED) {
+      return false;
+    } else {
+      visited[&type] = STARTED;
+      // Visit every required dep first
+      for (const auto& dep_type : required_types[&type]) {
+        if (!dfs(*dep_type)) {
+          return false;
+        }
+      }
+      visited[&type] = FINISHED;
+      visit(type);
+      return true;
+    }
+  };
+
+  for (const auto& type : nested_types) {
+    if (!dfs(*type)) {
+      return false;
+    }
+  }
+
+  return true;
+}