clang-tools 24.0.0git
Check.cpp
Go to the documentation of this file.
1//===--- Check.cpp - clangd self-diagnostics ------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8//
9// Many basic problems can occur processing a file in clangd, e.g.:
10// - system includes are not found
11// - crash when indexing its AST
12// clangd --check provides a simplified, isolated way to reproduce these,
13// with no editor, LSP, threads, background indexing etc to contend with.
14//
15// One important use case is gathering information for bug reports.
16// Another is reproducing crashes, and checking which setting prevent them.
17//
18// It simulates opening a file (determining compile command, parsing, indexing)
19// and then running features at many locations.
20//
21// Currently it adds some basic logging of progress and results.
22// We should consider extending it to also recognize common symptoms and
23// recommend solutions (e.g. standard library installation issues).
24//
25//===----------------------------------------------------------------------===//
26
27#include "../clang-tidy/ClangTidyModule.h"
28#include "../clang-tidy/ClangTidyOptions.h"
29#include "../clang-tidy/GlobList.h"
31#include "ClangdLSPServer.h"
32#include "ClangdServer.h"
33#include "CodeComplete.h"
34#include "CompileCommands.h"
35#include "Compiler.h"
36#include "Config.h"
37#include "ConfigFragment.h"
38#include "ConfigProvider.h"
39#include "Diagnostics.h"
40#include "Feature.h"
42#include "Hover.h"
43#include "InlayHints.h"
44#include "ParsedAST.h"
45#include "Preamble.h"
46#include "Protocol.h"
47#include "Selection.h"
49#include "SourceCode.h"
50#include "TidyProvider.h"
51#include "XRefs.h"
52#include "clang-include-cleaner/Record.h"
53#include "index/FileIndex.h"
54#include "refactor/Tweak.h"
55#include "support/Context.h"
56#include "support/Logger.h"
58#include "support/Trace.h"
59#include "clang/AST/ASTContext.h"
60#include "clang/Basic/Diagnostic.h"
61#include "clang/Basic/LLVM.h"
62#include "clang/Format/Format.h"
63#include "clang/Frontend/CompilerInvocation.h"
64#include "clang/Tooling/CompilationDatabase.h"
65#include "llvm/ADT/ArrayRef.h"
66#include "llvm/ADT/STLExtras.h"
67#include "llvm/ADT/ScopeExit.h"
68#include "llvm/ADT/SmallString.h"
69#include "llvm/Support/Chrono.h"
70#include "llvm/Support/CommandLine.h"
71#include "llvm/Support/Path.h"
72#include "llvm/Support/Process.h"
73#include <array>
74#include <chrono>
75#include <cstdint>
76#include <limits>
77#include <memory>
78#include <optional>
79#include <utility>
80#include <vector>
81
82namespace clang {
83namespace clangd {
84namespace {
85
86// These will never be shown in --help, ClangdMain doesn't list the category.
87llvm::cl::opt<std::string> CheckTidyTime{
88 "check-tidy-time",
89 llvm::cl::desc("Print the overhead of checks matching this glob"),
90 llvm::cl::init("")};
91llvm::cl::opt<std::string> CheckFileLines{
92 "check-lines",
93 llvm::cl::desc(
94 "Limits the range of tokens in -check file on which "
95 "various features are tested. Example --check-lines=3-7 restricts "
96 "testing to lines 3 to 7 (inclusive) or --check-lines=5 to restrict "
97 "to one line. Default is testing entire file."),
98 llvm::cl::init("")};
99llvm::cl::opt<bool> CheckLocations{
100 "check-locations",
101 llvm::cl::desc(
102 "Runs certain features (e.g. hover) at each point in the file. "
103 "Somewhat slow."),
104 llvm::cl::init(true)};
105llvm::cl::opt<bool> CheckCompletion{
106 "check-completion",
107 llvm::cl::desc("Run code-completion at each point (slow)"),
108 llvm::cl::init(false)};
109llvm::cl::opt<bool> CheckWarnings{
110 "check-warnings",
111 llvm::cl::desc("Print warnings as well as errors"),
112 llvm::cl::init(false)};
113
114// Print the diagnostics meeting severity threshold, and return count of errors.
115unsigned showErrors(llvm::ArrayRef<Diag> Diags) {
116 unsigned ErrCount = 0;
117 for (const auto &D : Diags) {
118 if (D.Severity >= DiagnosticsEngine::Error || CheckWarnings)
119 elog("[{0}] Line {1}: {2}", D.Name, D.Range.start.line + 1, D.Message);
120 if (D.Severity >= DiagnosticsEngine::Error)
121 ++ErrCount;
122 }
123 return ErrCount;
124}
125
126std::vector<std::string> listTidyChecks(llvm::StringRef Glob) {
127 tidy::GlobList G(Glob);
128 tidy::ClangTidyCheckFactories CTFactories;
129 for (const auto &E : tidy::ClangTidyModuleRegistry::entries())
130 E.instantiate()->addCheckFactories(CTFactories);
131 std::vector<std::string> Result;
132 for (const auto &E : CTFactories)
133 if (G.contains(E.getKey()))
134 Result.push_back(E.getKey().str());
135 llvm::sort(Result);
136 return Result;
137}
138
139// This class is just a linear pipeline whose functions get called in sequence.
140// Each exercises part of clangd's logic on our test file and logs results.
141// Later steps depend on state built in earlier ones (such as the AST).
142// Many steps can fatally fail (return false), then subsequent ones cannot run.
143// Nonfatal failures are logged and tracked in ErrCount.
144class Checker {
145 // from constructor
146 std::string File;
147 const ClangdLSPServer::Options &Opts;
148 // from buildCommand
149 tooling::CompileCommand Cmd;
150 std::unique_ptr<GlobalCompilationDatabase> BaseCDB;
151 std::unique_ptr<GlobalCompilationDatabase> CDB;
152 // from buildInvocation
153 ParseInputs Inputs;
154 std::unique_ptr<CompilerInvocation> Invocation;
155 format::FormatStyle Style;
156 std::optional<ModulesBuilder> ModulesManager;
157 // from buildAST
158 std::shared_ptr<const PreambleData> Preamble;
159 std::optional<ParsedAST> AST;
160 FileIndex Index;
161
162public:
163 // Number of non-fatal errors seen.
164 unsigned ErrCount = 0;
165
166 Checker(llvm::StringRef File, const ClangdLSPServer::Options &Opts)
167 : File(File), Opts(Opts), Index(/*SupportContainedRefs=*/true) {}
168
169 // Read compilation database and choose a compile command for the file.
170 bool buildCommand(const ThreadsafeFS &TFS) {
171 log("Loading compilation database...");
172 DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
173 if (Opts.StrongWorkspaceMode)
174 CDBOpts.applyFallbackWorkingDirectory(Opts.WorkspaceRoot);
175 CDBOpts.CompileCommandsDir =
177 BaseCDB =
178 std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
179 auto Mangler = CommandMangler::detect();
180 Mangler.SystemIncludeExtractor =
181 getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs));
182 if (Opts.ResourceDir)
183 Mangler.ResourceDir = *Opts.ResourceDir;
184
185 CDB = std::make_unique<OverlayCDB>(
186 BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler),
187 CDBOpts.FallbackWorkingDirectory);
188
189 if (auto TrueCmd = CDB->getCompileCommand(File)) {
190 Cmd = std::move(*TrueCmd);
191 log("Compile command {0} is: [{1}] {2}",
192 Cmd.Heuristic.empty() ? "from CDB" : Cmd.Heuristic, Cmd.Directory,
193 printArgv(Cmd.CommandLine));
194 } else {
195 Cmd = CDB->getFallbackCommand(File);
196 log("Generic fallback command is: [{0}] {1}", Cmd.Directory,
197 printArgv(Cmd.CommandLine));
198 }
199
200 return true;
201 }
202
203 // Prepare inputs and build CompilerInvocation (parsed compile command).
204 bool buildInvocation(const ThreadsafeFS &TFS,
205 std::optional<std::string> Contents) {
206 StoreDiags CaptureInvocationDiags;
207 std::vector<std::string> CC1Args;
208 Inputs.CompileCommand = Cmd;
209 Inputs.TFS = &TFS;
210 Inputs.FeatureModules = Opts.FeatureModules;
211 Inputs.Opts.PreambleParseForwardingFunctions =
212 Opts.PreambleParseForwardingFunctions;
213 if (Contents) {
214 Inputs.Contents = *Contents;
215 log("Imaginary source file contents:\n{0}", Inputs.Contents);
216 } else {
217 if (auto Contents = TFS.view(std::nullopt)->getBufferForFile(File)) {
218 Inputs.Contents = Contents->get()->getBuffer().str();
219 } else {
220 elog("Couldn't read {0}: {1}", File, Contents.getError().message());
221 return false;
222 }
223 }
224 if (Opts.EnableExperimentalModulesSupport) {
225 if (!ModulesManager)
226 ModulesManager.emplace(*CDB);
227 Inputs.ModulesManager = &*ModulesManager;
228 }
229 log("Parsing command...");
230 Invocation =
231 buildCompilerInvocation(Inputs, CaptureInvocationDiags, &CC1Args);
232 auto InvocationDiags = CaptureInvocationDiags.take();
233 ErrCount += showErrors(InvocationDiags);
234 log("internal (cc1) args are: {0}", printArgv(CC1Args));
235 if (!Invocation) {
236 elog("Failed to parse command line");
237 return false;
238 }
239
240 // FIXME: Check that resource-dir/built-in-headers exist?
241
242 Style = getFormatStyleForFile(File, Inputs.Contents, TFS, false);
243
244 return true;
245 }
246
247 // Build preamble and AST, and index them.
248 bool buildAST() {
249 log("Building preamble...");
250 Preamble = buildPreamble(
251 File, *Invocation, Inputs, /*StoreInMemory=*/true,
252 [&](CapturedASTCtx Ctx,
253 std::shared_ptr<const include_cleaner::PragmaIncludes> PI) {
254 if (!Opts.BuildDynamicSymbolIndex)
255 return;
256 log("Indexing headers...");
257 Index.updatePreamble(File, /*Version=*/"null", Ctx.getASTContext(),
258 Ctx.getPreprocessor(), *PI);
259 });
260 if (!Preamble) {
261 elog("Failed to build preamble");
262 return false;
263 }
264 ErrCount += showErrors(Preamble->Diags);
265
266 log("Building AST...");
267 AST = ParsedAST::build(File, Inputs, std::move(Invocation),
268 /*InvocationDiags=*/std::vector<Diag>{}, Preamble);
269 if (!AST) {
270 elog("Failed to build AST");
271 return false;
272 }
273 ErrCount +=
274 showErrors(AST->getDiagnostics().drop_front(Preamble->Diags.size()));
275
276 if (Opts.BuildDynamicSymbolIndex) {
277 log("Indexing AST...");
278 Index.updateMain(File, *AST);
279 }
280
281 if (!CheckTidyTime.empty()) {
282 if (!CLANGD_TIDY_CHECKS) {
283 elog("-{0} requires -DCLANGD_TIDY_CHECKS!", CheckTidyTime.ArgStr);
284 return false;
285 }
286 #ifndef NDEBUG
287 elog("Timing clang-tidy checks in asserts-mode is not representative!");
288 #endif
289 if (!checkTidyTimes())
290 return false;
291 }
292
293 return true;
294 }
295
296 // For each check foo, we want to build with checks=-* and checks=-*,foo.
297 // (We do a full build rather than just AST matchers to meausre PPCallbacks).
298 //
299 // However, performance has both random noise and systematic changes, such as
300 // step-function slowdowns due to CPU scaling.
301 // We take the median of 5 measurements, and after every check discard the
302 // measurement if the baseline changed by >3%.
303 bool checkTidyTimes() {
304 // Keep all other modules active while varying only tidy's configuration.
305 auto *TidyModule =
306 Inputs.FeatureModules
307 ? Inputs.FeatureModules->get<ClangTidyFeatureModule>()
308 : nullptr;
309 if (!TidyModule) {
310 elog("Cannot time clang-tidy checks without a clang-tidy feature module");
311 return false;
312 }
313 double Stability = 0.03;
314 log("Timing AST build with individual clang-tidy checks (target accuracy "
315 "{0:P0})",
316 Stability);
317
318 using Duration = std::chrono::nanoseconds;
319 // Measure time elapsed by a block of code. Currently: user CPU time.
320 auto Time = [&](auto &&Run) -> Duration {
321 llvm::sys::TimePoint<> Elapsed;
322 std::chrono::nanoseconds UserBegin, UserEnd, System;
323 llvm::sys::Process::GetTimeUsage(Elapsed, UserBegin, System);
324 Run();
325 llvm::sys::Process::GetTimeUsage(Elapsed, UserEnd, System);
326 return UserEnd - UserBegin;
327 };
328 auto Change = [&](Duration Exp, Duration Base) -> double {
329 return (double)(Exp.count() - Base.count()) / Base.count();
330 };
331 // Build ParsedAST with a fixed check glob, and return the time taken.
332 auto Build = [&](llvm::StringRef Checks) -> Duration {
333 TidyProvider CTProvider = [&](tidy::ClangTidyOptions &Opts,
334 llvm::StringRef) {
335 Opts.Checks = Checks.str();
336 };
337 auto Provider =
338 std::make_shared<const TidyProvider>(std::move(CTProvider));
339 TidyModule->swapProvider(Provider);
340 // Provider now holds the original configuration; restore it on exit.
341 llvm::scope_exit RestoreProvider(
342 [&] { TidyModule->swapProvider(Provider); });
343 // Sigh, can't reuse the CompilerInvocation.
344 IgnoringDiagConsumer IgnoreDiags;
345 auto Invocation = buildCompilerInvocation(Inputs, IgnoreDiags);
346 Duration Val = Time([&] {
347 ParsedAST::build(File, Inputs, std::move(Invocation), {}, Preamble);
348 });
349 vlog(" Measured {0} ==> {1}", Checks, Val);
350 return Val;
351 };
352 // Measure several times, return the median.
353 auto MedianTime = [&](llvm::StringRef Checks) -> Duration {
354 std::array<Duration, 5> Measurements;
355 for (auto &M : Measurements)
356 M = Build(Checks);
357 llvm::sort(Measurements);
358 return Measurements[Measurements.size() / 2];
359 };
360 Duration Baseline = MedianTime("-*");
361 log(" Baseline = {0}", Baseline);
362 // Attempt to time a check, may update Baseline if it is unstable.
363 auto Measure = [&](llvm::StringRef Check) -> double {
364 for (;;) {
365 Duration Median = MedianTime(("-*," + Check).str());
366 Duration NewBase = MedianTime("-*");
367
368 // Value only usable if baseline is fairly consistent before/after.
369 double DeltaFraction = Change(NewBase, Baseline);
370 Baseline = NewBase;
371 vlog(" Baseline = {0}", Baseline);
372 if (DeltaFraction < -Stability || DeltaFraction > Stability) {
373 elog(" Speed unstable, discarding measurement.");
374 continue;
375 }
376 return Change(Median, Baseline);
377 }
378 };
379
380 for (const auto& Check : listTidyChecks(CheckTidyTime)) {
381 // vlog the check name in case we crash!
382 vlog(" Timing {0}", Check);
383 double Fraction = Measure(Check);
384 log(" {0} = {1:P0}", Check, Fraction);
385 }
386 log("Finished individual clang-tidy checks");
387 return true;
388 }
389
390 // Build Inlay Hints for the entire AST or the specified range
391 void buildInlayHints(std::optional<Range> LineRange) {
392 log("Building inlay hints");
393 auto Hints = inlayHints(*AST, LineRange);
394
395 for (const auto &Hint : Hints) {
396 vlog(" {0} {1} [{2}]", Hint.kind, Hint.position, [&] {
397 return llvm::join(llvm::map_range(Hint.label,
398 [&](auto &L) {
399 return llvm::formatv("{{{0}}", L);
400 }),
401 ", ");
402 }());
403 }
404 }
405
406 void buildSemanticHighlighting(std::optional<Range> LineRange) {
407 log("Building semantic highlighting");
408 auto Highlights =
409 getSemanticHighlightings(*AST, /*IncludeInactiveRegionTokens=*/true);
410 for (const auto HL : Highlights)
411 if (!LineRange || LineRange->contains(HL.R))
412 vlog(" {0} {1} {2}", HL.R, HL.Kind, HL.Modifiers);
413 }
414
415 // Run AST-based features at each token in the file.
416 void testLocationFeatures(std::optional<Range> LineRange) {
417 trace::Span Trace("testLocationFeatures");
418 log("Testing features at each token (may be slow in large files)");
419 auto &SM = AST->getSourceManager();
420 auto SpelledTokens = AST->getTokens().spelledTokens(SM.getMainFileID());
421
422 CodeCompleteOptions CCOpts = Opts.CodeComplete;
423 CCOpts.Index = &Index;
424
425 for (const auto &Tok : SpelledTokens) {
426 unsigned Start = AST->getSourceManager().getFileOffset(Tok.location());
427 unsigned End = Start + Tok.length();
428 Position Pos = offsetToPosition(Inputs.Contents, Start);
429
430 if (LineRange && !LineRange->contains(Pos))
431 continue;
432
433 trace::Span Trace("Token");
434 SPAN_ATTACH(Trace, "pos", Pos);
435 SPAN_ATTACH(Trace, "text", Tok.text(AST->getSourceManager()));
436
437 // FIXME: dumping the tokens may leak sensitive code into bug reports.
438 // Add an option to turn this off, once we decide how options work.
439 vlog(" {0} {1}", Pos, Tok.text(AST->getSourceManager()));
440 auto Tree = SelectionTree::createRight(AST->getASTContext(),
441 AST->getTokens(), Start, End);
442 Tweak::Selection Selection(&Index, *AST, Start, End, std::move(Tree),
443 nullptr);
444 // FS is only populated when applying a tweak, not during prepare as
445 // prepare should not do any I/O to be fast.
446 auto Tweaks =
447 prepareTweaks(Selection, Opts.TweakFilter, Opts.FeatureModules);
448 Selection.FS =
449 &AST->getSourceManager().getFileManager().getVirtualFileSystem();
450 for (const auto &T : Tweaks) {
451 auto Result = T->apply(Selection);
452 if (!Result) {
453 elog(" tweak: {0} ==> FAIL: {1}", T->id(), Result.takeError());
454 ++ErrCount;
455 } else {
456 vlog(" tweak: {0}", T->id());
457 }
458 }
459 unsigned Definitions = locateSymbolAt(*AST, Pos, &Index).size();
460 vlog(" definition: {0}", Definitions);
461
462 auto Hover = getHover(*AST, Pos, Style, &Index);
463 vlog(" hover: {0}", Hover.has_value());
464
465 unsigned DocHighlights = findDocumentHighlights(*AST, Pos).size();
466 vlog(" documentHighlight: {0}", DocHighlights);
467
468 if (CheckCompletion) {
469 Position EndPos = offsetToPosition(Inputs.Contents, End);
470 auto CC = codeComplete(File, EndPos, Preamble.get(), Inputs, CCOpts);
471 vlog(" code completion: {0}",
472 CC.Completions.empty() ? "<empty>" : CC.Completions[0].Name);
473 }
474 }
475 }
476};
477
478} // namespace
479
480bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
482 std::optional<Range> LineRange;
483 if (!CheckFileLines.empty()) {
484 uint32_t Begin = 0, End = std::numeric_limits<uint32_t>::max();
485 StringRef RangeStr(CheckFileLines);
486 bool ParseError = RangeStr.consumeInteger(0, Begin);
487 if (RangeStr.empty()) {
488 End = Begin;
489 } else {
490 ParseError |= !RangeStr.consume_front("-");
491 ParseError |= RangeStr.consumeInteger(0, End);
492 }
493 if (ParseError || !RangeStr.empty() || Begin <= 0 || End < Begin) {
494 elog("Invalid --check-lines specified. Use Begin-End format, e.g. 3-17");
495 return false;
496 }
497 LineRange = Range{Position{static_cast<int>(Begin - 1), 0},
498 Position{static_cast<int>(End), 0}};
499 }
500
501 llvm::SmallString<0> FakeFile;
502 std::optional<std::string> Contents;
503 if (File.empty()) {
504 llvm::sys::path::system_temp_directory(false, FakeFile);
505 llvm::sys::path::append(FakeFile, "test.cc");
506 File = FakeFile;
507 Contents = R"cpp(
508 #include <stddef.h>
509 #include <string>
510
511 size_t N = 50;
512 auto xxx = std::string(N, 'x');
513 )cpp";
514 }
515 log("Testing on source file {0}", File);
516
517 class OverrideConfigProvider : public config::Provider {
518 std::vector<config::CompiledFragment>
519 getFragments(const config::Params &,
520 config::DiagnosticCallback Diag) const override {
522 // If we're timing clang-tidy checks, implicitly disabling the slow ones
523 // is counterproductive!
524 if (CheckTidyTime.getNumOccurrences())
525 F.Diagnostics.ClangTidy.FastCheckFilter.emplace("None");
526 return {std::move(F).compile(Diag)};
527 }
528 };
529 std::vector<std::unique_ptr<config::Provider>> ConfigProviders;
530 ConfigProviders.push_back(std::move(Opts.ConfigProvider));
531 ConfigProviders.push_back(std::make_unique<OverrideConfigProvider>());
532 auto ConfigProvider = config::Provider::combine(std::move(ConfigProviders));
533
535 ConfigProvider.get(), nullptr);
536 WithContext Ctx(ContextProvider(
537 FakeFile.empty()
538 ? File
539 : /*Don't turn on local configs for an arbitrary temp path.*/ ""));
540 Checker C(File, Opts);
541 if (!C.buildCommand(TFS) || !C.buildInvocation(TFS, Contents) ||
542 !C.buildAST())
543 return false;
544 C.buildInlayHints(LineRange);
545 C.buildSemanticHighlighting(LineRange);
546 if (CheckLocations)
547 C.testLocationFeatures(LineRange);
548
549 log("All checks completed, {0} errors", C.ErrCount);
550 return C.ErrCount == 0;
551}
552
553} // namespace clangd
554} // namespace clang
static cl::opt< std::string > Checks("checks", desc(R"( Comma-separated list of globs with optional '-' prefix. Globs are processed in order of appearance in the list. Globs without '-' prefix add checks with matching names to the set, globs with the '-' prefix remove checks with matching names from the set of enabled checks. This option's value is appended to the value of the 'Checks' option in .clang-tidy file, if any. )"), cl::init(""), cl::cat(ClangTidyCategory))
void elog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:61
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
Definition Trace.h:164
static std::function< Context(PathRef)> createConfiguredContextProvider(const config::Provider *Provider, ClangdServer::Callbacks *)
Creates a context provider that loads and installs config.
static std::optional< ParsedAST > build(llvm::StringRef Filename, const ParseInputs &Inputs, std::unique_ptr< clang::CompilerInvocation > CI, llvm::ArrayRef< Diag > CompilerInvocationDiags, std::shared_ptr< const PreambleData > Preamble)
Attempts to run Clang and store the parsed AST.
static SelectionTree createRight(ASTContext &AST, const syntax::TokenBuffer &Tokens, unsigned Begin, unsigned End)
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
WithContext replaces Context::current() with a provided scope.
Definition Context.h:185
A source of configuration fragments.
static std::unique_ptr< Provider > combine(std::vector< std::unique_ptr< Provider > >)
A provider that includes fragments from all the supplied providers.
Records an event whose duration is the lifetime of the Span object.
Definition Trace.h:143
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.
Definition AST.cpp:44
llvm::unique_function< void(tidy::ClangTidyOptions &, llvm::StringRef) const > TidyProvider
A factory to modify a tidy::ClangTidyOptions.
std::vector< HighlightingToken > getSemanticHighlightings(ParsedAST &AST, bool IncludeInactiveRegionTokens)
bool check(llvm::StringRef File, const ThreadsafeFS &TFS, ClangdLSPServer::Options &&Opts)
Definition Check.cpp:480
SystemIncludeExtractorFn getSystemIncludeExtractor(llvm::ArrayRef< std::string > QueryDriverGlobs)
Position offsetToPosition(llvm::StringRef Code, size_t Offset)
Turn an offset in Code into a [line, column] pair.
std::vector< DocumentHighlight > findDocumentHighlights(ParsedAST &AST, Position Pos)
Returns highlights for all usages of a symbol at Pos.
Definition XRefs.cpp:1511
std::unique_ptr< CompilerInvocation > buildCompilerInvocation(const ParseInputs &Inputs, clang::DiagnosticConsumer &D, std::vector< std::string > *CC1Args)
Builds compiler invocation that could be used to build AST or preamble.
Definition Compiler.cpp:96
void vlog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:72
std::optional< HoverInfo > getHover(ParsedAST &AST, Position Pos, const format::FormatStyle &Style, const SymbolIndex *Index)
Get the hover information when hovering at Pos.
Definition Hover.cpp:1313
std::vector< LocatedSymbol > locateSymbolAt(ParsedAST &AST, Position Pos, const SymbolIndex *Index)
Get definition of symbol at a specified Pos.
Definition XRefs.cpp:873
std::shared_ptr< const PreambleData > buildPreamble(PathRef FileName, CompilerInvocation CI, const ParseInputs &Inputs, bool StoreInMemory, PreambleParsedCallback PreambleCallback, PreambleBuildStats *Stats)
Build a preamble for the new inputs unless an old one can be reused.
Definition Preamble.cpp:578
void log(const char *Fmt, Ts &&... Vals)
Definition Logger.h:67
std::string printArgv(llvm::ArrayRef< llvm::StringRef > Args)
std::vector< std::unique_ptr< Tweak > > prepareTweaks(const Tweak::Selection &S, llvm::function_ref< bool(const Tweak &)> Filter, const FeatureModuleSet *Modules)
Calls prepare() on all tweaks that satisfy the filter, returning those that can run on the selection.
Definition Tweak.cpp:72
CodeCompleteResult codeComplete(PathRef FileName, Position Pos, const PreambleData *Preamble, const ParseInputs &ParseInput, CodeCompleteOptions Opts, SpeculativeFuzzyFind *SpecFuzzyFind)
Gets code completions at a specified Pos in FileName.
void elog(const char *Fmt, Ts &&... Vals)
Definition Logger.h:61
std::vector< InlayHint > inlayHints(ParsedAST &AST, std::optional< Range > RestrictRange, InlayHintOptions HintOptions)
Compute and return inlay hints for a file.
format::FormatStyle getFormatStyleForFile(llvm::StringRef File, llvm::StringRef Content, const ThreadsafeFS &TFS, bool FormatFile)
Choose the clang-format style we should apply to a certain file.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
static CommandMangler detect()
std::optional< std::string > FixedCDBPath
Definition Config.h:60
struct clang::clangd::Config::@347104204155140144054042115114221214347344026246 CompileFlags
Controls how the compile command for the current file is determined.
static const Config & current()
Returns the Config of the current Context, or an empty configuration.
Definition Config.cpp:17
CDBSearchSpec CDBSearch
Where to search for compilation databases for this file's flags.
Definition Config.h:70
A top-level diagnostic that may have Notes and Fixes.
Definition Diagnostics.h:95
Input to prepare and apply tweaks.
Definition Tweak.h:49
std::optional< Located< std::string > > FastCheckFilter
Whether to run checks that may slow down clangd.
A chunk of configuration obtained from a config file, LSP, or elsewhere.
Describes the context used to evaluate configuration fragments.