clang-tools 8.0.0

ClangIncludeFixer.cpp
Go to the documentation of this file.
1 //===-- ClangIncludeFixer.cpp - Standalone include fixer ------------------===//
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 "FuzzySymbolIndex.h"
11 #include "InMemorySymbolIndex.h"
12 #include "IncludeFixer.h"
13 #include "IncludeFixerContext.h"
14 #include "SymbolIndexManager.h"
15 #include "YamlSymbolIndex.h"
16 #include "clang/Format/Format.h"
17 #include "clang/Frontend/TextDiagnosticPrinter.h"
18 #include "clang/Rewrite/Core/Rewriter.h"
19 #include "clang/Tooling/CommonOptionsParser.h"
20 #include "clang/Tooling/Core/Replacement.h"
21 #include "clang/Tooling/Tooling.h"
22 #include "llvm/Support/CommandLine.h"
23 #include "llvm/Support/Path.h"
24 #include "llvm/Support/YAMLTraits.h"
25
26 using namespace clang;
27 using namespace llvm;
28 using clang::include_fixer::IncludeFixerContext;
29
30 LLVM_YAML_IS_DOCUMENT_LIST_VECTOR(IncludeFixerContext)
31 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::HeaderInfo)
32 LLVM_YAML_IS_FLOW_SEQUENCE_VECTOR(IncludeFixerContext::QuerySymbolInfo)
33
34 namespace llvm {
35 namespace yaml {
36
37 template <> struct MappingTraits<tooling::Range> {
38 struct NormalizedRange {
39 NormalizedRange(const IO &) : Offset(0), Length(0) {}
40
41 NormalizedRange(const IO &, const tooling::Range &R)
42 : Offset(R.getOffset()), Length(R.getLength()) {}
43
44 tooling::Range denormalize(const IO &) {
45 return tooling::Range(Offset, Length);
46 }
47
48 unsigned Offset;
49 unsigned Length;
50 };
51 static void mapping(IO &IO, tooling::Range &Info) {
52 MappingNormalization<NormalizedRange, tooling::Range> Keys(IO, Info);
53 IO.mapRequired("Offset", Keys->Offset);
54 IO.mapRequired("Length", Keys->Length);
55 }
56 };
57
58 template <> struct MappingTraits<IncludeFixerContext::HeaderInfo> {
59 static void mapping(IO &io, IncludeFixerContext::HeaderInfo &Info) {
60 io.mapRequired("Header", Info.Header);
61 io.mapRequired("QualifiedName", Info.QualifiedName);
62 }
63 };
64
65 template <> struct MappingTraits<IncludeFixerContext::QuerySymbolInfo> {
66 static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info) {
67 io.mapRequired("RawIdentifier", Info.RawIdentifier);
68 io.mapRequired("Range", Info.Range);
69 }
70 };
71
72 template <> struct MappingTraits<IncludeFixerContext> {
73 static void mapping(IO &IO, IncludeFixerContext &Context) {
74 IO.mapRequired("QuerySymbolInfos", Context.QuerySymbolInfos);
75 IO.mapRequired("HeaderInfos", Context.HeaderInfos);
76 IO.mapRequired("FilePath", Context.FilePath);
77 }
78 };
79 } // namespace yaml
80 } // namespace llvm
81
82 namespace {
83 cl::OptionCategory IncludeFixerCategory("Tool options");
84
85 enum DatabaseFormatTy {
86 fixed, ///< Hard-coded mapping.
87 yaml, ///< Yaml database created by find-all-symbols.
88 fuzzyYaml, ///< Yaml database with fuzzy-matched identifiers.
89 };
90
91 cl::opt<DatabaseFormatTy> DatabaseFormat(
92 "db", cl::desc("Specify input format"),
93 cl::values(clEnumVal(fixed, "Hard-coded mapping"),
94 clEnumVal(yaml, "Yaml database created by find-all-symbols"),
95 clEnumVal(fuzzyYaml, "Yaml database, with fuzzy-matched names")),
96 cl::init(yaml), cl::cat(IncludeFixerCategory));
97
98 cl::opt<std::string> Input("input",
99 cl::desc("String to initialize the database"),
100 cl::cat(IncludeFixerCategory));
101
102 cl::opt<std::string>
103 QuerySymbol("query-symbol",
104 cl::desc("Query a given symbol (e.g. \"a::b::foo\") in\n"
105 "database directly without parsing the file."),
106 cl::cat(IncludeFixerCategory));
107
108 cl::opt<bool>
109 MinimizeIncludePaths("minimize-paths",
110 cl::desc("Whether to minimize added include paths"),
111 cl::init(true), cl::cat(IncludeFixerCategory));
112
113 cl::opt<bool> Quiet("q", cl::desc("Reduce terminal output"), cl::init(false),
114 cl::cat(IncludeFixerCategory));
115
116 cl::opt<bool>
117 STDINMode("stdin",
118 cl::desc("Override source file's content (in the overlaying\n"
119 "virtual file system) with input from <stdin> and run\n"
120 "the tool on the new content with the compilation\n"
121 "options of the source file. This mode is currently\n"
122 "used for editor integration."),
123 cl::init(false), cl::cat(IncludeFixerCategory));
124
125 cl::opt<bool> OutputHeaders(
126 "output-headers",
127 cl::desc("Print the symbol being queried and all its relevant headers in\n"
128 "JSON format to stdout:\n"
129 " {\n"
130 " \"FilePath\": \"/path/to/foo.cc\",\n"
131 " \"QuerySymbolInfos\": [\n"
132 " {\"RawIdentifier\": \"foo\",\n"
133 " \"Range\": {\"Offset\": 0, \"Length\": 3}}\n"
134 " ],\n"
135 " \"HeaderInfos\": [ {\"Header\": \"\\\"foo_a.h\\\"\",\n"
136 " \"QualifiedName\": \"a::foo\"} ]\n"
137 " }"),
138 cl::init(false), cl::cat(IncludeFixerCategory));
139
140 cl::opt<std::string> InsertHeader(
141 "insert-header",
142 cl::desc("Insert a specific header. This should run with STDIN mode.\n"
143 "The result is written to stdout. It is currently used for\n"
144 "editor integration. Support YAML/JSON format:\n"
145 " -insert-header=\"{\n"
146 " FilePath: \"/path/to/foo.cc\",\n"
147 " QuerySymbolInfos: [\n"
148 " {RawIdentifier: foo,\n"
149 " Range: {Offset: 0, Length: 3}}\n"
150 " ],\n"
151 " HeaderInfos: [ {Headers: \"\\\"foo_a.h\\\"\",\n"
152 " QualifiedName: \"a::foo\"} ]}\""),
153 cl::init(""), cl::cat(IncludeFixerCategory));
154
155 cl::opt<std::string>
156 Style("style",
157 cl::desc("Fallback style for reformatting after inserting new\n"
158 "headers if there is no clang-format config file found."),
159 cl::init("llvm"), cl::cat(IncludeFixerCategory));
160
161 std::unique_ptr<include_fixer::SymbolIndexManager>
162 createSymbolIndexManager(StringRef FilePath) {
163 using find_all_symbols::SymbolInfo;
164
165 auto SymbolIndexMgr = llvm::make_unique<include_fixer::SymbolIndexManager>();
166 switch (DatabaseFormat) {
167 case fixed: {
168 // Parse input and fill the database with it.
169 // <symbol>=<header><, header...>
170 // Multiple symbols can be given, separated by semicolons.
171 std::map<std::string, std::vector<std::string>> SymbolsMap;
172 SmallVector<StringRef, 4> SemicolonSplits;
173 StringRef(Input).split(SemicolonSplits, ";");
174 std::vector<find_all_symbols::SymbolAndSignals> Symbols;
175 for (StringRef Pair : SemicolonSplits) {
176 auto Split = Pair.split('=');
177 std::vector<std::string> Headers;
178 SmallVector<StringRef, 4> CommaSplits;
179 Split.second.split(CommaSplits, ",");
180 for (size_t I = 0, E = CommaSplits.size(); I != E; ++I)
181 Symbols.push_back(
182 {SymbolInfo(Split.first.trim(), SymbolInfo::SymbolKind::Unknown,
183 CommaSplits[I].trim(), {}),
184 // Use fake "seen" signal for tests, so first header wins.
185 SymbolInfo::Signals(/*Seen=*/static_cast<unsigned>(E - I),
186 /*Used=*/0)});
187 }
188 SymbolIndexMgr->addSymbolIndex([=]() {
189 return llvm::make_unique<include_fixer::InMemorySymbolIndex>(Symbols);
190 });
191 break;
192 }
193 case yaml: {
194 auto CreateYamlIdx = [=]() -> std::unique_ptr<include_fixer::SymbolIndex> {
195 llvm::ErrorOr<std::unique_ptr<include_fixer::YamlSymbolIndex>> DB(
196 nullptr);
197 if (!Input.empty()) {
198 DB = include_fixer::YamlSymbolIndex::createFromFile(Input);
199 } else {
200 // If we don't have any input file, look in the directory of the
201 // first
202 // file and its parents.
203 SmallString<128> AbsolutePath(tooling::getAbsolutePath(FilePath));
204 StringRef Directory = llvm::sys::path::parent_path(AbsolutePath);
205 DB = include_fixer::YamlSymbolIndex::createFromDirectory(
206 Directory, "find_all_symbols_db.yaml");
207 }
208
209 if (!DB) {
210 llvm::errs() << "Couldn't find YAML db: " << DB.getError().message()
211 << '\n';
212 return nullptr;
213 }
214 return std::move(*DB);
215 };
216
217 SymbolIndexMgr->addSymbolIndex(std::move(CreateYamlIdx));
218 break;
219 }
220 case fuzzyYaml: {
221 // This mode is not very useful, because we don't correct the identifier.
222 // It's main purpose is to expose FuzzySymbolIndex to tests.
223 SymbolIndexMgr->addSymbolIndex(
224 []() -> std::unique_ptr<include_fixer::SymbolIndex> {
225 auto DB = include_fixer::FuzzySymbolIndex::createFromYAML(Input);
226 if (!DB) {
227 llvm::errs() << "Couldn't load fuzzy YAML db: "
228 << llvm::toString(DB.takeError()) << '\n';
229 return nullptr;
230 }
231 return std::move(*DB);
232 });
233 break;
234 }
235 }
236 return SymbolIndexMgr;
237 }
238
239 void writeToJson(llvm::raw_ostream &OS, const IncludeFixerContext& Context) {
240 OS << "{\n"
241 << " \"FilePath\": \""
242 << llvm::yaml::escape(Context.getFilePath()) << "\",\n"
243 << " \"QuerySymbolInfos\": [\n";
244 for (const auto &Info : Context.getQuerySymbolInfos()) {
245 OS << " {\"RawIdentifier\": \"" << Info.RawIdentifier << "\",\n";
246 OS << " \"Range\":{";
247 OS << "\"Offset\":" << Info.Range.getOffset() << ",";
248 OS << "\"Length\":" << Info.Range.getLength() << "}}";
249 if (&Info != &Context.getQuerySymbolInfos().back())
250 OS << ",\n";
251 }
252 OS << "\n ],\n";
253 OS << " \"HeaderInfos\": [\n";
254 const auto &HeaderInfos = Context.getHeaderInfos();
255 for (const auto &Info : HeaderInfos) {
256 OS << " {\"Header\": \"" << llvm::yaml::escape(Info.Header) << "\",\n"
257 << " \"QualifiedName\": \"" << Info.QualifiedName << "\"}";
258 if (&Info != &HeaderInfos.back())
259 OS << ",\n";
260 }
261 OS << "\n";
262 OS << " ]\n";
263 OS << "}\n";
264 }
265
266 int includeFixerMain(int argc, const char **argv) {
267 tooling::CommonOptionsParser options(argc, argv, IncludeFixerCategory);
268 tooling::ClangTool tool(options.getCompilations(),
269 options.getSourcePathList());
270
271 llvm::StringRef SourceFilePath = options.getSourcePathList().front();
272 // In STDINMode, we override the file content with the <stdin> input.
273 // Since `tool.mapVirtualFile` takes `StringRef`, we define `Code` outside of
274 // the if-block so that `Code` is not released after the if-block.
275 std::unique_ptr<llvm::MemoryBuffer> Code;
276 if (STDINMode) {
277 assert(options.getSourcePathList().size() == 1 &&
278 "Expect exactly one file path in STDINMode.");
279 llvm::ErrorOr<std::unique_ptr<llvm::MemoryBuffer>> CodeOrErr =
280 MemoryBuffer::getSTDIN();
281 if (std::error_code EC = CodeOrErr.getError()) {
282 errs() << EC.message() << "\n";
283 return 1;
284 }
285 Code = std::move(CodeOrErr.get());
286 if (Code->getBufferSize() == 0)
287 return 0; // Skip empty files.
288
289 tool.mapVirtualFile(SourceFilePath, Code->getBuffer());
290 }
291
292 if (!InsertHeader.empty()) {
293 if (!STDINMode) {
294 errs() << "Should be running in STDIN mode\n";
295 return 1;
296 }
297
298 llvm::yaml::Input yin(InsertHeader);
299 IncludeFixerContext Context;
300 yin >> Context;
301
302 const auto &HeaderInfos = Context.getHeaderInfos();
303 assert(!HeaderInfos.empty());
304 // We only accept one unique header.
305 // Check all elements in HeaderInfos have the same header.
306 bool IsUniqueHeader = std::equal(
307 HeaderInfos.begin()+1, HeaderInfos.end(), HeaderInfos.begin(),
308 [](const IncludeFixerContext::HeaderInfo &LHS,
309 const IncludeFixerContext::HeaderInfo &RHS) {
310 return LHS.Header == RHS.Header;
311 });
312 if (!IsUniqueHeader) {
313 errs() << "Expect exactly one unique header.\n";
314 return 1;
315 }
316
317 // If a header has multiple symbols, we won't add the missing namespace
318 // qualifiers because we don't know which one is exactly used.
319 //
320 // Check whether all elements in HeaderInfos have the same qualified name.
321 bool IsUniqueQualifiedName = std::equal(
322 HeaderInfos.begin() + 1, HeaderInfos.end(), HeaderInfos.begin(),
323 [](const IncludeFixerContext::HeaderInfo &LHS,
324 const IncludeFixerContext::HeaderInfo &RHS) {
325 return LHS.QualifiedName == RHS.QualifiedName;
326 });
327 auto InsertStyle = format::getStyle(format::DefaultFormatStyle,
328 Context.getFilePath(), Style);
329 if (!InsertStyle) {
330 llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
331 return 1;
332 }
333 auto Replacements = clang::include_fixer::createIncludeFixerReplacements(
334 Code->getBuffer(), Context, *InsertStyle,
335 /*AddQualifiers=*/IsUniqueQualifiedName);
336 if (!Replacements) {
337 errs() << "Failed to create replacements: "
338 << llvm::toString(Replacements.takeError()) << "\n";
339 return 1;
340 }
341
342 auto ChangedCode =
343 tooling::applyAllReplacements(Code->getBuffer(), *Replacements);
344 if (!ChangedCode) {
345 llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
346 return 1;
347 }
348 llvm::outs() << *ChangedCode;
349 return 0;
350 }
351
352 // Set up data source.
353 std::unique_ptr<include_fixer::SymbolIndexManager> SymbolIndexMgr =
354 createSymbolIndexManager(SourceFilePath);
355 if (!SymbolIndexMgr)
356 return 1;
357
358 // Query symbol mode.
359 if (!QuerySymbol.empty()) {
360 auto MatchedSymbols = SymbolIndexMgr->search(
361 QuerySymbol, /*IsNestedSearch=*/true, SourceFilePath);
362 for (auto &Symbol : MatchedSymbols) {
363 std::string HeaderPath = Symbol.getFilePath().str();
364 Symbol.SetFilePath(((HeaderPath[0] == '"' || HeaderPath[0] == '<')
365 ? HeaderPath
366 : "\"" + HeaderPath + "\""));
367 }
368
369 // We leave an empty symbol range as we don't know the range of the symbol
370 // being queried in this mode. include-fixer won't add namespace qualifiers
371 // if the symbol range is empty, which also fits this case.
372 IncludeFixerContext::QuerySymbolInfo Symbol;
373 Symbol.RawIdentifier = QuerySymbol;
374 auto Context =
375 IncludeFixerContext(SourceFilePath, {Symbol}, MatchedSymbols);
376 writeToJson(llvm::outs(), Context);
377 return 0;
378 }
379
380 // Now run our tool.
381 std::vector<include_fixer::IncludeFixerContext> Contexts;
382 include_fixer::IncludeFixerActionFactory Factory(*SymbolIndexMgr, Contexts,
383 Style, MinimizeIncludePaths);
384
385 if (tool.run(&Factory) != 0) {
386 // We suppress all Clang diagnostics (because they would be wrong,
387 // include-fixer does custom recovery) but still want to give some feedback
388 // in case there was a compiler error we couldn't recover from. The most
389 // common case for this is a #include in the file that couldn't be found.
390 llvm::errs() << "Fatal compiler error occurred while parsing file!"
391 " (incorrect include paths?)\n";
392 return 1;
393 }
394
395 assert(!Contexts.empty());
396
397 if (OutputHeaders) {
398 // FIXME: Print contexts of all processing files instead of the first one.
399 writeToJson(llvm::outs(), Contexts.front());
400 return 0;
401 }
402
403 std::vector<tooling::Replacements> FixerReplacements;
404 for (const auto &Context : Contexts) {
405 StringRef FilePath = Context.getFilePath();
406 auto InsertStyle =
407 format::getStyle(format::DefaultFormatStyle, FilePath, Style);
408 if (!InsertStyle) {
409 llvm::errs() << llvm::toString(InsertStyle.takeError()) << "\n";
410 return 1;
411 }
412 auto Buffer = llvm::MemoryBuffer::getFile(FilePath);
413 if (!Buffer) {
414 errs() << "Couldn't open file: " + FilePath.str() + ": "
415 << Buffer.getError().message() + "\n";
416 return 1;
417 }
418
419 auto Replacements = clang::include_fixer::createIncludeFixerReplacements(
420 Buffer.get()->getBuffer(), Context, *InsertStyle);
421 if (!Replacements) {
422 errs() << "Failed to create replacement: "
423 << llvm::toString(Replacements.takeError()) << "\n";
424 return 1;
425 }
426 FixerReplacements.push_back(*Replacements);
427 }
428
429 if (!Quiet) {
430 for (const auto &Context : Contexts) {
431 if (!Context.getHeaderInfos().empty()) {
432 llvm::errs() << "Added #include "
433 << Context.getHeaderInfos().front().Header << " for "
434 << Context.getFilePath() << "\n";
435 }
436 }
437 }
438
439 if (STDINMode) {
440 assert(FixerReplacements.size() == 1);
441 auto ChangedCode = tooling::applyAllReplacements(Code->getBuffer(),
442 FixerReplacements.front());
443 if (!ChangedCode) {
444 llvm::errs() << llvm::toString(ChangedCode.takeError()) << "\n";
445 return 1;
446 }
447 llvm::outs() << *ChangedCode;
448 return 0;
449 }
450
451 // Set up a new source manager for applying the resulting replacements.
452 IntrusiveRefCntPtr<DiagnosticOptions> DiagOpts(new DiagnosticOptions);
453 DiagnosticsEngine Diagnostics(new DiagnosticIDs, &*DiagOpts);
454 TextDiagnosticPrinter DiagnosticPrinter(outs(), &*DiagOpts);
455 SourceManager SM(Diagnostics, tool.getFiles());
456 Diagnostics.setClient(&DiagnosticPrinter, false);
457
458 // Write replacements to disk.
459 Rewriter Rewrites(SM, LangOptions());
460 for (const auto &Replacement : FixerReplacements) {
461 if (!tooling::applyAllReplacements(Replacement, Rewrites)) {
462 llvm::errs() << "Failed to apply replacements.\n";
463 return 1;
464 }
465 }
466 return Rewrites.overwriteChangedFiles();
467 }
468
469 } // namespace
470
471 int main(int argc, const char **argv) {
472 return includeFixerMain(argc, argv);
473 }
llvm::yaml::MappingTraits< tooling::Range >::mapping
static void mapping(IO &IO, tooling::Range &Info)
Definition: ClangIncludeFixer.cpp:51
llvm
Some operations such as code completion produce a set of candidates.
Definition: YAMLGenerator.cpp:28
llvm::yaml::MappingTraits< IncludeFixerContext >::mapping
static void mapping(IO &IO, IncludeFixerContext &Context)
Definition: ClangIncludeFixer.cpp:73
YamlSymbolIndex.h
clang::include_fixer::createIncludeFixerReplacements
llvm::Expected< tooling::Replacements > createIncludeFixerReplacements(StringRef Code, const IncludeFixerContext &Context, const clang::format::FormatStyle &Style, bool AddQualifiers)
Definition: IncludeFixer.cpp:403
clang::include_fixer::IncludeFixerContext::getQuerySymbolInfos
const std::vector< QuerySymbolInfo > & getQuerySymbolInfos() const
Get information of symbols being querid.
Definition: IncludeFixerContext.h:71
clang::include_fixer::IncludeFixerContext::getFilePath
StringRef getFilePath() const
Get the file path to the file being processed.
Definition: IncludeFixerContext.h:65
clang::include_fixer::IncludeFixerContext
A context for a file being processed.
Definition: IncludeFixerContext.h:23
FuzzySymbolIndex.h
clang::include_fixer::IncludeFixerContext::getHeaderInfos
const std::vector< HeaderInfo > & getHeaderInfos() const
Get header information.
Definition: IncludeFixerContext.h:68
main
int main(int argc, const char **argv)
Definition: ClangIncludeFixer.cpp:471
clang::tidy::cppcoreguidelines::toString
static llvm::StringRef toString(SpecialMemberFunctionsCheck::SpecialMemberFunctionKind K)
Definition: SpecialMemberFunctionsCheck.cpp:59
clang::include_fixer::FuzzySymbolIndex::createFromYAML
static llvm::Expected< std::unique_ptr< FuzzySymbolIndex > > createFromYAML(llvm::StringRef File)
Definition: FuzzySymbolIndex.cpp:134
DatabaseFormatTy
DatabaseFormatTy
Definition: ClangIncludeFixer.cpp:85
llvm::yaml::MappingTraits< tooling::Range >::NormalizedRange::denormalize
tooling::Range denormalize(const IO &)
Definition: ClangIncludeFixer.cpp:44
clang::find_all_symbols::SymbolInfo::Signals
Definition: SymbolInfo.h:54
Directory
static cl::opt< std::string > Directory(cl::Positional, cl::Required, cl::desc("<Search Root Directory>"))
SymbolInfo
clang::find_all_symbols::SymbolInfo SymbolInfo
Definition: FindAllSymbolsMain.cpp:39
llvm::yaml::MappingTraits< tooling::Range >::NormalizedRange::NormalizedRange
NormalizedRange(const IO &)
Definition: ClangIncludeFixer.cpp:39
SymbolIndexManager.h
clang::include_fixer::YamlSymbolIndex::createFromDirectory
static llvm::ErrorOr< std::unique_ptr< YamlSymbolIndex > > createFromDirectory(llvm::StringRef Directory, llvm::StringRef Name)
Look for a file called Name in Directory and all parent directories.
Definition: YamlSymbolIndex.cpp:36
llvm::yaml::MappingTraits< IncludeFixerContext::QuerySymbolInfo >::mapping
static void mapping(IO &io, IncludeFixerContext::QuerySymbolInfo &Info)
Definition: ClangIncludeFixer.cpp:66
yaml
Definition: ClangDocMain.cpp:68
Info
FunctionInfo Info
Definition: FunctionSizeCheck.cpp:121
IncludeFixerContext.h
clang
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Definition: ChangeNamespace.cpp:18
llvm::yaml::MappingTraits< tooling::Range >::NormalizedRange::Offset
unsigned Offset
Definition: ClangIncludeFixer.cpp:48
Range
CharSourceRange Range
SourceRange for the file name.
Definition: IncludeOrderCheck.cpp:38
InMemorySymbolIndex.h
clang::include_fixer::YamlSymbolIndex::createFromFile
static llvm::ErrorOr< std::unique_ptr< YamlSymbolIndex > > createFromFile(llvm::StringRef FilePath)
Create a new Yaml db from a file.
Definition: YamlSymbolIndex.cpp:26
llvm::yaml::MappingTraits< tooling::Range >::NormalizedRange::Length
unsigned Length
Definition: ClangIncludeFixer.cpp:49
IncludeFixer.h
clang::include_fixer::IncludeFixerActionFactory
Definition: IncludeFixer.h:31
llvm::yaml::MappingTraits< IncludeFixerContext::HeaderInfo >::mapping
static void mapping(IO &io, IncludeFixerContext::HeaderInfo &Info)
Definition: ClangIncludeFixer.cpp:59
llvm::yaml::MappingTraits< tooling::Range >::NormalizedRange::NormalizedRange
NormalizedRange(const IO &, const tooling::Range &R)
Definition: ClangIncludeFixer.cpp:41
Quiet
static cl::opt< bool > Quiet("quiet", cl::desc(R"( Run clang-tidy in quiet mode. This suppresses printing statistics about ignored warnings and warnings treated as errors if the respective options are specified. )"), cl::init(false), cl::cat(ClangTidyCategory))