diff --git a/clang-tools-extra/clangd/index/SymbolCollector.h b/clang-tools-extra/clangd/index/SymbolCollector.h --- a/clang-tools-extra/clangd/index/SymbolCollector.h +++ b/clang-tools-extra/clangd/index/SymbolCollector.h @@ -22,6 +22,7 @@ #include "llvm/ADT/DenseMap.h" #include "llvm/Support/Regex.h" #include +#include namespace clang { namespace clangd { @@ -142,6 +143,9 @@ // File IDs for Symbol.IncludeHeaders. // The final spelling is calculated in finish(). llvm::DenseMap IncludeFiles; + // Caches FileID to header mappings, values are either verbatim headers or + // URIs. None in case of a bad header, e.g. not include-guarded. + llvm::DenseMap> HeaderToInclude; void setIncludeLocation(const Symbol &S, SourceLocation); // Indexed macros, to be erased if they turned out to be include guards. llvm::DenseSet IndexedMacros; diff --git a/clang-tools-extra/clangd/index/SymbolCollector.cpp b/clang-tools-extra/clangd/index/SymbolCollector.cpp --- a/clang-tools-extra/clangd/index/SymbolCollector.cpp +++ b/clang-tools-extra/clangd/index/SymbolCollector.cpp @@ -781,13 +781,17 @@ if (Canonical != Filename) return toURI(SM, Canonical, Opts); } + auto FIDMapping = HeaderToInclude.find(FID); + if (FIDMapping != HeaderToInclude.end()) + return FIDMapping->second; if (!isSelfContainedHeader(FID)) { // A .inc or .def file is often included into a real header to define // symbols (e.g. LLVM tablegen files). if (Filename.endswith(".inc") || Filename.endswith(".def")) - return getIncludeHeader(S, SM.getFileID(SM.getIncludeLoc(FID))); + return HeaderToInclude[FID] = + getIncludeHeader(S, SM.getFileID(SM.getIncludeLoc(FID))); // Conservatively refuse to insert #includes to files without guards. - return llvm::None; + return HeaderToInclude[FID] = llvm::None; } // Store system includes as verbatim. This enables making use of the same // index in different environments, e.g. a system header like @@ -798,9 +802,9 @@ PP->getHeaderSearchInfo().suggestPathToFileForDiagnostics(FE, "", &IsSystem); if (IsSystem) - return "<" + ShorterInclude + ">"; + return HeaderToInclude[FID] = "<" + ShorterInclude + ">"; // Standard case: just insert the file itself. - return toURI(SM, Filename, Opts); + return HeaderToInclude[FID] = toURI(SM, Filename, Opts); } bool SymbolCollector::isSelfContainedHeader(FileID FID) {