forked from OSchip/llvm-project
[clangd] Test against path insensitivity
Differential Revision: https://reviews.llvm.org/D121286
This commit is contained in:
parent
442e9e1389
commit
164a10dcf2
|
@ -11,6 +11,7 @@
|
|||
#include "SourceCode.h"
|
||||
#include "index/SymbolCollector.h"
|
||||
#include "support/Logger.h"
|
||||
#include "support/Path.h"
|
||||
#include "clang/AST/Decl.h"
|
||||
|
||||
namespace clang {
|
||||
|
@ -82,7 +83,7 @@ llvm::Optional<Path> getCorrespondingHeaderOrSource(PathRef OriginalFile,
|
|||
llvm::StringMap<int> Candidates; // Target path => score.
|
||||
auto AwardTarget = [&](const char *TargetURI) {
|
||||
if (auto TargetPath = URI::resolve(TargetURI, OriginalFile)) {
|
||||
if (*TargetPath != OriginalFile) // exclude the original file.
|
||||
if (!pathEqual(*TargetPath, OriginalFile)) // exclude the original file.
|
||||
++Candidates[*TargetPath];
|
||||
} else {
|
||||
elog("Failed to resolve URI {0}: {1}", TargetURI, TargetPath.takeError());
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
#include "TestFS.h"
|
||||
#include "TestTU.h"
|
||||
#include "index/MemIndex.h"
|
||||
#include "support/Path.h"
|
||||
#include "llvm/ADT/None.h"
|
||||
#include "llvm/Testing/Support/SupportHelpers.h"
|
||||
#include "gmock/gmock.h"
|
||||
#include "gtest/gtest.h"
|
||||
|
||||
|
@ -271,6 +273,43 @@ TEST(HeaderSourceSwitchTest, ClangdServerIntegration) {
|
|||
*llvm::cantFail(runSwitchHeaderSource(Server, CppPath)));
|
||||
}
|
||||
|
||||
TEST(HeaderSourceSwitchTest, CaseSensitivity) {
|
||||
TestTU TU = TestTU::withCode("void foo() {}");
|
||||
// Define more symbols in the header than the source file to trick heuristics
|
||||
// into picking the header as source file, if the matching for header file
|
||||
// path fails.
|
||||
TU.HeaderCode = R"cpp(
|
||||
inline void bar1() {}
|
||||
inline void bar2() {}
|
||||
void foo();)cpp";
|
||||
// Give main file and header different base names to make sure file system
|
||||
// heuristics don't work.
|
||||
TU.Filename = "Source.cpp";
|
||||
TU.HeaderFilename = "Header.h";
|
||||
|
||||
auto Index = TU.index();
|
||||
TU.Code = std::move(TU.HeaderCode);
|
||||
TU.HeaderCode.clear();
|
||||
auto AST = TU.build();
|
||||
|
||||
// Provide a different-cased filename in the query than what we have in the
|
||||
// index, check if we can still find the source file, which defines less
|
||||
// symbols than the header.
|
||||
auto HeaderAbsPath = testPath("HEADER.H");
|
||||
// We expect the heuristics to pick:
|
||||
// - header on case sensitive file systems, because the HeaderAbsPath doesn't
|
||||
// match what we've seen through index.
|
||||
// - source on case insensitive file systems, as the HeaderAbsPath would match
|
||||
// the filename in index.
|
||||
#ifdef CLANGD_PATH_CASE_INSENSITIVE
|
||||
EXPECT_THAT(getCorrespondingHeaderOrSource(HeaderAbsPath, AST, Index.get()),
|
||||
llvm::ValueIs(testing::StrCaseEq(testPath(TU.Filename))));
|
||||
#else
|
||||
EXPECT_THAT(getCorrespondingHeaderOrSource(HeaderAbsPath, AST, Index.get()),
|
||||
llvm::ValueIs(testing::StrCaseEq(testPath(TU.HeaderFilename))));
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace
|
||||
} // namespace clangd
|
||||
} // namespace clang
|
||||
|
|
|
@ -18,6 +18,18 @@
|
|||
namespace clang {
|
||||
namespace clangd {
|
||||
|
||||
namespace {
|
||||
|
||||
// Tries to strip \p Prefix from beginning of \p Path. Returns true on success.
|
||||
// If \p Prefix doesn't match, leaves \p Path untouched and returns false.
|
||||
bool pathConsumeFront(PathRef &Path, PathRef Prefix) {
|
||||
if (!pathStartsWith(Prefix, Path))
|
||||
return false;
|
||||
Path = Path.drop_front(Prefix.size());
|
||||
return true;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
|
||||
buildTestFS(llvm::StringMap<std::string> const &Files,
|
||||
llvm::StringMap<time_t> const &Timestamps) {
|
||||
|
@ -99,7 +111,7 @@ public:
|
|||
llvm::Expected<std::string>
|
||||
getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
|
||||
llvm::StringRef HintPath) const override {
|
||||
if (!HintPath.empty() && !HintPath.startswith(testRoot()))
|
||||
if (!HintPath.empty() && !pathStartsWith(testRoot(), HintPath))
|
||||
return error("Hint path is not empty and doesn't start with {0}: {1}",
|
||||
testRoot(), HintPath);
|
||||
if (!Body.consume_front("/"))
|
||||
|
@ -111,12 +123,11 @@ public:
|
|||
|
||||
llvm::Expected<URI>
|
||||
uriFromAbsolutePath(llvm::StringRef AbsolutePath) const override {
|
||||
llvm::StringRef Body = AbsolutePath;
|
||||
if (!Body.consume_front(testRoot()))
|
||||
if (!pathConsumeFront(AbsolutePath, testRoot()))
|
||||
return error("{0} does not start with {1}", AbsolutePath, testRoot());
|
||||
|
||||
return URI(Scheme, /*Authority=*/"",
|
||||
llvm::sys::path::convert_to_slash(Body));
|
||||
llvm::sys::path::convert_to_slash(AbsolutePath));
|
||||
}
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue