From 25f1f7325feac42b3bf05fd408e15b6a6be7d81c Mon Sep 17 00:00:00 2001 From: Simon Marchi Date: Fri, 10 Aug 2018 22:27:53 +0000 Subject: [clangd] Avoid duplicates in findDefinitions response Summary: When compile_commands.json contains some source files expressed as relative paths, we can get duplicate responses to findDefinitions. The responses only differ by the URI, which are different versions of the same file: "result": [ { ... "uri": "file:///home/emaisin/src/ls-interact/cpp-test/build/../src/first.h" }, { ... "uri": "file:///home/emaisin/src/ls-interact/cpp-test/src/first.h" } ] In getAbsoluteFilePath, we try to obtain the realpath of the FileEntry by calling tryGetRealPathName. However, this can fail and return an empty string. It may be bug a bug in clang, but in any case we should fall back to computing it ourselves if it happens. I changed getAbsoluteFilePath so that if tryGetRealPathName succeeds, we return right away (a real path is always absolute). Otherwise, we try to build an absolute path, as we did before, but we also call VFS->getRealPath to make sure to get the canonical path (e.g. without any ".." in it). Reviewers: malaperle Subscribers: hokein, ilya-biryukov, ioeric, MaskRay, jkorous, cfe-commits Differential Revision: https://reviews.llvm.org/D48687 llvm-svn: 339483 --- clang-tools-extra/clangd/SourceCode.cpp | 34 ++++++++++++++++++++++++--------- 1 file changed, 25 insertions(+), 9 deletions(-) (limited to 'clang-tools-extra/clangd/SourceCode.cpp') diff --git a/clang-tools-extra/clangd/SourceCode.cpp b/clang-tools-extra/clangd/SourceCode.cpp index 88ec2c956830..931ad3c0f20e 100644 --- a/clang-tools-extra/clangd/SourceCode.cpp +++ b/clang-tools-extra/clangd/SourceCode.cpp @@ -185,18 +185,34 @@ std::vector replacementsToEdits(StringRef Code, return Edits; } -llvm::Optional -getAbsoluteFilePath(const FileEntry *F, const SourceManager &SourceMgr) { - SmallString<64> FilePath = F->tryGetRealPathName(); - if (FilePath.empty()) - FilePath = F->getName(); - if (!llvm::sys::path::is_absolute(FilePath)) { - if (!SourceMgr.getFileManager().makeAbsolutePath(FilePath)) { - log("Could not turn relative path to absolute: {0}", FilePath); +llvm::Optional getRealPath(const FileEntry *F, + const SourceManager &SourceMgr) { + // Ideally, we get the real path from the FileEntry object. + SmallString<128> FilePath = F->tryGetRealPathName(); + if (!FilePath.empty()) { + return FilePath.str().str(); + } + + // Otherwise, we try to compute ourselves. + vlog("FileEntry for {0} did not contain the real path.", F->getName()); + + llvm::SmallString<128> Path = F->getName(); + + if (!llvm::sys::path::is_absolute(Path)) { + if (!SourceMgr.getFileManager().makeAbsolutePath(Path)) { + log("Could not turn relative path to absolute: {0}", Path); return llvm::None; } } - return FilePath.str().str(); + + llvm::SmallString<128> RealPath; + if (SourceMgr.getFileManager().getVirtualFileSystem()->getRealPath( + Path, RealPath)) { + log("Could not compute real path: {0}", Path); + return Path.str().str(); + } + + return RealPath.str().str(); } TextEdit toTextEdit(const FixItHint &FixIt, const SourceManager &M, -- cgit v1.2.3