diff --git a/clang-tools-extra/clangd/Hover.h b/clang-tools-extra/clangd/Hover.h --- a/clang-tools-extra/clangd/Hover.h +++ b/clang-tools-extra/clangd/Hover.h @@ -58,7 +58,8 @@ std::string Documentation; /// Source code containing the definition of the symbol. std::string Definition; - + /// For #include directives, the pointed-to file. + llvm::Optional TargetFile; /// Access specifier for declarations inside class/struct/unions, empty for /// others. std::string AccessSpecifier; diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp --- a/clang-tools-extra/clangd/Hover.cpp +++ b/clang-tools-extra/clangd/Hover.cpp @@ -14,6 +14,7 @@ #include "ParsedAST.h" #include "Selection.h" #include "SourceCode.h" +#include "XRefs.h" #include "index/SymbolCollector.h" #include "support/Logger.h" #include "support/Markup.h" @@ -905,6 +906,16 @@ if (TokensTouchingCursor.empty()) return llvm::None; + // Show full header file path if cursor is on include directive. + if (const auto MainFilePath + = getCanonicalPath(SM.getFileEntryForID(SM.getMainFileID()), SM)) { + if (const auto File = locateFileReferent(Pos, AST, *MainFilePath)) { + HoverInfo HI; + HI.TargetFile = File->Definition; + return HI; + } + } + // To be used as a backup for highlighting the selected token, we use back as // it aligns better with biases elsewhere (editors tend to send the position // for the left of the hovered token). @@ -981,6 +992,13 @@ markup::Document HoverInfo::present() const { markup::Document Output; + + // For expanded header files, we just print the plain path. + if (TargetFile) { + Output.addParagraph().appendText(TargetFile->uri.file()); + return Output; + } + // Header contains a text of the form: // variable `var` // diff --git a/clang-tools-extra/clangd/XRefs.h b/clang-tools-extra/clangd/XRefs.h --- a/clang-tools-extra/clangd/XRefs.h +++ b/clang-tools-extra/clangd/XRefs.h @@ -74,6 +74,12 @@ const syntax::Token *findNearbyIdentifier(const SpelledWord &Word, const syntax::TokenBuffer &TB); +// Treat #included files as symbols, to enable go-to-definition and hover +// on them. +llvm::Optional locateFileReferent(const Position &Pos, + ParsedAST &AST, + llvm::StringRef MainFilePath); + /// Get all document links std::vector getDocumentLinks(ParsedAST &AST); diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -227,24 +227,6 @@ return L; } -// Treat #included files as symbols, to enable go-to-definition on them. -llvm::Optional locateFileReferent(const Position &Pos, - ParsedAST &AST, - llvm::StringRef MainFilePath) { - for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { - if (!Inc.Resolved.empty() && Inc.HashLine == Pos.line) { - LocatedSymbol File; - File.Name = std::string(llvm::sys::path::filename(Inc.Resolved)); - File.PreferredDeclaration = { - URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}}; - File.Definition = File.PreferredDeclaration; - // We're not going to find any further symbols on #include lines. - return File; - } - } - return llvm::None; -} - // Macros are simple: there's no declaration/definition distinction. // As a consequence, there's no need to look them up in the index either. llvm::Optional @@ -552,6 +534,23 @@ } // namespace +llvm::Optional locateFileReferent(const Position &Pos, + ParsedAST &AST, + llvm::StringRef MainFilePath) { + for (auto &Inc : AST.getIncludeStructure().MainFileIncludes) { + if (!Inc.Resolved.empty() && Inc.HashLine == Pos.line) { + LocatedSymbol File; + File.Name = std::string(llvm::sys::path::filename(Inc.Resolved)); + File.PreferredDeclaration = { + URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}}; + File.Definition = File.PreferredDeclaration; + // We're not going to find any further symbols on #include lines. + return File; + } + } + return llvm::None; +} + std::vector locateSymbolTextually(const SpelledWord &Word, ParsedAST &AST, const SymbolIndex *Index, const std::string &MainFilePath, @@ -1987,4 +1986,4 @@ } } // namespace clangd -} // namespace clang \ No newline at end of file +} // namespace clang diff --git a/clang-tools-extra/clangd/unittests/HoverTests.cpp b/clang-tools-extra/clangd/unittests/HoverTests.cpp --- a/clang-tools-extra/clangd/unittests/HoverTests.cpp +++ b/clang-tools-extra/clangd/unittests/HoverTests.cpp @@ -2750,6 +2750,15 @@ // In test::Bar int foo = 3)", + }, + { + [](HoverInfo &HI) + { + HI.TargetFile = Location(); + HI.TargetFile->uri + = URIForFile::canonicalize("/usr/include/stdio.h", "/"); + }, + "/usr/include/stdio.h", }}; for (const auto &C : Cases) {