brintos

brintos / llvm-project-archived public Read only

0
0
Text · 25.1 KiB · 0827793 Raw
642 lines · cpp
1//===-- ClangMoveTests.cpp - clang-move unit tests ------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "Move.h"10#include "unittests/Tooling/RewriterTestContext.h"11#include "clang/Format/Format.h"12#include "clang/Frontend/FrontendActions.h"13#include "clang/Frontend/TextDiagnosticPrinter.h"14#include "clang/Rewrite/Core/Rewriter.h"15#include "clang/Tooling/Refactoring.h"16#include "clang/Tooling/Tooling.h"17#include "llvm/ADT/StringRef.h"18#include "gmock/gmock-matchers.h"19#include "gtest/gtest.h"20#include <string>21#include <vector>22 23namespace clang {24namespace move {25namespace {26 27const char TestHeader[] = "namespace a {\n"28                          "class C1; // test\n"29                          "template <typename T> class C2;\n"30                          "namespace b {\n"31                          "// This is a Foo class\n"32                          "// which is used in\n"33                          "// test.\n"34                          "class Foo {\n"35                          "public:\n"36                          "  void f();\n"37                          "\n"38                          "private:\n"39                          "  C1 *c1;\n"40                          "  static int b;\n"41                          "}; // abc\n"42                          "\n"43                          "class Foo2 {\n"44                          "public:\n"45                          "  int f();\n"46                          "};\n"47                          "} // namespace b\n"48                          "} // namespace a\n";49 50const char TestCC[] = "#include \"foo.h\"\n"51                      "namespace a {\n"52                      "namespace b {\n"53                      "namespace {\n"54                      "// comment1.\n"55                      "void f1() {}\n"56                      "/// comment2.\n"57                      "int kConstInt1 = 0;\n"58                      "} // namespace\n"59                      "\n"60                      "/* comment 3*/\n"61                      "static int kConstInt2 = 1;\n"62                      "\n"63                      "/** comment4\n"64                      " */\n"65                      "static int help() {\n"66                      "  int a = 0;\n"67                      "  return a;\n"68                      "}\n"69                      "\n"70                      "// comment5\n"71                      "// comment5\n"72                      "void Foo::f() {\n"73                      "  f1();\n"74                      "  kConstInt1;\n"75                      "  kConstInt2;\n"76                      "  help();\n"77                      "}\n"78                      "\n"79                      "/////////////\n"80                      "// comment //\n"81                      "/////////////\n"82                      "int Foo::b = 2;\n"83                      "int Foo2::f() {\n"84                      "  kConstInt1;\n"85                      "  kConstInt2;\n"86                      "  help();\n"87                      "  f1();\n"88                      "  return 1;\n"89                      "}\n"90                      "} // namespace b\n"91                      "} // namespace a\n";92 93const char ExpectedTestHeader[] = "namespace a {\n"94                                  "class C1; // test\n"95                                  "template <typename T> class C2;\n"96                                  "namespace b {\n"97                                  "\n"98                                  "class Foo2 {\n"99                                  "public:\n"100                                  "  int f();\n"101                                  "};\n"102                                  "} // namespace b\n"103                                  "} // namespace a\n";104 105const char ExpectedTestCC[] = "#include \"foo.h\"\n"106                              "namespace a {\n"107                              "namespace b {\n"108                              "namespace {\n"109                              "// comment1.\n"110                              "void f1() {}\n"111                              "/// comment2.\n"112                              "int kConstInt1 = 0;\n"113                              "} // namespace\n"114                              "\n"115                              "/* comment 3*/\n"116                              "static int kConstInt2 = 1;\n"117                              "\n"118                              "/** comment4\n"119                              " */\n"120                              "static int help() {\n"121                              "  int a = 0;\n"122                              "  return a;\n"123                              "}\n"124                              "\n"125                              "int Foo2::f() {\n"126                              "  kConstInt1;\n"127                              "  kConstInt2;\n"128                              "  help();\n"129                              "  f1();\n"130                              "  return 1;\n"131                              "}\n"132                              "} // namespace b\n"133                              "} // namespace a\n";134 135const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"136                                 "#define NEW_FOO_H\n"137                                 "\n"138                                 "namespace a {\n"139                                 "class C1; // test\n"140                                 "\n"141                                 "template <typename T> class C2;\n"142                                 "namespace b {\n"143                                 "// This is a Foo class\n"144                                 "// which is used in\n"145                                 "// test.\n"146                                 "class Foo {\n"147                                 "public:\n"148                                 "  void f();\n"149                                 "\n"150                                 "private:\n"151                                 "  C1 *c1;\n"152                                 "  static int b;\n"153                                 "}; // abc\n"154                                 "} // namespace b\n"155                                 "} // namespace a\n"156                                 "\n"157                                 "#endif // NEW_FOO_H\n";158 159const char ExpectedNewCC[] = "namespace a {\n"160                             "namespace b {\n"161                             "namespace {\n"162                             "// comment1.\n"163                             "void f1() {}\n"164                             "\n"165                             "/// comment2.\n"166                             "int kConstInt1 = 0;\n"167                             "} // namespace\n"168                             "\n"169                             "/* comment 3*/\n"170                             "static int kConstInt2 = 1;\n"171                             "\n"172                             "/** comment4\n"173                             " */\n"174                             "static int help() {\n"175                             "  int a = 0;\n"176                             "  return a;\n"177                             "}\n"178                             "\n"179                             "// comment5\n"180                             "// comment5\n"181                             "void Foo::f() {\n"182                             "  f1();\n"183                             "  kConstInt1;\n"184                             "  kConstInt2;\n"185                             "  help();\n"186                             "}\n"187                             "\n"188                             "/////////////\n"189                             "// comment //\n"190                             "/////////////\n"191                             "int Foo::b = 2;\n"192                             "} // namespace b\n"193                             "} // namespace a\n";194 195#ifdef _WIN32196const char WorkingDir[] = "C:\\test";197#else198const char WorkingDir[] = "/test";199#endif200 201const char TestHeaderName[] = "foo.h";202const char TestCCName[] = "foo.cc";203 204std::map<std::string, std::string>205runClangMoveOnCode(const move::MoveDefinitionSpec &Spec,206                   const char *const Header = TestHeader,207                   const char *const CC = TestCC,208                   DeclarationReporter *const Reporter = nullptr) {209  clang::RewriterTestContext Context;210 211  llvm::SmallString<16> Dir(WorkingDir);212  llvm::sys::path::native(Dir);213  Context.InMemoryFileSystem->setCurrentWorkingDirectory(Dir);214 215  std::map<llvm::StringRef, clang::FileID> FileToFileID;216 217  auto CreateFiles = [&Context, &FileToFileID](llvm::StringRef Name,218                                               llvm::StringRef Code) {219    if (!Name.empty()) {220      FileToFileID[Name] = Context.createInMemoryFile(Name, Code);221    }222  };223  CreateFiles(Spec.NewCC, "");224  CreateFiles(Spec.NewHeader, "");225  CreateFiles(TestHeaderName, Header);226  CreateFiles(TestCCName, CC);227 228  std::map<std::string, tooling::Replacements> FileToReplacements;229  ClangMoveContext MoveContext = {Spec, FileToReplacements, Dir.c_str(), "LLVM",230                                  Reporter != nullptr};231 232  auto Factory = std::make_unique<clang::move::ClangMoveActionFactory>(233      &MoveContext, Reporter);234 235  tooling::runToolOnCodeWithArgs(236      Factory->create(), CC, Context.InMemoryFileSystem,237      {"-std=c++11", "-fparse-all-comments", "-I."}, TestCCName, "clang-move",238      std::make_shared<PCHContainerOperations>());239  formatAndApplyAllReplacements(FileToReplacements, Context.Rewrite, "llvm");240  // The Key is file name, value is the new code after moving the class.241  std::map<std::string, std::string> Results;242  for (const auto &It : FileToReplacements) {243    // The path may come out as "./foo.h", normalize to "foo.h".244    SmallString<32> FilePath (It.first);245    llvm::sys::path::remove_dots(FilePath);246    Results[FilePath.str().str()] = Context.getRewrittenText(FileToFileID[FilePath]);247  }248  return Results;249}250 251TEST(ClangMove, MoveHeaderAndCC) {252  move::MoveDefinitionSpec Spec;253  Spec.Names = {std::string("a::b::Foo")};254  Spec.OldHeader = "foo.h";255  Spec.OldCC = "foo.cc";256  Spec.NewHeader = "new_foo.h";257  Spec.NewCC = "new_foo.cc";258  std::string ExpectedHeader = "#include \"" + Spec.NewHeader + "\"\n\n";259  auto Results = runClangMoveOnCode(Spec);260  EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);261  EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);262  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);263  EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);264}265 266TEST(ClangMove, MoveHeaderOnly) {267  move::MoveDefinitionSpec Spec;268  Spec.Names = {std::string("a::b::Foo")};269  Spec.OldHeader = "foo.h";270  Spec.NewHeader = "new_foo.h";271  auto Results = runClangMoveOnCode(Spec);272  EXPECT_EQ(2u, Results.size());273  EXPECT_EQ(ExpectedTestHeader, Results[Spec.OldHeader]);274  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);275}276 277TEST(ClangMove, MoveCCOnly) {278  move::MoveDefinitionSpec Spec;279  Spec.Names = {std::string("a::b::Foo")};280  Spec.OldCC = "foo.cc";281  Spec.NewCC = "new_foo.cc";282  std::string ExpectedHeader = "#include \"foo.h\"\n\n";283  auto Results = runClangMoveOnCode(Spec);284  EXPECT_EQ(2u, Results.size());285  EXPECT_EQ(ExpectedTestCC, Results[Spec.OldCC]);286  EXPECT_EQ(ExpectedHeader + ExpectedNewCC, Results[Spec.NewCC]);287}288 289TEST(ClangMove, MoveNonExistClass) {290  move::MoveDefinitionSpec Spec;291  Spec.Names = {std::string("NonExistFoo")};292  Spec.OldHeader = "foo.h";293  Spec.OldCC = "foo.cc";294  Spec.NewHeader = "new_foo.h";295  Spec.NewCC = "new_foo.cc";296  auto Results = runClangMoveOnCode(Spec);297  EXPECT_EQ(0u, Results.size());298}299 300TEST(ClangMove, HeaderIncludeSelf) {301  move::MoveDefinitionSpec Spec;302  Spec.Names = {std::string("Foo")};303  Spec.OldHeader = "foo.h";304  Spec.OldCC = "foo.cc";305  Spec.NewHeader = "new_foo.h";306  Spec.NewCC = "new_foo.cc";307 308  const char TestHeader[] = "#ifndef FOO_H\n"309                            "#define FOO_H\n"310                            "#include \"foo.h\"\n"311                            "class Foo {};\n"312                            "#endif\n";313  const char TestCode[] = "#include \"foo.h\"";314  const char ExpectedNewHeader[] = "#ifndef FOO_H\n"315                                   "#define FOO_H\n"316                                   "#include \"new_foo.h\"\n"317                                   "class Foo {};\n"318                                   "#endif\n";319  const char ExpectedNewCC[] = "#include \"new_foo.h\"";320  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);321  EXPECT_EQ("", Results[Spec.OldHeader]);322  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);323  EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);324}325 326TEST(ClangMove, MoveAll) {327  std::vector<std::string> TestHeaders = {328    "class A {\npublic:\n  int f();\n};",329    // forward declaration.330    "class B;\nclass A {\npublic:\n  int f();\n};",331    // template forward declaration.332    "template <typename T> class B;\nclass A {\npublic:\n  int f();\n};",333    "namespace a {}\nclass A {\npublic:\n  int f();\n};",334    "namespace a {}\nusing namespace a;\nclass A {\npublic:\n  int f();\n};",335  };336  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";337  move::MoveDefinitionSpec Spec;338  Spec.Names.push_back("A");339  Spec.OldHeader = "foo.h";340  Spec.OldCC = "foo.cc";341  Spec.NewHeader = "new_foo.h";342  Spec.NewCC = "new_foo.cc";343  for (const auto& Header : TestHeaders) {344    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);345    EXPECT_EQ(Header, Results[Spec.NewHeader]);346    EXPECT_EQ("", Results[Spec.OldHeader]);347    EXPECT_EQ("", Results[Spec.OldCC]);348  }349}350 351TEST(ClangMove, MoveAllMultipleClasses) {352  move::MoveDefinitionSpec Spec;353  std::vector<std::string> TestHeaders = {354    "class C;\nclass A {\npublic:\n  int f();\n};\nclass B {};",355    "class C;\nclass B;\nclass A {\npublic:\n  int f();\n};\nclass B {};",356  };357  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";358  Spec.Names = {std::string("A"), std::string("B")};359  Spec.OldHeader = "foo.h";360  Spec.OldCC = "foo.cc";361  Spec.NewHeader = "new_foo.h";362  Spec.NewCC = "new_foo.cc";363  for (const auto& Header : TestHeaders) {364    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);365    EXPECT_EQ(Header, Results[Spec.NewHeader]);366    EXPECT_EQ("", Results[Spec.OldHeader]);367    EXPECT_EQ("", Results[Spec.OldCC]);368  }369}370 371TEST(ClangMove, DontMoveAll) {372  const char ExpectedHeader[] = "#ifndef NEW_FOO_H\n"373                                "#define NEW_FOO_H\n"374                                "\n"375                                "class A {\npublic:\n  int f();\n};\n"376                                "\n"377                                "#endif // NEW_FOO_H\n";378  const char Code[] = "#include \"foo.h\"\nint A::f() { return 0; }";379  std::vector<std::string> TestHeaders = {380    "class B {};\nclass A {\npublic:\n  int f();\n};\n",381    "void f() {};\nclass A {\npublic:\n  int f();\n};\n",382  };383  move::MoveDefinitionSpec Spec;384  Spec.Names.push_back("A");385  Spec.OldHeader = "foo.h";386  Spec.OldCC = "foo.cc";387  Spec.NewHeader = "new_foo.h";388  Spec.NewCC = "new_foo.cc";389  for (const auto& Header : TestHeaders) {390    auto Results = runClangMoveOnCode(Spec, Header.c_str(), Code);391    EXPECT_EQ(ExpectedHeader, Results[Spec.NewHeader]);392    // The expected old header should not contain class A definition.393    std::string ExpectedOldHeader = Header.substr(0, Header.size() - 32);394    EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);395  }396}397 398TEST(ClangMove, IgnoreMacroSymbolsAndMoveAll) {399  const char TestCode[] = "#include \"foo.h\"";400  std::vector<std::string> TestHeaders = {401    "#define DEFINE_Foo int Foo = 1;\nDEFINE_Foo;\nclass Bar {};\n",402    "#define DEFINE(x) int var_##x = 1;\nDEFINE(foo);\nclass Bar {};\n",403  };404  move::MoveDefinitionSpec Spec;405  Spec.Names.push_back("Bar");406  Spec.OldHeader = "foo.h";407  Spec.OldCC = "foo.cc";408  Spec.NewHeader = "new_foo.h";409  Spec.NewCC = "new_foo.cc";410 411  for (const auto& Header : TestHeaders) {412    auto Results = runClangMoveOnCode(Spec, Header.c_str(), TestCode);413    EXPECT_EQ("", Results[Spec.OldHeader]);414    EXPECT_EQ(Header, Results[Spec.NewHeader]);415  }416}417 418TEST(ClangMove, MacroInFunction) {419  const char TestHeader[] = "#define INT int\n"420                            "class A {\npublic:\n  int f();\n};\n"421                            "class B {};\n";422  const char TestCode[] = "#include \"foo.h\"\n"423                          "INT A::f() { return 0; }\n";424  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"425                                 "INT A::f() { return 0; }\n";426  move::MoveDefinitionSpec Spec;427  Spec.Names.push_back("A");428  Spec.OldHeader = "foo.h";429  Spec.OldCC = "foo.cc";430  Spec.NewHeader = "new_foo.h";431  Spec.NewCC = "new_foo.cc";432  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);433  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);434}435 436TEST(ClangMove, DefinitionInMacro) {437  const char TestHeader[] = "#define DEF(CLASS) void CLASS##_::f() {}\n"438                            "#define DEF2(CLASS, ...) void CLASS##_::f2() {}\n"439                            "class A_ {\nvoid f();\nvoid f2();\n};\n"440                            "class B {};\n";441  const char TestCode[] = "#include \"foo.h\"\n"442                          "DEF(A)\n\n"443                          "DEF2(A,\n"444                          "     123)\n";445  const char ExpectedNewCode[] = "#include \"new_foo.h\"\n\n"446                                 "DEF(A)\n\n"447                                 "DEF2(A, 123)\n";448  move::MoveDefinitionSpec Spec;449  Spec.Names.push_back("A_");450  Spec.OldHeader = "foo.h";451  Spec.OldCC = "foo.cc";452  Spec.NewHeader = "new_foo.h";453  Spec.NewCC = "new_foo.cc";454  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);455  EXPECT_EQ(ExpectedNewCode, Results[Spec.NewCC]);456}457 458TEST(ClangMove, WellFormattedCode) {459  const std::string CommonHeader =460      "namespace a {\n"461      "namespace b {\n"462      "namespace c {\n"463      "class C;\n"464      "\n"465      "class A {\npublic:\n  void f();\n  void f2();\n};\n"466      "} // namespace c\n"467      "} // namespace b\n"468      "\n"469      "namespace d {\n"470      "namespace e {\n"471      "class B {\npublic:\n  void f();\n};\n"472      "} // namespace e\n"473      "} // namespace d\n"474      "} // namespace a\n";475  const std::string CommonCode = "\n"476                                 "namespace a {\n"477                                 "namespace b {\n"478                                 "namespace c {\n"479                                 "void A::f() {}\n"480                                 "\n"481                                 "void A::f2() {}\n"482                                 "} // namespace c\n"483                                 "} // namespace b\n"484                                 "\n"485                                 "namespace d {\n"486                                 "namespace e {\n"487                                 "void B::f() {}\n"488                                 "} // namespace e\n"489                                 "} // namespace d\n"490                                 "} // namespace a\n";491  // Add dummy class to prevent behavior of moving all declarations from header.492  const std::string TestHeader = CommonHeader + "class D {};\n";493  const std::string TestCode = "#include \"foo.h\"\n" + CommonCode;494  const std::string ExpectedNewHeader = "#ifndef NEW_FOO_H\n"495                                        "#define NEW_FOO_H\n"496                                        "\n" +497                                        CommonHeader +498                                        "\n"499                                        "#endif // NEW_FOO_H\n";500  const std::string ExpectedNewCC = "#include \"new_foo.h\"\n" + CommonCode;501  move::MoveDefinitionSpec Spec;502  Spec.Names.push_back("a::b::c::A");503  Spec.Names.push_back("a::d::e::B");504  Spec.OldHeader = "foo.h";505  Spec.OldCC = "foo.cc";506  Spec.NewHeader = "new_foo.h";507  Spec.NewCC = "new_foo.cc";508  auto Results = runClangMoveOnCode(Spec, TestHeader.c_str(), TestCode.c_str());509  EXPECT_EQ(ExpectedNewCC, Results[Spec.NewCC]);510  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);511}512 513TEST(ClangMove, AddDependentNewHeader) {514  const char TestHeader[] = "class A {};\n"515                            "class B {};\n";516  const char TestCode[] = "#include \"foo.h\"\n";517  const char ExpectedOldHeader[] = "#include \"new_foo.h\"\nclass B {};\n";518  const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"519                                   "#define NEW_FOO_H\n"520                                   "\n"521                                   "class A {};\n"522                                   "\n"523                                   "#endif // NEW_FOO_H\n";524  move::MoveDefinitionSpec Spec;525  Spec.Names.push_back("A");526  Spec.OldHeader = "foo.h";527  Spec.OldCC = "foo.cc";528  Spec.NewHeader = "new_foo.h";529  Spec.NewCC = "new_foo.cc";530  Spec.OldDependOnNew = true;531  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);532  EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);533  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);534}535 536TEST(ClangMove, AddDependentOldHeader) {537  const char TestHeader[] = "class A {};\n"538                            "class B {};\n";539  const char TestCode[] = "#include \"foo.h\"\n";540  const char ExpectedNewHeader[] = "#ifndef NEW_FOO_H\n"541                                   "#define NEW_FOO_H\n"542                                   "\n"543                                   "#include \"foo.h\"\n"544                                   "\n"545                                   "class B {};\n"546                                   "\n"547                                   "#endif // NEW_FOO_H\n";548  const char ExpectedOldHeader[] = "class A {};\n";549  move::MoveDefinitionSpec Spec;550  Spec.Names.push_back("B");551  Spec.OldHeader = "foo.h";552  Spec.OldCC = "foo.cc";553  Spec.NewHeader = "new_foo.h";554  Spec.NewCC = "new_foo.cc";555  Spec.NewDependOnOld = true;556  auto Results = runClangMoveOnCode(Spec, TestHeader, TestCode);557  EXPECT_EQ(ExpectedNewHeader, Results[Spec.NewHeader]);558  EXPECT_EQ(ExpectedOldHeader, Results[Spec.OldHeader]);559}560 561TEST(ClangMove, DumpDecls) {562  const char TestHeader[] = "template <typename T>\n"563                            "class A {\n"564                            " public:\n"565                            "  void f();\n"566                            "  template <typename U> void h();\n"567                            "  static int b;\n"568                            "};\n"569                            "\n"570                            "template <typename T> void A<T>::f() {}\n"571                            "\n"572                            "template <typename T>\n"573                            "template <typename U>\n"574                            "void A<T>::h() {}\n"575                            "\n"576                            "template <typename T> int A<T>::b = 2;\n"577                            "\n"578                            "template <> class A<int> {};\n"579                            "\n"580                            "class B {};\n"581                            "\n"582                            "namespace a {\n"583                            "class Move1 {};\n"584                            "void f1() {}\n"585                            "template <typename T>"586                            "void f2(T t);\n"587                            "} // namespace a\n"588                            "\n"589                            "class ForwardClass;\n"590                            "namespace a {\n"591                            "namespace b {\n"592                            "class Move1 { public : void f(); };\n"593                            "void f() {}\n"594                            "enum E1 { Green };\n"595                            "enum class E2 { Red };\n"596                            "typedef int Int2;\n"597                            "typedef A<double> A_d;"598                            "using Int = int;\n"599                            "template <typename T>\n"600                            "using AA = A<T>;\n"601                            "extern int kGlobalInt;\n"602                            "extern const char* const kGlobalStr;\n"603                            "} // namespace b\n"604                            "} // namespace a\n"605                            "#define DEFINE_FOO class Foo {};\n"606                            "DEFINE_FOO\n";607  const char TestCode[] = "#include \"foo.h\"\n";608  move::MoveDefinitionSpec Spec;609  Spec.Names.push_back("B");610  Spec.OldHeader = "foo.h";611  Spec.OldCC = "foo.cc";612  Spec.NewHeader = "new_foo.h";613  Spec.NewCC = "new_foo.cc";614  DeclarationReporter Reporter;615  std::vector<DeclarationReporter::Declaration> ExpectedDeclarations = {616      {"A", "Class", true},617      {"B", "Class", false},618      {"a::Move1", "Class", false},619      {"a::f1", "Function", false},620      {"a::f2", "Function", true},621      {"a::b::Move1", "Class", false},622      {"a::b::f", "Function", false},623      {"a::b::E1", "Enum", false},624      {"a::b::E2", "Enum", false},625      {"a::b::Int2", "TypeAlias", false},626      {"a::b::A_d", "TypeAlias", false},627      {"a::b::Int", "TypeAlias", false},628      {"a::b::AA", "TypeAlias", true},629      {"a::b::kGlobalInt", "Variable", false},630      {"a::b::kGlobalStr", "Variable", false}};631  runClangMoveOnCode(Spec, TestHeader, TestCode, &Reporter);632  std::vector<DeclarationReporter::Declaration> Results;633  for (const auto &DelPair : Reporter.getDeclarationList())634    Results.push_back(DelPair);635  EXPECT_THAT(ExpectedDeclarations,636              testing::UnorderedElementsAreArray(Results));637}638 639} // namespace640} // namespace move641} // namespace clang642