12 #include "clang/Basic/LLVM.h"
13 #include "llvm/ADT/SmallString.h"
14 #include "llvm/Support/Debug.h"
15 #include "llvm/Support/Errc.h"
16 #include "llvm/Support/FileSystem.h"
17 #include "llvm/Support/Path.h"
18 #include "llvm/Support/YAMLTraits.h"
19 #include "llvm/Support/raw_ostream.h"
22 #define DEBUG_TYPE "clang-tidy-options"
28 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(
FileFilter::LineRange)
30 LLVM_YAML_IS_SEQUENCE_VECTOR(std::
string)
36 template <>
struct SequenceTraits<
FileFilter::LineRange> {
37 static size_t size(IO &IO, FileFilter::LineRange &
Range) {
38 return Range.first == 0 ? 0 : Range.second == 0 ? 1 : 2;
40 static unsigned &
element(IO &IO, FileFilter::LineRange &
Range,
size_t Index) {
42 IO.setError(
"Too many elements in line range.");
43 return Index == 0 ? Range.first : Range.second;
49 IO.mapRequired(
"name", File.
Name);
53 if (File.
Name.empty())
54 return "No file name specified";
56 if (Range.first <= 0 || Range.second <= 0)
57 return "Invalid line range";
64 static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) {
65 IO.mapRequired(
"key", KeyValue.first);
66 IO.mapRequired(
"value", KeyValue.second);
72 NOptionMap(IO &,
const ClangTidyOptions::OptionMap &OptionMap)
73 : Options(OptionMap.begin(), OptionMap.end()) {}
75 ClangTidyOptions::OptionMap Map;
76 for (
const auto &KeyValue : Options)
77 Map[KeyValue.first] = KeyValue.second;
80 std::vector<ClangTidyOptions::StringPair>
Options;
85 MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
87 IO.mapOptional(
"Checks", Options.
Checks);
90 IO.mapOptional(
"User", Options.
User);
91 IO.mapOptional(
"CheckOptions", NOpts->Options);
92 IO.mapOptional(
"ExtraArgs", Options.
ExtraArgs);
109 Options.
User = llvm::None;
110 for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
111 E = ClangTidyModuleRegistry::end();
113 Options = Options.
mergeWith(I->instantiate()->getModuleOptions());
151 OverrideOptions(OverrideOptions) {
162 OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {
170 DEBUG(llvm::dbgs() <<
"Getting options for file " << FileName <<
"...\n");
171 SmallString<256> FilePath(FileName);
173 if (std::error_code EC = llvm::sys::fs::make_absolute(FilePath)) {
174 llvm::errs() <<
"Can't make absolute path from " << FileName <<
": "
175 << EC.message() <<
"\n";
183 StringRef
Path = llvm::sys::path::parent_path(FileName);
184 for (StringRef CurrentPath = Path;;
185 CurrentPath = llvm::sys::path::parent_path(CurrentPath)) {
186 llvm::Optional<ClangTidyOptions>
Result;
190 Result = Iter->second;
197 while (Path != CurrentPath) {
198 DEBUG(llvm::dbgs() <<
"Caching configuration for path " << Path
201 Path = llvm::sys::path::parent_path(Path);
208 llvm::Optional<ClangTidyOptions>
210 assert(!Directory.empty());
212 if (!llvm::sys::fs::is_directory(Directory)) {
213 llvm::errs() <<
"Error reading configuration from " << Directory
214 <<
": directory doesn't exist.\n";
219 SmallString<128> ConfigFile(Directory);
220 llvm::sys::path::append(ConfigFile, ConfigHandler.first);
221 DEBUG(llvm::dbgs() <<
"Trying " << ConfigFile <<
"...\n");
226 llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
230 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> Text =
231 llvm::MemoryBuffer::getFile(ConfigFile.c_str());
232 if (std::error_code EC = Text.getError()) {
233 llvm::errs() <<
"Can't read " << ConfigFile <<
": " << EC.message()
240 if ((*Text)->getBuffer().empty())
242 llvm::ErrorOr<ClangTidyOptions> ParsedOptions =
243 ConfigHandler.second((*Text)->getBuffer());
244 if (!ParsedOptions) {
245 if (ParsedOptions.getError())
246 llvm::errs() <<
"Error parsing " << ConfigFile <<
": "
247 << ParsedOptions.getError().message() <<
"\n";
261 llvm::yaml::Input Input(LineFilter);
263 return Input.error();
267 llvm::yaml::Input Input(Config);
271 return Input.error();
277 llvm::raw_string_ostream Stream(Text);
278 llvm::yaml::Output Output(Stream);
282 Output << NonConstValue;
llvm::Optional< std::string > Checks
Checks filter.
llvm::Optional< ArgList > ExtraArgs
Add extra compilation arguments to the end of the list.
llvm::Optional< std::string > User
Specifies the name or e-mail of the user running clang-tidy.
llvm::Optional< std::string > HeaderFilterRegex
Output warnings from headers matching this filter.
static void mapping(IO &IO, FileFilter &File)
Contains options for clang-tidy.
std::error_code parseLineFilter(StringRef LineFilter, clang::tidy::ClangTidyGlobalOptions &Options)
Parses -line-filter option and stores it to the Options.
std::vector< HeaderHandle > Path
llvm::ErrorOr< ClangTidyOptions > parseConfiguration(StringRef Config)
static StringRef validate(IO &io, FileFilter &File)
NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
OptionMap CheckOptions
Key-value mapping used to store check-specific options.
llvm::Optional< bool > SystemHeaders
Output warnings from system headers matching HeaderFilterRegex.
ClangTidyOptions OverrideOptions
ConfigFileHandlers ConfigHandlers
llvm::Optional< ArgList > ExtraArgsBefore
Add extra compilation arguments to the start of the list.
static cl::opt< std::string > LineFilter("line-filter", cl::desc("List of files with line ranges to filter the\n""warnings. Can be used together with\n""-header-filter. The format of the list is a JSON\n""array of objects:\n"" [\n"" {\"name\":\"file1.cpp\",\"lines\":[[1,3],[5,7]]},\n"" {\"name\":\"file2.h\"}\n"" ]"), cl::init(""), cl::cat(ClangTidyCategory))
static cl::opt< std::string > Directory(cl::Positional, cl::Required, cl::desc("<Search Root Directory>"))
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
static unsigned & element(IO &IO, FileFilter::LineRange &Range, size_t Index)
static void mapping(IO &IO, ClangTidyOptions &Options)
std::vector< FileFilter > LineFilter
Output warnings from certain line ranges of certain files only.
ClangTidyOptions getOptions(llvm::StringRef) override
Returns options applying to a specific translation unit with the specified FileName.
ClangTidyOptions mergeWith(const ClangTidyOptions &Other) const
Creates a new ClangTidyOptions instance combined from all fields of this instance overridden by the f...
static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue)
std::pair< std::string, std::function< llvm::ErrorOr< ClangTidyOptions > llvm::StringRef)> > ConfigFileHandler
std::vector< ConfigFileHandler > ConfigFileHandlers
Configuration file handlers listed in the order of priority.
llvm::Optional< ClangTidyOptions > TryReadConfigFile(llvm::StringRef Directory)
Try to read configuration files from Directory using registered ConfigHandlers.
Contains a list of line ranges in a single file.
static cl::opt< std::string > Config("config", cl::desc("Specifies a configuration in YAML/JSON format:\n"" -config=\"{Checks: '*', CheckOptions: [{key: x, value: y}]}\"\n""When the value is empty, clang-tidy will attempt to find\n""a file named .clang-tidy for each source file in its parent\n""directories."), cl::init(""), cl::cat(ClangTidyCategory))
llvm::Optional< bool > AnalyzeTemporaryDtors
Turns on temporary destructor-based analysis.
llvm::StringMap< ClangTidyOptions > CachedOptions
CharSourceRange Range
SourceRange for the file name.
std::vector< ClangTidyOptions::StringPair > Options
static size_t size(IO &IO, FileFilter::LineRange &Range)
ClangTidyOptions getOptions(llvm::StringRef FileName) override
Returns options applying to a specific translation unit with the specified FileName.
ClangTidyOptions::OptionMap denormalize(IO &)
std::vector< LineRange > LineRanges
A list of line ranges in this file, for which we show warnings.
static ClangTidyOptions getDefaults()
These options are used for all settings that haven't been overridden by the OptionsProvider.
FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, const ClangTidyOptions &DefaultOptions, const ClangTidyOptions &OverrideOptions)
Initializes the FileOptionsProvider instance.
std::string Name
File name.
Implementation of the ClangTidyOptionsProvider interface, which returns the same options for all file...