| //===-- CanonicalIncludes.h - remap #include header -------------*- C++ -*-===// |
| // |
| // The LLVM Compiler Infrastructure |
| // |
| // This file is distributed under the University of Illinois Open Source |
| // License. See LICENSE.TXT for details. |
| // |
| //===----------------------------------------------------------------------===// |
| // |
| // At indexing time, we decide which file to #included for a symbol. |
| // Usually this is the file with the canonical decl, but there are exceptions: |
| // - private headers may have pragmas pointing to the matching public header. |
| // (These are "IWYU" pragmas, named after the include-what-you-use tool). |
| // - the standard library is implemented in many files, without any pragmas. |
| // We have a lookup table for common standard library implementations. |
| // libstdc++ puts char_traits in bits/char_traits.h, but we #include <string>. |
| // |
| //===---------------------------------------------------------------------===// |
| |
| #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H |
| #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H |
| |
| #include "clang/Lex/Preprocessor.h" |
| #include "llvm/ADT/StringMap.h" |
| #include "llvm/Support/Regex.h" |
| #include <mutex> |
| #include <string> |
| #include <vector> |
| |
| namespace clang { |
| namespace clangd { |
| |
| /// Maps a definition location onto an #include file, based on a set of filename |
| /// rules. |
| /// Only const methods (i.e. mapHeader) in this class are thread safe. |
| class CanonicalIncludes { |
| public: |
| CanonicalIncludes() = default; |
| |
| /// Adds a string-to-string mapping from \p Path to \p CanonicalPath. |
| void addMapping(llvm::StringRef Path, llvm::StringRef CanonicalPath); |
| |
| /// Maps all files matching \p RE to \p CanonicalPath |
| void addRegexMapping(llvm::StringRef RE, llvm::StringRef CanonicalPath); |
| |
| /// Sets the canonical include for any symbol with \p QualifiedName. |
| /// Symbol mappings take precedence over header mappings. |
| void addSymbolMapping(llvm::StringRef QualifiedName, |
| llvm::StringRef CanonicalPath); |
| |
| /// Returns the canonical include for symbol with \p QualifiedName. |
| /// \p Headers is the include stack: Headers.front() is the file declaring the |
| /// symbol, and Headers.back() is the main file. |
| llvm::StringRef mapHeader(llvm::ArrayRef<std::string> Headers, |
| llvm::StringRef QualifiedName) const; |
| |
| private: |
| // A map from header patterns to header names. This needs to be mutable so |
| // that we can match again a Regex in a const function member. |
| // FIXME(ioeric): All the regexes we have so far are suffix matches. The |
| // performance could be improved by allowing only suffix matches instead of |
| // arbitrary regexes. |
| mutable std::vector<std::pair<llvm::Regex, std::string>> |
| RegexHeaderMappingTable; |
| // A map from fully qualified symbol names to header names. |
| llvm::StringMap<std::string> SymbolMapping; |
| // Guards Regex matching as it's not thread-safe. |
| mutable std::mutex RegexMutex; |
| }; |
| |
| /// Returns a CommentHandler that parses pragma comment on include files to |
| /// determine when we should include a different header from the header that |
| /// directly defines a symbol. Mappinps are registered with \p Includes. |
| /// |
| /// Currently it only supports IWYU private pragma: |
| /// https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-private |
| std::unique_ptr<CommentHandler> |
| collectIWYUHeaderMaps(CanonicalIncludes *Includes); |
| |
| /// Adds mapping for system headers and some special symbols (e.g. STL symbols |
| /// in <iosfwd> need to be mapped individually). Approximately, the following |
| /// system headers are handled: |
| /// - C++ standard library e.g. bits/basic_string.h$ -> <string> |
| /// - Posix library e.g. bits/pthreadtypes.h$ -> <pthread.h> |
| /// - Compiler extensions, e.g. include/avx512bwintrin.h$ -> <immintrin.h> |
| /// The mapping is hardcoded and hand-maintained, so it might not cover all |
| /// headers. |
| void addSystemHeadersMapping(CanonicalIncludes *Includes); |
| |
| } // namespace clangd |
| } // namespace clang |
| |
| #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_HEADERMAPCOLLECTOR_H |