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/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"
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
);
32 using ::testing::AllOf
;
33 using ::testing::ElementsAre
;
34 using ::testing::IsEmpty
;
36 MATCHER_P(val
, Value
, "") {
39 *result_listener
<< "value is " << *arg
;
43 MATCHER_P2(PairVal
, Value1
, Value2
, "") {
44 if (*arg
.first
== Value1
&& *arg
.second
== Value2
)
46 *result_listener
<< "values are [" << *arg
.first
<< ", " << *arg
.second
51 TEST(ParseYAML
, SyntacticForms
) {
53 const char *YAML
= R
"yaml(
57 CompileFlags: { Add: [foo, bar] }
71 example-check.ExampleOption: 0
72 UnusedIncludes: Strict
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
) {
95 Annotations
YAML(R
"yaml(
97 PathMatch: [['???bad***regex(((']]
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
),
109 TEST(ParseYAML
, ConfigDiagnostics
) {
111 Annotations
YAML(R
"yaml(
113 $unknown[[UnknownCondition]]: "foo
"
117 CompileFlags: {$unexpected^
120 Fragment::parseYAML(YAML
.code(), "config.yaml", Diags
.callback());
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
) {
141 const char *YAML
= R
"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
) {
157 Annotations
YAML(R
"yaml(
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
) {
174 Annotations
YAML(R
"yaml(
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
) {
193 Annotations
YAML(R
"yaml(
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
) {
206 Annotations
YAML(R
"yaml(
208 AllScopes: $diagrange[[Truex]]
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
) {
223 Annotations
YAML(R
"yaml(
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
) {
236 Annotations
YAML(R
"yaml(
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
) {
252 Annotations
YAML(R
"yaml(
255 IgnoreHeader: [foo, bar]
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
) {
267 Annotations
YAML(R
"yaml(
269 FullyQualifiedNamespaces: [foo, bar])yaml");
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")));
278 } // namespace config
279 } // namespace clangd