aboutsummaryrefslogtreecommitdiff
path: root/clangd/Headers.h
diff options
context:
space:
mode:
Diffstat (limited to 'clangd/Headers.h')
-rw-r--r--clangd/Headers.h89
1 files changed, 63 insertions, 26 deletions
diff --git a/clangd/Headers.h b/clangd/Headers.h
index 987832fc..2abf27c6 100644
--- a/clangd/Headers.h
+++ b/clangd/Headers.h
@@ -45,29 +45,47 @@ struct Inclusion {
Path Resolved; // Resolved path of included file. Empty if not resolved.
};
+// Information captured about the inclusion graph in a translation unit.
+// This includes detailed information about the direct #includes, and summary
+// information about all transitive includes.
+//
+// It should be built incrementally with collectIncludeStructureCallback().
+// When we build the preamble, we capture and store its include structure along
+// with the preamble data. When we use the preamble, we can copy its
+// IncludeStructure and use another collectIncludeStructureCallback() to fill
+// in any non-preamble inclusions.
+class IncludeStructure {
+public:
+ std::vector<Inclusion> MainFileIncludes;
+
+ // Return all transitively reachable files, and their minimum include depth.
+ // All transitive includes (absolute paths), with their minimum include depth.
+ // Root --> 0, #included file --> 1, etc.
+ // Root is clang's name for a file, which may not be absolute.
+ // Usually it should be SM.getFileEntryForID(SM.getMainFileID())->getName().
+ llvm::StringMap<unsigned> includeDepth(llvm::StringRef Root) const;
+
+ // This updates IncludeDepth(), but not MainFileIncludes.
+ void recordInclude(llvm::StringRef IncludingName,
+ llvm::StringRef IncludedName,
+ llvm::StringRef IncludedRealName);
+
+private:
+ // Identifying files in a way that persists from preamble build to subsequent
+ // builds is surprisingly hard. FileID is unavailable in InclusionDirective(),
+ // and RealPathName and UniqueID are not preseved in the preamble.
+ // We use the FileEntry::Name, which is stable, interned into a "file index".
+ // The paths we want to expose are the RealPathName, so store those too.
+ std::vector<std::string> RealPathNames; // In file index order.
+ unsigned fileIndex(llvm::StringRef Name);
+ llvm::StringMap<unsigned> NameToIndex; // Values are file indexes.
+ // Maps a file's index to that of the files it includes.
+ llvm::DenseMap<unsigned, SmallVector<unsigned, 8>> IncludeChildren;
+};
+
/// Returns a PPCallback that visits all inclusions in the main file.
std::unique_ptr<PPCallbacks>
-collectInclusionsInMainFileCallback(const SourceManager &SM,
- std::function<void(Inclusion)> Callback);
-
-/// Determines the preferred way to #include a file, taking into account the
-/// search path. Usually this will prefer a shorter representation like
-/// 'Foo/Bar.h' over a longer one like 'Baz/include/Foo/Bar.h'.
-///
-/// \param File is an absolute file path.
-/// \param Inclusions Existing inclusions in the main file.
-/// \param DeclaringHeader is the original header corresponding to \p
-/// InsertedHeader e.g. the header that declares a symbol.
-/// \param InsertedHeader The preferred header to be inserted. This could be the
-/// same as DeclaringHeader but must be provided.
-// \return A quoted "path" or <path>. This returns an empty string if:
-/// - Either \p DeclaringHeader or \p InsertedHeader is already (directly)
-/// in \p Inclusions (including those included via different paths).
-/// - \p DeclaringHeader or \p InsertedHeader is the same as \p File.
-llvm::Expected<std::string> calculateIncludePath(
- PathRef File, StringRef BuildDir, HeaderSearch &HeaderSearchInfo,
- const std::vector<Inclusion> &Inclusions, const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader);
+collectIncludeStructureCallback(const SourceManager &SM, IncludeStructure *Out);
// Calculates insertion edit for including a new header in a file.
class IncludeInserter {
@@ -81,16 +99,35 @@ public:
void addExisting(Inclusion Inc) { Inclusions.push_back(std::move(Inc)); }
- /// Returns a TextEdit that inserts a new header; if the header is not
- /// inserted e.g. it's an existing header, this returns None. If any header is
- /// invalid, this returns error.
+ /// Checks whether to add an #include of the header into \p File.
+ /// An #include will not be added if:
+ /// - Either \p DeclaringHeader or \p InsertedHeader is already (directly)
+ /// in \p Inclusions (including those included via different paths).
+ /// - \p DeclaringHeader or \p InsertedHeader is the same as \p File.
///
/// \param DeclaringHeader is the original header corresponding to \p
/// InsertedHeader e.g. the header that declares a symbol.
/// \param InsertedHeader The preferred header to be inserted. This could be
/// the same as DeclaringHeader but must be provided.
- Expected<Optional<TextEdit>> insert(const HeaderFile &DeclaringHeader,
- const HeaderFile &InsertedHeader) const;
+ bool shouldInsertInclude(const HeaderFile &DeclaringHeader,
+ const HeaderFile &InsertedHeader) const;
+
+ /// Determines the preferred way to #include a file, taking into account the
+ /// search path. Usually this will prefer a shorter representation like
+ /// 'Foo/Bar.h' over a longer one like 'Baz/include/Foo/Bar.h'.
+ ///
+ /// \param DeclaringHeader is the original header corresponding to \p
+ /// InsertedHeader e.g. the header that declares a symbol.
+ /// \param InsertedHeader The preferred header to be inserted. This could be
+ /// the same as DeclaringHeader but must be provided.
+ ///
+ /// \return A quoted "path" or <path> to be included.
+ std::string calculateIncludePath(const HeaderFile &DeclaringHeader,
+ const HeaderFile &InsertedHeader) const;
+
+ /// Calculates an edit that inserts \p VerbatimHeader into code. If the header
+ /// is already included, this returns None.
+ llvm::Optional<TextEdit> insert(llvm::StringRef VerbatimHeader) const;
private:
StringRef FileName;