[docs] Add LICENSE.txt to the root of the mono-repo
[llvm-project.git] / clang-tools-extra / clangd / unittests / ConfigYAMLTests.cpp
blob6af1e3bb74111b2bcdd521ece228d516a74be9a5
1 //===-- ConfigYAMLTests.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 "Annotations.h"
10 #include "ConfigFragment.h"
11 #include "ConfigTesting.h"
12 #include "Protocol.h"
13 #include "llvm/ADT/None.h"
14 #include "llvm/ADT/StringRef.h"
15 #include "llvm/Support/SMLoc.h"
16 #include "llvm/Support/SourceMgr.h"
17 #include "llvm/Testing/Support/SupportHelpers.h"
18 #include "gmock/gmock.h"
19 #include "gtest/gtest.h"
21 namespace clang {
22 namespace clangd {
23 namespace config {
25 // PrintTo is a magic identifier of GTest
26 // NOLINTNEXTLINE (readability-identifier-naming)
27 template <typename T> void PrintTo(const Located<T> &V, std::ostream *OS) {
28 *OS << ::testing::PrintToString(*V);
31 namespace {
32 using ::testing::AllOf;
33 using ::testing::ElementsAre;
34 using ::testing::IsEmpty;
36 MATCHER_P(val, Value, "") {
37 if (*arg == Value)
38 return true;
39 *result_listener << "value is " << *arg;
40 return false;
43 MATCHER_P2(PairVal, Value1, Value2, "") {
44 if (*arg.first == Value1 && *arg.second == Value2)
45 return true;
46 *result_listener << "values are [" << *arg.first << ", " << *arg.second
47 << "]";
48 return false;
51 TEST(ParseYAML, SyntacticForms) {
52 CapturedDiags Diags;
53 const char *YAML = R"yaml(
54 If:
55 PathMatch:
56 - 'abc'
57 CompileFlags: { Add: [foo, bar] }
58 ---
59 CompileFlags:
60 Add: |
63 ---
64 Index:
65 Background: Skip
66 ---
67 Diagnostics:
68 ClangTidy:
69 CheckOptions:
70 IgnoreMacros: true
71 example-check.ExampleOption: 0
72 UnusedIncludes: Strict
73 )yaml";
74 auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback());
75 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
76 EXPECT_THAT(Diags.Files, ElementsAre("config.yaml"));
77 ASSERT_EQ(Results.size(), 4u);
78 EXPECT_FALSE(Results[0].If.HasUnrecognizedCondition);
79 EXPECT_THAT(Results[0].If.PathMatch, ElementsAre(val("abc")));
80 EXPECT_THAT(Results[0].CompileFlags.Add, ElementsAre(val("foo"), val("bar")));
82 EXPECT_THAT(Results[1].CompileFlags.Add, ElementsAre(val("b\naz\n")));
84 ASSERT_TRUE(Results[2].Index.Background);
85 EXPECT_EQ("Skip", *Results[2].Index.Background.value());
86 EXPECT_THAT(Results[3].Diagnostics.ClangTidy.CheckOptions,
87 ElementsAre(PairVal("IgnoreMacros", "true"),
88 PairVal("example-check.ExampleOption", "0")));
89 EXPECT_TRUE(Results[3].Diagnostics.UnusedIncludes);
90 EXPECT_EQ("Strict", *Results[3].Diagnostics.UnusedIncludes.value());
93 TEST(ParseYAML, Locations) {
94 CapturedDiags Diags;
95 Annotations YAML(R"yaml(
96 If:
97 PathMatch: [['???bad***regex(((']]
98 )yaml");
99 auto Results =
100 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
101 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
102 ASSERT_EQ(Results.size(), 1u);
103 ASSERT_NE(Results.front().Source.Manager, nullptr);
104 EXPECT_EQ(toRange(Results.front().If.PathMatch.front().Range,
105 *Results.front().Source.Manager),
106 YAML.range());
109 TEST(ParseYAML, ConfigDiagnostics) {
110 CapturedDiags Diags;
111 Annotations YAML(R"yaml(
113 $unknown[[UnknownCondition]]: "foo"
114 CompileFlags:
115 Add: 'first'
117 CompileFlags: {$unexpected^
118 )yaml");
119 auto Results =
120 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
122 ASSERT_THAT(
123 Diags.Diagnostics,
124 ElementsAre(AllOf(diagMessage("Unknown If key 'UnknownCondition'"),
125 diagKind(llvm::SourceMgr::DK_Warning),
126 diagPos(YAML.range("unknown").start),
127 diagRange(YAML.range("unknown"))),
128 AllOf(diagMessage("Unexpected token. Expected Key, Flow "
129 "Entry, or Flow Mapping End."),
130 diagKind(llvm::SourceMgr::DK_Error),
131 diagPos(YAML.point("unexpected")),
132 diagRange(llvm::None))));
134 ASSERT_EQ(Results.size(), 1u); // invalid fragment discarded.
135 EXPECT_THAT(Results.front().CompileFlags.Add, ElementsAre(val("first")));
136 EXPECT_TRUE(Results.front().If.HasUnrecognizedCondition);
139 TEST(ParseYAML, Invalid) {
140 CapturedDiags Diags;
141 const char *YAML = R"yaml(
144 horrible
147 )yaml";
148 auto Results = Fragment::parseYAML(YAML, "config.yaml", Diags.callback());
149 EXPECT_THAT(Diags.Diagnostics,
150 ElementsAre(diagMessage("If should be a dictionary"),
151 diagMessage("Config should be a dictionary")));
152 ASSERT_THAT(Results, IsEmpty());
155 TEST(ParseYAML, ExternalBlockNone) {
156 CapturedDiags Diags;
157 Annotations YAML(R"yaml(
158 Index:
159 External: None
160 )yaml");
161 auto Results =
162 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
163 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
164 ASSERT_EQ(Results.size(), 1u);
165 ASSERT_TRUE(Results[0].Index.External);
166 EXPECT_FALSE(Results[0].Index.External.value()->File.has_value());
167 EXPECT_FALSE(Results[0].Index.External.value()->MountPoint.has_value());
168 EXPECT_FALSE(Results[0].Index.External.value()->Server.has_value());
169 EXPECT_THAT(*Results[0].Index.External.value()->IsNone, testing::Eq(true));
172 TEST(ParseYAML, ExternalBlock) {
173 CapturedDiags Diags;
174 Annotations YAML(R"yaml(
175 Index:
176 External:
177 File: "foo"
178 Server: ^"bar"
179 MountPoint: "baz"
180 )yaml");
181 auto Results =
182 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
183 ASSERT_EQ(Results.size(), 1u);
184 ASSERT_TRUE(Results[0].Index.External);
185 EXPECT_THAT(*Results[0].Index.External.value()->File, val("foo"));
186 EXPECT_THAT(*Results[0].Index.External.value()->MountPoint, val("baz"));
187 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
188 EXPECT_THAT(*Results[0].Index.External.value()->Server, val("bar"));
191 TEST(ParseYAML, AllScopes) {
192 CapturedDiags Diags;
193 Annotations YAML(R"yaml(
194 Completion:
195 AllScopes: True
196 )yaml");
197 auto Results =
198 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
199 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
200 ASSERT_EQ(Results.size(), 1u);
201 EXPECT_THAT(Results[0].Completion.AllScopes, llvm::ValueIs(val(true)));
204 TEST(ParseYAML, AllScopesWarn) {
205 CapturedDiags Diags;
206 Annotations YAML(R"yaml(
207 Completion:
208 AllScopes: $diagrange[[Truex]]
209 )yaml");
210 auto Results =
211 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
212 EXPECT_THAT(Diags.Diagnostics,
213 ElementsAre(AllOf(diagMessage("AllScopes should be a boolean"),
214 diagKind(llvm::SourceMgr::DK_Warning),
215 diagPos(YAML.range("diagrange").start),
216 diagRange(YAML.range("diagrange")))));
217 ASSERT_EQ(Results.size(), 1u);
218 EXPECT_THAT(Results[0].Completion.AllScopes, testing::Eq(llvm::None));
221 TEST(ParseYAML, ShowAKA) {
222 CapturedDiags Diags;
223 Annotations YAML(R"yaml(
224 Hover:
225 ShowAKA: True
226 )yaml");
227 auto Results =
228 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
229 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
230 ASSERT_EQ(Results.size(), 1u);
231 EXPECT_THAT(Results[0].Hover.ShowAKA, llvm::ValueIs(val(true)));
234 TEST(ParseYAML, InlayHints) {
235 CapturedDiags Diags;
236 Annotations YAML(R"yaml(
237 InlayHints:
238 Enabled: No
239 ParameterNames: Yes
240 )yaml");
241 auto Results =
242 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
243 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
244 ASSERT_EQ(Results.size(), 1u);
245 EXPECT_THAT(Results[0].InlayHints.Enabled, llvm::ValueIs(val(false)));
246 EXPECT_THAT(Results[0].InlayHints.ParameterNames, llvm::ValueIs(val(true)));
247 EXPECT_EQ(Results[0].InlayHints.DeducedTypes, llvm::None);
250 TEST(ParseYAML, IncludesIgnoreHeader) {
251 CapturedDiags Diags;
252 Annotations YAML(R"yaml(
253 Diagnostics:
254 Includes:
255 IgnoreHeader: [foo, bar]
256 )yaml");
257 auto Results =
258 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
259 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
260 ASSERT_EQ(Results.size(), 1u);
261 EXPECT_THAT(Results[0].Diagnostics.Includes.IgnoreHeader,
262 ElementsAre(val("foo"), val("bar")));
265 TEST(ParseYAML, Style) {
266 CapturedDiags Diags;
267 Annotations YAML(R"yaml(
268 Style:
269 FullyQualifiedNamespaces: [foo, bar])yaml");
270 auto Results =
271 Fragment::parseYAML(YAML.code(), "config.yaml", Diags.callback());
272 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
273 ASSERT_EQ(Results.size(), 1u);
274 EXPECT_THAT(Results[0].Style.FullyQualifiedNamespaces,
275 ElementsAre(val("foo"), val("bar")));
277 } // namespace
278 } // namespace config
279 } // namespace clangd
280 } // namespace clang