
When a Record is declared in the global namespace, clang-doc serializes it as a child of the global namespace, so the global namespace is now one if its parent namespaces. This namespace was not being included in the list of namespaces of the Info causing paths to be incorrect and the index rendered incorrectly. Affected tests have been fixed. Differential revision: https://reviews.llvm.org/D66298 llvm-svn: 369123
565 lines
25 KiB
C++
565 lines
25 KiB
C++
//===-- clang-doc/SerializeTest.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 "Serialize.h"
|
|
#include "ClangDocTest.h"
|
|
#include "Representation.h"
|
|
#include "clang/AST/Comment.h"
|
|
#include "clang/AST/RecursiveASTVisitor.h"
|
|
#include "gtest/gtest.h"
|
|
|
|
namespace clang {
|
|
namespace doc {
|
|
|
|
class ClangDocSerializeTestVisitor
|
|
: public RecursiveASTVisitor<ClangDocSerializeTestVisitor> {
|
|
|
|
EmittedInfoList &EmittedInfos;
|
|
bool Public;
|
|
|
|
comments::FullComment *getComment(const NamedDecl *D) const {
|
|
if (RawComment *Comment =
|
|
D->getASTContext().getRawCommentForDeclNoCache(D)) {
|
|
Comment->setAttached();
|
|
return Comment->parse(D->getASTContext(), nullptr, D);
|
|
}
|
|
return nullptr;
|
|
}
|
|
|
|
public:
|
|
ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public)
|
|
: EmittedInfos(EmittedInfos), Public(Public) {}
|
|
|
|
template <typename T> bool mapDecl(const T *D) {
|
|
auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
|
|
/*File=*/"test.cpp", true, Public);
|
|
if (I.first)
|
|
EmittedInfos.emplace_back(std::move(I.first));
|
|
if (I.second)
|
|
EmittedInfos.emplace_back(std::move(I.second));
|
|
return true;
|
|
}
|
|
|
|
bool VisitNamespaceDecl(const NamespaceDecl *D) { return mapDecl(D); }
|
|
|
|
bool VisitFunctionDecl(const FunctionDecl *D) {
|
|
// Don't visit CXXMethodDecls twice
|
|
if (dyn_cast<CXXMethodDecl>(D))
|
|
return true;
|
|
return mapDecl(D);
|
|
}
|
|
|
|
bool VisitCXXMethodDecl(const CXXMethodDecl *D) { return mapDecl(D); }
|
|
|
|
bool VisitRecordDecl(const RecordDecl *D) { return mapDecl(D); }
|
|
|
|
bool VisitEnumDecl(const EnumDecl *D) { return mapDecl(D); }
|
|
};
|
|
|
|
void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
|
|
EmittedInfoList &EmittedInfos) {
|
|
auto ASTUnit = clang::tooling::buildASTFromCode(Code);
|
|
auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
|
|
ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
|
|
Visitor.TraverseTranslationUnitDecl(TU);
|
|
ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
|
|
}
|
|
|
|
void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
|
|
bool Public, EmittedInfoList &EmittedInfos,
|
|
std::vector<std::string> &Args) {
|
|
auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
|
|
auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
|
|
ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
|
|
Visitor.TraverseTranslationUnitDecl(TU);
|
|
ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
|
|
}
|
|
|
|
// Test serialization of namespace declarations.
|
|
TEST(SerializeTest, emitNamespaceInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
|
|
/*Public=*/false, Infos);
|
|
|
|
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedA(EmptySID, "A");
|
|
CheckNamespaceInfo(&ExpectedA, A);
|
|
|
|
NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
|
|
NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
|
|
ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
CheckNamespaceInfo(&ExpectedB, B);
|
|
|
|
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
|
|
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
|
FunctionInfo F;
|
|
F.Name = "f";
|
|
F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
|
|
F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
|
F.Access = AccessSpecifier::AS_none;
|
|
ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
|
|
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
|
}
|
|
|
|
TEST(SerializeTest, emitAnonymousNamespaceInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos);
|
|
|
|
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedA(EmptySID);
|
|
ExpectedA.Name = "@nonymous_namespace";
|
|
CheckNamespaceInfo(&ExpectedA, A);
|
|
}
|
|
|
|
// Test serialization of record declarations.
|
|
TEST(SerializeTest, emitRecordInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode(R"raw(class E {
|
|
public:
|
|
E() {}
|
|
protected:
|
|
void ProtectedMethod();
|
|
};
|
|
template <typename T>
|
|
struct F {
|
|
void TemplateMethod();
|
|
};
|
|
template <>
|
|
void F<int>::TemplateMethod();
|
|
typedef struct {} G;)raw",
|
|
10, /*Public=*/false, Infos);
|
|
|
|
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
|
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
|
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedE.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
CheckRecordInfo(&ExpectedE, E);
|
|
|
|
RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2].get());
|
|
RecordInfo ExpectedRecordWithEConstructor(EmptySID);
|
|
FunctionInfo EConstructor;
|
|
EConstructor.Name = "E";
|
|
EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
|
|
EConstructor.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
|
|
EConstructor.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
EConstructor.Access = AccessSpecifier::AS_public;
|
|
EConstructor.IsMethod = true;
|
|
ExpectedRecordWithEConstructor.ChildFunctions.emplace_back(
|
|
std::move(EConstructor));
|
|
CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
|
|
|
|
RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3].get());
|
|
RecordInfo ExpectedRecordWithMethod(EmptySID);
|
|
FunctionInfo Method;
|
|
Method.Name = "ProtectedMethod";
|
|
Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
|
|
Method.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
|
|
Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
|
|
Method.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
Method.Access = AccessSpecifier::AS_protected;
|
|
Method.IsMethod = true;
|
|
ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method));
|
|
CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
|
|
|
|
RecordInfo *F = InfoAsRecord(Infos[4].get());
|
|
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
|
|
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedF.TagType = TagTypeKind::TTK_Struct;
|
|
ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
CheckRecordInfo(&ExpectedF, F);
|
|
|
|
RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6].get());
|
|
RecordInfo ExpectedRecordWithTemplateMethod(EmptySID);
|
|
FunctionInfo TemplateMethod;
|
|
TemplateMethod.Name = "TemplateMethod";
|
|
TemplateMethod.Parent = Reference(EmptySID, "F", InfoType::IT_record);
|
|
TemplateMethod.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
TemplateMethod.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
|
|
TemplateMethod.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
|
|
TemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
TemplateMethod.Access = AccessSpecifier::AS_public;
|
|
TemplateMethod.IsMethod = true;
|
|
ExpectedRecordWithTemplateMethod.ChildFunctions.emplace_back(
|
|
std::move(TemplateMethod));
|
|
CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
|
|
|
|
RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7].get());
|
|
RecordInfo ExpectedTemplatedRecord(EmptySID);
|
|
FunctionInfo SpecializedTemplateMethod;
|
|
SpecializedTemplateMethod.Name = "TemplateMethod";
|
|
SpecializedTemplateMethod.Parent =
|
|
Reference(EmptySID, "F", InfoType::IT_record);
|
|
SpecializedTemplateMethod.ReturnType =
|
|
TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
SpecializedTemplateMethod.Loc.emplace_back(0,
|
|
llvm::SmallString<16>{"test.cpp"});
|
|
SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "F",
|
|
InfoType::IT_record);
|
|
SpecializedTemplateMethod.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
SpecializedTemplateMethod.Access = AccessSpecifier::AS_public;
|
|
SpecializedTemplateMethod.IsMethod = true;
|
|
ExpectedTemplatedRecord.ChildFunctions.emplace_back(
|
|
std::move(SpecializedTemplateMethod));
|
|
CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
|
|
|
|
RecordInfo *G = InfoAsRecord(Infos[8].get());
|
|
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
|
|
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedG.TagType = TagTypeKind::TTK_Struct;
|
|
ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedG.IsTypeDef = true;
|
|
CheckRecordInfo(&ExpectedG, G);
|
|
}
|
|
|
|
// Test serialization of enum declarations.
|
|
TEST(SerializeTest, emitEnumInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
|
|
/*Public=*/false, Infos);
|
|
|
|
NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
|
|
EnumInfo E;
|
|
E.Name = "E";
|
|
E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
E.Members.emplace_back("X");
|
|
E.Members.emplace_back("Y");
|
|
ExpectedNamespaceWithEnum.ChildEnums.emplace_back(std::move(E));
|
|
CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
|
|
|
|
NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
|
|
NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
|
|
EnumInfo G;
|
|
G.Name = "G";
|
|
G.Scoped = true;
|
|
G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
G.Members.emplace_back("A");
|
|
G.Members.emplace_back("B");
|
|
ExpectedNamespaceWithScopedEnum.ChildEnums.emplace_back(std::move(G));
|
|
CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
|
|
}
|
|
|
|
TEST(SerializeTest, emitUndefinedRecordInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("class E;", 2, /*Public=*/false, Infos);
|
|
|
|
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
|
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
|
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedE.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
|
|
CheckRecordInfo(&ExpectedE, E);
|
|
}
|
|
|
|
TEST(SerializeTest, emitRecordMemberInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos);
|
|
|
|
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
|
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
|
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedE.TagType = TagTypeKind::TTK_Struct;
|
|
ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedE.Members.emplace_back("int", "I", AccessSpecifier::AS_public);
|
|
CheckRecordInfo(&ExpectedE, E);
|
|
}
|
|
|
|
TEST(SerializeTest, emitInternalRecordInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos);
|
|
|
|
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
|
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
|
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedE.TagType = TagTypeKind::TTK_Class;
|
|
CheckRecordInfo(&ExpectedE, E);
|
|
|
|
RecordInfo *G = InfoAsRecord(Infos[2].get());
|
|
llvm::SmallString<128> ExpectedGPath("GlobalNamespace/E");
|
|
llvm::sys::path::native(ExpectedGPath);
|
|
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/ExpectedGPath);
|
|
ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedG.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
|
|
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
CheckRecordInfo(&ExpectedG, G);
|
|
}
|
|
|
|
TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos);
|
|
}
|
|
|
|
TEST(SerializeTest, emitPublicFunctionInternalInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
|
|
Infos);
|
|
|
|
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
|
FunctionInfo F;
|
|
F.Name = "F";
|
|
F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
|
|
F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
F.Access = AccessSpecifier::AS_none;
|
|
ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
|
|
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
|
}
|
|
|
|
TEST(SerializeTest, emitInlinedFunctionInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos);
|
|
|
|
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
|
FunctionInfo F;
|
|
F.Name = "F";
|
|
F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
F.Params.emplace_back("int", "I");
|
|
F.Access = AccessSpecifier::AS_none;
|
|
ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
|
|
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
|
}
|
|
|
|
TEST(SerializeTest, emitInheritedRecordInfo) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode(R"raw(class F { protected: void set(int N); };
|
|
class G { public: int get() { return 1; } protected: int I; };
|
|
class E : public F, virtual private G {};
|
|
class H : private E {};
|
|
template <typename T>
|
|
class I {} ;
|
|
class J : public I<int> {} ;)raw",
|
|
14, /*Public=*/false, Infos);
|
|
|
|
RecordInfo *F = InfoAsRecord(Infos[0].get());
|
|
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
|
|
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedF.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
CheckRecordInfo(&ExpectedF, F);
|
|
|
|
RecordInfo *G = InfoAsRecord(Infos[3].get());
|
|
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
|
|
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedG.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedG.Members.emplace_back("int", "I", AccessSpecifier::AS_protected);
|
|
CheckRecordInfo(&ExpectedG, G);
|
|
|
|
RecordInfo *E = InfoAsRecord(Infos[6].get());
|
|
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
|
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
|
|
/*Path*=*/"GlobalNamespace");
|
|
ExpectedE.VirtualParents.emplace_back(
|
|
EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path*=*/"GlobalNamespace");
|
|
ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
|
|
/*Path=*/"GlobalNamespace", false,
|
|
AccessSpecifier::AS_public, true);
|
|
FunctionInfo FunctionSet;
|
|
FunctionSet.Name = "set";
|
|
FunctionSet.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
FunctionSet.Loc.emplace_back();
|
|
FunctionSet.Params.emplace_back("int", "N");
|
|
FunctionSet.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
|
|
FunctionSet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
FunctionSet.Access = AccessSpecifier::AS_protected;
|
|
FunctionSet.IsMethod = true;
|
|
ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSet));
|
|
ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"G",
|
|
/*Path=*/"GlobalNamespace", true,
|
|
AccessSpecifier::AS_private, true);
|
|
FunctionInfo FunctionGet;
|
|
FunctionGet.Name = "get";
|
|
FunctionGet.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
|
|
FunctionGet.DefLoc = Location();
|
|
FunctionGet.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
|
|
FunctionGet.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
FunctionGet.Access = AccessSpecifier::AS_private;
|
|
FunctionGet.IsMethod = true;
|
|
ExpectedE.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGet));
|
|
ExpectedE.Bases.back().Members.emplace_back("int", "I",
|
|
AccessSpecifier::AS_private);
|
|
ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedE.TagType = TagTypeKind::TTK_Class;
|
|
CheckRecordInfo(&ExpectedE, E);
|
|
|
|
RecordInfo *H = InfoAsRecord(Infos[8].get());
|
|
RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
|
|
ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedH.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedH.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
|
|
/*Path=*/"GlobalNamespace");
|
|
ExpectedH.VirtualParents.emplace_back(
|
|
EmptySID, /*Name=*/"G", InfoType::IT_record, /*Path=*/"GlobalNamespace");
|
|
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"E",
|
|
/*Path=*/"GlobalNamespace", false,
|
|
AccessSpecifier::AS_private, true);
|
|
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"F",
|
|
/*Path=*/"GlobalNamespace", false,
|
|
AccessSpecifier::AS_private, false);
|
|
FunctionInfo FunctionSetNew;
|
|
FunctionSetNew.Name = "set";
|
|
FunctionSetNew.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
|
|
FunctionSetNew.Loc.emplace_back();
|
|
FunctionSetNew.Params.emplace_back("int", "N");
|
|
FunctionSetNew.Namespace.emplace_back(EmptySID, "F", InfoType::IT_record);
|
|
FunctionSetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
FunctionSetNew.Access = AccessSpecifier::AS_private;
|
|
FunctionSetNew.IsMethod = true;
|
|
ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionSetNew));
|
|
ExpectedH.Bases.emplace_back(EmptySID, /*Name=*/"G",
|
|
/*Path=*/"GlobalNamespace", true,
|
|
AccessSpecifier::AS_private, false);
|
|
FunctionInfo FunctionGetNew;
|
|
FunctionGetNew.Name = "get";
|
|
FunctionGetNew.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
|
|
FunctionGetNew.DefLoc = Location();
|
|
FunctionGetNew.Namespace.emplace_back(EmptySID, "G", InfoType::IT_record);
|
|
FunctionGetNew.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
FunctionGetNew.Access = AccessSpecifier::AS_private;
|
|
FunctionGetNew.IsMethod = true;
|
|
ExpectedH.Bases.back().ChildFunctions.emplace_back(std::move(FunctionGetNew));
|
|
ExpectedH.Bases.back().Members.emplace_back("int", "I",
|
|
AccessSpecifier::AS_private);
|
|
CheckRecordInfo(&ExpectedH, H);
|
|
|
|
RecordInfo *I = InfoAsRecord(Infos[10].get());
|
|
RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
|
|
ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedI.TagType = TagTypeKind::TTK_Class;
|
|
ExpectedI.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
CheckRecordInfo(&ExpectedI, I);
|
|
|
|
RecordInfo *J = InfoAsRecord(Infos[12].get());
|
|
RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
|
|
ExpectedJ.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
|
InfoType::IT_namespace);
|
|
ExpectedJ.Parents.emplace_back(EmptySID, /*Name=*/"I<int>",
|
|
InfoType::IT_record);
|
|
ExpectedJ.Bases.emplace_back(EmptySID, /*Name=*/"I<int>",
|
|
/*Path=*/"GlobalNamespace", false,
|
|
AccessSpecifier::AS_public, true);
|
|
ExpectedJ.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExpectedJ.TagType = TagTypeKind::TTK_Class;
|
|
CheckRecordInfo(&ExpectedJ, J);
|
|
}
|
|
|
|
TEST(SerializeTest, emitModulePublicLFunctions) {
|
|
EmittedInfoList Infos;
|
|
std::vector<std::string> Args;
|
|
Args.push_back("-fmodules-ts");
|
|
ExtractInfosFromCodeWithArgs(R"raw(export module M;
|
|
int moduleFunction(int x);
|
|
static int staticModuleFunction(int x);
|
|
export double exportedModuleFunction(double y);)raw",
|
|
2, /*Public=*/true, Infos, Args);
|
|
|
|
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
|
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
|
FunctionInfo F;
|
|
F.Name = "moduleFunction";
|
|
F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
|
|
F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
|
|
F.Params.emplace_back("int", "x");
|
|
F.Access = AccessSpecifier::AS_none;
|
|
ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
|
|
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
|
|
|
NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
|
|
NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
|
|
FunctionInfo ExportedF;
|
|
ExportedF.Name = "exportedModuleFunction";
|
|
ExportedF.ReturnType = TypeInfo(EmptySID, "double", InfoType::IT_default);
|
|
ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
|
|
ExportedF.Params.emplace_back("double", "y");
|
|
ExportedF.Access = AccessSpecifier::AS_none;
|
|
ExpectedBWithExportedFunction.ChildFunctions.emplace_back(
|
|
std::move(ExportedF));
|
|
CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
|
|
}
|
|
|
|
// Test serialization of child records in namespaces and other records
|
|
TEST(SerializeTest, emitChildRecords) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
|
|
/*Public=*/false, Infos);
|
|
|
|
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
|
|
NamespaceInfo ExpectedParentA(EmptySID);
|
|
ExpectedParentA.ChildRecords.emplace_back(EmptySID, "A", InfoType::IT_record,
|
|
"GlobalNamespace");
|
|
CheckNamespaceInfo(&ExpectedParentA, ParentA);
|
|
|
|
RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
|
|
RecordInfo ExpectedParentB(EmptySID);
|
|
llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
|
|
llvm::sys::path::native(ExpectedParentBPath);
|
|
ExpectedParentB.ChildRecords.emplace_back(EmptySID, "B", InfoType::IT_record,
|
|
ExpectedParentBPath);
|
|
CheckRecordInfo(&ExpectedParentB, ParentB);
|
|
|
|
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
|
|
NamespaceInfo ExpectedParentC(EmptySID);
|
|
ExpectedParentC.ChildRecords.emplace_back(EmptySID, "C", InfoType::IT_record,
|
|
"@nonymous_namespace");
|
|
CheckNamespaceInfo(&ExpectedParentC, ParentC);
|
|
}
|
|
|
|
// Test serialization of child namespaces
|
|
TEST(SerializeTest, emitChildNamespaces) {
|
|
EmittedInfoList Infos;
|
|
ExtractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
|
|
Infos);
|
|
|
|
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
|
|
NamespaceInfo ExpectedParentA(EmptySID);
|
|
ExpectedParentA.ChildNamespaces.emplace_back(EmptySID, "A",
|
|
InfoType::IT_namespace);
|
|
CheckNamespaceInfo(&ExpectedParentA, ParentA);
|
|
|
|
NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
|
|
NamespaceInfo ExpectedParentB(EmptySID);
|
|
ExpectedParentB.ChildNamespaces.emplace_back(EmptySID, "B",
|
|
InfoType::IT_namespace, "A");
|
|
CheckNamespaceInfo(&ExpectedParentB, ParentB);
|
|
}
|
|
|
|
} // namespace doc
|
|
} // end namespace clang
|