Index: clang-doc/CMakeLists.txt =================================================================== --- clang-doc/CMakeLists.txt +++ clang-doc/CMakeLists.txt @@ -23,3 +23,4 @@ ) add_subdirectory(tool) +add_subdirectory(generators) Index: clang-doc/Representation.h =================================================================== --- clang-doc/Representation.h +++ clang-doc/Representation.h @@ -62,6 +62,9 @@ struct Reference { Reference() = default; Reference(llvm::StringRef USR, InfoType IT) : USR(USR), RefType(IT) {} + bool operator==(const Reference &Other) const { + return USR == Other.USR && RefType == Other.RefType; + } SmallString<16> USR; InfoType RefType = InfoType::IT_default; @@ -73,6 +76,9 @@ struct TypeInfo { TypeInfo() = default; TypeInfo(llvm::StringRef Type, InfoType IT) : Type(Type, IT) {} + bool operator==(const TypeInfo &Other) const { + return Type == Other.Type; + } Reference Type; std::vector Description; @@ -101,6 +107,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; SmallString<32> Filename; Index: clang-doc/generators/CMakeLists.txt =================================================================== --- /dev/null +++ clang-doc/generators/CMakeLists.txt @@ -0,0 +1,9 @@ +set(LLVM_LINK_COMPONENTS support) + +add_clang_library(clangDocGenerators + GeneratorBase.cpp + YAMLGenerator.cpp + + LINK_LIBS + clangDoc + ) Index: clang-doc/generators/GeneratorBase.cpp =================================================================== --- /dev/null +++ clang-doc/generators/GeneratorBase.cpp @@ -0,0 +1,41 @@ +//===-- GeneratorBase.cpp - ClangDoc Generator ------------------*- C++ -*-===// +// +// The LLVM Compiler Infrastructure +// +// This file is distributed under the University of Illinois Open Source +// License. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#include "../Representation.h" +#include "Generators.h" +#include "llvm/ADT/StringRef.h" +#include "llvm/Support/FileSystem.h" +#include "llvm/Support/MemoryBuffer.h" +#include "llvm/Support/raw_ostream.h" + +using namespace llvm; + +namespace clang { +namespace doc { + +bool Generator::buildDirectory(StringRef Dir) { + std::error_code DirectoryStatus = sys::fs::create_directories(Dir); + if (DirectoryStatus != OK) { + errs() << "Unable to create documentation directories.\n"; + return false; + } + return true; +} + +bool Generator::removeExistingDirectory(StringRef Dir) { + std::error_code DirectoryStatus = sys::fs::remove_directories(Dir); + if (DirectoryStatus != OK) { + errs() << "Unable to remove existing documentation directories.\n"; + return false; + } + return true; +} + +} // namespace doc +} // namespace clang Index: clang-doc/generators/Generators.h =================================================================== --- /dev/null +++ clang-doc/generators/Generators.h @@ -0,0 +1,68 @@ +//===-- 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 +#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" + +using namespace llvm; + +namespace clang { +namespace doc { + +class Generator { + public: + Generator(std::unique_ptr &IS, StringRef Root, StringRef Format) + : IS(IS), Root(Root), Format(Format) {} + virtual ~Generator() = default; + + virtual int generate() = 0; + + protected: + virtual bool buildDirectory(StringRef Dir); + virtual bool removeExistingDirectory(StringRef Dir); + + std::unique_ptr &IS; + std::string Root; + std::string Format; + std::error_code OK; +}; + +class YAMLGenerator : public Generator { + public: + YAMLGenerator(std::unique_ptr &IS, StringRef Root, StringRef Format) + : Generator(IS, Root, Format) {} + virtual ~YAMLGenerator() = default; + + int generate() override; +}; + +class GeneratorFactory { + public: + static std::unique_ptr create(std::unique_ptr &IS, + StringRef Root, StringRef Format) { + if (Format == "yaml") + return llvm::make_unique(IS, Root, Format); + + errs() << "Unsupported documentation format.\n"; + return nullptr; + } +}; + +} // namespace doc +} // namespace clang + +#endif // LLVM_CLANG_TOOLS_EXTRA_CLANG_DOC_GENERATOR_H Index: clang-doc/generators/YAMLGenerator.cpp =================================================================== --- /dev/null +++ clang-doc/generators/YAMLGenerator.cpp @@ -0,0 +1,288 @@ +//===-- 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) +LLVM_YAML_IS_SEQUENCE_VECTOR(llvm::SmallString<16>) + +namespace llvm { +namespace yaml { + +template <> +struct ScalarEnumerationTraits { + 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 { + 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 { + 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 { + 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); + } +}; + +template <> +template +struct ScalarTraits> { + static void output(const SmallString &S, void *, llvm::raw_ostream &OS) { + OS << S.str(); + } + static StringRef input(StringRef Scalar, void *, SmallString &Value) { + Value = Scalar; + return StringRef(); + } + static QuotingType mustQuote(StringRef) { return QuotingType::Single; } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, Location &Loc) { + IO.mapOptional("LineNumber", Loc.LineNumber, 0); + IO.mapOptional("Filename", Loc.Filename, SmallString<32>()); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, Reference &Ref) { + IO.mapOptional("USR", Ref.USR, SmallString<16>()); + IO.mapOptional("Type", Ref.RefType, InfoType::IT_default); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, TypeInfo &I) { + IO.mapOptional("Type", I.Type, Reference()); + IO.mapOptional("Description", I.Description); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, FieldTypeInfo &I) { + IO.mapOptional("Type", I.Type, Reference()); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Description", I.Description); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, MemberTypeInfo &I) { + IO.mapOptional("Type", I.Type, Reference()); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Access", I.Access, clang::AccessSpecifier::AS_none); + IO.mapOptional("Description", I.Description); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, NamespaceInfo &I) { + IO.mapRequired("USR", I.USR); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector()); + IO.mapOptional("Description", I.Description); + IO.mapOptional("Namespaces", I.Namespaces, + llvm::SmallVector()); + IO.mapOptional("Records", I.Records, llvm::SmallVector()); + IO.mapOptional("Functions", I.Functions, llvm::SmallVector()); + IO.mapOptional("Enums", I.Enums, llvm::SmallVector()); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, RecordInfo &I) { + IO.mapRequired("USR", I.USR); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector()); + IO.mapOptional("Description", I.Description); + IO.mapOptional("Namespaces", I.Namespaces, + llvm::SmallVector()); + IO.mapOptional("Records", I.Records, llvm::SmallVector()); + IO.mapOptional("Functions", I.Functions, llvm::SmallVector()); + IO.mapOptional("Enums", I.Enums, llvm::SmallVector()); + IO.mapOptional("DefLocation", I.DefLoc, Optional()); + IO.mapOptional("Location", I.Loc, llvm::SmallVector()); + IO.mapOptional("TagType", I.TagType, clang::TagTypeKind::TTK_Struct); + IO.mapOptional("Members", I.Members); + IO.mapOptional("Parents", I.Parents, llvm::SmallVector()); + IO.mapOptional("VirtualParents", I.VirtualParents, + llvm::SmallVector()); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, EnumInfo &I) { + IO.mapRequired("USR", I.USR); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector()); + IO.mapOptional("Description", I.Description); + IO.mapOptional("Namespaces", I.Namespaces, + llvm::SmallVector()); + IO.mapOptional("Records", I.Records, llvm::SmallVector()); + IO.mapOptional("Functions", I.Functions, llvm::SmallVector()); + IO.mapOptional("Enums", I.Enums, llvm::SmallVector()); + IO.mapOptional("DefLocation", I.DefLoc, Optional()); + IO.mapOptional("Location", I.Loc, llvm::SmallVector()); + IO.mapOptional("Scoped", I.Scoped, false); + IO.mapOptional("Members", I.Members); + } +}; + +template <> +struct MappingTraits { + static void mapping(IO &IO, FunctionInfo &I) { + IO.mapRequired("USR", I.USR); + IO.mapOptional("Name", I.Name, SmallString<16>()); + IO.mapOptional("Namespace", I.Namespace, llvm::SmallVector()); + IO.mapOptional("Description", I.Description); + IO.mapOptional("Namespaces", I.Namespaces, + llvm::SmallVector()); + IO.mapOptional("Records", I.Records, llvm::SmallVector()); + IO.mapOptional("Functions", I.Functions, llvm::SmallVector()); + IO.mapOptional("Enums", I.Enums, llvm::SmallVector()); + IO.mapOptional("DefLocation", I.DefLoc, Optional()); + IO.mapOptional("Location", I.Loc, llvm::SmallVector()); + 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 { + static void mapping(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<4>()); + 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, 4>()); + IO.mapOptional("AttrKeys", I.AttrKeys, + llvm::SmallVector, 4>()); + IO.mapOptional("AttrValues", I.AttrValues, + llvm::SmallVector, 4>()); + IO.mapOptional("Children", I.Children); + } +}; + +template <> +struct MappingTraits> { + static void mapping(IO &IO, std::unique_ptr &C) { + IO.mapOptional("Kind", C->Kind, SmallString<16>()); + IO.mapOptional("Text", C->Text, SmallString<64>()); + IO.mapOptional("Name", C->Name, SmallString<16>()); + IO.mapOptional("Direction", C->Direction, SmallString<4>()); + IO.mapOptional("ParamName", C->ParamName, SmallString<16>()); + IO.mapOptional("CloseName", C->CloseName, SmallString<16>()); + IO.mapOptional("SelfClosing", C->SelfClosing, false); + IO.mapOptional("Explicit", C->Explicit, false); + IO.mapOptional("Args", C->Args, llvm::SmallVector, 4>()); + IO.mapOptional("AttrKeys", C->AttrKeys, + llvm::SmallVector, 4>()); + IO.mapOptional("AttrValues", C->AttrValues, + llvm::SmallVector, 4>()); + IO.mapOptional("Children", C->Children); + } +}; + +template <> +struct MappingTraits { + 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() { + SmallString<128> Path; + sys::path::native(Root, Path); + sys::path::append(Path, "docs.yaml"); + std::error_code OutErrorInfo; + raw_fd_ostream OS(Path, OutErrorInfo, sys::fs::F_None); + if (OutErrorInfo != OK) { + errs() << "Error opening yaml file.\n"; + return 1; + } + + 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/tool/CMakeLists.txt =================================================================== --- clang-doc/tool/CMakeLists.txt +++ clang-doc/tool/CMakeLists.txt @@ -11,7 +11,7 @@ clangBasic clangFrontend clangDoc + clangDocGenerators clangTooling clangToolingCore ) - \ No newline at end of file Index: clang-doc/tool/ClangDocMain.cpp =================================================================== --- clang-doc/tool/ClangDocMain.cpp +++ clang-doc/tool/ClangDocMain.cpp @@ -32,6 +32,7 @@ #include "clang/Tooling/Execution.h" #include "clang/Tooling/StandaloneExecution.h" #include "clang/Tooling/Tooling.h" +#include "generators/Generators.h" #include "llvm/ADT/APFloat.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Path.h" @@ -62,6 +63,11 @@ "omit-filenames", llvm::cl::desc("Omit filenames in output."), llvm::cl::init(false), llvm::cl::cat(ClangDocCategory)); +static llvm::cl::opt 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 DoxygenOnly( "doxygen", llvm::cl::desc("Use only doxygen-style comments to generate docs."), @@ -152,5 +158,24 @@ OS.close(); } - return 0; + // Documentation generation + llvm::outs() << "Generating docs...\n"; + SmallString<128> DocsRootPath; + sys::path::native(OutDirectory, DocsRootPath); + sys::path::append(DocsRootPath, Format); + std::error_code RemoveStatus = sys::fs::remove_directories(DocsRootPath); + if (RemoveStatus != OK) { + llvm::errs() << "Unable to remove existing documentation directory for " << Format + << ".\n"; + return 1; + } + std::error_code DirectoryStatus = sys::fs::create_directories(DocsRootPath); + if (DirectoryStatus != OK) { + llvm::errs() << "Unable to create documentation directories.\n"; + return 1; + } + std::unique_ptr G = + doc::GeneratorFactory::create(Infos, DocsRootPath, Format); + if (!G) return 1; + return G->generate(); } Index: test/clang-doc/yaml-comments.cpp =================================================================== --- /dev/null +++ test/clang-doc/yaml-comments.cpp @@ -0,0 +1,137 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "" > %t/compile_flags.txt +// RUN: cp "%s" "%t/test.cpp" +// RUN: clang-doc --omit-filenames -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. +/// +///
    +///
  • Testing. +///
+/// +/// \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: - Kind: 'FullComment' +// 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: Params: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'I' +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'J' +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: '7574630614A535710E5A6ABCFFF98BCA2D06A4CA' +// CHECK-NEXT: Name: 'F' +// CHECK-NEXT: Description: +// CHECK-NEXT: - Kind: 'FullComment' +// CHECK-NEXT: Children: +// CHECK-NEXT: - Kind: 'ParagraphComment' +// CHECK-NEXT: Children: +// CHECK-NEXT: - Kind: 'TextComment' +// CHECK-NEXT: Text: ' Bonus comment on definition' +// CHECK-NEXT: Params: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'I' +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'J' +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: ... Index: test/clang-doc/yaml-namespace.cpp =================================================================== --- /dev/null +++ test/clang-doc/yaml-namespace.cpp @@ -0,0 +1,81 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "" > %t/compile_flags.txt +// RUN: cp "%s" "%t/test.cpp" +// RUN: clang-doc --omit-filenames -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: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Name: 'A' +// CHECK-NEXT: - USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5' +// CHECK-NEXT: Name: 'B' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: Functions: +// CHECK-NEXT: - USR: '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC' +// CHECK-NEXT: Name: 'f' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: '39D3C95A5F7CE2BA4937BD7B01BAE09EBC2AD8AC' +// CHECK-NEXT: Name: 'f' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: '9A82CB33ED0FDF81EE383D31CD0957D153C5E840' +// CHECK-NEXT: Name: 'func' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: Params: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'i' +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'enum A::B::E' +// CHECK-NEXT: Enums: +// CHECK-NEXT: - USR: 'E9ABF7E7E2425B626723D41E76E4BC7E7A5BD775' +// CHECK-NEXT: Name: 'E' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: 'E21AF79E2A9D02554BA090D10DF39FE273F5CDB5' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: - USR: '8D042EFFC98B373450BC6B5B90A330C25A150E9C' +// CHECK-NEXT: Type: Namespace +// CHECK-NEXT: Members: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'A::B::X' +// CHECK-NEXT: Type: Enum +// CHECK-NEXT: ... Index: test/clang-doc/yaml-record.cpp =================================================================== --- /dev/null +++ test/clang-doc/yaml-record.cpp @@ -0,0 +1,161 @@ +// RUN: rm -rf %t +// RUN: mkdir %t +// RUN: echo "" > %t/compile_flags.txt +// RUN: cp "%s" "%t/test.cpp" +// RUN: clang-doc --omit-filenames -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: TagType: Union +// CHECK-NEXT: Members: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'A::X' +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'A::Y' +// CHECK-NEXT: - USR: '06B5F6A19BA9F6A832E127C9968282B94619B210' +// CHECK-NEXT: Name: 'C' +// CHECK-NEXT: Members: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'int' +// CHECK-NEXT: Name: 'C::i' +// CHECK-NEXT: - USR: '0921737541208B8FA9BB42B60F78AC1D779AA054' +// CHECK-NEXT: Name: 'D' +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Name: 'E' +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: - USR: 'E3B54702FABFF4037025BA194FC27C47006330B5' +// CHECK-NEXT: Name: 'F' +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: Parents: +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: VirtualParents: +// CHECK-NEXT: - USR: '0921737541208B8FA9BB42B60F78AC1D779AA054' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: - USR: 'CA7C7935730B5EACD25F080E9C83FA087CCDC75E' +// CHECK-NEXT: Name: 'X' +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: - USR: '641AB4A3D36399954ACDE29C7A8833032BF40472' +// CHECK-NEXT: Name: 'Y' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: 'CA7C7935730B5EACD25F080E9C83FA087CCDC75E' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: - USR: '73C72A405B7A00ECFAACE184766DE3ED7C3702DC' +// CHECK-NEXT: Name: 'I' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: 'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E' +// CHECK-NEXT: Type: Function +// CHECK-NEXT: TagType: Class +// CHECK-NEXT: Functions: +// CHECK-NEXT: - USR: 'DEB4AC1CD9253CD9EF7FBE6BCAC506D77984ABD4' +// CHECK-NEXT: Name: 'E' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: IsMethod: true +// CHECK-NEXT: Parent: +// CHECK-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: 'BD2BDEBD423F80BACCEA75DE6D6622D355FC2D17' +// CHECK-NEXT: Name: '~E' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: IsMethod: true +// CHECK-NEXT: Parent: +// CHECK-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: '5093D428CDC62096A67547BA52566E4FB9404EEE' +// CHECK-NEXT: Name: 'ProtectedMethod' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: IsMethod: true +// CHECK-NEXT: Parent: +// CHECK-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: '5093D428CDC62096A67547BA52566E4FB9404EEE' +// CHECK-NEXT: Name: 'ProtectedMethod' +// CHECK-NEXT: Namespace: +// CHECK-NEXT: - USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: IsMethod: true +// CHECK-NEXT: Parent: +// CHECK-NEXT: USR: '289584A8E0FF4178A794622A547AA622503967A1' +// CHECK-NEXT: Type: Record +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: - USR: 'B6AC4C5C9F2EA3F2B3ECE1A33D349F4EE502B24E' +// CHECK-NEXT: Name: 'H' +// CHECK-NEXT: ReturnType: +// CHECK-NEXT: Type: +// CHECK-NEXT: USR: 'void' +// CHECK-NEXT: Enums: +// CHECK-NEXT: - USR: 'FC07BD34D5E77782C263FA944447929EA8753740' +// CHECK-NEXT: Name: 'B' +// CHECK-NEXT: Members: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'X' +// CHECK-NEXT: Type: Enum +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'Y' +// CHECK-NEXT: Type: Enum +// CHECK-NEXT: - USR: '1E3438A08BA22025C0B46289FF0686F92C8924C5' +// CHECK-NEXT: Name: 'Bc' +// CHECK-NEXT: Scoped: true +// CHECK-NEXT: Members: +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'Bc::A' +// CHECK-NEXT: Type: Enum +// CHECK-NEXT: - Type: +// CHECK-NEXT: USR: 'Bc::B' +// CHECK-NEXT: Type: Enum +// CHECK-NEXT: ...