Line data Source code
1 : //===--- Headers.h - Include headers -----------------------------*- 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 : #ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
11 : #define LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
12 :
13 : #include "Path.h"
14 : #include "Protocol.h"
15 : #include "SourceCode.h"
16 : #include "clang/Format/Format.h"
17 : #include "clang/Lex/HeaderSearch.h"
18 : #include "clang/Lex/PPCallbacks.h"
19 : #include "clang/Tooling/Inclusions/HeaderIncludes.h"
20 : #include "llvm/ADT/StringRef.h"
21 : #include "llvm/ADT/StringSet.h"
22 : #include "llvm/Support/Error.h"
23 : #include "llvm/Support/VirtualFileSystem.h"
24 :
25 : namespace clang {
26 : namespace clangd {
27 :
28 : /// Returns true if \p Include is literal include like "path" or <path>.
29 : bool isLiteralInclude(llvm::StringRef Include);
30 :
31 : /// Represents a header file to be #include'd.
32 0 : struct HeaderFile {
33 : std::string File;
34 : /// If this is true, `File` is a literal string quoted with <> or "" that
35 : /// can be #included directly; otherwise, `File` is an absolute file path.
36 : bool Verbatim;
37 :
38 : bool valid() const;
39 : };
40 :
41 : // An #include directive that we found in the main file.
42 : struct Inclusion {
43 : Range R; // Inclusion range.
44 : std::string Written; // Inclusion name as written e.g. <vector>.
45 : Path Resolved; // Resolved path of included file. Empty if not resolved.
46 : };
47 :
48 : // Information captured about the inclusion graph in a translation unit.
49 : // This includes detailed information about the direct #includes, and summary
50 : // information about all transitive includes.
51 : //
52 : // It should be built incrementally with collectIncludeStructureCallback().
53 : // When we build the preamble, we capture and store its include structure along
54 : // with the preamble data. When we use the preamble, we can copy its
55 : // IncludeStructure and use another collectIncludeStructureCallback() to fill
56 : // in any non-preamble inclusions.
57 0 : class IncludeStructure {
58 : public:
59 : std::vector<Inclusion> MainFileIncludes;
60 :
61 : // Return all transitively reachable files, and their minimum include depth.
62 : // All transitive includes (absolute paths), with their minimum include depth.
63 : // Root --> 0, #included file --> 1, etc.
64 : // Root is clang's name for a file, which may not be absolute.
65 : // Usually it should be SM.getFileEntryForID(SM.getMainFileID())->getName().
66 : llvm::StringMap<unsigned> includeDepth(llvm::StringRef Root) const;
67 :
68 : // This updates IncludeDepth(), but not MainFileIncludes.
69 : void recordInclude(llvm::StringRef IncludingName,
70 : llvm::StringRef IncludedName,
71 : llvm::StringRef IncludedRealName);
72 :
73 : private:
74 : // Identifying files in a way that persists from preamble build to subsequent
75 : // builds is surprisingly hard. FileID is unavailable in InclusionDirective(),
76 : // and RealPathName and UniqueID are not preseved in the preamble.
77 : // We use the FileEntry::Name, which is stable, interned into a "file index".
78 : // The paths we want to expose are the RealPathName, so store those too.
79 : std::vector<std::string> RealPathNames; // In file index order.
80 : unsigned fileIndex(llvm::StringRef Name);
81 : llvm::StringMap<unsigned> NameToIndex; // Values are file indexes.
82 : // Maps a file's index to that of the files it includes.
83 : llvm::DenseMap<unsigned, SmallVector<unsigned, 8>> IncludeChildren;
84 : };
85 :
86 : /// Returns a PPCallback that visits all inclusions in the main file.
87 : std::unique_ptr<PPCallbacks>
88 : collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out);
89 :
90 : // Calculates insertion edit for including a new header in a file.
91 0 : class IncludeInserter {
92 : public:
93 : IncludeInserter(StringRef FileName, StringRef Code,
94 : const format::FormatStyle &Style, StringRef BuildDir,
95 : HeaderSearch &HeaderSearchInfo)
96 : : FileName(FileName), Code(Code), BuildDir(BuildDir),
97 : HeaderSearchInfo(HeaderSearchInfo),
98 0 : Inserter(FileName, Code, Style.IncludeStyle) {}
99 :
100 : void addExisting(const Inclusion &Inc);
101 :
102 : /// Checks whether to add an #include of the header into \p File.
103 : /// An #include will not be added if:
104 : /// - Either \p DeclaringHeader or \p InsertedHeader is already (directly)
105 : /// in \p Inclusions (including those included via different paths).
106 : /// - \p DeclaringHeader or \p InsertedHeader is the same as \p File.
107 : ///
108 : /// \param DeclaringHeader is the original header corresponding to \p
109 : /// InsertedHeader e.g. the header that declares a symbol.
110 : /// \param InsertedHeader The preferred header to be inserted. This could be
111 : /// the same as DeclaringHeader but must be provided.
112 : bool shouldInsertInclude(const HeaderFile &DeclaringHeader,
113 : const HeaderFile &InsertedHeader) const;
114 :
115 : /// Determines the preferred way to #include a file, taking into account the
116 : /// search path. Usually this will prefer a shorter representation like
117 : /// 'Foo/Bar.h' over a longer one like 'Baz/include/Foo/Bar.h'.
118 : ///
119 : /// \param DeclaringHeader is the original header corresponding to \p
120 : /// InsertedHeader e.g. the header that declares a symbol.
121 : /// \param InsertedHeader The preferred header to be inserted. This could be
122 : /// the same as DeclaringHeader but must be provided.
123 : ///
124 : /// \return A quoted "path" or <path> to be included.
125 : std::string calculateIncludePath(const HeaderFile &DeclaringHeader,
126 : const HeaderFile &InsertedHeader) const;
127 :
128 : /// Calculates an edit that inserts \p VerbatimHeader into code. If the header
129 : /// is already included, this returns None.
130 : llvm::Optional<TextEdit> insert(llvm::StringRef VerbatimHeader) const;
131 :
132 : private:
133 : StringRef FileName;
134 : StringRef Code;
135 : StringRef BuildDir;
136 : HeaderSearch &HeaderSearchInfo;
137 : llvm::StringSet<> IncludedHeaders; // Both written and resolved.
138 : tooling::HeaderIncludes Inserter; // Computers insertion replacement.
139 : };
140 :
141 : } // namespace clangd
142 : } // namespace clang
143 :
144 : #endif // LLVM_CLANG_TOOLS_EXTRA_CLANGD_HEADERS_H
|