//===-- IncludeFixer.h - Include inserter -----------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #ifndef LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H #define LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H #include "IncludeFixerContext.h" #include "SymbolIndexManager.h" #include "clang/Format/Format.h" #include "clang/Sema/ExternalSemaSource.h" #include "clang/Tooling/Core/Replacement.h" #include "clang/Tooling/Tooling.h" #include #include namespace clang { class CompilerInvocation; class DiagnosticConsumer; class FileManager; class PCHContainerOperations; namespace include_fixer { class IncludeFixerActionFactory : public clang::tooling::ToolAction { public: /// \param SymbolIndexMgr A source for matching symbols to header files. /// \param Contexts The contexts for the symbols being queried. /// \param StyleName Fallback style for reformatting. /// \param MinimizeIncludePaths whether inserted include paths are optimized. IncludeFixerActionFactory(SymbolIndexManager &SymbolIndexMgr, std::vector &Contexts, StringRef StyleName, bool MinimizeIncludePaths = true); ~IncludeFixerActionFactory() override; bool runInvocation(clang::CompilerInvocation *Invocation, clang::FileManager *Files, std::shared_ptr PCHContainerOps, clang::DiagnosticConsumer *Diagnostics) override; private: /// The client to use to find cross-references. SymbolIndexManager &SymbolIndexMgr; /// Multiple contexts for files being processed. std::vector &Contexts; /// Whether inserted include paths should be optimized. bool MinimizeIncludePaths; /// The fallback format style for formatting after insertion if no /// clang-format config file was found. std::string FallbackStyle; }; /// Create replacements, which are generated by clang-format, for the /// missing header and mising qualifiers insertions. The function uses the /// first header for insertion. /// /// \param Code The source code. /// \param Context The context which contains all information for creating /// include-fixer replacements. /// \param Style clang-format style being used. /// \param AddQualifiers Whether we should add qualifiers to all instances of /// an unidentified symbol. /// /// \return Formatted replacements for inserting, sorting headers and adding /// qualifiers on success; otherwise, an llvm::Error carrying llvm::StringError /// is returned. llvm::Expected createIncludeFixerReplacements( StringRef Code, const IncludeFixerContext &Context, const format::FormatStyle &Style = format::getLLVMStyle(), bool AddQualifiers = true); /// Handles callbacks from sema, does the include lookup and turns it into an /// IncludeFixerContext. class IncludeFixerSemaSource : public clang::ExternalSemaSource { public: explicit IncludeFixerSemaSource(SymbolIndexManager &SymbolIndexMgr, bool MinimizeIncludePaths, bool GenerateDiagnostics) : SymbolIndexMgr(SymbolIndexMgr), MinimizeIncludePaths(MinimizeIncludePaths), GenerateDiagnostics(GenerateDiagnostics) {} void setCompilerInstance(CompilerInstance *CI) { this->CI = CI; } void setFilePath(StringRef FilePath) { this->FilePath = FilePath; } /// Callback for incomplete types. If we encounter a forward declaration we /// have the fully qualified name ready. Just query that. bool MaybeDiagnoseMissingCompleteType(clang::SourceLocation Loc, clang::QualType T) override; /// Callback for unknown identifiers. Try to piece together as much /// qualification as we can get and do a query. clang::TypoCorrection CorrectTypo(const DeclarationNameInfo &Typo, int LookupKind, Scope *S, CXXScopeSpec *SS, CorrectionCandidateCallback &CCC, DeclContext *MemberContext, bool EnteringContext, const ObjCObjectPointerType *OPT) override; /// Get the minimal include for a given path. std::string minimizeInclude(StringRef Include, const clang::SourceManager &SourceManager, clang::HeaderSearch &HeaderSearch) const; /// Get the include fixer context for the queried symbol. IncludeFixerContext getIncludeFixerContext( const clang::SourceManager &SourceManager, clang::HeaderSearch &HeaderSearch, ArrayRef MatchedSymbols) const; /// Get the global matched symbols. ArrayRef getMatchedSymbols() const { return MatchedSymbols; } private: /// Query the database for a given identifier. std::vector query(StringRef Query, StringRef ScopedQualifiers, tooling::Range Range); CompilerInstance *CI; /// The client to use to find cross-references. SymbolIndexManager &SymbolIndexMgr; /// The information of the symbols being queried. std::vector QuerySymbolInfos; /// All symbol candidates which match QuerySymbol. We only include the first /// discovered identifier to avoid getting caught in results from error /// recovery. std::vector MatchedSymbols; /// The file path to the file being processed. std::string FilePath; /// Whether we should use the smallest possible include path. bool MinimizeIncludePaths = true; /// Whether we should generate diagnostics with fixits for missing symbols. bool GenerateDiagnostics = false; }; } // namespace include_fixer } // namespace clang #endif // LLVM_CLANG_TOOLS_EXTRA_INCLUDE_FIXER_INCLUDEFIXER_H