anniecherk updated this revision to Diff 153597.
anniecherk added a comment.
Herald added a subscriber: eraman.

- addressed Julie's comments
- updated logic to consider both access specifier & linkage
- added tests for each type of linkage


https://reviews.llvm.org/D48395

Files:
  clang-tools-extra/clang-doc/ClangDoc.cpp
  clang-tools-extra/clang-doc/ClangDoc.h
  clang-tools-extra/clang-doc/Mapper.cpp
  clang-tools-extra/clang-doc/Mapper.h
  clang-tools-extra/clang-doc/Serialize.cpp
  clang-tools-extra/clang-doc/Serialize.h
  clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
  clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-excluded.cpp
  clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-included.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonInlineFunction.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonStaticFunction.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonclass.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonfunction.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-classPrivate.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-functionInnerClass.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-namespace-private.cpp
  
clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-static.cpp
  clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-included.cpp
  clang-tools-extra/test/clang-doc/yaml-module.cpp

Index: clang-tools-extra/test/clang-doc/yaml-module.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/yaml-module.cpp
@@ -0,0 +1,63 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/moduleFunction.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs/staticModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-B
+// RUN: cat %t/docs/exportedModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-C
+
+export module M;
+
+int moduleFunction(int x); //ModuleLinkage
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             '4429AA8706EF483A44B1DCE2D956BF0FEF82A9B7'
+// CHECK-A-NEXT: Name:            'moduleFunction'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      12
+// CHECK-A-NEXT:     Filename:        'test'
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'int'
+// CHECK-A-NEXT: ...
+
+
+static int staticModuleFunction(int x); //ModuleInternalLinkage
+// CHECK-B: ---
+// CHECK-B-NEXT: USR:             '2E49675BF9D3FCCF51D5AA5EA02C280D894C1E4C'
+// CHECK-B-NEXT: Name:            'staticModuleFunction'
+// CHECK-B-NEXT: Location:
+// CHECK-B-NEXT:   - LineNumber:      29
+// CHECK-B-NEXT:     Filename:        'test'
+// CHECK-B-NEXT: Params:
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'int'
+// CHECK-B-NEXT:     Name:            'x'
+// CHECK-B-NEXT: ReturnType:
+// CHECK-B-NEXT:   Type:
+// CHECK-B-NEXT:     Name:            'int'
+// CHECK-B-NEXT: ...
+
+
+export double exportedModuleFunction(double y, int z); //ExternalLinkage
+// CHECK-C: ---
+// CHECK-C-NEXT: USR:             '325C328D4EB158CCBA4DF2B5321F63EB39C2B17C'
+// CHECK-C-NEXT: Name:            'exportedModuleFunction'
+// CHECK-C-NEXT: Location:
+// CHECK-C-NEXT:   - LineNumber:      46
+// CHECK-C-NEXT:     Filename:        'test'
+// CHECK-C-NEXT: Params:
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'double'
+// CHECK-C-NEXT:     Name:            'y'
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'int'
+// CHECK-C-NEXT:     Name:            'z'
+// CHECK-C-NEXT: ReturnType:
+// CHECK-C-NEXT:   Type:
+// CHECK-C-NEXT:     Name:            'double'
+// CHECK-C-NEXT: ...
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-included.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-included.cpp
@@ -0,0 +1,311 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/function.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs/inlinedFunction.yaml | FileCheck %s --check-prefix=CHECK-B
+// RUN: cat %t/docs/functionWithInnerClass.yaml | FileCheck %s --check-prefix=CHECK-C
+// RUN: cat %t/docs/inlinedFunctionWithInnerClass.yaml | FileCheck %s --check-prefix=CHECK-D
+// RUN: cat %t/docs/Class/publicMethod.yaml| FileCheck %s --check-prefix=CHECK-E
+// RUN: cat %t/docs/Class.yaml| FileCheck %s --check-prefix=CHECK-F
+// RUN: cat %t/docs/Class/protectedMethod.yaml| FileCheck %s --check-prefix=CHECK-G
+// RUN: cat %t/docs/named.yaml| FileCheck %s --check-prefix=CHECK-H
+// RUN: cat %t/docs/named/NamedClass.yaml| FileCheck %s --check-prefix=CHECK-I
+// RUN: cat %t/docs/named/namedFunction.yaml| FileCheck %s --check-prefix=CHECK-J
+// RUN: cat %t/docs/named/namedInlineFunction.yaml| FileCheck %s --check-prefix=CHECK-K
+// RUN: cat %t/docs/named/NamedClass/namedPublicMethod.yaml| FileCheck %s --check-prefix=CHECK-L
+// RUN: cat %t/docs/named/NamedClass/namedProtectedMethod.yaml| FileCheck %s --check-prefix=CHECK-M
+
+
+
+void function(int x);
+
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             'E789672E987C6FCE95B1BB760CB9A6998C4584A9'
+// CHECK-A-NEXT: Name:            'function'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      22
+// CHECK-A-NEXT:     Filename:        'test'
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'void'
+// CHECK-A-NEXT: ...
+
+
+
+
+inline int inlinedFunction(int x);
+
+// CHECK-B: ---
+// CHECK-B-NEXT: USR:             '9BDA332A65B254CC1F5FF736E8815A1CD3668A87'
+// CHECK-B-NEXT: Name:            'inlinedFunction'
+// CHECK-B-NEXT: Location:
+// CHECK-B-NEXT:   - LineNumber:      42
+// CHECK-B-NEXT:     Filename:        'test'
+// CHECK-B-NEXT: Params:
+// CHECK-B-NEXT:   - Type:
+// CHECK-B-NEXT:       Name:            'int'
+// CHECK-B-NEXT:     Name:            'x'
+// CHECK-B-NEXT: ReturnType:
+// CHECK-B-NEXT:   Type:
+// CHECK-B-NEXT:     Name:            'int'
+// CHECK-B-NEXT: ...
+
+
+
+int functionWithInnerClass(int x){
+    class InnerClass { //NoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+
+// CHECK-C: ---
+// CHECK-C-NEXT: USR:             'D7C0B43D134C4D904A64AB58AD050312E0F52B42'
+// CHECK-C-NEXT: Name:            'functionWithInnerClass'
+// CHECK-C-NEXT: DefLocation:
+// CHECK-C-NEXT:   LineNumber:      61
+// CHECK-C-NEXT:   Filename:        'test'
+// CHECK-C-NEXT: Params:
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'int'
+// CHECK-C-NEXT:     Name:            'x'
+// CHECK-C-NEXT: ReturnType:
+// CHECK-C-NEXT:   Type:
+// CHECK-C-NEXT:     Name:            'int'
+// CHECK-C-NEXT: ...
+
+
+
+
+inline int inlinedFunctionWithInnerClass(int x){
+    class InnerClass { //VisibleNoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+
+// CHECK-D: ---
+// CHECK-D-NEXT: USR:             '346651FA23D83A0D6F839127E52857EBF59ABB80'
+// CHECK-D-NEXT: Name:            'inlinedFunctionWithInnerClass'
+// CHECK-D-NEXT: DefLocation:
+// CHECK-D-NEXT:   LineNumber:      88
+// CHECK-D-NEXT:   Filename:        'test'
+// CHECK-D-NEXT: Params:
+// CHECK-D-NEXT:   - Type:
+// CHECK-D-NEXT:       Name:            'int'
+// CHECK-D-NEXT:     Name:            'x'
+// CHECK-D-NEXT: ReturnType:
+// CHECK-D-NEXT:   Type:
+// CHECK-D-NEXT:     Name:            'int'
+// CHECK-D-NEXT: ...
+
+
+
+
+
+class Class {
+ public:
+  void publicMethod();
+  int  publicField;
+ protected:
+  void protectedMethod();
+  int  protectedField;
+ private:
+  void privateMethod();
+  int  privateField;
+};
+
+
+// CHECK-E: ---
+// CHECK-E-NEXT: USR:             '05682AF6307337176313391E00A231C2C55A4972'
+// CHECK-E-NEXT: Name:            'publicMethod'
+// CHECK-E-NEXT: Namespace:
+// CHECK-E-NEXT:   - Type:            Record
+// CHECK-E-NEXT:     Name:            'Class'
+// CHECK-E-NEXT:     USR:             '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45'
+// CHECK-E-NEXT: Location:
+// CHECK-E-NEXT:   - LineNumber:      118
+// CHECK-E-NEXT:     Filename:        'test'
+// CHECK-E-NEXT: IsMethod:        true
+// CHECK-E-NEXT: Parent:
+// CHECK-E-NEXT:   Type:            Record
+// CHECK-E-NEXT:   Name:            'Class'
+// CHECK-E-NEXT:   USR:             '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45'
+// CHECK-E-NEXT: ReturnType:
+// CHECK-E-NEXT:   Type:
+// CHECK-E-NEXT:     Name:            'void'
+// CHECK-E-NEXT: ...
+
+
+// CHECK-F: ---
+// CHECK-F-NEXT: USR:             '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45'
+// CHECK-F-NEXT: Name:            'Class'
+// CHECK-F-NEXT: DefLocation:
+// CHECK-F-NEXT:   LineNumber:      116
+// CHECK-F-NEXT:   Filename:        'test'
+// CHECK-F-NEXT: TagType:         Class
+// CHECK-F-NEXT: Members:
+// CHECK-F-NEXT:   - Type:
+// CHECK-F-NEXT:       Name:            'int'
+// CHECK-F-NEXT:     Name:            'publicField'
+// CHECK-F-NEXT:   - Type:
+// CHECK-F-NEXT:       Name:            'int'
+// CHECK-F-NEXT:     Name:            'protectedField'
+// CHECK-F-NEXT:     Access:          Protected
+// CHECK-F-NEXT: ...
+
+
+
+// CHECK-G: ---
+// CHECK-G-NEXT: USR:             'F0D4F94A85D4BDF4212D4F782D3F5768C84D3869'
+// CHECK-G-NEXT: Name:            'protectedMethod'
+// CHECK-G-NEXT: Namespace:
+// CHECK-G-NEXT:   - Type:            Record
+// CHECK-G-NEXT:     Name:            'Class'
+// CHECK-G-NEXT:     USR:             '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45'
+// CHECK-G-NEXT: Location:
+// CHECK-G-NEXT:   - LineNumber:      121
+// CHECK-G-NEXT:     Filename:        'test'
+// CHECK-G-NEXT: IsMethod:        true
+// CHECK-G-NEXT: Parent:
+// CHECK-G-NEXT:   Type:            Record
+// CHECK-G-NEXT:   Name:            'Class'
+// CHECK-G-NEXT:   USR:             '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45'
+// CHECK-G-NEXT: ReturnType:
+// CHECK-G-NEXT:   Type:
+// CHECK-G-NEXT:     Name:            'void'
+// CHECK-G-NEXT: ...
+
+
+namespace named{
+    class NamedClass {
+     public:
+      void namedPublicMethod();
+      int  namedPublicField;
+     protected:
+      void namedProtectedMethod();
+      int  namedProtectedField;
+     private:
+      void namedPrivateMethod();
+      int  namedPrivateField;
+    };
+
+    void namedFunction();
+    static void namedStaticFunction();
+    inline void namedInlineFunction();
+}
+
+// CHECK-H: ---
+// CHECK-H-NEXT: USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-H-NEXT: Name:            'named'
+// CHECK-H-NEXT: ...
+
+// CHECK-I: ---
+// CHECK-I-NEXT: USR:             '4712C5FA37B298A25501D1033C619B65B0ECC449'
+// CHECK-I-NEXT: Name:            'NamedClass'
+// CHECK-I-NEXT: Namespace:
+// CHECK-I-NEXT:   - Type:            Namespace
+// CHECK-I-NEXT:     Name:            'named'
+// CHECK-I-NEXT:     USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-I-NEXT: DefLocation:
+// CHECK-I-NEXT:   LineNumber:      191
+// CHECK-I-NEXT:   Filename:        'test'
+// CHECK-I-NEXT: TagType:         Class
+// CHECK-I-NEXT: Members:
+// CHECK-I-NEXT:   - Type:
+// CHECK-I-NEXT:       Name:            'int'
+// CHECK-I-NEXT:     Name:            'namedPublicField'
+// CHECK-I-NEXT:   - Type:
+// CHECK-I-NEXT:       Name:            'int'
+// CHECK-I-NEXT:     Name:            'namedProtectedField'
+// CHECK-I-NEXT:     Access:          Protected
+// CHECK-I-NEXT: ...
+
+
+// CHECK-J: ---
+// CHECK-J-NEXT: USR:             'ADBF58C533B17E6425D64E71B1F3D0E13002FD8A'
+// CHECK-J-NEXT: Name:            'namedFunction'
+// CHECK-J-NEXT: Namespace:
+// CHECK-J-NEXT:   - Type:            Namespace
+// CHECK-J-NEXT:     Name:            'named'
+// CHECK-J-NEXT:     USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-J-NEXT: Location:
+// CHECK-J-NEXT:   - LineNumber:      203
+// CHECK-J-NEXT:     Filename:        'test'
+// CHECK-J-NEXT: ReturnType:
+// CHECK-J-NEXT:   Type:
+// CHECK-J-NEXT:     Name:            'void'
+// CHECK-J-NEXT: ...
+
+
+// CHECK-K: ---
+// CHECK-K-NEXT: USR:             '5DAFF70FA8324766ABC467DE0A11591E4EDFF45F'
+// CHECK-K-NEXT: Name:            'namedInlineFunction'
+// CHECK-K-NEXT: Namespace:
+// CHECK-K-NEXT:   - Type:            Namespace
+// CHECK-K-NEXT:     Name:            'named'
+// CHECK-K-NEXT:     USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-K-NEXT: Location:
+// CHECK-K-NEXT:   - LineNumber:      205
+// CHECK-K-NEXT:     Filename:        'test'
+// CHECK-K-NEXT: ReturnType:
+// CHECK-K-NEXT:   Type:
+// CHECK-K-NEXT:     Name:            'void'
+// CHECK-K-NEXT: ...
+
+// CHECK-L: ---
+// CHECK-L-NEXT: USR:             'F2681EE89CDEAF2361F501DF573CA891B1D5F830'
+// CHECK-L-NEXT: Name:            'namedPublicMethod'
+// CHECK-L-NEXT: Namespace:
+// CHECK-L-NEXT:   - Type:            Record
+// CHECK-L-NEXT:     Name:            'NamedClass'
+// CHECK-L-NEXT:     USR:             '4712C5FA37B298A25501D1033C619B65B0ECC449'
+// CHECK-L-NEXT:   - Type:            Namespace
+// CHECK-L-NEXT:     Name:            'named'
+// CHECK-L-NEXT:     USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-L-NEXT: Location:
+// CHECK-L-NEXT:   - LineNumber:      193
+// CHECK-L-NEXT:     Filename:        'test'
+// CHECK-L-NEXT: IsMethod:        true
+// CHECK-L-NEXT: Parent:
+// CHECK-L-NEXT:   Type:            Record
+// CHECK-L-NEXT:   Name:            'NamedClass'
+// CHECK-L-NEXT:   USR:             '4712C5FA37B298A25501D1033C619B65B0ECC449'
+// CHECK-L-NEXT: ReturnType:
+// CHECK-L-NEXT:   Type:
+// CHECK-L-NEXT:     Name:            'void'
+// CHECK-L-NEXT: ...
+
+
+// CHECK-M: ---
+// CHECK-M-NEXT: USR:             '3C833BDA29FA479525958F421369722A9BE182D6'
+// CHECK-M-NEXT: Name:            'namedProtectedMethod'
+// CHECK-M-NEXT: Namespace:
+// CHECK-M-NEXT:   - Type:            Record
+// CHECK-M-NEXT:     Name:            'NamedClass'
+// CHECK-M-NEXT:     USR:             '4712C5FA37B298A25501D1033C619B65B0ECC449'
+// CHECK-M-NEXT:   - Type:            Namespace
+// CHECK-M-NEXT:     Name:            'named'
+// CHECK-M-NEXT:     USR:             '8960B5C9247D6F5C532756E53A1AD1240FA2146F'
+// CHECK-M-NEXT: Location:
+// CHECK-M-NEXT:   - LineNumber:      196
+// CHECK-M-NEXT:     Filename:        'test'
+// CHECK-M-NEXT: IsMethod:        true
+// CHECK-M-NEXT: Parent:
+// CHECK-M-NEXT:   Type:            Record
+// CHECK-M-NEXT:   Name:            'NamedClass'
+// CHECK-M-NEXT:   USR:             '4712C5FA37B298A25501D1033C619B65B0ECC449'
+// CHECK-M-NEXT: ReturnType:
+// CHECK-M-NEXT:   Type:
+// CHECK-M-NEXT:     Name:            'void'
+// CHECK-M-NEXT: ...
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-static.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-static.cpp
@@ -0,0 +1,11 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/staticFunction.yaml
+// XFAIL: *
+
+
+static void staticFunction(int x);
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-namespace-private.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-namespace-private.cpp
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/named/NamedClass/PrivateMethod.yaml
+// XFAIL: *
+
+
+namespace named{
+    class NamedClass {
+     public:
+      void namedPublicMethod();
+      int  namedPublicField;
+     protected:
+      void namedProtectedMethod();
+      int  namedProtectedField;
+     private:
+      void namedPrivateMethod();
+      int  namedPrivateField;
+    };
+
+    void namedFunction();
+    static void namedStaticFunction();
+    inline void namedInlineFunction();
+}
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-functionInnerClass.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-functionInnerClass.cpp
@@ -0,0 +1,18 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/functionWithInnerClass/InnerClass.yaml
+// XFAIL: *
+
+
+int functionWithInnerClass(int x){
+    class InnerClass { //NoLinkage
+      public:
+        int innerPublicMethod() { return 2; };
+    }; //end class
+    InnerClass temp;
+    return temp.innerPublicMethod();
+};
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-classPrivate.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-classPrivate.cpp
@@ -0,0 +1,22 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/Class/privateMethod.yaml
+// XFAIL: *
+
+
+class Class {
+ public:
+  void publicMethod();
+  int  publicField;
+ protected:
+  void protectedMethod();
+  int  protectedField;
+ private:
+  void privateMethod();
+  int  privateField;
+};
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonfunction.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonfunction.cpp
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/anonFunction.yaml
+// XFAIL: *
+
+
+namespace{
+    class AnonClass {
+     public:
+      void anonPublicMethod();
+      int  anonPublicField;
+     protected:
+      void anonProtectedMethod();
+      int  anonProtectedField;
+     private:
+      void anonPrivateMethod();
+      int  anonPrivateField;
+    };
+
+    void anonFunction();
+    static void anonStaticFunction();
+    inline void anonInlineFunction();
+}
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonclass.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonclass.cpp
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/AnonClass.yaml
+// XFAIL: *
+
+
+namespace{
+    class AnonClass {
+     public:
+      void anonPublicMethod();
+      int  anonPublicField;
+     protected:
+      void anonProtectedMethod();
+      int  anonProtectedField;
+     private:
+      void anonPrivateMethod();
+      int  anonPrivateField;
+    };
+
+    void anonFunction();
+    static void anonStaticFunction();
+    inline void anonInlineFunction();
+}
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonStaticFunction.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonStaticFunction.cpp
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/anonStaticFunction.yaml
+// XFAIL: *
+
+
+namespace{
+    class AnonClass {
+     public:
+      void anonPublicMethod();
+      int  anonPublicField;
+     protected:
+      void anonProtectedMethod();
+      int  anonProtectedField;
+     private:
+      void anonPrivateMethod();
+      int  anonPrivateField;
+    };
+
+    void anonFunction();
+    static void anonStaticFunction();
+    inline void anonInlineFunction();
+}
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonInlineFunction.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-record-excluded-anonInlineFunction.cpp
@@ -0,0 +1,28 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-A-EMPTY --input-file=%t/docs/anonInlineFunction.yaml
+// XFAIL: *
+
+
+namespace{
+    class AnonClass {
+     public:
+      void anonPublicMethod();
+      int  anonPublicField;
+     protected:
+      void anonProtectedMethod();
+      int  anonProtectedField;
+     private:
+      void anonPrivateMethod();
+      int  anonPrivateField;
+    };
+
+    void anonFunction();
+    static void anonStaticFunction();
+    inline void anonInlineFunction();
+}
+
+// CHECK-A-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-included.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-included.cpp
@@ -0,0 +1,44 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: cat %t/docs/moduleFunction.yaml | FileCheck %s --check-prefix=CHECK-A
+// RUN: cat %t/docs/exportedModuleFunction.yaml | FileCheck %s --check-prefix=CHECK-C
+
+export module M;
+
+int moduleFunction(int x); //ModuleLinkage
+// CHECK-A: ---
+// CHECK-A-NEXT: USR:             '4429AA8706EF483A44B1DCE2D956BF0FEF82A9B7'
+// CHECK-A-NEXT: Name:            'moduleFunction'
+// CHECK-A-NEXT: Location:
+// CHECK-A-NEXT:   - LineNumber:      11
+// CHECK-A-NEXT:     Filename:        'test'
+// CHECK-A-NEXT: Params:
+// CHECK-A-NEXT:   - Type:
+// CHECK-A-NEXT:       Name:            'int'
+// CHECK-A-NEXT:     Name:            'x'
+// CHECK-A-NEXT: ReturnType:
+// CHECK-A-NEXT:   Type:
+// CHECK-A-NEXT:     Name:            'int'
+// CHECK-A-NEXT: ...
+
+export double exportedModuleFunction(double y, int z); //ExternalLinkage
+// CHECK-C: ---
+// CHECK-C-NEXT: USR:             '325C328D4EB158CCBA4DF2B5321F63EB39C2B17C'
+// CHECK-C-NEXT: Name:            'exportedModuleFunction'
+// CHECK-C-NEXT: Location:
+// CHECK-C-NEXT:   - LineNumber:      27
+// CHECK-C-NEXT:     Filename:        'test'
+// CHECK-C-NEXT: Params:
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'double'
+// CHECK-C-NEXT:     Name:            'y'
+// CHECK-C-NEXT:   - Type:
+// CHECK-C-NEXT:       Name:            'int'
+// CHECK-C-NEXT:     Name:            'z'
+// CHECK-C-NEXT: ReturnType:
+// CHECK-C-NEXT:   Type:
+// CHECK-C-NEXT:     Name:            'double'
+// CHECK-C-NEXT: ...
Index: clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-excluded.cpp
===================================================================
--- /dev/null
+++ clang-tools-extra/test/clang-doc/public-flag/yaml-public-module-excluded.cpp
@@ -0,0 +1,12 @@
+// RUN: rm -rf %t
+// RUN: mkdir %t
+// RUN: echo "" > %t/compile_flags.txt
+// RUN: cp "%s" "%t/test.cpp"
+// RUN: clang-doc --public --extra-arg=-fmodules-ts --doxygen -p %t %t/test.cpp -output=%t/docs
+// RUN: FileCheck %s --allow-empty --check-prefix=CHECK-B-EMPTY --input-file=%t/docs/staticModuleFunction.yaml
+// XFAIL: *
+
+export module M;
+
+static int staticModuleFunction(int x); //ModuleInternalLinkage
+// CHECK-B-EMPTY: {{^}}{{$}}
Index: clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
===================================================================
--- clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
+++ clang-tools-extra/clang-doc/tool/ClangDocMain.cpp
@@ -64,6 +64,11 @@
     llvm::cl::desc("Dump intermediate results to bitcode file."),
     llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
 
+static llvm::cl::opt<bool> PublicOnly(
+    "public",
+    llvm::cl::desc("Document only public structures."),
+    llvm::cl::init(false), llvm::cl::cat(ClangDocCategory));
+
 enum OutputFormatTy {
   yaml,
 };
@@ -171,9 +176,10 @@
 
   // Mapping phase
   llvm::outs() << "Mapping decls...\n";
-  auto Err = Exec->get()->execute(
-      doc::newMapperActionFactory(Exec->get()->getExecutionContext()),
-      ArgAdjuster);
+  clang::doc::ClangDocContext CDCtx =
+        {Exec->get()->getExecutionContext(), PublicOnly};
+  auto Err = Exec->get()->execute(doc::newMapperActionFactory(CDCtx),
+        ArgAdjuster);
   if (Err) {
     llvm::errs() << toString(std::move(Err)) << "\n";
     return 1;
Index: clang-tools-extra/clang-doc/Serialize.h
===================================================================
--- clang-tools-extra/clang-doc/Serialize.h
+++ clang-tools-extra/clang-doc/Serialize.h
@@ -29,15 +29,15 @@
 namespace serialize {
 
 std::string emitInfo(const NamespaceDecl *D, const FullComment *FC,
-                     int LineNumber, StringRef File);
+                     int LineNumber, StringRef File, bool PublicOnly);
 std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
-                     StringRef File);
+                     StringRef File, bool PublicOnly);
 std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
-                     StringRef File);
+                     StringRef File, bool PublicOnly);
 std::string emitInfo(const FunctionDecl *D, const FullComment *FC,
-                     int LineNumber, StringRef File);
+                     int LineNumber, StringRef File, bool PublicOnly);
 std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC,
-                     int LineNumber, StringRef File);
+                     int LineNumber, StringRef File, bool PublicOnly);
 
 // Function to hash a given USR value for storage.
 // As USRs (Unified Symbol Resolution) could be large, especially for functions
Index: clang-tools-extra/clang-doc/Serialize.cpp
===================================================================
--- clang-tools-extra/clang-doc/Serialize.cpp
+++ clang-tools-extra/clang-doc/Serialize.cpp
@@ -171,8 +171,22 @@
   return Ty->getDecl()->getDefinition();
 }
 
-static void parseFields(RecordInfo &I, const RecordDecl *D) {
+
+static bool shouldNotBePublic(const clang::AccessSpecifier as, const clang::Linkage link){
+    if(as == clang::AccessSpecifier::AS_private)
+        return true;
+    else if ((link == clang::Linkage::ModuleLinkage) ||
+             (link == clang::Linkage::ExternalLinkage))
+        return false;
+    return true; // otherwise, linkage is some form of internal linkage
+}
+
+
+static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) {
   for (const FieldDecl *F : D->fields()) {
+    if(PublicOnly && shouldNotBePublic(F->getAccessUnsafe(), F->getLinkageInternal())){
+        continue;
+    }
     if (const auto *T = getDeclForType(F->getTypeSourceInfo()->getType())) {
       // Use getAccessUnsafe so that we just get the default AS_none if it's not
       // valid, as opposed to an assert.
@@ -294,34 +308,50 @@
   parseParameters(I, D);
 }
 
+
 std::string emitInfo(const NamespaceDecl *D, const FullComment *FC,
-                     int LineNumber, llvm::StringRef File) {
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  bool nonPublicNamespace = (D->isAnonymousNamespace()) ||
+                    shouldNotBePublic(D->getAccess(), D->getLinkageInternal());
+  if(PublicOnly && nonPublicNamespace){
+    return "";
+  }
   NamespaceInfo I;
   populateInfo(I, D, FC);
   return serialize(I);
 }
 
 std::string emitInfo(const RecordDecl *D, const FullComment *FC, int LineNumber,
-                     llvm::StringRef File) {
+                     llvm::StringRef File, bool PublicOnly) {
+  if(PublicOnly && shouldNotBePublic(D->getAccess(), D->getLinkageInternal())){
+    return "";
+  }
   RecordInfo I;
   populateSymbolInfo(I, D, FC, LineNumber, File);
   I.TagType = D->getTagKind();
-  parseFields(I, D);
+  parseFields(I, D, PublicOnly);
   if (const auto *C = dyn_cast<CXXRecordDecl>(D))
     parseBases(I, C);
   return serialize(I);
 }
 
 std::string emitInfo(const FunctionDecl *D, const FullComment *FC,
-                     int LineNumber, llvm::StringRef File) {
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  if(PublicOnly && shouldNotBePublic(D->getAccess(), D->getLinkageInternal())){
+    return "";
+  }
   FunctionInfo I;
   populateFunctionInfo(I, D, FC, LineNumber, File);
   I.Access = clang::AccessSpecifier::AS_none;
   return serialize(I);
 }
 
+
 std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC,
-                     int LineNumber, llvm::StringRef File) {
+                     int LineNumber, llvm::StringRef File, bool PublicOnly) {
+  if(PublicOnly && shouldNotBePublic(D->getAccess(), D->getLinkageInternal())){
+    return "";
+  }
   FunctionInfo I;
   populateFunctionInfo(I, D, FC, LineNumber, File);
   I.IsMethod = true;
@@ -332,7 +362,10 @@
 }
 
 std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber,
-                     llvm::StringRef File) {
+                     llvm::StringRef File, bool PublicOnly) {
+  if(PublicOnly && shouldNotBePublic(D->getAccess(), D->getLinkageInternal())){
+    return "";
+  }
   EnumInfo I;
   populateSymbolInfo(I, D, FC, LineNumber, File);
   I.Scoped = D->isScoped();
Index: clang-tools-extra/clang-doc/Mapper.h
===================================================================
--- clang-tools-extra/clang-doc/Mapper.h
+++ clang-tools-extra/clang-doc/Mapper.h
@@ -20,18 +20,21 @@
 
 #include "clang/AST/RecursiveASTVisitor.h"
 #include "clang/Tooling/Execution.h"
+#include "ClangDoc.h"
 
 using namespace clang::comments;
 using namespace clang::tooling;
 
 namespace clang {
 namespace doc {
 
+
+
 class MapASTVisitor : public clang::RecursiveASTVisitor<MapASTVisitor>,
                       public ASTConsumer {
 public:
-  explicit MapASTVisitor(ASTContext *Ctx, ExecutionContext *ECtx)
-      : ECtx(ECtx) {}
+  explicit MapASTVisitor(ASTContext *Ctx, ClangDocContext CDCtx)
+        : CDCtx(CDCtx) {}
 
   void HandleTranslationUnit(ASTContext &Context) override;
   bool VisitNamespaceDecl(const NamespaceDecl *D);
@@ -48,7 +51,7 @@
   comments::FullComment *getComment(const NamedDecl *D,
                                     const ASTContext &Context) const;
 
-  ExecutionContext *ECtx;
+  ClangDocContext CDCtx;
 };
 
 } // namespace doc
Index: clang-tools-extra/clang-doc/Mapper.cpp
===================================================================
--- clang-tools-extra/clang-doc/Mapper.cpp
+++ clang-tools-extra/clang-doc/Mapper.cpp
@@ -33,10 +33,11 @@
   if (index::generateUSRForDecl(D, USR))
     return true;
 
-  ECtx->reportResult(llvm::toHex(llvm::toStringRef(serialize::hashUSR(USR))),
+  CDCtx.ECtx->reportResult(llvm::toHex(llvm::toStringRef(serialize::hashUSR(USR))),
                      serialize::emitInfo(D, getComment(D, D->getASTContext()),
                                          getLine(D, D->getASTContext()),
-                                         getFile(D, D->getASTContext())));
+                                         getFile(D, D->getASTContext()),
+                                         CDCtx.PublicOnly));
   return true;
 }
 
Index: clang-tools-extra/clang-doc/ClangDoc.h
===================================================================
--- clang-tools-extra/clang-doc/ClangDoc.h
+++ clang-tools-extra/clang-doc/ClangDoc.h
@@ -24,8 +24,15 @@
 namespace clang {
 namespace doc {
 
+struct ClangDocContext {
+    tooling::ExecutionContext *ECtx;
+    bool PublicOnly;
+};
+
+
 std::unique_ptr<tooling::FrontendActionFactory>
-newMapperActionFactory(tooling::ExecutionContext *ECtx);
+newMapperActionFactory(ClangDocContext CDCtx);
+
 
 } // namespace doc
 } // namespace clang
Index: clang-tools-extra/clang-doc/ClangDoc.cpp
===================================================================
--- clang-tools-extra/clang-doc/ClangDoc.cpp
+++ clang-tools-extra/clang-doc/ClangDoc.cpp
@@ -26,35 +26,36 @@
 namespace clang {
 namespace doc {
 
+
 class MapperActionFactory : public tooling::FrontendActionFactory {
 public:
-  MapperActionFactory(tooling::ExecutionContext *ECtx) : ECtx(ECtx) {}
+  MapperActionFactory(ClangDocContext CDCtx): CDCtx(CDCtx) {}
   clang::FrontendAction *create() override;
 
 private:
-  tooling::ExecutionContext *ECtx;
+    ClangDocContext CDCtx;
 };
 
 clang::FrontendAction *MapperActionFactory::create() {
   class ClangDocAction : public clang::ASTFrontendAction {
   public:
-    ClangDocAction(ExecutionContext *ECtx) : ECtx(ECtx) {}
+      ClangDocAction(ClangDocContext CDCtx) : CDCtx(CDCtx) {}
 
     std::unique_ptr<clang::ASTConsumer>
     CreateASTConsumer(clang::CompilerInstance &Compiler,
                       llvm::StringRef InFile) override {
-      return llvm::make_unique<MapASTVisitor>(&Compiler.getASTContext(), ECtx);
+      return llvm::make_unique<MapASTVisitor>(&Compiler.getASTContext(), CDCtx);
     }
 
   private:
-    ExecutionContext *ECtx;
+      ClangDocContext CDCtx;
   };
-  return new ClangDocAction(ECtx);
+  return new ClangDocAction(CDCtx);
 }
 
 std::unique_ptr<tooling::FrontendActionFactory>
-newMapperActionFactory(tooling::ExecutionContext *ECtx) {
-  return llvm::make_unique<MapperActionFactory>(ECtx);
+newMapperActionFactory(ClangDocContext CDCtx){ 
+  return llvm::make_unique<MapperActionFactory>(CDCtx);
 }
 
 } // namespace doc
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
http://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to