llvm-project

Форк
0
162 строки · 5.1 Кб
1
//===-- StdLibTests.cpp -----------------------------------------*- C++ -*-===//
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-exception
6
//
7
//===----------------------------------------------------------------------===//
8

9
#include "Annotations.h"
10
#include "ClangdServer.h"
11
#include "CodeComplete.h"
12
#include "Compiler.h"
13
#include "Config.h"
14
#include "SyncAPI.h"
15
#include "TestFS.h"
16
#include "index/StdLib.h"
17
#include "clang/Basic/LangOptions.h"
18
#include "clang/Basic/SourceManager.h"
19
#include "gmock/gmock.h"
20
#include "gtest/gtest.h"
21
#include <memory>
22

23
using namespace testing;
24

25
namespace clang {
26
namespace clangd {
27
namespace {
28

29
// Check the generated header sources contains usual standard library headers.
30
TEST(StdLibTests, getStdlibUmbrellaHeader) {
31
  LangOptions LO;
32
  LO.CPlusPlus = true;
33

34
  auto CXX = getStdlibUmbrellaHeader(LO).str();
35
  EXPECT_THAT(CXX, HasSubstr("#include <string>"));
36
  EXPECT_THAT(CXX, HasSubstr("#include <cstdio>"));
37
  EXPECT_THAT(CXX, Not(HasSubstr("#include <ios646.h>")));
38

39
  LO.CPlusPlus = false;
40
  auto C = getStdlibUmbrellaHeader(LO).str();
41
  EXPECT_THAT(C, Not(HasSubstr("#include <string>")));
42
  EXPECT_THAT(C, Not(HasSubstr("#include <cstdio>")));
43
  EXPECT_THAT(C, HasSubstr("#include <stdio.h>"));
44
}
45

46
MATCHER_P(Named, Name, "") { return arg.Name == Name; }
47

48
// Build an index, and check if it contains the right symbols.
49
TEST(StdLibTests, indexStandardLibrary) {
50
  MockFS FS;
51
  FS.Files["std/foo.h"] = R"cpp(
52
  #include <platform_stuff.h>
53
  #if __cplusplus >= 201703L
54
    int foo17();
55
  #elif __cplusplus >= 201402L
56
    int foo14();
57
  #else
58
    bool foo98();
59
  #endif
60
  )cpp";
61
  FS.Files["nonstd/platform_stuff.h"] = "int magic = 42;";
62

63
  ParseInputs OriginalInputs;
64
  OriginalInputs.TFS = &FS;
65
  OriginalInputs.CompileCommand.Filename = testPath("main.cc");
66
  OriginalInputs.CompileCommand.CommandLine = {"clang++", testPath("main.cc"),
67
                                               "-isystemstd/",
68
                                               "-isystemnonstd/", "-std=c++14"};
69
  OriginalInputs.CompileCommand.Directory = testRoot();
70
  IgnoreDiagnostics Diags;
71
  auto CI = buildCompilerInvocation(OriginalInputs, Diags);
72
  ASSERT_TRUE(CI);
73

74
  StdLibLocation Loc;
75
  Loc.Paths.push_back(testPath("std/"));
76

77
  auto Symbols =
78
      indexStandardLibrary("#include <foo.h>", std::move(CI), Loc, FS);
79
  EXPECT_THAT(Symbols, ElementsAre(Named("foo14")));
80
}
81

82
TEST(StdLibTests, StdLibSet) {
83
  StdLibSet Set;
84
  MockFS FS;
85
  FS.Files["std/_"] = "";
86
  FS.Files["libc/_"] = "";
87

88
  auto Add = [&](const LangOptions &LO,
89
                 std::vector<llvm::StringRef> SearchPath) {
90
    SourceManagerForFile SM("scratch", "");
91
    SM.get().getFileManager().setVirtualFileSystem(FS.view(std::nullopt));
92
    HeaderSearch HS(/*HSOpts=*/nullptr, SM.get(), SM.get().getDiagnostics(), LO,
93
                    /*Target=*/nullptr);
94
    for (auto P : SearchPath)
95
      HS.AddSearchPath(
96
          DirectoryLookup(
97
              cantFail(SM.get().getFileManager().getDirectoryRef(testPath(P))),
98
              SrcMgr::C_System, /*isFramework=*/false),
99
          true);
100
    return Set.add(LO, HS);
101
  };
102

103
  Config Cfg;
104
  Cfg.Index.StandardLibrary = false;
105
  WithContextValue Disabled(Config::Key, std::move(Cfg));
106

107
  LangOptions LO;
108
  LO.CPlusPlus = true;
109
  EXPECT_FALSE(Add(LO, {"std"})) << "Disabled in config";
110

111
  Cfg = Config();
112
  Cfg.Index.StandardLibrary = true;
113
  WithContextValue Enabled(Config::Key, std::move(Cfg));
114

115
  EXPECT_FALSE(Add(LO, {"std"})) << "No <vector> found";
116
  FS.Files["std/vector"] = "class vector;";
117
  EXPECT_TRUE(Add(LO, {"std"})) << "Indexing as C++98";
118
  EXPECT_FALSE(Add(LO, {"std"})) << "Don't reindex";
119
  LO.CPlusPlus11 = true;
120
  EXPECT_TRUE(Add(LO, {"std"})) << "Indexing as C++11";
121
  LO.CPlusPlus = false;
122
  EXPECT_FALSE(Add(LO, {"libc"})) << "No <stdio.h>";
123
  FS.Files["libc/stdio.h"] = true;
124
  EXPECT_TRUE(Add(LO, {"libc"})) << "Indexing as C";
125
}
126

127
MATCHER_P(StdlibSymbol, Name, "") {
128
  return arg.Name == Name && arg.Includes.size() == 1 &&
129
         llvm::StringRef(arg.Includes.front().Header).starts_with("<");
130
}
131

132
TEST(StdLibTests, EndToEnd) {
133
  Config Cfg;
134
  Cfg.Index.StandardLibrary = true;
135
  WithContextValue Enabled(Config::Key, std::move(Cfg));
136

137
  MockFS FS;
138
  FS.Files["stdlib/vector"] =
139
      "namespace std { template <class> class vector; }";
140
  FS.Files["stdlib/list"] =
141
      " namespace std { template <typename T> class list; }";
142
  MockCompilationDatabase CDB;
143
  CDB.ExtraClangFlags.push_back("-isystem" + testPath("stdlib"));
144
  ClangdServer::Options Opts = ClangdServer::optsForTest();
145
  Opts.BuildDynamicSymbolIndex = true; // also used for stdlib index
146
  ClangdServer Server(CDB, FS, Opts);
147

148
  Annotations A("std::^");
149

150
  Server.addDocument(testPath("foo.cc"), A.code());
151
  ASSERT_TRUE(Server.blockUntilIdleForTest());
152
  clangd::CodeCompleteOptions CCOpts;
153
  auto Completions =
154
      cantFail(runCodeComplete(Server, testPath("foo.cc"), A.point(), CCOpts));
155
  EXPECT_THAT(
156
      Completions.Completions,
157
      UnorderedElementsAre(StdlibSymbol("list"), StdlibSymbol("vector")));
158
}
159

160
} // namespace
161
} // namespace clangd
162
} // namespace clang
163

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.