[mlir] Update Ch-2.md (#121379)
[llvm-project.git] / clang-tools-extra / clangd / unittests / ConfigCompileTests.cpp
blob179960a02cadece3a7ca3250355fc69f9c965d6c
1 //===-- ConfigCompileTests.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 //===----------------------------------------------------------------------===//
9 #include "Config.h"
10 #include "ConfigFragment.h"
11 #include "ConfigTesting.h"
12 #include "Diagnostics.h"
13 #include "Feature.h"
14 #include "TestFS.h"
15 #include "clang/Basic/DiagnosticSema.h"
16 #include "llvm/ADT/StringRef.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/SourceMgr.h"
19 #include "gmock/gmock.h"
20 #include "gtest/gtest.h"
21 #include <optional>
22 #include <string>
24 namespace clang {
25 namespace clangd {
26 namespace config {
27 namespace {
28 using ::testing::AllOf;
29 using ::testing::Contains;
30 using ::testing::ElementsAre;
31 using ::testing::IsEmpty;
32 using ::testing::SizeIs;
33 using ::testing::StartsWith;
34 using ::testing::UnorderedElementsAre;
36 class ConfigCompileTests : public ::testing::Test {
37 protected:
38 CapturedDiags Diags;
39 Config Conf;
40 Fragment Frag;
41 Params Parm;
43 bool compileAndApply() {
44 Conf = Config();
45 Diags.Diagnostics.clear();
46 auto Compiled = std::move(Frag).compile(Diags.callback());
47 return Compiled(Parm, Conf);
51 TEST_F(ConfigCompileTests, Condition) {
52 // No condition.
53 Frag = {};
54 Frag.CompileFlags.Add.emplace_back("X");
55 EXPECT_TRUE(compileAndApply()) << "Empty config";
56 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
57 EXPECT_THAT(Conf.CompileFlags.Edits, SizeIs(1));
59 // Regex with no file.
60 Frag = {};
61 Frag.If.PathMatch.emplace_back("fo*");
62 EXPECT_FALSE(compileAndApply());
63 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
64 EXPECT_THAT(Conf.CompileFlags.Edits, SizeIs(0));
66 // Following tests have a file path set.
67 Parm.Path = "bar";
69 // Non-matching regex.
70 Frag = {};
71 Frag.If.PathMatch.emplace_back("fo*");
72 EXPECT_FALSE(compileAndApply());
73 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
75 // Matching regex.
76 Frag = {};
77 Frag.If.PathMatch.emplace_back("fo*");
78 Frag.If.PathMatch.emplace_back("ba*r");
79 EXPECT_TRUE(compileAndApply());
80 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
82 // Excluded regex.
83 Frag = {};
84 Frag.If.PathMatch.emplace_back("b.*");
85 Frag.If.PathExclude.emplace_back(".*r");
86 EXPECT_FALSE(compileAndApply()) << "Included but also excluded";
87 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
89 // Invalid regex.
90 Frag = {};
91 Frag.If.PathMatch.emplace_back("**]@theu");
92 EXPECT_TRUE(compileAndApply());
93 EXPECT_THAT(Diags.Diagnostics, SizeIs(1));
94 EXPECT_THAT(Diags.Diagnostics.front().Message, StartsWith("Invalid regex"));
96 // Valid regex and unknown key.
97 Frag = {};
98 Frag.If.HasUnrecognizedCondition = true;
99 Frag.If.PathMatch.emplace_back("ba*r");
100 EXPECT_FALSE(compileAndApply());
101 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
103 // Only matches case-insensitively.
104 Frag = {};
105 Frag.If.PathMatch.emplace_back("B.*R");
106 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
107 #ifdef CLANGD_PATH_CASE_INSENSITIVE
108 EXPECT_TRUE(compileAndApply());
109 #else
110 EXPECT_FALSE(compileAndApply());
111 #endif
113 Frag = {};
114 Frag.If.PathExclude.emplace_back("B.*R");
115 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
116 #ifdef CLANGD_PATH_CASE_INSENSITIVE
117 EXPECT_FALSE(compileAndApply());
118 #else
119 EXPECT_TRUE(compileAndApply());
120 #endif
123 TEST_F(ConfigCompileTests, CompileCommands) {
124 Frag.CompileFlags.Compiler.emplace("tpc.exe");
125 Frag.CompileFlags.Add.emplace_back("-foo");
126 Frag.CompileFlags.Remove.emplace_back("--include-directory=");
127 std::vector<std::string> Argv = {"clang", "-I", "bar/", "--", "a.cc"};
128 EXPECT_TRUE(compileAndApply());
129 EXPECT_THAT(Conf.CompileFlags.Edits, SizeIs(3));
130 for (auto &Edit : Conf.CompileFlags.Edits)
131 Edit(Argv);
132 EXPECT_THAT(Argv, ElementsAre("tpc.exe", "-foo", "--", "a.cc"));
135 TEST_F(ConfigCompileTests, CompilationDatabase) {
136 Frag.CompileFlags.CompilationDatabase.emplace("None");
137 EXPECT_TRUE(compileAndApply());
138 EXPECT_EQ(Conf.CompileFlags.CDBSearch.Policy,
139 Config::CDBSearchSpec::NoCDBSearch);
141 Frag.CompileFlags.CompilationDatabase.emplace("Ancestors");
142 EXPECT_TRUE(compileAndApply());
143 EXPECT_EQ(Conf.CompileFlags.CDBSearch.Policy,
144 Config::CDBSearchSpec::Ancestors);
146 // Relative path not allowed without directory set.
147 Frag.CompileFlags.CompilationDatabase.emplace("Something");
148 EXPECT_TRUE(compileAndApply());
149 EXPECT_EQ(Conf.CompileFlags.CDBSearch.Policy,
150 Config::CDBSearchSpec::Ancestors)
151 << "default value";
152 EXPECT_THAT(Diags.Diagnostics,
153 ElementsAre(diagMessage(
154 "CompilationDatabase must be an absolute path, because this "
155 "fragment is not associated with any directory.")));
157 // Relative path allowed if directory is set.
158 Frag.Source.Directory = testRoot();
159 EXPECT_TRUE(compileAndApply());
160 EXPECT_EQ(Conf.CompileFlags.CDBSearch.Policy,
161 Config::CDBSearchSpec::FixedDir);
162 EXPECT_EQ(Conf.CompileFlags.CDBSearch.FixedCDBPath, testPath("Something"));
163 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
165 // Absolute path allowed.
166 Frag.Source.Directory.clear();
167 Frag.CompileFlags.CompilationDatabase.emplace(testPath("Something2"));
168 EXPECT_TRUE(compileAndApply());
169 EXPECT_EQ(Conf.CompileFlags.CDBSearch.Policy,
170 Config::CDBSearchSpec::FixedDir);
171 EXPECT_EQ(Conf.CompileFlags.CDBSearch.FixedCDBPath, testPath("Something2"));
172 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
175 TEST_F(ConfigCompileTests, Index) {
176 Frag.Index.Background.emplace("Skip");
177 EXPECT_TRUE(compileAndApply());
178 EXPECT_EQ(Conf.Index.Background, Config::BackgroundPolicy::Skip);
180 Frag = {};
181 Frag.Index.Background.emplace("Foo");
182 EXPECT_TRUE(compileAndApply());
183 EXPECT_EQ(Conf.Index.Background, Config::BackgroundPolicy::Build)
184 << "by default";
185 EXPECT_THAT(
186 Diags.Diagnostics,
187 ElementsAre(diagMessage(
188 "Invalid Background value 'Foo'. Valid values are Build, Skip.")));
191 TEST_F(ConfigCompileTests, PathSpecMatch) {
192 auto BarPath = llvm::sys::path::convert_to_slash(testPath("foo/bar.h"));
193 Parm.Path = BarPath;
195 struct {
196 std::string Directory;
197 std::string PathSpec;
198 bool ShouldMatch;
199 } Cases[] = {
201 // Absolute path matches.
203 llvm::sys::path::convert_to_slash(testPath("foo/bar.h")),
204 true,
207 // Absolute path fails.
209 llvm::sys::path::convert_to_slash(testPath("bar/bar.h")),
210 false,
213 // Relative should fail to match as /foo/bar.h doesn't reside under
214 // /baz/.
215 testPath("baz"),
216 "bar\\.h",
217 false,
220 // Relative should pass with /foo as directory.
221 testPath("foo"),
222 "bar\\.h",
223 true,
227 // PathMatch
228 for (const auto &Case : Cases) {
229 Frag = {};
230 Frag.If.PathMatch.emplace_back(Case.PathSpec);
231 Frag.Source.Directory = Case.Directory;
232 EXPECT_EQ(compileAndApply(), Case.ShouldMatch);
233 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
236 // PathEclude
237 for (const auto &Case : Cases) {
238 SCOPED_TRACE(Case.Directory);
239 SCOPED_TRACE(Case.PathSpec);
240 Frag = {};
241 Frag.If.PathExclude.emplace_back(Case.PathSpec);
242 Frag.Source.Directory = Case.Directory;
243 EXPECT_NE(compileAndApply(), Case.ShouldMatch);
244 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
248 TEST_F(ConfigCompileTests, DiagnosticsIncludeCleaner) {
249 // Defaults to Strict.
250 EXPECT_TRUE(compileAndApply());
251 EXPECT_EQ(Conf.Diagnostics.UnusedIncludes, Config::IncludesPolicy::Strict);
253 Frag = {};
254 Frag.Diagnostics.UnusedIncludes.emplace("None");
255 EXPECT_TRUE(compileAndApply());
256 EXPECT_EQ(Conf.Diagnostics.UnusedIncludes, Config::IncludesPolicy::None);
258 Frag = {};
259 Frag.Diagnostics.UnusedIncludes.emplace("Strict");
260 EXPECT_TRUE(compileAndApply());
261 EXPECT_EQ(Conf.Diagnostics.UnusedIncludes, Config::IncludesPolicy::Strict);
263 Frag = {};
264 EXPECT_TRUE(Conf.Diagnostics.Includes.IgnoreHeader.empty())
265 << Conf.Diagnostics.Includes.IgnoreHeader.size();
266 Frag.Diagnostics.Includes.IgnoreHeader.push_back(
267 Located<std::string>("foo.h"));
268 Frag.Diagnostics.Includes.IgnoreHeader.push_back(
269 Located<std::string>(".*inc"));
270 EXPECT_TRUE(compileAndApply());
271 auto HeaderFilter = [this](llvm::StringRef Path) {
272 for (auto &Filter : Conf.Diagnostics.Includes.IgnoreHeader) {
273 if (Filter(Path))
274 return true;
276 return false;
278 EXPECT_TRUE(HeaderFilter("foo.h"));
279 EXPECT_FALSE(HeaderFilter("bar.h"));
281 Frag = {};
282 EXPECT_FALSE(Conf.Diagnostics.Includes.AnalyzeAngledIncludes);
283 Frag.Diagnostics.Includes.AnalyzeAngledIncludes = true;
284 EXPECT_TRUE(compileAndApply());
285 EXPECT_TRUE(Conf.Diagnostics.Includes.AnalyzeAngledIncludes);
288 TEST_F(ConfigCompileTests, DiagnosticSuppression) {
289 Frag.Diagnostics.Suppress.emplace_back("bugprone-use-after-move");
290 Frag.Diagnostics.Suppress.emplace_back("unreachable-code");
291 Frag.Diagnostics.Suppress.emplace_back("-Wunused-variable");
292 Frag.Diagnostics.Suppress.emplace_back("typecheck_bool_condition");
293 Frag.Diagnostics.Suppress.emplace_back("err_unexpected_friend");
294 Frag.Diagnostics.Suppress.emplace_back("warn_alloca");
295 EXPECT_TRUE(compileAndApply());
296 EXPECT_THAT(Conf.Diagnostics.Suppress.keys(),
297 UnorderedElementsAre("bugprone-use-after-move",
298 "unreachable-code", "unused-variable",
299 "typecheck_bool_condition",
300 "unexpected_friend", "warn_alloca"));
301 EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
302 diag::warn_unreachable, Conf.Diagnostics.Suppress, LangOptions()));
303 // Subcategory not respected/suppressed.
304 EXPECT_FALSE(isBuiltinDiagnosticSuppressed(
305 diag::warn_unreachable_break, Conf.Diagnostics.Suppress, LangOptions()));
306 EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
307 diag::warn_unused_variable, Conf.Diagnostics.Suppress, LangOptions()));
308 EXPECT_TRUE(isBuiltinDiagnosticSuppressed(diag::err_typecheck_bool_condition,
309 Conf.Diagnostics.Suppress,
310 LangOptions()));
311 EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
312 diag::err_unexpected_friend, Conf.Diagnostics.Suppress, LangOptions()));
313 EXPECT_TRUE(isBuiltinDiagnosticSuppressed(
314 diag::warn_alloca, Conf.Diagnostics.Suppress, LangOptions()));
316 Frag.Diagnostics.Suppress.emplace_back("*");
317 EXPECT_TRUE(compileAndApply());
318 EXPECT_TRUE(Conf.Diagnostics.SuppressAll);
319 EXPECT_THAT(Conf.Diagnostics.Suppress, IsEmpty());
322 TEST_F(ConfigCompileTests, Tidy) {
323 auto &Tidy = Frag.Diagnostics.ClangTidy;
324 Tidy.Add.emplace_back("bugprone-use-after-move");
325 Tidy.Add.emplace_back("llvm-*");
326 Tidy.Remove.emplace_back("llvm-include-order");
327 Tidy.Remove.emplace_back("readability-*");
328 Tidy.CheckOptions.emplace_back(
329 std::make_pair(std::string("StrictMode"), std::string("true")));
330 Tidy.CheckOptions.emplace_back(std::make_pair(
331 std::string("example-check.ExampleOption"), std::string("0")));
332 EXPECT_TRUE(compileAndApply());
333 EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.size(), 2U);
334 EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup("StrictMode"),
335 "true");
336 EXPECT_EQ(Conf.Diagnostics.ClangTidy.CheckOptions.lookup(
337 "example-check.ExampleOption"),
338 "0");
339 #if CLANGD_TIDY_CHECKS
340 EXPECT_EQ(
341 Conf.Diagnostics.ClangTidy.Checks,
342 "bugprone-use-after-move,llvm-*,-llvm-include-order,-readability-*");
343 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
344 #else // !CLANGD_TIDY_CHECKS
345 EXPECT_EQ(Conf.Diagnostics.ClangTidy.Checks, "llvm-*,-readability-*");
346 EXPECT_THAT(
347 Diags.Diagnostics,
348 ElementsAre(
349 diagMessage(
350 "clang-tidy check 'bugprone-use-after-move' was not found"),
351 diagMessage("clang-tidy check 'llvm-include-order' was not found")));
352 #endif
355 TEST_F(ConfigCompileTests, TidyBadChecks) {
356 auto &Tidy = Frag.Diagnostics.ClangTidy;
357 Tidy.Add.emplace_back("unknown-check");
358 Tidy.Remove.emplace_back("*");
359 Tidy.Remove.emplace_back("llvm-includeorder");
360 EXPECT_TRUE(compileAndApply());
361 // Ensure bad checks are stripped from the glob.
362 EXPECT_EQ(Conf.Diagnostics.ClangTidy.Checks, "-*");
363 EXPECT_THAT(
364 Diags.Diagnostics,
365 ElementsAre(
366 AllOf(diagMessage("clang-tidy check 'unknown-check' was not found"),
367 diagKind(llvm::SourceMgr::DK_Warning)),
368 AllOf(
369 diagMessage("clang-tidy check 'llvm-includeorder' was not found"),
370 diagKind(llvm::SourceMgr::DK_Warning))));
373 TEST_F(ConfigCompileTests, ExternalServerNeedsTrusted) {
374 Fragment::IndexBlock::ExternalBlock External;
375 External.Server.emplace("xxx");
376 Frag.Index.External = std::move(External);
377 compileAndApply();
378 EXPECT_THAT(
379 Diags.Diagnostics,
380 ElementsAre(diagMessage(
381 "Remote index may not be specified by untrusted configuration. "
382 "Copy this into user config to use it.")));
383 EXPECT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
386 TEST_F(ConfigCompileTests, ExternalBlockWarnOnMultipleSource) {
387 Frag.Source.Trusted = true;
388 Fragment::IndexBlock::ExternalBlock External;
389 External.File.emplace("");
390 External.Server.emplace("");
391 Frag.Index.External = std::move(External);
392 compileAndApply();
393 #ifdef CLANGD_ENABLE_REMOTE
394 EXPECT_THAT(
395 Diags.Diagnostics,
396 Contains(
397 AllOf(diagMessage("Exactly one of File, Server or None must be set."),
398 diagKind(llvm::SourceMgr::DK_Error))));
399 #else
400 ASSERT_TRUE(Conf.Index.External.hasValue());
401 EXPECT_EQ(Conf.Index.External->Kind, Config::ExternalIndexSpec::File);
402 #endif
405 TEST_F(ConfigCompileTests, ExternalBlockDisableWithNone) {
406 compileAndApply();
407 EXPECT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
409 Fragment::IndexBlock::ExternalBlock External;
410 External.IsNone = true;
411 Frag.Index.External = std::move(External);
412 compileAndApply();
413 EXPECT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
416 TEST_F(ConfigCompileTests, ExternalBlockErrOnNoSource) {
417 Frag.Index.External.emplace(Fragment::IndexBlock::ExternalBlock{});
418 compileAndApply();
419 EXPECT_THAT(
420 Diags.Diagnostics,
421 Contains(
422 AllOf(diagMessage("Exactly one of File, Server or None must be set."),
423 diagKind(llvm::SourceMgr::DK_Error))));
426 TEST_F(ConfigCompileTests, ExternalBlockDisablesBackgroundIndex) {
427 auto BazPath = testPath("foo/bar/baz.h", llvm::sys::path::Style::posix);
428 Parm.Path = BazPath;
429 Frag.Index.Background.emplace("Build");
430 Fragment::IndexBlock::ExternalBlock External;
431 External.File.emplace(testPath("foo"));
432 External.MountPoint.emplace(
433 testPath("foo/bar", llvm::sys::path::Style::posix));
434 Frag.Index.External = std::move(External);
435 compileAndApply();
436 EXPECT_EQ(Conf.Index.Background, Config::BackgroundPolicy::Skip);
439 TEST_F(ConfigCompileTests, ExternalBlockMountPoint) {
440 auto GetFrag = [](llvm::StringRef Directory,
441 std::optional<const char *> MountPoint) {
442 Fragment Frag;
443 Frag.Source.Directory = Directory.str();
444 Fragment::IndexBlock::ExternalBlock External;
445 External.File.emplace(testPath("foo"));
446 if (MountPoint)
447 External.MountPoint.emplace(*MountPoint);
448 Frag.Index.External = std::move(External);
449 return Frag;
452 auto BarPath = testPath("foo/bar.h", llvm::sys::path::Style::posix);
453 BarPath = llvm::sys::path::convert_to_slash(BarPath);
454 Parm.Path = BarPath;
455 // Non-absolute MountPoint without a directory raises an error.
456 Frag = GetFrag("", "foo");
457 compileAndApply();
458 ASSERT_THAT(
459 Diags.Diagnostics,
460 ElementsAre(
461 AllOf(diagMessage("MountPoint must be an absolute path, because this "
462 "fragment is not associated with any directory."),
463 diagKind(llvm::SourceMgr::DK_Error))));
464 EXPECT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
466 auto FooPath = testPath("foo/", llvm::sys::path::Style::posix);
467 FooPath = llvm::sys::path::convert_to_slash(FooPath);
468 // Ok when relative.
469 Frag = GetFrag(testRoot(), "foo/");
470 compileAndApply();
471 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
472 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::File);
473 EXPECT_THAT(Conf.Index.External.MountPoint, FooPath);
475 // None defaults to ".".
476 Frag = GetFrag(FooPath, std::nullopt);
477 compileAndApply();
478 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
479 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::File);
480 EXPECT_THAT(Conf.Index.External.MountPoint, FooPath);
482 // Without a file, external index is empty.
483 Parm.Path = "";
484 Frag = GetFrag("", FooPath.c_str());
485 compileAndApply();
486 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
487 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
489 // File outside MountPoint, no index.
490 auto BazPath = testPath("bar/baz.h", llvm::sys::path::Style::posix);
491 BazPath = llvm::sys::path::convert_to_slash(BazPath);
492 Parm.Path = BazPath;
493 Frag = GetFrag("", FooPath.c_str());
494 compileAndApply();
495 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
496 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
498 // File under MountPoint, index should be set.
499 BazPath = testPath("foo/baz.h", llvm::sys::path::Style::posix);
500 BazPath = llvm::sys::path::convert_to_slash(BazPath);
501 Parm.Path = BazPath;
502 Frag = GetFrag("", FooPath.c_str());
503 compileAndApply();
504 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
505 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::File);
506 EXPECT_THAT(Conf.Index.External.MountPoint, FooPath);
508 // Only matches case-insensitively.
509 BazPath = testPath("fOo/baz.h", llvm::sys::path::Style::posix);
510 BazPath = llvm::sys::path::convert_to_slash(BazPath);
511 Parm.Path = BazPath;
513 FooPath = testPath("FOO/", llvm::sys::path::Style::posix);
514 FooPath = llvm::sys::path::convert_to_slash(FooPath);
515 Frag = GetFrag("", FooPath.c_str());
516 compileAndApply();
517 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
518 #ifdef CLANGD_PATH_CASE_INSENSITIVE
519 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::File);
520 EXPECT_THAT(Conf.Index.External.MountPoint, FooPath);
521 #else
522 ASSERT_EQ(Conf.Index.External.Kind, Config::ExternalIndexSpec::None);
523 #endif
526 TEST_F(ConfigCompileTests, AllScopes) {
527 // Defaults to true.
528 EXPECT_TRUE(compileAndApply());
529 EXPECT_TRUE(Conf.Completion.AllScopes);
531 Frag = {};
532 Frag.Completion.AllScopes = false;
533 EXPECT_TRUE(compileAndApply());
534 EXPECT_FALSE(Conf.Completion.AllScopes);
536 Frag = {};
537 Frag.Completion.AllScopes = true;
538 EXPECT_TRUE(compileAndApply());
539 EXPECT_TRUE(Conf.Completion.AllScopes);
542 TEST_F(ConfigCompileTests, Style) {
543 Frag = {};
544 Frag.Style.FullyQualifiedNamespaces.push_back(std::string("foo"));
545 Frag.Style.FullyQualifiedNamespaces.push_back(std::string("bar"));
546 EXPECT_TRUE(compileAndApply());
547 EXPECT_THAT(Conf.Style.FullyQualifiedNamespaces, ElementsAre("foo", "bar"));
550 Frag = {};
551 EXPECT_TRUE(Conf.Style.QuotedHeaders.empty())
552 << Conf.Style.QuotedHeaders.size();
553 Frag.Style.QuotedHeaders.push_back(Located<std::string>("foo.h"));
554 Frag.Style.QuotedHeaders.push_back(Located<std::string>(".*inc"));
555 EXPECT_TRUE(compileAndApply());
556 auto HeaderFilter = [this](llvm::StringRef Path) {
557 for (auto &Filter : Conf.Style.QuotedHeaders) {
558 if (Filter(Path))
559 return true;
561 return false;
563 EXPECT_TRUE(HeaderFilter("foo.h"));
564 EXPECT_TRUE(HeaderFilter("prefix/foo.h"));
565 EXPECT_FALSE(HeaderFilter("bar.h"));
566 EXPECT_FALSE(HeaderFilter("foo.h/bar.h"));
570 Frag = {};
571 EXPECT_TRUE(Conf.Style.AngledHeaders.empty())
572 << Conf.Style.AngledHeaders.size();
573 Frag.Style.AngledHeaders.push_back(Located<std::string>("foo.h"));
574 Frag.Style.AngledHeaders.push_back(Located<std::string>(".*inc"));
575 EXPECT_TRUE(compileAndApply());
576 auto HeaderFilter = [this](llvm::StringRef Path) {
577 for (auto &Filter : Conf.Style.AngledHeaders) {
578 if (Filter(Path))
579 return true;
581 return false;
583 EXPECT_TRUE(HeaderFilter("foo.h"));
584 EXPECT_FALSE(HeaderFilter("bar.h"));
587 } // namespace
588 } // namespace config
589 } // namespace clangd
590 } // namespace clang