clang-tools 3.8.0

- Main Page
- Namespaces
- Classes
- Files

- File List
- File Members

ClangTidyOptions.cpp
Go to the documentation of this file.
1 //===--- ClangTidyOptions.cpp - clang-tidy ----------------------*- C++ -*-===//
2 //
3 // The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ClangTidyOptions.h"
11 #include "ClangTidyModuleRegistry.h"
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"
20 #include <utility>
21
22 #define DEBUG_TYPE "clang-tidy-options"
23
24 using clang::tidy::ClangTidyOptions;
25 using clang::tidy::FileFilter;
26
27 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter)
28 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(FileFilter::LineRange)
29 LLVM_YAML_IS_SEQUENCE_VECTOR(ClangTidyOptions::StringPair)
30 LLVM_YAML_IS_SEQUENCE_VECTOR(std::string)
31
32 namespace llvm {
33 namespace yaml {
34
35 // Map std::pair<int, int> to a JSON array of size 2.
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;
39 }
40 static unsigned &element(IO &IO, FileFilter::LineRange &Range, size_t Index) {
41 if (Index > 1)
42 IO.setError("Too many elements in line range.");
43 return Index == 0 ? Range.first : Range.second;
44 }
45 };
46
47 template <> struct MappingTraits<FileFilter> {
48 static void mapping(IO &IO, FileFilter &File) {
49 IO.mapRequired("name", File.Name);
50 IO.mapOptional("lines", File.LineRanges);
51 }
52 static StringRef validate(IO &io, FileFilter &File) {
53 if (File.Name.empty())
54 return "No file name specified";
55 for (const FileFilter::LineRange &Range : File.LineRanges) {
56 if (Range.first <= 0 || Range.second <= 0)
57 return "Invalid line range";
58 }
59 return StringRef();
60 }
61 };
62
63 template <> struct MappingTraits<ClangTidyOptions::StringPair> {
64 static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue) {
65 IO.mapRequired("key", KeyValue.first);
66 IO.mapRequired("value", KeyValue.second);
67 }
68 };
69
70 struct NOptionMap {
71 NOptionMap(IO &) {}
72 NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
73 : Options(OptionMap.begin(), OptionMap.end()) {}
74 ClangTidyOptions::OptionMap denormalize(IO &) {
75 ClangTidyOptions::OptionMap Map;
76 for (const auto &KeyValue : Options)
77 Map[KeyValue.first] = KeyValue.second;
78 return Map;
79 }
80 std::vector<ClangTidyOptions::StringPair> Options;
81 };
82
83 template <> struct MappingTraits<ClangTidyOptions> {
84 static void mapping(IO &IO, ClangTidyOptions &Options) {
85 MappingNormalization<NOptionMap, ClangTidyOptions::OptionMap> NOpts(
86 IO, Options.CheckOptions);
87 IO.mapOptional("Checks", Options.Checks);
88 IO.mapOptional("HeaderFilterRegex", Options.HeaderFilterRegex);
89 IO.mapOptional("AnalyzeTemporaryDtors", Options.AnalyzeTemporaryDtors);
90 IO.mapOptional("User", Options.User);
91 IO.mapOptional("CheckOptions", NOpts->Options);
92 IO.mapOptional("ExtraArgs", Options.ExtraArgs);
93 IO.mapOptional("ExtraArgsBefore", Options.ExtraArgsBefore);
94 }
95 };
96
97 } // namespace yaml
98 } // namespace llvm
99
100 namespace clang {
101 namespace tidy {
102
103 ClangTidyOptions ClangTidyOptions::getDefaults() {
104 ClangTidyOptions Options;
105 Options.Checks = "";
106 Options.HeaderFilterRegex = "";
107 Options.SystemHeaders = false;
108 Options.AnalyzeTemporaryDtors = false;
109 Options.User = llvm::None;
110 for (ClangTidyModuleRegistry::iterator I = ClangTidyModuleRegistry::begin(),
111 E = ClangTidyModuleRegistry::end();
112 I != E; ++I)
113 Options = Options.mergeWith(I->instantiate()->getModuleOptions());
114 return Options;
115 }
116
117 ClangTidyOptions
118 ClangTidyOptions::mergeWith(const ClangTidyOptions &Other) const {
119 ClangTidyOptions Result = *this;
120
121 // Merge comma-separated glob lists by appending the new value after a comma.
122 if (Other.Checks)
123 Result.Checks =
124 (Result.Checks && !Result.Checks->empty() ? *Result.Checks + "," : "") +
125 *Other.Checks;
126
127 if (Other.HeaderFilterRegex)
128 Result.HeaderFilterRegex = Other.HeaderFilterRegex;
129 if (Other.SystemHeaders)
130 Result.SystemHeaders = Other.SystemHeaders;
131 if (Other.AnalyzeTemporaryDtors)
132 Result.AnalyzeTemporaryDtors = Other.AnalyzeTemporaryDtors;
133 if (Other.User)
134 Result.User = Other.User;
135 if (Other.ExtraArgs)
136 Result.ExtraArgs = Other.ExtraArgs;
137 if (Other.ExtraArgsBefore)
138 Result.ExtraArgsBefore = Other.ExtraArgsBefore;
139
140 for (const auto &KeyValue : Other.CheckOptions)
141 Result.CheckOptions[KeyValue.first] = KeyValue.second;
142
143 return Result;
144 }
145
146 FileOptionsProvider::FileOptionsProvider(
147 const ClangTidyGlobalOptions &GlobalOptions,
148 const ClangTidyOptions &DefaultOptions,
149 const ClangTidyOptions &OverrideOptions)
150 : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
151 OverrideOptions(OverrideOptions) {
152 ConfigHandlers.emplace_back(".clang-tidy", parseConfiguration);
153 CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
154 }
155
156 FileOptionsProvider::FileOptionsProvider(
157 const ClangTidyGlobalOptions &GlobalOptions,
158 const ClangTidyOptions &DefaultOptions,
159 const ClangTidyOptions &OverrideOptions,
160 const FileOptionsProvider::ConfigFileHandlers &ConfigHandlers)
161 : DefaultOptionsProvider(GlobalOptions, DefaultOptions),
162 OverrideOptions(OverrideOptions), ConfigHandlers(ConfigHandlers) {
163 CachedOptions[""] = DefaultOptions.mergeWith(OverrideOptions);
164 }
165
166 // FIXME: This method has some common logic with clang::format::getStyle().
167 // Consider pulling out common bits to a findParentFileWithName function or
168 // similar.
169 ClangTidyOptions FileOptionsProvider::getOptions(StringRef FileName) {
170 DEBUG(llvm::dbgs() << "Getting options for file " << FileName << "...\n");
171 SmallString<256> FilePath(FileName);
172
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";
176 // FIXME: Figure out what to do.
177 } else {
178 FileName = FilePath;
179 }
180
181 // Look for a suitable configuration file in all parent directories of the
182 // file. Start with the immediate parent directory and move up.
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;
187
188 auto Iter = CachedOptions.find(CurrentPath);
189 if (Iter != CachedOptions.end())
190 Result = Iter->second;
191
192 if (!Result)
193 Result = TryReadConfigFile(CurrentPath);
194
195 if (Result) {
196 // Store cached value for all intermediate directories.
197 while (Path != CurrentPath) {
198 DEBUG(llvm::dbgs() << "Caching configuration for path " << Path
199 << ".\n");
200 CachedOptions[Path] = *Result;
201 Path = llvm::sys::path::parent_path(Path);
202 }
203 return CachedOptions[Path] = *Result;
204 }
205 }
206 }
207
208 llvm::Optional<ClangTidyOptions>
209 FileOptionsProvider::TryReadConfigFile(StringRef Directory) {
210 assert(!Directory.empty());
211
212 if (!llvm::sys::fs::is_directory(Directory)) {
213 llvm::errs() << "Error reading configuration from " << Directory
214 << ": directory doesn't exist.\n";
215 return llvm::None;
216 }
217
218 for (const ConfigFileHandler &ConfigHandler : ConfigHandlers) {
219 SmallString<128> ConfigFile(Directory);
220 llvm::sys::path::append(ConfigFile, ConfigHandler.first);
221 DEBUG(llvm::dbgs() << "Trying " << ConfigFile << "...\n");
222
223 bool IsFile = false;
224 // Ignore errors from is_regular_file: we only need to know if we can read
225 // the file or not.
226 llvm::sys::fs::is_regular_file(Twine(ConfigFile), IsFile);
227 if (!IsFile)
228 continue;
229
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()
234 << "\n";
235 continue;
236 }
237
238 // Skip empty files, e.g. files opened for writing via shell output
239 // redirection.
240 if ((*Text)->getBuffer().empty())
241 continue;
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";
248 continue;
249 }
250
251 return DefaultOptionsProvider::getOptions(Directory)
252 .mergeWith(*ParsedOptions)
253 .mergeWith(OverrideOptions);
254 }
255 return llvm::None;
256 }
257
258 /// \brief Parses -line-filter option and stores it to the \c Options.
259 std::error_code parseLineFilter(StringRef LineFilter,
260 clang::tidy::ClangTidyGlobalOptions &Options) {
261 llvm::yaml::Input Input(LineFilter);
262 Input >> Options.LineFilter;
263 return Input.error();
264 }
265
266 llvm::ErrorOr<ClangTidyOptions> parseConfiguration(StringRef Config) {
267 llvm::yaml::Input Input(Config);
268 ClangTidyOptions Options;
269 Input >> Options;
270 if (Input.error())
271 return Input.error();
272 return Options;
273 }
274
275 std::string configurationAsText(const ClangTidyOptions &Options) {
276 std::string Text;
277 llvm::raw_string_ostream Stream(Text);
278 llvm::yaml::Output Output(Stream);
279 // We use the same mapping method for input and output, so we need a non-const
280 // reference here.
281 ClangTidyOptions NonConstValue = Options;
282 Output << NonConstValue;
283 return Stream.str();
284 }
285
286 } // namespace tidy
287 } // namespace clang
clang::tidy::ClangTidyOptions::Checks
llvm::Optional< std::string > Checks
Checks filter.
Definition: ClangTidyOptions.h:63
clang::tidy::ClangTidyOptions::ExtraArgs
llvm::Optional< ArgList > ExtraArgs
Add extra compilation arguments to the end of the list.
Definition: ClangTidyOptions.h:90
clang::tidy::ClangTidyOptions::User
llvm::Optional< std::string > User
Specifies the name or e-mail of the user running clang-tidy.
Definition: ClangTidyOptions.h:79
File
HeaderHandle File
Definition: PreprocessorTracker.cpp:526
clang::tidy::ClangTidyOptions::HeaderFilterRegex
llvm::Optional< std::string > HeaderFilterRegex
Output warnings from headers matching this filter.
Definition: ClangTidyOptions.h:67
llvm::yaml::MappingTraits< FileFilter >::mapping
static void mapping(IO &IO, FileFilter &File)
Definition: ClangTidyOptions.cpp:48
clang::tidy::ClangTidyOptions
Contains options for clang-tidy.
Definition: ClangTidyOptions.h:49
clang::tidy::ClangTidyGlobalOptions
Global options.
Definition: ClangTidyOptions.h:41
clang::tidy::parseLineFilter
std::error_code parseLineFilter(StringRef LineFilter, clang::tidy::ClangTidyGlobalOptions &Options)
Parses -line-filter option and stores it to the Options.
Definition: ClangTidyOptions.cpp:259
Path
std::vector< HeaderHandle > Path
Definition: PreprocessorTracker.cpp:538
clang::tidy::parseConfiguration
llvm::ErrorOr< ClangTidyOptions > parseConfiguration(StringRef Config)
Definition: ClangTidyOptions.cpp:266
llvm::yaml::MappingTraits< FileFilter >::validate
static StringRef validate(IO &io, FileFilter &File)
Definition: ClangTidyOptions.cpp:52
llvm::yaml::NOptionMap::NOptionMap
NOptionMap(IO &, const ClangTidyOptions::OptionMap &OptionMap)
Definition: ClangTidyOptions.cpp:72
clang::tidy::ClangTidyOptions::CheckOptions
OptionMap CheckOptions
Key-value mapping used to store check-specific options.
Definition: ClangTidyOptions.h:85
clang::tidy::ClangTidyOptions::SystemHeaders
llvm::Optional< bool > SystemHeaders
Output warnings from system headers matching HeaderFilterRegex.
Definition: ClangTidyOptions.h:70
clang::tidy::FileOptionsProvider::OverrideOptions
ClangTidyOptions OverrideOptions
Definition: ClangTidyOptions.h:206
ClangTidyOptions.h
clang::tidy::FileOptionsProvider::ConfigHandlers
ConfigFileHandlers ConfigHandlers
Definition: ClangTidyOptions.h:207
clang::tidy::ClangTidyOptions::ExtraArgsBefore
llvm::Optional< ArgList > ExtraArgsBefore
Add extra compilation arguments to the start of the list.
Definition: ClangTidyOptions.h:93
LineFilter
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))
Directory
static cl::opt< std::string > Directory(cl::Positional, cl::Required, cl::desc("<Search Root Directory>"))
clang::tidy::configurationAsText
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
Definition: ClangTidyOptions.cpp:275
ClangTidyModuleRegistry.h
llvm::yaml::SequenceTraits< FileFilter::LineRange >::element
static unsigned & element(IO &IO, FileFilter::LineRange &Range, size_t Index)
Definition: ClangTidyOptions.cpp:40
llvm::yaml::NOptionMap
Definition: ClangTidyOptions.cpp:70
llvm::yaml::MappingTraits< ClangTidyOptions >::mapping
static void mapping(IO &IO, ClangTidyOptions &Options)
Definition: ClangTidyOptions.cpp:84
clang::tidy::ClangTidyGlobalOptions::LineFilter
std::vector< FileFilter > LineFilter
Output warnings from certain line ranges of certain files only.
Definition: ClangTidyOptions.h:44
clang::tidy::DefaultOptionsProvider::getOptions
ClangTidyOptions getOptions(llvm::StringRef) override
Returns options applying to a specific translation unit with the specified FileName.
Definition: ClangTidyOptions.h:119
clang::tidy::ClangTidyOptions::mergeWith
ClangTidyOptions mergeWith(const ClangTidyOptions &Other) const
Creates a new ClangTidyOptions instance combined from all fields of this instance overridden by the f...
Definition: ClangTidyOptions.cpp:118
llvm::yaml::MappingTraits< ClangTidyOptions::StringPair >::mapping
static void mapping(IO &IO, ClangTidyOptions::StringPair &KeyValue)
Definition: ClangTidyOptions.cpp:64
clang::tidy::FileOptionsProvider::ConfigFileHandler
std::pair< std::string, std::function< llvm::ErrorOr< ClangTidyOptions > llvm::StringRef)> > ConfigFileHandler
Definition: ClangTidyOptions.h:141
clang::tidy::FileOptionsProvider::ConfigFileHandlers
std::vector< ConfigFileHandler > ConfigFileHandlers
Configuration file handlers listed in the order of priority.
Definition: ClangTidyOptions.h:160
clang::tidy::FileOptionsProvider::TryReadConfigFile
llvm::Optional< ClangTidyOptions > TryReadConfigFile(llvm::StringRef Directory)
Try to read configuration files from Directory using registered ConfigHandlers.
Definition: ClangTidyOptions.cpp:209
clang::tidy::FileFilter
Contains a list of line ranges in a single file.
Definition: ClangTidyOptions.h:28
Config
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))
clang::tidy::ClangTidyOptions::AnalyzeTemporaryDtors
llvm::Optional< bool > AnalyzeTemporaryDtors
Turns on temporary destructor-based analysis.
Definition: ClangTidyOptions.h:73
clang::tidy::FileOptionsProvider::CachedOptions
llvm::StringMap< ClangTidyOptions > CachedOptions
Definition: ClangTidyOptions.h:205
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:35
llvm::yaml::NOptionMap::Options
std::vector< ClangTidyOptions::StringPair > Options
Definition: ClangTidyOptions.cpp:80
llvm::yaml::SequenceTraits< FileFilter::LineRange >::size
static size_t size(IO &IO, FileFilter::LineRange &Range)
Definition: ClangTidyOptions.cpp:37
clang::tidy::FileOptionsProvider::getOptions
ClangTidyOptions getOptions(llvm::StringRef FileName) override
Returns options applying to a specific translation unit with the specified FileName.
Definition: ClangTidyOptions.cpp:169
llvm::yaml::NOptionMap::NOptionMap
NOptionMap(IO &)
Definition: ClangTidyOptions.cpp:71
llvm::yaml::NOptionMap::denormalize
ClangTidyOptions::OptionMap denormalize(IO &)
Definition: ClangTidyOptions.cpp:74
clang::tidy::FileFilter::LineRanges
std::vector< LineRange > LineRanges
A list of line ranges in this file, for which we show warnings.
Definition: ClangTidyOptions.h:36
clang::tidy::ClangTidyOptions::getDefaults
static ClangTidyOptions getDefaults()
These options are used for all settings that haven't been overridden by the OptionsProvider.
Definition: ClangTidyOptions.cpp:103
clang::tidy::FileOptionsProvider::FileOptionsProvider
FileOptionsProvider(const ClangTidyGlobalOptions &GlobalOptions, const ClangTidyOptions &DefaultOptions, const ClangTidyOptions &OverrideOptions)
Initializes the FileOptionsProvider instance.
Definition: ClangTidyOptions.cpp:146
clang::tidy::FileFilter::Name
std::string Name
File name.
Definition: ClangTidyOptions.h:30
clang::tidy::DefaultOptionsProvider
Implementation of the ClangTidyOptionsProvider interface, which returns the same options for all file...
Definition: ClangTidyOptions.h:111
Result
const NamedDecl * Result
Definition: USRFinder.cpp:121