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 std::vector<std::unique_ptr<Provider>> Providers;
62 Providers.push_back(std::make_unique<FakeProvider>(
"foo"));
63 Providers.push_back(std::make_unique<FakeProvider>(
"bar"));
65 Config Cfg = Combined->getConfig(
Params(), Diags.callback());
66 EXPECT_THAT(Diags.Diagnostics,
67 ElementsAre(diagMessage(
"foo"), diagMessage(
"bar")));
68 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo1",
"bar1"));
69 Diags.Diagnostics.clear();
71 Cfg = Combined->getConfig(
Params(), Diags.callback());
72 EXPECT_THAT(Diags.Diagnostics,
73 ElementsAre(diagMessage(
"foo"), diagMessage(
"bar")));
74 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo2",
"bar2"));
77const char *AddFooWithErr = R
"yaml(
83const char *AddFooWithTypoErr = R
"yaml(
89const char *AddBarBaz = R
"yaml(
97TEST(ProviderTest, FromYAMLFile) {
99 FS.Files["foo.yaml"] = AddFooWithErr;
103 auto Cfg =
P->getConfig(
Params(), Diags.callback());
104 EXPECT_THAT(Diags.Diagnostics,
105 ElementsAre(diagMessage(
"Unknown CompileFlags key 'Unknown'")));
106 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
107 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
110 Cfg =
P->getConfig(
Params(), Diags.callback());
111 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Cached, not re-parsed";
112 EXPECT_THAT(Diags.Files, IsEmpty());
113 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
115 FS.Files[
"foo.yaml"] = AddFooWithTypoErr;
116 Cfg =
P->getConfig(
Params(), Diags.callback());
119 ElementsAre(diagMessage(
120 "Unknown CompileFlags key 'Removr'; did you mean 'Remove'?")));
121 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
122 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
125 FS.Files[
"foo.yaml"] = AddBarBaz;
126 Cfg =
P->getConfig(
Params(), Diags.callback());
127 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"New config, no errors";
128 EXPECT_THAT(Diags.Files, ElementsAre(
testPath(
"foo.yaml")));
129 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar",
"baz"));
132 FS.Files.erase(
"foo.yaml");
133 Cfg =
P->getConfig(
Params(), Diags.callback());
134 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Missing file is not an error";
135 EXPECT_THAT(Diags.Files, IsEmpty());
136 EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
139TEST(ProviderTest, FromAncestorRelativeYAMLFiles) {
141 FS.Files[
"a/b/c/foo.yaml"] = AddBarBaz;
142 FS.Files[
"a/foo.yaml"] = AddFooWithErr;
144 std::string ABCPath =
145 testPath(
"a/b/c/d/test.cc", llvm::sys::path::Style::posix);
147 ABCParams.
Path = ABCPath;
149 testPath(
"a/b/e/f/test.cc", llvm::sys::path::Style::posix);
151 AParams.
Path = APath;
156 auto Cfg =
P->getConfig(
Params(), Diags.callback());
157 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
158 EXPECT_THAT(Diags.Files, IsEmpty());
159 EXPECT_THAT(getAddedArgs(Cfg), IsEmpty());
161 Cfg =
P->getConfig(ABCParams, Diags.callback());
162 EXPECT_THAT(Diags.Diagnostics,
163 ElementsAre(diagMessage(
"Unknown CompileFlags key 'Unknown'")));
165 EXPECT_THAT(Diags.Files,
167 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo",
"bar",
"baz"));
170 Cfg =
P->getConfig(AParams, Diags.callback());
171 EXPECT_THAT(Diags.Diagnostics, IsEmpty()) <<
"Cached config";
172 EXPECT_THAT(Diags.Files, IsEmpty());
173 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"foo"));
175 FS.Files.erase(
"a/foo.yaml");
176 Cfg =
P->getConfig(ABCParams, Diags.callback());
177 EXPECT_THAT(Diags.Diagnostics, IsEmpty());
178 EXPECT_THAT(Diags.Files, IsEmpty());
179 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar",
"baz"));
182TEST(ProviderTest, SourceInfo) {
185 FS.Files[
"baz/foo.yaml"] = R
"yaml(
192 const auto BarPath =
testPath(
"baz/bar.h", llvm::sys::path::Style::posix);
201 auto Cfg =
P->getConfig(Bar, Diags.callback());
202 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
203 EXPECT_THAT(getAddedArgs(Cfg), ElementsAre(
"bar"));
208 Cfg =
P->getConfig(Bar, Diags.callback());
209 ASSERT_THAT(Diags.Diagnostics, IsEmpty());
210 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< std::unique_ptr< 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::ProBoundsAvoidUncheckedContainerAccessCheck 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.