13#include "llvm/Support/Path.h"
14#include "llvm/Support/SourceMgr.h"
15#include "gmock/gmock.h"
16#include "gtest/gtest.h"
24using ::testing::ElementsAre;
25using ::testing::IsEmpty;
30class FakeProvider :
public Provider {
32 mutable std::atomic<unsigned> Index = {0};
34 std::vector<CompiledFragment>
36 DC(llvm::SMDiagnostic(
"", llvm::SourceMgr::DK_Error, Prefix));
38 [Arg(Prefix + std::to_string(++Index))](
const Params &
P,
Config &
C) {
39 C.CompileFlags.Edits.push_back(
40 [Arg](std::vector<std::string> &Argv) { Argv.push_back(Arg); });
47 FakeProvider(llvm::StringRef Prefix) : Prefix(Prefix) {}
50std::vector<std::string> getAddedArgs(
Config &C) {
51 std::vector<std::string> Argv;
52 for (
auto &Edit :
C.CompileFlags.Edits)
59TEST(ProviderTest, Combine) {
61 FakeProvider Foo(
"foo");
62 FakeProvider Bar(
"bar");
64 Config Cfg = Combined->getConfig(
Params(), Diags.callback());
65 EXPECT_THAT(Diags.Diagnostics,
66 ElementsAre(diagMessage(
"foo"), diagMessage(
"bar")));
67 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo1",
"bar1"));
68 Diags.Diagnostics.clear();
70 Cfg = Combined->getConfig(
Params(), Diags.callback());
71 EXPECT_THAT(Diags.Diagnostics,
72 ElementsAre(diagMessage(
"foo"), diagMessage(
"bar")));
73 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo2",
"bar2"));
76const char *AddFooWithErr = R
"yaml(
82const char *AddFooWithTypoErr = R
"yaml(
88const char *AddBarBaz = R
"yaml(
96TEST(ProviderTest, FromYAMLFile) {
98 FS.Files["foo.yaml"] = AddFooWithErr;
102 auto Cfg =
P->getConfig(
Params(), Diags.callback());
103 EXPECT_THAT(Diags.Diagnostics,
104 ElementsAre(diagMessage(
"Unknown CompileFlags key 'Unknown'")));
105 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
106 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
109 Cfg =
P->getConfig(
Params(), Diags.callback());
110 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Cached, not re-parsed";
111 EXPECT_THAT(Diags.Files, IsEmpty());
112 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
114 FS.Files[
"foo.yaml"] = AddFooWithTypoErr;
115 Cfg =
P->getConfig(
Params(), Diags.callback());
118 ElementsAre(diagMessage(
119 "Unknown CompileFlags key 'Removr'; did you mean 'Remove'?")));
120 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
121 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
124 FS.Files[
"foo.yaml"] = AddBarBaz;
125 Cfg =
P->getConfig(
Params(), Diags.callback());
126 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"New config, no errors";
127 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
128 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar",
"baz"));
131 FS.Files.erase(
"foo.yaml");
132 Cfg =
P->getConfig(
Params(), Diags.callback());
133 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Missing file is not an error";
134 EXPECT_THAT(Diags.Files, IsEmpty());
135 EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
138TEST(ProviderTest, FromAncestorRelativeYAMLFiles) {
140 FS.Files[
"a/b/c/foo.yaml"] = AddBarBaz;
141 FS.Files[
"a/foo.yaml"] = AddFooWithErr;
143 std::string ABCPath =
144 testPath(
"a/b/c/d/test.cc", llvm::sys::path::Style::posix);
146 ABCParams.
Path = ABCPath;
148 testPath(
"a/b/e/f/test.cc", llvm::sys::path::Style::posix);
150 AParams.
Path = APath;
155 auto Cfg =
P->getConfig(
Params(), Diags.callback());
156 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
157 EXPECT_THAT(Diags.Files, IsEmpty());
158 EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
160 Cfg =
P->getConfig(ABCParams, Diags.callback());
161 EXPECT_THAT(Diags.Diagnostics,
162 ElementsAre(diagMessage(
"Unknown CompileFlags key 'Unknown'")));
164 EXPECT_THAT(Diags.Files,
166 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo",
"bar",
"baz"));
169 Cfg =
P->getConfig(AParams, Diags.callback());
170 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Cached config";
171 EXPECT_THAT(Diags.Files, IsEmpty());
172 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
174 FS.Files.erase(
"a/foo.yaml");
175 Cfg =
P->getConfig(ABCParams, Diags.callback());
176 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
177 EXPECT_THAT(Diags.Files, IsEmpty());
178 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar",
"baz"));
181TEST(ProviderTest, SourceInfo) {
184 FS.Files[
"baz/foo.yaml"] = R
"yaml(
191 const auto BarPath =
testPath(
"baz/bar.h", llvm::sys::path::Style::posix);
200 auto Cfg =
P->getConfig(Bar, Diags.callback());
201 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
202 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar"));
207 Cfg =
P->getConfig(Bar, Diags.callback());
208 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
209 EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
static cl::opt< std::string > Config("config", desc(R"(
Specifies a configuration in YAML/JSON format:
-config="{Checks:' *', CheckOptions:{x:y}}"
When the value is empty, clang-tidy will
attempt to find a file named .clang-tidy for
each source file in its parent directories.
)"), cl::init(""), cl::cat(ClangTidyCategory))
A source of configuration fragments.
static std::unique_ptr< Provider > fromYAMLFile(llvm::StringRef AbsPath, llvm::StringRef Directory, const ThreadsafeFS &, bool Trusted=false)
Reads fragments from a single YAML file with a fixed path.
static std::unique_ptr< Provider > fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath, const ThreadsafeFS &, bool Trusted=false)
static std::unique_ptr< Provider > combine(std::vector< const Provider * >)
A provider that includes fragments from all the supplied providers.
std::function< bool(const Params &, Config &)> CompiledFragment
A chunk of configuration that has been fully analyzed and is ready to apply.
llvm::function_ref< void(const llvm::SMDiagnostic &)> DiagnosticCallback
Used to report problems in parsing or interpreting a config.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
std::string testPath(PathRef File, llvm::sys::path::Style Style)
TEST(BackgroundQueueTest, Priority)
cppcoreguidelines::ProBoundsAvoidUncheckedContainerAccess P
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Describes the context used to evaluate configuration fragments.
llvm::StringRef Path
Absolute path to a source file we're applying the config to.