Run diagnostics in a separate visitor

CheckValid() is already quite complicated and adding more to the method
seems not to be scalable.

Bug: 168028537
Test: aidl_unittests
Change-Id: I41a11ce028d8b8f018e80e7203b0d6a955d3768b
diff --git a/aidl_language.h b/aidl_language.h
index 112c6dc..d36cec1 100644
--- a/aidl_language.h
+++ b/aidl_language.h
@@ -92,6 +92,52 @@
 
 std::ostream& operator<<(std::ostream& os, const AidlLocation& l);
 
+class AidlDocument;
+class AidlInterface;
+class AidlParcelable;
+class AidlStructuredParcelable;
+class AidlEnumDeclaration;
+class AidlUnionDecl;
+class AidlVariableDeclaration;
+class AidlConstantDeclaration;
+class AidlEnumerator;
+class AidlMethod;
+class AidlArgument;
+
+class AidlVisitor {
+ public:
+  virtual ~AidlVisitor() = default;
+  virtual void VisitDocument(const AidlDocument& d) = 0;
+  virtual void VisitInterface(const AidlInterface& i) = 0;
+  virtual void VisitUnstructuredParcelable(const AidlParcelable& p) = 0;
+  virtual void VisitStructuredParcelable(const AidlStructuredParcelable& p) = 0;
+  virtual void VisitUnion(const AidlUnionDecl& u) = 0;
+  virtual void VisitEnum(const AidlEnumDeclaration& e) = 0;
+  virtual void VisitEnumerator(const AidlEnumerator& e) = 0;
+  virtual void VisitMethod(const AidlMethod& m) = 0;
+  virtual void VisitVariable(const AidlVariableDeclaration& v) = 0;
+  virtual void VisitConstant(const AidlConstantDeclaration& c) = 0;
+  virtual void VisitArgument(const AidlArgument& a) = 0;
+};
+
+// Provides default implementation which visits child nodes.
+// In a derived class, call super method to visit chid nodes.
+// Calling super method first visits nodes in bottom-up way.
+class AidlVisitAll : public AidlVisitor {
+ public:
+  void VisitDocument(const AidlDocument& d) override;
+  void VisitInterface(const AidlInterface& i) override;
+  void VisitUnstructuredParcelable(const AidlParcelable& p) override;
+  void VisitStructuredParcelable(const AidlStructuredParcelable& p) override;
+  void VisitUnion(const AidlUnionDecl& u) override;
+  void VisitEnum(const AidlEnumDeclaration& e) override;
+  void VisitEnumerator(const AidlEnumerator& e) override;
+  void VisitMethod(const AidlMethod& m) override;
+  void VisitVariable(const AidlVariableDeclaration& v) override;
+  void VisitConstant(const AidlConstantDeclaration& c) override;
+  void VisitArgument(const AidlArgument& a) override;
+};
+
 // Anything that is locatable in a .aidl file.
 class AidlNode {
  public:
@@ -392,6 +438,8 @@
     return const_cast<AidlVariableDeclaration*>(
         const_cast<const AidlMember*>(this)->AsVariableDeclaration());
   }
+
+  virtual void Accept(AidlVisitor& vis) const = 0;
 };
 
 // TODO: This class is used for method arguments and also parcelable fields,
@@ -425,6 +473,7 @@
 
   AidlTypeSpecifier* GetMutableType() { return type_.get(); }
 
+  void Accept(AidlVisitor& vis) const override { vis.VisitVariable(*this); }
   bool CheckValid(const AidlTypenames& typenames) const;
 
   // ToString is for dumping AIDL.
@@ -474,6 +523,7 @@
   // This is "direction annotations type name".
   // e.g) "in @utf8InCpp String[] names"
   std::string ToString() const;
+  void Accept(AidlVisitor& vis) const override { vis.VisitArgument(*this); }
 
  private:
   Direction direction_;
@@ -677,6 +727,7 @@
   AidlTypeSpecifier* GetMutableType() { return type_.get(); }
   const string& GetName() const { return name_; }
   const AidlConstantValue& GetValue() const { return *value_; }
+  void Accept(AidlVisitor& vis) const override { vis.VisitConstant(*this); }
   bool CheckValid(const AidlTypenames& typenames) const;
 
   // ToString is for dumping AIDL.
@@ -759,6 +810,8 @@
   // e.g) "foo(int, String)"
   std::string Signature() const;
 
+  void Accept(AidlVisitor& vis) const override { vis.VisitMethod(*this); }
+
  private:
   bool oneway_;
   std::string comments_;
@@ -812,7 +865,8 @@
   virtual const AidlUnionDecl* AsUnionDeclaration() const { return nullptr; }
   virtual const AidlInterface* AsInterface() const { return nullptr; }
   virtual const AidlParameterizable<std::string>* AsParameterizable() const { return nullptr; }
-  virtual bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const;
+  virtual bool CheckValid(const AidlTypenames& typenames) const;
+  virtual void Accept(AidlVisitor& vis) const = 0;
   virtual bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
                                           Options::Language lang) const = 0;
   AidlStructuredParcelable* AsStructuredParcelable() {
@@ -896,7 +950,10 @@
   std::string GetCppHeader() const { return cpp_header_; }
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const override;
+  bool CheckValid(const AidlTypenames& typenames) const override;
+  void Accept(AidlVisitor& vis) const override {
+    if (AsUnstructuredParcelable()) vis.VisitUnstructuredParcelable(*this);
+  }
   bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
                                   Options::Language lang) const override;
   const AidlParcelable* AsParcelable() const override { return this; }
@@ -930,7 +987,8 @@
   void Dump(CodeWriter* writer) const override;
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const override;
+  void Accept(AidlVisitor& vis) const override { vis.VisitStructuredParcelable(*this); }
+  bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
                                   Options::Language lang) const override;
 };
@@ -950,6 +1008,7 @@
   const std::string& GetName() const { return name_; }
   AidlConstantValue* GetValue() const { return value_.get(); }
   const std::string& GetComments() const { return comments_; }
+  void Accept(AidlVisitor& vis) const { vis.VisitEnumerator(*this); }
   bool CheckValid(const AidlTypeSpecifier& enum_backing_type) const;
 
   string ValueString(const AidlTypeSpecifier& backing_type,
@@ -984,7 +1043,8 @@
     return enumerators_;
   }
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const override;
+  void Accept(AidlVisitor& vis) const override { vis.VisitEnum(*this); }
+  bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(const AidlTypenames& /*typenames*/,
                                   Options::Language) const override {
     return true;
@@ -1017,8 +1077,8 @@
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
 
   const AidlNode& AsAidlNode() const override { return *this; }
-
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const override;
+  void Accept(AidlVisitor& vis) const override { vis.VisitUnion(*this); }
+  bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
                                   Options::Language lang) const override;
   std::string GetPreprocessDeclarationName() const override { return "union"; }
@@ -1046,7 +1106,8 @@
   void Dump(CodeWriter* writer) const override;
 
   std::set<AidlAnnotation::Type> GetSupportedAnnotations() const override;
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& context) const override;
+  void Accept(AidlVisitor& vis) const override { vis.VisitInterface(*this); }
+  bool CheckValid(const AidlTypenames& typenames) const override;
   bool LanguageSpecificCheckValid(const AidlTypenames& typenames,
                                   Options::Language lang) const override;
 
@@ -1086,7 +1147,7 @@
   AidlDocument& operator=(const AidlDocument&) = delete;
   AidlDocument& operator=(AidlDocument&&) = delete;
 
-  bool CheckValid(const AidlTypenames& typenames, DiagnosticsContext& diag) const;
+  void Accept(AidlVisitor& vis) const { vis.VisitDocument(*this); }
   std::optional<std::string> ResolveName(const std::string& unresolved_type) const;
   const std::vector<std::unique_ptr<AidlImport>>& Imports() const { return imports_; }
   const std::vector<std::unique_ptr<AidlDefinedType>>& DefinedTypes() const {