//===-- clang-doc/HTMLGeneratorTest.cpp -----------------------------------===// // // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. // See https://llvm.org/LICENSE.txt for license information. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception // //===----------------------------------------------------------------------===// #include "ClangDocTest.h" #include "Generators.h" #include "Representation.h" #include "Serialize.h" #include "clang/Basic/Version.h" #include "gtest/gtest.h" namespace clang { namespace doc { static const std::string ClangDocVersion = clang::getClangToolFullVersion("clang-doc"); std::unique_ptr getHTMLGenerator() { auto G = doc::findGeneratorByName("html"); if (!G) return nullptr; return std::move(G.get()); } ClangDocContext getClangDocContext(std::vector UserStylesheets = {}, StringRef RepositoryUrl = "") { ClangDocContext CDCtx{ {}, "test-project", {}, {}, {}, RepositoryUrl, UserStylesheets, {}}; CDCtx.UserStylesheets.insert( CDCtx.UserStylesheets.begin(), "../share/clang/clang-doc-default-stylesheet.css"); CDCtx.JsScripts.emplace_back("index.js"); return CDCtx; } TEST(HTMLGeneratorTest, emitNamespaceHTML) { NamespaceInfo I; I.Name = "Namespace"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.ChildNamespaces.emplace_back(EmptySID, "ChildNamespace", InfoType::IT_namespace, "Namespace"); I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "Namespace"); I.ChildFunctions.emplace_back(); I.ChildFunctions.back().Access = AccessSpecifier::AS_none; I.ChildFunctions.back().Name = "OneFunction"; I.ChildEnums.emplace_back(); I.ChildEnums.back().Name = "OneEnum"; auto G = getHTMLGenerator(); assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); ClangDocContext CDCtx = getClangDocContext({"user-provided-stylesheet.css"}); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw( namespace Namespace
test-project

namespace Namespace

Namespaces

Records

Functions

OneFunction

OneFunction()

Enums

enum OneEnum

)raw" + ClangDocVersion + R"raw(
)raw"; EXPECT_EQ(Expected, Actual.str()); } TEST(HTMLGeneratorTest, emitRecordHTML) { RecordInfo I; I.Name = "r"; I.Path = "X/Y/Z"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, true); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); SmallString<16> PathTo; llvm::sys::path::native("path/to", PathTo); I.Members.emplace_back("int", "X/Y", "X", AccessSpecifier::AS_private); I.TagType = TagTypeKind::TTK_Class; I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, PathTo); I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record); I.ChildRecords.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record, "X/Y/Z/r"); I.ChildFunctions.emplace_back(); I.ChildFunctions.back().Name = "OneFunction"; I.ChildEnums.emplace_back(); I.ChildEnums.back().Name = "OneEnum"; auto G = getHTMLGenerator(); assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); ClangDocContext CDCtx = getClangDocContext({}, "http://www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw( class r
test-project

class r

Defined at line 10 of file test.cpp

Inherits from F , G

Members

  • private int X

Records

Functions

OneFunction

public OneFunction()

Enums

enum OneEnum

)raw" + ClangDocVersion + R"raw(
)raw"; EXPECT_EQ(Expected, Actual.str()); } TEST(HTMLGeneratorTest, emitFunctionHTML) { FunctionInfo I; I.Name = "f"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, llvm::SmallString<16>{"dir/test.cpp"}, false); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); I.Access = AccessSpecifier::AS_none; SmallString<16> PathTo; llvm::sys::path::native("path/to", PathTo); I.ReturnType = TypeInfo(EmptySID, "float", InfoType::IT_default, PathTo); I.Params.emplace_back("int", PathTo, "P"); I.IsMethod = true; I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record); auto G = getHTMLGenerator(); assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); ClangDocContext CDCtx = getClangDocContext({}, "https://www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw(
test-project

f

float f( int P)

Defined at line 10 of file dir/test.cpp

)raw" + ClangDocVersion + R"raw(
)raw"; EXPECT_EQ(Expected, Actual.str()); } TEST(HTMLGeneratorTest, emitEnumHTML) { EnumInfo I; I.Name = "e"; I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace); I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}, true); I.Loc.emplace_back(12, llvm::SmallString<16>{"test.cpp"}); I.Members.emplace_back("X"); I.Scoped = true; auto G = getHTMLGenerator(); assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); ClangDocContext CDCtx = getClangDocContext({}, "www.repository.com"); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw(
test-project

enum class e

  • X

Defined at line 10 of file test.cpp

)raw" + ClangDocVersion + R"raw(
)raw"; EXPECT_EQ(Expected, Actual.str()); } TEST(HTMLGeneratorTest, emitCommentHTML) { FunctionInfo I; I.Name = "f"; I.DefLoc = Location(10, llvm::SmallString<16>{"test.cpp"}); I.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default); I.Params.emplace_back("int", "I"); I.Params.emplace_back("int", "J"); I.Access = AccessSpecifier::AS_none; CommentInfo Top; Top.Kind = "FullComment"; Top.Children.emplace_back(std::make_unique()); CommentInfo *BlankLine = Top.Children.back().get(); BlankLine->Kind = "ParagraphComment"; BlankLine->Children.emplace_back(std::make_unique()); BlankLine->Children.back()->Kind = "TextComment"; Top.Children.emplace_back(std::make_unique()); CommentInfo *Brief = Top.Children.back().get(); Brief->Kind = "ParagraphComment"; Brief->Children.emplace_back(std::make_unique()); Brief->Children.back()->Kind = "TextComment"; Brief->Children.back()->Name = "ParagraphComment"; Brief->Children.back()->Text = " Brief description."; Top.Children.emplace_back(std::make_unique()); CommentInfo *Extended = Top.Children.back().get(); Extended->Kind = "ParagraphComment"; Extended->Children.emplace_back(std::make_unique()); Extended->Children.back()->Kind = "TextComment"; Extended->Children.back()->Text = " Extended description that"; Extended->Children.emplace_back(std::make_unique()); Extended->Children.back()->Kind = "TextComment"; Extended->Children.back()->Text = " continues onto the next line."; Top.Children.emplace_back(std::make_unique()); CommentInfo *Entities = Top.Children.back().get(); Entities->Kind = "ParagraphComment"; Entities->Children.emplace_back(std::make_unique()); Entities->Children.back()->Kind = "TextComment"; Entities->Children.back()->Name = "ParagraphComment"; Entities->Children.back()->Text = " Comment with html entities: &, <, >, \", \'."; I.Description.emplace_back(std::move(Top)); auto G = getHTMLGenerator(); assert(G); std::string Buffer; llvm::raw_string_ostream Actual(Buffer); ClangDocContext CDCtx = getClangDocContext(); auto Err = G->generateDocForInfo(&I, Actual, CDCtx); assert(!Err); std::string Expected = R"raw(
test-project

f

void f(int I, int J)

Defined at line 10 of file test.cpp

Brief description.

Extended description that continues onto the next line.

Comment with html entities: &, <, >, ", '.

)raw"; EXPECT_EQ(Expected, Actual.str()); } } // namespace doc } // namespace clang