1 | #include "ClangTidyOptions.h" |
2 | #include "ClangTidyCheck.h" |
3 | #include "ClangTidyDiagnosticConsumer.h" |
4 | #include "llvm/ADT/StringExtras.h" |
5 | #include "llvm/Support/ScopedPrinter.h" |
6 | #include "llvm/Testing/Annotations/Annotations.h" |
7 | #include "gmock/gmock.h" |
8 | #include "gtest/gtest.h" |
9 | #include <optional> |
10 | |
11 | namespace clang { |
12 | namespace tidy { |
13 | |
14 | enum class Colours { Red, Orange, Yellow, Green, Blue, Indigo, Violet }; |
15 | |
16 | template <> struct OptionEnumMapping<Colours> { |
17 | static llvm::ArrayRef<std::pair<Colours, StringRef>> getEnumMapping() { |
18 | static constexpr std::pair<Colours, StringRef> Mapping[] = { |
19 | {Colours::Red, "Red" }, {Colours::Orange, "Orange" }, |
20 | {Colours::Yellow, "Yellow" }, {Colours::Green, "Green" }, |
21 | {Colours::Blue, "Blue" }, {Colours::Indigo, "Indigo" }, |
22 | {Colours::Violet, "Violet" }}; |
23 | return ArrayRef(Mapping); |
24 | } |
25 | }; |
26 | |
27 | namespace test { |
28 | |
29 | TEST(ParseLineFilter, EmptyFilter) { |
30 | ClangTidyGlobalOptions Options; |
31 | EXPECT_FALSE(parseLineFilter("" , Options)); |
32 | EXPECT_TRUE(Options.LineFilter.empty()); |
33 | EXPECT_FALSE(parseLineFilter("[]" , Options)); |
34 | EXPECT_TRUE(Options.LineFilter.empty()); |
35 | } |
36 | |
37 | TEST(ParseLineFilter, InvalidFilter) { |
38 | ClangTidyGlobalOptions Options; |
39 | EXPECT_TRUE(!!parseLineFilter("asdf" , Options)); |
40 | EXPECT_TRUE(Options.LineFilter.empty()); |
41 | |
42 | EXPECT_TRUE(!!parseLineFilter("[{}]" , Options)); |
43 | EXPECT_TRUE(!!parseLineFilter("[{\"name\":\"\"}]" , Options)); |
44 | EXPECT_TRUE( |
45 | !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1]]}]" , Options)); |
46 | EXPECT_TRUE( |
47 | !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1,2,3]]}]" , Options)); |
48 | EXPECT_TRUE( |
49 | !!parseLineFilter("[{\"name\":\"test\",\"lines\":[[1,-1]]}]" , Options)); |
50 | } |
51 | |
52 | TEST(ParseLineFilter, ValidFilter) { |
53 | ClangTidyGlobalOptions Options; |
54 | std::error_code Error = parseLineFilter( |
55 | LineFilter: "[{\"name\":\"file1.cpp\",\"lines\":[[3,15],[20,30],[42,42]]}," |
56 | "{\"name\":\"file2.h\"}," |
57 | "{\"name\":\"file3.cc\",\"lines\":[[100,1000]]}]" , |
58 | Options); |
59 | EXPECT_FALSE(Error); |
60 | EXPECT_EQ(3u, Options.LineFilter.size()); |
61 | EXPECT_EQ("file1.cpp" , Options.LineFilter[0].Name); |
62 | EXPECT_EQ(3u, Options.LineFilter[0].LineRanges.size()); |
63 | EXPECT_EQ(3u, Options.LineFilter[0].LineRanges[0].first); |
64 | EXPECT_EQ(15u, Options.LineFilter[0].LineRanges[0].second); |
65 | EXPECT_EQ(20u, Options.LineFilter[0].LineRanges[1].first); |
66 | EXPECT_EQ(30u, Options.LineFilter[0].LineRanges[1].second); |
67 | EXPECT_EQ(42u, Options.LineFilter[0].LineRanges[2].first); |
68 | EXPECT_EQ(42u, Options.LineFilter[0].LineRanges[2].second); |
69 | EXPECT_EQ("file2.h" , Options.LineFilter[1].Name); |
70 | EXPECT_EQ(0u, Options.LineFilter[1].LineRanges.size()); |
71 | EXPECT_EQ("file3.cc" , Options.LineFilter[2].Name); |
72 | EXPECT_EQ(1u, Options.LineFilter[2].LineRanges.size()); |
73 | EXPECT_EQ(100u, Options.LineFilter[2].LineRanges[0].first); |
74 | EXPECT_EQ(1000u, Options.LineFilter[2].LineRanges[0].second); |
75 | } |
76 | |
77 | TEST(ParseConfiguration, ValidConfiguration) { |
78 | llvm::ErrorOr<ClangTidyOptions> Options = |
79 | parseConfiguration(Config: llvm::MemoryBufferRef( |
80 | "Checks: \"-*,misc-*\"\n" |
81 | "HeaderFileExtensions: [\"\",\"h\",\"hh\",\"hpp\",\"hxx\"]\n" |
82 | "ImplementationFileExtensions: [\"c\",\"cc\",\"cpp\",\"cxx\"]\n" |
83 | "HeaderFilterRegex: \".*\"\n" |
84 | "User: some.user" , |
85 | "Options" )); |
86 | EXPECT_TRUE(!!Options); |
87 | EXPECT_EQ("-*,misc-*" , *Options->Checks); |
88 | EXPECT_EQ(std::vector<std::string>({"" , "h" , "hh" , "hpp" , "hxx" }), |
89 | *Options->HeaderFileExtensions); |
90 | EXPECT_EQ(std::vector<std::string>({"c" , "cc" , "cpp" , "cxx" }), |
91 | *Options->ImplementationFileExtensions); |
92 | EXPECT_EQ(".*" , *Options->HeaderFilterRegex); |
93 | EXPECT_EQ("some.user" , *Options->User); |
94 | } |
95 | |
96 | TEST(ParseConfiguration, ChecksSeparatedByNewlines) { |
97 | auto MemoryBuffer = llvm::MemoryBufferRef("Checks: |\n" |
98 | " -*,misc-*\n" |
99 | " llvm-*\n" |
100 | " -clang-*,\n" |
101 | " google-*" , |
102 | "Options" ); |
103 | |
104 | auto Options = parseConfiguration(Config: MemoryBuffer); |
105 | |
106 | EXPECT_TRUE(!!Options); |
107 | EXPECT_EQ("-*,misc-*\nllvm-*\n-clang-*,\ngoogle-*\n" , *Options->Checks); |
108 | } |
109 | |
110 | TEST(ParseConfiguration, MergeConfigurations) { |
111 | llvm::ErrorOr<ClangTidyOptions> Options1 = |
112 | parseConfiguration(Config: llvm::MemoryBufferRef(R"( |
113 | Checks: "check1,check2" |
114 | HeaderFileExtensions: ["h","hh"] |
115 | ImplementationFileExtensions: ["c","cc"] |
116 | HeaderFilterRegex: "filter1" |
117 | User: user1 |
118 | ExtraArgs: ['arg1', 'arg2'] |
119 | ExtraArgsBefore: ['arg-before1', 'arg-before2'] |
120 | UseColor: false |
121 | SystemHeaders: false |
122 | )" , |
123 | "Options1" )); |
124 | ASSERT_TRUE(!!Options1); |
125 | llvm::ErrorOr<ClangTidyOptions> Options2 = |
126 | parseConfiguration(Config: llvm::MemoryBufferRef(R"( |
127 | Checks: "check3,check4" |
128 | HeaderFileExtensions: ["hpp","hxx"] |
129 | ImplementationFileExtensions: ["cpp","cxx"] |
130 | HeaderFilterRegex: "filter2" |
131 | User: user2 |
132 | ExtraArgs: ['arg3', 'arg4'] |
133 | ExtraArgsBefore: ['arg-before3', 'arg-before4'] |
134 | UseColor: true |
135 | SystemHeaders: true |
136 | )" , |
137 | "Options2" )); |
138 | ASSERT_TRUE(!!Options2); |
139 | ClangTidyOptions Options = Options1->merge(Other: *Options2, Order: 0); |
140 | EXPECT_EQ("check1,check2,check3,check4" , *Options.Checks); |
141 | EXPECT_EQ(std::vector<std::string>({"hpp" , "hxx" }), |
142 | *Options.HeaderFileExtensions); |
143 | EXPECT_EQ(std::vector<std::string>({"cpp" , "cxx" }), |
144 | *Options.ImplementationFileExtensions); |
145 | EXPECT_EQ("filter2" , *Options.HeaderFilterRegex); |
146 | EXPECT_EQ("user2" , *Options.User); |
147 | ASSERT_TRUE(Options.ExtraArgs.has_value()); |
148 | EXPECT_EQ("arg1,arg2,arg3,arg4" , llvm::join(Options.ExtraArgs->begin(), |
149 | Options.ExtraArgs->end(), "," )); |
150 | ASSERT_TRUE(Options.ExtraArgsBefore.has_value()); |
151 | EXPECT_EQ("arg-before1,arg-before2,arg-before3,arg-before4" , |
152 | llvm::join(Options.ExtraArgsBefore->begin(), |
153 | Options.ExtraArgsBefore->end(), "," )); |
154 | ASSERT_TRUE(Options.UseColor.has_value()); |
155 | EXPECT_TRUE(*Options.UseColor); |
156 | |
157 | ASSERT_TRUE(Options.SystemHeaders.has_value()); |
158 | EXPECT_TRUE(*Options.SystemHeaders); |
159 | } |
160 | |
161 | namespace { |
162 | class DiagCollecter { |
163 | public: |
164 | struct Diag { |
165 | private: |
166 | static size_t posToOffset(const llvm::SMLoc Loc, |
167 | const llvm::SourceMgr *Src) { |
168 | return Loc.getPointer() - |
169 | Src->getMemoryBuffer(i: Src->FindBufferContainingLoc(Loc)) |
170 | ->getBufferStart(); |
171 | } |
172 | |
173 | public: |
174 | Diag(const llvm::SMDiagnostic &D) |
175 | : Message(D.getMessage()), Kind(D.getKind()), |
176 | Pos(posToOffset(Loc: D.getLoc(), Src: D.getSourceMgr())) { |
177 | if (!D.getRanges().empty()) { |
178 | // Ranges are stored as column numbers on the line that has the error. |
179 | unsigned Offset = Pos - D.getColumnNo(); |
180 | Range.emplace(); |
181 | Range->Begin = Offset + D.getRanges().front().first, |
182 | Range->End = Offset + D.getRanges().front().second; |
183 | } |
184 | } |
185 | std::string Message; |
186 | llvm::SourceMgr::DiagKind Kind; |
187 | size_t Pos; |
188 | std::optional<llvm::Annotations::Range> Range; |
189 | |
190 | friend void PrintTo(const Diag &D, std::ostream *OS) { |
191 | *OS << (D.Kind == llvm::SourceMgr::DK_Error ? "error: " : "warning: " ) |
192 | << D.Message << "@" << llvm::to_string(Value: D.Pos); |
193 | if (D.Range) |
194 | *OS << ":[" << D.Range->Begin << ", " << D.Range->End << ")" ; |
195 | } |
196 | }; |
197 | |
198 | DiagCollecter() = default; |
199 | DiagCollecter(const DiagCollecter &) = delete; |
200 | |
201 | std::function<void(const llvm::SMDiagnostic &)> |
202 | getCallback(bool Clear = true) & { |
203 | if (Clear) |
204 | Diags.clear(); |
205 | return [&](const llvm::SMDiagnostic &Diag) { Diags.emplace_back(args: Diag); }; |
206 | } |
207 | |
208 | std::function<void(const llvm::SMDiagnostic &)> |
209 | getCallback(bool Clear = true) && = delete; |
210 | |
211 | llvm::ArrayRef<Diag> getDiags() const { return Diags; } |
212 | |
213 | private: |
214 | std::vector<Diag> Diags; |
215 | }; |
216 | |
217 | MATCHER_P(DiagMessage, M, "" ) { return arg.Message == M; } |
218 | MATCHER_P(DiagKind, K, "" ) { return arg.Kind == K; } |
219 | MATCHER_P(DiagPos, P, "" ) { return arg.Pos == P; } |
220 | MATCHER_P(DiagRange, P, "" ) { return arg.Range && *arg.Range == P; } |
221 | } // namespace |
222 | |
223 | using ::testing::AllOf; |
224 | using ::testing::ElementsAre; |
225 | using ::testing::UnorderedElementsAre; |
226 | |
227 | TEST(ParseConfiguration, CollectDiags) { |
228 | DiagCollecter Collector; |
229 | auto ParseWithDiags = [&](llvm::StringRef Buffer) { |
230 | return parseConfigurationWithDiags(Config: llvm::MemoryBufferRef(Buffer, "Options" ), |
231 | Handler: Collector.getCallback()); |
232 | }; |
233 | llvm::Annotations Options(R"( |
234 | [[Check]]: llvm-include-order |
235 | )" ); |
236 | llvm::ErrorOr<ClangTidyOptions> ParsedOpt = ParseWithDiags(Options.code()); |
237 | EXPECT_TRUE(!ParsedOpt); |
238 | EXPECT_THAT(Collector.getDiags(), |
239 | testing::ElementsAre(AllOf(DiagMessage("unknown key 'Check'" ), |
240 | DiagKind(llvm::SourceMgr::DK_Error), |
241 | DiagPos(Options.range().Begin), |
242 | DiagRange(Options.range())))); |
243 | |
244 | Options = llvm::Annotations(R"( |
245 | UseColor: [[NotABool]] |
246 | )" ); |
247 | ParsedOpt = ParseWithDiags(Options.code()); |
248 | EXPECT_TRUE(!ParsedOpt); |
249 | EXPECT_THAT(Collector.getDiags(), |
250 | testing::ElementsAre(AllOf(DiagMessage("invalid boolean" ), |
251 | DiagKind(llvm::SourceMgr::DK_Error), |
252 | DiagPos(Options.range().Begin), |
253 | DiagRange(Options.range())))); |
254 | |
255 | Options = llvm::Annotations(R"( |
256 | SystemHeaders: [[NotABool]] |
257 | )" ); |
258 | ParsedOpt = ParseWithDiags(Options.code()); |
259 | EXPECT_TRUE(!ParsedOpt); |
260 | EXPECT_THAT(Collector.getDiags(), |
261 | testing::ElementsAre(AllOf(DiagMessage("invalid boolean" ), |
262 | DiagKind(llvm::SourceMgr::DK_Error), |
263 | DiagPos(Options.range().Begin), |
264 | DiagRange(Options.range())))); |
265 | } |
266 | |
267 | namespace { |
268 | class TestCheck : public ClangTidyCheck { |
269 | public: |
270 | TestCheck(ClangTidyContext *Context) : ClangTidyCheck("test" , Context) {} |
271 | |
272 | template <typename... Args> auto getLocal(Args &&... Arguments) { |
273 | return Options.get(std::forward<Args>(Arguments)...); |
274 | } |
275 | |
276 | template <typename... Args> auto getGlobal(Args &&... Arguments) { |
277 | return Options.getLocalOrGlobal(std::forward<Args>(Arguments)...); |
278 | } |
279 | |
280 | template <typename IntType = int, typename... Args> |
281 | auto getIntLocal(Args &&... Arguments) { |
282 | return Options.get<IntType>(std::forward<Args>(Arguments)...); |
283 | } |
284 | |
285 | template <typename IntType = int, typename... Args> |
286 | auto getIntGlobal(Args &&... Arguments) { |
287 | return Options.getLocalOrGlobal<IntType>(std::forward<Args>(Arguments)...); |
288 | } |
289 | }; |
290 | |
291 | #define CHECK_VAL(Value, Expected) \ |
292 | do { \ |
293 | auto Item = Value; \ |
294 | ASSERT_TRUE(!!Item); \ |
295 | EXPECT_EQ(*Item, Expected); \ |
296 | } while (false) |
297 | |
298 | MATCHER_P(ToolDiagMessage, M, "" ) { return arg.Message.Message == M; } |
299 | MATCHER_P(ToolDiagLevel, L, "" ) { return arg.DiagLevel == L; } |
300 | |
301 | } // namespace |
302 | |
303 | } // namespace test |
304 | |
305 | static constexpr auto Warning = tooling::Diagnostic::Warning; |
306 | static constexpr auto Error = tooling::Diagnostic::Error; |
307 | |
308 | static void PrintTo(const ClangTidyError &Err, ::std::ostream *OS) { |
309 | *OS << (Err.DiagLevel == Error ? "error: " : "warning: " ) |
310 | << Err.Message.Message; |
311 | } |
312 | |
313 | namespace test { |
314 | |
315 | TEST(CheckOptionsValidation, MissingOptions) { |
316 | ClangTidyOptions Options; |
317 | ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( |
318 | args: ClangTidyGlobalOptions(), args&: Options)); |
319 | ClangTidyDiagnosticConsumer DiagConsumer(Context); |
320 | DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, |
321 | &DiagConsumer, false); |
322 | Context.setDiagnosticsEngine(&DE); |
323 | TestCheck TestCheck(&Context); |
324 | EXPECT_FALSE(TestCheck.getLocal("Opt" )); |
325 | EXPECT_EQ(TestCheck.getLocal("Opt" , "Unknown" ), "Unknown" ); |
326 | // Missing options aren't errors. |
327 | EXPECT_TRUE(DiagConsumer.take().empty()); |
328 | } |
329 | |
330 | TEST(CheckOptionsValidation, ValidIntOptions) { |
331 | ClangTidyOptions Options; |
332 | auto &CheckOptions = Options.CheckOptions; |
333 | CheckOptions["test.IntExpected" ] = "1" ; |
334 | CheckOptions["test.IntInvalid1" ] = "1WithMore" ; |
335 | CheckOptions["test.IntInvalid2" ] = "NoInt" ; |
336 | CheckOptions["GlobalIntExpected" ] = "1" ; |
337 | CheckOptions["GlobalIntInvalid" ] = "NoInt" ; |
338 | CheckOptions["test.DefaultedIntInvalid" ] = "NoInt" ; |
339 | CheckOptions["test.BoolITrueValue" ] = "1" ; |
340 | CheckOptions["test.BoolIFalseValue" ] = "0" ; |
341 | CheckOptions["test.BoolTrueValue" ] = "true" ; |
342 | CheckOptions["test.BoolFalseValue" ] = "false" ; |
343 | CheckOptions["test.BoolTrueShort" ] = "Y" ; |
344 | CheckOptions["test.BoolFalseShort" ] = "N" ; |
345 | CheckOptions["test.BoolUnparseable" ] = "Nothing" ; |
346 | |
347 | ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( |
348 | args: ClangTidyGlobalOptions(), args&: Options)); |
349 | ClangTidyDiagnosticConsumer DiagConsumer(Context); |
350 | DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, |
351 | &DiagConsumer, false); |
352 | Context.setDiagnosticsEngine(&DE); |
353 | TestCheck TestCheck(&Context); |
354 | |
355 | CHECK_VAL(TestCheck.getIntLocal("IntExpected" ), 1); |
356 | CHECK_VAL(TestCheck.getIntGlobal("GlobalIntExpected" ), 1); |
357 | EXPECT_FALSE(TestCheck.getIntLocal("IntInvalid1" ).has_value()); |
358 | EXPECT_FALSE(TestCheck.getIntLocal("IntInvalid2" ).has_value()); |
359 | EXPECT_FALSE(TestCheck.getIntGlobal("GlobalIntInvalid" ).has_value()); |
360 | ASSERT_EQ(TestCheck.getIntLocal("DefaultedIntInvalid" , 1), 1); |
361 | |
362 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolITrueValue" ), true); |
363 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolIFalseValue" ), false); |
364 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolTrueValue" ), true); |
365 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolFalseValue" ), false); |
366 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolTrueShort" ), true); |
367 | CHECK_VAL(TestCheck.getIntLocal<bool>("BoolFalseShort" ), false); |
368 | EXPECT_FALSE(TestCheck.getIntLocal<bool>("BoolUnparseable" )); |
369 | |
370 | EXPECT_THAT( |
371 | DiagConsumer.take(), |
372 | UnorderedElementsAre( |
373 | AllOf(ToolDiagMessage( |
374 | "invalid configuration value '1WithMore' for option " |
375 | "'test.IntInvalid1'; expected an integer" ), |
376 | ToolDiagLevel(Warning)), |
377 | AllOf( |
378 | ToolDiagMessage("invalid configuration value 'NoInt' for option " |
379 | "'test.IntInvalid2'; expected an integer" ), |
380 | ToolDiagLevel(Warning)), |
381 | AllOf( |
382 | ToolDiagMessage("invalid configuration value 'NoInt' for option " |
383 | "'GlobalIntInvalid'; expected an integer" ), |
384 | ToolDiagLevel(Warning)), |
385 | AllOf(ToolDiagMessage( |
386 | "invalid configuration value 'NoInt' for option " |
387 | "'test.DefaultedIntInvalid'; expected an integer" ), |
388 | ToolDiagLevel(Warning)), |
389 | AllOf(ToolDiagMessage( |
390 | "invalid configuration value 'Nothing' for option " |
391 | "'test.BoolUnparseable'; expected a bool" ), |
392 | ToolDiagLevel(Warning)))); |
393 | } |
394 | |
395 | TEST(ValidConfiguration, ValidEnumOptions) { |
396 | |
397 | ClangTidyOptions Options; |
398 | auto &CheckOptions = Options.CheckOptions; |
399 | |
400 | CheckOptions["test.Valid" ] = "Red" ; |
401 | CheckOptions["test.Invalid" ] = "Scarlet" ; |
402 | CheckOptions["test.ValidWrongCase" ] = "rED" ; |
403 | CheckOptions["test.NearMiss" ] = "Oragne" ; |
404 | CheckOptions["GlobalValid" ] = "Violet" ; |
405 | CheckOptions["GlobalInvalid" ] = "Purple" ; |
406 | CheckOptions["GlobalValidWrongCase" ] = "vIOLET" ; |
407 | CheckOptions["GlobalNearMiss" ] = "Yelow" ; |
408 | |
409 | ClangTidyContext Context(std::make_unique<DefaultOptionsProvider>( |
410 | args: ClangTidyGlobalOptions(), args&: Options)); |
411 | ClangTidyDiagnosticConsumer DiagConsumer(Context); |
412 | DiagnosticsEngine DE(new DiagnosticIDs(), new DiagnosticOptions, |
413 | &DiagConsumer, false); |
414 | Context.setDiagnosticsEngine(&DE); |
415 | TestCheck TestCheck(&Context); |
416 | |
417 | CHECK_VAL(TestCheck.getIntLocal<Colours>("Valid" ), Colours::Red); |
418 | CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValid" ), Colours::Violet); |
419 | |
420 | CHECK_VAL( |
421 | TestCheck.getIntLocal<Colours>("ValidWrongCase" , /*IgnoreCase*/ true), |
422 | Colours::Red); |
423 | CHECK_VAL(TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase" , |
424 | /*IgnoreCase*/ true), |
425 | Colours::Violet); |
426 | |
427 | EXPECT_FALSE(TestCheck.getIntLocal<Colours>("ValidWrongCase" ).has_value()); |
428 | EXPECT_FALSE(TestCheck.getIntLocal<Colours>("NearMiss" ).has_value()); |
429 | EXPECT_FALSE(TestCheck.getIntGlobal<Colours>("GlobalInvalid" ).has_value()); |
430 | EXPECT_FALSE( |
431 | TestCheck.getIntGlobal<Colours>("GlobalValidWrongCase" ).has_value()); |
432 | EXPECT_FALSE(TestCheck.getIntGlobal<Colours>("GlobalNearMiss" ).has_value()); |
433 | |
434 | EXPECT_FALSE(TestCheck.getIntLocal<Colours>("Invalid" ).has_value()); |
435 | EXPECT_THAT( |
436 | DiagConsumer.take(), |
437 | UnorderedElementsAre( |
438 | AllOf(ToolDiagMessage("invalid configuration value " |
439 | "'Scarlet' for option 'test.Invalid'" ), |
440 | ToolDiagLevel(Warning)), |
441 | AllOf(ToolDiagMessage("invalid configuration value 'rED' for option " |
442 | "'test.ValidWrongCase'; did you mean 'Red'?" ), |
443 | ToolDiagLevel(Warning)), |
444 | AllOf( |
445 | ToolDiagMessage("invalid configuration value 'Oragne' for option " |
446 | "'test.NearMiss'; did you mean 'Orange'?" ), |
447 | ToolDiagLevel(Warning)), |
448 | AllOf(ToolDiagMessage("invalid configuration value " |
449 | "'Purple' for option 'GlobalInvalid'" ), |
450 | ToolDiagLevel(Warning)), |
451 | AllOf( |
452 | ToolDiagMessage("invalid configuration value 'vIOLET' for option " |
453 | "'GlobalValidWrongCase'; did you mean 'Violet'?" ), |
454 | ToolDiagLevel(Warning)), |
455 | AllOf( |
456 | ToolDiagMessage("invalid configuration value 'Yelow' for option " |
457 | "'GlobalNearMiss'; did you mean 'Yellow'?" ), |
458 | ToolDiagLevel(Warning)))); |
459 | } |
460 | |
461 | #undef CHECK_VAL |
462 | |
463 | } // namespace test |
464 | } // namespace tidy |
465 | } // namespace clang |
466 | |