[clang-tools-extra] r344650 - [clang-doc] Add unit tests for serialization

Julie Hockett via cfe-commits cfe-commits at lists.llvm.org
Tue Oct 16 16:06:42 PDT 2018


Author: juliehockett
Date: Tue Oct 16 16:06:42 2018
New Revision: 344650

URL: http://llvm.org/viewvc/llvm-project?rev=344650&view=rev
Log:
[clang-doc] Add unit tests for serialization

Adds unit tests for the Serialize library.

This is part of a move to convert clang-doc's tests to a more
maintainable unit test framework, with a smaller number of integration
tests to maintain and more granular failure feedback.

Differential Revision: https://reviews.llvm.org/D53081

Added:
    clang-tools-extra/trunk/unittests/clang-doc/
    clang-tools-extra/trunk/unittests/clang-doc/CMakeLists.txt
    clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp
    clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.h
    clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp
Modified:
    clang-tools-extra/trunk/unittests/CMakeLists.txt

Modified: clang-tools-extra/trunk/unittests/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/CMakeLists.txt?rev=344650&r1=344649&r2=344650&view=diff
==============================================================================
--- clang-tools-extra/trunk/unittests/CMakeLists.txt (original)
+++ clang-tools-extra/trunk/unittests/CMakeLists.txt Tue Oct 16 16:06:42 2018
@@ -16,6 +16,7 @@ endif()
 
 add_subdirectory(change-namespace)
 add_subdirectory(clang-apply-replacements)
+add_subdirectory(clang-doc)
 add_subdirectory(clang-move)
 add_subdirectory(clang-query)
 add_subdirectory(clang-tidy)

Added: clang-tools-extra/trunk/unittests/clang-doc/CMakeLists.txt
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/CMakeLists.txt?rev=344650&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/CMakeLists.txt (added)
+++ clang-tools-extra/trunk/unittests/clang-doc/CMakeLists.txt Tue Oct 16 16:06:42 2018
@@ -0,0 +1,29 @@
+set(LLVM_LINK_COMPONENTS
+  support
+  BitReader
+  BitWriter
+  )
+
+get_filename_component(CLANG_DOC_SOURCE_DIR
+  ${CMAKE_CURRENT_SOURCE_DIR}/../../clang-doc REALPATH)
+include_directories(
+  ${CLANG_DOC_SOURCE_DIR}
+  )
+
+add_extra_unittest(ClangDocTests
+  ClangDocTest.cpp
+  SerializeTest.cpp
+  )
+
+target_link_libraries(ClangDocTests
+  PRIVATE
+  clangAST
+  clangASTMatchers
+  clangBasic
+  clangDoc
+  clangFormat
+  clangFrontend
+  clangRewrite
+  clangTooling
+  clangToolingCore
+  )

Added: clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp?rev=344650&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp (added)
+++ clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.cpp Tue Oct 16 16:06:42 2018
@@ -0,0 +1,182 @@
+//===-- clang-doc/ClangDocTest.cpp ----------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Representation.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+NamespaceInfo *InfoAsNamespace(Info *I) {
+  assert(I->IT == InfoType::IT_namespace);
+  return static_cast<NamespaceInfo *>(I);
+}
+
+RecordInfo *InfoAsRecord(Info *I) {
+  assert(I->IT == InfoType::IT_record);
+  return static_cast<RecordInfo *>(I);
+}
+
+FunctionInfo *InfoAsFunction(Info *I) {
+  assert(I->IT == InfoType::IT_function);
+  return static_cast<FunctionInfo *>(I);
+}
+
+EnumInfo *InfoAsEnum(Info *I) {
+  assert(I->IT == InfoType::IT_enum);
+  return static_cast<EnumInfo *>(I);
+}
+
+void CheckCommentInfo(CommentInfo &Expected, CommentInfo &Actual) {
+  EXPECT_EQ(Expected.Kind, Actual.Kind);
+  EXPECT_EQ(Expected.Text, Actual.Text);
+  EXPECT_EQ(Expected.Name, Actual.Name);
+  EXPECT_EQ(Expected.Direction, Actual.Direction);
+  EXPECT_EQ(Expected.ParamName, Actual.ParamName);
+  EXPECT_EQ(Expected.CloseName, Actual.CloseName);
+  EXPECT_EQ(Expected.SelfClosing, Actual.SelfClosing);
+  EXPECT_EQ(Expected.Explicit, Actual.Explicit);
+
+  ASSERT_EQ(Expected.AttrKeys.size(), Actual.AttrKeys.size());
+  for (size_t Idx = 0; Idx < Actual.AttrKeys.size(); ++Idx)
+    EXPECT_EQ(Expected.AttrKeys[Idx], Actual.AttrKeys[Idx]);
+
+  ASSERT_EQ(Expected.AttrValues.size(), Actual.AttrValues.size());
+  for (size_t Idx = 0; Idx < Actual.AttrValues.size(); ++Idx)
+    EXPECT_EQ(Expected.AttrValues[Idx], Actual.AttrValues[Idx]);
+
+  ASSERT_EQ(Expected.Args.size(), Actual.Args.size());
+  for (size_t Idx = 0; Idx < Actual.Args.size(); ++Idx)
+    EXPECT_EQ(Expected.Args[Idx], Actual.Args[Idx]);
+
+  ASSERT_EQ(Expected.Children.size(), Actual.Children.size());
+  for (size_t Idx = 0; Idx < Actual.Children.size(); ++Idx)
+    CheckCommentInfo(*Expected.Children[Idx], *Actual.Children[Idx]);
+}
+
+void CheckReference(Reference &Expected, Reference &Actual) {
+  EXPECT_EQ(Expected.Name, Actual.Name);
+  EXPECT_EQ(Expected.RefType, Actual.RefType);
+}
+
+void CheckTypeInfo(TypeInfo *Expected, TypeInfo *Actual) {
+  CheckReference(Expected->Type, Actual->Type);
+}
+
+void CheckFieldTypeInfo(FieldTypeInfo *Expected, FieldTypeInfo *Actual) {
+  CheckTypeInfo(Expected, Actual);
+  EXPECT_EQ(Expected->Name, Actual->Name);
+}
+
+void CheckMemberTypeInfo(MemberTypeInfo *Expected, MemberTypeInfo *Actual) {
+  CheckFieldTypeInfo(Expected, Actual);
+  EXPECT_EQ(Expected->Access, Actual->Access);
+}
+
+void CheckBaseInfo(Info *Expected, Info *Actual) {
+  EXPECT_EQ(size_t(20), Actual->USR.size());
+  EXPECT_EQ(Expected->Name, Actual->Name);
+  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]);
+  ASSERT_EQ(Expected->Description.size(), Actual->Description.size());
+  for (size_t Idx = 0; Idx < Actual->Description.size(); ++Idx)
+    CheckCommentInfo(Expected->Description[Idx], Actual->Description[Idx]);
+}
+
+void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual) {
+  CheckBaseInfo(Expected, Actual);
+  EXPECT_EQ(Expected->DefLoc.hasValue(), Actual->DefLoc.hasValue());
+  if (Expected->DefLoc.hasValue() && Actual->DefLoc.hasValue()) {
+    EXPECT_EQ(Expected->DefLoc->LineNumber, Actual->DefLoc->LineNumber);
+    EXPECT_EQ(Expected->DefLoc->Filename, Actual->DefLoc->Filename);
+  }
+  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(FunctionInfo *Expected, FunctionInfo *Actual) {
+  CheckSymbolInfo(Expected, Actual);
+
+  EXPECT_EQ(Expected->IsMethod, Actual->IsMethod);
+  CheckReference(Expected->Parent, Actual->Parent);
+  CheckTypeInfo(&Expected->ReturnType, &Actual->ReturnType);
+
+  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(EnumInfo *Expected, EnumInfo *Actual) {
+  CheckSymbolInfo(Expected, Actual);
+
+  EXPECT_EQ(Expected->Scoped, Actual->Scoped);
+  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 CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual) {
+  CheckBaseInfo(Expected, Actual);
+
+  ASSERT_EQ(Expected->ChildNamespaces.size(), Actual->ChildNamespaces.size());
+  for (size_t Idx = 0; Idx < Actual->ChildNamespaces.size(); ++Idx)
+    EXPECT_EQ(Expected->ChildNamespaces[Idx], Actual->ChildNamespaces[Idx]);
+
+  ASSERT_EQ(Expected->ChildRecords.size(), Actual->ChildRecords.size());
+  for (size_t Idx = 0; Idx < Actual->ChildRecords.size(); ++Idx)
+    EXPECT_EQ(Expected->ChildRecords[Idx], Actual->ChildRecords[Idx]);
+
+  ASSERT_EQ(Expected->ChildFunctions.size(), Actual->ChildFunctions.size());
+  for (size_t Idx = 0; Idx < Actual->ChildFunctions.size(); ++Idx)
+    CheckFunctionInfo(&Expected->ChildFunctions[Idx],
+                      &Actual->ChildFunctions[Idx]);
+
+  ASSERT_EQ(Expected->ChildEnums.size(), Actual->ChildEnums.size());
+  for (size_t Idx = 0; Idx < Actual->ChildEnums.size(); ++Idx)
+    CheckEnumInfo(&Expected->ChildEnums[Idx], &Actual->ChildEnums[Idx]);
+}
+
+void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual) {
+  CheckSymbolInfo(Expected, Actual);
+
+  EXPECT_EQ(Expected->TagType, Actual->TagType);
+
+  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]);
+
+  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]);
+
+  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]);
+
+  ASSERT_EQ(Expected->ChildRecords.size(), Actual->ChildRecords.size());
+  for (size_t Idx = 0; Idx < Actual->ChildRecords.size(); ++Idx)
+    EXPECT_EQ(Expected->ChildRecords[Idx], Actual->ChildRecords[Idx]);
+
+  ASSERT_EQ(Expected->ChildFunctions.size(), Actual->ChildFunctions.size());
+  for (size_t Idx = 0; Idx < Actual->ChildFunctions.size(); ++Idx)
+    CheckFunctionInfo(&Expected->ChildFunctions[Idx],
+                      &Actual->ChildFunctions[Idx]);
+
+  ASSERT_EQ(Expected->ChildEnums.size(), Actual->ChildEnums.size());
+  for (size_t Idx = 0; Idx < Actual->ChildEnums.size(); ++Idx)
+    CheckEnumInfo(&Expected->ChildEnums[Idx], &Actual->ChildEnums[Idx]);
+}
+
+} // namespace doc
+} // namespace clang

Added: clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.h
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.h?rev=344650&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.h (added)
+++ clang-tools-extra/trunk/unittests/clang-doc/ClangDocTest.h Tue Oct 16 16:06:42 2018
@@ -0,0 +1,51 @@
+//===-- clang-doc/ClangDocTest.h ------------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_DOC_CLANGDOCTEST_H
+#define LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_DOC_CLANGDOCTEST_H
+
+#include "ClangDocTest.h"
+#include "Representation.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+using EmittedInfoList = std::vector<std::unique_ptr<Info>>;
+
+static const SymbolID EmptySID = SymbolID();
+static const SymbolID NonEmptySID =
+    SymbolID{1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
+
+NamespaceInfo *InfoAsNamespace(Info *I);
+RecordInfo *InfoAsRecord(Info *I);
+FunctionInfo *InfoAsFunction(Info *I);
+EnumInfo *InfoAsEnum(Info *I);
+
+// 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(Info *Expected, Info *Actual);
+void CheckSymbolInfo(SymbolInfo *Expected, SymbolInfo *Actual);
+void CheckFunctionInfo(FunctionInfo *Expected, FunctionInfo *Actual);
+void CheckEnumInfo(EnumInfo *Expected, EnumInfo *Actual);
+void CheckNamespaceInfo(NamespaceInfo *Expected, NamespaceInfo *Actual);
+void CheckRecordInfo(RecordInfo *Expected, RecordInfo *Actual);
+
+} // namespace doc
+} // namespace clang
+
+#endif // LLVM_CLANG_TOOLS_EXTRA_UNITTESTS_CLANG_DOC_CLANGDOCTEST_H

Added: clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp
URL: http://llvm.org/viewvc/llvm-project/clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp?rev=344650&view=auto
==============================================================================
--- clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp (added)
+++ clang-tools-extra/trunk/unittests/clang-doc/SerializeTest.cpp Tue Oct 16 16:06:42 2018
@@ -0,0 +1,346 @@
+//===-- clang-doc/SerializeTest.cpp ---------------------------------------===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "Serialize.h"
+#include "ClangDocTest.h"
+#include "Representation.h"
+#include "clang/AST/Comment.h"
+#include "clang/AST/RecursiveASTVisitor.h"
+#include "gtest/gtest.h"
+
+namespace clang {
+namespace doc {
+
+class ClangDocSerializeTestVisitor
+    : public RecursiveASTVisitor<ClangDocSerializeTestVisitor> {
+
+  EmittedInfoList &EmittedInfos;
+  bool Public;
+
+  comments::FullComment *getComment(const NamedDecl *D) const {
+    if (RawComment *Comment =
+            D->getASTContext().getRawCommentForDeclNoCache(D)) {
+      Comment->setAttached();
+      return Comment->parse(D->getASTContext(), nullptr, D);
+    }
+    return nullptr;
+  }
+
+public:
+  ClangDocSerializeTestVisitor(EmittedInfoList &EmittedInfos, bool Public)
+      : EmittedInfos(EmittedInfos), Public(Public) {}
+
+  bool VisitNamespaceDecl(const NamespaceDecl *D) {
+    auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+                                 /*File=*/"test.cpp", Public);
+    if (I)
+      EmittedInfos.emplace_back(std::move(I));
+    return true;
+  }
+
+  bool VisitFunctionDecl(const FunctionDecl *D) {
+    // Don't visit CXXMethodDecls twice
+    if (dyn_cast<CXXMethodDecl>(D))
+      return true;
+    auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+                                 /*File=*/"test.cpp", Public);
+    if (I)
+      EmittedInfos.emplace_back(std::move(I));
+    return true;
+  }
+
+  bool VisitCXXMethodDecl(const CXXMethodDecl *D) {
+    auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+                                 /*File=*/"test.cpp", Public);
+    if (I)
+      EmittedInfos.emplace_back(std::move(I));
+    return true;
+  }
+
+  bool VisitRecordDecl(const RecordDecl *D) {
+    auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+                                 /*File=*/"test.cpp", Public);
+    if (I)
+      EmittedInfos.emplace_back(std::move(I));
+    return true;
+  }
+
+  bool VisitEnumDecl(const EnumDecl *D) {
+    auto I = serialize::emitInfo(D, getComment(D), /*Line=*/0,
+                                 /*File=*/"test.cpp", Public);
+    if (I)
+      EmittedInfos.emplace_back(std::move(I));
+    return true;
+  }
+};
+
+void ExtractInfosFromCode(StringRef Code, size_t NumExpectedInfos, bool Public,
+                          EmittedInfoList &EmittedInfos) {
+  auto ASTUnit = clang::tooling::buildASTFromCode(Code);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+void ExtractInfosFromCodeWithArgs(StringRef Code, size_t NumExpectedInfos,
+                                  bool Public, EmittedInfoList &EmittedInfos,
+                                  std::vector<std::string> &Args) {
+  auto ASTUnit = clang::tooling::buildASTFromCodeWithArgs(Code, Args);
+  auto TU = ASTUnit->getASTContext().getTranslationUnitDecl();
+  ClangDocSerializeTestVisitor Visitor(EmittedInfos, Public);
+  Visitor.TraverseTranslationUnitDecl(TU);
+  ASSERT_EQ(NumExpectedInfos, EmittedInfos.size());
+}
+
+// Test serialization of namespace declarations.
+TEST(SerializeTest, emitNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace A { namespace B { void f() {} } }", 3,
+                       /*Public=*/false, Infos);
+
+  NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedA(EmptySID, "A");
+  CheckNamespaceInfo(&ExpectedA, A);
+
+  NamespaceInfo *B = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedB(EmptySID, "B");
+  ExpectedB.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+  CheckNamespaceInfo(&ExpectedB, B);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[2].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "f";
+  F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  F.Namespace.emplace_back(EmptySID, "B", InfoType::IT_namespace);
+  F.Namespace.emplace_back(EmptySID, "A", InfoType::IT_namespace);
+  ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
+  CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
+}
+
+TEST(SerializeTest, emitAnonymousNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace { }", 1, /*Public=*/false, Infos);
+
+  NamespaceInfo *A = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedA(EmptySID);
+  CheckNamespaceInfo(&ExpectedA, A);
+}
+
+// Test serialization of record declarations.
+TEST(SerializeTest, emitRecordInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode(R"raw(class E {
+public:
+  E() {}
+protected:
+  void ProtectedMethod();
+};)raw", 3, /*Public=*/false, Infos);
+
+  RecordInfo *E = InfoAsRecord(Infos[0].get());
+  RecordInfo ExpectedE(EmptySID, "E");
+  ExpectedE.TagType = TagTypeKind::TTK_Class;
+  ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedE, E);
+
+  RecordInfo *RecordWithEConstructor = InfoAsRecord(Infos[1].get());
+  RecordInfo ExpectedRecordWithEConstructor(EmptySID);
+  FunctionInfo EConstructor;
+  EConstructor.Name = "E";
+  EConstructor.Parent = Reference(EmptySID, "E", InfoType::IT_record);
+  EConstructor.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  EConstructor.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  EConstructor.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  EConstructor.Access = AccessSpecifier::AS_public;
+  EConstructor.IsMethod = true;
+  ExpectedRecordWithEConstructor.ChildFunctions.emplace_back(
+      std::move(EConstructor));
+  CheckRecordInfo(&ExpectedRecordWithEConstructor, RecordWithEConstructor);
+
+  RecordInfo *RecordWithMethod = InfoAsRecord(Infos[2].get());
+  RecordInfo ExpectedRecordWithMethod(EmptySID);
+  FunctionInfo Method;
+  Method.Name = "ProtectedMethod";
+  Method.Parent = Reference(EmptySID, "E", InfoType::IT_record);
+  Method.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  Method.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
+  Method.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  Method.Access = AccessSpecifier::AS_protected;
+  Method.IsMethod = true;
+  ExpectedRecordWithMethod.ChildFunctions.emplace_back(std::move(Method));
+  CheckRecordInfo(&ExpectedRecordWithMethod, RecordWithMethod);
+}
+
+// Test serialization of enum declarations.
+TEST(SerializeTest, emitEnumInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("enum E { X, Y }; enum class G { A, B };", 2,
+                       /*Public=*/false, Infos);
+
+  NamespaceInfo *NamespaceWithEnum = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedNamespaceWithEnum(EmptySID);
+  EnumInfo E;
+  E.Name = "E";
+  E.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  E.Members.emplace_back("X");
+  E.Members.emplace_back("Y");
+  ExpectedNamespaceWithEnum.ChildEnums.emplace_back(std::move(E));
+  CheckNamespaceInfo(&ExpectedNamespaceWithEnum, NamespaceWithEnum);
+
+  NamespaceInfo *NamespaceWithScopedEnum = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedNamespaceWithScopedEnum(EmptySID);
+  EnumInfo G;
+  G.Name = "G";
+  G.Scoped = true;
+  G.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  G.Members.emplace_back("A");
+  G.Members.emplace_back("B");
+  ExpectedNamespaceWithScopedEnum.ChildEnums.emplace_back(std::move(G));
+  CheckNamespaceInfo(&ExpectedNamespaceWithScopedEnum, NamespaceWithScopedEnum);
+}
+
+TEST(SerializeTest, emitUndefinedRecordInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("class E;", 1, /*Public=*/false, Infos);
+
+  RecordInfo *E = InfoAsRecord(Infos[0].get());
+  RecordInfo ExpectedE(EmptySID, "E");
+  ExpectedE.TagType = TagTypeKind::TTK_Class;
+  ExpectedE.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedE, E);
+}
+
+TEST(SerializeTest, emitRecordMemberInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("struct E { int I; };", 1, /*Public=*/false, Infos);
+
+  RecordInfo *E = InfoAsRecord(Infos[0].get());
+  RecordInfo ExpectedE(EmptySID, "E");
+  ExpectedE.TagType = TagTypeKind::TTK_Struct;
+  ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedE.Members.emplace_back("int", "I", AccessSpecifier::AS_public);
+  CheckRecordInfo(&ExpectedE, E);
+}
+
+TEST(SerializeTest, emitInternalRecordInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("class E { class G {}; };", 2, /*Public=*/false, Infos);
+
+  RecordInfo *E = InfoAsRecord(Infos[0].get());
+  RecordInfo ExpectedE(EmptySID, "E");
+  ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedE.TagType = TagTypeKind::TTK_Class;
+  CheckRecordInfo(&ExpectedE, E);
+
+  RecordInfo *G = InfoAsRecord(Infos[1].get());
+  RecordInfo ExpectedG(EmptySID, "G");
+  ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedG.TagType = TagTypeKind::TTK_Class;
+  ExpectedG.Namespace.emplace_back(EmptySID, "E", InfoType::IT_record);
+  CheckRecordInfo(&ExpectedG, G);
+}
+
+TEST(SerializeTest, emitPublicAnonymousNamespaceInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("namespace { class A; }", 0, /*Public=*/true, Infos);
+}
+
+TEST(SerializeTest, emitPublicFunctionInternalInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("int F() { class G {}; return 0; };", 1, /*Public=*/true,
+                       Infos);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "F";
+  F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
+  F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
+  CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
+}
+
+TEST(SerializeTest, emitInlinedFunctionInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode("inline void F(int I) { };", 1, /*Public=*/true, Infos);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "F";
+  F.ReturnType = TypeInfo(EmptySID, "void", InfoType::IT_default);
+  F.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  F.Params.emplace_back("int", "I");
+  ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
+  CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
+}
+
+TEST(SerializeTest, emitInheritedRecordInfo) {
+  EmittedInfoList Infos;
+  ExtractInfosFromCode(
+      "class F {}; class G{} ; class E : public F, virtual private G {};", 3,
+      /*Public=*/false, Infos);
+
+  RecordInfo *F = InfoAsRecord(Infos[0].get());
+  RecordInfo ExpectedF(EmptySID, "F");
+  ExpectedF.TagType = TagTypeKind::TTK_Class;
+  ExpectedF.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedF, F);
+
+  RecordInfo *G = InfoAsRecord(Infos[1].get());
+  RecordInfo ExpectedG(EmptySID, "G");
+  ExpectedG.TagType = TagTypeKind::TTK_Class;
+  ExpectedG.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  CheckRecordInfo(&ExpectedG, G);
+
+  RecordInfo *E = InfoAsRecord(Infos[2].get());
+  RecordInfo ExpectedE(EmptySID, "E");
+  ExpectedE.Parents.emplace_back(EmptySID, "F", InfoType::IT_record);
+  ExpectedE.VirtualParents.emplace_back(EmptySID, "G", InfoType::IT_record);
+  ExpectedE.DefLoc = Location(0, llvm::SmallString<16>{"test.cpp"});
+  ExpectedE.TagType = TagTypeKind::TTK_Class;
+  CheckRecordInfo(&ExpectedE, E);
+}
+
+TEST(SerializeTest, emitModulePublicLFunctions) {
+  EmittedInfoList Infos;
+  std::vector<std::string> Args;
+  Args.push_back("-fmodules-ts");
+  ExtractInfosFromCodeWithArgs(R"raw(export module M;
+int moduleFunction(int x);
+static int staticModuleFunction(int x);
+export double exportedModuleFunction(double y);)raw",
+                               2, /*Public=*/true, Infos, Args);
+
+  NamespaceInfo *BWithFunction = InfoAsNamespace(Infos[0].get());
+  NamespaceInfo ExpectedBWithFunction(EmptySID);
+  FunctionInfo F;
+  F.Name = "moduleFunction";
+  F.ReturnType = TypeInfo(EmptySID, "int", InfoType::IT_default);
+  F.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
+  F.Params.emplace_back("int", "x");
+  ExpectedBWithFunction.ChildFunctions.emplace_back(std::move(F));
+  CheckNamespaceInfo(&ExpectedBWithFunction, BWithFunction);
+
+  NamespaceInfo *BWithExportedFunction = InfoAsNamespace(Infos[1].get());
+  NamespaceInfo ExpectedBWithExportedFunction(EmptySID);
+  FunctionInfo ExportedF;
+  ExportedF.Name = "exportedModuleFunction";
+  ExportedF.ReturnType = TypeInfo(EmptySID, "double", InfoType::IT_default);
+  ExportedF.Loc.emplace_back(0, llvm::SmallString<16>{"test.cpp"});
+  ExportedF.Params.emplace_back("double", "y");
+  ExpectedBWithExportedFunction.ChildFunctions.emplace_back(
+      std::move(ExportedF));
+  CheckNamespaceInfo(&ExpectedBWithExportedFunction, BWithExportedFunction);
+}
+
+} // namespace doc
+} // end namespace clang




More information about the cfe-commits mailing list