Line data Source code
1 : //===-- CanonicalIncludes.h - remap #include header -------------*- C++ -*-===//
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 : // At indexing time, we decide which file to #included for a symbol.
11 : // Usually this is the file with the canonical decl, but there are exceptions:
12 : // - private headers may have pragmas pointing to the matching public header.
13 : // (These are "IWYU" pragmas, named after the include-what-you-use tool).
14 : // - the standard library is implemented in many files, without any pragmas.
15 : // We have a lookup table for common standard library implementations.
16 : // libstdc++ puts char_traits in bits/char_traits.h, but we #include <string>.
17 : //
18 : //===----------------------------------------------------------------------===//
19 :
20 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H
21 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_CANONICALINCLUDES_H
22 :
23 : #include "clang/Lex/Preprocessor.h"
24 : #include "llvm/ADT/StringMap.h"
25 : #include "llvm/Support/Regex.h"
26 : #include <mutex>
27 : #include <string>
28 : #include <vector>
29 :
30 : namespace clang {
31 : namespace clangd {
32 :
33 : /// Maps a definition location onto an #include file, based on a set of filename
34 : /// rules.
35 : /// Only const methods (i.e. mapHeader) in this class are thread safe.
36 : class CanonicalIncludes {
37 : public:
38 0 : CanonicalIncludes() = default;
39 :
40 : /// Adds a string-to-string mapping from \p Path to \p CanonicalPath.
41 : void addMapping(llvm::StringRef Path, llvm::StringRef CanonicalPath);
42 :
43 : /// Maps files with last path components matching \p Suffix to \p
44 : /// CanonicalPath.
45 : void addPathSuffixMapping(llvm::StringRef Suffix,
46 : llvm::StringRef CanonicalPath);
47 :
48 : /// Sets the canonical include for any symbol with \p QualifiedName.
49 : /// Symbol mappings take precedence over header mappings.
50 : void addSymbolMapping(llvm::StringRef QualifiedName,
51 : llvm::StringRef CanonicalPath);
52 :
53 : /// Returns the canonical include for symbol with \p QualifiedName.
54 : /// \p Headers is the include stack: Headers.front() is the file declaring the
55 : /// symbol, and Headers.back() is the main file.
56 : llvm::StringRef mapHeader(llvm::ArrayRef<std::string> Headers,
57 : llvm::StringRef QualifiedName) const;
58 :
59 : private:
60 : /// A map from full include path to a canonical path.
61 : llvm::StringMap<std::string> FullPathMapping;
62 : /// A map from a suffix (one or components of a path) to a canonical path.
63 : llvm::StringMap<std::string> SuffixHeaderMapping;
64 : /// Maximum number of path components stored in a key of SuffixHeaderMapping.
65 : /// Used to reduce the number of lookups into SuffixHeaderMapping.
66 : int MaxSuffixComponents = 0;
67 : /// A map from fully qualified symbol names to header names.
68 : llvm::StringMap<std::string> SymbolMapping;
69 : };
70 :
71 : /// Returns a CommentHandler that parses pragma comment on include files to
72 : /// determine when we should include a different header from the header that
73 : /// directly defines a symbol. Mappinps are registered with \p Includes.
74 : ///
75 : /// Currently it only supports IWYU private pragma:
76 : /// https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-private
77 : std::unique_ptr<CommentHandler>
78 : collectIWYUHeaderMaps(CanonicalIncludes *Includes);
79 :
80 : /// Adds mapping for system headers and some special symbols (e.g. STL symbols
81 : /// in <iosfwd> need to be mapped individually). Approximately, the following
82 : /// system headers are handled:
83 : /// - C++ standard library e.g. bits/basic_string.h$ -> <string>
84 : /// - Posix library e.g. bits/pthreadtypes.h$ -> <pthread.h>
85 : /// - Compiler extensions, e.g. include/avx512bwintrin.h$ -> <immintrin.h>
86 : /// The mapping is hardcoded and hand-maintained, so it might not cover all
87 : /// headers.
88 : void addSystemHeadersMapping(CanonicalIncludes *Includes);
89 :
90 : } // namespace clangd
91 : } // namespace clang
92 :
93 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_INDEX_HEADERMAPCOLLECTOR_H
|