27#include "clang-include-cleaner/Record.h"
32#include "clang/AST/ASTContext.h"
33#include "clang/AST/Decl.h"
34#include "clang/AST/DeclGroup.h"
35#include "clang/AST/ExternalASTSource.h"
36#include "clang/ASTMatchers/ASTMatchFinder.h"
37#include "clang/Basic/Diagnostic.h"
38#include "clang/Basic/DiagnosticIDs.h"
39#include "clang/Basic/DiagnosticSema.h"
40#include "clang/Basic/FileEntry.h"
41#include "clang/Basic/LLVM.h"
42#include "clang/Basic/LangOptions.h"
43#include "clang/Basic/SourceLocation.h"
44#include "clang/Basic/SourceManager.h"
45#include "clang/Basic/TokenKinds.h"
46#include "clang/Frontend/CompilerInstance.h"
47#include "clang/Frontend/CompilerInvocation.h"
48#include "clang/Frontend/FrontendActions.h"
49#include "clang/Frontend/FrontendOptions.h"
50#include "clang/Frontend/PrecompiledPreamble.h"
51#include "clang/Lex/Lexer.h"
52#include "clang/Lex/PPCallbacks.h"
53#include "clang/Lex/Preprocessor.h"
54#include "clang/Sema/HeuristicResolver.h"
55#include "clang/Serialization/ASTWriter.h"
56#include "clang/Tooling/CompilationDatabase.h"
57#include "clang/Tooling/Core/Diagnostic.h"
58#include "clang/Tooling/Syntax/Tokens.h"
59#include "llvm/ADT/ArrayRef.h"
60#include "llvm/ADT/DenseMap.h"
61#include "llvm/ADT/DenseSet.h"
62#include "llvm/ADT/STLExtras.h"
63#include "llvm/ADT/STLFunctionalExtras.h"
64#include "llvm/ADT/SmallVector.h"
65#include "llvm/ADT/StringRef.h"
66#include "llvm/Support/Error.h"
67#include "llvm/Support/MemoryBuffer.h"
81#define CLANG_TIDY_DISABLE_STATIC_ANALYZER_CHECKS
89template <
class T> std::size_t getUsedBytes(
const std::vector<T> &Vec) {
90 return Vec.capacity() *
sizeof(
T);
93class DeclTrackingASTConsumer :
public ASTConsumer {
95 DeclTrackingASTConsumer(std::vector<Decl *> &TopLevelDecls)
96 : TopLevelDecls(TopLevelDecls) {}
98 bool HandleTopLevelDecl(DeclGroupRef DG)
override {
100 auto &SM =
D->getASTContext().getSourceManager();
103 if (
const NamedDecl *ND = dyn_cast<NamedDecl>(D))
108 if (isa<ObjCMethodDecl>(D))
111 TopLevelDecls.push_back(D);
117 std::vector<Decl *> &TopLevelDecls;
120class ClangdFrontendAction :
public SyntaxOnlyAction {
122 std::vector<Decl *> takeTopLevelDecls() {
return std::move(TopLevelDecls); }
125 std::unique_ptr<ASTConsumer>
126 CreateASTConsumer(CompilerInstance &CI, llvm::StringRef InFile)
override {
127 return std::make_unique<DeclTrackingASTConsumer>( TopLevelDecls);
131 std::vector<Decl *> TopLevelDecls;
140class ReplayPreamble :
private PPCallbacks {
145 static void attach(std::vector<Inclusion> Includes,
146 const MainFileMacros Macros, CompilerInstance &Clang,
147 const PreambleBounds &PB) {
148 auto &PP = Clang.getPreprocessor();
149 auto *ExistingCallbacks = PP.getPPCallbacks();
151 if (!ExistingCallbacks)
153 PP.addPPCallbacks(std::unique_ptr<PPCallbacks>(
new ReplayPreamble(
154 std::move(Includes), std::move(Macros), ExistingCallbacks,
155 Clang.getSourceManager(), PP, Clang.getLangOpts(), PB)));
158 assert(PP.getPPCallbacks() != ExistingCallbacks &&
159 "Expected chaining implementation");
163 ReplayPreamble(std::vector<Inclusion> Includes, MainFileMacros Macros,
164 PPCallbacks *Delegate,
const SourceManager &SM,
165 Preprocessor &PP,
const LangOptions &LangOpts,
166 const PreambleBounds &PB)
167 : Includes(std::move(Includes)), Macros(std::move(Macros)),
168 Delegate(Delegate), SM(SM), PP(PP) {
171 MainFileTokens = syntax::tokenize(
172 syntax::FileRange(SM.getMainFileID(), 0, PB.Size), SM, LangOpts);
190 void FileChanged(SourceLocation Loc, FileChangeReason Reason,
191 SrcMgr::CharacteristicKind Kind, FileID PrevFID)
override {
193 if (Reason == FileChangeReason::ExitFile &&
194 SM.getBufferOrFake(PrevFID).getBufferIdentifier() ==
"<built-in>")
201 for (
const auto &[SID, Refs] : Macros.MacroRefs) {
202 for (
const auto &Ref : Refs) {
203 if (!Ref.IsDefinition)
205 auto Loc = SM.getComposedLoc(SM.getMainFileID(), Ref.StartOffset);
207 if (Lexer::getRawToken(Loc, Tok, SM, PP.getLangOpts(),
false))
209 if (
auto *II = PP.getIdentifierInfo(Tok.getRawIdentifier())) {
210 Tok.setIdentifierInfo(II);
211 Tok.setKind(tok::identifier);
212 if (
auto *
MD = PP.getLocalMacroDirective(II))
213 Delegate->MacroDefined(Tok,
MD);
217 for (
const auto &Inc : Includes) {
218 OptionalFileEntryRef
File;
219 if (Inc.Resolved !=
"")
220 File = expectedToOptional(SM.getFileManager().getFileRef(Inc.Resolved));
223 auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
224 auto HashTok = llvm::partition_point(MainFileTokens,
225 [&HashLoc](
const syntax::Token &T) {
226 return T.location() < HashLoc;
228 assert(HashTok != MainFileTokens.end() && HashTok->kind() == tok::hash);
230 auto IncludeTok = std::next(HashTok);
231 assert(IncludeTok != MainFileTokens.end());
233 auto FileTok = std::next(IncludeTok);
234 assert(FileTok != MainFileTokens.end());
238 Token SynthesizedIncludeTok;
239 SynthesizedIncludeTok.startToken();
240 SynthesizedIncludeTok.setLocation(IncludeTok->location());
241 SynthesizedIncludeTok.setLength(IncludeTok->length());
242 SynthesizedIncludeTok.setKind(tok::raw_identifier);
243 SynthesizedIncludeTok.setRawIdentifierData(IncludeTok->text(SM).data());
244 PP.LookUpIdentifierInfo(SynthesizedIncludeTok);
247 Token SynthesizedFilenameTok;
248 SynthesizedFilenameTok.startToken();
249 SynthesizedFilenameTok.setLocation(FileTok->location());
254 SynthesizedFilenameTok.setLength(Inc.Written.length());
255 SynthesizedFilenameTok.setKind(tok::header_name);
256 SynthesizedFilenameTok.setLiteralData(Inc.Written.data());
258 llvm::StringRef WrittenFilename =
259 llvm::StringRef(Inc.Written).drop_front().drop_back();
260 Delegate->InclusionDirective(
261 HashTok->location(), SynthesizedIncludeTok, WrittenFilename,
262 Inc.Written.front() ==
'<',
263 syntax::FileRange(SM, SynthesizedFilenameTok.getLocation(),
264 SynthesizedFilenameTok.getEndLoc())
266 File,
"SearchPath",
"RelPath",
267 nullptr,
false, Inc.FileKind);
269 Delegate->FileSkipped(*
File, SynthesizedFilenameTok, Inc.FileKind);
273 const std::vector<Inclusion> Includes;
274 const MainFileMacros Macros;
275 PPCallbacks *Delegate;
276 const SourceManager &SM;
278 std::vector<syntax::Token> MainFileTokens;
289class TidyDiagnosticGroups {
292 bool Default =
false;
295 llvm::DenseSet<unsigned> Exceptions;
298 TidyDiagnosticGroups(llvm::StringRef
Checks) {
299 constexpr llvm::StringLiteral CDPrefix =
"clang-diagnostic-";
301 llvm::StringRef Check;
304 Check = Check.trim();
309 bool Enable = !Check.consume_front(
"-");
310 bool Glob = Check.consume_back(
"*");
314 if (CDPrefix.starts_with(Check)) {
322 if (Default == Enable)
325 if (!Check.consume_front(CDPrefix))
328 if (
auto Group = DiagnosticIDs::getGroupForWarningOption(Check))
329 Exceptions.insert(
static_cast<unsigned>(*Group));
333 bool operator()(diag::Group GroupID)
const {
334 return Exceptions.contains(
static_cast<unsigned>(GroupID)) ? !Default
344void applyWarningOptions(llvm::ArrayRef<std::string> ExtraArgs,
345 llvm::function_ref<
bool(diag::Group)> EnabledGroups,
346 DiagnosticsEngine &Diags) {
347 for (llvm::StringRef Group : ExtraArgs) {
350 llvm::SmallVector<diag::kind> Members;
351 if (!Group.consume_front(
"-W") || Group.empty())
353 bool Enable = !Group.consume_front(
"no-");
354 if (Diags.getDiagnosticIDs()->getDiagnosticsInGroup(
355 diag::Flavor::WarningOrError, Group, Members))
361 bool NeedsWerrorExclusion =
false;
362 for (diag::kind ID : Members) {
364 if (Diags.getDiagnosticLevel(ID, SourceLocation()) <
365 DiagnosticsEngine::Warning) {
366 auto Group = Diags.getDiagnosticIDs()->getGroupForDiag(ID);
367 if (!Group || !EnabledGroups(*Group))
369 Diags.setSeverity(ID, diag::Severity::Warning, SourceLocation());
370 if (Diags.getWarningsAsErrors())
371 NeedsWerrorExclusion =
true;
374 Diags.setSeverity(ID, diag::Severity::Ignored, SourceLocation());
377 if (NeedsWerrorExclusion) {
381 Diags.setDiagnosticGroupWarningAsError(Group,
false);
386std::vector<Diag> getIncludeCleanerDiags(
ParsedAST &
AST, llvm::StringRef Code,
389 if (Cfg.Diagnostics.SuppressAll)
391 bool SuppressMissing =
392 Cfg.Diagnostics.Suppress.contains(
"missing-includes") ||
394 bool SuppressUnused =
395 Cfg.Diagnostics.Suppress.contains(
"unused-includes") ||
397 if (SuppressMissing && SuppressUnused)
400 AST, Cfg.Diagnostics.Includes.AnalyzeAngledIncludes);
402 Findings.MissingIncludes.clear();
404 Findings.UnusedIncludes.clear();
406 AST, Code, Findings, TFS, Cfg.Diagnostics.Includes.IgnoreHeader,
407 Cfg.Style.AngledHeaders, Cfg.Style.QuotedHeaders);
410tidy::ClangTidyCheckFactories
411filterFastTidyChecks(
const tidy::ClangTidyCheckFactories &
All,
416 tidy::ClangTidyCheckFactories Fast;
417 for (
const auto &Factory :
All) {
419 Fast.registerCheckFactory(Factory.first(), Factory.second);
426std::optional<ParsedAST>
428 std::unique_ptr<clang::CompilerInvocation> CI,
429 llvm::ArrayRef<Diag> CompilerInvocationDiags,
430 std::shared_ptr<const PreambleData> Preamble) {
436 if (Preamble && Preamble->StatCache)
437 VFS = Preamble->StatCache->getConsumingFS(std::move(VFS));
441 if (CI->getFrontendOpts().Inputs.size() > 0) {
442 auto Lang = CI->getFrontendOpts().Inputs[0].getKind().getLanguage();
443 if (Lang == Language::Asm || Lang == Language::LLVM_IR) {
444 elog(
"Clangd does not support assembly or IR source files");
451 CI->getFrontendOpts().DisableFree =
false;
452 const PrecompiledPreamble *PreamblePCH =
453 Preamble ? &Preamble->Preamble :
nullptr;
457 CI->getLangOpts().DelayedTemplateParsing =
false;
459 std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
462 if (
auto Listener = M.astListeners())
463 ASTListeners.emplace_back(std::move(Listener));
469 for (
const auto &L : ASTListeners)
470 L->sawDiagnostic(D,
Diag);
475 if (Preamble && Preamble->RequiredModules)
476 Preamble->RequiredModules->adjustHeaderSearchOptions(
477 CI->getHeaderSearchOpts());
479 std::optional<PreamblePatch> Patch;
490 llvm::MemoryBuffer::getMemBufferCopy(Inputs.
Contents, Filename), VFS,
496 std::vector<Diag> Diags(ASTDiags.
take());
497 elog(
"Failed to prepare a compiler instance: {0}",
506 dlog(
"ClangTidy configuration for file {0}: {1}", Filename,
527 auto &Diags = Clang->getDiagnostics();
528 TidyDiagnosticGroups TidyGroups(ClangTidyOpts.
Checks ? *ClangTidyOpts.
Checks
529 : llvm::StringRef());
531 applyWarningOptions(*ClangTidyOpts.
ExtraArgsBefore, TidyGroups, Diags);
533 applyWarningOptions(*ClangTidyOpts.
ExtraArgs, TidyGroups, Diags);
536 auto Action = std::make_unique<ClangdFrontendAction>();
537 const FrontendInputFile &MainInput = Clang->getFrontendOpts().Inputs[0];
538 if (!Action->BeginSourceFile(*Clang, MainInput)) {
539 elog(
"BeginSourceFile() failed when building AST for {0}",
540 MainInput.getFile());
548 if (Preamble && Preamble->MainIsIncludeGuarded) {
549 const SourceManager &SM = Clang->getSourceManager();
550 OptionalFileEntryRef MainFE = SM.getFileEntryRefForID(SM.getMainFileID());
551 Clang->getPreprocessor().getHeaderSearchInfo().MarkFileIncludeOnce(*MainFE);
560 std::vector<std::unique_ptr<tidy::ClangTidyCheck>> CTChecks;
561 ast_matchers::MatchFinder CTFinder;
562 std::optional<tidy::ClangTidyContext> CTContext;
564 auto BuildDir = VFS->getCurrentWorkingDirectory();
565 std::optional<IncludeFixer> FixIncludes;
566 llvm::DenseMap<diag::kind, DiagnosticsEngine::Level> OverriddenSeverity;
571 static const auto *AllCTFactories = [] {
573 for (
const auto &E : tidy::ClangTidyModuleRegistry::entries())
574 E.instantiate()->addCheckFactories(*CTFactories);
579 CTContext.emplace(std::make_unique<tidy::DefaultOptionsProvider>(
582 CTContext->setDiagnosticsEngine(
nullptr, &Clang->getDiagnostics());
583 CTContext->setASTContext(&Clang->getASTContext());
584 CTContext->setCurrentFile(Filename);
585 CTContext->setSelfContainedDiags(
true);
587 Preprocessor *PP = &Clang->getPreprocessor();
588 for (
const auto &Check : CTChecks) {
589 Check->registerPPCallbacks(Clang->getSourceManager(), PP, PP);
590 Check->registerMatchers(&CTFinder);
598 for (
auto ID : {diag::ext_implicit_function_decl_c99,
599 diag::ext_implicit_lib_function_decl,
600 diag::ext_implicit_lib_function_decl_c99,
601 diag::warn_implicit_function_decl}) {
602 OverriddenSeverity.try_emplace(
603 ID, Clang->getDiagnostics().getDiagnosticLevel(ID, SourceLocation()));
604 Clang->getDiagnostics().setSeverity(ID, diag::Severity::Error,
609 const clang::Diagnostic &
Info) {
610 auto It = OverriddenSeverity.find(
Info.getID());
611 if (It != OverriddenSeverity.end())
612 DiagLevel = It->second;
614 if (!CTChecks.empty()) {
615 std::string CheckName = CTContext->getCheckName(
Info.getID());
616 bool IsClangTidyDiag = !CheckName.empty();
617 if (IsClangTidyDiag) {
619 return DiagnosticsEngine::Ignored;
626 bool IsInsideMainFile =
627 Info.hasSourceManager() &&
630 if (IsInsideMainFile && CTContext->shouldSuppressDiagnostic(
631 DiagLevel,
Info, TidySuppressedErrors,
636 return DiagnosticsEngine::Ignored;
638 if (!CTContext->getOptions().SystemHeaders.value_or(
false) &&
639 Info.hasSourceManager() &&
640 Info.getSourceManager().isInSystemMacro(
Info.getLocation()))
641 return DiagnosticsEngine::Ignored;
644 if (DiagLevel == DiagnosticsEngine::Warning &&
645 CTContext->treatAsError(CheckName)) {
646 return DiagnosticsEngine::Error;
655 if (Inputs.
Index && !BuildDir.getError()) {
658 auto Inserter = std::make_shared<IncludeInserter>(
659 Filename, Inputs.
Contents, Style, BuildDir.get(),
660 &Clang->getPreprocessor().getHeaderSearchInfo(),
662 ArrayRef<Inclusion> MainFileIncludes;
664 MainFileIncludes = Preamble->Includes.MainFileIncludes;
665 for (
const auto &Inc : Preamble->Includes.MainFileIncludes)
666 Inserter->addExisting(Inc);
673 MainFileIncludes, {})
675 FixIncludes.emplace(Filename, Inserter, *Inputs.
Index,
677 ASTDiags.
contributeFixes([&FixIncludes](DiagnosticsEngine::Level DiagLevl,
678 const clang::Diagnostic &
Info) {
679 return FixIncludes->fix(DiagLevl,
Info);
681 Clang->setExternalSemaSource(FixIncludes->unresolvedNameRecorder());
686 include_cleaner::PragmaIncludes PI;
689 Includes = Preamble->Includes;
690 Includes.MainFileIncludes = Patch->preambleIncludes();
692 ReplayPreamble::attach(Patch->preambleIncludes(), Patch->mainFileMacros(),
693 *Clang, Patch->modifiedBounds());
694 PI = *Preamble->Pragmas;
706 std::vector<PragmaMark> Marks;
708 Macros = Patch->mainFileMacros();
709 Marks = Patch->marks();
711 auto &PP = Clang->getPreprocessor();
712 auto MacroCollector = std::make_unique<CollectMainFileMacros>(PP, Macros);
713 auto *MacroCollectorPtr = MacroCollector.get();
714 PP.addPPCallbacks(std::move(MacroCollector));
723 syntax::TokenCollector CollectTokens(PP);
728 for (
const auto &L : ASTListeners)
729 L->beforeExecute(*Clang);
731 if (llvm::Error Err = Action->Execute())
732 log(
"Execute() failed when building AST for {0}: {1}", MainInput.getFile(),
737 MacroCollectorPtr->doneParse();
742 syntax::TokenBuffer Tokens = std::move(CollectTokens).consume();
744 Tokens.indexExpandedTokens();
745 std::vector<Decl *> ParsedDecls = Action->takeTopLevelDecls();
747 Clang->getASTContext().setTraversalScope(ParsedDecls);
748 if (!CTChecks.empty()) {
752 CTFinder.matchAST(Clang->getASTContext());
765 std::vector<Diag> Diags = CompilerInvocationDiags;
770 llvm::append_range(Diags, Patch->patchedDiags());
773 std::vector<Diag> D = ASTDiags.
take(&*CTContext);
774 Diags.insert(Diags.end(), D.begin(), D.end());
777 std::move(Clang), std::move(Action), std::move(Tokens),
778 std::move(Macros), std::move(Marks), std::move(ParsedDecls),
779 std::move(Diags), std::move(Includes), std::move(PI));
780 llvm::move(getIncludeCleanerDiags(Result, Inputs.
Contents, *Inputs.
TFS),
781 std::back_inserter(Result.Diags));
782 return std::move(Result);
793 auto PP = Clang->getPreprocessorPtr();
794 Clang->setPreprocessor(
nullptr);
795 Action->EndSourceFile();
803 return Clang->getASTContext();
811 return Clang->getPreprocessorPtr();
815 return Clang->getPreprocessor();
819 return LocalTopLevelDecls;
823 return LocalTopLevelDecls;
834 clangd::getUsedBytes(LocalTopLevelDecls) + clangd::getUsedBytes(Diags);
840 Total +=
AST.getASTAllocatedMemory();
841 Total +=
AST.getSideTableAllocatedMemory();
842 Total +=
AST.Idents.getAllocator().getTotalMemory();
843 Total +=
AST.Selectors.getTotalMemory();
845 Total +=
AST.getSourceManager().getContentCacheSize();
846 Total +=
AST.getSourceManager().getDataStructureSizes();
847 Total +=
AST.getSourceManager().getMemoryBufferSizes().malloc_bytes;
849 if (ExternalASTSource *Ext =
AST.getExternalSource())
850 Total += Ext->getMemoryBufferSizes().malloc_bytes;
853 Total += PP.getTotalMemory();
854 if (PreprocessingRecord *PRec = PP.getPreprocessingRecord())
855 Total += PRec->getTotalMemory();
856 Total += PP.getHeaderSearchInfo().getTotalMemory();
866 std::shared_ptr<const PreambleData>
Preamble,
867 std::unique_ptr<CompilerInstance> Clang,
868 std::unique_ptr<FrontendAction> Action,
870 std::vector<PragmaMark> Marks,
871 std::vector<Decl *> LocalTopLevelDecls,
873 include_cleaner::PragmaIncludes PI)
875 Clang(std::
move(Clang)), Action(std::
move(Action)),
876 Tokens(std::
move(Tokens)), Macros(std::
move(Macros)),
877 Marks(std::
move(Marks)), Diags(std::
move(Diags)),
878 LocalTopLevelDecls(std::
move(LocalTopLevelDecls)),
879 Includes(std::
move(Includes)), PI(std::
move(PI)),
880 Resolver(std::make_unique<HeuristicResolver>(getASTContext())) {
882 assert(this->Action);
892 return llvm::StringRef(Preamble->Version);
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))
Include Cleaner is clangd functionality for providing diagnostics for misuse of transitive headers an...
static GeneratorRegistry::Add< MDGenerator > MD(MDGenerator::Format, "Generator for MD output.")
#define SPAN_ATTACH(S, Name, Expr)
Attach a key-value pair to a Span event.
void collect(const CompilerInstance &CI)
Stores and provides access to parsed AST.
std::size_t getUsedBytes() const
Returns the estimated size of the AST and the accessory structures, in bytes.
std::optional< llvm::StringRef > preambleVersion() const
Returns the version of the ParseInputs used to build Preamble part of this AST.
const include_cleaner::PragmaIncludes & getPragmaIncludes() const
Returns the PramaIncludes for preamble + main file includes.
const std::vector< PragmaMark > & getMarks() const
Gets all pragma marks in the main file.
ASTContext & getASTContext()
Note that the returned ast will not contain decls from the preamble that were not deserialized during...
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.
llvm::ArrayRef< Diag > getDiagnostics() const
std::shared_ptr< Preprocessor > getPreprocessorPtr()
Preprocessor & getPreprocessor()
ArrayRef< Decl * > getLocalTopLevelDecls()
This function returns top-level decls present in the main file of the AST.
ParsedAST & operator=(ParsedAST &&Other)
const IncludeStructure & getIncludeStructure() const
ParsedAST(ParsedAST &&Other)
const MainFileMacros & getMacros() const
Gets all macro references (definition, expansions) present in the main file, including those in the p...
static PreamblePatch createFullPatch(llvm::StringRef FileName, const ParseInputs &Modified, const PreambleData &Baseline)
Builds a patch that contains new PP directives introduced to the preamble section of Modified compare...
StoreDiags collects the diagnostics that can later be reported by clangd.
void contributeFixes(DiagFixer Fixer)
If set, possibly adds fixes for diagnostics using Fixer.
void setLevelAdjuster(LevelAdjuster Adjuster)
If set, this allows the client of this class to adjust the level of diagnostics, such as promoting wa...
std::vector< Diag > take(const clang::tidy::ClangTidyContext *Tidy=nullptr)
void setDiagCallback(DiagCallback CB)
Invokes a callback every time a diagnostics is completely formed.
void EndSourceFile() override
Wrapper for vfs::FileSystem for use in multithreaded programs like clangd.
llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > view(std::nullopt_t CWD) const
Obtain a vfs::FileSystem with an arbitrary initial working directory.
Records an event whose duration is the lifetime of the Span object.
A collection of ClangTidyCheckFactory instances.
std::vector< std::unique_ptr< ClangTidyCheck > > createChecksForLanguage(ClangTidyContext *Context) const
Create instances of checks that are enabled for the current Language.
FIXME: Skip testing on windows temporarily due to the different escaping code mode.
@ Info
An information message.
bool isInsideMainFile(SourceLocation Loc, const SourceManager &SM)
Returns true iff Loc is inside the main file.
static const char * toString(OffsetEncoding OE)
std::unique_ptr< PPCallbacks > collectPragmaMarksCallback(const SourceManager &SM, std::vector< PragmaMark > &Out)
Collect all pragma marks from the main file.
std::optional< bool > isFastTidyCheck(llvm::StringRef Check)
Returns if Check is known-fast, known-slow, or its speed is unknown.
Symbol::IncludeDirective preferredIncludeDirective(llvm::StringRef FileName, const LangOptions &LangOpts, ArrayRef< Inclusion > MainFileIncludes, ArrayRef< const Decl * > TopLevelDecls)
Infer the include directive to use for the given FileName.
std::unique_ptr< CompilerInstance > prepareCompilerInstance(std::unique_ptr< clang::CompilerInvocation > CI, const PrecompiledPreamble *Preamble, std::unique_ptr< llvm::MemoryBuffer > Buffer, llvm::IntrusiveRefCntPtr< llvm::vfs::FileSystem > VFS, DiagnosticConsumer &DiagsClient)
void log(const char *Fmt, Ts &&... Vals)
IncludeCleanerFindings computeIncludeCleanerFindings(ParsedAST &AST, bool AnalyzeAngledIncludes)
llvm::StringRef PathRef
A typedef to represent a ref to file path.
tidy::ClangTidyOptions getTidyOptionsForFile(TidyProviderRef Provider, llvm::StringRef Filename)
bool isImplicitTemplateInstantiation(const NamedDecl *D)
Indicates if D is a template instantiation implicitly generated by the compiler, e....
std::vector< Diag > issueIncludeCleanerDiagnostics(ParsedAST &AST, llvm::StringRef Code, const IncludeCleanerFindings &Findings, const ThreadsafeFS &TFS, HeaderFilter IgnoreHeaders, HeaderFilter AngledHeaders, HeaderFilter QuotedHeaders)
void elog(const char *Fmt, Ts &&... Vals)
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.
std::string configurationAsText(const ClangTidyOptions &Options)
Serializes configuration to a YAML-encoded string.
===– Representation.cpp - ClangDoc Representation --------—*- C++ -*-===//
Settings that express user/project preferences and control clangd behavior.
struct clang::clangd::Config::@314053012031341203055315320366267371313202370174 Style
Style of the codebase.
FastCheckPolicy FastCheckFilter
static const Config & current()
Returns the Config of the current Context, or an empty configuration.
struct clang::clangd::Config::@343034053122374337352226322054223376344037116252 Diagnostics
Controls warnings and errors when parsing code.
struct clang::clangd::Config::@343034053122374337352226322054223376344037116252::@107156241027253143221327255130274177352007274355 ClangTidy
Configures what clang-tidy checks to run and options to use with them.
std::vector< std::function< bool(llvm::StringRef)> > QuotedHeaders
std::vector< std::function< bool(llvm::StringRef)> > AngledHeaders
Contains basic information about a diagnostic.
A top-level diagnostic that may have Notes and Fixes.
@ Include
#include "header.h"
Contains options for clang-tidy.
std::optional< std::string > Checks
Checks filter.
std::optional< ArgList > ExtraArgsBefore
Add extra compilation arguments to the start of the list.
std::optional< ArgList > ExtraArgs
Add extra compilation arguments to the end of the list.