llvm-project

Форк
0
215 строк · 6.8 Кб
1
//===-- ConfigProviderTests.cpp -------------------------------------------===//
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 "Config.h"
10
#include "ConfigProvider.h"
11
#include "ConfigTesting.h"
12
#include "TestFS.h"
13
#include "llvm/Support/Path.h"
14
#include "llvm/Support/SourceMgr.h"
15
#include "gmock/gmock.h"
16
#include "gtest/gtest.h"
17
#include <atomic>
18
#include <chrono>
19

20
namespace clang {
21
namespace clangd {
22
namespace config {
23
namespace {
24
using ::testing::ElementsAre;
25
using ::testing::IsEmpty;
26

27
// Provider that appends an arg to compile flags.
28
// The arg is prefix<N>, where N is the times getFragments() was called.
29
// It also yields a diagnostic each time it's called.
30
class FakeProvider : public Provider {
31
  std::string Prefix;
32
  mutable std::atomic<unsigned> Index = {0};
33

34
  std::vector<CompiledFragment>
35
  getFragments(const Params &, DiagnosticCallback DC) const override {
36
    DC(llvm::SMDiagnostic("", llvm::SourceMgr::DK_Error, Prefix));
37
    CompiledFragment F =
38
        [Arg(Prefix + std::to_string(++Index))](const Params &P, Config &C) {
39
          C.CompileFlags.Edits.push_back(
40
              [Arg](std::vector<std::string> &Argv) { Argv.push_back(Arg); });
41
          return true;
42
        };
43
    return {F};
44
  }
45

46
public:
47
  FakeProvider(llvm::StringRef Prefix) : Prefix(Prefix) {}
48
};
49

50
std::vector<std::string> getAddedArgs(Config &C) {
51
  std::vector<std::string> Argv;
52
  for (auto &Edit : C.CompileFlags.Edits)
53
    Edit(Argv);
54
  return Argv;
55
}
56

57
// The provider from combine() should invoke its providers in order, and not
58
// cache their results.
59
TEST(ProviderTest, Combine) {
60
  CapturedDiags Diags;
61
  FakeProvider Foo("foo");
62
  FakeProvider Bar("bar");
63
  auto Combined = Provider::combine({&Foo, &Bar});
64
  Config Cfg = Combined->getConfig(Params(), Diags.callback());
65
  EXPECT_THAT(Diags.Diagnostics,
66
              ElementsAre(diagMessage("foo"), diagMessage("bar")));
67
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo1", "bar1"));
68
  Diags.Diagnostics.clear();
69

70
  Cfg = Combined->getConfig(Params(), Diags.callback());
71
  EXPECT_THAT(Diags.Diagnostics,
72
              ElementsAre(diagMessage("foo"), diagMessage("bar")));
73
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo2", "bar2"));
74
}
75

76
const char *AddFooWithErr = R"yaml(
77
CompileFlags:
78
  Add: foo
79
  Unknown: 42
80
)yaml";
81

82
const char *AddFooWithTypoErr = R"yaml(
83
CompileFlags:
84
  Add: foo
85
  Removr: 42
86
)yaml";
87

88
const char *AddBarBaz = R"yaml(
89
CompileFlags:
90
  Add: bar
91
---
92
CompileFlags:
93
  Add: baz
94
)yaml";
95

96
TEST(ProviderTest, FromYAMLFile) {
97
  MockFS FS;
98
  FS.Files["foo.yaml"] = AddFooWithErr;
99

100
  CapturedDiags Diags;
101
  auto P = Provider::fromYAMLFile(testPath("foo.yaml"), /*Directory=*/"", FS);
102
  auto Cfg = P->getConfig(Params(), Diags.callback());
103
  EXPECT_THAT(Diags.Diagnostics,
104
              ElementsAre(diagMessage("Unknown CompileFlags key 'Unknown'")));
105
  EXPECT_THAT(Diags.Files, ElementsAre(testPath("foo.yaml")));
106
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo"));
107
  Diags.clear();
108

109
  Cfg = P->getConfig(Params(), Diags.callback());
110
  EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Cached, not re-parsed";
111
  EXPECT_THAT(Diags.Files, IsEmpty());
112
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo"));
113

114
  FS.Files["foo.yaml"] = AddFooWithTypoErr;
115
  Cfg = P->getConfig(Params(), Diags.callback());
116
  EXPECT_THAT(
117
      Diags.Diagnostics,
118
      ElementsAre(diagMessage(
119
          "Unknown CompileFlags key 'Removr'; did you mean 'Remove'?")));
120
  EXPECT_THAT(Diags.Files, ElementsAre(testPath("foo.yaml")));
121
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo"));
122
  Diags.clear();
123

124
  FS.Files["foo.yaml"] = AddBarBaz;
125
  Cfg = P->getConfig(Params(), Diags.callback());
126
  EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "New config, no errors";
127
  EXPECT_THAT(Diags.Files, ElementsAre(testPath("foo.yaml")));
128
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz"));
129
  Diags.clear();
130

131
  FS.Files.erase("foo.yaml");
132
  Cfg = P->getConfig(Params(), Diags.callback());
133
  EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Missing file is not an error";
134
  EXPECT_THAT(Diags.Files, IsEmpty());
135
  EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
136
}
137

138
TEST(ProviderTest, FromAncestorRelativeYAMLFiles) {
139
  MockFS FS;
140
  FS.Files["a/b/c/foo.yaml"] = AddBarBaz;
141
  FS.Files["a/foo.yaml"] = AddFooWithErr;
142

143
  std::string ABCPath =
144
      testPath("a/b/c/d/test.cc", llvm::sys::path::Style::posix);
145
  Params ABCParams;
146
  ABCParams.Path = ABCPath;
147
  std::string APath =
148
      testPath("a/b/e/f/test.cc", llvm::sys::path::Style::posix);
149
  Params AParams;
150
  AParams.Path = APath;
151

152
  CapturedDiags Diags;
153
  auto P = Provider::fromAncestorRelativeYAMLFiles("foo.yaml", FS);
154

155
  auto Cfg = P->getConfig(Params(), Diags.callback());
156
  EXPECT_THAT(Diags.Diagnostics, IsEmpty());
157
  EXPECT_THAT(Diags.Files, IsEmpty());
158
  EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
159

160
  Cfg = P->getConfig(ABCParams, Diags.callback());
161
  EXPECT_THAT(Diags.Diagnostics,
162
              ElementsAre(diagMessage("Unknown CompileFlags key 'Unknown'")));
163
  // FIXME: fails on windows: paths have mixed slashes like C:\a/b\c.yaml
164
  EXPECT_THAT(Diags.Files,
165
              ElementsAre(testPath("a/foo.yaml"), testPath("a/b/c/foo.yaml")));
166
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo", "bar", "baz"));
167
  Diags.clear();
168

169
  Cfg = P->getConfig(AParams, Diags.callback());
170
  EXPECT_THAT(Diags.Diagnostics, IsEmpty()) << "Cached config";
171
  EXPECT_THAT(Diags.Files, IsEmpty());
172
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("foo"));
173

174
  FS.Files.erase("a/foo.yaml");
175
  Cfg = P->getConfig(ABCParams, Diags.callback());
176
  EXPECT_THAT(Diags.Diagnostics, IsEmpty());
177
  EXPECT_THAT(Diags.Files, IsEmpty());
178
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar", "baz"));
179
}
180

181
TEST(ProviderTest, SourceInfo) {
182
  MockFS FS;
183

184
  FS.Files["baz/foo.yaml"] = R"yaml(
185
If:
186
  PathMatch: .*
187
  PathExclude: bar.h
188
CompileFlags:
189
  Add: bar
190
)yaml";
191
  const auto BarPath = testPath("baz/bar.h", llvm::sys::path::Style::posix);
192
  CapturedDiags Diags;
193
  Params Bar;
194
  Bar.Path = BarPath;
195

196
  // This should be an absolute match/exclude hence baz/bar.h should not be
197
  // excluded.
198
  auto P =
199
      Provider::fromYAMLFile(testPath("baz/foo.yaml"), /*Directory=*/"", FS);
200
  auto Cfg = P->getConfig(Bar, Diags.callback());
201
  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
202
  EXPECT_THAT(getAddedArgs(Cfg), ElementsAre("bar"));
203
  Diags.clear();
204

205
  // This should be a relative match/exclude hence baz/bar.h should be excluded.
206
  P = Provider::fromAncestorRelativeYAMLFiles("foo.yaml", FS);
207
  Cfg = P->getConfig(Bar, Diags.callback());
208
  ASSERT_THAT(Diags.Diagnostics, IsEmpty());
209
  EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
210
  Diags.clear();
211
}
212
} // namespace
213
} // namespace config
214
} // namespace clangd
215
} // namespace clang
216

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

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

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

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