refactor: type resolution using visitor

Type references and constant references are done in a same visitor.

Visitor provides "scope" which can be used to (not implemented in this
change)

- resolve "type parameter"(AidlTypeSpecifier) bound to the scope
- resolve nested types
- ...

Bug: n/a
Test: aidl_unittests
Change-Id: I44aef519545ca377b208dbe98ef5a57b9cec1878
diff --git a/aidl_language.h b/aidl_language.h
index e0c28a0..fcc592a 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -700,8 +700,10 @@
   const std::string& GetFieldName() const { return field_name_; }
 
   bool CheckValid() const override;
-  void TraverseChildren(std::function<void(const AidlNode&)>) const override {
-    // resolved_ is not my child.
+  void TraverseChildren(std::function<void(const AidlNode&)> traverse) const override {
+    if (ref_type_) {
+      traverse(*ref_type_);
+    }
   }
   void DispatchVisit(AidlVisitor& v) const override { v.Visit(*this); }
   const AidlConstantValue* Resolve(const AidlDefinedType* scope) const;
@@ -1249,4 +1251,17 @@
     n.TraverseChildren(top_down);
   };
   top_down(node);
+}
+
+// Utility to make a visitor to visit AST tree in bottom-up order
+// Given:       foo
+//              / \
+//            bar baz
+// VisitBottomUp(v, foo) makes v visit bar -> baz -> foo.
+inline void VisitBottomUp(AidlVisitor& v, const AidlNode& node) {
+  std::function<void(const AidlNode&)> bottom_up = [&](const AidlNode& n) {
+    n.TraverseChildren(bottom_up);
+    n.DispatchVisit(v);
+  };
+  bottom_up(node);
 }
\ No newline at end of file
diff --git a/aidl_language_y.yy b/aidl_language_y.yy
index ab3e479..19b1262 100644
--- a/aidl_language_y.yy
+++ b/aidl_language_y.yy
@@ -660,7 +660,6 @@
 non_array_type
  : annotation_list qualified_name {
     $$ = new AidlTypeSpecifier(loc(@2), $2->GetText(), false, nullptr, $2->GetComments());
-    ps->DeferResolution($$);
     if (!$1->empty()) {
       $$->SetComments($1->begin()->GetComments());
       $$->Annotate(std::move(*$1));
diff --git a/parser.cpp b/parser.cpp
index 721979f..c8cf476 100644
--- a/parser.cpp
+++ b/parser.cpp
@@ -61,24 +61,26 @@
   }
 }
 
-class ConstantReferenceResolver : public AidlVisitor {
+class ReferenceResolver : public AidlVisitor {
  public:
-  ConstantReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
-                            TypeResolver& resolver, bool* success)
+  ReferenceResolver(const AidlDefinedType* scope, const AidlTypenames& typenames,
+                    TypeResolver& resolver, bool* success)
       : scope_(scope), typenames_(typenames), resolver_(resolver), success_(success) {}
+
+  void Visit(const AidlTypeSpecifier& t) override {
+    AidlTypeSpecifier& type = const_cast<AidlTypeSpecifier&>(t);
+    if (!resolver_(typenames_.GetDocumentFor(scope_), &type)) {
+      AIDL_ERROR(type) << "Failed to resolve '" << type.GetUnresolvedName() << "'";
+      *success_ = false;
+    }
+  }
+
   void Visit(const AidlConstantReference& v) override {
     if (IsCircularReference(&v)) {
       *success_ = false;
       return;
     }
 
-    if (v.GetRefType() && !v.GetRefType()->IsResolved()) {
-      if (!resolver_(typenames_.GetDocumentFor(scope_), v.GetRefType().get())) {
-        AIDL_ERROR(v.GetRefType()) << "Unknown type '" << v.GetRefType()->GetName() << "'";
-        *success_ = false;
-        return;
-      }
-    }
     const AidlConstantValue* resolved = v.Resolve(scope_);
     if (!resolved) {
       AIDL_ERROR(v) << "Unknown reference '" << v.Literal() << "'";
@@ -88,7 +90,7 @@
 
     // resolve recursive references
     Push(&v);
-    VisitTopDown(*this, *resolved);
+    VisitBottomUp(*this, *resolved);
     Pop();
   }
 
@@ -133,20 +135,13 @@
   std::vector<StackElem> stack_ = {};
 };
 
+// Resolve "unresolved" types in the "main" document.
 bool Parser::Resolve(TypeResolver& type_resolver) {
   bool success = true;
-  for (AidlTypeSpecifier* typespec : unresolved_typespecs_) {
-    if (!type_resolver(document_, typespec)) {
-      AIDL_ERROR(typespec) << "Failed to resolve '" << typespec->GetUnresolvedName() << "'";
-      success = false;
-      // don't stop to show more errors if any
-    }
-  }
 
-  // resolve "field references" as well.
   for (const auto& type : document_->DefinedTypes()) {
-    ConstantReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
-    VisitTopDown(ref_resolver, *type);
+    ReferenceResolver ref_resolver{type.get(), typenames_, type_resolver, &success};
+    VisitBottomUp(ref_resolver, *type);
   }
 
   return success;
diff --git a/parser.h b/parser.h
index e2dea08..f34ca78 100644
--- a/parser.h
+++ b/parser.h
@@ -87,12 +87,6 @@
   void SetPackage(const std::string& package) { package_ = package; }
   const std::string& Package() const { return package_; }
 
-  void DeferResolution(AidlTypeSpecifier* typespec) {
-    unresolved_typespecs_.emplace_back(typespec);
-  }
-
-  const vector<AidlTypeSpecifier*>& GetUnresolvedTypespecs() const { return unresolved_typespecs_; }
-
   bool Resolve(TypeResolver& type_resolver);
   void SetDocument(std::unique_ptr<AidlDocument>&& document) {
     // The parsed document is owned by typenames_. This parser object only has
@@ -121,6 +115,5 @@
   YY_BUFFER_STATE buffer_;
   int error_ = 0;
 
-  vector<AidlTypeSpecifier*> unresolved_typespecs_;
   const AidlDocument* document_;
 };