
This patch refactors CommentKind handling in clang-doc by introducing a strongly typed enum class for better type safety and clarity. It updates all relevant places, including YAML traits and serialization, to work with the new enum. Additionally, it enhances the Mustache-based HTML generation by fully supporting all comment kinds, ensuring accurate structured rendering of comment blocks. The changes simplify future maintenance, improve robustness by eliminating unchecked defaults, and ensure consistency between generators. Fixes https://github.com/llvm/llvm-project/issues/142083
273 lines
11 KiB
C++
273 lines
11 KiB
C++
//===-- clang-doc/MergeTest.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 "Representation.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace doc {
|
|
|
|
TEST(MergeTest, mergeNamespaceInfos) {
|
|
NamespaceInfo One;
|
|
One.Name = "Namespace";
|
|
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
One.Children.Namespaces.emplace_back(NonEmptySID, "ChildNamespace",
|
|
InfoType::IT_namespace);
|
|
One.Children.Records.emplace_back(NonEmptySID, "ChildStruct",
|
|
InfoType::IT_record);
|
|
One.Children.Functions.emplace_back();
|
|
One.Children.Functions.back().Name = "OneFunction";
|
|
One.Children.Functions.back().USR = NonEmptySID;
|
|
One.Children.Enums.emplace_back();
|
|
One.Children.Enums.back().Name = "OneEnum";
|
|
One.Children.Enums.back().USR = NonEmptySID;
|
|
|
|
NamespaceInfo Two;
|
|
Two.Name = "Namespace";
|
|
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Two.Children.Namespaces.emplace_back(EmptySID, "OtherChildNamespace",
|
|
InfoType::IT_namespace);
|
|
Two.Children.Records.emplace_back(EmptySID, "OtherChildStruct",
|
|
InfoType::IT_record);
|
|
Two.Children.Functions.emplace_back();
|
|
Two.Children.Functions.back().Name = "TwoFunction";
|
|
Two.Children.Enums.emplace_back();
|
|
Two.Children.Enums.back().Name = "TwoEnum";
|
|
|
|
std::vector<std::unique_ptr<Info>> Infos;
|
|
Infos.emplace_back(std::make_unique<NamespaceInfo>(std::move(One)));
|
|
Infos.emplace_back(std::make_unique<NamespaceInfo>(std::move(Two)));
|
|
|
|
auto Expected = std::make_unique<NamespaceInfo>();
|
|
Expected->Name = "Namespace";
|
|
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Expected->Children.Namespaces.emplace_back(NonEmptySID, "ChildNamespace",
|
|
InfoType::IT_namespace);
|
|
Expected->Children.Records.emplace_back(NonEmptySID, "ChildStruct",
|
|
InfoType::IT_record);
|
|
Expected->Children.Namespaces.emplace_back(EmptySID, "OtherChildNamespace",
|
|
InfoType::IT_namespace);
|
|
Expected->Children.Records.emplace_back(EmptySID, "OtherChildStruct",
|
|
InfoType::IT_record);
|
|
Expected->Children.Functions.emplace_back();
|
|
Expected->Children.Functions.back().Name = "OneFunction";
|
|
Expected->Children.Functions.back().USR = NonEmptySID;
|
|
Expected->Children.Functions.emplace_back();
|
|
Expected->Children.Functions.back().Name = "TwoFunction";
|
|
Expected->Children.Enums.emplace_back();
|
|
Expected->Children.Enums.back().Name = "OneEnum";
|
|
Expected->Children.Enums.back().USR = NonEmptySID;
|
|
Expected->Children.Enums.emplace_back();
|
|
Expected->Children.Enums.back().Name = "TwoEnum";
|
|
|
|
auto Actual = mergeInfos(Infos);
|
|
assert(Actual);
|
|
CheckNamespaceInfo(InfoAsNamespace(Expected.get()),
|
|
InfoAsNamespace(Actual.get().get()));
|
|
}
|
|
|
|
TEST(MergeTest, mergeRecordInfos) {
|
|
RecordInfo One;
|
|
One.Name = "r";
|
|
One.IsTypeDef = true;
|
|
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
One.DefLoc = Location(10, 10, "test.cpp");
|
|
|
|
One.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
|
One.TagType = TagTypeKind::Class;
|
|
One.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
|
|
One.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
|
|
|
|
One.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
|
|
AccessSpecifier::AS_protected, true);
|
|
One.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
|
|
InfoType::IT_record);
|
|
One.Children.Functions.emplace_back();
|
|
One.Children.Functions.back().Name = "OneFunction";
|
|
One.Children.Functions.back().USR = NonEmptySID;
|
|
One.Children.Enums.emplace_back();
|
|
One.Children.Enums.back().Name = "OneEnum";
|
|
One.Children.Enums.back().USR = NonEmptySID;
|
|
|
|
RecordInfo Two;
|
|
Two.Name = "r";
|
|
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Two.Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
Two.TagType = TagTypeKind::Class;
|
|
|
|
Two.Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
|
|
InfoType::IT_record, "path");
|
|
Two.Children.Functions.emplace_back();
|
|
Two.Children.Functions.back().Name = "TwoFunction";
|
|
Two.Children.Enums.emplace_back();
|
|
Two.Children.Enums.back().Name = "TwoEnum";
|
|
|
|
std::vector<std::unique_ptr<Info>> Infos;
|
|
Infos.emplace_back(std::make_unique<RecordInfo>(std::move(One)));
|
|
Infos.emplace_back(std::make_unique<RecordInfo>(std::move(Two)));
|
|
|
|
auto Expected = std::make_unique<RecordInfo>();
|
|
Expected->Name = "r";
|
|
Expected->IsTypeDef = true;
|
|
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Expected->DefLoc = Location(10, 10, "test.cpp");
|
|
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
Expected->Members.emplace_back(TypeInfo("int"), "X",
|
|
AccessSpecifier::AS_private);
|
|
Expected->TagType = TagTypeKind::Class;
|
|
Expected->Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
|
|
Expected->VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
|
|
Expected->Bases.emplace_back(EmptySID, "F", "path/to/F", true,
|
|
AccessSpecifier::AS_protected, true);
|
|
|
|
Expected->Children.Records.emplace_back(NonEmptySID, "SharedChildStruct",
|
|
InfoType::IT_record, "path");
|
|
Expected->Children.Functions.emplace_back();
|
|
Expected->Children.Functions.back().Name = "OneFunction";
|
|
Expected->Children.Functions.back().USR = NonEmptySID;
|
|
Expected->Children.Functions.emplace_back();
|
|
Expected->Children.Functions.back().Name = "TwoFunction";
|
|
Expected->Children.Enums.emplace_back();
|
|
Expected->Children.Enums.back().Name = "OneEnum";
|
|
Expected->Children.Enums.back().USR = NonEmptySID;
|
|
Expected->Children.Enums.emplace_back();
|
|
Expected->Children.Enums.back().Name = "TwoEnum";
|
|
|
|
auto Actual = mergeInfos(Infos);
|
|
assert(Actual);
|
|
CheckRecordInfo(InfoAsRecord(Expected.get()),
|
|
InfoAsRecord(Actual.get().get()));
|
|
}
|
|
|
|
TEST(MergeTest, mergeFunctionInfos) {
|
|
FunctionInfo One;
|
|
One.Name = "f";
|
|
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
One.DefLoc = Location(10, 10, "test.cpp");
|
|
One.Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
One.IsMethod = true;
|
|
One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
|
|
|
|
One.Description.emplace_back();
|
|
auto *OneFullComment = &One.Description.back();
|
|
OneFullComment->Kind = CommentKind::CK_FullComment;
|
|
auto OneParagraphComment = std::make_unique<CommentInfo>();
|
|
OneParagraphComment->Kind = CommentKind::CK_ParagraphComment;
|
|
auto OneTextComment = std::make_unique<CommentInfo>();
|
|
OneTextComment->Kind = CommentKind::CK_TextComment;
|
|
OneTextComment->Text = "This is a text comment.";
|
|
OneParagraphComment->Children.push_back(std::move(OneTextComment));
|
|
OneFullComment->Children.push_back(std::move(OneParagraphComment));
|
|
|
|
FunctionInfo Two;
|
|
Two.Name = "f";
|
|
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Two.Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
Two.ReturnType = TypeInfo("void");
|
|
Two.Params.emplace_back(TypeInfo("int"), "P");
|
|
|
|
Two.Description.emplace_back();
|
|
auto *TwoFullComment = &Two.Description.back();
|
|
TwoFullComment->Kind = CommentKind::CK_FullComment;
|
|
auto TwoParagraphComment = std::make_unique<CommentInfo>();
|
|
TwoParagraphComment->Kind = CommentKind::CK_ParagraphComment;
|
|
auto TwoTextComment = std::make_unique<CommentInfo>();
|
|
TwoTextComment->Kind = CommentKind::CK_TextComment;
|
|
TwoTextComment->Text = "This is a text comment.";
|
|
TwoParagraphComment->Children.push_back(std::move(TwoTextComment));
|
|
TwoFullComment->Children.push_back(std::move(TwoParagraphComment));
|
|
|
|
std::vector<std::unique_ptr<Info>> Infos;
|
|
Infos.emplace_back(std::make_unique<FunctionInfo>(std::move(One)));
|
|
Infos.emplace_back(std::make_unique<FunctionInfo>(std::move(Two)));
|
|
|
|
auto Expected = std::make_unique<FunctionInfo>();
|
|
Expected->Name = "f";
|
|
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Expected->DefLoc = Location(10, 10, "test.cpp");
|
|
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
Expected->ReturnType = TypeInfo("void");
|
|
Expected->Params.emplace_back(TypeInfo("int"), "P");
|
|
Expected->IsMethod = true;
|
|
Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
|
|
|
|
Expected->Description.emplace_back();
|
|
auto *ExpectedFullComment = &Expected->Description.back();
|
|
ExpectedFullComment->Kind = CommentKind::CK_FullComment;
|
|
auto ExpectedParagraphComment = std::make_unique<CommentInfo>();
|
|
ExpectedParagraphComment->Kind = CommentKind::CK_ParagraphComment;
|
|
auto ExpectedTextComment = std::make_unique<CommentInfo>();
|
|
ExpectedTextComment->Kind = CommentKind::CK_TextComment;
|
|
ExpectedTextComment->Text = "This is a text comment.";
|
|
ExpectedParagraphComment->Children.push_back(std::move(ExpectedTextComment));
|
|
ExpectedFullComment->Children.push_back(std::move(ExpectedParagraphComment));
|
|
|
|
auto Actual = mergeInfos(Infos);
|
|
assert(Actual);
|
|
CheckFunctionInfo(InfoAsFunction(Expected.get()),
|
|
InfoAsFunction(Actual.get().get()));
|
|
}
|
|
|
|
TEST(MergeTest, mergeEnumInfos) {
|
|
EnumInfo One;
|
|
One.Name = "e";
|
|
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
One.DefLoc = Location(10, 10, "test.cpp");
|
|
One.Loc.emplace_back(12, 12, "test.cpp");
|
|
|
|
One.Scoped = true;
|
|
|
|
EnumInfo Two;
|
|
Two.Name = "e";
|
|
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Two.Loc.emplace_back(20, 20, "test.cpp");
|
|
|
|
Two.Members.emplace_back("X");
|
|
Two.Members.emplace_back("Y");
|
|
|
|
std::vector<std::unique_ptr<Info>> Infos;
|
|
Infos.emplace_back(std::make_unique<EnumInfo>(std::move(One)));
|
|
Infos.emplace_back(std::make_unique<EnumInfo>(std::move(Two)));
|
|
|
|
auto Expected = std::make_unique<EnumInfo>();
|
|
Expected->Name = "e";
|
|
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
|
|
Expected->DefLoc = Location(10, 10, "test.cpp");
|
|
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
|
Expected->Loc.emplace_back(20, 20, "test.cpp");
|
|
|
|
Expected->Members.emplace_back("X");
|
|
Expected->Members.emplace_back("Y");
|
|
Expected->Scoped = true;
|
|
|
|
auto Actual = mergeInfos(Infos);
|
|
assert(Actual);
|
|
CheckEnumInfo(InfoAsEnum(Expected.get()), InfoAsEnum(Actual.get().get()));
|
|
}
|
|
|
|
} // namespace doc
|
|
} // namespace clang
|