juliehockett updated this revision to Diff 147606.
juliehockett marked 11 inline comments as done.
juliehockett edited the summary of this revision.
juliehockett added a comment.

Updating for better integration with MR framework, the generator now takes in 
an info and an output stream and emits the YAML to that stream. Each info is 
emitted to its own YAML file.


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