juliehockett updated this revision to Diff 140021.
juliehockett added a comment.

Updating to for adjustments to the internal representation & cleaning up 
duplication.


https://reviews.llvm.org/D43667

Files:
  clang-doc/CMakeLists.txt
  clang-doc/Representation.h
  clang-doc/generators/CMakeLists.txt
  clang-doc/generators/Generators.h
  clang-doc/generators/YAMLGenerator.cpp
  clang-doc/tool/CMakeLists.txt
  clang-doc/tool/ClangDocMain.cpp
  test/clang-doc/yaml-comments.cpp
  test/clang-doc/yaml-namespace.cpp
  test/clang-doc/yaml-record.cpp

Index: test/clang-doc/yaml-record.cpp
===================================================================
--- /dev/null
+++ test/clang-doc/yaml-record.cpp
@@ -0,0 +1,212 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/yaml/docs.yaml | FileCheck %s
+
+union A { int X; int Y; };
+
+enum B { X, Y };
+
+enum class Bc { A, B };
+
+struct C { int i; };
+
+class D {};
+
+class E {
+public:
+  E() {}
+  ~E() {}
+
+protected:
+  void ProtectedMethod();
+};
+
+void E::ProtectedMethod() {}
+
+class F : virtual private D, public E {};
+
+class X {
+  class Y {};
+};
+
+void H() {
+  class I {};
+}
+
+// CHECK: ---
+// CHECK-NEXT: Records:         
+// CHECK-NEXT:   - USR:             'ACE81AFA6627B4CEF2B456FB6E1252925674AF7E'
+// CHECK-NEXT:     Name:            'A'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      8
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Union
+// CHECK-NEXT:     Members:         
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'A::X'
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'A::Y'
+// CHECK-NEXT:   - USR:             '06B5F6A19BA9F6A832E127C9968282B94619B210'
+// CHECK-NEXT:     Name:            'C'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      14
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Members:         
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'C::i'
+// CHECK-NEXT:   - USR:             '0921737541208B8FA9BB42B60F78AC1D779AA054'
+// CHECK-NEXT:     Name:            'D'
+// CHECK-NEXT:     Records:         
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             'E3B54702FABFF4037025BA194FC27C47006330B5'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      16
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT:   - USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     Name:            'E'
+// CHECK-NEXT:     Records:         
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             'E3B54702FABFF4037025BA194FC27C47006330B5'
+// CHECK-NEXT:     Functions:       
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             '5093D428CDC62096A67547BA52566E4FB9404EEE'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             '5093D428CDC62096A67547BA52566E4FB9404EEE'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      18
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT:   - USR:             'E3B54702FABFF4037025BA194FC27C47006330B5'
+// CHECK-NEXT:     Name:            'F'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      29
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT:     Parents:         
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     VirtualParents:  
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '0921737541208B8FA9BB42B60F78AC1D779AA054'
+// CHECK-NEXT:   - USR:             'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
+// CHECK-NEXT:     Name:            'X'
+// CHECK-NEXT:     Records:         
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '641AB4A3D36399954ACDE29C7A8833032BF40472'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      31
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT:   - USR:             '641AB4A3D36399954ACDE29C7A8833032BF40472'
+// CHECK-NEXT:     Name:            'Y'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             'CA7C7935730B5EACD25F080E9C83FA087CCDC75E'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      32
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT:   - USR:             '{{.*}}'
+// CHECK-NEXT:     Name:            'I'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      36
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     TagType:         Class
+// CHECK-NEXT: Functions:       
+// CHECK-NEXT:   - USR:             'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4'
+// CHECK-NEXT:     Name:            'E'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      20
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     IsMethod:        true
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:       Type:            Record
+// CHECK-NEXT:       USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT:   - USR:             'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17'
+// CHECK-NEXT:     Name:            '~E'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      21
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     IsMethod:        true
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:       Type:            Record
+// CHECK-NEXT:       USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT:   - USR:             '5093D428CDC62096A67547BA52566E4FB9404EEE'
+// CHECK-NEXT:     Name:            'ProtectedMethod'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      27
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Location:        
+// CHECK-NEXT:       - LineNumber:      24
+// CHECK-NEXT:         Filename:        '{{.*}}'
+// CHECK-NEXT:     IsMethod:        true
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:       Type:            Record
+// CHECK-NEXT:       USR:             '289584A8E0FF4178A794622A547AA622503967A1'
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT:   - USR:             'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E'
+// CHECK-NEXT:     Name:            'H'
+// CHECK-NEXT:     Records:         
+// CHECK-NEXT:       - Type:            Record
+// CHECK-NEXT:         USR:             '{{.*}}'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      35
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT: Enums:           
+// CHECK-NEXT:   - USR:             'FC07BD34D5E77782C263FA944447929EA8753740'
+// CHECK-NEXT:     Name:            'B'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      10
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Members:         
+// CHECK-NEXT:       - 'X'
+// CHECK-NEXT:       - 'Y'
+// CHECK-NEXT:   - USR:             '1E3438A08BA22025C0B46289FF0686F92C8924C5'
+// CHECK-NEXT:     Name:            'Bc'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      12
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Scoped:          true
+// CHECK-NEXT:     Members:         
+// CHECK-NEXT:       - 'A'
+// CHECK-NEXT:       - 'B'
+// CHECK-NEXT: ...
Index: test/clang-doc/yaml-namespace.cpp
===================================================================
--- /dev/null
+++ test/clang-doc/yaml-namespace.cpp
@@ -0,0 +1,100 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/yaml/docs.yaml | FileCheck %s
+
+namespace A {
+
+void f();
+
+}  // namespace A
+
+namespace A {
+
+void f(){};
+
+namespace B {
+
+enum E { X };
+
+E func(int i) { return X; }
+
+}  // namespace B
+}  // namespace A
+
+// CHECK: ---
+// CHECK-NEXT: Namespaces:      
+// CHECK-NEXT:   - USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-NEXT:     Name:            'A'
+// CHECK-NEXT:     Namespaces:      
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-NEXT:     Functions:       
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC'
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             '9A82CB33ED0FDF81EE383D31CD0957D153C5E840'
+// CHECK-NEXT:     Enums:           
+// CHECK-NEXT:       - Type:            Enum
+// CHECK-NEXT:         USR:             'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775'
+// CHECK-NEXT:   - USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-NEXT:     Name:            'B'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-NEXT:     Functions:       
+// CHECK-NEXT:       - Type:            Function
+// CHECK-NEXT:         USR:             '9A82CB33ED0FDF81EE383D31CD0957D153C5E840'
+// CHECK-NEXT:     Enums:           
+// CHECK-NEXT:       - Type:            Enum
+// CHECK-NEXT:         USR:             'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775'
+// CHECK-NEXT: Functions:       
+// CHECK-NEXT:   - USR:             '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC'
+// CHECK-NEXT:     Name:            'f'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      16
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Location:        
+// CHECK-NEXT:       - LineNumber:      10
+// CHECK-NEXT:         Filename:        '{{.*}}'
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT:   - USR:             '9A82CB33ED0FDF81EE383D31CD0957D153C5E840'
+// CHECK-NEXT:     Name:            'func'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      22
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:     Params:          
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'i'
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'enum A::B::E'
+// CHECK-NEXT: Enums:           
+// CHECK-NEXT:   - USR:             'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775'
+// CHECK-NEXT:     Name:            'E'
+// CHECK-NEXT:     Namespace:       
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5'
+// CHECK-NEXT:       - Type:            Namespace
+// CHECK-NEXT:         USR:             '8D042EFFC98B373450BC6B5B90A330C25A150E9C'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      20
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Members:         
+// CHECK-NEXT:       - 'X'
+// CHECK-NEXT: ...
Index: test/clang-doc/yaml-comments.cpp
===================================================================
--- /dev/null
+++ test/clang-doc/yaml-comments.cpp
@@ -0,0 +1,129 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc -doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/yaml/docs.yaml | FileCheck %s
+
+/// \brief Brief description.
+///
+/// Extended description that
+/// continues onto the next line.
+/// 
+/// <ul class="test">
+///   <li> Testing.
+/// </ul>
+///
+/// \verbatim
+/// The description continues.
+/// \endverbatim
+///
+/// \param [out] I is a parameter.
+/// \param J is a parameter.
+/// \return void
+void F(int I, int J);
+
+/// Bonus comment on definition
+void F(int I, int J) {}
+
+// CHECK: ---
+// CHECK-NEXT: Functions:       
+// CHECK-NEXT:   - USR:             '7574630614A535710E5A6ABCFFF98BCA2D06A4CA'
+// CHECK-NEXT:     Name:            'F'
+// CHECK-NEXT:     Description:     
+// CHECK-NEXT:       - Children:        
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:           - Kind:            'BlockCommandComment'
+// CHECK-NEXT:             Name:            'brief'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'ParagraphComment'
+// CHECK-NEXT:                 Children:        
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:                     Text:            ' Brief description.'
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:                 Text:            ' Extended description that'
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:                 Text:            ' continues onto the next line.'
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:               - Kind:            'HTMLStartTagComment'
+// CHECK-NEXT:                 Name:            'ul'
+// CHECK-NEXT:                 AttrKeys:        
+// CHECK-NEXT:                   - 'class'
+// CHECK-NEXT:                 AttrValues:      
+// CHECK-NEXT:                   - 'test'
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:               - Kind:            'HTMLStartTagComment'
+// CHECK-NEXT:                 Name:            'li'
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:                 Text:            ' Testing.'
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:               - Kind:            'HTMLEndTagComment'
+// CHECK-NEXT:                 Name:            'ul'
+// CHECK-NEXT:                 SelfClosing:     true
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:           - Kind:            'VerbatimBlockComment'
+// CHECK-NEXT:             Name:            'verbatim'
+// CHECK-NEXT:             CloseName:       'endverbatim'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'VerbatimBlockLineComment'
+// CHECK-NEXT:                 Text:            ' The description continues.'
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:           - Kind:            'ParamCommandComment'
+// CHECK-NEXT:             Direction:       '[out]'
+// CHECK-NEXT:             ParamName:       'I'
+// CHECK-NEXT:             Explicit:        true
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'ParagraphComment'
+// CHECK-NEXT:                 Children:        
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:                     Text:            ' is a parameter.'
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:           - Kind:            'ParamCommandComment'
+// CHECK-NEXT:             Direction:       '[in]'
+// CHECK-NEXT:             ParamName:       'J'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'ParagraphComment'
+// CHECK-NEXT:                 Children:        
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:                     Text:            ' is a parameter.'
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:           - Kind:            'BlockCommandComment'
+// CHECK-NEXT:             Name:            'return'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'ParagraphComment'
+// CHECK-NEXT:                 Children:        
+// CHECK-NEXT:                   - Kind:            'TextComment'
+// CHECK-NEXT:                     Text:            ' void'
+// CHECK-NEXT:       - Children:        
+// CHECK-NEXT:           - Kind:            'ParagraphComment'
+// CHECK-NEXT:             Children:        
+// CHECK-NEXT:               - Kind:            'TextComment'
+// CHECK-NEXT:                 Text:            ' Bonus comment on definition'
+// CHECK-NEXT:     DefLocation:     
+// CHECK-NEXT:       LineNumber:      27
+// CHECK-NEXT:       Filename:        '{{.*}}'
+// CHECK-NEXT:     Location:        
+// CHECK-NEXT:       - LineNumber:      24
+// CHECK-NEXT:         Filename:        '{{.*}}'
+// CHECK-NEXT:     Parent:          
+// CHECK-NEXT:     Params:          
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'I'
+// CHECK-NEXT:       - Type:            
+// CHECK-NEXT:           UnresolvedName:  'int'
+// CHECK-NEXT:         Name:            'J'
+// CHECK-NEXT:     ReturnType:      
+// CHECK-NEXT:       Type:            
+// CHECK-NEXT:         UnresolvedName:  'void'
+// CHECK-NEXT: ...
Index: clang-doc/tool/ClangDocMain.cpp
===================================================================
--- clang-doc/tool/ClangDocMain.cpp
+++ clang-doc/tool/ClangDocMain.cpp
@@ -21,6 +21,7 @@
 #include "BitcodeWriter.h"
 #include "ClangDoc.h"
 #include "Reducer.h"
+#include "generators/Generators.h"
 #include "clang/AST/AST.h"
 #include "clang/AST/Decl.h"
 #include "clang/ASTMatchers/ASTMatchFinder.h"
@@ -61,23 +62,43 @@
                llvm::cl::desc("Dump intermediate results to bitcode file."),
                llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
 
+static llvm::cl::opt<std::string> Format(
+    "format",
+    llvm::cl::desc("Format for outputted docs (Current options are yaml)."),
+    llvm::cl::init("yaml"), llvm::cl::cat(ClangDocCategory));
+
 static llvm::cl::opt<bool> DoxygenOnly(
     "doxygen",
     llvm::cl::desc("Use only doxygen-style comments to generate docs."),
     llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
 
-bool DumpResultToFile(const Twine &DirName, const Twine &FileName,
-                      StringRef Buffer) {
+bool CreateDirectory(const Twine &DirName, bool ClearDirectory = false) {
   std::error_code OK;
-  SmallString<128> IRRootPath;
-  llvm::sys::path::native(OutDirectory, IRRootPath);
-  llvm::sys::path::append(IRRootPath, DirName);
-  std::error_code DirectoryStatus =
-      llvm::sys::fs::create_directories(IRRootPath);
+  llvm::SmallString<128> DocsRootPath;
+  if (ClearDirectory) {
+    std::error_code RemoveStatus = llvm::sys::fs::remove_directories(DirName);
+    if (RemoveStatus != OK) {
+      llvm::errs() << "Unable to remove existing documentation directory for "
+                   << DirName << ".\n";
+      return true;
+    }
+  }
+  std::error_code DirectoryStatus = llvm::sys::fs::create_directories(DirName);
   if (DirectoryStatus != OK) {
     llvm::errs() << "Unable to create documentation directories.\n";
     return true;
   }
+  return false;
+}
+
+bool DumpResultToFile(const Twine &DirName, const Twine &FileName,
+                      StringRef Buffer, bool ClearDirectory = false) {
+  std::error_code OK;
+  llvm::SmallString<128> IRRootPath;
+  llvm::sys::path::native(OutDirectory, IRRootPath);
+  llvm::sys::path::append(IRRootPath, DirName);
+  if (CreateDirectory(IRRootPath, ClearDirectory))
+    return true;
   llvm::sys::path::append(IRRootPath, FileName);
   std::error_code OutErrorInfo;
   llvm::raw_fd_ostream OS(IRRootPath, OutErrorInfo, llvm::sys::fs::F_None);
@@ -122,7 +143,8 @@
         [&](StringRef Key, StringRef Value) {
           Err = DumpResultToFile("bc", Key + ".bc", Value);
         });
-    if (Err) return 1;
+    if (Err)
+      return 1;
   }
 
   // Reducing phase
@@ -135,13 +157,24 @@
 
   if (DumpResult) {
     llvm::outs() << "Writing intermediate results...\n";
-    SmallString<4096> Buffer;
+    llvm::SmallString<4096> Buffer;
     llvm::BitstreamWriter Stream(Buffer);
     doc::ClangDocBitcodeWriter Writer(Stream);
     Writer.emitInfoSet(*Infos);
-    if (DumpResultToFile("bc", "docs.bc", Buffer))
+    if (DumpResultToFile("bc", "docs.bc", Buffer, /*ClearDirectory=*/true))
       return 1;
   }
 
-  return 0;
+  // Documentation generation
+  llvm::outs() << "Generating docs...\n";
+  llvm::SmallString<128> DocsRootPath;
+  llvm::sys::path::native(OutDirectory, DocsRootPath);
+  llvm::sys::path::append(DocsRootPath, Format);
+  if (CreateDirectory(DocsRootPath))
+    return 1;
+  std::unique_ptr<doc::Generator> G =
+      doc::GeneratorFactory::create(Infos, DocsRootPath, Format);
+  if (!G)
+    return 1;
+  return G->generate();
 }
Index: clang-doc/tool/CMakeLists.txt
===================================================================
--- clang-doc/tool/CMakeLists.txt
+++ clang-doc/tool/CMakeLists.txt
@@ -11,7 +11,8 @@
   clangBasic
   clangFrontend
   clangDoc
+  clangDocGenerators
   clangTooling
   clangToolingCore
   )
   
\ No newline at end of file
Index: clang-doc/generators/YAMLGenerator.cpp
===================================================================
--- /dev/null
+++ clang-doc/generators/YAMLGenerator.cpp
@@ -0,0 +1,265 @@
+//===--  ClangDocYAML.h - ClangDoc YAML -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANG_DOC_YAML_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANG_DOC_YAML_H
+
+#include "Generators.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/Path.h"
+#include "llvm/Support/YAMLTraits.h"
+#include "llvm/Support/raw_ostream.h"
+
+using namespace clang::doc;
+
+LLVM_YAML_IS_SEQUENCE_VECTOR(TypeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FieldTypeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(MemberTypeInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(NamespaceInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(RecordInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(EnumInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(FunctionInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(Reference)
+LLVM_YAML_IS_SEQUENCE_VECTOR(Location)
+LLVM_YAML_IS_SEQUENCE_VECTOR(CommentInfo)
+LLVM_YAML_IS_SEQUENCE_VECTOR(std::unique_ptr<CommentInfo>)
+LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>)
+
+namespace llvm {
+namespace yaml {
+
+// Enumerations to YAML output.
+
+template <> struct ScalarEnumerationTraits<clang::AccessSpecifier> {
+  static void enumeration(IO &IO, clang::AccessSpecifier &Value) {
+    IO.enumCase(Value, "Public", clang::AccessSpecifier::AS_public);
+    IO.enumCase(Value, "Protected", clang::AccessSpecifier::AS_protected);
+    IO.enumCase(Value, "Private", clang::AccessSpecifier::AS_private);
+    IO.enumCase(Value, "None", clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<clang::TagTypeKind> {
+  static void enumeration(IO &IO, clang::TagTypeKind &Value) {
+    IO.enumCase(Value, "Struct", clang::TagTypeKind::TTK_Struct);
+    IO.enumCase(Value, "Interface", clang::TagTypeKind::TTK_Interface);
+    IO.enumCase(Value, "Union", clang::TagTypeKind::TTK_Union);
+    IO.enumCase(Value, "Class", clang::TagTypeKind::TTK_Class);
+    IO.enumCase(Value, "Enum", clang::TagTypeKind::TTK_Enum);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<InfoType> {
+  static void enumeration(IO &IO, InfoType &Value) {
+    IO.enumCase(Value, "Namespace", InfoType::IT_namespace);
+    IO.enumCase(Value, "Record", InfoType::IT_record);
+    IO.enumCase(Value, "Function", InfoType::IT_function);
+    IO.enumCase(Value, "Enum", InfoType::IT_enum);
+    IO.enumCase(Value, "Default", InfoType::IT_default);
+  }
+};
+
+template <> struct ScalarEnumerationTraits<TypeInfoType> {
+  static void enumeration(IO &IO, TypeInfoType &Value) {
+    IO.enumCase(Value, "Namespace", TypeInfoType::TT_type);
+    IO.enumCase(Value, "Record", TypeInfoType::TT_field_type);
+    IO.enumCase(Value, "Function", TypeInfoType::TT_member_type);
+  }
+};
+
+// Scalars to YAML output.
+template <unsigned U> struct ScalarTraits<SmallString<U>> {
+  static void output(const SmallString<U> &S, void *, llvm::raw_ostream &OS) {
+    for (const auto &C : S)
+      OS << C;
+  }
+  static StringRef input(StringRef Scalar, void *, SmallString<U> &Value) {
+    Value.assign(Scalar.begin(), Scalar.end());
+    return StringRef();
+  }
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+template <> struct ScalarTraits<std::array<unsigned char, 20>> {
+  static void output(const std::array<unsigned char, 20> &S, void *,
+                     llvm::raw_ostream &OS) {
+    OS << toHex(toStringRef(S));
+  }
+  static StringRef input(StringRef Scalar, void *,
+                         std::array<unsigned char, 20> &Value) {
+    assert(Scalar.size() == 40);
+    Value = StringToSymbol(Scalar);
+    return StringRef();
+  }
+  static QuotingType mustQuote(StringRef) { return QuotingType::Single; }
+};
+
+// Helper functions to map infos to YAML.
+
+static void TypeInfoMapping(IO &IO, TypeInfo &I) {
+  IO.mapOptional("Type", I.Type, Reference());
+}
+
+static void FieldTypeInfoMapping(IO &IO, FieldTypeInfo &I) {
+  TypeInfoMapping(IO, I);
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+}
+
+static void InfoMapping(IO &IO, Info &I) {
+  IO.mapRequired("USR", I.USR);
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+  IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector<Reference, 4>());
+  IO.mapOptional("Description", I.Description);
+  IO.mapOptional("Namespaces", I.Namespaces, llvm::SmallVector<Reference, 4>());
+  IO.mapOptional("Records", I.Records, llvm::SmallVector<Reference, 4>());
+  IO.mapOptional("Functions", I.Functions, llvm::SmallVector<Reference, 4>());
+  IO.mapOptional("Enums", I.Enums, llvm::SmallVector<Reference, 4>());
+}
+
+static void SymbolInfoMapping(IO &IO, SymbolInfo &I) {
+  InfoMapping(IO, I);
+  IO.mapOptional("DefLocation", I.DefLoc, Optional<Location>());
+  IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
+}
+
+static void CommentInfoMapping(IO &IO, CommentInfo &I) {
+  IO.mapOptional("Kind", I.Kind, SmallString<16>());
+  IO.mapOptional("Text", I.Text, SmallString<64>());
+  IO.mapOptional("Name", I.Name, SmallString<16>());
+  IO.mapOptional("Direction", I.Direction, SmallString<8>());
+  IO.mapOptional("ParamName", I.ParamName, SmallString<16>());
+  IO.mapOptional("CloseName", I.CloseName, SmallString<16>());
+  IO.mapOptional("SelfClosing", I.SelfClosing, false);
+  IO.mapOptional("Explicit", I.Explicit, false);
+  IO.mapOptional("Args", I.Args, llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("AttrKeys", I.AttrKeys,
+                 llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("AttrValues", I.AttrValues,
+                 llvm::SmallVector<SmallString<16>, 4>());
+  IO.mapOptional("Children", I.Children);
+}
+
+// Template specialization to YAML traits for Infos.
+
+template <> struct MappingTraits<Location> {
+  static void mapping(IO &IO, Location &Loc) {
+    IO.mapOptional("LineNumber", Loc.LineNumber, 0);
+    IO.mapOptional("Filename", Loc.Filename, SmallString<32>());
+  }
+};
+
+template <> struct MappingTraits<Reference> {
+  static void mapping(IO &IO, Reference &Ref) {
+    IO.mapOptional("Type", Ref.RefType, InfoType::IT_default);
+    if (Ref.RefType == InfoType::IT_default)
+      IO.mapOptional("UnresolvedName", Ref.UnresolvedName, SmallString<16>());
+    else
+      IO.mapOptional("USR", Ref.USR, SymbolID{});
+  }
+};
+
+template <> struct MappingTraits<TypeInfo> {
+  static void mapping(IO &IO, TypeInfo &I) { TypeInfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<FieldTypeInfo> {
+  static void mapping(IO &IO, FieldTypeInfo &I) {
+    TypeInfoMapping(IO, I);
+    IO.mapOptional("Name", I.Name, SmallString<16>());
+  }
+};
+
+template <> struct MappingTraits<MemberTypeInfo> {
+  static void mapping(IO &IO, MemberTypeInfo &I) {
+    FieldTypeInfoMapping(IO, I);
+    IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct MappingTraits<NamespaceInfo> {
+  static void mapping(IO &IO, NamespaceInfo &I) { InfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<RecordInfo> {
+  static void mapping(IO &IO, RecordInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct);
+    IO.mapOptional("Members", I.Members);
+    IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
+    IO.mapOptional("VirtualParents", I.VirtualParents,
+                   llvm::SmallVector<Reference, 4>());
+  }
+};
+
+template <> struct MappingTraits<EnumInfo> {
+  static void mapping(IO &IO, EnumInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("Scoped", I.Scoped, false);
+    IO.mapOptional("Members", I.Members);
+  }
+};
+
+template <> struct MappingTraits<FunctionInfo> {
+  static void mapping(IO &IO, FunctionInfo &I) {
+    SymbolInfoMapping(IO, I);
+    IO.mapOptional("IsMethod", I.IsMethod, false);
+    IO.mapOptional("Parent", I.Parent, Reference());
+    IO.mapOptional("Params", I.Params);
+    IO.mapOptional("ReturnType", I.ReturnType);
+    IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none);
+  }
+};
+
+template <> struct MappingTraits<CommentInfo> {
+  static void mapping(IO &IO, CommentInfo &I) { CommentInfoMapping(IO, I); }
+};
+
+template <> struct MappingTraits<std::unique_ptr<CommentInfo>> {
+  static void mapping(IO &IO, std::unique_ptr<CommentInfo> &I) {
+    CommentInfoMapping(IO, *I);
+  }
+};
+
+template <> struct MappingTraits<InfoSet> {
+  static void mapping(IO &IO, InfoSet &IS) {
+    IO.mapOptional("Namespaces", IS.getNamespaceInfos());
+    IO.mapOptional("Records", IS.getRecordInfos());
+    IO.mapOptional("Functions", IS.getFunctionInfos());
+    IO.mapOptional("Enums", IS.getEnumInfos());
+  }
+};
+
+} // end namespace yaml
+} // end namespace llvm
+
+namespace clang {
+namespace doc {
+
+int YAMLGenerator::generate() {
+  std::error_code OK;
+  llvm::SmallString<128> Path;
+  llvm::sys::path::native(Root, Path);
+  llvm::sys::path::append(Path, "docs.yaml");
+  std::error_code OutErrorInfo;
+  llvm::raw_fd_ostream OS(Path, OutErrorInfo, llvm::sys::fs::F_None);
+  if (OutErrorInfo != OK) {
+    llvm::errs() << "Error opening yaml file.\n";
+    return 1;
+  }
+
+  llvm::yaml::Output Output(OS);
+  Output << *IS;
+  OS.close();
+  return 0;
+}
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_CLANG_DOC_YAML_H
Index: clang-doc/generators/Generators.h
===================================================================
--- /dev/null
+++ clang-doc/generators/Generators.h
@@ -0,0 +1,65 @@
+//===-- Generators.h - ClangDoc Generator ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
+#define LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
+
+#include "../Representation.h"
+#include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/Support/FileSystem.h"
+#include "llvm/Support/raw_ostream.h"
+#include <string>
+
+namespace clang {
+namespace doc {
+
+class Generator {
+public:
+  Generator(std::unique_ptr<InfoSet> &IS, llvm::StringRef Root,
+            llvm::StringRef Format)
+      : IS(IS), Root(Root), Format(Format) {}
+  virtual ~Generator() = default;
+
+  virtual int generate() = 0;
+
+protected:
+  std::unique_ptr<InfoSet> &IS;
+  std::string Root;
+  std::string Format;
+};
+
+class YAMLGenerator : public Generator {
+public:
+  YAMLGenerator(std::unique_ptr<InfoSet> &IS, llvm::StringRef Root,
+                llvm::StringRef Format)
+      : Generator(IS, Root, Format) {}
+  virtual ~YAMLGenerator() = default;
+
+  int generate() override;
+};
+
+class GeneratorFactory {
+public:
+  static std::unique_ptr<Generator> create(std::unique_ptr<InfoSet> &IS,
+                                           llvm::StringRef Root,
+                                           llvm::StringRef Format) {
+    if (Format == "yaml")
+      return llvm::make_unique<YAMLGenerator>(IS, Root, Format);
+
+    llvm::errs() << "Unsupported documentation format.\n";
+    return nullptr;
+  }
+};
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H
Index: clang-doc/generators/CMakeLists.txt
===================================================================
--- /dev/null
+++ clang-doc/generators/CMakeLists.txt
@@ -0,0 +1,8 @@
+set(LLVM_LINK_COMPONENTS support)
+
+add_clang_library(clangDocGenerators
+  YAMLGenerator.cpp
+
+  LINK_LIBS
+  clangDoc
+  )
Index: clang-doc/Representation.h
===================================================================
--- clang-doc/Representation.h
+++ clang-doc/Representation.h
@@ -84,6 +84,9 @@
   Reference() = default;
   Reference(llvm::StringRef Name) : UnresolvedName(Name) {}
   Reference(SymbolID USR, InfoType IT) : USR(USR), RefType(IT) {}
+  bool operator==(const Reference &Other) const {
+    return USR == Other.USR && RefType == Other.RefType;
+  }
 
   SymbolID USR;                   // Unique identifer for referenced decl
   SmallString<16> UnresolvedName; // Name of unresolved type.
@@ -98,6 +101,7 @@
   TypeInfo() = default;
   TypeInfo(SymbolID &Type, InfoType IT) : Type(Type, IT) {}
   TypeInfo(llvm::StringRef RefName) : Type(RefName) {}
+  bool operator==(const TypeInfo &Other) const { return Type == Other.Type; }
 
   Reference Type; // Referenced type in this info.
 };
@@ -131,6 +135,9 @@
   Location() = default;
   Location(int LineNumber, SmallString<16> Filename)
       : LineNumber(LineNumber), Filename(std::move(Filename)) {}
+  bool operator==(const Location &Other) const {
+    return LineNumber == Other.LineNumber && Filename == Other.Filename;
+  }
 
   int LineNumber;           // Line number of this Location.
   SmallString<32> Filename; // File for this Location.
@@ -228,6 +235,12 @@
   const std::vector<RecordInfo> &getRecordInfos() const { return RecordInfos; }
   const std::vector<EnumInfo> &getEnumInfos() const { return EnumInfos; }
 
+  // Non-const accessors for YAML output.
+  std::vector<NamespaceInfo> &getNamespaceInfos() { return NamespaceInfos; }
+  std::vector<FunctionInfo> &getFunctionInfos() { return FunctionInfos; }
+  std::vector<RecordInfo> &getRecordInfos() { return RecordInfos; }
+  std::vector<EnumInfo> &getEnumInfos() { return EnumInfos; }
+
 private:
   void resolveReferences(llvm::SmallVectorImpl<Reference> &References,
                          Reference &Caller);
Index: clang-doc/CMakeLists.txt
===================================================================
--- clang-doc/CMakeLists.txt
+++ clang-doc/CMakeLists.txt
@@ -23,4 +23,5 @@
   clangToolingCore
   )
 
+add_subdirectory(generators)
 add_subdirectory(tool)
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to