Index: clang-tools-extra/clang-doc/ClangDoc.h =================================================================== --- clang-tools-extra/clang-doc/ClangDoc.h +++ clang-tools-extra/clang-doc/ClangDoc.h @@ -25,7 +25,7 @@ namespace doc { std::unique_ptr -newMapperActionFactory(tooling::ExecutionContext *ECtx); +newMapperActionFactory(tooling::ExecutionContext *ECtx, bool PublicOnly); } // 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 @@ -28,33 +28,36 @@ class MapperActionFactory : public tooling::FrontendActionFactory { public: - MapperActionFactory(tooling::ExecutionContext *ECtx) : ECtx(ECtx) {} + MapperActionFactory(tooling::ExecutionContext *ECtx, bool PublicOnly) : + ECtx(ECtx), PublicOnly(PublicOnly) {} clang::FrontendAction *create() override; private: tooling::ExecutionContext *ECtx; + bool PublicOnly; }; clang::FrontendAction *MapperActionFactory::create() { class ClangDocAction : public clang::ASTFrontendAction { public: - ClangDocAction(ExecutionContext *ECtx) : ECtx(ECtx) {} + ClangDocAction(ExecutionContext *ECtx, bool PublicOnly) : ECtx(ECtx), PublicOnly(PublicOnly) {} std::unique_ptr CreateASTConsumer(clang::CompilerInstance &Compiler, llvm::StringRef InFile) override { - return llvm::make_unique(&Compiler.getASTContext(), ECtx); + return llvm::make_unique(&Compiler.getASTContext(), ECtx, PublicOnly); } private: ExecutionContext *ECtx; + bool PublicOnly; }; - return new ClangDocAction(ECtx); + return new ClangDocAction(ECtx, PublicOnly); } std::unique_ptr -newMapperActionFactory(tooling::ExecutionContext *ECtx) { - return llvm::make_unique(ECtx); +newMapperActionFactory(tooling::ExecutionContext *ECtx, bool PublicOnly) { + return llvm::make_unique(ECtx, PublicOnly); } } // namespace doc Index: clang-tools-extra/clang-doc/Mapper.h =================================================================== --- clang-tools-extra/clang-doc/Mapper.h +++ clang-tools-extra/clang-doc/Mapper.h @@ -30,8 +30,8 @@ class MapASTVisitor : public clang::RecursiveASTVisitor, public ASTConsumer { public: - explicit MapASTVisitor(ASTContext *Ctx, ExecutionContext *ECtx) - : ECtx(ECtx) {} + explicit MapASTVisitor(ASTContext *Ctx, ExecutionContext *ECtx, bool PublicOnly) + : ECtx(ECtx), PublicOnly(PublicOnly) {} void HandleTranslationUnit(ASTContext &Context) override; bool VisitNamespaceDecl(const NamespaceDecl *D); @@ -49,6 +49,7 @@ const ASTContext &Context) const; ExecutionContext *ECtx; + bool PublicOnly; }; } // namespace doc Index: clang-tools-extra/clang-doc/Mapper.cpp =================================================================== --- clang-tools-extra/clang-doc/Mapper.cpp +++ clang-tools-extra/clang-doc/Mapper.cpp @@ -36,7 +36,8 @@ 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()), + PublicOnly)); return true; } 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,11 @@ return Ty->getDecl()->getDefinition(); } -static void parseFields(RecordInfo &I, const RecordDecl *D) { +static void parseFields(RecordInfo &I, const RecordDecl *D, bool PublicOnly) { for (const FieldDecl *F : D->fields()) { + if(PublicOnly && (F->getAccessUnsafe() != clang::AccessSpecifier::AS_public)){ + 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. @@ -295,25 +298,25 @@ } std::string emitInfo(const NamespaceDecl *D, const FullComment *FC, - int LineNumber, llvm::StringRef File) { + int LineNumber, llvm::StringRef File, bool PublicOnly) { 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) { 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(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) { FunctionInfo I; populateFunctionInfo(I, D, FC, LineNumber, File); I.Access = clang::AccessSpecifier::AS_none; @@ -321,18 +324,21 @@ } std::string emitInfo(const CXXMethodDecl *D, const FullComment *FC, - int LineNumber, llvm::StringRef File) { + int LineNumber, llvm::StringRef File, bool PublicOnly) { FunctionInfo I; populateFunctionInfo(I, D, FC, LineNumber, File); I.IsMethod = true; I.Parent = Reference{getUSRForDecl(D->getParent()), D->getParent()->getNameAsString(), InfoType::IT_record}; I.Access = D->getAccess(); + if(PublicOnly && (I.Access != clang::AccessSpecifier::AS_public)){ + return ""; + } return serialize(I); } std::string emitInfo(const EnumDecl *D, const FullComment *FC, int LineNumber, - llvm::StringRef File) { + llvm::StringRef File, bool PublicOnly) { EnumInfo I; populateSymbolInfo(I, D, FC, LineNumber, File); I.Scoped = D->isScoped(); 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 PublicOnly( + "public-only", + llvm::cl::desc("Only document public methods & public fields."), + llvm::cl::init(false), llvm::cl::cat(ClangDocCategory)); + enum OutputFormatTy { yaml, }; @@ -172,7 +177,7 @@ // Mapping phase llvm::outs() << "Mapping decls...\n"; auto Err = Exec->get()->execute( - doc::newMapperActionFactory(Exec->get()->getExecutionContext()), + doc::newMapperActionFactory(Exec->get()->getExecutionContext(), PublicOnly), ArgAdjuster); if (Err) { llvm::errs() << toString(std::move(Err)) << "\n"; Index: clang-tools-extra/test/clang-doc/yaml-record-public-only.cpp =================================================================== --- /dev/null +++ clang-tools-extra/test/clang-doc/yaml-record-public-only.cpp @@ -0,0 +1,103 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "" > %t/compile_flags.txt +// RUN: cp "%s" "%t/test.cpp" +// RUN: clang-doc --public-only --doxygen -p %t %t/test.cpp -output=%t/docs +// RUN: cat %t/docs/Struct.yaml | FileCheck %s --check-prefix=CHECK-A +// RUN: cat %t/docs/Struct/publicMethod.yaml | FileCheck %s --check-prefix=CHECK-B +// RUN: cat %t/docs/Class.yaml | FileCheck %s --check-prefix=CHECK-C +// RUN: cat %t/docs/Class/publicMethod.yaml | FileCheck %s --check-prefix=CHECK-D + +struct Struct { + public: + void publicMethod(); + int publicField; + protected: + void protectedMethod(); + int protectedField; + private: + void privateMethod(); + int privateField; +}; + + +// CHECK-A: --- +// CHECK-A-NEXT: USR: '0E0522198A2C7D141073719DA0815FCD6DC95610' +// CHECK-A-NEXT: Name: 'Struct' +// CHECK-A-NEXT: DefLocation: +// CHECK-A-NEXT: LineNumber: 11 +// CHECK-A-NEXT: Filename: 'test' +// CHECK-A-NEXT: Members: +// CHECK-A-NEXT: - Type: +// CHECK-A-NEXT: Name: 'int' +// CHECK-A-NEXT: Name: 'publicField' +// CHECK-A-NEXT: ... + + +// CHECK-B: --- +// CHECK-B-NEXT: USR: 'DC71C1FF683E2DE57395B0029458ADC4BDDE46CA' +// CHECK-B-NEXT: Name: 'publicMethod' +// CHECK-B-NEXT: Namespace: +// CHECK-B-NEXT: - Type: Record +// CHECK-B-NEXT: Name: 'Struct' +// CHECK-B-NEXT: USR: '0E0522198A2C7D141073719DA0815FCD6DC95610' +// CHECK-B-NEXT: Location: +// CHECK-B-NEXT: - LineNumber: 13 +// CHECK-B-NEXT: Filename: 'test' +// CHECK-B-NEXT: IsMethod: true +// CHECK-B-NEXT: Parent: +// CHECK-B-NEXT: Type: Record +// CHECK-B-NEXT: Name: 'Struct' +// CHECK-B-NEXT: USR: '0E0522198A2C7D141073719DA0815FCD6DC95610' +// CHECK-B-NEXT: ReturnType: +// CHECK-B-NEXT: Type: +// CHECK-B-NEXT: Name: 'void' +// CHECK-B-NEXT: ... + + +class Class { + public: + void publicMethod(); + int publicField; + protected: + void protectedMethod(); + int protectedField; + private: + void privateMethod(); + int privateField; +}; + + +// CHECK-C: --- +// CHECK-C-NEXT: USR: '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45' +// CHECK-C-NEXT: Name: 'Class' +// CHECK-C-NEXT: DefLocation: +// CHECK-C-NEXT: LineNumber: 58 +// CHECK-C-NEXT: Filename: 'test' +// CHECK-C-NEXT: TagType: Class +// CHECK-C-NEXT: Members: +// CHECK-C-NEXT: - Type: +// CHECK-C-NEXT: Name: 'int' +// CHECK-C-NEXT: Name: 'publicField' +// CHECK-C-NEXT: ... + + +// CHECK-D: --- +// CHECK-D-NEXT: USR: '05682AF6307337176313391E00A231C2C55A4972' +// CHECK-D-NEXT: Name: 'publicMethod' +// CHECK-D-NEXT: Namespace: +// CHECK-D-NEXT: - Type: Record +// CHECK-D-NEXT: Name: 'Class' +// CHECK-D-NEXT: USR: '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45' +// CHECK-D-NEXT: Location: +// CHECK-D-NEXT: - LineNumber: 60 +// CHECK-D-NEXT: Filename: 'test' +// CHECK-D-NEXT: IsMethod: true +// CHECK-D-NEXT: Parent: +// CHECK-D-NEXT: Type: Record +// CHECK-D-NEXT: Name: 'Class' +// CHECK-D-NEXT: USR: '7CDD73DCD6CD72F7E5CE25502810A182C66C4B45' +// CHECK-D-NEXT: ReturnType: +// CHECK-D-NEXT: Type: +// CHECK-D-NEXT: Name: 'void' +// CHECK-D-NEXT: ...