diff options
| -rw-r--r-- | clang-tools-extra/clangd/XRefs.cpp | 12 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/TestFS.cpp | 12 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/TestFS.h | 5 | ||||
| -rw-r--r-- | clang-tools-extra/unittests/clangd/XRefsTests.cpp | 30 |
4 files changed, 51 insertions, 8 deletions
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp index e7ded2ee1e8..6f43353dce6 100644 --- a/clang-tools-extra/clangd/XRefs.cpp +++ b/clang-tools-extra/clangd/XRefs.cpp @@ -11,6 +11,7 @@ #include "URI.h" #include "clang/Index/IndexDataConsumer.h" #include "clang/Index/IndexingAction.h" +#include "llvm/Support/Path.h" namespace clang { namespace clangd { using namespace llvm; @@ -138,10 +139,17 @@ getDeclarationLocation(ParsedAST &AST, const SourceRange &ValSourceRange) { Range R = {Begin, End}; Location L; - StringRef FilePath = F->tryGetRealPathName(); + SmallString<64> FilePath = F->tryGetRealPathName(); if (FilePath.empty()) FilePath = F->getName(); - L.uri.file = FilePath; + if (!llvm::sys::path::is_absolute(FilePath)) { + if (!SourceMgr.getFileManager().makeAbsolutePath(FilePath)) { + log("Could not turn relative path to absolute: " + FilePath); + return llvm::None; + } + } + + L.uri.file = FilePath.str(); L.range = R; return L; } diff --git a/clang-tools-extra/unittests/clangd/TestFS.cpp b/clang-tools-extra/unittests/clangd/TestFS.cpp index 55506e6c4e0..38cef894074 100644 --- a/clang-tools-extra/unittests/clangd/TestFS.cpp +++ b/clang-tools-extra/unittests/clangd/TestFS.cpp @@ -33,8 +33,10 @@ MockFSProvider::getTaggedFileSystem(PathRef File) { return make_tagged(FS, Tag); } -MockCompilationDatabase::MockCompilationDatabase() - : ExtraClangFlags({"-ffreestanding"}) {} // Avoid implicit stdc-predef.h. +MockCompilationDatabase::MockCompilationDatabase(bool UseRelPaths) + : ExtraClangFlags({"-ffreestanding"}), UseRelPaths(UseRelPaths) { + // -ffreestanding avoids implicit stdc-predef.h. +} llvm::Optional<tooling::CompileCommand> MockCompilationDatabase::getCompileCommand(PathRef File) const { @@ -42,10 +44,10 @@ MockCompilationDatabase::getCompileCommand(PathRef File) const { return llvm::None; auto CommandLine = ExtraClangFlags; + auto FileName = llvm::sys::path::filename(File); CommandLine.insert(CommandLine.begin(), "clang"); - CommandLine.insert(CommandLine.end(), File.str()); - return {tooling::CompileCommand(llvm::sys::path::parent_path(File), - llvm::sys::path::filename(File), + CommandLine.insert(CommandLine.end(), UseRelPaths ? FileName : File); + return {tooling::CompileCommand(llvm::sys::path::parent_path(File), FileName, std::move(CommandLine), "")}; } diff --git a/clang-tools-extra/unittests/clangd/TestFS.h b/clang-tools-extra/unittests/clangd/TestFS.h index 6ff1c662201..5edde1fff9e 100644 --- a/clang-tools-extra/unittests/clangd/TestFS.h +++ b/clang-tools-extra/unittests/clangd/TestFS.h @@ -37,12 +37,15 @@ public: // A Compilation database that returns a fixed set of compile flags. class MockCompilationDatabase : public GlobalCompilationDatabase { public: - MockCompilationDatabase(); + /// When \p UseRelPaths is true, uses relative paths in compile commands. + /// When \p UseRelPaths is false, uses absoulte paths. + MockCompilationDatabase(bool UseRelPaths = false); llvm::Optional<tooling::CompileCommand> getCompileCommand(PathRef File) const override; std::vector<std::string> ExtraClangFlags; + const bool UseRelPaths; }; // Returns an absolute (fake) test directory for this OS. diff --git a/clang-tools-extra/unittests/clangd/XRefsTests.cpp b/clang-tools-extra/unittests/clangd/XRefsTests.cpp index 59e30725ba0..50d24c50113 100644 --- a/clang-tools-extra/unittests/clangd/XRefsTests.cpp +++ b/clang-tools-extra/unittests/clangd/XRefsTests.cpp @@ -8,6 +8,7 @@ //===----------------------------------------------------------------------===// #include "Annotations.h" #include "ClangdUnit.h" +#include "Compiler.h" #include "Matchers.h" #include "TestFS.h" #include "XRefs.h" @@ -37,6 +38,11 @@ using testing::Field; using testing::Matcher; using testing::UnorderedElementsAreArray; +class IgnoreDiagnostics : public DiagnosticsConsumer { + void onDiagnosticsReady( + PathRef File, Tagged<std::vector<DiagWithFixIts>> Diagnostics) override {} +}; + // FIXME: this is duplicated with FileIndexTests. Share it. ParsedAST build(StringRef Code) { auto TestFile = getVirtualTestFilePath("Foo.cpp"); @@ -227,6 +233,30 @@ TEST(GoToDefinition, All) { } } +TEST(GoToDefinition, RelPathsInCompileCommand) { + Annotations SourceAnnotations(R"cpp( +[[int foo]]; +int baz = f^oo; +)cpp"); + + IgnoreDiagnostics DiagConsumer; + MockCompilationDatabase CDB(/*UseRelPaths=*/true); + MockFSProvider FS; + ClangdServer Server(CDB, DiagConsumer, FS, /*AsyncThreadsCount=*/0, + /*StorePreambleInMemory=*/true); + + auto FooCpp = getVirtualTestFilePath("foo.cpp"); + FS.Files[FooCpp] = ""; + + Server.addDocument(FooCpp, SourceAnnotations.code()); + auto Locations = Server.findDefinitions(FooCpp, SourceAnnotations.point()); + EXPECT_TRUE(bool(Locations)) << "findDefinitions returned an error"; + + EXPECT_THAT(Locations->Value, + ElementsAre(Location{URIForFile{FooCpp.str()}, + SourceAnnotations.range()})); +} + } // namespace } // namespace clangd } // namespace clang |

