1 //===-- ConfigYAMLTests.cpp -----------------------------------------------===//
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
7 //===----------------------------------------------------------------------===//
9 #include "Annotations.h"
10 #include "ConfigFragment.h"
11 #include "ConfigTesting.h"
13 #include "llvm/ADT/StringRef.h"
14 #include "llvm/Support/SMLoc.h"
15 #include "llvm/Support/SourceMgr.h"
16 #include "llvm/Testing/Support/SupportHelpers.h"
17 #include "gmock/gmock.h"
18 #include "gtest/gtest.h"
24 // PrintTo is a magic identifier of GTest
25 // NOLINTNEXTLINE (readability-identifier-naming)
26 template <typename T
> void PrintTo(const Located
<T
> &V
, std::ostream
*OS
) {
27 *OS
<< ::testing::PrintToString(*V
);
31 using ::testing::AllOf
;
32 using ::testing::ElementsAre
;
33 using ::testing::IsEmpty
;
35 MATCHER_P(val
, Value
, "") {
38 *result_listener
<< "value is " << *arg
;
42 MATCHER_P2(PairVal
, Value1
, Value2
, "") {
43 if (*arg
.first
== Value1
&& *arg
.second
== Value2
)
45 *result_listener
<< "values are [" << *arg
.first
<< ", " << *arg
.second
50 TEST(ParseYAML
, SyntacticForms
) {
52 const char *YAML
= R
"yaml(
56 CompileFlags: { Add: [foo, bar] }
70 example-check.ExampleOption: 0
71 UnusedIncludes: Strict
73 auto Results
= Fragment::parseYAML(YAML
, "config.yaml", Diags
.callback());
74 EXPECT_THAT(Diags
.Diagnostics
, IsEmpty());
75 EXPECT_THAT(Diags
.Files
, ElementsAre("config.yaml"));
76 ASSERT_EQ(Results
.size(), 4u);
77 EXPECT_FALSE(Results
[0].If
.HasUnrecognizedCondition
);
78 EXPECT_THAT(Results
[0].If
.PathMatch
, ElementsAre(val("abc")));
79 EXPECT_THAT(Results
[0].CompileFlags
.Add
, ElementsAre(val("foo"), val("bar")));
81 EXPECT_THAT(Results
[1].CompileFlags
.Add
, ElementsAre(val("b\naz\n")));
83 ASSERT_TRUE(Results
[2].Index
.Background
);
84 EXPECT_EQ("Skip", **Results
[2].Index
.Background
);
85 EXPECT_THAT(Results
[3].Diagnostics
.ClangTidy
.CheckOptions
,
86 ElementsAre(PairVal("IgnoreMacros", "true"),
87 PairVal("example-check.ExampleOption", "0")));
88 EXPECT_TRUE(Results
[3].Diagnostics
.UnusedIncludes
);
89 EXPECT_EQ("Strict", **Results
[3].Diagnostics
.UnusedIncludes
);
92 TEST(ParseYAML
, Locations
) {
94 Annotations
YAML(R
"yaml(
96 PathMatch: [['???bad***regex(((']]
99 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
100 EXPECT_THAT(Diags
.Diagnostics
, IsEmpty());
101 ASSERT_EQ(Results
.size(), 1u);
102 ASSERT_NE(Results
.front().Source
.Manager
, nullptr);
103 EXPECT_EQ(toRange(Results
.front().If
.PathMatch
.front().Range
,
104 *Results
.front().Source
.Manager
),
108 TEST(ParseYAML
, ConfigDiagnostics
) {
110 Annotations
YAML(R
"yaml(
112 $unknown[[UnknownCondition]]: "foo
"
116 CompileFlags: {$unexpected^
119 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
123 ElementsAre(AllOf(diagMessage("Unknown If key 'UnknownCondition'"),
124 diagKind(llvm::SourceMgr::DK_Warning
),
125 diagPos(YAML
.range("unknown").start
),
126 diagRange(YAML
.range("unknown"))),
127 AllOf(diagMessage("Unexpected token. Expected Key, Flow "
128 "Entry, or Flow Mapping End."),
129 diagKind(llvm::SourceMgr::DK_Error
),
130 diagPos(YAML
.point("unexpected")),
131 diagRange(std::nullopt
))));
133 ASSERT_EQ(Results
.size(), 1u); // invalid fragment discarded.
134 EXPECT_THAT(Results
.front().CompileFlags
.Add
, ElementsAre(val("first")));
135 EXPECT_TRUE(Results
.front().If
.HasUnrecognizedCondition
);
138 TEST(ParseYAML
, Invalid
) {
140 const char *YAML
= R
"yaml(
147 auto Results
= Fragment::parseYAML(YAML
, "config.yaml", Diags
.callback());
148 EXPECT_THAT(Diags
.Diagnostics
,
149 ElementsAre(diagMessage("If should be a dictionary"),
150 diagMessage("Config should be a dictionary")));
151 ASSERT_THAT(Results
, IsEmpty());
154 TEST(ParseYAML
, ExternalBlockNone
) {
156 Annotations
YAML(R
"yaml(
161 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
162 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
163 ASSERT_EQ(Results
.size(), 1u);
164 ASSERT_TRUE(Results
[0].Index
.External
);
165 EXPECT_FALSE((*Results
[0].Index
.External
)->File
.has_value());
166 EXPECT_FALSE((*Results
[0].Index
.External
)->MountPoint
.has_value());
167 EXPECT_FALSE((*Results
[0].Index
.External
)->Server
.has_value());
168 EXPECT_THAT(*(*Results
[0].Index
.External
)->IsNone
, testing::Eq(true));
171 TEST(ParseYAML
, ExternalBlock
) {
173 Annotations
YAML(R
"yaml(
181 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
182 ASSERT_EQ(Results
.size(), 1u);
183 ASSERT_TRUE(Results
[0].Index
.External
);
184 EXPECT_THAT(*(*Results
[0].Index
.External
)->File
, val("foo"));
185 EXPECT_THAT(*(*Results
[0].Index
.External
)->MountPoint
, val("baz"));
186 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
187 EXPECT_THAT(*(*Results
[0].Index
.External
)->Server
, val("bar"));
190 TEST(ParseYAML
, AllScopes
) {
192 Annotations
YAML(R
"yaml(
197 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
198 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
199 ASSERT_EQ(Results
.size(), 1u);
200 EXPECT_THAT(Results
[0].Completion
.AllScopes
, llvm::ValueIs(val(true)));
203 TEST(ParseYAML
, AllScopesWarn
) {
205 Annotations
YAML(R
"yaml(
207 AllScopes: $diagrange[[Truex]]
210 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
211 EXPECT_THAT(Diags
.Diagnostics
,
212 ElementsAre(AllOf(diagMessage("AllScopes should be a boolean"),
213 diagKind(llvm::SourceMgr::DK_Warning
),
214 diagPos(YAML
.range("diagrange").start
),
215 diagRange(YAML
.range("diagrange")))));
216 ASSERT_EQ(Results
.size(), 1u);
217 EXPECT_THAT(Results
[0].Completion
.AllScopes
, testing::Eq(std::nullopt
));
220 TEST(ParseYAML
, ShowAKA
) {
222 Annotations
YAML(R
"yaml(
227 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
228 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
229 ASSERT_EQ(Results
.size(), 1u);
230 EXPECT_THAT(Results
[0].Hover
.ShowAKA
, llvm::ValueIs(val(true)));
233 TEST(ParseYAML
, InlayHints
) {
235 Annotations
YAML(R
"yaml(
241 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
242 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
243 ASSERT_EQ(Results
.size(), 1u);
244 EXPECT_THAT(Results
[0].InlayHints
.Enabled
, llvm::ValueIs(val(false)));
245 EXPECT_THAT(Results
[0].InlayHints
.ParameterNames
, llvm::ValueIs(val(true)));
246 EXPECT_EQ(Results
[0].InlayHints
.DeducedTypes
, std::nullopt
);
249 TEST(ParseYAML
, SemanticTokens
) {
251 Annotations
YAML(R
"yaml(
253 DisabledKinds: [ Operator, InactiveCode]
254 DisabledModifiers: Readonly
257 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
258 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
259 ASSERT_EQ(Results
.size(), 1u);
260 EXPECT_THAT(Results
[0].SemanticTokens
.DisabledKinds
,
261 ElementsAre(val("Operator"), val("InactiveCode")));
262 EXPECT_THAT(Results
[0].SemanticTokens
.DisabledModifiers
,
263 ElementsAre(val("Readonly")));
266 TEST(ParseYAML
, IncludesIgnoreHeader
) {
268 Annotations
YAML(R
"yaml(
271 IgnoreHeader: [foo, bar]
274 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
275 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
276 ASSERT_EQ(Results
.size(), 1u);
277 EXPECT_THAT(Results
[0].Diagnostics
.Includes
.IgnoreHeader
,
278 ElementsAre(val("foo"), val("bar")));
281 TEST(ParseYAML
, Style
) {
283 Annotations
YAML(R
"yaml(
285 FullyQualifiedNamespaces: [foo, bar])yaml");
287 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
288 ASSERT_THAT(Diags
.Diagnostics
, IsEmpty());
289 ASSERT_EQ(Results
.size(), 1u);
290 EXPECT_THAT(Results
[0].Style
.FullyQualifiedNamespaces
,
291 ElementsAre(val("foo"), val("bar")));
294 } // namespace config
295 } // namespace clangd