Revert clang-doc arena merging patches (#191668)
This is a set of squashed reverts of recent clang doc patches, since its breaking something on Darwin builders: https://lab.llvm.org/buildbot/#/builders/23/builds/19172 Revert "[clang-doc][nfc] Default initialize all StringRef members (#191641)" This reverts commit155b9b354c. Revert "[clang-doc] Initialize StringRef members in Info types (#191637)" This reverts commit489dab3827. Revert "[clang-doc] Initialize member variable (#191570)" This reverts commit5d64a44a84. Revert "[clang-doc] Merge data into persistent memory (#190056)" This reverts commit21e0034c69. Revert "[clang-doc] Support deep copy between arenas for merging (#190055)" This reverts commitc70dae8b0c.
This commit is contained in:
@@ -129,15 +129,14 @@ static llvm::Error decodeRecord(const Record &R, FieldId &Field,
|
||||
"invalid value for FieldId");
|
||||
}
|
||||
|
||||
static llvm::Error decodeRecord(const Record &R, OwningVec<Location> &Field,
|
||||
static llvm::Error decodeRecord(const Record &R,
|
||||
llvm::SmallVectorImpl<Location> &Field,
|
||||
llvm::StringRef Blob) {
|
||||
if (R[0] > INT_MAX)
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"integer too large to parse");
|
||||
|
||||
Field.push_back(*allocatePtr<Location>(static_cast<int>(R[0]),
|
||||
static_cast<int>(R[1]), Blob,
|
||||
static_cast<bool>(R[2])));
|
||||
Field.emplace_back(static_cast<int>(R[0]), static_cast<int>(R[1]), Blob,
|
||||
static_cast<bool>(R[2]));
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
@@ -426,99 +425,6 @@ ClangDocBitcodeReader::parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T, typename BlockBeginHandler, typename BlockEndHandler>
|
||||
llvm::Error ClangDocBitcodeReader::parseBlock(unsigned ID, T I,
|
||||
BlockBeginHandler &&BBH,
|
||||
BlockEndHandler &&BEH) {
|
||||
return parseBlock(ID, I, std::forward<BlockBeginHandler>(BBH),
|
||||
std::forward<BlockEndHandler>(BEH),
|
||||
[&](unsigned Code) { return readRecord(Code, I); });
|
||||
}
|
||||
|
||||
template <typename ChildType>
|
||||
llvm::Expected<bool> ClangDocBitcodeReader::readSubBlockIfMatch(
|
||||
unsigned ID, unsigned TargetID, llvm::SmallVectorImpl<ChildType> &V) {
|
||||
if (ID != TargetID)
|
||||
return false;
|
||||
ChildType Val;
|
||||
if (auto Err = readBlock(ID, &Val))
|
||||
return std::move(Err);
|
||||
V.push_back(std::move(Val));
|
||||
return true;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static llvm::Error addReference(T I, Reference &&R, FieldId F);
|
||||
|
||||
template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F);
|
||||
template <> llvm::Error addReference(TypeInfo *I, Reference &&R, FieldId F);
|
||||
template <>
|
||||
llvm::Error addReference(FieldTypeInfo *I, Reference &&R, FieldId F);
|
||||
template <>
|
||||
llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F);
|
||||
template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F);
|
||||
template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F);
|
||||
template <>
|
||||
llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F);
|
||||
template <> llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F);
|
||||
template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F);
|
||||
template <>
|
||||
llvm::Error addReference(ConstraintInfo *I, Reference &&R, FieldId F);
|
||||
template <>
|
||||
llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F);
|
||||
|
||||
template <typename InfoT>
|
||||
llvm::Expected<bool> ClangDocBitcodeReader::routeReferenceBlock(
|
||||
unsigned ID, llvm::SmallVectorImpl<Reference> &Namespaces, InfoT *I,
|
||||
std::initializer_list<ReferenceMap> Mappings) {
|
||||
if (ID != BI_REFERENCE_BLOCK_ID)
|
||||
return false;
|
||||
Reference R;
|
||||
if (auto Err = readBlock(ID, &R))
|
||||
return std::move(Err);
|
||||
|
||||
for (const auto &Map : Mappings) {
|
||||
if (CurrentReferenceField == Map.Field) {
|
||||
Map.Vec->push_back(std::move(R));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (CurrentReferenceField == FieldId::F_namespace) {
|
||||
Namespaces.push_back(std::move(R));
|
||||
return true;
|
||||
}
|
||||
|
||||
if (auto Err = addReference(I, std::move(R), CurrentReferenceField))
|
||||
return std::move(Err);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID,
|
||||
TemplateSpecializationInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I);
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I);
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
|
||||
llvm::SmallVector<CommentInfo> LocalChildren;
|
||||
@@ -542,13 +448,25 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
|
||||
if (!LocalChildren.empty())
|
||||
I->Children =
|
||||
allocateArray<CommentInfo>(LocalChildren, TransientArena);
|
||||
if (!AttrKeys.empty())
|
||||
I->AttrKeys = allocateArray(AttrKeys, TransientArena);
|
||||
if (!AttrValues.empty())
|
||||
I->AttrValues = allocateArray(AttrValues, TransientArena);
|
||||
if (!Args.empty())
|
||||
I->Args = allocateArray(Args, TransientArena);
|
||||
|
||||
if (!AttrKeys.empty()) {
|
||||
StringRef *KeysMem =
|
||||
TransientArena.Allocate<StringRef>(AttrKeys.size());
|
||||
std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
|
||||
I->AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
|
||||
}
|
||||
if (!AttrValues.empty()) {
|
||||
StringRef *ValuesMem =
|
||||
TransientArena.Allocate<StringRef>(AttrValues.size());
|
||||
std::uninitialized_copy(AttrValues.begin(), AttrValues.end(),
|
||||
ValuesMem);
|
||||
I->AttrValues =
|
||||
llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
|
||||
}
|
||||
if (!Args.empty()) {
|
||||
StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
|
||||
std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
|
||||
I->Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
|
||||
}
|
||||
return llvm::Error::success();
|
||||
},
|
||||
[&](unsigned BlockOrCode) -> llvm::Error {
|
||||
@@ -563,219 +481,6 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, CommentInfo *I) {
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FunctionInfo *I) {
|
||||
llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
|
||||
llvm::SmallVector<Reference> LocalNamespaces;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID,
|
||||
LocalParams);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
I->Params = allocateArray(LocalParams, TransientArena);
|
||||
if (!LocalNamespaces.empty())
|
||||
I->Namespace = allocateArray(LocalNamespaces, TransientArena);
|
||||
return llvm::Error::success();
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, EnumInfo *I) {
|
||||
llvm::SmallVector<EnumValueInfo, 4> LocalMembers;
|
||||
llvm::SmallVector<Reference> LocalNamespaces;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_ENUM_VALUE_BLOCK_ID,
|
||||
LocalMembers);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
I->Members = allocateArray(LocalMembers, TransientArena);
|
||||
if (!LocalNamespaces.empty())
|
||||
I->Namespace = allocateArray(LocalNamespaces, TransientArena);
|
||||
return llvm::Error::success();
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, BaseRecordInfo *I) {
|
||||
// BaseRecordInfo and FriendInfo are over 256 bytes and require a size.
|
||||
llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
|
||||
llvm::SmallVector<FriendInfo, 4> LocalFriends;
|
||||
llvm::SmallVector<MemberTypeInfo> LocalMembers;
|
||||
llvm::SmallVector<Reference> LocalParents;
|
||||
llvm::SmallVector<Reference> LocalVirtualParents;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID,
|
||||
LocalMembers);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID,
|
||||
LocalBases);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
llvm::SmallVector<Reference> Dummy;
|
||||
return routeReferenceBlock(
|
||||
BlockOrCode, Dummy, I,
|
||||
{{FieldId::F_parent, &LocalParents},
|
||||
{FieldId::F_vparent, &LocalVirtualParents}});
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
if (!LocalMembers.empty())
|
||||
I->Members = allocateArray(LocalMembers, TransientArena);
|
||||
if (!LocalParents.empty())
|
||||
I->Parents = allocateArray(LocalParents, TransientArena);
|
||||
if (!LocalVirtualParents.empty())
|
||||
I->VirtualParents =
|
||||
allocateArray(LocalVirtualParents, TransientArena);
|
||||
I->Bases = allocateArray(LocalBases, TransientArena);
|
||||
I->Friends = allocateArray(LocalFriends, TransientArena);
|
||||
return llvm::Error::success();
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, RecordInfo *I) {
|
||||
llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
|
||||
llvm::SmallVector<FriendInfo, 4> LocalFriends;
|
||||
llvm::SmallVector<MemberTypeInfo> LocalMembers;
|
||||
llvm::SmallVector<Reference> LocalParents;
|
||||
llvm::SmallVector<Reference> LocalVirtualParents;
|
||||
llvm::SmallVector<Reference> LocalNamespaces;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_MEMBER_TYPE_BLOCK_ID,
|
||||
LocalMembers);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
B = readSubBlockIfMatch(BlockOrCode, BI_BASE_RECORD_BLOCK_ID,
|
||||
LocalBases);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
B = readSubBlockIfMatch(BlockOrCode, BI_FRIEND_BLOCK_ID, LocalFriends);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
return routeReferenceBlock(
|
||||
BlockOrCode, LocalNamespaces, I,
|
||||
{{FieldId::F_parent, &LocalParents},
|
||||
{FieldId::F_vparent, &LocalVirtualParents}});
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
if (!LocalMembers.empty())
|
||||
I->Members = allocateArray(LocalMembers, TransientArena);
|
||||
if (!LocalParents.empty())
|
||||
I->Parents = allocateArray(LocalParents, TransientArena);
|
||||
if (!LocalVirtualParents.empty())
|
||||
I->VirtualParents =
|
||||
allocateArray(LocalVirtualParents, TransientArena);
|
||||
if (!LocalNamespaces.empty())
|
||||
I->Namespace = allocateArray(LocalNamespaces, TransientArena);
|
||||
I->Bases = allocateArray(LocalBases, TransientArena);
|
||||
I->Friends = allocateArray(LocalFriends, TransientArena);
|
||||
return llvm::Error::success();
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TemplateInfo *I) {
|
||||
llvm::SmallVector<TemplateParamInfo> LocalParams;
|
||||
llvm::SmallVector<ConstraintInfo> LocalConstraints;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID,
|
||||
LocalParams);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
B = readSubBlockIfMatch(BlockOrCode, BI_CONSTRAINT_BLOCK_ID,
|
||||
LocalConstraints);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
I->Params = allocateArray(LocalParams, TransientArena);
|
||||
I->Constraints = allocateArray(LocalConstraints, TransientArena);
|
||||
return llvm::Error::success();
|
||||
},
|
||||
[&](unsigned BlockOrCode) -> llvm::Error {
|
||||
return readRecord(BlockOrCode, I);
|
||||
});
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID,
|
||||
TemplateSpecializationInfo *I) {
|
||||
llvm::SmallVector<TemplateParamInfo> LocalParams;
|
||||
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_TEMPLATE_PARAM_BLOCK_ID,
|
||||
LocalParams);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
I->Params = allocateArray(LocalParams, TransientArena);
|
||||
return llvm::Error::success();
|
||||
},
|
||||
[&](unsigned BlockOrCode) -> llvm::Error {
|
||||
return readRecord(BlockOrCode, I);
|
||||
});
|
||||
}
|
||||
|
||||
static llvm::Error parseRecord(const Record &R, unsigned ID,
|
||||
llvm::StringRef Blob, Reference *I, FieldId &F) {
|
||||
switch (ID) {
|
||||
@@ -874,25 +579,51 @@ static llvm::Error parseRecord(const Record &R, unsigned ID, StringRef Blob,
|
||||
"invalid field for Friend");
|
||||
}
|
||||
|
||||
template <typename, typename = void>
|
||||
struct has_description : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_description<T, std::void_t<decltype(std::declval<T>().Description)>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename T> static llvm::Expected<CommentInfo *> getCommentInfo(T I) {
|
||||
if constexpr (std::is_pointer_v<T>) {
|
||||
using Pointee = std::remove_pointer_t<T>;
|
||||
if constexpr (has_description<Pointee>::value) {
|
||||
auto *NewComment = allocatePtr<CommentInfo>();
|
||||
I->Description.push_back(*NewComment);
|
||||
return NewComment;
|
||||
}
|
||||
}
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid type cannot contain CommentInfo");
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(FunctionInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(NamespaceInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(RecordInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(MemberTypeInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(TypedefInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(EnumValueInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> llvm::Expected<CommentInfo *> getCommentInfo(ConceptInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> Expected<CommentInfo *> getCommentInfo(VarInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
template <> Expected<CommentInfo *> getCommentInfo(FriendInfo *I) {
|
||||
return &I->Description.emplace_back();
|
||||
}
|
||||
|
||||
// When readSubBlock encounters a TypeInfo sub-block, it calls addTypeInfo on
|
||||
// the parent block to set it. The template specializations define what to do
|
||||
// for each supported parent block.
|
||||
@@ -902,11 +633,26 @@ static llvm::Error addTypeInfo(T I, TTypeInfo &&TI) {
|
||||
"invalid type cannot contain TypeInfo");
|
||||
}
|
||||
|
||||
template <> llvm::Error addTypeInfo(RecordInfo *I, MemberTypeInfo &&T) {
|
||||
I->Members.emplace_back(std::move(T));
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <> llvm::Error addTypeInfo(BaseRecordInfo *I, MemberTypeInfo &&T) {
|
||||
I->Members.emplace_back(std::move(T));
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <> llvm::Error addTypeInfo(FunctionInfo *I, TypeInfo &&T) {
|
||||
I->ReturnType = std::move(T);
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <> llvm::Error addTypeInfo(FunctionInfo *I, FieldTypeInfo &&T) {
|
||||
I->Params.emplace_back(std::move(T));
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <> llvm::Error addTypeInfo(FriendInfo *I, TypeInfo &&T) {
|
||||
I->ReturnType.emplace(std::move(T));
|
||||
return llvm::Error::success();
|
||||
@@ -935,6 +681,9 @@ static llvm::Error addReference(T I, Reference &&R, FieldId F) {
|
||||
|
||||
template <> llvm::Error addReference(VarInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"VarInfo cannot contain this Reference");
|
||||
@@ -978,6 +727,9 @@ llvm::Error addReference(MemberTypeInfo *I, Reference &&R, FieldId F) {
|
||||
|
||||
template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid type cannot contain Reference");
|
||||
@@ -986,6 +738,9 @@ template <> llvm::Error addReference(EnumInfo *I, Reference &&R, FieldId F) {
|
||||
|
||||
template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid type cannot contain Reference");
|
||||
@@ -995,13 +750,16 @@ template <> llvm::Error addReference(TypedefInfo *I, Reference &&R, FieldId F) {
|
||||
template <>
|
||||
llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_child_namespace:
|
||||
I->Children.Namespaces.push_back(
|
||||
*allocatePtr<Reference>(TransientArena, std::move(R)));
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
case FieldId::F_child_namespace: {
|
||||
Reference *NewR = allocatePtr<Reference>(TransientArena, std::move(R));
|
||||
I->Children.Namespaces.push_back(*NewR);
|
||||
return llvm::Error::success();
|
||||
}
|
||||
case FieldId::F_child_record:
|
||||
I->Children.Records.push_back(
|
||||
*allocatePtr<Reference>(TransientArena, std::move(R)));
|
||||
I->Children.Records.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
@@ -1012,6 +770,9 @@ llvm::Error addReference(NamespaceInfo *I, Reference &&R, FieldId F) {
|
||||
template <>
|
||||
llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
case FieldId::F_parent:
|
||||
I->Parent = std::move(R);
|
||||
return llvm::Error::success();
|
||||
@@ -1023,9 +784,17 @@ llvm::Error addReference(FunctionInfo *I, Reference &&R, FieldId F) {
|
||||
|
||||
template <> llvm::Error addReference(RecordInfo *I, Reference &&R, FieldId F) {
|
||||
switch (F) {
|
||||
case FieldId::F_namespace:
|
||||
I->Namespace.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
case FieldId::F_parent:
|
||||
I->Parents.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
case FieldId::F_vparent:
|
||||
I->VirtualParents.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
case FieldId::F_child_record:
|
||||
I->Children.Records.push_back(
|
||||
*allocatePtr<Reference>(TransientArena, std::move(R)));
|
||||
I->Children.Records.emplace_back(std::move(R));
|
||||
return llvm::Error::success();
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
@@ -1054,42 +823,54 @@ llvm::Error addReference(FriendInfo *Friend, Reference &&R, FieldId F) {
|
||||
"Friend cannot contain this Reference");
|
||||
}
|
||||
|
||||
static auto &getList(ScopeChildren &C, FunctionInfo *) { return C.Functions; }
|
||||
static auto &getList(ScopeChildren &C, EnumInfo *) { return C.Enums; }
|
||||
static auto &getList(ScopeChildren &C, TypedefInfo *) { return C.Typedefs; }
|
||||
static auto &getList(ScopeChildren &C, ConceptInfo *) { return C.Concepts; }
|
||||
static auto &getList(ScopeChildren &C, VarInfo *) { return C.Variables; }
|
||||
|
||||
template <typename T, typename = void> struct has_children : std::false_type {};
|
||||
template <typename T>
|
||||
struct has_children<T, std::void_t<decltype(std::declval<T>().Children)>>
|
||||
: std::is_same<decltype(std::declval<T>().Children), ScopeChildren> {};
|
||||
|
||||
template <typename TargetChild, typename = void>
|
||||
struct is_valid_child : std::false_type {};
|
||||
template <typename TargetChild>
|
||||
struct is_valid_child<
|
||||
TargetChild, std::void_t<decltype(getList(std::declval<ScopeChildren &>(),
|
||||
std::declval<TargetChild *>()))>>
|
||||
: std::true_type {};
|
||||
|
||||
template <typename Target, typename Child>
|
||||
static void addChild(Target I, Child &&R) {
|
||||
if constexpr (std::is_pointer_v<Target>) {
|
||||
using Pointee = std::remove_pointer_t<Target>;
|
||||
if constexpr (has_children<Pointee>::value) {
|
||||
using BareChild = std::remove_cv_t<std::remove_reference_t<Child>>;
|
||||
if constexpr (is_valid_child<BareChild>::value) {
|
||||
auto *Node = allocatePtr<BareChild>(std::move(R));
|
||||
getList(I->Children, Node).push_back(*Node);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
template <typename T, typename ChildInfoType>
|
||||
static void addChild(T I, ChildInfoType &&R) {
|
||||
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid child type for info"));
|
||||
}
|
||||
|
||||
// Namespace children:
|
||||
template <> void addChild(NamespaceInfo *I, FunctionInfo &&R) {
|
||||
I->Children.Functions.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(NamespaceInfo *I, EnumInfo &&R) {
|
||||
I->Children.Enums.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(NamespaceInfo *I, TypedefInfo &&R) {
|
||||
I->Children.Typedefs.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(NamespaceInfo *I, ConceptInfo &&R) {
|
||||
I->Children.Concepts.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(NamespaceInfo *I, VarInfo &&R) {
|
||||
I->Children.Variables.emplace_back(std::move(R));
|
||||
}
|
||||
|
||||
// Record children:
|
||||
template <> void addChild(RecordInfo *I, FunctionInfo &&R) {
|
||||
I->Children.Functions.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(RecordInfo *I, EnumInfo &&R) {
|
||||
I->Children.Enums.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(RecordInfo *I, TypedefInfo &&R) {
|
||||
I->Children.Typedefs.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(RecordInfo *I, FriendInfo &&R) {
|
||||
I->Friends.emplace_back(std::move(R));
|
||||
}
|
||||
|
||||
// Other types of children:
|
||||
template <> void addChild(EnumInfo *I, EnumValueInfo &&R) {
|
||||
I->Members.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(RecordInfo *I, BaseRecordInfo &&R) {
|
||||
I->Bases.emplace_back(std::move(R));
|
||||
}
|
||||
template <> void addChild(BaseRecordInfo *I, FunctionInfo &&R) {
|
||||
I->Children.Functions.emplace_back(std::move(R));
|
||||
}
|
||||
|
||||
// TemplateParam children. These go into either a TemplateInfo (for template
|
||||
// parameters) or TemplateSpecializationInfo (for the specialization's
|
||||
// parameters).
|
||||
@@ -1098,6 +879,13 @@ template <typename T> static void addTemplateParam(T I, TemplateParamInfo &&P) {
|
||||
llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid container for template parameter"));
|
||||
}
|
||||
template <> void addTemplateParam(TemplateInfo *I, TemplateParamInfo &&P) {
|
||||
I->Params.emplace_back(std::move(P));
|
||||
}
|
||||
template <>
|
||||
void addTemplateParam(TemplateSpecializationInfo *I, TemplateParamInfo &&P) {
|
||||
I->Params.emplace_back(std::move(P));
|
||||
}
|
||||
|
||||
// Template info. These apply to either records or functions.
|
||||
template <typename T> static void addTemplate(T I, TemplateInfo &&P) {
|
||||
@@ -1137,6 +925,9 @@ template <typename T> static void addConstraint(T I, ConstraintInfo &&C) {
|
||||
ExitOnErr(llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"invalid container for constraint info"));
|
||||
}
|
||||
template <> void addConstraint(TemplateInfo *I, ConstraintInfo &&C) {
|
||||
I->Constraints.emplace_back(std::move(C));
|
||||
}
|
||||
|
||||
// Read records from bitcode into a given info.
|
||||
template <typename T>
|
||||
@@ -1161,37 +952,6 @@ llvm::Error ClangDocBitcodeReader::readRecord(unsigned ID, Reference *I) {
|
||||
}
|
||||
|
||||
// Read a block of records into a single info.
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, VarInfo *I) {
|
||||
return readBlockWithNamespace(ID, I);
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, TypedefInfo *I) {
|
||||
return readBlockWithNamespace(ID, I);
|
||||
}
|
||||
|
||||
template <>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, NamespaceInfo *I) {
|
||||
return readBlockWithNamespace(ID, I);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::Error ClangDocBitcodeReader::readBlockWithNamespace(unsigned ID, T I) {
|
||||
llvm::SmallVector<Reference> LocalNamespaces;
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
return routeReferenceBlock(BlockOrCode, LocalNamespaces, I);
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
if (!LocalNamespaces.empty())
|
||||
I->Namespace = allocateArray(LocalNamespaces, TransientArena);
|
||||
return llvm::Error::success();
|
||||
});
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, T I) {
|
||||
return parseBlock(
|
||||
@@ -1209,13 +969,13 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
|
||||
return parseBlock(
|
||||
ID, I,
|
||||
[&](unsigned BlockOrCode) -> llvm::Expected<bool> {
|
||||
auto B = readSubBlockIfMatch(BlockOrCode, BI_FIELD_TYPE_BLOCK_ID,
|
||||
LocalParams);
|
||||
if (!B)
|
||||
return B.takeError();
|
||||
if (*B)
|
||||
if (BlockOrCode == BI_FIELD_TYPE_BLOCK_ID) {
|
||||
FieldTypeInfo FI;
|
||||
if (auto Err = readBlock(BlockOrCode, &FI))
|
||||
return std::move(Err);
|
||||
LocalParams.push_back(std::move(FI));
|
||||
return true;
|
||||
|
||||
}
|
||||
return false;
|
||||
},
|
||||
[&]() -> llvm::Error {
|
||||
@@ -1228,19 +988,27 @@ llvm::Error ClangDocBitcodeReader::readBlock(unsigned ID, FriendInfo *I) {
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: fix inconsistentent returning of errors in add callbacks.
|
||||
// Once that's fixed, we only need one handleSubBlock.
|
||||
template <typename InfoType, typename T, typename Callback>
|
||||
llvm::Error ClangDocBitcodeReader::handleSubBlock(unsigned ID, T Parent,
|
||||
Callback Function) {
|
||||
InfoType Info;
|
||||
if (auto Err = readBlock(ID, &Info))
|
||||
return Err;
|
||||
if constexpr (std::is_void_v<
|
||||
std::invoke_result_t<Callback, T, InfoType &&>>) {
|
||||
Function(Parent, std::move(Info));
|
||||
return llvm::Error::success();
|
||||
} else {
|
||||
return Function(Parent, std::move(Info));
|
||||
}
|
||||
Function(Parent, std::move(Info));
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <typename InfoType, typename T, typename Callback>
|
||||
llvm::Error ClangDocBitcodeReader::handleTypeSubBlock(unsigned ID, T Parent,
|
||||
Callback Function) {
|
||||
InfoType Info;
|
||||
if (auto Err = readBlock(ID, &Info))
|
||||
return Err;
|
||||
if (auto Err = Function(Parent, std::move(Info)))
|
||||
return Err;
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -1264,15 +1032,15 @@ llvm::Error ClangDocBitcodeReader::readSubBlock(unsigned ID, T I) {
|
||||
return llvm::Error::success();
|
||||
}
|
||||
case BI_TYPE_BLOCK_ID: {
|
||||
return handleSubBlock<TypeInfo>(ID, I,
|
||||
CreateAddFunc(addTypeInfo<T, TypeInfo>));
|
||||
return handleTypeSubBlock<TypeInfo>(
|
||||
ID, I, CreateAddFunc(addTypeInfo<T, TypeInfo>));
|
||||
}
|
||||
case BI_FIELD_TYPE_BLOCK_ID: {
|
||||
return handleSubBlock<FieldTypeInfo>(
|
||||
return handleTypeSubBlock<FieldTypeInfo>(
|
||||
ID, I, CreateAddFunc(addTypeInfo<T, FieldTypeInfo>));
|
||||
}
|
||||
case BI_MEMBER_TYPE_BLOCK_ID: {
|
||||
return handleSubBlock<MemberTypeInfo>(
|
||||
return handleTypeSubBlock<MemberTypeInfo>(
|
||||
ID, I, CreateAddFunc(addTypeInfo<T, MemberTypeInfo>));
|
||||
}
|
||||
case BI_REFERENCE_BLOCK_ID: {
|
||||
|
||||
@@ -44,32 +44,12 @@ private:
|
||||
// Read a block of records into a single Info struct, calls readRecord on each
|
||||
// record found.
|
||||
template <typename T> llvm::Error readBlock(unsigned ID, T I);
|
||||
template <typename T> llvm::Error readBlockWithNamespace(unsigned ID, T I);
|
||||
|
||||
template <typename T, typename BlockBeginHandler, typename BlockEndHandler,
|
||||
typename RecordHandler>
|
||||
llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
|
||||
BlockEndHandler &&BEH, RecordHandler &&RH);
|
||||
|
||||
template <typename T, typename BlockBeginHandler, typename BlockEndHandler>
|
||||
llvm::Error parseBlock(unsigned ID, T I, BlockBeginHandler &&BBH,
|
||||
BlockEndHandler &&BEH);
|
||||
|
||||
template <typename ChildType>
|
||||
llvm::Expected<bool> readSubBlockIfMatch(unsigned ID, unsigned TargetID,
|
||||
llvm::SmallVectorImpl<ChildType> &V);
|
||||
|
||||
struct ReferenceMap {
|
||||
FieldId Field;
|
||||
llvm::SmallVectorImpl<Reference> *Vec;
|
||||
};
|
||||
|
||||
template <typename InfoT>
|
||||
llvm::Expected<bool>
|
||||
routeReferenceBlock(unsigned ID, llvm::SmallVectorImpl<Reference> &Namespaces,
|
||||
InfoT *I,
|
||||
std::initializer_list<ReferenceMap> Mappings = {});
|
||||
|
||||
// Step through a block of records to find the next data field.
|
||||
template <typename T> llvm::Error readSubBlock(unsigned ID, T I);
|
||||
|
||||
|
||||
@@ -27,7 +27,6 @@ class JSONGenerator : public Generator {
|
||||
void serializeCommonChildren(
|
||||
const ScopeChildren &Children, json::Object &Obj,
|
||||
std::optional<ReferenceFunc> MDReferenceLambda = std::nullopt);
|
||||
void serializeContexts(Info *I, llvm::StringMap<OwnedPtr<Info>> &Infos);
|
||||
void serializeInfo(const ConstraintInfo &I, Object &Obj);
|
||||
void serializeInfo(const TemplateInfo &Template, Object &Obj);
|
||||
void serializeInfo(const ConceptInfo &I, Object &Obj);
|
||||
@@ -62,12 +61,10 @@ class JSONGenerator : public Generator {
|
||||
};
|
||||
}
|
||||
|
||||
llvm::DenseMap<const Info *, SmallVector<Context, 4>> ContextsMap;
|
||||
const ClangDocContext *CDCtx;
|
||||
bool Markdown;
|
||||
|
||||
public:
|
||||
static const char *Format;
|
||||
const ClangDocContext *CDCtx;
|
||||
bool Markdown;
|
||||
|
||||
Error generateDocumentation(StringRef RootDir,
|
||||
llvm::StringMap<OwnedPtr<doc::Info>> Infos,
|
||||
@@ -323,20 +320,13 @@ static Object serializeComment(const CommentInfo &I, Object &Description) {
|
||||
|
||||
/// Creates Contexts for namespaces and records to allow for navigation.
|
||||
void JSONGenerator::generateContext(const Info &I, Object &Obj) {
|
||||
Obj["Contexts"] = json::Array();
|
||||
Obj["HasContexts"] = true;
|
||||
|
||||
auto It = ContextsMap.find(&I);
|
||||
if (It == ContextsMap.end() || It->second.empty())
|
||||
return;
|
||||
|
||||
auto &ContextArrayRef = *Obj["Contexts"].getAsArray();
|
||||
const auto &Contexts = It->second;
|
||||
ContextArrayRef.reserve(Contexts.size());
|
||||
json::Value ContextArray = json::Array();
|
||||
auto &ContextArrayRef = *ContextArray.getAsArray();
|
||||
ContextArrayRef.reserve(I.Contexts.size());
|
||||
|
||||
std::string CurrentRelativePath;
|
||||
bool PreviousRecord = false;
|
||||
for (const auto &Current : Contexts) {
|
||||
for (const auto &Current : I.Contexts) {
|
||||
json::Value ContextVal = Object();
|
||||
Object &Context = *ContextVal.getAsObject();
|
||||
serializeReference(Current, Context);
|
||||
@@ -382,9 +372,11 @@ void JSONGenerator::generateContext(const Info &I, Object &Obj) {
|
||||
}
|
||||
|
||||
ContextArrayRef.back().getAsObject()->insert({"End", true});
|
||||
Obj["Contexts"] = ContextArray;
|
||||
Obj["HasContexts"] = true;
|
||||
}
|
||||
|
||||
static void serializeDescription(const OwningVec<CommentInfo> &Description,
|
||||
static void serializeDescription(llvm::ArrayRef<CommentInfo> Description,
|
||||
json::Object &Obj, StringRef Key = "") {
|
||||
if (Description.empty())
|
||||
return;
|
||||
@@ -437,8 +429,7 @@ void JSONGenerator::serializeCommonAttributes(const Info &I,
|
||||
Obj["Location"] = serializeLocation(Symbol->DefLoc.value());
|
||||
}
|
||||
|
||||
auto It = ContextsMap.find(&I);
|
||||
if (It != ContextsMap.end() && !It->second.empty())
|
||||
if (!I.Contexts.empty())
|
||||
generateContext(I, Obj);
|
||||
}
|
||||
|
||||
@@ -835,9 +826,9 @@ SmallString<16> JSONGenerator::determineFileName(Info *I,
|
||||
|
||||
/// \param CDCtxIndex Passed by copy since clang-doc's context is passed to the
|
||||
/// generator as `const`
|
||||
static std::vector<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
|
||||
static OwningVec<Index> preprocessCDCtxIndex(Index CDCtxIndex) {
|
||||
CDCtxIndex.sort();
|
||||
std::vector<Index> Processed;
|
||||
OwningVec<Index> Processed;
|
||||
Processed.reserve(CDCtxIndex.Children.size());
|
||||
for (const auto *Idx : CDCtxIndex.getSortedChildren()) {
|
||||
Index NewIdx = *Idx;
|
||||
@@ -857,7 +848,7 @@ Error JSONGenerator::serializeAllFiles(const ClangDocContext &CDCtx,
|
||||
StringRef RootDir) {
|
||||
json::Value ObjVal = Object();
|
||||
Object &Obj = *ObjVal.getAsObject();
|
||||
std::vector<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
|
||||
OwningVec<Index> IndexCopy = preprocessCDCtxIndex(CDCtx.Idx);
|
||||
serializeArray(IndexCopy, Obj, "Index", serializeReferenceLambda());
|
||||
SmallString<128> Path;
|
||||
sys::path::append(Path, RootDir, "json", "all_files.json");
|
||||
@@ -920,12 +911,10 @@ Error JSONGenerator::serializeIndex(StringRef RootDir) {
|
||||
return Error::success();
|
||||
}
|
||||
|
||||
void JSONGenerator::serializeContexts(Info *I,
|
||||
StringMap<OwnedPtr<Info>> &Infos) {
|
||||
static void serializeContexts(Info *I, StringMap<OwnedPtr<Info>> &Infos) {
|
||||
if (I->USR == GlobalNamespaceID)
|
||||
return;
|
||||
auto ParentUSR = I->ParentUSR;
|
||||
auto &LocalContexts = ContextsMap[I];
|
||||
|
||||
while (true) {
|
||||
// Infos may not have the ParentUSR, if its been filtered (public or path),
|
||||
@@ -939,12 +928,12 @@ void JSONGenerator::serializeContexts(Info *I,
|
||||
Context GlobalRef(ParentInfo->USR, "Global Namespace",
|
||||
InfoType::IT_namespace, "GlobalNamespace", "",
|
||||
SmallString<16>("index"));
|
||||
LocalContexts.push_back(GlobalRef);
|
||||
break;
|
||||
I->Contexts.push_back(GlobalRef);
|
||||
return;
|
||||
}
|
||||
|
||||
Context ParentRef(*ParentInfo);
|
||||
LocalContexts.push_back(ParentRef);
|
||||
I->Contexts.push_back(ParentRef);
|
||||
ParentUSR = ParentInfo->ParentUSR;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,7 +31,8 @@ static std::string genEmphasis(const Twine &Text) {
|
||||
return "**" + Text.str() + "**";
|
||||
}
|
||||
|
||||
static std::string genReferenceList(llvm::ArrayRef<Reference> Refs) {
|
||||
static std::string
|
||||
genReferenceList(const llvm::SmallVectorImpl<Reference> &Refs) {
|
||||
std::string Buffer;
|
||||
llvm::raw_string_ostream Stream(Buffer);
|
||||
for (const auto &R : Refs) {
|
||||
@@ -81,7 +82,7 @@ class TableCommentWriter {
|
||||
public:
|
||||
explicit TableCommentWriter(llvm::raw_ostream &OS) : OS(OS) {}
|
||||
|
||||
void write(const OwningVec<CommentInfo> &Comments) {
|
||||
void write(llvm::ArrayRef<CommentInfo> Comments) {
|
||||
for (const auto &C : Comments)
|
||||
writeTableSafeComment(C);
|
||||
|
||||
@@ -435,7 +436,7 @@ static llvm::Error serializeIndex(ClangDocContext &CDCtx) {
|
||||
OS << " for " << CDCtx.ProjectName;
|
||||
OS << "\n\n";
|
||||
|
||||
std::vector<const Index *> Children = CDCtx.Idx.getSortedChildren();
|
||||
OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
|
||||
for (const auto *C : Children)
|
||||
serializeReference(OS, *C, 0);
|
||||
|
||||
@@ -454,7 +455,7 @@ static llvm::Error genIndex(ClangDocContext &CDCtx) {
|
||||
FileErr.message());
|
||||
CDCtx.Idx.sort();
|
||||
OS << "# " << CDCtx.ProjectName << " C/C++ Reference\n\n";
|
||||
std::vector<const Index *> Children = CDCtx.Idx.getSortedChildren();
|
||||
OwningVec<const Index *> Children = CDCtx.Idx.getSortedChildren();
|
||||
for (const auto *C : Children) {
|
||||
if (!C->Children.empty()) {
|
||||
const char *Type;
|
||||
|
||||
@@ -43,9 +43,6 @@ void MapASTVisitor::HandleTranslationUnit(ASTContext &Context) {
|
||||
if (CDCtx.FTimeTrace)
|
||||
llvm::timeTraceProfilerInitialize(200, "clang-doc");
|
||||
TraverseDecl(Context.getTranslationUnitDecl());
|
||||
|
||||
TransientArena.Reset();
|
||||
|
||||
if (CDCtx.FTimeTrace)
|
||||
llvm::timeTraceProfilerFinishThread();
|
||||
}
|
||||
|
||||
@@ -105,6 +105,17 @@ static llvm::Expected<OwnedPtr<Info>> reduce(OwningPtrArray<Info> &Values) {
|
||||
return std::move(Merged);
|
||||
}
|
||||
|
||||
// Return the index of the matching child in the vector, or -1 if merge is not
|
||||
// necessary.
|
||||
template <typename T>
|
||||
static int getChildIndexIfExists(OwningVec<T> &Children, T &ChildToMerge) {
|
||||
for (unsigned long I = 0; I < Children.size(); I++) {
|
||||
if (ChildToMerge.USR == Children[I].USR)
|
||||
return I;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void reduceChildren(llvm::simple_ilist<T> &Children,
|
||||
llvm::simple_ilist<T> &&ChildrenToMerge) {
|
||||
@@ -115,145 +126,34 @@ static void reduceChildren(llvm::simple_ilist<T> &Children,
|
||||
auto It = llvm::find_if(
|
||||
Children, [&](const T &C) { return C.USR == ChildToMerge->USR; });
|
||||
if (It == Children.end()) {
|
||||
T *NewChild = allocatePtr<T>(PersistentArena, ChildToMerge->USR);
|
||||
NewChild->merge(std::move(*ChildToMerge));
|
||||
Children.push_back(*NewChild);
|
||||
Children.push_back(*ChildToMerge);
|
||||
} else {
|
||||
It->merge(std::move(*ChildToMerge));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void reduceChildren<Reference>(
|
||||
llvm::simple_ilist<Reference> &Children,
|
||||
llvm::simple_ilist<Reference> &&ChildrenToMerge) {
|
||||
while (!ChildrenToMerge.empty()) {
|
||||
Reference *ChildToMerge = &ChildrenToMerge.front();
|
||||
ChildrenToMerge.pop_front();
|
||||
|
||||
auto It = llvm::find_if(Children, [&](const Reference &C) {
|
||||
return C.USR == ChildToMerge->USR;
|
||||
});
|
||||
if (It == Children.end()) {
|
||||
Reference *NewChild = allocatePtr<Reference>(PersistentArena);
|
||||
NewChild->USR = ChildToMerge->USR;
|
||||
NewChild->RefType = ChildToMerge->RefType;
|
||||
NewChild->merge(std::move(*ChildToMerge));
|
||||
Children.push_back(*NewChild);
|
||||
} else {
|
||||
It->merge(std::move(*ChildToMerge));
|
||||
template <typename T>
|
||||
static void reduceChildren(OwningVec<T> &Children,
|
||||
OwningVec<T> &&ChildrenToMerge) {
|
||||
for (auto &ChildToMerge : ChildrenToMerge) {
|
||||
int MergeIdx = getChildIndexIfExists(Children, ChildToMerge);
|
||||
if (MergeIdx == -1) {
|
||||
Children.push_back(std::move(ChildToMerge));
|
||||
continue;
|
||||
}
|
||||
Children[MergeIdx].merge(std::move(ChildToMerge));
|
||||
}
|
||||
}
|
||||
|
||||
template <typename Container>
|
||||
static void mergeUnkeyed(Container &Target, Container &&Source) {
|
||||
using T = typename Container::value_type;
|
||||
while (!Source.empty()) {
|
||||
auto &Item = Source.front();
|
||||
Source.pop_front();
|
||||
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
|
||||
T *NewItem = allocatePtr<T>(PersistentArena, Item);
|
||||
Target.push_back(*NewItem);
|
||||
}
|
||||
for (auto &Item : Source) {
|
||||
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; }))
|
||||
Target.push_back(std::move(Item));
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
void mergeUnkeyed<OwningVec<CommentInfo>>(OwningVec<CommentInfo> &Target,
|
||||
OwningVec<CommentInfo> &&Source) {
|
||||
while (!Source.empty()) {
|
||||
auto &Item = Source.front();
|
||||
Source.pop_front();
|
||||
if (llvm::none_of(Target, [&](const auto &E) { return E == Item; })) {
|
||||
CommentInfo *NewItem =
|
||||
allocatePtr<CommentInfo>(PersistentArena, Item, PersistentArena);
|
||||
Target.push_back(*NewItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
llvm::Error mergeSingleInfo(doc::OwnedPtr<doc::Info> &Reduced,
|
||||
doc::OwnedPtr<doc::Info> &&NewInfo,
|
||||
llvm::BumpPtrAllocator &Arena) {
|
||||
if (!Reduced) {
|
||||
switch (NewInfo->IT) {
|
||||
case InfoType::IT_namespace:
|
||||
Reduced = allocatePtr<NamespaceInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_record:
|
||||
Reduced = allocatePtr<RecordInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_enum:
|
||||
Reduced = allocatePtr<EnumInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_function:
|
||||
Reduced = allocatePtr<FunctionInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_typedef:
|
||||
Reduced = allocatePtr<TypedefInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_concept:
|
||||
Reduced = allocatePtr<ConceptInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_variable:
|
||||
Reduced = allocatePtr<VarInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
case InfoType::IT_friend:
|
||||
Reduced = allocatePtr<FriendInfo>(Arena, NewInfo->USR);
|
||||
break;
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"unknown info type");
|
||||
}
|
||||
}
|
||||
|
||||
if (Reduced->IT != NewInfo->IT)
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"info types mismatch");
|
||||
|
||||
switch (Reduced->IT) {
|
||||
case InfoType::IT_namespace:
|
||||
static_cast<NamespaceInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<NamespaceInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_record:
|
||||
static_cast<RecordInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<RecordInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_enum:
|
||||
static_cast<EnumInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<EnumInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_function:
|
||||
static_cast<FunctionInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<FunctionInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_typedef:
|
||||
static_cast<TypedefInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<TypedefInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_concept:
|
||||
static_cast<ConceptInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<ConceptInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_variable:
|
||||
static_cast<VarInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<VarInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
case InfoType::IT_friend:
|
||||
static_cast<FriendInfo *>(getPtr(Reduced))
|
||||
->merge(std::move(*static_cast<FriendInfo *>(getPtr(NewInfo))));
|
||||
break;
|
||||
default:
|
||||
return llvm::createStringError(llvm::inconvertibleErrorCode(),
|
||||
"unknown info type");
|
||||
}
|
||||
|
||||
return llvm::Error::success();
|
||||
}
|
||||
|
||||
// Dispatch function.
|
||||
llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
|
||||
if (Values.empty() || !Values[0])
|
||||
@@ -284,20 +184,6 @@ llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values) {
|
||||
llvm_unreachable("unhandled enumerator");
|
||||
}
|
||||
|
||||
TemplateSpecializationInfo::TemplateSpecializationInfo(
|
||||
const TemplateSpecializationInfo &Other, llvm::BumpPtrAllocator &Arena)
|
||||
: SpecializationOf(Other.SpecializationOf) {
|
||||
Params = allocateArray(Other.Params, Arena);
|
||||
}
|
||||
|
||||
TemplateInfo::TemplateInfo(const TemplateInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena) {
|
||||
Params = allocateArray(Other.Params, Arena);
|
||||
if (Other.Specialization)
|
||||
Specialization = TemplateSpecializationInfo(*Other.Specialization, Arena);
|
||||
Constraints = allocateArray(Other.Constraints, Arena);
|
||||
}
|
||||
|
||||
bool CommentInfo::operator==(const CommentInfo &Other) const {
|
||||
auto FirstCI = std::tie(Kind, Text, Name, Direction, ParamName, CloseName,
|
||||
SelfClosing, Explicit, AttrKeys, AttrValues, Args);
|
||||
@@ -333,28 +219,6 @@ bool CommentInfo::operator<(const CommentInfo &Other) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
CommentInfo::CommentInfo(const CommentInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena) {
|
||||
Kind = Other.Kind;
|
||||
Direction = Other.Direction;
|
||||
Name = Other.Name;
|
||||
ParamName = Other.ParamName;
|
||||
CloseName = Other.CloseName;
|
||||
SelfClosing = Other.SelfClosing;
|
||||
Explicit = Other.Explicit;
|
||||
Text = Other.Text;
|
||||
AttrKeys = allocateArray(Other.AttrKeys, Arena);
|
||||
AttrValues = allocateArray(Other.AttrValues, Arena);
|
||||
Args = allocateArray(Other.Args, Arena);
|
||||
if (!Other.Children.empty()) {
|
||||
CommentInfo *NewArray = Arena.Allocate<CommentInfo>(Other.Children.size());
|
||||
for (size_t Idx = 0; Idx < Other.Children.size(); ++Idx) {
|
||||
new (NewArray + Idx) CommentInfo(Other.Children[Idx], Arena);
|
||||
}
|
||||
Children = llvm::ArrayRef<CommentInfo>(NewArray, Other.Children.size());
|
||||
}
|
||||
}
|
||||
|
||||
static llvm::SmallString<64>
|
||||
calculateRelativeFilePath(const InfoType &Type, const StringRef &Path,
|
||||
const StringRef &Name, const StringRef &CurrentPath) {
|
||||
@@ -411,8 +275,6 @@ void Reference::merge(Reference &&Other) {
|
||||
Name = Other.Name;
|
||||
if (Path.empty())
|
||||
Path = Other.Path;
|
||||
if (QualName.empty())
|
||||
QualName = Other.QualName;
|
||||
if (DocumentationFileName.empty())
|
||||
DocumentationFileName = Other.DocumentationFileName;
|
||||
}
|
||||
@@ -427,31 +289,6 @@ void FriendInfo::merge(FriendInfo &&Other) {
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
}
|
||||
|
||||
FriendInfo::FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena)
|
||||
: SymbolInfo(Other, Arena) {
|
||||
Ref = Other.Ref;
|
||||
if (Other.Template)
|
||||
Template.emplace(*Other.Template, Arena);
|
||||
if (Other.ReturnType)
|
||||
ReturnType = Other.ReturnType;
|
||||
if (!Other.Params.empty())
|
||||
Params = allocateArray(Other.Params, Arena);
|
||||
IsClass = Other.IsClass;
|
||||
}
|
||||
|
||||
Info::Info(const Info &Other, llvm::BumpPtrAllocator &Arena)
|
||||
: Path(Other.Path), Name(Other.Name),
|
||||
DocumentationFileName(Other.DocumentationFileName), USR(Other.USR),
|
||||
ParentUSR(Other.ParentUSR), IT(Other.IT) {
|
||||
Namespace = allocateArray(Other.Namespace, Arena);
|
||||
if (!Other.Description.empty()) {
|
||||
for (const auto &Desc : Other.Description) {
|
||||
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
|
||||
Description.push_back(*NewDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Info::mergeBase(Info &&Other) {
|
||||
assert(mergeable(Other));
|
||||
if (USR == EmptySID)
|
||||
@@ -460,8 +297,8 @@ void Info::mergeBase(Info &&Other) {
|
||||
Name = Other.Name;
|
||||
if (Path == "")
|
||||
Path = Other.Path;
|
||||
if (Namespace.empty() && !Other.Namespace.empty())
|
||||
Namespace = allocateArray(Other.Namespace, PersistentArena);
|
||||
if (Namespace.empty())
|
||||
Namespace = std::move(Other.Namespace);
|
||||
// Unconditionally extend the description, since each decl may have a comment.
|
||||
mergeUnkeyed(Description, std::move(Other.Description));
|
||||
if (ParentUSR == EmptySID)
|
||||
@@ -474,17 +311,6 @@ bool Info::mergeable(const Info &Other) {
|
||||
return IT == Other.IT && USR == Other.USR;
|
||||
}
|
||||
|
||||
SymbolInfo::SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena)
|
||||
: Info(Other, Arena), DefLoc(Other.DefLoc), MangledName(Other.MangledName),
|
||||
IsStatic(Other.IsStatic) {
|
||||
if (!Other.Loc.empty()) {
|
||||
for (const auto &L : Other.Loc) {
|
||||
Location *NewL = allocatePtr<Location>(Arena, L);
|
||||
Loc.push_back(*NewL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SymbolInfo::merge(SymbolInfo &&Other) {
|
||||
assert(mergeable(Other));
|
||||
if (!DefLoc)
|
||||
@@ -494,8 +320,6 @@ void SymbolInfo::merge(SymbolInfo &&Other) {
|
||||
mergeBase(std::move(Other));
|
||||
if (MangledName.empty())
|
||||
MangledName = std::move(Other.MangledName);
|
||||
if (!IsStatic)
|
||||
IsStatic = Other.IsStatic;
|
||||
}
|
||||
|
||||
NamespaceInfo::NamespaceInfo(SymbolID USR, StringRef Name, StringRef Path)
|
||||
@@ -517,76 +341,37 @@ void NamespaceInfo::merge(NamespaceInfo &&Other) {
|
||||
RecordInfo::RecordInfo(SymbolID USR, StringRef Name, StringRef Path)
|
||||
: SymbolInfo(InfoType::IT_record, USR, Name, Path) {}
|
||||
|
||||
// FIXME: This constructor is currently unsafe for cross-arena copies of
|
||||
// populated records. Because a default copy of ScopeChildren will shallow-copy
|
||||
// the intrusive pointers, leading to a use-after-free when the TransientArena
|
||||
// is reset. Subsequent patches will address this by deep-copying children
|
||||
// individually via reduceChildren.
|
||||
RecordInfo::RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena)
|
||||
: SymbolInfo(Other, Arena), TagType(Other.TagType),
|
||||
IsTypeDef(Other.IsTypeDef) {
|
||||
Members = deepCopyArray(Other.Members, Arena);
|
||||
Parents = allocateArray(Other.Parents, Arena);
|
||||
VirtualParents = allocateArray(Other.VirtualParents, Arena);
|
||||
Bases = deepCopyArray(Other.Bases, Arena);
|
||||
Friends = deepCopyArray(Other.Friends, Arena);
|
||||
}
|
||||
|
||||
MemberTypeInfo::MemberTypeInfo(const MemberTypeInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena)
|
||||
: FieldTypeInfo(Other), Access(Other.Access), IsStatic(Other.IsStatic) {
|
||||
if (!Other.Description.empty()) {
|
||||
for (const auto &Desc : Other.Description) {
|
||||
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
|
||||
Description.push_back(*NewDesc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RecordInfo::merge(RecordInfo &&Other) {
|
||||
assert(mergeable(Other));
|
||||
if (!llvm::to_underlying(TagType))
|
||||
TagType = Other.TagType;
|
||||
IsTypeDef = IsTypeDef || Other.IsTypeDef;
|
||||
if (Members.empty() && !Other.Members.empty())
|
||||
Members = deepCopyArray(Other.Members, PersistentArena);
|
||||
if (Bases.empty() && !Other.Bases.empty())
|
||||
Bases = deepCopyArray(Other.Bases, PersistentArena);
|
||||
if (Parents.empty() && !Other.Parents.empty())
|
||||
Parents = allocateArray(Other.Parents, PersistentArena);
|
||||
if (VirtualParents.empty() && !Other.VirtualParents.empty())
|
||||
VirtualParents = allocateArray(Other.VirtualParents, PersistentArena);
|
||||
if (Friends.empty() && !Other.Friends.empty())
|
||||
Friends = deepCopyArray(Other.Friends, PersistentArena);
|
||||
if (Members.empty())
|
||||
Members = std::move(Other.Members);
|
||||
if (Bases.empty())
|
||||
Bases = std::move(Other.Bases);
|
||||
if (Parents.empty())
|
||||
Parents = std::move(Other.Parents);
|
||||
if (VirtualParents.empty())
|
||||
VirtualParents = std::move(Other.VirtualParents);
|
||||
if (Friends.empty())
|
||||
Friends = std::move(Other.Friends);
|
||||
// Reduce children if necessary.
|
||||
reduceChildren(Children.Records, std::move(Other.Children.Records));
|
||||
reduceChildren(Children.Functions, std::move(Other.Children.Functions));
|
||||
reduceChildren(Children.Enums, std::move(Other.Children.Enums));
|
||||
reduceChildren(Children.Typedefs, std::move(Other.Children.Typedefs));
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
if (!Template && Other.Template)
|
||||
Template = TemplateInfo(*Other.Template, PersistentArena);
|
||||
}
|
||||
|
||||
EnumValueInfo::EnumValueInfo(const EnumValueInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena)
|
||||
: Name(Other.Name), Value(Other.Value), ValueExpr(Other.ValueExpr) {
|
||||
if (!Other.Description.empty()) {
|
||||
for (const auto &Desc : Other.Description) {
|
||||
CommentInfo *NewDesc = allocatePtr<CommentInfo>(Arena, Desc, Arena);
|
||||
Description.push_back(*NewDesc);
|
||||
}
|
||||
}
|
||||
if (!Template)
|
||||
Template = Other.Template;
|
||||
}
|
||||
|
||||
void EnumInfo::merge(EnumInfo &&Other) {
|
||||
assert(mergeable(Other));
|
||||
if (!Scoped)
|
||||
Scoped = Other.Scoped;
|
||||
if (!BaseType && Other.BaseType)
|
||||
BaseType = std::move(Other.BaseType);
|
||||
if (Members.empty() && !Other.Members.empty())
|
||||
Members = deepCopyArray(Other.Members, PersistentArena);
|
||||
if (Members.empty())
|
||||
Members = std::move(Other.Members);
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
}
|
||||
|
||||
@@ -600,11 +385,11 @@ void FunctionInfo::merge(FunctionInfo &&Other) {
|
||||
ReturnType = std::move(Other.ReturnType);
|
||||
if (Parent.USR == EmptySID && Parent.Name == "")
|
||||
Parent = std::move(Other.Parent);
|
||||
if (Params.empty() && !Other.Params.empty())
|
||||
Params = allocateArray(Other.Params, PersistentArena);
|
||||
if (Params.empty())
|
||||
Params = std::move(Other.Params);
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
if (!Template && Other.Template)
|
||||
Template = TemplateInfo(*Other.Template, PersistentArena);
|
||||
if (!Template)
|
||||
Template = Other.Template;
|
||||
}
|
||||
|
||||
void TypedefInfo::merge(TypedefInfo &&Other) {
|
||||
@@ -613,8 +398,8 @@ void TypedefInfo::merge(TypedefInfo &&Other) {
|
||||
IsUsing = Other.IsUsing;
|
||||
if (Underlying.Type.Name == "")
|
||||
Underlying = Other.Underlying;
|
||||
if (!Template && Other.Template)
|
||||
Template = TemplateInfo(*Other.Template, PersistentArena);
|
||||
if (!Template)
|
||||
Template = Other.Template;
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
}
|
||||
|
||||
@@ -624,11 +409,10 @@ void ConceptInfo::merge(ConceptInfo &&Other) {
|
||||
IsType = Other.IsType;
|
||||
if (ConstraintExpression.empty())
|
||||
ConstraintExpression = std::move(Other.ConstraintExpression);
|
||||
if (Template.Constraints.empty() && !Other.Template.Constraints.empty())
|
||||
Template.Constraints =
|
||||
allocateArray(Other.Template.Constraints, PersistentArena);
|
||||
if (Template.Params.empty() && !Other.Template.Params.empty())
|
||||
Template.Params = allocateArray(Other.Template.Params, PersistentArena);
|
||||
if (Template.Constraints.empty())
|
||||
Template.Constraints = std::move(Other.Template.Constraints);
|
||||
if (Template.Params.empty())
|
||||
Template.Params = std::move(Other.Template.Params);
|
||||
SymbolInfo::merge(std::move(Other));
|
||||
}
|
||||
|
||||
@@ -643,11 +427,6 @@ void VarInfo::merge(VarInfo &&Other) {
|
||||
|
||||
BaseRecordInfo::BaseRecordInfo() : RecordInfo() {}
|
||||
|
||||
BaseRecordInfo::BaseRecordInfo(const BaseRecordInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena)
|
||||
: RecordInfo(Other, Arena), Access(Other.Access),
|
||||
IsVirtual(Other.IsVirtual), IsParent(Other.IsParent) {}
|
||||
|
||||
BaseRecordInfo::BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path,
|
||||
bool IsVirtual, AccessSpecifier Access,
|
||||
bool IsParent)
|
||||
@@ -705,8 +484,8 @@ bool Index::operator<(const Index &Other) const {
|
||||
return Name < Other.Name;
|
||||
}
|
||||
|
||||
std::vector<const Index *> Index::getSortedChildren() const {
|
||||
std::vector<const Index *> SortedChildren;
|
||||
OwningVec<const Index *> Index::getSortedChildren() const {
|
||||
OwningVec<const Index *> SortedChildren;
|
||||
SortedChildren.reserve(Children.size());
|
||||
for (const auto &[_, C] : Children)
|
||||
SortedChildren.push_back(&C);
|
||||
@@ -750,12 +529,12 @@ ClangDocContext::ClangDocContext(tooling::ExecutionContext *ECtx,
|
||||
|
||||
void ScopeChildren::sort() {
|
||||
Namespaces.sort();
|
||||
Records.sort();
|
||||
Functions.sort();
|
||||
Enums.sort();
|
||||
Typedefs.sort();
|
||||
Concepts.sort();
|
||||
Variables.sort();
|
||||
llvm::sort(Records);
|
||||
llvm::sort(Functions);
|
||||
llvm::sort(Enums);
|
||||
llvm::sort(Typedefs);
|
||||
llvm::sort(Concepts);
|
||||
llvm::sort(Variables);
|
||||
}
|
||||
} // namespace doc
|
||||
} // namespace clang
|
||||
|
||||
@@ -52,7 +52,6 @@ private:
|
||||
ConcurrentStringPool &getGlobalStringPool();
|
||||
|
||||
extern thread_local llvm::BumpPtrAllocator TransientArena;
|
||||
extern thread_local llvm::BumpPtrAllocator PersistentArena;
|
||||
|
||||
inline StringRef internString(const Twine &T) {
|
||||
if (T.isTriviallyEmpty())
|
||||
@@ -73,8 +72,8 @@ inline StringRef internString(const Twine &T) {
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::ArrayRef<T> allocateArray(llvm::SmallVectorImpl<T> &V,
|
||||
llvm::BumpPtrAllocator &Alloc) {
|
||||
inline llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
|
||||
llvm::BumpPtrAllocator &Alloc) {
|
||||
if (V.empty())
|
||||
return llvm::ArrayRef<T>();
|
||||
T *Allocated = (T *)Alloc.Allocate<T>(V.size());
|
||||
@@ -82,31 +81,9 @@ llvm::ArrayRef<T> allocateArray(llvm::SmallVectorImpl<T> &V,
|
||||
return llvm::ArrayRef<T>(Allocated, V.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::ArrayRef<T> allocateArray(llvm::ArrayRef<T> V,
|
||||
llvm::BumpPtrAllocator &Alloc) {
|
||||
if (V.empty())
|
||||
return llvm::ArrayRef<T>();
|
||||
T *Allocated = (T *)Alloc.Allocate<T>(V.size());
|
||||
std::uninitialized_copy(V.begin(), V.end(), Allocated);
|
||||
return llvm::ArrayRef<T>(Allocated, V.size());
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
llvm::ArrayRef<T> deepCopyArray(llvm::ArrayRef<T> V,
|
||||
llvm::BumpPtrAllocator &Alloc) {
|
||||
if (V.empty())
|
||||
return llvm::ArrayRef<T>();
|
||||
T *Allocated = (T *)Alloc.Allocate<T>(V.size());
|
||||
for (size_t Idx = 0; Idx < V.size(); ++Idx) {
|
||||
new (Allocated + Idx) T(V[Idx], Alloc);
|
||||
}
|
||||
return llvm::ArrayRef<T>(Allocated, V.size());
|
||||
}
|
||||
|
||||
// An abstraction for owned pointers. Initially mapped to OwnedPtr,
|
||||
// to be eventually transitioned to bare pointers in an arena.
|
||||
template <typename T> using OwnedPtr = T *;
|
||||
template <typename T> using OwnedPtr = std::unique_ptr<T>;
|
||||
|
||||
// An abstraction for vectors that are populated and read sequentially.
|
||||
// To be eventually transitioned to llvm::ArrayRef for arena storage.
|
||||
@@ -114,7 +91,7 @@ template <typename T> using OwningArray = std::vector<T>;
|
||||
|
||||
// An abstraction for lists that are dynamically managed (inserted/removed).
|
||||
// To be eventually transitioned to llvm::simple_ilist.
|
||||
template <typename T> using OwningVec = llvm::simple_ilist<T>;
|
||||
template <typename T> using OwningVec = std::vector<T>;
|
||||
|
||||
// An abstraction for dynamic lists of owned pointers.
|
||||
// To be eventually transitioned to llvm::simple_ilist<T*> or similar.
|
||||
@@ -128,10 +105,9 @@ template <typename T> using OwningPtrArray = std::vector<OwnedPtr<T>>;
|
||||
// allocation mechanism.
|
||||
template <typename T, typename... Args>
|
||||
OwnedPtr<T> allocatePtr(Args &&...args) {
|
||||
return new (TransientArena.Allocate<T>()) T(std::forward<Args>(args)...);
|
||||
return std::make_unique<T>(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
// An overload to explicitly allocate on an arena, returning a bare pointer.
|
||||
template <typename T, typename... Args>
|
||||
T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
|
||||
return new (Alloc.Allocate<T>()) T(std::forward<Args>(args)...);
|
||||
@@ -139,7 +115,7 @@ T *allocatePtr(llvm::BumpPtrAllocator &Alloc, Args &&...args) {
|
||||
|
||||
// A helper function to access the underlying pointer from an owned pointer,
|
||||
// abstracting away the pointer dereferencing mechanism.
|
||||
template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O; }
|
||||
template <typename T> T *getPtr(const OwnedPtr<T> &O) { return O.get(); }
|
||||
|
||||
// SHA1'd hash of a USR.
|
||||
using SymbolID = std::array<uint8_t, 20>;
|
||||
@@ -193,7 +169,6 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
|
||||
CommentInfo() = default;
|
||||
CommentInfo(const CommentInfo &Other) = default;
|
||||
CommentInfo &operator=(const CommentInfo &Other) = default;
|
||||
CommentInfo(const CommentInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
CommentInfo(CommentInfo &&Other) = default;
|
||||
CommentInfo &operator=(CommentInfo &&Other) = default;
|
||||
|
||||
@@ -219,11 +194,11 @@ struct CommentInfo : public llvm::ilist_node<CommentInfo> {
|
||||
|
||||
llvm::ArrayRef<CommentInfo>
|
||||
Children; // List of child comments for this CommentInfo.
|
||||
StringRef Direction = {}; // Parameter direction (for (T)ParamCommand).
|
||||
StringRef Name = {}; // Name of the comment (for Verbatim and HTML).
|
||||
StringRef ParamName = {}; // Parameter name (for (T)ParamCommand).
|
||||
StringRef CloseName = {}; // Closing tag name (for VerbatimBlock).
|
||||
StringRef Text = {}; // Text of the comment.
|
||||
StringRef Direction; // Parameter direction (for (T)ParamCommand).
|
||||
StringRef Name; // Name of the comment (for Verbatim and HTML).
|
||||
StringRef ParamName; // Parameter name (for (T)ParamCommand).
|
||||
StringRef CloseName; // Closing tag name (for VerbatimBlock).
|
||||
StringRef Text; // Text of the comment.
|
||||
llvm::ArrayRef<StringRef> AttrKeys; // List of attribute keys (for HTML).
|
||||
llvm::ArrayRef<StringRef>
|
||||
AttrValues; // List of attribute values for each key (for HTML).
|
||||
@@ -285,17 +260,17 @@ struct Reference : public llvm::ilist_node<Reference> {
|
||||
// Name of type (possibly unresolved). Not including namespaces or template
|
||||
// parameters (so for a std::vector<int> this would be "vector"). See also
|
||||
// QualName.
|
||||
StringRef Name = {};
|
||||
StringRef Name;
|
||||
|
||||
// Full qualified name of this type, including namespaces and template
|
||||
// parameter (for example this could be "std::vector<int>"). Contrast to
|
||||
// Name.
|
||||
StringRef QualName = {};
|
||||
StringRef QualName;
|
||||
|
||||
// Path of directory where the clang-doc generated file will be saved
|
||||
// (possibly unresolved)
|
||||
StringRef Path = {};
|
||||
StringRef DocumentationFileName = {};
|
||||
StringRef Path;
|
||||
StringRef DocumentationFileName;
|
||||
};
|
||||
|
||||
// A Context is a reference that holds a relative path from a certain Info's
|
||||
@@ -305,7 +280,7 @@ struct Context : public Reference {
|
||||
StringRef Path, StringRef DocumentationFileName)
|
||||
: Reference(USR, Name, IT, QualName, Path, DocumentationFileName) {}
|
||||
explicit Context(const Info &I);
|
||||
StringRef RelativePath = {};
|
||||
StringRef RelativePath;
|
||||
};
|
||||
|
||||
// Holds the children of a record or namespace.
|
||||
@@ -317,7 +292,7 @@ struct ScopeChildren {
|
||||
//
|
||||
// Namespaces are not syntactically valid as children of records, but making
|
||||
// this general for all possible container types reduces code complexity.
|
||||
OwningVec<Reference> Namespaces;
|
||||
llvm::simple_ilist<Reference> Namespaces;
|
||||
OwningVec<Reference> Records;
|
||||
OwningVec<FunctionInfo> Functions;
|
||||
OwningVec<EnumInfo> Enums;
|
||||
@@ -359,19 +334,15 @@ struct TemplateParamInfo {
|
||||
// The literal contents of the code for that specifies this template parameter
|
||||
// for this declaration. Typical values will be "class T" and
|
||||
// "typename T = int".
|
||||
StringRef Contents = {};
|
||||
StringRef Contents;
|
||||
};
|
||||
|
||||
struct TemplateSpecializationInfo {
|
||||
TemplateSpecializationInfo() = default;
|
||||
TemplateSpecializationInfo(const TemplateSpecializationInfo &Other,
|
||||
llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
// Indicates the declaration that this specializes.
|
||||
SymbolID SpecializationOf;
|
||||
|
||||
// Template parameters applying to the specialized record/function.
|
||||
llvm::ArrayRef<TemplateParamInfo> Params;
|
||||
OwningVec<TemplateParamInfo> Params;
|
||||
};
|
||||
|
||||
struct ConstraintInfo {
|
||||
@@ -380,21 +351,18 @@ struct ConstraintInfo {
|
||||
: ConceptRef(USR, Name, InfoType::IT_concept) {}
|
||||
Reference ConceptRef;
|
||||
|
||||
StringRef ConstraintExpr = {};
|
||||
StringRef ConstraintExpr;
|
||||
};
|
||||
|
||||
// Records the template information for a struct or function that is a template
|
||||
// or an explicit template specialization.
|
||||
struct TemplateInfo {
|
||||
TemplateInfo() = default;
|
||||
TemplateInfo(const TemplateInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
// May be empty for non-partial specializations.
|
||||
llvm::ArrayRef<TemplateParamInfo> Params;
|
||||
OwningVec<TemplateParamInfo> Params;
|
||||
|
||||
// Set when this is a specialization of another record/function.
|
||||
std::optional<TemplateSpecializationInfo> Specialization;
|
||||
llvm::ArrayRef<ConstraintInfo> Constraints;
|
||||
OwningVec<ConstraintInfo> Constraints;
|
||||
};
|
||||
|
||||
// Info for field types.
|
||||
@@ -410,27 +378,24 @@ struct FieldTypeInfo : public TypeInfo {
|
||||
std::tie(Other.Type, Other.Name, Other.DefaultValue);
|
||||
}
|
||||
|
||||
StringRef Name = {}; // Name associated with this info.
|
||||
StringRef Name; // Name associated with this info.
|
||||
|
||||
// When used for function parameters, contains the string representing the
|
||||
// expression of the default value, if any.
|
||||
StringRef DefaultValue = {};
|
||||
StringRef DefaultValue;
|
||||
};
|
||||
|
||||
// Info for member types.
|
||||
struct MemberTypeInfo : public FieldTypeInfo {
|
||||
MemberTypeInfo() = default;
|
||||
MemberTypeInfo(const MemberTypeInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
MemberTypeInfo(const TypeInfo &TI, StringRef Name, AccessSpecifier Access,
|
||||
bool IsStatic = false)
|
||||
: FieldTypeInfo(TI, Name), Access(Access), IsStatic(IsStatic) {}
|
||||
|
||||
bool operator==(const MemberTypeInfo &Other) const {
|
||||
if (std::tie(Type, Name, Access, IsStatic) !=
|
||||
std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic))
|
||||
return false;
|
||||
return std::equal(Description.begin(), Description.end(),
|
||||
Other.Description.begin(), Other.Description.end());
|
||||
return std::tie(Type, Name, Access, IsStatic, Description) ==
|
||||
std::tie(Other.Type, Other.Name, Other.Access, Other.IsStatic,
|
||||
Other.Description);
|
||||
}
|
||||
|
||||
OwningVec<CommentInfo> Description;
|
||||
@@ -465,7 +430,7 @@ struct Location : public llvm::ilist_node<Location> {
|
||||
std::tie(Other.StartLineNumber, Other.EndLineNumber, Other.Filename);
|
||||
}
|
||||
|
||||
StringRef Filename = {};
|
||||
StringRef Filename;
|
||||
int StartLineNumber = 0;
|
||||
int EndLineNumber = 0;
|
||||
bool IsFileInRootDir = false;
|
||||
@@ -477,9 +442,9 @@ struct Info {
|
||||
StringRef Name = StringRef(), StringRef Path = StringRef())
|
||||
: Path(internString(Path)), Name(internString(Name)), USR(USR), IT(IT) {}
|
||||
|
||||
Info(const Info &Other, llvm::BumpPtrAllocator &Arena);
|
||||
Info(const Info &Other) = delete;
|
||||
Info(Info &&Other) = default;
|
||||
virtual ~Info() = default;
|
||||
|
||||
Info &operator=(Info &&Other) = default;
|
||||
|
||||
@@ -495,18 +460,18 @@ struct Info {
|
||||
StringRef getFileBaseName() const;
|
||||
|
||||
// Path of directory where the clang-doc generated file will be saved.
|
||||
StringRef Path = {};
|
||||
StringRef Path;
|
||||
|
||||
// Unqualified name of the decl.
|
||||
StringRef Name = {};
|
||||
StringRef Name;
|
||||
|
||||
// The name used for the file that this info is documented in.
|
||||
// In the JSON generator, infos are documented in files with mangled names.
|
||||
// Thus, we keep track of the physical filename for linking purposes.
|
||||
StringRef DocumentationFileName = {};
|
||||
StringRef DocumentationFileName;
|
||||
|
||||
// List of parent namespaces for this decl.
|
||||
llvm::ArrayRef<Reference> Namespace;
|
||||
llvm::SmallVector<Reference, 4> Namespace;
|
||||
|
||||
// Unique identifier for the decl described by this Info.
|
||||
SymbolID USR = SymbolID();
|
||||
@@ -519,6 +484,8 @@ struct Info {
|
||||
|
||||
// Comment description of this decl.
|
||||
OwningVec<CommentInfo> Description;
|
||||
|
||||
SmallVector<Context, 4> Contexts;
|
||||
};
|
||||
|
||||
inline Context::Context(const Info &I)
|
||||
@@ -540,8 +507,6 @@ struct SymbolInfo : public Info {
|
||||
StringRef Name = StringRef(), StringRef Path = StringRef())
|
||||
: Info(IT, USR, Name, Path) {}
|
||||
|
||||
SymbolInfo(const SymbolInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
void merge(SymbolInfo &&I);
|
||||
|
||||
bool operator<(const SymbolInfo &Other) const {
|
||||
@@ -549,9 +514,8 @@ struct SymbolInfo : public Info {
|
||||
// generated in the order of the source code.
|
||||
// If the declaration location is the same, or not present
|
||||
// we sort by defined location otherwise fallback to the extracted name
|
||||
if (Loc.size() > 0 && Other.Loc.size() > 0 &&
|
||||
Loc.front() != Other.Loc.front())
|
||||
return Loc.front() < Other.Loc.front();
|
||||
if (Loc.size() > 0 && Other.Loc.size() > 0 && Loc[0] != Other.Loc[0])
|
||||
return Loc[0] < Other.Loc[0];
|
||||
|
||||
if (DefLoc && Other.DefLoc && *DefLoc != *Other.DefLoc)
|
||||
return *DefLoc < *Other.DefLoc;
|
||||
@@ -560,8 +524,8 @@ struct SymbolInfo : public Info {
|
||||
}
|
||||
|
||||
std::optional<Location> DefLoc; // Location where this decl is defined.
|
||||
OwningVec<Location> Loc; // Locations where this decl is declared.
|
||||
StringRef MangledName = {};
|
||||
llvm::SmallVector<Location, 2> Loc; // Locations where this decl is declared.
|
||||
StringRef MangledName;
|
||||
bool IsStatic = false;
|
||||
};
|
||||
|
||||
@@ -571,7 +535,6 @@ struct FriendInfo : public SymbolInfo, public llvm::ilist_node<FriendInfo> {
|
||||
FriendInfo(const InfoType IT, const SymbolID &USR,
|
||||
const StringRef Name = StringRef())
|
||||
: SymbolInfo(IT, USR, Name) {}
|
||||
FriendInfo(const FriendInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
bool mergeable(const FriendInfo &Other);
|
||||
void merge(FriendInfo &&Other);
|
||||
|
||||
@@ -601,8 +564,8 @@ struct FunctionInfo : public SymbolInfo, public llvm::ilist_node<FunctionInfo> {
|
||||
|
||||
Reference Parent;
|
||||
TypeInfo ReturnType;
|
||||
llvm::ArrayRef<FieldTypeInfo> Params;
|
||||
StringRef Prototype = {};
|
||||
llvm::SmallVector<FieldTypeInfo, 4> Params;
|
||||
StringRef Prototype;
|
||||
|
||||
// When present, this function is a template or specialization.
|
||||
std::optional<TemplateInfo> Template;
|
||||
@@ -623,8 +586,6 @@ struct RecordInfo : public SymbolInfo {
|
||||
RecordInfo(SymbolID USR = SymbolID(), StringRef Name = StringRef(),
|
||||
StringRef Path = StringRef());
|
||||
|
||||
RecordInfo(const RecordInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
void merge(RecordInfo &&I);
|
||||
|
||||
// Type of this record (struct, class, union, interface).
|
||||
@@ -639,18 +600,18 @@ struct RecordInfo : public SymbolInfo {
|
||||
// When present, this record is a template or specialization.
|
||||
std::optional<TemplateInfo> Template;
|
||||
|
||||
llvm::ArrayRef<MemberTypeInfo> Members; // List of info about record members.
|
||||
llvm::ArrayRef<Reference> Parents; // List of base/parent records
|
||||
// (does not include virtual
|
||||
// parents).
|
||||
llvm::ArrayRef<Reference>
|
||||
llvm::SmallVector<MemberTypeInfo, 4>
|
||||
Members; // List of info about record members.
|
||||
llvm::SmallVector<Reference, 4> Parents; // List of base/parent records
|
||||
// (does not include virtual
|
||||
// parents).
|
||||
llvm::SmallVector<Reference, 4>
|
||||
VirtualParents; // List of virtual base/parent records.
|
||||
|
||||
llvm::ArrayRef<BaseRecordInfo>
|
||||
Bases; // List of base/parent records; this includes
|
||||
// inherited methods and attributes
|
||||
OwningVec<BaseRecordInfo> Bases; // List of base/parent records; this includes
|
||||
// inherited methods and attributes
|
||||
|
||||
llvm::ArrayRef<FriendInfo> Friends;
|
||||
OwningVec<FriendInfo> Friends;
|
||||
|
||||
ScopeChildren Children;
|
||||
};
|
||||
@@ -668,7 +629,7 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node<TypedefInfo> {
|
||||
std::optional<TemplateInfo> Template;
|
||||
|
||||
// Underlying type declaration
|
||||
StringRef TypeDeclaration = {};
|
||||
StringRef TypeDeclaration;
|
||||
|
||||
// Indicates if this is a new C++ "using"-style typedef:
|
||||
// using MyVector = std::vector<int>
|
||||
@@ -677,10 +638,8 @@ struct TypedefInfo : public SymbolInfo, public llvm::ilist_node<TypedefInfo> {
|
||||
bool IsUsing = false;
|
||||
};
|
||||
|
||||
struct BaseRecordInfo : public RecordInfo,
|
||||
public llvm::ilist_node<BaseRecordInfo> {
|
||||
struct BaseRecordInfo : public RecordInfo {
|
||||
BaseRecordInfo();
|
||||
BaseRecordInfo(const BaseRecordInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
BaseRecordInfo(SymbolID USR, StringRef Name, StringRef Path, bool IsVirtual,
|
||||
AccessSpecifier Access, bool IsParent);
|
||||
|
||||
@@ -700,8 +659,6 @@ struct EnumValueInfo {
|
||||
: Name(internString(Name)), Value(internString(Value)),
|
||||
ValueExpr(internString(ValueExpr)) {}
|
||||
|
||||
EnumValueInfo(const EnumValueInfo &Other, llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
bool operator==(const EnumValueInfo &Other) const {
|
||||
return std::tie(Name, Value, ValueExpr) ==
|
||||
std::tie(Other.Name, Other.Value, Other.ValueExpr);
|
||||
@@ -738,7 +695,7 @@ struct EnumInfo : public SymbolInfo, public llvm::ilist_node<EnumInfo> {
|
||||
// this will be "short".
|
||||
std::optional<TypeInfo> BaseType;
|
||||
|
||||
llvm::ArrayRef<EnumValueInfo> Members; // List of enum members.
|
||||
llvm::SmallVector<EnumValueInfo, 4> Members; // List of enum members.
|
||||
};
|
||||
|
||||
struct ConceptInfo : public SymbolInfo, public llvm::ilist_node<ConceptInfo> {
|
||||
@@ -747,9 +704,9 @@ struct ConceptInfo : public SymbolInfo, public llvm::ilist_node<ConceptInfo> {
|
||||
|
||||
void merge(ConceptInfo &&I);
|
||||
|
||||
bool IsType = false;
|
||||
bool IsType;
|
||||
TemplateInfo Template;
|
||||
StringRef ConstraintExpression = {};
|
||||
StringRef ConstraintExpression;
|
||||
};
|
||||
|
||||
struct Index : public Reference {
|
||||
@@ -766,7 +723,7 @@ struct Index : public Reference {
|
||||
std::optional<StringRef> JumpToSection;
|
||||
llvm::StringMap<Index> Children;
|
||||
|
||||
std::vector<const Index *> getSortedChildren() const;
|
||||
OwningVec<const Index *> getSortedChildren() const;
|
||||
void sort();
|
||||
};
|
||||
|
||||
@@ -777,12 +734,6 @@ struct Index : public Reference {
|
||||
// if they are different.
|
||||
llvm::Expected<OwnedPtr<Info>> mergeInfos(OwningPtrArray<Info> &Values);
|
||||
|
||||
// Merges a single new Info into an existing Reduced Info (allocating it if
|
||||
// needed).
|
||||
llvm::Error mergeSingleInfo(doc::OwnedPtr<doc::Info> &Reduced,
|
||||
doc::OwnedPtr<doc::Info> &&NewInfo,
|
||||
llvm::BumpPtrAllocator &Arena);
|
||||
|
||||
struct ClangDocContext {
|
||||
ClangDocContext(tooling::ExecutionContext *ECtx, StringRef ProjectName,
|
||||
bool PublicOnly, StringRef OutDirectory, StringRef SourceRoot,
|
||||
@@ -822,26 +773,28 @@ struct ClangDocContext {
|
||||
// Ensure arena allocated types remain safe to allocate in the arena.
|
||||
// Only trivially destructible types are safe, so enforce that at compile-time.
|
||||
static_assert(std::is_trivially_destructible_v<CommentInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<ConceptInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<ConstraintInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<EnumInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<FieldTypeInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<FriendInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<FunctionInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<Info>);
|
||||
static_assert(std::is_trivially_destructible_v<Location>);
|
||||
static_assert(std::is_trivially_destructible_v<MemberTypeInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<NamespaceInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<RecordInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<Reference>);
|
||||
static_assert(std::is_trivially_destructible_v<ScopeChildren>);
|
||||
static_assert(std::is_trivially_destructible_v<SymbolInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<TemplateInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<TemplateParamInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<TemplateSpecializationInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<TypeInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<TypedefInfo>);
|
||||
static_assert(std::is_trivially_destructible_v<VarInfo>);
|
||||
|
||||
// FIXME: These types need to be trivially destructible for arena allocation.
|
||||
static_assert(!std::is_trivially_destructible_v<ConceptInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<EnumInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<FriendInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<FunctionInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<Info>);
|
||||
static_assert(!std::is_trivially_destructible_v<MemberTypeInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<NamespaceInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<RecordInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<ScopeChildren>);
|
||||
static_assert(!std::is_trivially_destructible_v<SymbolInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<TemplateInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<TemplateSpecializationInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<TypedefInfo>);
|
||||
static_assert(!std::is_trivially_destructible_v<VarInfo>);
|
||||
|
||||
} // namespace doc
|
||||
} // namespace clang
|
||||
|
||||
@@ -182,8 +182,8 @@ StringRef Serializer::getTypeAlias(const TypeAliasDecl *Alias) {
|
||||
//
|
||||
// }
|
||||
// }
|
||||
StringRef
|
||||
Serializer::getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces) {
|
||||
StringRef Serializer::getInfoRelativePath(
|
||||
const llvm::SmallVectorImpl<doc::Reference> &Namespaces) {
|
||||
llvm::SmallString<128> Path;
|
||||
for (auto R = Namespaces.rbegin(), E = Namespaces.rend(); R != E; ++R)
|
||||
llvm::sys::path::append(Path, R->Name);
|
||||
@@ -258,7 +258,9 @@ void ClangDocCommentVisitor::visitInlineCommandComment(
|
||||
for (unsigned I = 0, E = C->getNumArgs(); I != E; ++I)
|
||||
Args.push_back(internString(C->getArgText(I).trim()));
|
||||
if (!Args.empty()) {
|
||||
CurrentCI.Args = allocateArray(Args, TransientArena);
|
||||
StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
|
||||
std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
|
||||
CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,10 +276,16 @@ void ClangDocCommentVisitor::visitHTMLStartTagComment(
|
||||
AttrValues.push_back(internString(Attr.Value));
|
||||
}
|
||||
if (!AttrKeys.empty()) {
|
||||
CurrentCI.AttrKeys = allocateArray(AttrKeys, TransientArena);
|
||||
StringRef *KeysMem = TransientArena.Allocate<StringRef>(AttrKeys.size());
|
||||
std::uninitialized_copy(AttrKeys.begin(), AttrKeys.end(), KeysMem);
|
||||
CurrentCI.AttrKeys = llvm::ArrayRef<StringRef>(KeysMem, AttrKeys.size());
|
||||
}
|
||||
if (!AttrValues.empty()) {
|
||||
CurrentCI.AttrValues = allocateArray(AttrValues, TransientArena);
|
||||
StringRef *ValuesMem =
|
||||
TransientArena.Allocate<StringRef>(AttrValues.size());
|
||||
std::uninitialized_copy(AttrValues.begin(), AttrValues.end(), ValuesMem);
|
||||
CurrentCI.AttrValues =
|
||||
llvm::ArrayRef<StringRef>(ValuesMem, AttrValues.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,7 +302,9 @@ void ClangDocCommentVisitor::visitBlockCommandComment(
|
||||
for (unsigned I = 0, E = C->getNumArgs(); I < E; ++I)
|
||||
Args.push_back(internString(C->getArgText(I).trim()));
|
||||
if (!Args.empty()) {
|
||||
CurrentCI.Args = allocateArray(Args, TransientArena);
|
||||
StringRef *ArgsMem = TransientArena.Allocate<StringRef>(Args.size());
|
||||
std::uninitialized_copy(Args.begin(), Args.end(), ArgsMem);
|
||||
CurrentCI.Args = llvm::ArrayRef<StringRef>(ArgsMem, Args.size());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -465,35 +475,29 @@ void Serializer::InsertChild(ScopeChildren &Scope, const NamespaceInfo &Info) {
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, const RecordInfo &Info) {
|
||||
Reference *R = allocatePtr<Reference>(
|
||||
Info.USR, Info.Name, InfoType::IT_record, Info.Name,
|
||||
getInfoRelativePath(Info.Namespace), Info.MangledName);
|
||||
Scope.Records.push_back(*R);
|
||||
Scope.Records.emplace_back(Info.USR, Info.Name, InfoType::IT_record,
|
||||
Info.Name, getInfoRelativePath(Info.Namespace),
|
||||
Info.MangledName);
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, EnumInfo Info) {
|
||||
EnumInfo *E = allocatePtr<EnumInfo>(std::move(Info));
|
||||
Scope.Enums.push_back(*E);
|
||||
Scope.Enums.push_back(std::move(Info));
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, FunctionInfo Info) {
|
||||
FunctionInfo *F = allocatePtr<FunctionInfo>(std::move(Info));
|
||||
Scope.Functions.push_back(*F);
|
||||
Scope.Functions.push_back(std::move(Info));
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, TypedefInfo Info) {
|
||||
TypedefInfo *T = allocatePtr<TypedefInfo>(std::move(Info));
|
||||
Scope.Typedefs.push_back(*T);
|
||||
Scope.Typedefs.push_back(std::move(Info));
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, ConceptInfo Info) {
|
||||
ConceptInfo *C = allocatePtr<ConceptInfo>(std::move(Info));
|
||||
Scope.Concepts.push_back(*C);
|
||||
Scope.Concepts.push_back(std::move(Info));
|
||||
}
|
||||
|
||||
void Serializer::InsertChild(ScopeChildren &Scope, VarInfo Info) {
|
||||
VarInfo *V = allocatePtr<VarInfo>(std::move(Info));
|
||||
Scope.Variables.push_back(*V);
|
||||
Scope.Variables.push_back(std::move(Info));
|
||||
}
|
||||
|
||||
// Creates a parent of the correct type for the given child and inserts it into
|
||||
@@ -577,18 +581,14 @@ AccessSpecifier Serializer::getFinalAccessSpecifier(AccessSpecifier FirstAS,
|
||||
// record, the access specification of the field depends on the inheritance mode
|
||||
void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
|
||||
bool PublicOnly, AccessSpecifier Access) {
|
||||
SmallVector<MemberTypeInfo, 4> Members;
|
||||
for (const FieldDecl *F : D->fields()) {
|
||||
if (!shouldSerializeInfo(PublicOnly, /*IsInAnonymousNamespace=*/false, F))
|
||||
continue;
|
||||
populateMemberTypeInfo(Members, Access, F);
|
||||
populateMemberTypeInfo(I, Access, F);
|
||||
}
|
||||
const auto *CxxRD = dyn_cast<CXXRecordDecl>(D);
|
||||
if (!CxxRD) {
|
||||
if (!Members.empty())
|
||||
I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
|
||||
if (!CxxRD)
|
||||
return;
|
||||
}
|
||||
for (Decl *CxxDecl : CxxRD->decls()) {
|
||||
auto *VD = dyn_cast<VarDecl>(CxxDecl);
|
||||
if (!VD ||
|
||||
@@ -596,49 +596,40 @@ void Serializer::parseFields(RecordInfo &I, const RecordDecl *D,
|
||||
continue;
|
||||
|
||||
if (VD->isStaticDataMember())
|
||||
populateMemberTypeInfo(Members, Access, VD, /*IsStatic=*/true);
|
||||
populateMemberTypeInfo(I, Access, VD, /*IsStatic=*/true);
|
||||
}
|
||||
if (!Members.empty())
|
||||
I.Members = allocateArray<MemberTypeInfo>(Members, TransientArena);
|
||||
}
|
||||
|
||||
void Serializer::parseEnumerators(EnumInfo &I, const EnumDecl *D) {
|
||||
llvm::SmallVector<EnumValueInfo, 4> LocalMembers;
|
||||
for (const EnumConstantDecl *E : D->enumerators()) {
|
||||
std::string ValueExpr;
|
||||
if (const Expr *InitExpr = E->getInitExpr())
|
||||
ValueExpr = getSourceCode(D, InitExpr->getSourceRange());
|
||||
SmallString<16> ValueStr;
|
||||
E->getInitVal().toString(ValueStr);
|
||||
EnumValueInfo &Member = LocalMembers.emplace_back(
|
||||
E->getNameAsString(), ValueStr.str(), ValueExpr);
|
||||
I.Members.emplace_back(E->getNameAsString(), ValueStr.str(), ValueExpr);
|
||||
ASTContext &Context = E->getASTContext();
|
||||
if (RawComment *Comment =
|
||||
E->getASTContext().getRawCommentForDeclNoCache(E)) {
|
||||
Comment->setAttached();
|
||||
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, E)) {
|
||||
CommentInfo *NewCI = allocatePtr<CommentInfo>();
|
||||
Member.Description.push_back(*NewCI);
|
||||
EnumValueInfo &Member = I.Members.back();
|
||||
Member.Description.emplace_back();
|
||||
parseFullComment(Fc, Member.Description.back());
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!LocalMembers.empty())
|
||||
I.Members = allocateArray<EnumValueInfo>(LocalMembers, TransientArena);
|
||||
}
|
||||
|
||||
void Serializer::parseParameters(FunctionInfo &I, const FunctionDecl *D) {
|
||||
llvm::SmallVector<FieldTypeInfo, 4> LocalParams;
|
||||
auto &LO = D->getLangOpts();
|
||||
for (const ParmVarDecl *P : D->parameters()) {
|
||||
FieldTypeInfo &FieldInfo = LocalParams.emplace_back(
|
||||
FieldTypeInfo &FieldInfo = I.Params.emplace_back(
|
||||
getTypeInfoForType(P->getOriginalType(), LO), P->getNameAsString());
|
||||
if (std::optional<StringRef> DefaultValue =
|
||||
getSourceCode(D, P->getDefaultArgRange()))
|
||||
FieldInfo.DefaultValue = *DefaultValue;
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
I.Params = allocateArray<FieldTypeInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
|
||||
// TODO: Remove the serialization of Parents and VirtualParents, this
|
||||
@@ -648,36 +639,28 @@ void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D) {
|
||||
if (!D->isThisDeclarationADefinition())
|
||||
return;
|
||||
|
||||
llvm::SmallVector<Reference, 4> LocalParents;
|
||||
for (const CXXBaseSpecifier &B : D->bases()) {
|
||||
if (B.isVirtual())
|
||||
continue;
|
||||
if (const auto *Ty = B.getType()->getAs<TemplateSpecializationType>()) {
|
||||
const TemplateDecl *D = Ty->getTemplateName().getAsTemplateDecl();
|
||||
LocalParents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
|
||||
InfoType::IT_record, B.getType().getAsString());
|
||||
I.Parents.emplace_back(getUSRForDecl(D), B.getType().getAsString(),
|
||||
InfoType::IT_record, B.getType().getAsString());
|
||||
} else if (const RecordDecl *P = getRecordDeclForType(B.getType()))
|
||||
LocalParents.emplace_back(
|
||||
getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
|
||||
P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
|
||||
I.Parents.emplace_back(getUSRForDecl(P), P->getNameAsString(),
|
||||
InfoType::IT_record, P->getQualifiedNameAsString(),
|
||||
internString(getInfoRelativePath(P)));
|
||||
else
|
||||
LocalParents.emplace_back(SymbolID(), B.getType().getAsString());
|
||||
I.Parents.emplace_back(SymbolID(), B.getType().getAsString());
|
||||
}
|
||||
if (!LocalParents.empty())
|
||||
I.Parents = allocateArray<Reference>(LocalParents, TransientArena);
|
||||
|
||||
llvm::SmallVector<Reference, 4> LocalVirtualParents;
|
||||
for (const CXXBaseSpecifier &B : D->vbases()) {
|
||||
if (const RecordDecl *P = getRecordDeclForType(B.getType()))
|
||||
LocalVirtualParents.emplace_back(
|
||||
I.VirtualParents.emplace_back(
|
||||
getUSRForDecl(P), P->getNameAsString(), InfoType::IT_record,
|
||||
P->getQualifiedNameAsString(), internString(getInfoRelativePath(P)));
|
||||
else
|
||||
LocalVirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
|
||||
I.VirtualParents.emplace_back(SymbolID(), B.getType().getAsString());
|
||||
}
|
||||
if (!LocalVirtualParents.empty())
|
||||
I.VirtualParents =
|
||||
allocateArray<Reference>(LocalVirtualParents, TransientArena);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
@@ -725,13 +708,10 @@ void Serializer::populateTemplateParameters(
|
||||
if (!TemplateInfo) {
|
||||
TemplateInfo.emplace();
|
||||
}
|
||||
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (const NamedDecl *ND : *ParamList) {
|
||||
LocalParams.emplace_back(getSourceCode(ND, ND->getSourceRange()));
|
||||
TemplateInfo->Params.emplace_back(
|
||||
getSourceCode(ND, ND->getSourceRange()));
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
TemplateInfo->Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -794,14 +774,9 @@ void Serializer::populateInfo(Info &I, const T *D, const FullComment *C,
|
||||
ConversionDecl->getConversionType().getAsString());
|
||||
else
|
||||
I.Name = internString(D->getNameAsString());
|
||||
llvm::SmallVector<Reference, 4> LocalNamespaces;
|
||||
populateParentNamespaces(LocalNamespaces, D, IsInAnonymousNamespace);
|
||||
if (!LocalNamespaces.empty())
|
||||
I.Namespace = allocateArray<Reference>(LocalNamespaces, TransientArena);
|
||||
populateParentNamespaces(I.Namespace, D, IsInAnonymousNamespace);
|
||||
if (C) {
|
||||
|
||||
CommentInfo *NewCI = allocatePtr<CommentInfo>();
|
||||
I.Description.push_back(*NewCI);
|
||||
I.Description.emplace_back();
|
||||
parseFullComment(C, I.Description.back());
|
||||
}
|
||||
}
|
||||
@@ -813,10 +788,8 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
|
||||
populateInfo(I, D, C, IsInAnonymousNamespace);
|
||||
if (D->isThisDeclarationADefinition())
|
||||
I.DefLoc = Loc;
|
||||
else {
|
||||
Location *NewL = allocatePtr<Location>(Loc);
|
||||
I.Loc.push_back(*NewL);
|
||||
}
|
||||
else
|
||||
I.Loc.emplace_back(Loc);
|
||||
|
||||
auto *Mangler = ItaniumMangleContext::create(
|
||||
D->getASTContext(), D->getASTContext().getDiagnostics());
|
||||
@@ -838,8 +811,7 @@ void Serializer::populateSymbolInfo(SymbolInfo &I, const T *D,
|
||||
}
|
||||
|
||||
void Serializer::handleCompoundConstraints(
|
||||
const Expr *Constraint,
|
||||
llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos) {
|
||||
const Expr *Constraint, OwningVec<ConstraintInfo> &ConstraintInfos) {
|
||||
if (Constraint->getStmtClass() == Stmt::ParenExprClass) {
|
||||
handleCompoundConstraints(dyn_cast<ParenExpr>(Constraint)->getSubExpr(),
|
||||
ConstraintInfos);
|
||||
@@ -863,7 +835,6 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
|
||||
|
||||
SmallVector<AssociatedConstraint> AssociatedConstraints;
|
||||
D->getAssociatedConstraints(AssociatedConstraints);
|
||||
SmallVector<ConstraintInfo, 4> LocalConstraints;
|
||||
for (const auto &Constraint : AssociatedConstraints) {
|
||||
if (!Constraint)
|
||||
continue;
|
||||
@@ -875,14 +846,11 @@ void Serializer::populateConstraints(TemplateInfo &I, const TemplateDecl *D) {
|
||||
ConstraintInfo CI(getUSRForDecl(ConstraintExpr->getNamedConcept()),
|
||||
ConstraintExpr->getNamedConcept()->getNameAsString());
|
||||
CI.ConstraintExpr = internString(exprToString(ConstraintExpr));
|
||||
LocalConstraints.push_back(std::move(CI));
|
||||
I.Constraints.push_back(std::move(CI));
|
||||
} else {
|
||||
handleCompoundConstraints(Constraint.ConstraintExpr, LocalConstraints);
|
||||
handleCompoundConstraints(Constraint.ConstraintExpr, I.Constraints);
|
||||
}
|
||||
}
|
||||
if (!LocalConstraints.empty())
|
||||
I.Constraints =
|
||||
allocateArray<ConstraintInfo>(LocalConstraints, TransientArena);
|
||||
}
|
||||
|
||||
void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
|
||||
@@ -911,13 +879,9 @@ void Serializer::populateFunctionInfo(FunctionInfo &I, const FunctionDecl *D,
|
||||
|
||||
// Template parameters to the specialization.
|
||||
if (FTSI->TemplateArguments) {
|
||||
SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (const TemplateArgument &Arg : FTSI->TemplateArguments->asArray()) {
|
||||
LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
|
||||
Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
Specialization.Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -937,28 +901,26 @@ void Serializer::populateMemberTypeInfo(T &I, const Decl *D) {
|
||||
|
||||
Comment->setAttached();
|
||||
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
|
||||
CommentInfo *NewCI = allocatePtr<CommentInfo>();
|
||||
I.Description.push_back(*NewCI);
|
||||
I.Description.emplace_back();
|
||||
parseFullComment(Fc, I.Description.back());
|
||||
}
|
||||
}
|
||||
|
||||
void Serializer::populateMemberTypeInfo(
|
||||
SmallVectorImpl<MemberTypeInfo> &Members, AccessSpecifier &Access,
|
||||
const DeclaratorDecl *D, bool IsStatic) {
|
||||
void Serializer::populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
|
||||
const DeclaratorDecl *D,
|
||||
bool IsStatic) {
|
||||
// Use getAccessUnsafe so that we just get the default AS_none if it's not
|
||||
// valid, as opposed to an assert.
|
||||
MemberTypeInfo &NewMember = Members.emplace_back(
|
||||
MemberTypeInfo &NewMember = I.Members.emplace_back(
|
||||
getTypeInfoForType(D->getTypeSourceInfo()->getType(), D->getLangOpts()),
|
||||
D->getNameAsString(),
|
||||
getFinalAccessSpecifier(Access, D->getAccessUnsafe()), IsStatic);
|
||||
populateMemberTypeInfo(NewMember, D);
|
||||
}
|
||||
|
||||
void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
|
||||
const CXXRecordDecl *D, bool IsFileInRootDir,
|
||||
bool PublicOnly, bool IsParent,
|
||||
AccessSpecifier ParentAccess) {
|
||||
void Serializer::parseBases(RecordInfo &I, const CXXRecordDecl *D,
|
||||
bool IsFileInRootDir, bool PublicOnly,
|
||||
bool IsParent, AccessSpecifier ParentAccess) {
|
||||
// Don't parse bases if this isn't a definition.
|
||||
if (!D->isThisDeclarationADefinition())
|
||||
return;
|
||||
@@ -997,15 +959,14 @@ void Serializer::parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
|
||||
IsInAnonymousNamespace);
|
||||
FI.Access =
|
||||
getFinalAccessSpecifier(BI.Access, MD->getAccessUnsafe());
|
||||
FunctionInfo *FIPtr = allocatePtr<FunctionInfo>(std::move(FI));
|
||||
BI.Children.Functions.push_back(*FIPtr);
|
||||
BI.Children.Functions.emplace_back(std::move(FI));
|
||||
}
|
||||
Bases.emplace_back(std::move(BI));
|
||||
I.Bases.emplace_back(std::move(BI));
|
||||
// Call this function recursively to get the inherited classes of
|
||||
// this base; these new bases will also get stored in the original
|
||||
// RecordInfo: I.
|
||||
parseBases(Bases, Base, IsFileInRootDir, PublicOnly, false,
|
||||
Bases.back().Access);
|
||||
parseBases(I, Base, IsFileInRootDir, PublicOnly, false,
|
||||
I.Bases.back().Access);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1034,8 +995,6 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
|
||||
if (!D->hasDefinition() || !D->hasFriends())
|
||||
return;
|
||||
|
||||
llvm::SmallVector<FriendInfo, 4> LocalFriends;
|
||||
|
||||
for (const FriendDecl *FD : D->friends()) {
|
||||
if (FD->isUnsupportedFriend())
|
||||
continue;
|
||||
@@ -1057,12 +1016,9 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
|
||||
if (isa<RecordDecl>(ActualTD->getTemplatedDecl()))
|
||||
F.IsClass = true;
|
||||
F.Template.emplace();
|
||||
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (const auto *Param : ActualTD->getTemplateParameters()->asArray())
|
||||
LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
|
||||
if (!LocalParams.empty())
|
||||
F.Template->Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
F.Template->Params.emplace_back(
|
||||
getSourceCode(Param, Param->getSourceRange()));
|
||||
ActualDecl = ActualTD->getTemplatedDecl();
|
||||
}
|
||||
|
||||
@@ -1080,10 +1036,8 @@ void Serializer::parseFriends(RecordInfo &RI, const CXXRecordDecl *D) {
|
||||
getInfoRelativePath(ActualDecl));
|
||||
|
||||
populateMemberTypeInfo(F, ActualDecl);
|
||||
LocalFriends.push_back(std::move(F));
|
||||
RI.Friends.push_back(std::move(F));
|
||||
}
|
||||
if (!LocalFriends.empty())
|
||||
RI.Friends = allocateArray<FriendInfo>(LocalFriends, TransientArena);
|
||||
}
|
||||
|
||||
std::pair<OwnedPtr<Info>, OwnedPtr<Info>>
|
||||
@@ -1107,11 +1061,7 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
|
||||
}
|
||||
// TODO: remove first call to parseBases, that function should be deleted
|
||||
parseBases(*RI, C);
|
||||
llvm::SmallVector<BaseRecordInfo, 4> LocalBases;
|
||||
parseBases(LocalBases, C, /*IsFileInRootDir=*/true, PublicOnly,
|
||||
/*IsParent=*/true);
|
||||
if (!LocalBases.empty())
|
||||
RI->Bases = allocateArray<BaseRecordInfo>(LocalBases, TransientArena);
|
||||
parseBases(*RI, C, /*IsFileInRootDir=*/true, PublicOnly, /*IsParent=*/true);
|
||||
parseFriends(*RI, C);
|
||||
}
|
||||
RI->Path = internString(getInfoRelativePath(RI->Namespace));
|
||||
@@ -1144,23 +1094,15 @@ Serializer::emitInfo(const RecordDecl *D, const FullComment *FC, Location Loc,
|
||||
dyn_cast<ClassTemplatePartialSpecializationDecl>(D)) {
|
||||
if (const ASTTemplateArgumentListInfo *AsWritten =
|
||||
CTPSD->getTemplateArgsAsWritten()) {
|
||||
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (unsigned Idx = 0; Idx < AsWritten->getNumTemplateArgs(); Idx++) {
|
||||
LocalParams.emplace_back(
|
||||
Specialization.Params.emplace_back(
|
||||
getSourceCode(D, (*AsWritten)[Idx].getSourceRange()));
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
Specialization.Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
} else {
|
||||
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (const TemplateArgument &Arg : CTSD->getTemplateArgs().asArray()) {
|
||||
LocalParams.push_back(convertTemplateArgToInfo(D, Arg));
|
||||
Specialization.Params.push_back(convertTemplateArgToInfo(D, Arg));
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
Specialization.Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1222,9 +1164,8 @@ void Serializer::extractCommentFromDecl(const Decl *D, TypedefInfo &Info) {
|
||||
|
||||
Comment->setAttached();
|
||||
if (comments::FullComment *Fc = Comment->parse(Context, nullptr, D)) {
|
||||
CommentInfo *NewCI = allocatePtr<CommentInfo>();
|
||||
Info.Description.push_back(*NewCI);
|
||||
parseFullComment(Fc, *NewCI);
|
||||
Info.Description.emplace_back();
|
||||
parseFullComment(Fc, Info.Description.back());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1317,13 +1258,10 @@ Serializer::emitInfo(const ConceptDecl *D, const FullComment *FC,
|
||||
Concept.ConstraintExpression = exprToString(D->getConstraintExpr());
|
||||
|
||||
if (auto *ConceptParams = D->getTemplateParameters()) {
|
||||
llvm::SmallVector<TemplateParamInfo, 4> LocalParams;
|
||||
for (const auto *Param : ConceptParams->asArray()) {
|
||||
LocalParams.emplace_back(getSourceCode(Param, Param->getSourceRange()));
|
||||
Concept.Template.Params.emplace_back(
|
||||
getSourceCode(Param, Param->getSourceRange()));
|
||||
}
|
||||
if (!LocalParams.empty())
|
||||
Concept.Template.Params =
|
||||
allocateArray<TemplateParamInfo>(LocalParams, TransientArena);
|
||||
}
|
||||
|
||||
if (!shouldSerializeInfo(PublicOnly, IsInAnonymousNamespace, D))
|
||||
|
||||
@@ -94,7 +94,8 @@ private:
|
||||
|
||||
StringRef getTypeAlias(const TypeAliasDecl *Alias);
|
||||
|
||||
StringRef getInfoRelativePath(llvm::ArrayRef<doc::Reference> Namespaces);
|
||||
StringRef
|
||||
getInfoRelativePath(const llvm::SmallVectorImpl<doc::Reference> &Namespaces);
|
||||
|
||||
StringRef getInfoRelativePath(const Decl *D);
|
||||
|
||||
@@ -138,9 +139,8 @@ private:
|
||||
|
||||
void parseBases(RecordInfo &I, const CXXRecordDecl *D);
|
||||
|
||||
void parseBases(llvm::SmallVectorImpl<BaseRecordInfo> &Bases,
|
||||
const CXXRecordDecl *D, bool IsFileInRootDir, bool PublicOnly,
|
||||
bool IsParent,
|
||||
void parseBases(RecordInfo &I, const CXXRecordDecl *D, bool IsFileInRootDir,
|
||||
bool PublicOnly, bool IsParent,
|
||||
AccessSpecifier ParentAccess = AccessSpecifier::AS_public);
|
||||
|
||||
template <typename T>
|
||||
@@ -165,9 +165,8 @@ private:
|
||||
void populateSymbolInfo(SymbolInfo &I, const T *D, const FullComment *C,
|
||||
Location Loc, bool &IsInAnonymousNamespace);
|
||||
|
||||
void handleCompoundConstraints(
|
||||
const Expr *Constraint,
|
||||
llvm::SmallVectorImpl<ConstraintInfo> &ConstraintInfos);
|
||||
void handleCompoundConstraints(const Expr *Constraint,
|
||||
OwningVec<ConstraintInfo> &ConstraintInfos);
|
||||
|
||||
void populateConstraints(TemplateInfo &I, const TemplateDecl *D);
|
||||
|
||||
@@ -177,9 +176,8 @@ private:
|
||||
|
||||
template <typename T> void populateMemberTypeInfo(T &I, const Decl *D);
|
||||
|
||||
void populateMemberTypeInfo(llvm::SmallVectorImpl<MemberTypeInfo> &Members,
|
||||
AccessSpecifier &Access, const DeclaratorDecl *D,
|
||||
bool IsStatic = false);
|
||||
void populateMemberTypeInfo(RecordInfo &I, AccessSpecifier &Access,
|
||||
const DeclaratorDecl *D, bool IsStatic = false);
|
||||
|
||||
void parseFriends(RecordInfo &RI, const CXXRecordDecl *D);
|
||||
|
||||
|
||||
@@ -31,70 +31,9 @@ LLVM_YAML_IS_SEQUENCE_VECTOR(BaseRecordInfo)
|
||||
LLVM_YAML_IS_SEQUENCE_VECTOR(OwnedPtr<CommentInfo>)
|
||||
|
||||
namespace llvm {
|
||||
|
||||
template <typename T>
|
||||
bool operator==(const llvm::simple_ilist<T> &LHS,
|
||||
const llvm::simple_ilist<T> &RHS) {
|
||||
auto LIt = LHS.begin(), LEnd = LHS.end();
|
||||
auto RIt = RHS.begin(), REnd = RHS.end();
|
||||
for (; LIt != LEnd && RIt != REnd; ++LIt, ++RIt) {
|
||||
if (!(*LIt == *RIt))
|
||||
return false;
|
||||
}
|
||||
return LIt == LEnd && RIt == REnd;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
bool operator!=(const llvm::simple_ilist<T> &LHS,
|
||||
const llvm::simple_ilist<T> &RHS) {
|
||||
return !(LHS == RHS);
|
||||
}
|
||||
|
||||
namespace yaml {
|
||||
|
||||
// Provide SequenceTraits for ArrayRef<T*> since YAMLTraits only provides it for
|
||||
// MutableArrayRef
|
||||
template <typename T> struct SequenceTraits<ArrayRef<T *>> {
|
||||
static size_t size(IO &io, ArrayRef<T *> &seq) { return seq.size(); }
|
||||
static T *&element(IO &io, ArrayRef<T *> &seq, size_t index) {
|
||||
// ArrayRef is not mutable, but YAML output only reads the value.
|
||||
return const_cast<T *&>(seq[index]);
|
||||
}
|
||||
};
|
||||
|
||||
template <typename T> struct SequenceTraits<llvm::simple_ilist<T>> {
|
||||
static size_t size(IO &io, llvm::simple_ilist<T> &seq) { return seq.size(); }
|
||||
static T &element(IO &io, llvm::simple_ilist<T> &seq, size_t index) {
|
||||
return *std::next(seq.begin(), index);
|
||||
}
|
||||
};
|
||||
|
||||
// Map pointers to the value mappings as clang-doc only does output
|
||||
// serialization.
|
||||
template <typename T> struct PointerMappingTraits {
|
||||
static void mapping(IO &IO, T *&Val) {
|
||||
if (Val)
|
||||
MappingTraits<T>::mapping(IO, *Val);
|
||||
}
|
||||
};
|
||||
|
||||
template <>
|
||||
struct MappingTraits<clang::doc::Reference *>
|
||||
: PointerMappingTraits<clang::doc::Reference> {};
|
||||
template <>
|
||||
struct MappingTraits<clang::doc::CommentInfo *>
|
||||
: PointerMappingTraits<clang::doc::CommentInfo> {};
|
||||
template <>
|
||||
struct MappingTraits<clang::doc::FunctionInfo *>
|
||||
: PointerMappingTraits<clang::doc::FunctionInfo> {};
|
||||
template <>
|
||||
struct MappingTraits<clang::doc::EnumInfo *>
|
||||
: PointerMappingTraits<clang::doc::EnumInfo> {};
|
||||
template <>
|
||||
struct MappingTraits<clang::doc::TemplateParamInfo *>
|
||||
: PointerMappingTraits<clang::doc::TemplateParamInfo> {};
|
||||
|
||||
template <typename T> struct SequenceTraits<ArrayRef<T>> {
|
||||
template <typename T> struct SequenceTraits<llvm::ArrayRef<T>> {
|
||||
static size_t size(IO &io, llvm::ArrayRef<T> &seq) { return seq.size(); }
|
||||
static T &element(IO &io, llvm::ArrayRef<T> &seq, size_t index) {
|
||||
return const_cast<T &>(seq[index]);
|
||||
@@ -252,7 +191,7 @@ static void infoMapping(IO &IO, Info &I) {
|
||||
static void symbolInfoMapping(IO &IO, SymbolInfo &I) {
|
||||
infoMapping(IO, I);
|
||||
IO.mapOptional("DefLocation", I.DefLoc, std::optional<Location>());
|
||||
IO.mapOptional("Location", I.Loc);
|
||||
IO.mapOptional("Location", I.Loc, llvm::SmallVector<Location, 2>());
|
||||
}
|
||||
|
||||
static void recordInfoMapping(IO &IO, RecordInfo &I) {
|
||||
@@ -261,10 +200,10 @@ static void recordInfoMapping(IO &IO, RecordInfo &I) {
|
||||
IO.mapOptional("IsTypeDef", I.IsTypeDef, false);
|
||||
IO.mapOptional("Members", I.Members);
|
||||
IO.mapOptional("Bases", I.Bases);
|
||||
IO.mapOptional("Parents", I.Parents, SmallVector<Reference, 4>());
|
||||
IO.mapOptional("Parents", I.Parents, llvm::SmallVector<Reference, 4>());
|
||||
IO.mapOptional("VirtualParents", I.VirtualParents,
|
||||
llvm::SmallVector<Reference, 4>());
|
||||
IO.mapOptional("ChildRecords", I.Children.Records);
|
||||
IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
|
||||
IO.mapOptional("ChildFunctions", I.Children.Functions);
|
||||
IO.mapOptional("ChildEnums", I.Children.Enums);
|
||||
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
|
||||
@@ -400,7 +339,7 @@ template <> struct MappingTraits<NamespaceInfo> {
|
||||
for (const auto &N : I.Children.Namespaces)
|
||||
TempNamespaces.push_back(N);
|
||||
IO.mapOptional("ChildNamespaces", TempNamespaces, std::vector<Reference>());
|
||||
IO.mapOptional("ChildRecords", I.Children.Records);
|
||||
IO.mapOptional("ChildRecords", I.Children.Records, OwningVec<Reference>());
|
||||
IO.mapOptional("ChildFunctions", I.Children.Functions);
|
||||
IO.mapOptional("ChildEnums", I.Children.Enums);
|
||||
IO.mapOptional("ChildTypedefs", I.Children.Typedefs);
|
||||
@@ -502,6 +441,13 @@ template <> struct MappingTraits<CommentInfo> {
|
||||
static void mapping(IO &IO, CommentInfo &I) { commentInfoMapping(IO, I); }
|
||||
};
|
||||
|
||||
template <> struct MappingTraits<OwnedPtr<CommentInfo>> {
|
||||
static void mapping(IO &IO, OwnedPtr<CommentInfo> &I) {
|
||||
if (I)
|
||||
commentInfoMapping(IO, *I);
|
||||
}
|
||||
};
|
||||
|
||||
} // end namespace yaml
|
||||
} // end namespace llvm
|
||||
|
||||
|
||||
@@ -184,10 +184,9 @@ static void BM_JSONGenerator_Scale(benchmark::State &State) {
|
||||
auto NI = allocatePtr<NamespaceInfo>();
|
||||
NI->Name = "GlobalNamespace";
|
||||
for (int i = 0; i < NumRecords; ++i) {
|
||||
Reference *R = new (TransientArena.Allocate<Reference>())
|
||||
Reference(SymbolID{(uint8_t)(i & 0xFF)}, "Record" + std::to_string(i),
|
||||
InfoType::IT_record);
|
||||
NI->Children.Records.push_back(*R);
|
||||
NI->Children.Records.emplace_back(SymbolID{(uint8_t)(i & 0xFF)},
|
||||
"Record" + std::to_string(i),
|
||||
InfoType::IT_record);
|
||||
}
|
||||
|
||||
IntrusiveRefCntPtr<DiagnosticIDs> DiagID(new DiagnosticIDs());
|
||||
|
||||
@@ -29,7 +29,6 @@
|
||||
#include "clang/Tooling/CommonOptionsParser.h"
|
||||
#include "clang/Tooling/Execution.h"
|
||||
#include "llvm/ADT/APFloat.h"
|
||||
#include "llvm/ADT/ScopeExit.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Support/Error.h"
|
||||
#include "llvm/Support/FileSystem.h"
|
||||
@@ -359,22 +358,15 @@ Example usage for a project using a compile commands database:
|
||||
llvm::hardware_concurrency(ExecutorConcurrency));
|
||||
{
|
||||
llvm::TimeTraceScope TS("Reduce");
|
||||
for (const auto &Group : USRToBitcode) {
|
||||
StringRef Key = Group.getKey();
|
||||
std::vector<StringRef> Bitcodes = Group.getValue();
|
||||
Pool.async([Key, Bitcodes, &CDCtx, &Diags, &USRToInfo, &USRToInfoMutex,
|
||||
&IndexMutex, &DiagMutex, &Error, DiagIDBitcodeReading,
|
||||
DiagIDBitcodeMerging]() {
|
||||
if (CDCtx.FTimeTrace)
|
||||
for (auto &Group : USRToBitcode) {
|
||||
Pool.async([&, &Diags = Diags]() { // time trace decoding bitcode
|
||||
if (FTimeTrace)
|
||||
llvm::timeTraceProfilerInitialize(200, "clang-doc");
|
||||
|
||||
doc::OwnedPtr<doc::Info> Reduced = nullptr;
|
||||
doc::OwningPtrVec<doc::Info> Infos;
|
||||
{
|
||||
llvm::TimeTraceScope Red("decoding and merging bitcode");
|
||||
for (const auto &Bitcode : Bitcodes) {
|
||||
|
||||
llvm::scope_exit ArenaGuard(
|
||||
[] { clang::doc::TransientArena.Reset(); });
|
||||
llvm::TimeTraceScope Red("decoding bitcode");
|
||||
for (auto &Bitcode : Group.getValue()) {
|
||||
llvm::BitstreamCursor Stream(Bitcode);
|
||||
doc::ClangDocBitcodeReader Reader(Stream, Diags);
|
||||
auto ReadInfos = Reader.readBitcode();
|
||||
@@ -386,17 +378,25 @@ Example usage for a project using a compile commands database:
|
||||
Error = true;
|
||||
return;
|
||||
}
|
||||
for (auto &I : *ReadInfos) {
|
||||
if (auto Err = doc::mergeSingleInfo(
|
||||
Reduced, std::move(I), clang::doc::PersistentArena)) {
|
||||
std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex);
|
||||
Diags.Report(DiagIDBitcodeMerging)
|
||||
<< toString(std::move(Err));
|
||||
return;
|
||||
}
|
||||
}
|
||||
std::move(ReadInfos->begin(), ReadInfos->end(),
|
||||
std::back_inserter(Infos));
|
||||
}
|
||||
} // time trace decoding and merging bitcode
|
||||
} // time trace decoding bitcode
|
||||
|
||||
doc::OwnedPtr<doc::Info> Reduced;
|
||||
|
||||
{
|
||||
llvm::TimeTraceScope Merge("merging bitcode");
|
||||
auto ExpReduced = doc::mergeInfos(Infos);
|
||||
|
||||
if (!ExpReduced) {
|
||||
std::lock_guard<llvm::sys::Mutex> Guard(DiagMutex);
|
||||
Diags.Report(DiagIDBitcodeMerging)
|
||||
<< toString(ExpReduced.takeError());
|
||||
return;
|
||||
}
|
||||
Reduced = std::move(*ExpReduced);
|
||||
} // time trace merging bitcode
|
||||
|
||||
// Add a reference to this Info in the Index
|
||||
{
|
||||
@@ -408,7 +408,7 @@ Example usage for a project using a compile commands database:
|
||||
{
|
||||
llvm::TimeTraceScope Merge("USRToInfo");
|
||||
std::lock_guard<llvm::sys::Mutex> Guard(USRToInfoMutex);
|
||||
USRToInfo[Key] = std::move(Reduced);
|
||||
USRToInfo[Group.getKey()] = std::move(Reduced);
|
||||
}
|
||||
|
||||
if (CDCtx.FTimeTrace)
|
||||
|
||||
@@ -56,6 +56,7 @@ static OwningPtrVec<Info> readInfo(StringRef Bitcode, size_t NumInfos,
|
||||
llvm::BitstreamCursor Stream(Bitcode);
|
||||
doc::ClangDocBitcodeReader Reader(Stream, Diags);
|
||||
auto Infos = Reader.readBitcode();
|
||||
|
||||
// Check that there was no error in the read.
|
||||
assert(Infos);
|
||||
EXPECT_EQ(Infos.get().size(), NumInfos);
|
||||
@@ -67,43 +68,39 @@ class BitcodeTest : public ClangDocContextTest {};
|
||||
TEST_F(BitcodeTest, emitNamespaceInfoBitcode) {
|
||||
NamespaceInfo I;
|
||||
I.Name = "r";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
|
||||
I.Children.Namespaces.push_back(NewNamespace);
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo FI;
|
||||
I.Children.Functions.push_back(FI);
|
||||
EnumInfo EI;
|
||||
I.Children.Enums.push_back(EI);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Enums.emplace_back();
|
||||
|
||||
std::string WriteResult = writeInfo(&I, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0]));
|
||||
CheckNamespaceInfo(&I, InfoAsNamespace(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitRecordInfoBitcode) {
|
||||
RecordInfo I;
|
||||
I.Name = "r";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
I.TagType = TagTypeKind::Class;
|
||||
I.IsTypeDef = true;
|
||||
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
|
||||
true);
|
||||
FunctionInfo FI;
|
||||
B.Children.Functions.push_back(FI);
|
||||
MemberTypeInfo BM(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
|
||||
AccessSpecifier::AS_public, true);
|
||||
I.Bases.back().Children.Functions.emplace_back();
|
||||
I.Bases.back().Members.emplace_back(TypeInfo("int"), "X",
|
||||
AccessSpecifier::AS_private);
|
||||
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
|
||||
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
|
||||
|
||||
// Documentation for the data member.
|
||||
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
|
||||
@@ -112,47 +109,29 @@ TEST_F(BitcodeTest, emitRecordInfoBitcode) {
|
||||
CommentInfo TopCommentChildren[] = {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
|
||||
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
|
||||
BM.Description.push_back(TopComment);
|
||||
MemberTypeInfo BMem[] = {std::move(BM)};
|
||||
B.Members = llvm::ArrayRef(BMem);
|
||||
BaseRecordInfo Bases[] = {std::move(B)};
|
||||
I.Bases = llvm::ArrayRef(Bases);
|
||||
I.Bases.back().Members.back().Description.emplace_back(std::move(TopComment));
|
||||
|
||||
MemberTypeInfo Mem[] = {std::move(M)};
|
||||
I.Members = llvm::ArrayRef(Mem);
|
||||
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)};
|
||||
I.Parents = llvm::ArrayRef(Parents);
|
||||
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)};
|
||||
I.VirtualParents = llvm::ArrayRef(VParents);
|
||||
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo FI2;
|
||||
I.Children.Functions.push_back(FI2);
|
||||
EnumInfo EI;
|
||||
I.Children.Enums.push_back(EI);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Enums.emplace_back();
|
||||
|
||||
std::string WriteResult = writeInfo(&I, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckRecordInfo(&I, InfoAsRecord(ReadResults[0]));
|
||||
CheckRecordInfo(&I, InfoAsRecord(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
|
||||
FunctionInfo I;
|
||||
I.Name = "f";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
I.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo P(TypeInfo("int"), "P");
|
||||
FieldTypeInfo Params[] = {std::move(P)};
|
||||
I.Params = llvm::ArrayRef(Params);
|
||||
I.Params.emplace_back(TypeInfo("int"), "P");
|
||||
|
||||
I.Access = AccessSpecifier::AS_none;
|
||||
|
||||
@@ -160,23 +139,19 @@ TEST_F(BitcodeTest, emitFunctionInfoBitcode) {
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
|
||||
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitMethodInfoBitcode) {
|
||||
FunctionInfo I;
|
||||
I.Name = "f";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
I.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo P(TypeInfo("int"), "P");
|
||||
FieldTypeInfo Params[] = {std::move(P)};
|
||||
I.Params = llvm::ArrayRef(Params);
|
||||
I.Params.emplace_back(TypeInfo("int"), "P");
|
||||
I.IsMethod = true;
|
||||
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
|
||||
|
||||
@@ -186,36 +161,31 @@ TEST_F(BitcodeTest, emitMethodInfoBitcode) {
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0]));
|
||||
CheckFunctionInfo(&I, InfoAsFunction(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitEnumInfoBitcode) {
|
||||
EnumInfo I;
|
||||
I.Name = "e";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
EnumValueInfo EV("X");
|
||||
EnumValueInfo Mems[] = {std::move(EV)};
|
||||
I.Members = llvm::ArrayRef(Mems);
|
||||
I.Members.emplace_back("X");
|
||||
I.Scoped = true;
|
||||
|
||||
std::string WriteResult = writeInfo(&I, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckEnumInfo(&I, InfoAsEnum(ReadResults[0]));
|
||||
CheckEnumInfo(&I, InfoAsEnum(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
|
||||
TypedefInfo I;
|
||||
I.Name = "MyInt";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
I.Underlying = TypeInfo("unsigned");
|
||||
@@ -226,13 +196,13 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, BlankChildren)};
|
||||
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
|
||||
|
||||
I.Description.push_back(Top);
|
||||
I.Description.emplace_back(std::move(Top));
|
||||
|
||||
std::string WriteResult = writeInfo(&I, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0]));
|
||||
CheckTypedefInfo(&I, InfoAsTypedef(ReadResults[0].get()));
|
||||
|
||||
// Check one with no IsUsing set, no description, and no definition location.
|
||||
TypedefInfo I2;
|
||||
@@ -243,7 +213,7 @@ TEST_F(BitcodeTest, emitTypedefInfoBitcode) {
|
||||
WriteResult = writeInfo(&I2, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0]));
|
||||
CheckTypedefInfo(&I2, InfoAsTypedef(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
|
||||
@@ -251,8 +221,7 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
|
||||
F.Name = "F";
|
||||
F.ReturnType = TypeInfo("void");
|
||||
F.DefLoc = Location(0, 0, "test.cpp");
|
||||
FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I")};
|
||||
F.Params = llvm::ArrayRef(PI);
|
||||
F.Params.emplace_back(TypeInfo("int"), "I");
|
||||
|
||||
// BlankLine
|
||||
CommentInfo BlankChildren[] = {CommentInfo(CommentKind::CK_TextComment)};
|
||||
@@ -324,13 +293,13 @@ TEST_F(BitcodeTest, emitInfoWithCommentBitcode) {
|
||||
Verbatim, ParamOut, ParamIn, Return};
|
||||
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
|
||||
|
||||
F.Description.push_back(Top);
|
||||
F.Description.emplace_back(std::move(Top));
|
||||
|
||||
std::string WriteResult = writeInfo(&F, this->Diags);
|
||||
EXPECT_TRUE(WriteResult.size() > 0);
|
||||
OwningPtrVec<Info> ReadResults = readInfo(WriteResult, 1, this->Diags);
|
||||
|
||||
CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0]));
|
||||
CheckFunctionInfo(&F, InfoAsFunction(ReadResults[0].get()));
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
||||
@@ -54,10 +54,10 @@ TypedefInfo *InfoAsTypedef(Info *I) {
|
||||
return static_cast<TypedefInfo *>(I);
|
||||
}
|
||||
|
||||
void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
|
||||
ArrayRef<CommentInfo> Actual);
|
||||
void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
|
||||
const OwningVec<CommentInfo> &Actual);
|
||||
void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
|
||||
const std::vector<CommentInfo> &Actual);
|
||||
void CheckCommentInfo(const std::vector<OwnedPtr<CommentInfo>> &Expected,
|
||||
const std::vector<OwnedPtr<CommentInfo>> &Actual);
|
||||
|
||||
void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
|
||||
EXPECT_EQ(Expected.Kind, Actual.Kind);
|
||||
@@ -84,71 +84,52 @@ void CheckCommentInfo(const CommentInfo &Expected, const CommentInfo &Actual) {
|
||||
CheckCommentInfo(Expected.Children, Actual.Children);
|
||||
}
|
||||
|
||||
void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
|
||||
ArrayRef<CommentInfo> Actual) {
|
||||
auto ItE = Expected.begin();
|
||||
auto ItA = Actual.begin();
|
||||
while (ItE != Expected.end() && ItA != Actual.end()) {
|
||||
CheckCommentInfo(*ItE, *ItA);
|
||||
++ItE;
|
||||
++ItA;
|
||||
}
|
||||
EXPECT_TRUE(ItE == Expected.end() && ItA == Actual.end());
|
||||
void CheckCommentInfo(const std::vector<CommentInfo> &Expected,
|
||||
const std::vector<CommentInfo> &Actual) {
|
||||
ASSERT_EQ(Expected.size(), Actual.size());
|
||||
for (size_t Idx = 0; Idx < Actual.size(); ++Idx)
|
||||
CheckCommentInfo(Expected[Idx], Actual[Idx]);
|
||||
}
|
||||
|
||||
void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
|
||||
const OwningVec<CommentInfo> &Actual) {
|
||||
auto ItE = Expected.begin();
|
||||
auto ItA = Actual.begin();
|
||||
while (ItE != Expected.end() && ItA != Actual.end()) {
|
||||
CheckCommentInfo(*ItE, *ItA);
|
||||
++ItE;
|
||||
++ItA;
|
||||
}
|
||||
EXPECT_TRUE(ItE == Expected.end() && ItA == Actual.end());
|
||||
void CheckCommentInfo(const std::vector<OwnedPtr<CommentInfo>> &Expected,
|
||||
const std::vector<OwnedPtr<CommentInfo>> &Actual) {
|
||||
ASSERT_EQ(Expected.size(), Actual.size());
|
||||
for (size_t Idx = 0; Idx < Actual.size(); ++Idx)
|
||||
CheckCommentInfo(*Expected[Idx], *Actual[Idx]);
|
||||
}
|
||||
|
||||
void CheckReference(const Reference &Expected, const Reference &Actual) {
|
||||
void CheckReference(Reference &Expected, Reference &Actual) {
|
||||
EXPECT_EQ(Expected.Name, Actual.Name);
|
||||
EXPECT_EQ(Expected.RefType, Actual.RefType);
|
||||
EXPECT_EQ(Expected.Path, Actual.Path);
|
||||
}
|
||||
|
||||
void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual) {
|
||||
void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) {
|
||||
CheckReference(Expected->Type, Actual->Type);
|
||||
}
|
||||
|
||||
void CheckFieldTypeInfo(const FieldTypeInfo *Expected,
|
||||
const FieldTypeInfo *Actual) {
|
||||
void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) {
|
||||
CheckTypeInfo(Expected, Actual);
|
||||
EXPECT_EQ(Expected->Name, Actual->Name);
|
||||
}
|
||||
|
||||
void CheckMemberTypeInfo(const MemberTypeInfo *Expected,
|
||||
const MemberTypeInfo *Actual) {
|
||||
void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
|
||||
CheckFieldTypeInfo(Expected, Actual);
|
||||
EXPECT_EQ(Expected->Access, Actual->Access);
|
||||
CheckCommentInfo(Expected->Description, Actual->Description);
|
||||
}
|
||||
|
||||
void CheckBaseInfo(const Info *Expected, const Info *Actual) {
|
||||
void CheckBaseInfo(Info *Expected, Info *Actual) {
|
||||
EXPECT_EQ(size_t(20), Actual->USR.size());
|
||||
EXPECT_EQ(Expected->Name, Actual->Name);
|
||||
EXPECT_EQ(Expected->Path, Actual->Path);
|
||||
auto ItN_E = Expected->Namespace.begin();
|
||||
auto ItN_A = Actual->Namespace.begin();
|
||||
while (ItN_E != Expected->Namespace.end() &&
|
||||
ItN_A != Actual->Namespace.end()) {
|
||||
CheckReference(*ItN_E, *ItN_A);
|
||||
++ItN_E;
|
||||
++ItN_A;
|
||||
}
|
||||
EXPECT_TRUE(ItN_E == Expected->Namespace.end() &&
|
||||
ItN_A == Actual->Namespace.end());
|
||||
ASSERT_EQ(Expected->Namespace.size(), Actual->Namespace.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Namespace.size(); ++Idx)
|
||||
CheckReference(Expected->Namespace[Idx], Actual->Namespace[Idx]);
|
||||
CheckCommentInfo(Expected->Description, Actual->Description);
|
||||
}
|
||||
|
||||
void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) {
|
||||
void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
|
||||
CheckBaseInfo(Expected, Actual);
|
||||
EXPECT_EQ(Expected->DefLoc.has_value(), Actual->DefLoc.has_value());
|
||||
if (Expected->DefLoc && Actual->DefLoc.has_value()) {
|
||||
@@ -157,186 +138,109 @@ void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual) {
|
||||
EXPECT_EQ(Expected->DefLoc->EndLineNumber, Actual->DefLoc->EndLineNumber);
|
||||
EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename);
|
||||
}
|
||||
auto ItE = Expected->Loc.begin();
|
||||
auto ItA = Actual->Loc.begin();
|
||||
while (ItE != Expected->Loc.end() && ItA != Actual->Loc.end()) {
|
||||
EXPECT_EQ(*ItE, *ItA);
|
||||
++ItE;
|
||||
++ItA;
|
||||
}
|
||||
EXPECT_TRUE(ItE == Expected->Loc.end() && ItA == Actual->Loc.end());
|
||||
ASSERT_EQ(Expected->Loc.size(), Actual->Loc.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Loc.size(); ++Idx)
|
||||
EXPECT_EQ(Expected->Loc[Idx], Actual->Loc[Idx]);
|
||||
}
|
||||
|
||||
void CheckFunctionInfo(const FunctionInfo *Expected,
|
||||
const FunctionInfo *Actual) {
|
||||
void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual) {
|
||||
CheckSymbolInfo(Expected, Actual);
|
||||
|
||||
EXPECT_EQ(Expected->IsMethod, Actual->IsMethod);
|
||||
CheckReference(Expected->Parent, Actual->Parent);
|
||||
CheckTypeInfo(&Expected->ReturnType, &Actual->ReturnType);
|
||||
|
||||
for (size_t Idx = 0; Idx < Expected->Params.size(); ++Idx) {
|
||||
ASSERT_EQ(Expected->Params.size(), Actual->Params.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Params.size(); ++Idx)
|
||||
EXPECT_EQ(Expected->Params[Idx], Actual->Params[Idx]);
|
||||
}
|
||||
|
||||
EXPECT_EQ(Expected->Access, Actual->Access);
|
||||
}
|
||||
|
||||
void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual) {
|
||||
void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual) {
|
||||
CheckSymbolInfo(Expected, Actual);
|
||||
|
||||
EXPECT_EQ(Expected->Scoped, Actual->Scoped);
|
||||
auto ItM_E = Expected->Members.begin();
|
||||
auto ItM_A = Actual->Members.begin();
|
||||
while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) {
|
||||
EXPECT_EQ(*ItM_E, *ItM_A);
|
||||
++ItM_E;
|
||||
++ItM_A;
|
||||
}
|
||||
EXPECT_TRUE(ItM_E == Expected->Members.end() &&
|
||||
ItM_A == Actual->Members.end());
|
||||
ASSERT_EQ(Expected->Members.size(), Actual->Members.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx)
|
||||
EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]);
|
||||
}
|
||||
|
||||
void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual) {
|
||||
void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual) {
|
||||
CheckSymbolInfo(Expected, Actual);
|
||||
EXPECT_EQ(Expected->IsUsing, Actual->IsUsing);
|
||||
CheckTypeInfo(&Expected->Underlying, &Actual->Underlying);
|
||||
}
|
||||
|
||||
void CheckNamespaceInfo(const NamespaceInfo *Expected,
|
||||
const NamespaceInfo *Actual) {
|
||||
void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual) {
|
||||
CheckBaseInfo(Expected, Actual);
|
||||
|
||||
ASSERT_EQ(Expected->Children.Namespaces.size(),
|
||||
Actual->Children.Namespaces.size());
|
||||
auto ItN_E = Expected->Children.Namespaces.begin();
|
||||
auto ItN_A = Actual->Children.Namespaces.begin();
|
||||
while (ItN_E != Expected->Children.Namespaces.end() &&
|
||||
ItN_A != Actual->Children.Namespaces.end()) {
|
||||
CheckReference(*ItN_E, *ItN_A);
|
||||
++ItN_E;
|
||||
++ItN_A;
|
||||
auto ItExpected = Expected->Children.Namespaces.begin();
|
||||
auto ItActual = Actual->Children.Namespaces.begin();
|
||||
while (ItExpected != Expected->Children.Namespaces.end()) {
|
||||
CheckReference(*ItExpected, *ItActual);
|
||||
++ItExpected;
|
||||
++ItActual;
|
||||
}
|
||||
EXPECT_TRUE(ItN_E == Expected->Children.Namespaces.end() &&
|
||||
ItN_A == Actual->Children.Namespaces.end());
|
||||
|
||||
auto ItR_E = Expected->Children.Records.begin();
|
||||
auto ItR_A = Actual->Children.Records.begin();
|
||||
while (ItR_E != Expected->Children.Records.end() &&
|
||||
ItR_A != Actual->Children.Records.end()) {
|
||||
CheckReference(*ItR_E, *ItR_A);
|
||||
++ItR_E;
|
||||
++ItR_A;
|
||||
}
|
||||
EXPECT_TRUE(ItR_E == Expected->Children.Records.end() &&
|
||||
ItR_A == Actual->Children.Records.end());
|
||||
ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx)
|
||||
CheckReference(Expected->Children.Records[Idx],
|
||||
Actual->Children.Records[Idx]);
|
||||
|
||||
auto ItF_E = Expected->Children.Functions.begin();
|
||||
auto ItF_A = Actual->Children.Functions.begin();
|
||||
while (ItF_E != Expected->Children.Functions.end() &&
|
||||
ItF_A != Actual->Children.Functions.end()) {
|
||||
CheckFunctionInfo(&(*ItF_E), &(*ItF_A));
|
||||
++ItF_E;
|
||||
++ItF_A;
|
||||
}
|
||||
EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() &&
|
||||
ItF_A == Actual->Children.Functions.end());
|
||||
ASSERT_EQ(Expected->Children.Functions.size(),
|
||||
Actual->Children.Functions.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx)
|
||||
CheckFunctionInfo(&Expected->Children.Functions[Idx],
|
||||
&Actual->Children.Functions[Idx]);
|
||||
|
||||
auto ItEnum_E = Expected->Children.Enums.begin();
|
||||
auto ItEnum_A = Actual->Children.Enums.begin();
|
||||
while (ItEnum_E != Expected->Children.Enums.end() &&
|
||||
ItEnum_A != Actual->Children.Enums.end()) {
|
||||
CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A));
|
||||
++ItEnum_E;
|
||||
++ItEnum_A;
|
||||
}
|
||||
EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() &&
|
||||
ItEnum_A == Actual->Children.Enums.end());
|
||||
ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx)
|
||||
CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]);
|
||||
}
|
||||
|
||||
void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual) {
|
||||
void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual) {
|
||||
CheckSymbolInfo(Expected, Actual);
|
||||
|
||||
EXPECT_EQ(Expected->TagType, Actual->TagType);
|
||||
|
||||
EXPECT_EQ(Expected->IsTypeDef, Actual->IsTypeDef);
|
||||
|
||||
auto ItM_E = Expected->Members.begin();
|
||||
auto ItM_A = Actual->Members.begin();
|
||||
while (ItM_E != Expected->Members.end() && ItM_A != Actual->Members.end()) {
|
||||
EXPECT_EQ(*ItM_E, *ItM_A);
|
||||
++ItM_E;
|
||||
++ItM_A;
|
||||
}
|
||||
EXPECT_TRUE(ItM_E == Expected->Members.end() &&
|
||||
ItM_A == Actual->Members.end());
|
||||
ASSERT_EQ(Expected->Members.size(), Actual->Members.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Members.size(); ++Idx)
|
||||
EXPECT_EQ(Expected->Members[Idx], Actual->Members[Idx]);
|
||||
|
||||
auto ItP_E = Expected->Parents.begin();
|
||||
auto ItP_A = Actual->Parents.begin();
|
||||
while (ItP_E != Expected->Parents.end() && ItP_A != Actual->Parents.end()) {
|
||||
CheckReference(*ItP_E, *ItP_A);
|
||||
++ItP_E;
|
||||
++ItP_A;
|
||||
}
|
||||
EXPECT_TRUE(ItP_E == Expected->Parents.end() &&
|
||||
ItP_A == Actual->Parents.end());
|
||||
ASSERT_EQ(Expected->Parents.size(), Actual->Parents.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Parents.size(); ++Idx)
|
||||
CheckReference(Expected->Parents[Idx], Actual->Parents[Idx]);
|
||||
|
||||
auto ItVP_E = Expected->VirtualParents.begin();
|
||||
auto ItVP_A = Actual->VirtualParents.begin();
|
||||
while (ItVP_E != Expected->VirtualParents.end() &&
|
||||
ItVP_A != Actual->VirtualParents.end()) {
|
||||
CheckReference(*ItVP_E, *ItVP_A);
|
||||
++ItVP_E;
|
||||
++ItVP_A;
|
||||
}
|
||||
EXPECT_TRUE(ItVP_E == Expected->VirtualParents.end() &&
|
||||
ItVP_A == Actual->VirtualParents.end());
|
||||
ASSERT_EQ(Expected->VirtualParents.size(), Actual->VirtualParents.size());
|
||||
for (size_t Idx = 0; Idx < Actual->VirtualParents.size(); ++Idx)
|
||||
CheckReference(Expected->VirtualParents[Idx], Actual->VirtualParents[Idx]);
|
||||
|
||||
auto ItB_E = Expected->Bases.begin();
|
||||
auto ItB_A = Actual->Bases.begin();
|
||||
while (ItB_E != Expected->Bases.end() && ItB_A != Actual->Bases.end()) {
|
||||
CheckBaseRecordInfo(&(*ItB_E), &(*ItB_A));
|
||||
++ItB_E;
|
||||
++ItB_A;
|
||||
}
|
||||
EXPECT_TRUE(ItB_E == Expected->Bases.end() && ItB_A == Actual->Bases.end());
|
||||
ASSERT_EQ(Expected->Bases.size(), Actual->Bases.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Bases.size(); ++Idx)
|
||||
CheckBaseRecordInfo(&Expected->Bases[Idx], &Actual->Bases[Idx]);
|
||||
|
||||
auto ItR_E = Expected->Children.Records.begin();
|
||||
auto ItR_A = Actual->Children.Records.begin();
|
||||
while (ItR_E != Expected->Children.Records.end() &&
|
||||
ItR_A != Actual->Children.Records.end()) {
|
||||
CheckReference(*ItR_E, *ItR_A);
|
||||
++ItR_E;
|
||||
++ItR_A;
|
||||
}
|
||||
EXPECT_TRUE(ItR_E == Expected->Children.Records.end() &&
|
||||
ItR_A == Actual->Children.Records.end());
|
||||
ASSERT_EQ(Expected->Children.Records.size(), Actual->Children.Records.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Records.size(); ++Idx)
|
||||
CheckReference(Expected->Children.Records[Idx],
|
||||
Actual->Children.Records[Idx]);
|
||||
|
||||
auto ItF_E = Expected->Children.Functions.begin();
|
||||
auto ItF_A = Actual->Children.Functions.begin();
|
||||
while (ItF_E != Expected->Children.Functions.end() &&
|
||||
ItF_A != Actual->Children.Functions.end()) {
|
||||
CheckFunctionInfo(&(*ItF_E), &(*ItF_A));
|
||||
++ItF_E;
|
||||
++ItF_A;
|
||||
}
|
||||
EXPECT_TRUE(ItF_E == Expected->Children.Functions.end() &&
|
||||
ItF_A == Actual->Children.Functions.end());
|
||||
ASSERT_EQ(Expected->Children.Functions.size(),
|
||||
Actual->Children.Functions.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Functions.size(); ++Idx)
|
||||
CheckFunctionInfo(&Expected->Children.Functions[Idx],
|
||||
&Actual->Children.Functions[Idx]);
|
||||
|
||||
auto ItEnum_E = Expected->Children.Enums.begin();
|
||||
auto ItEnum_A = Actual->Children.Enums.begin();
|
||||
while (ItEnum_E != Expected->Children.Enums.end() &&
|
||||
ItEnum_A != Actual->Children.Enums.end()) {
|
||||
CheckEnumInfo(&(*ItEnum_E), &(*ItEnum_A));
|
||||
++ItEnum_E;
|
||||
++ItEnum_A;
|
||||
}
|
||||
EXPECT_TRUE(ItEnum_E == Expected->Children.Enums.end() &&
|
||||
ItEnum_A == Actual->Children.Enums.end());
|
||||
ASSERT_EQ(Expected->Children.Enums.size(), Actual->Children.Enums.size());
|
||||
for (size_t Idx = 0; Idx < Actual->Children.Enums.size(); ++Idx)
|
||||
CheckEnumInfo(&Expected->Children.Enums[Idx], &Actual->Children.Enums[Idx]);
|
||||
}
|
||||
|
||||
void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
|
||||
const BaseRecordInfo *Actual) {
|
||||
void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual) {
|
||||
CheckRecordInfo(Expected, Actual);
|
||||
|
||||
EXPECT_EQ(Expected->IsVirtual, Actual->IsVirtual);
|
||||
@@ -344,7 +248,7 @@ void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
|
||||
EXPECT_EQ(Expected->IsParent, Actual->IsParent);
|
||||
}
|
||||
|
||||
void CheckIndex(const Index &Expected, const Index &Actual) {
|
||||
void CheckIndex(Index &Expected, Index &Actual) {
|
||||
CheckReference(Expected, Actual);
|
||||
ASSERT_EQ(Expected.Children.size(), Actual.Children.size());
|
||||
for (auto &[_, C] : Expected.Children)
|
||||
|
||||
@@ -31,32 +31,25 @@ FunctionInfo *InfoAsFunction(Info *I);
|
||||
EnumInfo *InfoAsEnum(Info *I);
|
||||
TypedefInfo *InfoAsTypedef(Info *I);
|
||||
|
||||
void CheckCommentInfo(ArrayRef<CommentInfo> Expected,
|
||||
ArrayRef<CommentInfo> Actual);
|
||||
void CheckCommentInfo(const OwningVec<CommentInfo> &Expected,
|
||||
const OwningVec<CommentInfo> &Actual);
|
||||
void CheckReference(const Reference &Expected, const Reference &Actual);
|
||||
void CheckTypeInfo(const TypeInfo *Expected, const TypeInfo *Actual);
|
||||
void CheckFieldTypeInfo(const FieldTypeInfo *Expected,
|
||||
const FieldTypeInfo *Actual);
|
||||
void CheckMemberTypeInfo(const MemberTypeInfo *Expected,
|
||||
const MemberTypeInfo *Actual);
|
||||
// Unlike the operator==, these functions explicitly does not check USRs, as
|
||||
// that may change and it would be better to not rely on its implementation.
|
||||
void CheckReference(Reference &Expected, Reference &Actual);
|
||||
void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual);
|
||||
void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual);
|
||||
void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual);
|
||||
|
||||
// This function explicitly does not check USRs, as that may change and it would
|
||||
// be better to not rely on its implementation.
|
||||
void CheckBaseInfo(const Info *Expected, const Info *Actual);
|
||||
void CheckSymbolInfo(const SymbolInfo *Expected, const SymbolInfo *Actual);
|
||||
void CheckFunctionInfo(const FunctionInfo *Expected,
|
||||
const FunctionInfo *Actual);
|
||||
void CheckEnumInfo(const EnumInfo *Expected, const EnumInfo *Actual);
|
||||
void CheckTypedefInfo(const TypedefInfo *Expected, const TypedefInfo *Actual);
|
||||
void CheckNamespaceInfo(const NamespaceInfo *Expected,
|
||||
const NamespaceInfo *Actual);
|
||||
void CheckRecordInfo(const RecordInfo *Expected, const RecordInfo *Actual);
|
||||
void CheckBaseRecordInfo(const BaseRecordInfo *Expected,
|
||||
const BaseRecordInfo *Actual);
|
||||
void CheckBaseInfo(Info *Expected, Info *Actual);
|
||||
void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual);
|
||||
void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual);
|
||||
void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual);
|
||||
void CheckTypedefInfo(TypedefInfo *Expected, TypedefInfo *Actual);
|
||||
void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual);
|
||||
void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual);
|
||||
void CheckBaseRecordInfo(BaseRecordInfo *Expected, BaseRecordInfo *Actual);
|
||||
|
||||
void CheckIndex(const Index &Expected, const Index &Actual);
|
||||
void CheckIndex(Index &Expected, Index &Actual);
|
||||
|
||||
class ClangDocContextTest : public ::testing::Test {
|
||||
protected:
|
||||
|
||||
@@ -28,8 +28,7 @@ TEST_F(GeneratorTest, emitIndex) {
|
||||
InfoC->USR = serialize::hashUSR("3");
|
||||
Reference RefB = Reference(SymbolID(), "B");
|
||||
RefB.USR = serialize::hashUSR("2");
|
||||
Reference NsC[] = {std::move(RefB)};
|
||||
InfoC->Namespace = llvm::ArrayRef(NsC);
|
||||
InfoC->Namespace = {std::move(RefB)};
|
||||
Generator::addInfoToIndex(Idx, InfoC.get());
|
||||
auto InfoD = std::make_unique<Info>();
|
||||
InfoD->Name = "D";
|
||||
@@ -41,8 +40,7 @@ TEST_F(GeneratorTest, emitIndex) {
|
||||
RefD.USR = serialize::hashUSR("4");
|
||||
Reference RefE = Reference(SymbolID(), "E");
|
||||
RefE.USR = serialize::hashUSR("5");
|
||||
Reference NsF[] = {std::move(RefE), std::move(RefD)};
|
||||
InfoF->Namespace = llvm::ArrayRef(NsF);
|
||||
InfoF->Namespace = {std::move(RefE), std::move(RefD)};
|
||||
Generator::addInfoToIndex(Idx, InfoF.get());
|
||||
auto InfoG = std::make_unique<Info>(InfoType::IT_namespace);
|
||||
Generator::addInfoToIndex(Idx, InfoG.get());
|
||||
|
||||
@@ -19,54 +19,39 @@ TEST_F(JSONGeneratorTest, emitRecordJSON) {
|
||||
RecordInfo I;
|
||||
I.Name = "Foo";
|
||||
I.IsTypeDef = false;
|
||||
Reference Ns[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "GlobalNamespace", InfoType::IT_namespace);
|
||||
I.Path = "GlobalNamespace";
|
||||
I.DefLoc = Location(1, 1, "main.cpp");
|
||||
I.TagType = TagTypeKind::Class;
|
||||
|
||||
I.Template = TemplateInfo();
|
||||
TemplateParamInfo TParams[] = {TemplateParamInfo("class T")};
|
||||
I.Template->Params = llvm::ArrayRef(TParams);
|
||||
I.Template->Params.emplace_back("class T");
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "Color";
|
||||
E.Scoped = false;
|
||||
EnumValueInfo EV[] = {EnumValueInfo("RED", "0")};
|
||||
E.Members = llvm::ArrayRef(EV);
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "Color";
|
||||
I.Children.Enums.back().Scoped = false;
|
||||
I.Children.Enums.back().Members.emplace_back();
|
||||
I.Children.Enums.back().Members.back().Name = "RED";
|
||||
I.Children.Enums.back().Members.back().Value = "0";
|
||||
|
||||
MemberTypeInfo M[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_protected)};
|
||||
I.Members = llvm::ArrayRef(M);
|
||||
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_protected);
|
||||
|
||||
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
|
||||
true);
|
||||
FunctionInfo F;
|
||||
F.Name = "InheritedFunctionOne";
|
||||
B.Children.Functions.push_back(F);
|
||||
MemberTypeInfo BM[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_public)};
|
||||
B.Members = llvm::ArrayRef(BM);
|
||||
|
||||
BaseRecordInfo Bases[] = {std::move(B)};
|
||||
I.Bases = llvm::ArrayRef(Bases);
|
||||
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
|
||||
AccessSpecifier::AS_public, true);
|
||||
I.Bases.back().Children.Functions.emplace_back();
|
||||
I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";
|
||||
I.Bases.back().Members.emplace_back(TypeInfo("int"), "N",
|
||||
AccessSpecifier::AS_public);
|
||||
|
||||
// F is in the global namespace
|
||||
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")};
|
||||
I.Parents = llvm::ArrayRef(Parents);
|
||||
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record,
|
||||
"path::to::G::G", "path/to/G")};
|
||||
I.VirtualParents = llvm::ArrayRef(VParents);
|
||||
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
|
||||
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
|
||||
"path::to::G::G", "path/to/G");
|
||||
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::r::ChildStruct", "path/to/A/r");
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
|
||||
FunctionInfo F2;
|
||||
F2.Name = "OneFunction";
|
||||
I.Children.Functions.push_back(F2);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::r::ChildStruct", "path/to/A/r");
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
|
||||
auto G = getJSONGenerator();
|
||||
assert(G);
|
||||
@@ -212,26 +197,20 @@ TEST_F(JSONGeneratorTest, emitNamespaceJSON) {
|
||||
NamespaceInfo I;
|
||||
I.Name = "Namespace";
|
||||
I.Path = "path/to/A";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
|
||||
"path::to::A::Namespace::ChildNamespace",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Namespaces.push_back(NewNamespace);
|
||||
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::Namespace::ChildStruct",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo F;
|
||||
F.Name = "OneFunction";
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
I.Children.Functions.push_back(F);
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "OneEnum";
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::Namespace::ChildStruct",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getJSONGenerator();
|
||||
assert(G);
|
||||
|
||||
@@ -26,22 +26,16 @@ class MDGeneratorTest : public ClangDocContextTest {};
|
||||
TEST_F(MDGeneratorTest, emitNamespaceMD) {
|
||||
NamespaceInfo I;
|
||||
I.Name = "Namespace";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace);
|
||||
I.Children.Namespaces.push_back(NewNamespace);
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
|
||||
FunctionInfo F;
|
||||
F.Name = "OneFunction";
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
I.Children.Functions.push_back(F);
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "OneEnum";
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getMDGenerator();
|
||||
assert(G);
|
||||
@@ -85,31 +79,21 @@ TEST_F(MDGeneratorTest, emitNamespaceMD) {
|
||||
TEST_F(MDGeneratorTest, emitRecordMD) {
|
||||
RecordInfo I;
|
||||
I.Name = "r";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
MemberTypeInfo M[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
|
||||
I.Members = llvm::ArrayRef(M);
|
||||
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
I.TagType = TagTypeKind::Class;
|
||||
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record)};
|
||||
I.Parents = llvm::ArrayRef(Parents);
|
||||
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record)};
|
||||
I.VirtualParents = llvm::ArrayRef(VParents);
|
||||
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
|
||||
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
|
||||
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo F;
|
||||
F.Name = "OneFunction";
|
||||
I.Children.Functions.push_back(F);
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "OneEnum";
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record);
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getMDGenerator();
|
||||
assert(G);
|
||||
@@ -159,18 +143,15 @@ ChildStruct
|
||||
TEST_F(MDGeneratorTest, emitFunctionMD) {
|
||||
FunctionInfo I;
|
||||
I.Name = "f";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
I.Access = AccessSpecifier::AS_none;
|
||||
|
||||
I.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo P[] = {FieldTypeInfo(TypeInfo("int"), "P")};
|
||||
I.Params = llvm::ArrayRef(P);
|
||||
I.Params.emplace_back(TypeInfo("int"), "P");
|
||||
I.IsMethod = true;
|
||||
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
|
||||
|
||||
@@ -194,15 +175,12 @@ TEST_F(MDGeneratorTest, emitFunctionMD) {
|
||||
TEST_F(MDGeneratorTest, emitEnumMD) {
|
||||
EnumInfo I;
|
||||
I.Name = "e";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
EnumValueInfo EV[] = {EnumValueInfo("X")};
|
||||
I.Members = llvm::ArrayRef(EV);
|
||||
I.Members.emplace_back("X");
|
||||
I.Scoped = true;
|
||||
|
||||
auto G = getMDGenerator();
|
||||
@@ -230,9 +208,8 @@ TEST_F(MDGeneratorTest, emitCommentMD) {
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
I.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo PI[] = {FieldTypeInfo(TypeInfo("int"), "I"),
|
||||
FieldTypeInfo(TypeInfo("int"), "J")};
|
||||
I.Params = llvm::ArrayRef(PI);
|
||||
I.Params.emplace_back(TypeInfo("int"), "I");
|
||||
I.Params.emplace_back(TypeInfo("int"), "J");
|
||||
I.Access = AccessSpecifier::AS_none;
|
||||
|
||||
CommentInfo Top;
|
||||
|
||||
@@ -18,200 +18,150 @@ class MergeTest : public ClangDocContextTest {};
|
||||
TEST_F(MergeTest, mergeNamespaceInfos) {
|
||||
NamespaceInfo One;
|
||||
One.Name = "Namespace";
|
||||
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
One.Namespace = llvm::ArrayRef(Ns1);
|
||||
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference RA(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
|
||||
One.Children.Namespaces.push_back(RA);
|
||||
Reference RC1(NonEmptySID, "ChildStruct", InfoType::IT_record);
|
||||
One.Children.Records.push_back(RC1);
|
||||
|
||||
FunctionInfo F1;
|
||||
F1.Name = "OneFunction";
|
||||
F1.USR = NonEmptySID;
|
||||
One.Children.Functions.push_back(F1);
|
||||
|
||||
EnumInfo E1;
|
||||
E1.Name = "OneEnum";
|
||||
E1.USR = NonEmptySID;
|
||||
One.Children.Enums.push_back(E1);
|
||||
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";
|
||||
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Two.Namespace = llvm::ArrayRef(Ns2);
|
||||
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference RB(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
|
||||
Two.Children.Namespaces.push_back(RB);
|
||||
Reference RC2(EmptySID, "OtherChildStruct", InfoType::IT_record);
|
||||
Two.Children.Records.push_back(RC2);
|
||||
|
||||
FunctionInfo F2;
|
||||
F2.Name = "TwoFunction";
|
||||
Two.Children.Functions.push_back(F2);
|
||||
|
||||
EnumInfo E2;
|
||||
E2.Name = "TwoEnum";
|
||||
Two.Children.Enums.push_back(E2);
|
||||
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";
|
||||
|
||||
OwningPtrVec<Info> Infos;
|
||||
Infos.push_back(&One);
|
||||
Infos.push_back(&Two);
|
||||
Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(One)));
|
||||
Infos.emplace_back(allocatePtr<NamespaceInfo>(std::move(Two)));
|
||||
|
||||
NamespaceInfo Expected;
|
||||
Expected.Name = "Namespace";
|
||||
Reference NsExpected[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Expected.Namespace = llvm::ArrayRef(NsExpected);
|
||||
auto Expected = allocatePtr<NamespaceInfo>();
|
||||
Expected->Name = "Namespace";
|
||||
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference RC(NonEmptySID, "ChildNamespace", InfoType::IT_namespace);
|
||||
Expected.Children.Namespaces.push_back(RC);
|
||||
Reference RCE1(NonEmptySID, "ChildStruct", InfoType::IT_record);
|
||||
Expected.Children.Records.push_back(RCE1);
|
||||
Expected->Children.Namespaces.push_back(RC);
|
||||
Expected->Children.Records.emplace_back(NonEmptySID, "ChildStruct",
|
||||
InfoType::IT_record);
|
||||
Reference RD(EmptySID, "OtherChildNamespace", InfoType::IT_namespace);
|
||||
Expected.Children.Namespaces.push_back(RD);
|
||||
Reference RCE2(EmptySID, "OtherChildStruct", InfoType::IT_record);
|
||||
Expected.Children.Records.push_back(RCE2);
|
||||
|
||||
FunctionInfo FE1;
|
||||
FE1.Name = "OneFunction";
|
||||
FE1.USR = NonEmptySID;
|
||||
Expected.Children.Functions.push_back(FE1);
|
||||
|
||||
FunctionInfo FE2;
|
||||
FE2.Name = "TwoFunction";
|
||||
Expected.Children.Functions.push_back(FE2);
|
||||
|
||||
EnumInfo EE1;
|
||||
EE1.Name = "OneEnum";
|
||||
EE1.USR = NonEmptySID;
|
||||
Expected.Children.Enums.push_back(EE1);
|
||||
|
||||
EnumInfo EE2;
|
||||
EE2.Name = "TwoEnum";
|
||||
Expected.Children.Enums.push_back(EE2);
|
||||
Expected->Children.Namespaces.push_back(RD);
|
||||
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), InfoAsNamespace(Actual.get()));
|
||||
CheckNamespaceInfo(InfoAsNamespace(Expected.get()),
|
||||
InfoAsNamespace(Actual.get().get()));
|
||||
}
|
||||
|
||||
TEST_F(MergeTest, mergeRecordInfos) {
|
||||
RecordInfo One;
|
||||
One.Name = "r";
|
||||
One.IsTypeDef = true;
|
||||
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
One.Namespace = llvm::ArrayRef(Ns1);
|
||||
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
One.DefLoc = Location(10, 10, "test.cpp");
|
||||
|
||||
MemberTypeInfo M1[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
|
||||
One.Members = llvm::ArrayRef(M1);
|
||||
One.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
One.TagType = TagTypeKind::Class;
|
||||
Reference P1[] = {Reference(EmptySID, "F", InfoType::IT_record)};
|
||||
One.Parents = llvm::ArrayRef(P1);
|
||||
Reference VP1[] = {Reference(EmptySID, "G", InfoType::IT_record)};
|
||||
One.VirtualParents = llvm::ArrayRef(VP1);
|
||||
One.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
|
||||
One.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
|
||||
|
||||
BaseRecordInfo B1[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true,
|
||||
AccessSpecifier::AS_protected, true)};
|
||||
One.Bases = llvm::ArrayRef(B1);
|
||||
Reference RCShared1(NonEmptySID, "SharedChildStruct", InfoType::IT_record);
|
||||
One.Children.Records.push_back(RCShared1);
|
||||
|
||||
FunctionInfo F1;
|
||||
F1.Name = "OneFunction";
|
||||
F1.USR = NonEmptySID;
|
||||
One.Children.Functions.push_back(F1);
|
||||
|
||||
EnumInfo E1;
|
||||
E1.Name = "OneEnum";
|
||||
E1.USR = NonEmptySID;
|
||||
One.Children.Enums.push_back(E1);
|
||||
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";
|
||||
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Two.Namespace = llvm::ArrayRef(Ns2);
|
||||
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Location Loc2(12, 12, "test.cpp");
|
||||
Two.Loc.push_back(Loc2);
|
||||
Two.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
Two.TagType = TagTypeKind::Class;
|
||||
|
||||
Reference RCShared2(NonEmptySID, "SharedChildStruct", InfoType::IT_record,
|
||||
"path");
|
||||
Two.Children.Records.push_back(RCShared2);
|
||||
|
||||
FunctionInfo F2;
|
||||
F2.Name = "TwoFunction";
|
||||
Two.Children.Functions.push_back(F2);
|
||||
|
||||
EnumInfo E2;
|
||||
E2.Name = "TwoEnum";
|
||||
Two.Children.Enums.push_back(E2);
|
||||
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";
|
||||
|
||||
OwningPtrVec<Info> Infos;
|
||||
Infos.push_back(&One);
|
||||
Infos.push_back(&Two);
|
||||
Infos.emplace_back(allocatePtr<RecordInfo>(std::move(One)));
|
||||
Infos.emplace_back(allocatePtr<RecordInfo>(std::move(Two)));
|
||||
|
||||
RecordInfo Expected;
|
||||
Expected.Name = "r";
|
||||
Expected.IsTypeDef = true;
|
||||
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Expected.Namespace = llvm::ArrayRef(NsE);
|
||||
auto Expected = allocatePtr<RecordInfo>();
|
||||
Expected->Name = "r";
|
||||
Expected->IsTypeDef = true;
|
||||
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Expected.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location LocE(12, 12, "test.cpp");
|
||||
Expected.Loc.push_back(LocE);
|
||||
Expected->DefLoc = Location(10, 10, "test.cpp");
|
||||
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
MemberTypeInfo ME[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "X", AccessSpecifier::AS_private)};
|
||||
Expected.Members = llvm::ArrayRef(ME);
|
||||
Expected.TagType = TagTypeKind::Class;
|
||||
Reference PE[] = {Reference(EmptySID, "F", InfoType::IT_record)};
|
||||
Expected.Parents = llvm::ArrayRef(PE);
|
||||
Reference VPE[] = {Reference(EmptySID, "G", InfoType::IT_record)};
|
||||
Expected.VirtualParents = llvm::ArrayRef(VPE);
|
||||
BaseRecordInfo BE[] = {BaseRecordInfo(EmptySID, "F", "path/to/F", true,
|
||||
AccessSpecifier::AS_protected, true)};
|
||||
Expected.Bases = llvm::ArrayRef(BE);
|
||||
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);
|
||||
|
||||
Reference RCSharedE(NonEmptySID, "SharedChildStruct", InfoType::IT_record,
|
||||
"path");
|
||||
Expected.Children.Records.push_back(RCSharedE);
|
||||
FunctionInfo FE1;
|
||||
FE1.Name = "OneFunction";
|
||||
FE1.USR = NonEmptySID;
|
||||
Expected.Children.Functions.push_back(FE1);
|
||||
|
||||
FunctionInfo FE2;
|
||||
FE2.Name = "TwoFunction";
|
||||
Expected.Children.Functions.push_back(FE2);
|
||||
|
||||
EnumInfo EE1;
|
||||
EE1.Name = "OneEnum";
|
||||
EE1.USR = NonEmptySID;
|
||||
Expected.Children.Enums.push_back(EE1);
|
||||
|
||||
EnumInfo EE2;
|
||||
EE2.Name = "TwoEnum";
|
||||
Expected.Children.Enums.push_back(EE2);
|
||||
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), InfoAsRecord(Actual.get()));
|
||||
CheckRecordInfo(InfoAsRecord(Expected.get()),
|
||||
InfoAsRecord(Actual.get().get()));
|
||||
}
|
||||
|
||||
TEST_F(MergeTest, mergeFunctionInfos) {
|
||||
FunctionInfo One;
|
||||
One.Name = "f";
|
||||
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
One.Namespace = llvm::ArrayRef(Ns1);
|
||||
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
One.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
One.Loc.push_back(Loc1);
|
||||
One.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
One.IsMethod = true;
|
||||
One.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
|
||||
@@ -220,106 +170,89 @@ TEST_F(MergeTest, mergeFunctionInfos) {
|
||||
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
|
||||
CommentInfo OnePara[] = {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, OneText)};
|
||||
CommentInfo TopOne(CommentKind::CK_FullComment, OnePara);
|
||||
One.Description.push_back(TopOne);
|
||||
One.Description.emplace_back(CommentKind::CK_FullComment, OnePara);
|
||||
|
||||
FunctionInfo Two;
|
||||
Two.Name = "f";
|
||||
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Two.Namespace = llvm::ArrayRef(Ns2);
|
||||
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Location Loc2(12, 12, "test.cpp");
|
||||
Two.Loc.push_back(Loc2);
|
||||
Two.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
Two.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo P2(TypeInfo("int"), "P");
|
||||
FieldTypeInfo Params2[] = {std::move(P2)};
|
||||
Two.Params = llvm::ArrayRef(Params2);
|
||||
Two.Params.emplace_back(TypeInfo("int"), "P");
|
||||
|
||||
CommentInfo TwoText[] = {
|
||||
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
|
||||
CommentInfo TwoPara[] = {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, TwoText)};
|
||||
CommentInfo TopTwo(CommentKind::CK_FullComment, TwoPara);
|
||||
Two.Description.push_back(TopTwo);
|
||||
Two.Description.emplace_back(CommentKind::CK_FullComment, TwoPara);
|
||||
|
||||
OwningPtrVec<Info> Infos;
|
||||
Infos.push_back(&One);
|
||||
Infos.push_back(&Two);
|
||||
Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(One)));
|
||||
Infos.emplace_back(allocatePtr<FunctionInfo>(std::move(Two)));
|
||||
|
||||
FunctionInfo Expected;
|
||||
Expected.Name = "f";
|
||||
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Expected.Namespace = llvm::ArrayRef(NsE);
|
||||
auto Expected = allocatePtr<FunctionInfo>();
|
||||
Expected->Name = "f";
|
||||
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Expected.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location LocE(12, 12, "test.cpp");
|
||||
Expected.Loc.push_back(LocE);
|
||||
Expected->DefLoc = Location(10, 10, "test.cpp");
|
||||
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
Expected.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo PE(TypeInfo("int"), "P");
|
||||
FieldTypeInfo ParamsE[] = {std::move(PE)};
|
||||
Expected.Params = llvm::ArrayRef(ParamsE);
|
||||
Expected.IsMethod = true;
|
||||
Expected.Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
|
||||
Expected->ReturnType = TypeInfo("void");
|
||||
Expected->Params.emplace_back(TypeInfo("int"), "P");
|
||||
Expected->IsMethod = true;
|
||||
Expected->Parent = Reference(EmptySID, "Parent", InfoType::IT_namespace);
|
||||
|
||||
CommentInfo ExpectedText[] = {
|
||||
CommentInfo(CommentKind::CK_TextComment, {}, "This is a text comment.")};
|
||||
CommentInfo ExpectedPara[] = {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, ExpectedText)};
|
||||
CommentInfo TopE(CommentKind::CK_FullComment, ExpectedPara);
|
||||
Expected.Description.push_back(TopE);
|
||||
Expected->Description.emplace_back(CommentKind::CK_FullComment, ExpectedPara);
|
||||
|
||||
auto Actual = mergeInfos(Infos);
|
||||
assert(Actual);
|
||||
CheckFunctionInfo(InfoAsFunction(&Expected), InfoAsFunction(Actual.get()));
|
||||
CheckFunctionInfo(InfoAsFunction(Expected.get()),
|
||||
InfoAsFunction(Actual.get().get()));
|
||||
}
|
||||
|
||||
TEST_F(MergeTest, mergeEnumInfos) {
|
||||
EnumInfo One;
|
||||
One.Name = "e";
|
||||
Reference Ns1[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
One.Namespace = llvm::ArrayRef(Ns1);
|
||||
One.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
One.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
One.Loc.push_back(Loc1);
|
||||
One.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
One.Scoped = true;
|
||||
|
||||
EnumInfo Two;
|
||||
Two.Name = "e";
|
||||
Reference Ns2[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Two.Namespace = llvm::ArrayRef(Ns2);
|
||||
Two.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Location Loc2(20, 20, "test.cpp");
|
||||
Two.Loc.push_back(Loc2);
|
||||
Two.Loc.emplace_back(20, 20, "test.cpp");
|
||||
|
||||
EnumValueInfo EV2[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
|
||||
Two.Members = llvm::ArrayRef(EV2);
|
||||
Two.Members.emplace_back("X");
|
||||
Two.Members.emplace_back("Y");
|
||||
|
||||
OwningPtrVec<Info> Infos;
|
||||
Infos.push_back(&One);
|
||||
Infos.push_back(&Two);
|
||||
Infos.emplace_back(allocatePtr<EnumInfo>(std::move(One)));
|
||||
Infos.emplace_back(allocatePtr<EnumInfo>(std::move(Two)));
|
||||
|
||||
EnumInfo Expected;
|
||||
Expected.Name = "e";
|
||||
Reference NsE[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
Expected.Namespace = llvm::ArrayRef(NsE);
|
||||
auto Expected = allocatePtr<EnumInfo>();
|
||||
Expected->Name = "e";
|
||||
Expected->Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Expected.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location LocE1(12, 12, "test.cpp");
|
||||
Expected.Loc.push_back(LocE1);
|
||||
Location LocE2(20, 20, "test.cpp");
|
||||
Expected.Loc.push_back(LocE2);
|
||||
Expected->DefLoc = Location(10, 10, "test.cpp");
|
||||
Expected->Loc.emplace_back(12, 12, "test.cpp");
|
||||
Expected->Loc.emplace_back(20, 20, "test.cpp");
|
||||
|
||||
EnumValueInfo EV_E[] = {EnumValueInfo("X"), EnumValueInfo("Y")};
|
||||
Expected.Members = llvm::ArrayRef(EV_E);
|
||||
Expected.Scoped = true;
|
||||
Expected->Members.emplace_back("X");
|
||||
Expected->Members.emplace_back("Y");
|
||||
Expected->Scoped = true;
|
||||
|
||||
auto Actual = mergeInfos(Infos);
|
||||
assert(Actual);
|
||||
CheckEnumInfo(InfoAsEnum(&Expected), InfoAsEnum(Actual.get()));
|
||||
CheckEnumInfo(InfoAsEnum(Expected.get()), InfoAsEnum(Actual.get().get()));
|
||||
}
|
||||
|
||||
} // namespace doc
|
||||
|
||||
@@ -117,27 +117,25 @@ TEST_F(SerializeTest, emitNamespaceInfo) {
|
||||
extractInfosFromCode("namespace A { namespace B { void f() {} } }", 5,
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
NamespaceInfo *A = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedA(EmptySID, "A");
|
||||
CheckNamespaceInfo(&ExpectedA, A);
|
||||
|
||||
NamespaceInfo *B = InfoAsNamespace(Infos[2]);
|
||||
NamespaceInfo *B = InfoAsNamespace(Infos[2].get());
|
||||
NamespaceInfo ExpectedB(EmptySID, /*Name=*/"B", /*Path=*/"A");
|
||||
Reference NsB[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
ExpectedB.Namespace = llvm::ArrayRef(NsB);
|
||||
ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
CheckNamespaceInfo(&ExpectedB, B);
|
||||
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4]);
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[4].get());
|
||||
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
||||
FunctionInfo F;
|
||||
F.Name = "f";
|
||||
F.ReturnType = TypeInfo("void");
|
||||
F.DefLoc = Location(0, 0, "test.cpp");
|
||||
Reference NsF[] = {Reference(EmptySID, "B", InfoType::IT_namespace),
|
||||
Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
F.Namespace = llvm::ArrayRef(NsF);
|
||||
F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
|
||||
F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
ExpectedBWithFunction.Children.Functions.push_back(F);
|
||||
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
|
||||
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
||||
}
|
||||
|
||||
@@ -146,7 +144,7 @@ TEST_F(SerializeTest, emitAnonymousNamespaceInfo) {
|
||||
extractInfosFromCode("namespace { }", 2, /*Public=*/false, Infos,
|
||||
this->Diags);
|
||||
|
||||
NamespaceInfo *A = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedA(EmptySID);
|
||||
ExpectedA.Name = "@nonymous_namespace";
|
||||
CheckNamespaceInfo(&ExpectedA, A);
|
||||
@@ -172,103 +170,95 @@ void F<int>::TemplateMethod();
|
||||
typedef struct {} G;)raw",
|
||||
10, /*Public=*/false, Infos, this->Diags);
|
||||
|
||||
RecordInfo *E = InfoAsRecord(Infos[0]);
|
||||
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
||||
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
||||
Reference NsE[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedE.Namespace = llvm::ArrayRef(NsE);
|
||||
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedE.TagType = TagTypeKind::Class;
|
||||
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
|
||||
MemberTypeInfo MemE[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "value", AccessSpecifier::AS_public)};
|
||||
ExpectedE.Members = llvm::ArrayRef(MemE);
|
||||
ExpectedE.Members.emplace_back(TypeInfo("int"), "value",
|
||||
AccessSpecifier::AS_public);
|
||||
// TODO the data member should have the docstring on it:
|
||||
//ExpectedE.Members.back().Description.push_back(MakeOneLineCommentInfo(" Some docs"));
|
||||
CheckRecordInfo(&ExpectedE, E);
|
||||
|
||||
RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[2]);
|
||||
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("void");
|
||||
EConstructor.DefLoc = Location(0, 0, "test.cpp");
|
||||
Reference NsEC[] = {
|
||||
Reference(EmptySID, "E", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
EConstructor.Namespace = llvm::ArrayRef(NsEC);
|
||||
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.Children.Functions.push_back(EConstructor);
|
||||
ExpectedRecordWithEConstructor.Children.Functions.emplace_back(
|
||||
std::move(EConstructor));
|
||||
CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
|
||||
|
||||
RecordInfo *RecordWithMethod = InfoAsRecord(Infos[3]);
|
||||
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("void");
|
||||
Location LMethod(0, 0, "test.cpp");
|
||||
Method.Loc.push_back(LMethod);
|
||||
Reference NsMethod[] = {
|
||||
Reference(EmptySID, "E", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
Method.Namespace = llvm::ArrayRef(NsMethod);
|
||||
Method.Loc.emplace_back(0, 0, "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.Children.Functions.push_back(Method);
|
||||
ExpectedRecordWithMethod.Children.Functions.emplace_back(std::move(Method));
|
||||
CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
|
||||
|
||||
RecordInfo *F = InfoAsRecord(Infos[4]);
|
||||
RecordInfo *F = InfoAsRecord(Infos[4].get());
|
||||
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
|
||||
Reference NsF3[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedF.Namespace = llvm::ArrayRef(NsF3);
|
||||
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedF.TagType = TagTypeKind::Struct;
|
||||
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
|
||||
CheckRecordInfo(&ExpectedF, F);
|
||||
|
||||
RecordInfo *RecordWithTemplateMethod = InfoAsRecord(Infos[6]);
|
||||
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("void");
|
||||
Location LTemp1(0, 0, "test.cpp");
|
||||
TemplateMethod.Loc.push_back(LTemp1);
|
||||
Reference NsT1[] = {
|
||||
Reference(EmptySID, "F", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
TemplateMethod.Namespace = llvm::ArrayRef(NsT1);
|
||||
TemplateMethod.Loc.emplace_back(0, 0, "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.Children.Functions.push_back(TemplateMethod);
|
||||
ExpectedRecordWithTemplateMethod.Children.Functions.emplace_back(
|
||||
std::move(TemplateMethod));
|
||||
CheckRecordInfo(&ExpectedRecordWithTemplateMethod, RecordWithTemplateMethod);
|
||||
|
||||
RecordInfo *TemplatedRecord = InfoAsRecord(Infos[7]);
|
||||
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("void");
|
||||
Location LTemp2(0, 0, "test.cpp");
|
||||
SpecializedTemplateMethod.Loc.push_back(LTemp2);
|
||||
Reference NsT2[] = {
|
||||
Reference(EmptySID, "F", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
SpecializedTemplateMethod.Namespace = llvm::ArrayRef(NsT2);
|
||||
SpecializedTemplateMethod.Loc.emplace_back(0, 0, "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.Children.Functions.push_back(
|
||||
SpecializedTemplateMethod);
|
||||
ExpectedTemplatedRecord.Children.Functions.emplace_back(
|
||||
std::move(SpecializedTemplateMethod));
|
||||
CheckRecordInfo(&ExpectedTemplatedRecord, TemplatedRecord);
|
||||
|
||||
RecordInfo *G = InfoAsRecord(Infos[8]);
|
||||
RecordInfo *G = InfoAsRecord(Infos[8].get());
|
||||
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
|
||||
Reference NsG[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedG.Namespace = llvm::ArrayRef(NsG);
|
||||
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedG.TagType = TagTypeKind::Struct;
|
||||
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
|
||||
ExpectedG.IsTypeDef = true;
|
||||
@@ -281,25 +271,25 @@ TEST_F(SerializeTest, emitEnumInfo) {
|
||||
extractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
|
||||
EnumInfo E;
|
||||
E.Name = "E";
|
||||
E.DefLoc = Location(0, 0, "test.cpp");
|
||||
EnumValueInfo EMem[] = {EnumValueInfo("X", "0"), EnumValueInfo("Y", "1")};
|
||||
E.Members = llvm::ArrayRef(EMem);
|
||||
ExpectedNamespaceWithEnum.Children.Enums.push_back(E);
|
||||
E.Members.emplace_back("X", "0");
|
||||
E.Members.emplace_back("Y", "1");
|
||||
ExpectedNamespaceWithEnum.Children.Enums.emplace_back(std::move(E));
|
||||
CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
|
||||
|
||||
NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
|
||||
NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
|
||||
EnumInfo G;
|
||||
G.Name = "G";
|
||||
G.Scoped = true;
|
||||
G.DefLoc = Location(0, 0, "test.cpp");
|
||||
EnumValueInfo GMem[] = {EnumValueInfo("A", "0"), EnumValueInfo("B", "1")};
|
||||
G.Members = llvm::ArrayRef(GMem);
|
||||
ExpectedNamespaceWithScopedEnum.Children.Enums.push_back(G);
|
||||
G.Members.emplace_back("A", "0");
|
||||
G.Members.emplace_back("B", "1");
|
||||
ExpectedNamespaceWithScopedEnum.Children.Enums.emplace_back(std::move(G));
|
||||
CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
|
||||
}
|
||||
|
||||
@@ -307,14 +297,12 @@ TEST_F(SerializeTest, emitUndefinedRecordInfo) {
|
||||
EmittedInfoList Infos;
|
||||
extractInfosFromCode("class E;", 2, /*Public=*/false, Infos, this->Diags);
|
||||
|
||||
RecordInfo *E = InfoAsRecord(Infos[0]);
|
||||
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
||||
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
||||
Reference NsE[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedE.Namespace = llvm::ArrayRef(NsE);
|
||||
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedE.TagType = TagTypeKind::Class;
|
||||
Location LE(0, 0, "test.cpp");
|
||||
ExpectedE.Loc.push_back(LE);
|
||||
ExpectedE.Loc.emplace_back(0, 0, "test.cpp");
|
||||
CheckRecordInfo(&ExpectedE, E);
|
||||
}
|
||||
|
||||
@@ -323,16 +311,14 @@ TEST_F(SerializeTest, emitRecordMemberInfo) {
|
||||
extractInfosFromCode("struct E { int I; };", 2, /*Public=*/false, Infos,
|
||||
this->Diags);
|
||||
|
||||
RecordInfo *E = InfoAsRecord(Infos[0]);
|
||||
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
||||
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
||||
Reference NsE[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedE.Namespace = llvm::ArrayRef(NsE);
|
||||
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedE.TagType = TagTypeKind::Struct;
|
||||
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
|
||||
MemberTypeInfo MemE[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_public)};
|
||||
ExpectedE.Members = llvm::ArrayRef(MemE);
|
||||
ExpectedE.Members.emplace_back(TypeInfo("int"), "I",
|
||||
AccessSpecifier::AS_public);
|
||||
CheckRecordInfo(&ExpectedE, E);
|
||||
}
|
||||
|
||||
@@ -341,25 +327,23 @@ TEST_F(SerializeTest, emitInternalRecordInfo) {
|
||||
extractInfosFromCode("class E { class G {}; };", 4, /*Public=*/false, Infos,
|
||||
this->Diags);
|
||||
|
||||
RecordInfo *E = InfoAsRecord(Infos[0]);
|
||||
RecordInfo *E = InfoAsRecord(Infos[0].get());
|
||||
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
||||
Reference NsE[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedE.Namespace = llvm::ArrayRef(NsE);
|
||||
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
|
||||
ExpectedE.TagType = TagTypeKind::Class;
|
||||
CheckRecordInfo(&ExpectedE, E);
|
||||
|
||||
RecordInfo *G = InfoAsRecord(Infos[2]);
|
||||
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, 0, "test.cpp");
|
||||
ExpectedG.TagType = TagTypeKind::Class;
|
||||
Reference NsG[] = {
|
||||
Reference(EmptySID, "E", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedG.Namespace = llvm::ArrayRef(NsG);
|
||||
ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
|
||||
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
CheckRecordInfo(&ExpectedG, G);
|
||||
}
|
||||
|
||||
@@ -374,14 +358,14 @@ TEST_F(SerializeTest, emitPublicFunctionInternalInfo) {
|
||||
extractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
|
||||
Infos, this->Diags);
|
||||
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
||||
FunctionInfo F;
|
||||
F.Name = "F";
|
||||
F.ReturnType = TypeInfo("int");
|
||||
F.DefLoc = Location(0, 0, "test.cpp");
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
ExpectedBWithFunction.Children.Functions.push_back(F);
|
||||
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
|
||||
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
||||
}
|
||||
|
||||
@@ -390,16 +374,15 @@ TEST_F(SerializeTest, emitInlinedFunctionInfo) {
|
||||
extractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos,
|
||||
this->Diags);
|
||||
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
||||
FunctionInfo F;
|
||||
F.Name = "F";
|
||||
F.ReturnType = TypeInfo("void");
|
||||
F.DefLoc = Location(0, 0, "test.cpp");
|
||||
FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I")};
|
||||
F.Params = llvm::ArrayRef(Params);
|
||||
F.Params.emplace_back(TypeInfo("int"), "I");
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
ExpectedBWithFunction.Children.Functions.push_back(F);
|
||||
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
|
||||
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
||||
}
|
||||
|
||||
@@ -414,169 +397,132 @@ class I {} ;
|
||||
class J : public I<int> {} ;)raw",
|
||||
14, /*Public=*/false, Infos, this->Diags);
|
||||
|
||||
RecordInfo *F = InfoAsRecord(Infos[0]);
|
||||
RecordInfo *F = InfoAsRecord(Infos[0].get());
|
||||
RecordInfo ExpectedF(EmptySID, /*Name=*/"F", /*Path=*/"GlobalNamespace");
|
||||
Reference NsF[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedF.Namespace = llvm::ArrayRef(NsF);
|
||||
ExpectedF.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace, "");
|
||||
ExpectedF.TagType = TagTypeKind::Class;
|
||||
ExpectedF.DefLoc = Location(0, 0, "test.cpp");
|
||||
CheckRecordInfo(&ExpectedF, F);
|
||||
|
||||
RecordInfo *G = InfoAsRecord(Infos[3]);
|
||||
RecordInfo *G = InfoAsRecord(Infos[3].get());
|
||||
RecordInfo ExpectedG(EmptySID, /*Name=*/"G", /*Path=*/"GlobalNamespace");
|
||||
Reference NsG[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedG.Namespace = llvm::ArrayRef(NsG);
|
||||
ExpectedG.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedG.TagType = TagTypeKind::Class;
|
||||
ExpectedG.DefLoc = Location(0, 0, "test.cpp");
|
||||
MemberTypeInfo MemG[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_protected)};
|
||||
ExpectedG.Members = llvm::ArrayRef(MemG);
|
||||
ExpectedG.Members.emplace_back(TypeInfo("int"), "I",
|
||||
AccessSpecifier::AS_protected);
|
||||
CheckRecordInfo(&ExpectedG, G);
|
||||
|
||||
RecordInfo *E = InfoAsRecord(Infos[6]);
|
||||
RecordInfo *E = InfoAsRecord(Infos[6].get());
|
||||
RecordInfo ExpectedE(EmptySID, /*Name=*/"E", /*Path=*/"GlobalNamespace");
|
||||
Reference NsE[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedE.Namespace = llvm::ArrayRef(NsE);
|
||||
Reference ParE[] = {Reference(EmptySID, /*Name=*/"F", InfoType::IT_record,
|
||||
/*QualName=*/"", /*Path=*/"GlobalNamespace")};
|
||||
ExpectedE.Parents = llvm::ArrayRef(ParE);
|
||||
Reference VParE[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record,
|
||||
/*QualName=*/"G",
|
||||
/*Path=*/"GlobalNamespace")};
|
||||
ExpectedE.VirtualParents = llvm::ArrayRef(VParE);
|
||||
BaseRecordInfo BaseF(EmptySID, /*Name=*/"F",
|
||||
/*Path=*/"GlobalNamespace", false,
|
||||
AccessSpecifier::AS_public, true);
|
||||
ExpectedE.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedE.Parents.emplace_back(EmptySID, /*Name=*/"F", InfoType::IT_record,
|
||||
/*QualName=*/"", /*Path*=*/"GlobalNamespace");
|
||||
ExpectedE.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
|
||||
InfoType::IT_record, /*QualName=*/"G",
|
||||
/*Path*=*/"GlobalNamespace");
|
||||
ExpectedE.Bases.emplace_back(EmptySID, /*Name=*/"F",
|
||||
/*Path=*/"GlobalNamespace", false,
|
||||
AccessSpecifier::AS_public, true);
|
||||
FunctionInfo FunctionSet;
|
||||
FunctionSet.Name = "set";
|
||||
FunctionSet.ReturnType = TypeInfo("void");
|
||||
Location LSet;
|
||||
FunctionSet.Loc.push_back(LSet);
|
||||
FieldTypeInfo ParamsSet[] = {FieldTypeInfo(TypeInfo("int"), "N")};
|
||||
FunctionSet.Params = llvm::ArrayRef(ParamsSet);
|
||||
Reference NsSet[] = {
|
||||
Reference(EmptySID, "F", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
FunctionSet.Namespace = llvm::ArrayRef(NsSet);
|
||||
FunctionSet.Access =
|
||||
AccessSpecifier::AS_none; // Wait, previous had AS_protected, but wait,
|
||||
// F.Access was AS_protected. FunctionSet.Access
|
||||
// should be AS_protected if it was so. In the
|
||||
// original it was AS_protected.
|
||||
FunctionSet.Loc.emplace_back();
|
||||
FunctionSet.Params.emplace_back(TypeInfo("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;
|
||||
BaseF.Children.Functions.push_back(FunctionSet);
|
||||
|
||||
BaseRecordInfo BaseG(EmptySID, /*Name=*/"G",
|
||||
/*Path=*/"GlobalNamespace", true,
|
||||
AccessSpecifier::AS_private, true);
|
||||
ExpectedE.Bases.back().Children.Functions.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("int");
|
||||
Location LGet;
|
||||
FunctionGet.DefLoc = LGet;
|
||||
Reference NsGet[] = {
|
||||
Reference(EmptySID, "G", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
FunctionGet.Namespace = llvm::ArrayRef(NsGet);
|
||||
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;
|
||||
BaseG.Children.Functions.push_back(FunctionGet);
|
||||
MemberTypeInfo MemG2[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)};
|
||||
BaseG.Members = llvm::ArrayRef(MemG2);
|
||||
|
||||
BaseRecordInfo BasesE[] = {std::move(BaseF), std::move(BaseG)};
|
||||
ExpectedE.Bases = llvm::ArrayRef(BasesE);
|
||||
ExpectedE.Bases.back().Children.Functions.emplace_back(
|
||||
std::move(FunctionGet));
|
||||
ExpectedE.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
|
||||
AccessSpecifier::AS_private);
|
||||
ExpectedE.DefLoc = Location(0, 0, "test.cpp");
|
||||
ExpectedE.TagType = TagTypeKind::Class;
|
||||
CheckRecordInfo(&ExpectedE, E);
|
||||
|
||||
RecordInfo *H = InfoAsRecord(Infos[8]);
|
||||
RecordInfo *H = InfoAsRecord(Infos[8].get());
|
||||
RecordInfo ExpectedH(EmptySID, /*Name=*/"H", /*Path=*/"GlobalNamespace");
|
||||
Reference NsH[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedH.Namespace = llvm::ArrayRef(NsH);
|
||||
ExpectedH.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedH.TagType = TagTypeKind::Class;
|
||||
ExpectedH.DefLoc = Location(0, 0, "test.cpp");
|
||||
Reference ParH[] = {Reference(EmptySID, /*Name=*/"E", InfoType::IT_record,
|
||||
/*QualName=*/"E", /*Path=*/"GlobalNamespace")};
|
||||
ExpectedH.Parents = llvm::ArrayRef(ParH);
|
||||
Reference VParH[] = {Reference(EmptySID, /*Name=*/"G", InfoType::IT_record,
|
||||
/*QualName=*/"G",
|
||||
/*Path=*/"GlobalNamespace")};
|
||||
ExpectedH.VirtualParents = llvm::ArrayRef(VParH);
|
||||
|
||||
BaseRecordInfo BaseHE(EmptySID, /*Name=*/"E",
|
||||
/*Path=*/"GlobalNamespace", false,
|
||||
AccessSpecifier::AS_private, true);
|
||||
|
||||
BaseRecordInfo BaseHF(EmptySID, /*Name=*/"F",
|
||||
/*Path=*/"GlobalNamespace", false,
|
||||
AccessSpecifier::AS_private, false);
|
||||
ExpectedH.Parents.emplace_back(EmptySID, /*Name=*/"E", InfoType::IT_record,
|
||||
/*QualName=*/"E", /*Path=*/"GlobalNamespace");
|
||||
ExpectedH.VirtualParents.emplace_back(EmptySID, /*Name=*/"G",
|
||||
InfoType::IT_record, /*QualName=*/"G",
|
||||
/*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("void");
|
||||
Location LSetNew;
|
||||
FunctionSetNew.Loc.push_back(LSetNew);
|
||||
FieldTypeInfo ParamsSetNew[] = {FieldTypeInfo(TypeInfo("int"), "N")};
|
||||
FunctionSetNew.Params = llvm::ArrayRef(ParamsSetNew);
|
||||
Reference NsSetNew[] = {
|
||||
Reference(EmptySID, "F", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
FunctionSetNew.Namespace = llvm::ArrayRef(NsSetNew);
|
||||
FunctionSetNew.Loc.emplace_back();
|
||||
FunctionSetNew.Params.emplace_back(TypeInfo("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;
|
||||
BaseHF.Children.Functions.push_back(FunctionSetNew);
|
||||
BaseRecordInfo BaseHG(EmptySID, /*Name=*/"G",
|
||||
/*Path=*/"GlobalNamespace", true,
|
||||
AccessSpecifier::AS_private, false);
|
||||
ExpectedH.Bases.back().Children.Functions.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("int");
|
||||
Location LGetNew;
|
||||
FunctionGetNew.DefLoc = LGetNew;
|
||||
Reference NsGetNew[] = {
|
||||
Reference(EmptySID, "G", InfoType::IT_record),
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
FunctionGetNew.Namespace = llvm::ArrayRef(NsGetNew);
|
||||
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;
|
||||
BaseHG.Children.Functions.push_back(FunctionGetNew);
|
||||
MemberTypeInfo MemHG[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "I", AccessSpecifier::AS_private)};
|
||||
BaseHG.Members = llvm::ArrayRef(MemHG);
|
||||
|
||||
BaseRecordInfo BasesH[] = {std::move(BaseHE), std::move(BaseHF),
|
||||
std::move(BaseHG)};
|
||||
ExpectedH.Bases = llvm::ArrayRef(BasesH);
|
||||
|
||||
ExpectedH.Bases.back().Children.Functions.emplace_back(
|
||||
std::move(FunctionGetNew));
|
||||
ExpectedH.Bases.back().Members.emplace_back(TypeInfo("int"), "I",
|
||||
AccessSpecifier::AS_private);
|
||||
CheckRecordInfo(&ExpectedH, H);
|
||||
|
||||
RecordInfo *I = InfoAsRecord(Infos[10]);
|
||||
RecordInfo *I = InfoAsRecord(Infos[10].get());
|
||||
RecordInfo ExpectedI(EmptySID, /*Name=*/"I", /*Path=*/"GlobalNamespace");
|
||||
Reference NsI[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedI.Namespace = llvm::ArrayRef(NsI);
|
||||
ExpectedI.Namespace.emplace_back(EmptySID, "GlobalNamespace",
|
||||
InfoType::IT_namespace);
|
||||
ExpectedI.TagType = TagTypeKind::Class;
|
||||
ExpectedI.DefLoc = Location(0, 0, "test.cpp");
|
||||
CheckRecordInfo(&ExpectedI, I);
|
||||
|
||||
RecordInfo *J = InfoAsRecord(Infos[12]);
|
||||
RecordInfo *J = InfoAsRecord(Infos[12].get());
|
||||
RecordInfo ExpectedJ(EmptySID, /*Name=*/"J", /*Path=*/"GlobalNamespace");
|
||||
Reference NsJ[] = {
|
||||
Reference(EmptySID, "GlobalNamespace", InfoType::IT_namespace)};
|
||||
ExpectedJ.Namespace = llvm::ArrayRef(NsJ);
|
||||
Reference ParJ[] = {
|
||||
Reference(EmptySID, /*Name=*/"I<int>", InfoType::IT_record)};
|
||||
ExpectedJ.Parents = llvm::ArrayRef(ParJ);
|
||||
BaseRecordInfo BasesJ[] = {BaseRecordInfo(EmptySID, /*Name=*/"I<int>",
|
||||
/*Path=*/"GlobalNamespace", false,
|
||||
AccessSpecifier::AS_public, true)};
|
||||
ExpectedJ.Bases = llvm::ArrayRef(BasesJ);
|
||||
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, 0, "test.cpp");
|
||||
ExpectedJ.TagType = TagTypeKind::Class;
|
||||
CheckRecordInfo(&ExpectedJ, J);
|
||||
@@ -592,33 +538,30 @@ static int staticModuleFunction(int x);
|
||||
export double exportedModuleFunction(double y);)raw",
|
||||
2, /*Public=*/true, Infos, Args, this->Diags);
|
||||
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
|
||||
NamespaceInfo ExpectedBWithFunction(EmptySID);
|
||||
FunctionInfo F;
|
||||
F.Name = "moduleFunction";
|
||||
F.ReturnType = TypeInfo("int");
|
||||
Location LF1(0, 0, "test.cpp");
|
||||
F.Loc.push_back(LF1);
|
||||
FieldTypeInfo ParamsF[] = {FieldTypeInfo(TypeInfo("int"), "x"),
|
||||
FieldTypeInfo(TypeInfo("double"), "d")};
|
||||
ParamsF[1].DefaultValue = "3.2 - 1.0";
|
||||
F.Params = llvm::ArrayRef(ParamsF);
|
||||
F.Loc.emplace_back(0, 0, "test.cpp");
|
||||
F.Params.emplace_back(TypeInfo("int"), "x");
|
||||
F.Params.emplace_back(TypeInfo("double"), "d");
|
||||
F.Params.back().DefaultValue = "3.2 - 1.0";
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
ExpectedBWithFunction.Children.Functions.push_back(F);
|
||||
ExpectedBWithFunction.Children.Functions.emplace_back(std::move(F));
|
||||
CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
|
||||
|
||||
NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
|
||||
NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
|
||||
FunctionInfo ExportedF;
|
||||
ExportedF.Name = "exportedModuleFunction";
|
||||
ExportedF.ReturnType =
|
||||
TypeInfo(Reference(EmptySID, "double", InfoType::IT_default));
|
||||
Location LF2(0, 0, "test.cpp");
|
||||
ExportedF.Loc.push_back(LF2);
|
||||
FieldTypeInfo ParamsExportedF[] = {FieldTypeInfo(TypeInfo("double"), "y")};
|
||||
ExportedF.Params = llvm::ArrayRef(ParamsExportedF);
|
||||
ExportedF.Loc.emplace_back(0, 0, "test.cpp");
|
||||
ExportedF.Params.emplace_back(TypeInfo("double"), "y");
|
||||
ExportedF.Access = AccessSpecifier::AS_none;
|
||||
ExpectedBWithExportedFunction.Children.Functions.push_back(ExportedF);
|
||||
ExpectedBWithExportedFunction.Children.Functions.emplace_back(
|
||||
std::move(ExportedF));
|
||||
CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
|
||||
}
|
||||
|
||||
@@ -628,24 +571,24 @@ TEST_F(SerializeTest, emitChildRecords) {
|
||||
extractInfosFromCode("class A { class B {}; }; namespace { class C {}; } ", 8,
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
|
||||
NamespaceInfo ExpectedParentA(EmptySID);
|
||||
Reference RA(EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
|
||||
ExpectedParentA.Children.Records.push_back(RA);
|
||||
ExpectedParentA.Children.Records.emplace_back(
|
||||
EmptySID, "A", InfoType::IT_record, "A", "GlobalNamespace");
|
||||
CheckNamespaceInfo(&ExpectedParentA, ParentA);
|
||||
|
||||
RecordInfo *ParentB = InfoAsRecord(Infos[3]);
|
||||
RecordInfo *ParentB = InfoAsRecord(Infos[3].get());
|
||||
RecordInfo ExpectedParentB(EmptySID);
|
||||
llvm::SmallString<128> ExpectedParentBPath("GlobalNamespace/A");
|
||||
llvm::sys::path::native(ExpectedParentBPath);
|
||||
Reference RB(EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
|
||||
ExpectedParentB.Children.Records.push_back(RB);
|
||||
ExpectedParentB.Children.Records.emplace_back(
|
||||
EmptySID, "B", InfoType::IT_record, "A::B", ExpectedParentBPath);
|
||||
CheckRecordInfo(&ExpectedParentB, ParentB);
|
||||
|
||||
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7]);
|
||||
NamespaceInfo *ParentC = InfoAsNamespace(Infos[7].get());
|
||||
NamespaceInfo ExpectedParentC(EmptySID);
|
||||
Reference RC(EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
|
||||
ExpectedParentC.Children.Records.push_back(RC);
|
||||
ExpectedParentC.Children.Records.emplace_back(
|
||||
EmptySID, "C", InfoType::IT_record, "C", "@nonymous_namespace");
|
||||
CheckNamespaceInfo(&ExpectedParentC, ParentC);
|
||||
}
|
||||
|
||||
@@ -655,13 +598,13 @@ TEST_F(SerializeTest, emitChildNamespaces) {
|
||||
extractInfosFromCode("namespace A { namespace B { } }", 4, /*Public=*/false,
|
||||
Infos, this->Diags);
|
||||
|
||||
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *ParentA = InfoAsNamespace(Infos[1].get());
|
||||
NamespaceInfo ExpectedParentA(EmptySID);
|
||||
Reference RA(EmptySID, "A", InfoType::IT_namespace);
|
||||
ExpectedParentA.Children.Namespaces.push_back(RA);
|
||||
CheckNamespaceInfo(&ExpectedParentA, ParentA);
|
||||
|
||||
NamespaceInfo *ParentB = InfoAsNamespace(Infos[3]);
|
||||
NamespaceInfo *ParentB = InfoAsNamespace(Infos[3].get());
|
||||
NamespaceInfo ExpectedParentB(EmptySID);
|
||||
Reference RB(EmptySID, "B", InfoType::IT_namespace, "A::B", "A");
|
||||
ExpectedParentB.Children.Namespaces.push_back(RB);
|
||||
@@ -674,10 +617,10 @@ TEST_F(SerializeTest, emitTypedefs) {
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
// First info will be the global namespace with the typedef in it.
|
||||
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
|
||||
ASSERT_EQ(1u, GlobalNS1->Children.Typedefs.size());
|
||||
|
||||
const TypedefInfo &FirstTD = *GlobalNS1->Children.Typedefs.begin();
|
||||
const TypedefInfo &FirstTD = GlobalNS1->Children.Typedefs[0];
|
||||
EXPECT_EQ("MyInt", FirstTD.Name);
|
||||
EXPECT_FALSE(FirstTD.IsUsing);
|
||||
EXPECT_EQ("int", FirstTD.Underlying.Type.Name);
|
||||
@@ -685,11 +628,11 @@ TEST_F(SerializeTest, emitTypedefs) {
|
||||
// The second will be another global namespace with the using in it (the
|
||||
// global namespace is duplicated because the items haven't been merged at the
|
||||
// serialization phase of processing).
|
||||
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
|
||||
ASSERT_EQ(1u, GlobalNS2->Children.Typedefs.size());
|
||||
|
||||
// Second is the "using" typedef.
|
||||
const TypedefInfo &SecondTD = *GlobalNS2->Children.Typedefs.begin();
|
||||
const TypedefInfo &SecondTD = GlobalNS2->Children.Typedefs[0];
|
||||
EXPECT_EQ("MyDouble", SecondTD.Name);
|
||||
EXPECT_TRUE(SecondTD.IsUsing);
|
||||
EXPECT_EQ("double", SecondTD.Underlying.Type.Name);
|
||||
@@ -704,10 +647,10 @@ TEST_F(SerializeTest, emitFunctionTemplate) {
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
// First info will be the global namespace.
|
||||
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0]);
|
||||
NamespaceInfo *GlobalNS1 = InfoAsNamespace(Infos[0].get());
|
||||
ASSERT_EQ(1u, GlobalNS1->Children.Functions.size());
|
||||
|
||||
const FunctionInfo &Func1 = *GlobalNS1->Children.Functions.begin();
|
||||
const FunctionInfo &Func1 = GlobalNS1->Children.Functions[0];
|
||||
EXPECT_EQ("GetFoo", Func1.Name);
|
||||
ASSERT_TRUE(Func1.Template);
|
||||
EXPECT_FALSE(Func1.Template->Specialization); // Not a specialization.
|
||||
@@ -719,11 +662,11 @@ TEST_F(SerializeTest, emitFunctionTemplate) {
|
||||
// The second will be another global namespace with the function in it (the
|
||||
// global namespace is duplicated because the items haven't been merged at the
|
||||
// serialization phase of processing).
|
||||
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1]);
|
||||
NamespaceInfo *GlobalNS2 = InfoAsNamespace(Infos[1].get());
|
||||
ASSERT_EQ(1u, GlobalNS2->Children.Functions.size());
|
||||
|
||||
// This one is a template specialization.
|
||||
const FunctionInfo &Func2 = *GlobalNS2->Children.Functions.begin();
|
||||
const FunctionInfo &Func2 = GlobalNS2->Children.Functions[0];
|
||||
EXPECT_EQ("GetFoo", Func2.Name);
|
||||
ASSERT_TRUE(Func2.Template);
|
||||
EXPECT_TRUE(Func2.Template->Params.empty()); // No template params.
|
||||
@@ -751,7 +694,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
|
||||
/*Public=*/false, Infos, this->Diags);
|
||||
|
||||
// First record.
|
||||
const RecordInfo *Rec1 = InfoAsRecord(Infos[0]);
|
||||
const RecordInfo *Rec1 = InfoAsRecord(Infos[0].get());
|
||||
EXPECT_EQ("MyTemplate", Rec1->Name);
|
||||
ASSERT_TRUE(Rec1->Template);
|
||||
EXPECT_FALSE(Rec1->Template->Specialization); // Not a specialization.
|
||||
@@ -761,7 +704,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
|
||||
EXPECT_EQ("int I", Rec1->Template->Params[0].Contents);
|
||||
|
||||
// Second record.
|
||||
const RecordInfo *Rec2 = InfoAsRecord(Infos[2]);
|
||||
const RecordInfo *Rec2 = InfoAsRecord(Infos[2].get());
|
||||
EXPECT_EQ("MyTemplate", Rec2->Name);
|
||||
ASSERT_TRUE(Rec2->Template);
|
||||
EXPECT_TRUE(Rec2->Template->Params.empty()); // No template params.
|
||||
@@ -773,7 +716,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
|
||||
EXPECT_EQ(Rec1->USR, Rec2->Template->Specialization->SpecializationOf);
|
||||
|
||||
// Third record.
|
||||
const RecordInfo *Rec3 = InfoAsRecord(Infos[4]);
|
||||
const RecordInfo *Rec3 = InfoAsRecord(Infos[4].get());
|
||||
EXPECT_EQ("OtherTemplate", Rec3->Name);
|
||||
ASSERT_TRUE(Rec3->Template);
|
||||
|
||||
@@ -783,7 +726,7 @@ TEST_F(SerializeTest, emitClassTemplate) {
|
||||
EXPECT_EQ("int U = 1", Rec3->Template->Params[1].Contents);
|
||||
|
||||
// Fourth record.
|
||||
const RecordInfo *Rec4 = InfoAsRecord(Infos[6]);
|
||||
const RecordInfo *Rec4 = InfoAsRecord(Infos[6].get());
|
||||
EXPECT_EQ("OtherTemplate", Rec3->Name);
|
||||
ASSERT_TRUE(Rec4->Template);
|
||||
ASSERT_TRUE(Rec4->Template->Specialization);
|
||||
|
||||
@@ -28,25 +28,20 @@ TEST_F(YAMLGeneratorTest, emitNamespaceYAML) {
|
||||
NamespaceInfo I;
|
||||
I.Name = "Namespace";
|
||||
I.Path = "path/to/A";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
Reference NewNamespace(EmptySID, "ChildNamespace", InfoType::IT_namespace,
|
||||
"path::to::A::Namespace::ChildNamespace",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Namespaces.push_back(NewNamespace);
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::Namespace::ChildStruct",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo F;
|
||||
F.Name = "OneFunction";
|
||||
F.Access = AccessSpecifier::AS_none;
|
||||
I.Children.Functions.push_back(F);
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "OneEnum";
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::Namespace::ChildStruct",
|
||||
"path/to/A/Namespace");
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Functions.back().Access = AccessSpecifier::AS_none;
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getYAMLGenerator();
|
||||
assert(G);
|
||||
@@ -90,14 +85,12 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
|
||||
I.Name = "r";
|
||||
I.Path = "path/to/A";
|
||||
I.IsTypeDef = true;
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
MemberTypeInfo M(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
I.Members.emplace_back(TypeInfo("int"), "X", AccessSpecifier::AS_private);
|
||||
|
||||
// Member documentation.
|
||||
CommentInfo BriefChildren[] = {CommentInfo(CommentKind::CK_TextComment, {},
|
||||
@@ -106,39 +99,26 @@ TEST_F(YAMLGeneratorTest, emitRecordYAML) {
|
||||
CommentInfo TopCommentChildren[] = {
|
||||
CommentInfo(CommentKind::CK_ParagraphComment, BriefChildren)};
|
||||
CommentInfo TopComment(CommentKind::CK_FullComment, TopCommentChildren);
|
||||
M.Description.push_back(TopComment);
|
||||
MemberTypeInfo MemArr[] = {std::move(M)};
|
||||
I.Members = llvm::ArrayRef(MemArr);
|
||||
I.Members.back().Description.push_back(std::move(TopComment));
|
||||
|
||||
I.TagType = TagTypeKind::Class;
|
||||
BaseRecordInfo B(EmptySID, "F", "path/to/F", true, AccessSpecifier::AS_public,
|
||||
true);
|
||||
FunctionInfo F;
|
||||
F.Name = "InheritedFunctionOne";
|
||||
B.Children.Functions.push_back(F);
|
||||
MemberTypeInfo BMem[] = {
|
||||
MemberTypeInfo(TypeInfo("int"), "N", AccessSpecifier::AS_private)};
|
||||
B.Members = llvm::ArrayRef(BMem);
|
||||
BaseRecordInfo Bases[] = {std::move(B)};
|
||||
I.Bases = llvm::ArrayRef(Bases);
|
||||
|
||||
I.Bases.emplace_back(EmptySID, "F", "path/to/F", true,
|
||||
AccessSpecifier::AS_public, true);
|
||||
I.Bases.back().Children.Functions.emplace_back();
|
||||
I.Bases.back().Children.Functions.back().Name = "InheritedFunctionOne";
|
||||
I.Bases.back().Members.emplace_back(TypeInfo("int"), "N",
|
||||
AccessSpecifier::AS_private);
|
||||
// F is in the global namespace
|
||||
Reference Parents[] = {Reference(EmptySID, "F", InfoType::IT_record, "")};
|
||||
I.Parents = llvm::ArrayRef(Parents);
|
||||
Reference VParents[] = {Reference(EmptySID, "G", InfoType::IT_record,
|
||||
"path::to::G::G", "path/to/G")};
|
||||
I.VirtualParents = llvm::ArrayRef(VParents);
|
||||
I.Parents.emplace_back(EmptySID, "F", InfoType::IT_record, "");
|
||||
I.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record,
|
||||
"path::to::G::G", "path/to/G");
|
||||
|
||||
Reference ChildStruct(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::r::ChildStruct", "path/to/A/r");
|
||||
I.Children.Records.push_back(ChildStruct);
|
||||
FunctionInfo F2;
|
||||
F2.Name = "OneFunction";
|
||||
I.Children.Functions.push_back(F2);
|
||||
|
||||
EnumInfo E;
|
||||
E.Name = "OneEnum";
|
||||
I.Children.Enums.push_back(E);
|
||||
I.Children.Records.emplace_back(EmptySID, "ChildStruct", InfoType::IT_record,
|
||||
"path::to::A::r::ChildStruct", "path/to/A/r");
|
||||
I.Children.Functions.emplace_back();
|
||||
I.Children.Functions.back().Name = "OneFunction";
|
||||
I.Children.Enums.emplace_back();
|
||||
I.Children.Enums.back().Name = "OneEnum";
|
||||
|
||||
auto G = getYAMLGenerator();
|
||||
assert(G);
|
||||
@@ -225,22 +205,17 @@ ChildEnums:
|
||||
TEST_F(YAMLGeneratorTest, emitFunctionYAML) {
|
||||
FunctionInfo I;
|
||||
I.Name = "f";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
I.Access = AccessSpecifier::AS_none;
|
||||
|
||||
I.ReturnType = TypeInfo(Reference(EmptySID, "void", InfoType::IT_default));
|
||||
|
||||
FieldTypeInfo P1(TypeInfo("int"), "P");
|
||||
FieldTypeInfo D(TypeInfo("double"), "D");
|
||||
D.DefaultValue = "2.0 * M_PI";
|
||||
FieldTypeInfo Params[] = {std::move(P1), std::move(D)};
|
||||
I.Params = llvm::ArrayRef(Params);
|
||||
I.Params.emplace_back(TypeInfo("int"), "P");
|
||||
I.Params.emplace_back(TypeInfo("double"), "D");
|
||||
I.Params.back().DefaultValue = "2.0 * M_PI";
|
||||
I.IsMethod = true;
|
||||
I.Parent = Reference(EmptySID, "Parent", InfoType::IT_record);
|
||||
|
||||
@@ -295,15 +270,12 @@ ReturnType:
|
||||
TEST_F(YAMLGeneratorTest, emitSimpleEnumYAML) {
|
||||
EnumInfo I;
|
||||
I.Name = "e";
|
||||
Reference Ns[] = {Reference(EmptySID, "A", InfoType::IT_namespace)};
|
||||
I.Namespace = llvm::ArrayRef(Ns);
|
||||
I.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
|
||||
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
Location Loc1(12, 12, "test.cpp");
|
||||
I.Loc.push_back(Loc1);
|
||||
I.Loc.emplace_back(12, 12, "test.cpp");
|
||||
|
||||
EnumValueInfo EV[] = {EnumValueInfo("X")};
|
||||
I.Members = llvm::ArrayRef(EV);
|
||||
I.Members.emplace_back("X");
|
||||
I.Scoped = false;
|
||||
|
||||
auto G = getYAMLGenerator();
|
||||
@@ -340,8 +312,7 @@ TEST_F(YAMLGeneratorTest, enumTypedScopedEnumYAML) {
|
||||
EnumInfo I;
|
||||
I.Name = "e";
|
||||
|
||||
EnumValueInfo EV[] = {EnumValueInfo("X", "-9876", "FOO_BAR + 2")};
|
||||
I.Members = llvm::ArrayRef(EV);
|
||||
I.Members.emplace_back("X", "-9876", "FOO_BAR + 2");
|
||||
I.Scoped = true;
|
||||
I.BaseType = TypeInfo("short");
|
||||
|
||||
@@ -399,9 +370,8 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
|
||||
I.Name = "f";
|
||||
I.DefLoc = Location(10, 10, "test.cpp");
|
||||
I.ReturnType = TypeInfo("void");
|
||||
FieldTypeInfo Params[] = {FieldTypeInfo(TypeInfo("int"), "I"),
|
||||
FieldTypeInfo(TypeInfo("int"), "J")};
|
||||
I.Params = llvm::ArrayRef(Params);
|
||||
I.Params.emplace_back(TypeInfo("int"), "I");
|
||||
I.Params.emplace_back(TypeInfo("int"), "J");
|
||||
I.Access = AccessSpecifier::AS_none;
|
||||
|
||||
// BlankLine
|
||||
@@ -474,7 +444,7 @@ TEST_F(YAMLGeneratorTest, emitCommentYAML) {
|
||||
Verbatim, ParamOut, ParamIn, Return};
|
||||
CommentInfo Top(CommentKind::CK_FullComment, TopChildren);
|
||||
|
||||
I.Description.push_back(Top);
|
||||
I.Description.emplace_back(std::move(Top));
|
||||
|
||||
auto G = getYAMLGenerator();
|
||||
assert(G);
|
||||
|
||||
Reference in New Issue
Block a user