[clang-tools-extra] [clangd] Turn `Path` and `PathRef` into classes (PR #136439)
via cfe-commits
cfe-commits at lists.llvm.org
Sat Apr 19 10:50:40 PDT 2025
https://github.com/Nerixyz updated https://github.com/llvm/llvm-project/pull/136439
>From 9fc8237e136176ed60981e3c28a991bf00fe4dbc Mon Sep 17 00:00:00 2001
From: Nerixyz <nerixdev at outlook.de>
Date: Sat, 19 Apr 2025 18:30:38 +0200
Subject: [PATCH] [clangd] Turn `Path` and `PathRef` into classes
---
clang-tools-extra/clangd/ASTSignals.cpp | 2 +-
clang-tools-extra/clangd/ClangdLSPServer.cpp | 6 +-
clang-tools-extra/clangd/ClangdServer.cpp | 72 ++++---
clang-tools-extra/clangd/CodeComplete.cpp | 32 +--
clang-tools-extra/clangd/ConfigCompile.cpp | 5 +-
clang-tools-extra/clangd/ConfigProvider.cpp | 9 +-
clang-tools-extra/clangd/DraftStore.cpp | 6 +-
clang-tools-extra/clangd/FS.cpp | 6 -
clang-tools-extra/clangd/FS.h | 8 -
.../clangd/GlobalCompilationDatabase.cpp | 50 ++---
.../clangd/HeaderSourceSwitch.cpp | 24 ++-
clang-tools-extra/clangd/Headers.cpp | 6 +-
clang-tools-extra/clangd/Hover.cpp | 2 +-
clang-tools-extra/clangd/IncludeCleaner.cpp | 16 +-
clang-tools-extra/clangd/ModulesBuilder.cpp | 14 +-
clang-tools-extra/clangd/ParsedAST.cpp | 5 +-
clang-tools-extra/clangd/Preamble.cpp | 8 +-
clang-tools-extra/clangd/Protocol.cpp | 10 +-
clang-tools-extra/clangd/Protocol.h | 4 +-
.../clangd/ScanningProjectModules.cpp | 8 +-
clang-tools-extra/clangd/TUScheduler.cpp | 60 +++---
clang-tools-extra/clangd/TidyProvider.cpp | 14 +-
clang-tools-extra/clangd/XRefs.cpp | 29 +--
clang-tools-extra/clangd/index/Background.cpp | 14 +-
clang-tools-extra/clangd/index/Background.h | 1 +
.../clangd/index/BackgroundIndexLoader.cpp | 16 +-
.../clangd/index/BackgroundIndexLoader.h | 2 +-
.../clangd/index/BackgroundIndexStorage.cpp | 4 +-
clang-tools-extra/clangd/index/FileIndex.cpp | 4 +-
clang-tools-extra/clangd/refactor/Rename.cpp | 5 +-
clang-tools-extra/clangd/refactor/Tweak.cpp | 2 +-
clang-tools-extra/clangd/refactor/Tweak.h | 3 +-
.../clangd/refactor/tweaks/DefineInline.cpp | 5 +-
.../clangd/refactor/tweaks/DefineOutline.cpp | 17 +-
.../clangd/support/FileCache.cpp | 6 +-
clang-tools-extra/clangd/support/Path.cpp | 146 +++++++++++--
clang-tools-extra/clangd/support/Path.h | 202 ++++++++++++++++--
.../clangd/support/ThreadsafeFS.cpp | 2 +-
clang-tools-extra/clangd/tool/ClangdMain.cpp | 16 +-
.../clangd/unittests/ASTTests.cpp | 2 +-
.../clangd/unittests/BackgroundIndexTests.cpp | 43 ++--
.../clangd/unittests/ClangdTests.cpp | 16 +-
.../clangd/unittests/CodeCompleteTests.cpp | 2 +-
.../GlobalCompilationDatabaseTests.cpp | 10 +-
.../unittests/HeaderSourceSwitchTests.cpp | 14 +-
.../clangd/unittests/HeadersTests.cpp | 2 +-
.../clangd/unittests/PreambleTests.cpp | 10 +-
.../clangd/unittests/TUSchedulerTests.cpp | 6 +-
clang-tools-extra/clangd/unittests/TestFS.cpp | 21 +-
.../clangd/unittests/support/PathTests.cpp | 20 +-
50 files changed, 625 insertions(+), 362 deletions(-)
diff --git a/clang-tools-extra/clangd/ASTSignals.cpp b/clang-tools-extra/clangd/ASTSignals.cpp
index cffadb091d557..21647994d259e 100644
--- a/clang-tools-extra/clangd/ASTSignals.cpp
+++ b/clang-tools-extra/clangd/ASTSignals.cpp
@@ -19,7 +19,7 @@ ASTSignals ASTSignals::derive(const ParsedAST &AST) {
trace::Span Span("ASTSignals::derive");
ASTSignals Signals;
Signals.InsertionDirective = preferredIncludeDirective(
- AST.tuPath(), AST.getLangOpts(),
+ AST.tuPath().raw(), AST.getLangOpts(),
AST.getIncludeStructure().MainFileIncludes, AST.getLocalTopLevelDecls());
const SourceManager &SM = AST.getSourceManager();
findExplicitReferences(
diff --git a/clang-tools-extra/clangd/ClangdLSPServer.cpp b/clang-tools-extra/clangd/ClangdLSPServer.cpp
index 1e981825c7c15..35ada432cd5dd 100644
--- a/clang-tools-extra/clangd/ClangdLSPServer.cpp
+++ b/clang-tools-extra/clangd/ClangdLSPServer.cpp
@@ -926,11 +926,11 @@ void ClangdLSPServer::onDocumentDidClose(
{
std::lock_guard<std::mutex> Lock(DiagRefMutex);
- DiagRefMap.erase(File);
+ DiagRefMap.erase(File.raw());
}
{
std::lock_guard<std::mutex> HLock(SemanticTokensMutex);
- LastSemanticTokens.erase(File);
+ LastSemanticTokens.erase(File.raw());
}
// clangd will not send updates for this file anymore, so we empty out the
// list of diagnostics shown on the client (e.g. in the "Problems" pane of
@@ -1816,7 +1816,7 @@ void ClangdLSPServer::onDiagnosticsReady(PathRef File, llvm::StringRef Version,
// Cache DiagRefMap
{
std::lock_guard<std::mutex> Lock(DiagRefMutex);
- DiagRefMap[File] = LocalDiagMap;
+ DiagRefMap[File.raw()] = LocalDiagMap;
}
// Send a notification to the LSP client.
diff --git a/clang-tools-extra/clangd/ClangdServer.cpp b/clang-tools-extra/clangd/ClangdServer.cpp
index 52844129834c3..8ae5aa79674f2 100644
--- a/clang-tools-extra/clangd/ClangdServer.cpp
+++ b/clang-tools-extra/clangd/ClangdServer.cpp
@@ -88,15 +88,15 @@ struct UpdateIndexCallbacks : public ParsingCallbacks {
indexStdlib(CI, std::move(*Loc));
// FIndex outlives the UpdateIndexCallbacks.
- auto Task = [FIndex(FIndex), Path(Path.str()), Version(Version.str()),
+ auto Task = [FIndex(FIndex), Path(Path.owned()), Version(Version.str()),
ASTCtx(std::move(ASTCtx)), PI(std::move(PI))]() mutable {
trace::Span Tracer("PreambleIndexing");
- FIndex->updatePreamble(Path, Version, ASTCtx.getASTContext(),
+ FIndex->updatePreamble(Path.raw(), Version, ASTCtx.getASTContext(),
ASTCtx.getPreprocessor(), *PI);
};
if (Tasks) {
- Tasks->runAsync("Preamble indexing for:" + Path + Version,
+ Tasks->runAsync("Preamble indexing for:" + Path.raw() + Version,
std::move(Task));
} else
Task();
@@ -262,7 +262,7 @@ ClangdServer::ClangdServer(const GlobalCompilationDatabase &CDB,
BackgroundIdx = std::make_unique<BackgroundIndex>(
TFS, CDB,
BackgroundIndexStorage::createDiskBackedStorageFactory(
- [&CDB](llvm::StringRef File) { return CDB.getProjectInfo(File); }),
+ [&CDB](PathRef File) { return CDB.getProjectInfo(File); }),
std::move(BGOpts));
AddIndex(BackgroundIdx.get());
}
@@ -316,14 +316,14 @@ void ClangdServer::addDocument(PathRef File, llvm::StringRef Contents,
bool NewFile = WorkScheduler->update(File, Inputs, WantDiags);
// If we loaded Foo.h, we want to make sure Foo.cpp is indexed.
if (NewFile && BackgroundIdx)
- BackgroundIdx->boostRelated(File);
+ BackgroundIdx->boostRelated(File.raw());
}
void ClangdServer::reparseOpenFilesIfNeeded(
llvm::function_ref<bool(llvm::StringRef File)> Filter) {
// Reparse only opened files that were modified.
for (const Path &FilePath : DraftMgr.getActiveFiles())
- if (Filter(FilePath))
+ if (Filter(FilePath.raw()))
if (auto Draft = DraftMgr.getDraft(FilePath)) // else disappeared in race?
addDocument(FilePath, *Draft->Contents, Draft->Version,
WantDiagnostics::Auto);
@@ -340,7 +340,7 @@ std::function<Context(PathRef)>
ClangdServer::createConfiguredContextProvider(const config::Provider *Provider,
Callbacks *Publish) {
if (!Provider)
- return [](llvm::StringRef) { return Context::current().clone(); };
+ return [](PathRef) { return Context::current().clone(); };
struct Impl {
const config::Provider *Provider;
@@ -408,8 +408,8 @@ ClangdServer::createConfiguredContextProvider(const config::Provider *Provider,
};
// Copyable wrapper.
- return [I(std::make_shared<Impl>(Provider, Publish))](llvm::StringRef Path) {
- return (*I)(Path);
+ return [I(std::make_shared<Impl>(Provider, Publish))](PathRef Path) {
+ return (*I)(Path.raw());
};
}
@@ -426,7 +426,7 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
if (!CodeCompleteOpts.Index) // Respect overridden index.
CodeCompleteOpts.Index = Index;
- auto Task = [Pos, CodeCompleteOpts, File = File.str(), CB = std::move(CB),
+ auto Task = [Pos, CodeCompleteOpts, File = File.owned(), CB = std::move(CB),
this](llvm::Expected<InputsAndPreamble> IP) mutable {
if (!IP)
return CB(IP.takeError());
@@ -442,7 +442,8 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
SpecFuzzyFind.emplace();
{
std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
- SpecFuzzyFind->CachedReq = CachedCompletionFuzzyFindRequestByFile[File];
+ SpecFuzzyFind->CachedReq =
+ CachedCompletionFuzzyFindRequestByFile[File.raw()];
}
}
ParseInputs ParseInput{IP->Command, &getHeaderFS(), IP->Contents.str()};
@@ -473,7 +474,8 @@ void ClangdServer::codeComplete(PathRef File, Position Pos,
return;
if (SpecFuzzyFind->NewReq) {
std::lock_guard<std::mutex> Lock(CachedCompletionFuzzyFindRequestMutex);
- CachedCompletionFuzzyFindRequestByFile[File] = *SpecFuzzyFind->NewReq;
+ CachedCompletionFuzzyFindRequestByFile[File.raw()] =
+ *SpecFuzzyFind->NewReq;
}
// Explicitly block until async task completes, this is fine as we've
// already provided reply to the client and running as a preamble task
@@ -495,7 +497,7 @@ void ClangdServer::signatureHelp(PathRef File, Position Pos,
MarkupKind DocumentationFormat,
Callback<SignatureHelp> CB) {
- auto Action = [Pos, File = File.str(), CB = std::move(CB),
+ auto Action = [Pos, File = File.owned(), CB = std::move(CB),
DocumentationFormat,
this](llvm::Expected<InputsAndPreamble> IP) mutable {
if (!IP)
@@ -540,12 +542,13 @@ void ClangdServer::formatFile(PathRef File, std::optional<Range> Rng,
}
// Call clang-format.
- auto Action = [File = File.str(), Code = std::move(*Code),
+ auto Action = [File = File.owned(), Code = std::move(*Code),
Ranges = std::vector<tooling::Range>{RequestedRange},
CB = std::move(CB), this]() mutable {
- format::FormatStyle Style = getFormatStyleForFile(File, Code, TFS, true);
+ format::FormatStyle Style =
+ getFormatStyleForFile(File.raw(), Code, TFS, true);
tooling::Replacements IncludeReplaces =
- format::sortIncludes(Style, Code, Ranges, File);
+ format::sortIncludes(Style, Code, Ranges, File.raw());
auto Changed = tooling::applyAllReplacements(Code, IncludeReplaces);
if (!Changed)
return CB(Changed.takeError());
@@ -553,9 +556,9 @@ void ClangdServer::formatFile(PathRef File, std::optional<Range> Rng,
CB(IncludeReplaces.merge(format::reformat(
Style, *Changed,
tooling::calculateRangesAfterReplacements(IncludeReplaces, Ranges),
- File)));
+ File.raw())));
};
- WorkScheduler->runQuick("Format", File, std::move(Action));
+ WorkScheduler->runQuick("Format", File.raw(), std::move(Action));
}
void ClangdServer::formatOnType(PathRef File, Position Pos,
@@ -568,24 +571,24 @@ void ClangdServer::formatOnType(PathRef File, Position Pos,
llvm::Expected<size_t> CursorPos = positionToOffset(*Code, Pos);
if (!CursorPos)
return CB(CursorPos.takeError());
- auto Action = [File = File.str(), Code = std::move(*Code),
+ auto Action = [File = File.owned(), Code = std::move(*Code),
TriggerText = TriggerText.str(), CursorPos = *CursorPos,
CB = std::move(CB), this]() mutable {
- auto Style = getFormatStyleForFile(File, Code, TFS, false);
+ auto Style = getFormatStyleForFile(File.raw(), Code, TFS, false);
std::vector<TextEdit> Result;
for (const tooling::Replacement &R :
formatIncremental(Code, CursorPos, TriggerText, Style))
Result.push_back(replacementToEdit(Code, R));
return CB(Result);
};
- WorkScheduler->runQuick("FormatOnType", File, std::move(Action));
+ WorkScheduler->runQuick("FormatOnType", File.raw(), std::move(Action));
}
void ClangdServer::prepareRename(PathRef File, Position Pos,
std::optional<std::string> NewName,
const RenameOptions &RenameOpts,
Callback<RenameResult> CB) {
- auto Action = [Pos, File = File.str(), CB = std::move(CB),
+ auto Action = [Pos, File = File.owned(), CB = std::move(CB),
NewName = std::move(NewName),
RenameOpts](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
@@ -594,7 +597,7 @@ void ClangdServer::prepareRename(PathRef File, Position Pos,
// only need main-file references
auto Results =
clangd::rename({Pos, NewName.value_or("__clangd_rename_placeholder"),
- InpAST->AST, File, /*FS=*/nullptr,
+ InpAST->AST, File.raw(), /*FS=*/nullptr,
/*Index=*/nullptr, RenameOpts});
if (!Results) {
// LSP says to return null on failure, but that will result in a generic
@@ -610,7 +613,7 @@ void ClangdServer::prepareRename(PathRef File, Position Pos,
void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
const RenameOptions &Opts,
Callback<RenameResult> CB) {
- auto Action = [File = File.str(), NewName = NewName.str(), Pos, Opts,
+ auto Action = [File = File.owned(), NewName = NewName.str(), Pos, Opts,
CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
// Tracks number of files edited per invocation.
@@ -618,13 +621,13 @@ void ClangdServer::rename(PathRef File, Position Pos, llvm::StringRef NewName,
trace::Metric::Distribution);
if (!InpAST)
return CB(InpAST.takeError());
- auto R = clangd::rename({Pos, NewName, InpAST->AST, File,
+ auto R = clangd::rename({Pos, NewName, InpAST->AST, File.raw(),
DirtyFS->view(std::nullopt), Index, Opts});
if (!R)
return CB(R.takeError());
if (Opts.WantFormat) {
- auto Style = getFormatStyleForFile(File, InpAST->Inputs.Contents,
+ auto Style = getFormatStyleForFile(File.raw(), InpAST->Inputs.Contents,
*InpAST->Inputs.TFS, false);
llvm::Error Err = llvm::Error::success();
for (auto &E : R->GlobalChanges)
@@ -756,7 +759,7 @@ void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
static constexpr trace::Metric TweakFailed(
"tweak_failed", trace::Metric::Counter, "tweak_id");
TweakAttempt.record(1, TweakID);
- auto Action = [File = File.str(), Sel, TweakID = TweakID.str(),
+ auto Action = [File = File.owned(), Sel, TweakID = TweakID.str(),
CB = std::move(CB),
this](Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
@@ -782,7 +785,7 @@ void ClangdServer::applyTweak(PathRef File, Range Sel, StringRef TweakID,
for (auto &It : (*Effect)->ApplyEdits) {
Edit &E = It.second;
format::FormatStyle Style =
- getFormatStyleForFile(File, E.InitialCode, TFS, false);
+ getFormatStyleForFile(File.raw(), E.InitialCode, TFS, false);
if (llvm::Error Err = reformatEdit(E, Style))
elog("Failed to format {0}: {1}", It.first(), std::move(Err));
}
@@ -817,7 +820,7 @@ void ClangdServer::switchSourceHeader(
if (auto CorrespondingFile =
getCorrespondingHeaderOrSource(Path, TFS.view(std::nullopt)))
return CB(std::move(CorrespondingFile));
- auto Action = [Path = Path.str(), CB = std::move(CB),
+ auto Action = [Path = Path.owned(), CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
@@ -840,12 +843,12 @@ void ClangdServer::findDocumentHighlights(
void ClangdServer::findHover(PathRef File, Position Pos,
Callback<std::optional<HoverInfo>> CB) {
- auto Action = [File = File.str(), Pos, CB = std::move(CB),
+ auto Action = [File = File.owned(), Pos, CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
format::FormatStyle Style = getFormatStyleForFile(
- File, InpAST->Inputs.Contents, *InpAST->Inputs.TFS, false);
+ File.raw(), InpAST->Inputs.Contents, *InpAST->Inputs.TFS, false);
CB(clangd::getHover(InpAST->AST, Pos, std::move(Style), Index));
};
@@ -855,7 +858,8 @@ void ClangdServer::findHover(PathRef File, Position Pos,
void ClangdServer::typeHierarchy(PathRef File, Position Pos, int Resolve,
TypeHierarchyDirection Direction,
Callback<std::vector<TypeHierarchyItem>> CB) {
- auto Action = [File = File.str(), Pos, Resolve, Direction, CB = std::move(CB),
+ auto Action = [File = File.owned(), Pos, Resolve, Direction,
+ CB = std::move(CB),
this](Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
@@ -894,7 +898,7 @@ void ClangdServer::resolveTypeHierarchy(
void ClangdServer::prepareCallHierarchy(
PathRef File, Position Pos, Callback<std::vector<CallHierarchyItem>> CB) {
- auto Action = [File = File.str(), Pos,
+ auto Action = [File = File.owned(), Pos,
CB = std::move(CB)](Expected<InputsAndAST> InpAST) mutable {
if (!InpAST)
return CB(InpAST.takeError());
@@ -976,7 +980,7 @@ void ClangdServer::foldingRanges(llvm::StringRef File,
WorkScheduler->runQuick("FoldingRanges", File, std::move(Action));
}
-void ClangdServer::findType(llvm::StringRef File, Position Pos,
+void ClangdServer::findType(PathRef File, Position Pos,
Callback<std::vector<LocatedSymbol>> CB) {
auto Action = [Pos, CB = std::move(CB),
this](llvm::Expected<InputsAndAST> InpAST) mutable {
diff --git a/clang-tools-extra/clangd/CodeComplete.cpp b/clang-tools-extra/clangd/CodeComplete.cpp
index 0eb196fbad46a..ebbcea5f67bbf 100644
--- a/clang-tools-extra/clangd/CodeComplete.cpp
+++ b/clang-tools-extra/clangd/CodeComplete.cpp
@@ -1384,14 +1384,14 @@ bool semaCodeComplete(std::unique_ptr<CodeCompleteConsumer> Consumer,
CI->getLangOpts().DelayedTemplateParsing = false;
// Setup code completion.
FrontendOpts.CodeCompleteOpts = Options;
- FrontendOpts.CodeCompletionAt.FileName = std::string(Input.FileName);
+ FrontendOpts.CodeCompletionAt.FileName = Input.FileName.owned().raw();
std::tie(FrontendOpts.CodeCompletionAt.Line,
FrontendOpts.CodeCompletionAt.Column) =
offsetToClangLineColumn(Input.ParseInput.Contents, Input.Offset);
std::unique_ptr<llvm::MemoryBuffer> ContentsBuffer =
llvm::MemoryBuffer::getMemBuffer(Input.ParseInput.Contents,
- Input.FileName);
+ Input.FileName.raw());
// The diagnostic options must be set before creating a CompilerInstance.
CI->getDiagnosticOpts().IgnoreWarnings = true;
// We reuse the preamble whether it's valid or not. This is a
@@ -1649,7 +1649,7 @@ class CodeCompleteFlow {
assert(Recorder && "Recorder is not set");
CCContextKind = Recorder->CCContext.getKind();
IsUsingDeclaration = Recorder->CCContext.isUsingDeclaration();
- auto Style = getFormatStyleForFile(SemaCCInput.FileName,
+ auto Style = getFormatStyleForFile(SemaCCInput.FileName.raw(),
SemaCCInput.ParseInput.Contents,
*SemaCCInput.ParseInput.TFS, false);
const auto NextToken = findTokenAfterCompletionPoint(
@@ -1660,7 +1660,7 @@ class CodeCompleteFlow {
// If preprocessor was run, inclusions from preprocessor callback should
// already be added to Includes.
Inserter.emplace(
- SemaCCInput.FileName, SemaCCInput.ParseInput.Contents, Style,
+ SemaCCInput.FileName.raw(), SemaCCInput.ParseInput.Contents, Style,
SemaCCInput.ParseInput.CompileCommand.Directory,
&Recorder->CCSema->getPreprocessor().getHeaderSearchInfo(),
Config::current().Style.QuotedHeaders,
@@ -1741,12 +1741,12 @@ class CodeCompleteFlow {
ReplacedRange.start.character -= HeuristicPrefix.Name.size();
llvm::StringMap<SourceParams> ProxSources;
- ProxSources[FileName].Cost = 0;
+ ProxSources[FileName.raw()].Cost = 0;
FileProximity.emplace(ProxSources);
- auto Style = getFormatStyleForFile(FileName, Content, TFS, false);
+ auto Style = getFormatStyleForFile(FileName.raw(), Content, TFS, false);
// This will only insert verbatim headers.
- Inserter.emplace(FileName, Content, Style,
+ Inserter.emplace(FileName.raw(), Content, Style,
/*BuildDir=*/"", /*HeaderSearchInfo=*/nullptr,
Config::current().Style.QuotedHeaders,
Config::current().Style.AngledHeaders);
@@ -1917,7 +1917,7 @@ class CodeCompleteFlow {
Req.Scopes = QueryScopes;
Req.AnyScope = AllScopes;
// FIXME: we should send multiple weighted paths here.
- Req.ProximityPaths.push_back(std::string(FileName));
+ Req.ProximityPaths.push_back(FileName.owned().raw());
if (PreferredType)
Req.PreferredTypes.push_back(std::string(PreferredType->raw()));
vlog("Code complete: fuzzyFind({0:2})", toJSON(Req));
@@ -1972,8 +1972,9 @@ class CodeCompleteFlow {
assert(IdentifierResult);
C.Name = IdentifierResult->Name;
}
- if (auto OverloadSet = C.overloadSet(
- Opts, FileName, Inserter ? &*Inserter : nullptr, CCContextKind)) {
+ if (auto OverloadSet =
+ C.overloadSet(Opts, FileName.raw(),
+ Inserter ? &*Inserter : nullptr, CCContextKind)) {
auto Ret = BundleLookup.try_emplace(OverloadSet, Bundles.size());
if (Ret.second)
Bundles.emplace_back();
@@ -2140,8 +2141,9 @@ class CodeCompleteFlow {
: nullptr;
if (!Builder)
Builder.emplace(Recorder ? &Recorder->CCSema->getASTContext() : nullptr,
- Item, SemaCCS, AccessibleScopes, *Inserter, FileName,
- CCContextKind, Opts, IsUsingDeclaration, NextTokenKind);
+ Item, SemaCCS, AccessibleScopes, *Inserter,
+ FileName.raw(), CCContextKind, Opts, IsUsingDeclaration,
+ NextTokenKind);
else
Builder->add(Item, SemaCCS, CCContextKind);
}
@@ -2214,7 +2216,7 @@ CodeCompleteResult codeCompleteComment(PathRef FileName, unsigned Offset,
semaCodeComplete(
std::make_unique<ParamNameCollector>(Options, ParamNames), Options,
{FileName, Offset, *Preamble,
- PreamblePatch::createFullPatch(FileName, ParseInput, *Preamble),
+ PreamblePatch::createFullPatch(FileName.raw(), ParseInput, *Preamble),
ParseInput});
if (ParamNames.empty())
return CodeCompleteResult();
@@ -2288,7 +2290,7 @@ CodeCompleteResult codeComplete(PathRef FileName, Position Pos,
: std::move(Flow).run({FileName, *Offset, *Preamble,
/*PreamblePatch=*/
PreamblePatch::createMacroPatch(
- FileName, ParseInput, *Preamble),
+ FileName.raw(), ParseInput, *Preamble),
ParseInput});
}
@@ -2312,7 +2314,7 @@ SignatureHelp signatureHelp(PathRef FileName, Position Pos,
ParseInput.Index, Result),
Options,
{FileName, *Offset, Preamble,
- PreamblePatch::createFullPatch(FileName, ParseInput, Preamble),
+ PreamblePatch::createFullPatch(FileName.raw(), ParseInput, Preamble),
ParseInput});
return Result;
}
diff --git a/clang-tools-extra/clangd/ConfigCompile.cpp b/clang-tools-extra/clangd/ConfigCompile.cpp
index 13c2405e76df7..a2487c957a230 100644
--- a/clang-tools-extra/clangd/ConfigCompile.cpp
+++ b/clang-tools-extra/clangd/ConfigCompile.cpp
@@ -411,8 +411,9 @@ struct FragmentCompiler {
C.Index.External = Spec;
return;
}
- if (P.Path.empty() || !pathStartsWith(Spec.MountPoint, P.Path,
- llvm::sys::path::Style::posix))
+ if (P.Path.empty() ||
+ !PathRef(Spec.MountPoint)
+ .startsWith(P.Path, llvm::sys::path::Style::posix))
return;
C.Index.External = Spec;
// Disable background indexing for the files under the mountpoint.
diff --git a/clang-tools-extra/clangd/ConfigProvider.cpp b/clang-tools-extra/clangd/ConfigProvider.cpp
index ac437ee8b6eb1..24dacabd82b2a 100644
--- a/clang-tools-extra/clangd/ConfigProvider.cpp
+++ b/clang-tools-extra/clangd/ConfigProvider.cpp
@@ -43,7 +43,8 @@ class FileConfigCache : public FileCache {
[&](std::optional<llvm::StringRef> Data) {
CachedValue.clear();
if (Data)
- for (auto &Fragment : Fragment::parseYAML(*Data, path(), DC)) {
+ for (auto &Fragment :
+ Fragment::parseYAML(*Data, path().raw(), DC)) {
Fragment.Source.Directory = Directory;
Fragment.Source.Trusted = Trusted;
CachedValue.push_back(std::move(Fragment).compile(DC));
@@ -103,9 +104,9 @@ Provider::fromAncestorRelativeYAMLFiles(llvm::StringRef RelPath,
// Compute absolute paths to all ancestors (substrings of P.Path).
llvm::SmallVector<llvm::StringRef, 8> Ancestors;
- for (auto Ancestor = absoluteParent(P.Path); !Ancestor.empty();
- Ancestor = absoluteParent(Ancestor)) {
- Ancestors.emplace_back(Ancestor);
+ for (auto Ancestor = PathRef(P.Path).absoluteParent(); !Ancestor.empty();
+ Ancestor = Ancestor.absoluteParent()) {
+ Ancestors.emplace_back(Ancestor.raw());
}
// Ensure corresponding cache entries exist in the map.
llvm::SmallVector<FileConfigCache *, 8> Caches;
diff --git a/clang-tools-extra/clangd/DraftStore.cpp b/clang-tools-extra/clangd/DraftStore.cpp
index 66e45b0c04ce3..de84b693f449b 100644
--- a/clang-tools-extra/clangd/DraftStore.cpp
+++ b/clang-tools-extra/clangd/DraftStore.cpp
@@ -19,7 +19,7 @@ namespace clangd {
std::optional<DraftStore::Draft> DraftStore::getDraft(PathRef File) const {
std::lock_guard<std::mutex> Lock(Mutex);
- auto It = Drafts.find(File);
+ auto It = Drafts.find(File.raw());
if (It == Drafts.end())
return std::nullopt;
@@ -76,7 +76,7 @@ std::string DraftStore::addDraft(PathRef File, llvm::StringRef Version,
llvm::StringRef Contents) {
std::lock_guard<std::mutex> Lock(Mutex);
- auto &D = Drafts[File];
+ auto &D = Drafts[File.raw()];
updateVersion(D.D, Version);
std::time(&D.MTime);
D.D.Contents = std::make_shared<std::string>(Contents);
@@ -86,7 +86,7 @@ std::string DraftStore::addDraft(PathRef File, llvm::StringRef Version,
void DraftStore::removeDraft(PathRef File) {
std::lock_guard<std::mutex> Lock(Mutex);
- Drafts.erase(File);
+ Drafts.erase(File.raw());
}
namespace {
diff --git a/clang-tools-extra/clangd/FS.cpp b/clang-tools-extra/clangd/FS.cpp
index 5729b9341d9d4..cdf5fc6aceae0 100644
--- a/clang-tools-extra/clangd/FS.cpp
+++ b/clang-tools-extra/clangd/FS.cpp
@@ -113,11 +113,5 @@ PreambleFileStatusCache::getConsumingFS(
return llvm::IntrusiveRefCntPtr<CacheVFS>(new CacheVFS(std::move(FS), *this));
}
-Path removeDots(PathRef File) {
- llvm::SmallString<128> CanonPath(File);
- llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
- return CanonPath.str().str();
-}
-
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/FS.h b/clang-tools-extra/clangd/FS.h
index 827b465aed983..4f9845bdf9111 100644
--- a/clang-tools-extra/clangd/FS.h
+++ b/clang-tools-extra/clangd/FS.h
@@ -9,7 +9,6 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_FS_H
-#include "support/Path.h"
#include "clang/Basic/LLVM.h"
#include "llvm/ADT/StringMap.h"
#include "llvm/Support/VirtualFileSystem.h"
@@ -68,13 +67,6 @@ class PreambleFileStatusCache {
llvm::StringMap<llvm::vfs::Status> StatCache;
};
-/// Returns a version of \p File that doesn't contain dots and dot dots.
-/// e.g /a/b/../c -> /a/c
-/// /a/b/./c -> /a/b/c
-/// FIXME: We should avoid encountering such paths in clangd internals by
-/// filtering everything we get over LSP, CDB, etc.
-Path removeDots(PathRef File);
-
} // namespace clangd
} // namespace clang
diff --git a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
index 7c0eb9651feaa..8743344845125 100644
--- a/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
+++ b/clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
@@ -47,8 +47,8 @@ namespace {
// deepest directory and going up to root. Stops whenever action succeeds.
void actOnAllParentDirectories(PathRef FileName,
llvm::function_ref<bool(PathRef)> Action) {
- for (auto Path = absoluteParent(FileName); !Path.empty() && !Action(Path);
- Path = absoluteParent(Path))
+ for (auto Path = FileName.absoluteParent(); !Path.empty() && !Action(Path);
+ Path = Path.absoluteParent())
;
}
@@ -60,12 +60,12 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
// Clang treats .h files as C by default and files without extension as linker
// input, resulting in unhelpful diagnostics.
// Parsing as Objective C++ is friendly to more cases.
- auto FileExtension = llvm::sys::path::extension(File);
+ auto FileExtension = File.extension();
if (FileExtension.empty() || FileExtension == ".h")
Argv.push_back("-xobjective-c++-header");
- Argv.push_back(std::string(File));
- tooling::CompileCommand Cmd(llvm::sys::path::parent_path(File),
- llvm::sys::path::filename(File), std::move(Argv),
+ Argv.push_back(File.owned().raw());
+ tooling::CompileCommand Cmd(File.parentPath().raw(), File.filename(),
+ std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
return Cmd;
@@ -265,7 +265,7 @@ parseJSON(PathRef Path, llvm::StringRef Data, std::string &Error) {
static std::unique_ptr<tooling::CompilationDatabase>
parseFixed(PathRef Path, llvm::StringRef Data, std::string &Error) {
return tooling::FixedCompilationDatabase::loadFromBuffer(
- llvm::sys::path::parent_path(Path), Data, Error);
+ Path.parentPath().raw(), Data, Error);
}
bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load(
@@ -374,7 +374,7 @@ DirectoryBasedGlobalCompilationDatabase::getCompileCommand(PathRef File) const {
return std::nullopt;
}
- auto Candidates = Res->CDB->getCompileCommands(File);
+ auto Candidates = Res->CDB->getCompileCommands(File.raw());
if (!Candidates.empty())
return std::move(Candidates.front());
@@ -388,10 +388,10 @@ DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches(
FoldedDirs.reserve(Dirs.size());
for (const auto &Dir : Dirs) {
#ifndef NDEBUG
- if (!llvm::sys::path::is_absolute(Dir))
+ if (!PathRef(Dir).isAbsolute())
elog("Trying to cache CDB for relative {0}");
#endif
- FoldedDirs.push_back(maybeCaseFoldPath(Dir));
+ FoldedDirs.push_back(PathRef(Dir).caseFolded().raw());
}
std::vector<DirectoryCache *> Ret;
@@ -406,15 +406,15 @@ DirectoryBasedGlobalCompilationDatabase::getDirectoryCaches(
std::optional<DirectoryBasedGlobalCompilationDatabase::CDBLookupResult>
DirectoryBasedGlobalCompilationDatabase::lookupCDB(
CDBLookupRequest Request) const {
- assert(llvm::sys::path::is_absolute(Request.FileName) &&
- "path must be absolute");
+ assert(Request.FileName.isAbsolute() && "path must be absolute");
std::string Storage;
std::vector<llvm::StringRef> SearchDirs;
if (Opts.CompileCommandsDir) // FIXME: unify this case with config.
- SearchDirs = {*Opts.CompileCommandsDir};
+ SearchDirs = {Opts.CompileCommandsDir->raw()};
else {
- WithContext WithProvidedContext(Opts.ContextProvider(Request.FileName));
+ WithContext WithProvidedContext(
+ Opts.ContextProvider(Request.FileName.raw()));
const auto &Spec = Config::current().CompileFlags.CDBSearch;
switch (Spec.Policy) {
case Config::CDBSearchSpec::NoCDBSearch:
@@ -427,9 +427,9 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
// Traverse the canonical version to prevent false positives. i.e.:
// src/build/../a.cc can detect a CDB in /src/build if not
// canonicalized.
- Storage = removeDots(Request.FileName);
- actOnAllParentDirectories(Storage, [&](llvm::StringRef Dir) {
- SearchDirs.push_back(Dir);
+ Storage = Request.FileName.removeDots().raw();
+ actOnAllParentDirectories(Storage, [&](PathRef Dir) {
+ SearchDirs.push_back(Dir.raw());
return false;
});
}
@@ -581,8 +581,8 @@ class DirectoryBasedGlobalCompilationDatabase::BroadcastThread::Filter {
DirInfo *addParents(llvm::StringRef FilePath) {
DirInfo *Leaf = nullptr;
DirInfo *Child = nullptr;
- actOnAllParentDirectories(FilePath, [&](llvm::StringRef Dir) {
- auto &Info = Dirs[Dir];
+ actOnAllParentDirectories(FilePath, [&](PathRef Dir) {
+ auto &Info = Dirs[Dir.raw()];
// If this is the first iteration, then this node is the overall result.
if (!Leaf)
Leaf = &Info;
@@ -677,7 +677,7 @@ class DirectoryBasedGlobalCompilationDatabase::BroadcastThread::Filter {
std::vector<SearchPath> SearchPaths(AllFiles.size());
for (unsigned I = 0; I < AllFiles.size(); ++I) {
if (Parent.Opts.CompileCommandsDir) { // FIXME: unify with config
- SearchPaths[I].setPointer(&Dirs[*Parent.Opts.CompileCommandsDir]);
+ SearchPaths[I].setPointer(&Dirs[Parent.Opts.CompileCommandsDir->raw()]);
continue;
}
if (ExitEarly()) // loading config may be slow
@@ -768,7 +768,7 @@ OverlayCDB::getCompileCommand(PathRef File) const {
std::optional<tooling::CompileCommand> Cmd;
{
std::lock_guard<std::mutex> Lock(Mutex);
- auto It = Commands.find(removeDots(File));
+ auto It = Commands.find(File.removeDots().raw());
if (It != Commands.end())
Cmd = It->second;
}
@@ -793,7 +793,7 @@ OverlayCDB::getCompileCommand(PathRef File) const {
if (!Cmd)
return std::nullopt;
if (Mangler)
- Mangler(*Cmd, File);
+ Mangler(*Cmd, File.raw());
return Cmd;
}
@@ -803,7 +803,7 @@ tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
if (Mangler)
- Mangler(Cmd, File);
+ Mangler(Cmd, File.raw());
return Cmd;
}
@@ -812,7 +812,7 @@ bool OverlayCDB::setCompileCommand(PathRef File,
// We store a canonical version internally to prevent mismatches between set
// and get compile commands. Also it assures clients listening to broadcasts
// doesn't receive different names for the same file.
- std::string CanonPath = removeDots(File);
+ std::string CanonPath = File.removeDots().raw();
{
std::unique_lock<std::mutex> Lock(Mutex);
if (Cmd) {
@@ -835,7 +835,7 @@ OverlayCDB::getProjectModules(PathRef File) const {
auto MDB = DelegatingCDB::getProjectModules(File);
MDB->setCommandMangler([&Mangler = Mangler](tooling::CompileCommand &Command,
PathRef CommandPath) {
- Mangler(Command, CommandPath);
+ Mangler(Command, CommandPath.raw());
});
return MDB;
}
diff --git a/clang-tools-extra/clangd/HeaderSourceSwitch.cpp b/clang-tools-extra/clangd/HeaderSourceSwitch.cpp
index d54c3668570eb..4ea2fccda464e 100644
--- a/clang-tools-extra/clangd/HeaderSourceSwitch.cpp
+++ b/clang-tools-extra/clangd/HeaderSourceSwitch.cpp
@@ -26,16 +26,18 @@ std::optional<Path> getCorrespondingHeaderOrSource(
".inc", ".cppm", ".ccm", ".cxxm",
".c++m", ".ixx"};
- llvm::StringRef PathExt = llvm::sys::path::extension(OriginalFile);
+ llvm::StringRef PathExt = OriginalFile.extension();
// Lookup in a list of known extensions.
- bool IsSource = llvm::any_of(SourceExtensions, [&PathExt](PathRef SourceExt) {
- return SourceExt.equals_insensitive(PathExt);
- });
+ bool IsSource =
+ llvm::any_of(SourceExtensions, [&PathExt](llvm::StringRef SourceExt) {
+ return SourceExt.equals_insensitive(PathExt);
+ });
- bool IsHeader = llvm::any_of(HeaderExtensions, [&PathExt](PathRef HeaderExt) {
- return HeaderExt.equals_insensitive(PathExt);
- });
+ bool IsHeader =
+ llvm::any_of(HeaderExtensions, [&PathExt](llvm::StringRef HeaderExt) {
+ return HeaderExt.equals_insensitive(PathExt);
+ });
// We can only switch between the known extensions.
if (!IsSource && !IsHeader)
@@ -50,7 +52,7 @@ std::optional<Path> getCorrespondingHeaderOrSource(
NewExts = SourceExtensions;
// Storage for the new path.
- llvm::SmallString<128> NewPath = OriginalFile;
+ llvm::SmallString<128> NewPath = OriginalFile.raw();
// Loop through switched extension candidates.
for (llvm::StringRef NewExt : NewExts) {
@@ -81,8 +83,8 @@ std::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 (!pathEqual(*TargetPath, OriginalFile)) // exclude the original file.
+ if (auto TargetPath = URI::resolve(TargetURI, OriginalFile.raw())) {
+ if (PathRef(*TargetPath) != OriginalFile) // exclude the original file.
++Candidates[*TargetPath];
} else {
elog("Failed to resolve URI {0}: {1}", TargetURI, TargetPath.takeError());
@@ -94,7 +96,7 @@ std::optional<Path> getCorrespondingHeaderOrSource(PathRef OriginalFile,
//
// For each symbol in the original file, we get its target location (decl or
// def) from the index, then award that target file.
- bool IsHeader = isHeaderFile(OriginalFile, AST.getLangOpts());
+ bool IsHeader = isHeaderFile(OriginalFile.raw(), AST.getLangOpts());
Index->lookup(Request, [&](const Symbol &Sym) {
if (IsHeader)
AwardTarget(Sym.Definition.FileURI);
diff --git a/clang-tools-extra/clangd/Headers.cpp b/clang-tools-extra/clangd/Headers.cpp
index 87fd261b906e6..58bf77a1c9285 100644
--- a/clang-tools-extra/clangd/Headers.cpp
+++ b/clang-tools-extra/clangd/Headers.cpp
@@ -263,7 +263,7 @@ IncludeStructure::mainFileIncludesWithSpelling(llvm::StringRef Spelling) const {
void IncludeInserter::addExisting(const Inclusion &Inc) {
IncludedHeaders.insert(Inc.Written);
if (!Inc.Resolved.empty())
- IncludedHeaders.insert(Inc.Resolved);
+ IncludedHeaders.insert(Inc.Resolved.raw());
}
/// FIXME(ioeric): we might not want to insert an absolute include path if the
@@ -278,7 +278,7 @@ bool IncludeInserter::shouldInsertInclude(
auto Included = [&](llvm::StringRef Header) {
return IncludedHeaders.contains(Header);
};
- return !Included(DeclaringHeader) && !Included(InsertedHeader.File);
+ return !Included(DeclaringHeader.raw()) && !Included(InsertedHeader.File);
}
std::optional<std::string>
@@ -348,7 +348,7 @@ IncludeInserter::insert(llvm::StringRef VerbatimHeader,
llvm::raw_ostream &operator<<(llvm::raw_ostream &OS, const Inclusion &Inc) {
return OS << Inc.Written << " = "
- << (!Inc.Resolved.empty() ? Inc.Resolved : "[unresolved]")
+ << (!Inc.Resolved.empty() ? Inc.Resolved.raw() : "[unresolved]")
<< " at line" << Inc.HashLine;
}
diff --git a/clang-tools-extra/clangd/Hover.cpp b/clang-tools-extra/clangd/Hover.cpp
index 3ab3d89030520..c5957afbdc4de 100644
--- a/clang-tools-extra/clangd/Hover.cpp
+++ b/clang-tools-extra/clangd/Hover.cpp
@@ -1302,7 +1302,7 @@ std::optional<HoverInfo> getHover(ParsedAST &AST, Position Pos,
continue;
HoverCountMetric.record(1, "include");
HoverInfo HI;
- HI.Name = std::string(llvm::sys::path::filename(Inc.Resolved));
+ HI.Name = Inc.Resolved.ref().filename().str();
// FIXME: We don't have a fitting value for Kind.
HI.Definition =
URIForFile::canonicalize(Inc.Resolved, AST.tuPath()).file().str();
diff --git a/clang-tools-extra/clangd/IncludeCleaner.cpp b/clang-tools-extra/clangd/IncludeCleaner.cpp
index e34706172f0bf..c37adc1f58593 100644
--- a/clang-tools-extra/clangd/IncludeCleaner.cpp
+++ b/clang-tools-extra/clangd/IncludeCleaner.cpp
@@ -100,7 +100,7 @@ bool mayConsiderUnused(const Inclusion &Inc, ParsedAST &AST,
// Since most private -> public mappings happen in a verbatim way, we
// check textually here. This might go wrong in presence of symlinks or
// header mappings. But that's not different than rest of the places.
- if (AST.tuPath().ends_with(PHeader))
+ if (AST.tuPath().raw().ends_with(PHeader))
return false;
}
}
@@ -122,9 +122,9 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
const SourceManager &SM = AST.getSourceManager();
const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID());
- auto FileStyle = getFormatStyleForFile(AST.tuPath(), Code, TFS, false);
+ auto FileStyle = getFormatStyleForFile(AST.tuPath().raw(), Code, TFS, false);
- tooling::HeaderIncludes HeaderIncludes(AST.tuPath(), Code,
+ tooling::HeaderIncludes HeaderIncludes(AST.tuPath().raw(), Code,
FileStyle.IncludeStyle);
for (const auto &SymbolWithMissingInclude : MissingIncludes) {
llvm::StringRef ResolvedPath =
@@ -157,7 +157,7 @@ std::vector<Diag> generateMissingIncludeDiagnostics(
SymbolWithMissingInclude.Symbol.name());
D.Name = "missing-includes";
D.Source = Diag::DiagSource::Clangd;
- D.File = AST.tuPath();
+ D.File = AST.tuPath().raw();
D.InsideMainFile = true;
// We avoid the "warning" severity here in favor of LSP's "information".
//
@@ -194,7 +194,7 @@ std::vector<Diag> generateUnusedIncludeDiagnostics(
llvm::StringRef Code, HeaderFilter IgnoreHeaders) {
std::vector<Diag> Result;
for (const auto *Inc : UnusedIncludes) {
- if (isIgnored(Inc->Resolved, IgnoreHeaders))
+ if (isIgnored(Inc->Resolved.raw(), IgnoreHeaders))
continue;
Diag &D = Result.emplace_back();
D.Message =
@@ -204,7 +204,7 @@ std::vector<Diag> generateUnusedIncludeDiagnostics(
llvm::sys::path::Style::posix));
D.Name = "unused-includes";
D.Source = Diag::DiagSource::Clangd;
- D.File = FileName;
+ D.File = FileName.raw();
D.InsideMainFile = true;
D.Severity = DiagnosticsEngine::Warning;
D.Tags.push_back(Unnecessary);
@@ -343,7 +343,7 @@ include_cleaner::Includes convertIncludes(const ParsedAST &AST) {
TransformedInc.Angled = WrittenRef.starts_with("<");
// Inc.Resolved is canonicalized with clangd::getCanonicalPath(),
// which is based on FileManager::getCanonicalName(ParentDir).
- auto FE = SM.getFileManager().getFileRef(Inc.Resolved);
+ auto FE = SM.getFileManager().getFileRef(Inc.Resolved.raw());
if (!FE) {
elog("IncludeCleaner: Failed to get an entry for resolved path {0}: {1}",
Inc.Resolved, FE.takeError());
@@ -363,7 +363,7 @@ computeIncludeCleanerFindings(ParsedAST &AST, bool AnalyzeAngledIncludes) {
const auto &SM = AST.getSourceManager();
include_cleaner::Includes ConvertedIncludes = convertIncludes(AST);
const FileEntry *MainFile = SM.getFileEntryForID(SM.getMainFileID());
- auto PreamblePatch = PreamblePatch::getPatchEntry(AST.tuPath(), SM);
+ auto PreamblePatch = PreamblePatch::getPatchEntry(AST.tuPath().raw(), SM);
std::vector<include_cleaner::SymbolReference> Macros =
collectMacroReferences(AST);
diff --git a/clang-tools-extra/clangd/ModulesBuilder.cpp b/clang-tools-extra/clangd/ModulesBuilder.cpp
index c1878f91b5e16..72d5f6568ce51 100644
--- a/clang-tools-extra/clangd/ModulesBuilder.cpp
+++ b/clang-tools-extra/clangd/ModulesBuilder.cpp
@@ -36,10 +36,10 @@ namespace {
// TODO: Move these module fils out of the temporary directory if the module
// files are persistent.
llvm::SmallString<256> getUniqueModuleFilesPath(PathRef MainFile) {
- llvm::SmallString<128> HashedPrefix = llvm::sys::path::filename(MainFile);
+ llvm::SmallString<128> HashedPrefix = MainFile.filename();
// There might be multiple files with the same name in a project. So appending
// the hash value of the full path to make sure they won't conflict.
- HashedPrefix += std::to_string(llvm::hash_value(MainFile));
+ HashedPrefix += std::to_string(hash_value(MainFile));
llvm::SmallString<256> ResultPattern;
@@ -64,7 +64,7 @@ llvm::SmallString<256> getUniqueModuleFilesPath(PathRef MainFile) {
// Get a unique module file path under \param ModuleFilesPrefix.
std::string getModuleFilePath(llvm::StringRef ModuleName,
PathRef ModuleFilesPrefix) {
- llvm::SmallString<256> ModuleFilePath(ModuleFilesPrefix);
+ llvm::SmallString<256> ModuleFilePath(ModuleFilesPrefix.raw());
auto [PrimaryModuleName, PartitionName] = ModuleName.split(':');
llvm::sys::path::append(ModuleFilePath, PrimaryModuleName);
if (!PartitionName.empty()) {
@@ -97,7 +97,7 @@ class FailedPrerequisiteModules : public PrerequisiteModules {
struct ModuleFile {
ModuleFile(StringRef ModuleName, PathRef ModuleFilePath)
- : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.str()) {}
+ : ModuleName(ModuleName.str()), ModuleFilePath(ModuleFilePath.raw()) {}
ModuleFile() = delete;
@@ -216,7 +216,7 @@ bool IsModuleFileUpToDate(PathRef ModuleFilePath,
// listener.
Reader.setListener(nullptr);
- if (Reader.ReadAST(ModuleFilePath, serialization::MK_MainFile,
+ if (Reader.ReadAST(ModuleFilePath.raw(), serialization::MK_MainFile,
SourceLocation(),
ASTReader::ARR_None) != ASTReader::Success)
return false;
@@ -308,7 +308,7 @@ bool ReusablePrerequisiteModules::canReuse(
if (RequiredModules.empty())
return true;
- llvm::SmallVector<llvm::StringRef> BMIPaths;
+ llvm::SmallVector<PathRef> BMIPaths;
for (auto &MF : RequiredModules)
BMIPaths.push_back(MF->getModuleFilePath());
return IsModuleFilesUpToDate(BMIPaths, *this, VFS);
@@ -370,7 +370,7 @@ class ModuleNameToSourceCache {
void addEntry(llvm::StringRef ModuleName, PathRef Source) {
std::lock_guard<std::mutex> Lock(CacheMutex);
- ModuleNameToSourceCache[ModuleName] = Source.str();
+ ModuleNameToSourceCache[ModuleName] = Source.raw();
}
void eraseEntry(llvm::StringRef ModuleName) {
diff --git a/clang-tools-extra/clangd/ParsedAST.cpp b/clang-tools-extra/clangd/ParsedAST.cpp
index 3f63daaf400db..2874b2c245bbd 100644
--- a/clang-tools-extra/clangd/ParsedAST.cpp
+++ b/clang-tools-extra/clangd/ParsedAST.cpp
@@ -196,8 +196,9 @@ class ReplayPreamble : private PPCallbacks {
void replay() {
for (const auto &Inc : Includes) {
OptionalFileEntryRef File;
- if (Inc.Resolved != "")
- File = expectedToOptional(SM.getFileManager().getFileRef(Inc.Resolved));
+ if (!Inc.Resolved.empty())
+ File = expectedToOptional(
+ SM.getFileManager().getFileRef(Inc.Resolved.ref().raw()));
// Re-lex the #include directive to find its interesting parts.
auto HashLoc = SM.getComposedLoc(SM.getMainFileID(), Inc.HashOffset);
diff --git a/clang-tools-extra/clangd/Preamble.cpp b/clang-tools-extra/clangd/Preamble.cpp
index 6fab3e2191426..1e2fcccf78c71 100644
--- a/clang-tools-extra/clangd/Preamble.cpp
+++ b/clang-tools-extra/clangd/Preamble.cpp
@@ -595,11 +595,11 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
// Note that we don't need to copy the input contents, preamble can live
// without those.
auto ContentsBuffer =
- llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
+ llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName.raw());
auto Bounds = ComputePreambleBounds(CI.getLangOpts(), *ContentsBuffer, 0);
trace::Span Tracer("BuildPreamble");
- SPAN_ATTACH(Tracer, "File", FileName);
+ SPAN_ATTACH(Tracer, "File", FileName.raw());
std::vector<std::unique_ptr<FeatureModule::ASTListener>> ASTListeners;
if (Inputs.FeatureModules) {
for (auto &M : *Inputs.FeatureModules) {
@@ -650,7 +650,7 @@ buildPreamble(PathRef FileName, CompilerInvocation CI,
for (const auto &L : ASTListeners)
L->beforeExecute(CI);
});
- llvm::SmallString<32> AbsFileName(FileName);
+ llvm::SmallString<32> AbsFileName(FileName.raw());
VFS->makeAbsolute(AbsFileName);
auto StatCache = std::make_shared<PreambleFileStatusCache>(AbsFileName);
auto StatCacheFS = StatCache->getProducingFS(VFS);
@@ -743,7 +743,7 @@ bool isPreambleCompatible(const PreambleData &Preamble,
const ParseInputs &Inputs, PathRef FileName,
const CompilerInvocation &CI) {
auto ContentsBuffer =
- llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName);
+ llvm::MemoryBuffer::getMemBuffer(Inputs.Contents, FileName.raw());
auto Bounds = ComputePreambleBounds(CI.getLangOpts(), *ContentsBuffer, 0);
auto VFS = Inputs.TFS->view(Inputs.CompileCommand.Directory);
return compileCommandsAreEqual(Inputs.CompileCommand,
diff --git a/clang-tools-extra/clangd/Protocol.cpp b/clang-tools-extra/clangd/Protocol.cpp
index 05c8041df7de7..dc220daba1c82 100644
--- a/clang-tools-extra/clangd/Protocol.cpp
+++ b/clang-tools-extra/clangd/Protocol.cpp
@@ -13,6 +13,7 @@
#include "Protocol.h"
#include "URI.h"
#include "support/Logger.h"
+#include "support/Path.h"
#include "clang/Basic/LLVM.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/StringExtras.h"
@@ -43,15 +44,14 @@ bool mapOptOrNull(const llvm::json::Value &Params, llvm::StringLiteral Prop,
char LSPError::ID;
-URIForFile URIForFile::canonicalize(llvm::StringRef AbsPath,
- llvm::StringRef TUPath) {
- assert(llvm::sys::path::is_absolute(AbsPath) && "the path is relative");
- auto Resolved = URI::resolvePath(AbsPath, TUPath);
+URIForFile URIForFile::canonicalize(PathRef AbsPath, PathRef TUPath) {
+ assert(AbsPath.isAbsolute() && "the path is relative");
+ auto Resolved = URI::resolvePath(AbsPath.raw(), TUPath.raw());
if (!Resolved) {
elog("URIForFile: failed to resolve path {0} with TU path {1}: "
"{2}.\nUsing unresolved path.",
AbsPath, TUPath, Resolved.takeError());
- return URIForFile(std::string(AbsPath));
+ return URIForFile(AbsPath.owned().raw());
}
return URIForFile(std::move(*Resolved));
}
diff --git a/clang-tools-extra/clangd/Protocol.h b/clang-tools-extra/clangd/Protocol.h
index c7ef1a13e6e39..e89880527ca1c 100644
--- a/clang-tools-extra/clangd/Protocol.h
+++ b/clang-tools-extra/clangd/Protocol.h
@@ -26,6 +26,7 @@
#include "URI.h"
#include "index/SymbolID.h"
#include "support/MemoryTree.h"
+#include "support/Path.h"
#include "clang/Index/IndexSymbol.h"
#include "llvm/ADT/SmallVector.h"
#include "llvm/Support/JSON.h"
@@ -94,8 +95,7 @@ struct URIForFile {
/// Files can be referred to by several paths (e.g. in the presence of links).
/// Which one we prefer may depend on where we're coming from. \p TUPath is a
/// hint, and should usually be the main entrypoint file we're processing.
- static URIForFile canonicalize(llvm::StringRef AbsPath,
- llvm::StringRef TUPath);
+ static URIForFile canonicalize(PathRef AbsPath, PathRef TUPath);
static llvm::Expected<URIForFile> fromURI(const URI &U,
llvm::StringRef HintPath);
diff --git a/clang-tools-extra/clangd/ScanningProjectModules.cpp b/clang-tools-extra/clangd/ScanningProjectModules.cpp
index e561513fe687f..b509d7cee838d 100644
--- a/clang-tools-extra/clangd/ScanningProjectModules.cpp
+++ b/clang-tools-extra/clangd/ScanningProjectModules.cpp
@@ -92,7 +92,7 @@ class ModuleDependencyScanner {
std::optional<ModuleDependencyScanner::ModuleDependencyInfo>
ModuleDependencyScanner::scan(PathRef FilePath,
const ProjectModules::CommandMangler &Mangler) {
- auto Candidates = CDB->getCompileCommands(FilePath);
+ auto Candidates = CDB->getCompileCommands(FilePath.raw());
if (Candidates.empty())
return std::nullopt;
@@ -106,7 +106,7 @@ ModuleDependencyScanner::scan(PathRef FilePath,
using namespace clang::tooling::dependencies;
- llvm::SmallString<128> FilePathDir(FilePath);
+ llvm::SmallString<128> FilePathDir(FilePath.raw());
llvm::sys::path::remove_filename(FilePathDir);
DependencyScanningTool ScanningTool(Service, TFS.view(FilePathDir));
@@ -122,7 +122,7 @@ ModuleDependencyScanner::scan(PathRef FilePath,
ModuleDependencyInfo Result;
if (ScanningResult->Provides) {
- ModuleNameToSource[ScanningResult->Provides->ModuleName] = FilePath;
+ ModuleNameToSource[ScanningResult->Provides->ModuleName] = FilePath.raw();
Result.ModuleName = ScanningResult->Provides->ModuleName;
}
@@ -195,7 +195,7 @@ class ScanningAllProjectModules : public ProjectModules {
std::string getSourceForModuleName(llvm::StringRef ModuleName,
PathRef RequiredSourceFile) override {
Scanner.globalScan(Mangler);
- return Scanner.getSourceForModuleName(ModuleName).str();
+ return Scanner.getSourceForModuleName(ModuleName).owned().raw();
}
std::string getModuleNameForSource(PathRef File) override {
diff --git a/clang-tools-extra/clangd/TUScheduler.cpp b/clang-tools-extra/clangd/TUScheduler.cpp
index 035e5e63d8fbb..c7e76d9d70e96 100644
--- a/clang-tools-extra/clangd/TUScheduler.cpp
+++ b/clang-tools-extra/clangd/TUScheduler.cpp
@@ -310,7 +310,7 @@ class TUScheduler::HeaderIncluderCache {
// Headers not in the list will have their associations removed.
void update(PathRef MainFile, llvm::ArrayRef<std::string> Headers) {
std::lock_guard<std::mutex> Lock(Mu);
- auto It = MainToFirst.try_emplace(MainFile, nullptr);
+ auto It = MainToFirst.try_emplace(MainFile.raw(), nullptr);
Association *&First = It.first->second;
if (First)
invalidate(First);
@@ -323,7 +323,7 @@ class TUScheduler::HeaderIncluderCache {
// will be eligible for association with other files that get update()d.
void remove(PathRef MainFile) {
std::lock_guard<std::mutex> Lock(Mu);
- Association *&First = MainToFirst[MainFile];
+ Association *&First = MainToFirst[MainFile.raw()];
if (First) {
invalidate(First);
First = nullptr;
@@ -335,7 +335,7 @@ class TUScheduler::HeaderIncluderCache {
/// Get the mainfile associated with Header, or the empty string if none.
std::string get(PathRef Header) const {
std::lock_guard<std::mutex> Lock(Mu);
- return HeaderToMain.lookup(Header).MainFile.str();
+ return HeaderToMain.lookup(Header.raw()).MainFile.str();
}
size_t getUsedBytes() const {
@@ -483,7 +483,7 @@ class PreambleThread {
break;
{
- Throttle.emplace(FileName, Throttler, ReqCV);
+ Throttle.emplace(FileName.raw(), Throttler, ReqCV);
std::optional<trace::Span> Tracer;
// If acquire succeeded synchronously, avoid status jitter.
if (!Throttle->satisfied()) {
@@ -822,9 +822,9 @@ ASTWorker::create(PathRef FileName, const GlobalCompilationDatabase &CDB,
new ASTWorker(FileName, CDB, IdleASTs, HeaderIncluders, Barrier,
/*RunSync=*/!Tasks, Opts, Callbacks));
if (Tasks) {
- Tasks->runAsync("ASTWorker:" + llvm::sys::path::filename(FileName),
+ Tasks->runAsync("ASTWorker:" + FileName.filename(),
[Worker]() { Worker->run(); });
- Tasks->runAsync("PreambleWorker:" + llvm::sys::path::filename(FileName),
+ Tasks->runAsync("PreambleWorker:" + FileName.filename(),
[Worker]() { Worker->PreamblePeer.run(); });
}
@@ -841,8 +841,9 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
UpdateDebounce(Opts.UpdateDebounce), FileName(FileName),
ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks),
Barrier(Barrier), Done(false), Status(FileName, Callbacks),
- PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync,
- Opts.PreambleThrottler, Status, HeaderIncluders, *this) {
+ PreamblePeer(FileName.raw(), Callbacks, Opts.StorePreamblesInMemory,
+ RunSync, Opts.PreambleThrottler, Status, HeaderIncluders,
+ *this) {
// Set a fallback command because compile command can be accessed before
// `Inputs` is initialized. Other fields are only used after initialization
// from client inputs.
@@ -881,7 +882,8 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
HeaderIncluders.remove(ProxyFile);
} else {
// We have a reliable command for an including file, use it.
- Cmd = tooling::transferCompileCommand(std::move(*ProxyCmd), FileName);
+ Cmd = tooling::transferCompileCommand(std::move(*ProxyCmd),
+ FileName.raw());
}
}
}
@@ -995,9 +997,9 @@ void ASTWorker::runWithAST(
// return a compatible preamble as ASTWorker::update blocks.
std::optional<ParsedAST> NewAST;
if (Invocation) {
- NewAST = ParsedAST::build(FileName, FileInputs, std::move(Invocation),
- CompilerInvocationDiagConsumer.take(),
- getPossiblyStalePreamble());
+ NewAST = ParsedAST::build(
+ FileName.raw(), FileInputs, std::move(Invocation),
+ CompilerInvocationDiagConsumer.take(), getPossiblyStalePreamble());
++ASTBuildCount;
}
AST = NewAST ? std::make_unique<ParsedAST>(std::move(*NewAST)) : nullptr;
@@ -1211,8 +1213,9 @@ void ASTWorker::generateDiagnostics(
IdleASTs.take(this, &ASTAccessForDiag);
if (!AST || !InputsAreLatest) {
auto RebuildStartTime = DebouncePolicy::clock::now();
- std::optional<ParsedAST> NewAST = ParsedAST::build(
- FileName, Inputs, std::move(Invocation), CIDiags, *LatestPreamble);
+ std::optional<ParsedAST> NewAST =
+ ParsedAST::build(FileName.raw(), Inputs, std::move(Invocation), CIDiags,
+ *LatestPreamble);
auto RebuildDuration = DebouncePolicy::clock::now() - RebuildStartTime;
++ASTBuildCount;
// Try to record the AST-build time, to inform future update debouncing.
@@ -1324,7 +1327,7 @@ void ASTWorker::runTask(llvm::StringRef Name, llvm::function_ref<void()> Task) {
crashDumpParseInputs(llvm::errs(), FileInputs);
});
trace::Span Tracer(Name);
- WithContext WithProvidedContext(ContextProvider(FileName));
+ WithContext WithProvidedContext(ContextProvider(FileName.raw()));
Task();
}
@@ -1352,7 +1355,7 @@ void ASTWorker::startTask(llvm::StringRef Name,
}
// Allow this request to be cancelled if invalidated.
- Context Ctx = Context::current().derive(FileBeingProcessed, FileName);
+ Context Ctx = Context::current().derive(FileBeingProcessed, FileName.raw());
Canceler Invalidate = nullptr;
if (Invalidation) {
WithContext WC(std::move(Ctx));
@@ -1640,7 +1643,7 @@ TUScheduler::TUScheduler(const GlobalCompilationDatabase &CDB,
HeaderIncluders(std::make_unique<HeaderIncluderCache>()) {
// Avoid null checks everywhere.
if (!Opts.ContextProvider) {
- this->Opts.ContextProvider = [](llvm::StringRef) {
+ this->Opts.ContextProvider = [](PathRef) {
return Context::current().clone();
};
}
@@ -1673,7 +1676,7 @@ bool TUScheduler::blockUntilIdle(Deadline D) const {
bool TUScheduler::update(PathRef File, ParseInputs Inputs,
WantDiagnostics WantDiags) {
- std::unique_ptr<FileData> &FD = Files[File];
+ std::unique_ptr<FileData> &FD = Files[File.raw()];
bool NewFile = FD == nullptr;
bool ContentChanged = false;
if (!FD) {
@@ -1692,12 +1695,12 @@ bool TUScheduler::update(PathRef File, ParseInputs Inputs,
// There might be synthetic update requests, don't change the LastActiveFile
// in such cases.
if (ContentChanged)
- LastActiveFile = File.str();
+ LastActiveFile = File.owned().raw();
return NewFile;
}
void TUScheduler::remove(PathRef File) {
- bool Removed = Files.erase(File);
+ bool Removed = Files.erase(File.raw());
if (!Removed)
elog("Trying to remove file from TUScheduler that is not tracked: {0}",
File);
@@ -1744,13 +1747,13 @@ void TUScheduler::runWithAST(
llvm::StringRef Name, PathRef File,
llvm::unique_function<void(llvm::Expected<InputsAndAST>)> Action,
TUScheduler::ASTActionInvalidation Invalidation) {
- auto It = Files.find(File);
+ auto It = Files.find(File.raw());
if (It == Files.end()) {
Action(llvm::make_error<LSPError>(
"trying to get AST for non-added document", ErrorCode::InvalidParams));
return;
}
- LastActiveFile = File.str();
+ LastActiveFile = File.owned().raw();
It->second->Worker->runWithAST(Name, std::move(Action), Invalidation);
}
@@ -1758,18 +1761,18 @@ void TUScheduler::runWithAST(
void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File,
PreambleConsistency Consistency,
Callback<InputsAndPreamble> Action) {
- auto It = Files.find(File);
+ auto It = Files.find(File.raw());
if (It == Files.end()) {
Action(llvm::make_error<LSPError>(
"trying to get preamble for non-added document",
ErrorCode::InvalidParams));
return;
}
- LastActiveFile = File.str();
+ LastActiveFile = File.owned().raw();
if (!PreambleTasks) {
trace::Span Tracer(Name);
- SPAN_ATTACH(Tracer, "file", File);
+ SPAN_ATTACH(Tracer, "file", File.raw());
std::shared_ptr<const ASTSignals> Signals;
std::shared_ptr<const PreambleData> Preamble =
It->second->Worker->getPossiblyStalePreamble(&Signals);
@@ -1781,11 +1784,11 @@ void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File,
}
std::shared_ptr<const ASTWorker> Worker = It->second->Worker.lock();
- auto Task = [Worker, Consistency, Name = Name.str(), File = File.str(),
+ auto Task = [Worker, Consistency, Name = Name.str(), File = File.owned(),
Contents = It->second->Contents,
Command = Worker->getCurrentCompileCommand(),
Ctx = Context::current().derive(FileBeingProcessed,
- std::string(File)),
+ File.owned().raw()),
Action = std::move(Action), this]() mutable {
clang::noteBottomOfStack();
ThreadCrashReporter ScopedReporter([&Name, &Contents, &Command]() {
@@ -1811,8 +1814,7 @@ void TUScheduler::runWithPreamble(llvm::StringRef Name, PathRef File,
Action(InputsAndPreamble{Contents, Command, Preamble.get(), Signals.get()});
};
- PreambleTasks->runAsync("task:" + llvm::sys::path::filename(File),
- std::move(Task));
+ PreambleTasks->runAsync("task:" + File.filename(), std::move(Task));
}
llvm::StringMap<TUScheduler::FileStats> TUScheduler::fileStats() const {
diff --git a/clang-tools-extra/clangd/TidyProvider.cpp b/clang-tools-extra/clangd/TidyProvider.cpp
index 1d79a7a7399ec..d2be8fa03b057 100644
--- a/clang-tools-extra/clangd/TidyProvider.cpp
+++ b/clang-tools-extra/clangd/TidyProvider.cpp
@@ -64,7 +64,7 @@ class DotClangTidyCache : private FileCache {
}
};
if (auto Parsed = tidy::parseConfigurationWithDiags(
- llvm::MemoryBufferRef(*Data, path()), Diagnostics))
+ llvm::MemoryBufferRef(*Data, path().raw()), Diagnostics))
Value = std::make_shared<const tidy::ClangTidyOptions>(
std::move(*Parsed));
else
@@ -99,21 +99,21 @@ class DotClangTidyTree {
void apply(tidy::ClangTidyOptions &Result, PathRef AbsPath) {
namespace path = llvm::sys::path;
- assert(path::is_absolute(AbsPath));
+ assert(AbsPath.isAbsolute());
// Compute absolute paths to all ancestors (substrings of P.Path).
// Ensure cache entries for each ancestor exist in the map.
llvm::SmallVector<DotClangTidyCache *> Caches;
{
std::lock_guard<std::mutex> Lock(Mu);
- for (auto Ancestor = absoluteParent(AbsPath); !Ancestor.empty();
- Ancestor = absoluteParent(Ancestor)) {
- auto It = Cache.find(Ancestor);
+ for (auto Ancestor = AbsPath.absoluteParent(); !Ancestor.empty();
+ Ancestor = Ancestor.absoluteParent()) {
+ auto It = Cache.find(Ancestor.raw());
// Assemble the actual config file path only if needed.
if (It == Cache.end()) {
- llvm::SmallString<256> ConfigPath = Ancestor;
+ llvm::SmallString<256> ConfigPath = Ancestor.raw();
path::append(ConfigPath, RelPath);
- It = Cache.try_emplace(Ancestor, ConfigPath.str()).first;
+ It = Cache.try_emplace(Ancestor.raw(), ConfigPath.str()).first;
}
Caches.push_back(&It->second);
}
diff --git a/clang-tools-extra/clangd/XRefs.cpp b/clang-tools-extra/clangd/XRefs.cpp
index 8b9fffa3f64cd..af63e15bcea14 100644
--- a/clang-tools-extra/clangd/XRefs.cpp
+++ b/clang-tools-extra/clangd/XRefs.cpp
@@ -226,7 +226,7 @@ std::optional<LocatedSymbol> locateFileReferent(const Position &Pos,
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.Name = Inc.Resolved.ref().filename().str();
File.PreferredDeclaration = {
URIForFile::canonicalize(Inc.Resolved, MainFilePath), Range{}};
File.Definition = File.PreferredDeclaration;
@@ -514,7 +514,7 @@ std::vector<LocatedSymbol> locateSymbolForType(const ParsedAST &AST,
const QualType &Type,
const SymbolIndex *Index) {
const auto &SM = AST.getSourceManager();
- auto MainFilePath = AST.tuPath();
+ auto MainFilePath = AST.tuPath().raw();
// FIXME: this sends unique_ptr<Foo> to unique_ptr<T>.
// Likely it would be better to send it to Foo (heuristically) or to both.
@@ -776,7 +776,7 @@ const syntax::Token *findNearbyIdentifier(const SpelledWord &Word,
std::vector<LocatedSymbol> locateSymbolAt(ParsedAST &AST, Position Pos,
const SymbolIndex *Index) {
const auto &SM = AST.getSourceManager();
- auto MainFilePath = AST.tuPath();
+ auto MainFilePath = AST.tuPath().raw();
if (auto File = locateFileReferent(Pos, AST, MainFilePath))
return {std::move(*File)};
@@ -1320,7 +1320,7 @@ std::vector<LocatedSymbol> findImplementations(ParsedAST &AST, Position Pos,
QueryKind = RelationKind::BaseOf;
}
}
- return findImplementors(std::move(IDs), QueryKind, Index, AST.tuPath());
+ return findImplementors(std::move(IDs), QueryKind, Index, AST.tuPath().raw());
}
namespace {
@@ -1538,8 +1538,9 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
return;
}
const auto LSPLocDecl =
- toLSPLocation(Object.CanonicalDeclaration, MainFilePath);
- const auto LSPLocDef = toLSPLocation(Object.Definition, MainFilePath);
+ toLSPLocation(Object.CanonicalDeclaration, MainFilePath.raw());
+ const auto LSPLocDef =
+ toLSPLocation(Object.Definition, MainFilePath.raw());
if (LSPLocDecl && LSPLocDecl != LSPLocDef) {
ReferencesResult::Reference Result;
Result.Loc = {std::move(*LSPLocDecl), std::nullopt};
@@ -1590,7 +1591,7 @@ ReferencesResult findReferences(ParsedAST &AST, Position Pos, uint32_t Limit,
LookupRequest ContainerLookup;
llvm::DenseMap<SymbolID, std::vector<size_t>> RefIndicesForContainer;
Results.HasMore |= Index->refs(Req, [&](const Ref &R) {
- auto LSPLoc = toLSPLocation(R.Location, MainFilePath);
+ auto LSPLoc = toLSPLocation(R.Location, MainFilePath.raw());
// Avoid indexed results for the main file - the AST is authoritative.
if (!LSPLoc ||
(!AllowMainFileSymbols && LSPLoc->uri.file() == MainFilePath))
@@ -1668,9 +1669,9 @@ std::vector<SymbolDetails> getSymbolInfo(ParsedAST &AST, Position Pos) {
}
if (const NamedDecl *Def = getDefinition(D))
NewSymbol.definitionRange = makeLocation(
- AST.getASTContext(), nameLocation(*Def, SM), MainFilePath);
- NewSymbol.declarationRange =
- makeLocation(AST.getASTContext(), nameLocation(*D, SM), MainFilePath);
+ AST.getASTContext(), nameLocation(*Def, SM), MainFilePath.raw());
+ NewSymbol.declarationRange = makeLocation(
+ AST.getASTContext(), nameLocation(*D, SM), MainFilePath.raw());
Results.push_back(std::move(NewSymbol));
}
@@ -1789,7 +1790,7 @@ declToCallHierarchyItem(const NamedDecl &ND, llvm::StringRef TUPath) {
template <typename HierarchyItem>
static std::optional<HierarchyItem> symbolToHierarchyItem(const Symbol &S,
PathRef TUPath) {
- auto Loc = symbolToLocation(S, TUPath);
+ auto Loc = symbolToLocation(S, TUPath.raw());
if (!Loc) {
elog("Failed to convert symbol to hierarchy item: {0}", Loc.takeError());
return std::nullopt;
@@ -2204,12 +2205,12 @@ getTypeHierarchy(ParsedAST &AST, Position Pos, int ResolveLevels,
}
std::optional<TypeHierarchyItem> Result =
- declToTypeHierarchyItem(*CXXRD, AST.tuPath());
+ declToTypeHierarchyItem(*CXXRD, AST.tuPath().raw());
if (!Result)
continue;
RecursionProtectionSet RPSet;
- fillSuperTypes(*CXXRD, AST.tuPath(), *Result, RPSet);
+ fillSuperTypes(*CXXRD, AST.tuPath().raw(), *Result, RPSet);
if (WantChildren && ResolveLevels > 0) {
Result->children.emplace();
@@ -2289,7 +2290,7 @@ prepareCallHierarchy(ParsedAST &AST, Position Pos, PathRef TUPath) {
!cast<VarDecl>(Decl)->isLocalVarDecl()) &&
Decl->getKind() != Decl::Kind::Field)
continue;
- if (auto CHI = declToCallHierarchyItem(*Decl, AST.tuPath()))
+ if (auto CHI = declToCallHierarchyItem(*Decl, AST.tuPath().raw()))
Result.emplace_back(std::move(*CHI));
}
return Result;
diff --git a/clang-tools-extra/clangd/index/Background.cpp b/clang-tools-extra/clangd/index/Background.cpp
index 496d1455def4b..fad6e3cbe3e46 100644
--- a/clang-tools-extra/clangd/index/Background.cpp
+++ b/clang-tools-extra/clangd/index/Background.cpp
@@ -78,7 +78,7 @@ llvm::SmallString<128> getAbsolutePath(const tooling::CompileCommand &Cmd) {
}
bool shardIsStale(const LoadedShard &LS, llvm::vfs::FileSystem *FS) {
- auto Buf = FS->getBufferForFile(LS.AbsolutePath);
+ auto Buf = FS->getBufferForFile(LS.AbsolutePath.raw());
if (!Buf) {
vlog("Background-index: Couldn't read {0} to validate stored index: {1}",
LS.AbsolutePath, Buf.getError().message());
@@ -224,14 +224,14 @@ void BackgroundIndex::update(
// We need to store shards before updating the index, since the latter
// consumes slabs.
// FIXME: Also skip serializing the shard if it is already up-to-date.
- if (auto Error = IndexStorageFactory(Path)->storeShard(Path, *IF))
+ if (auto Error = IndexStorageFactory(Path)->storeShard(Path.raw(), *IF))
elog("Failed to write background-index shard for file {0}: {1}", Path,
std::move(Error));
{
std::lock_guard<std::mutex> Lock(ShardVersionsMu);
const auto &Hash = FileIt.getValue().second;
- auto DigestIt = ShardVersions.try_emplace(Path);
+ auto DigestIt = ShardVersions.try_emplace(Path.raw());
ShardVersion &SV = DigestIt.first->second;
// Skip if file is already up to date, unless previous index was broken
// and this one is not.
@@ -386,12 +386,12 @@ BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
LS.Shard->Relations
? std::make_unique<RelationSlab>(std::move(*LS.Shard->Relations))
: nullptr;
- ShardVersion &SV = ShardVersions[LS.AbsolutePath];
+ ShardVersion &SV = ShardVersions[LS.AbsolutePath.raw()];
SV.Digest = LS.Digest;
SV.HadErrors = LS.HadErrors;
++LoadedShards;
- IndexedSymbols.update(URI::create(LS.AbsolutePath).toString(),
+ IndexedSymbols.update(URI::create(LS.AbsolutePath.raw()).toString(),
std::move(SS), std::move(RS), std::move(RelS),
LS.CountReferences);
}
@@ -417,7 +417,9 @@ BackgroundIndex::loadProject(std::vector<std::string> MainFiles) {
TUsToIndex.insert(TUForFile);
}
- return {TUsToIndex.begin(), TUsToIndex.end()};
+ auto ToRaw = [](PathRef R) { return R.raw(); };
+ return {llvm::map_iterator(TUsToIndex.begin(), ToRaw),
+ llvm::map_iterator(TUsToIndex.end(), ToRaw)};
}
void BackgroundIndex::profile(MemoryTree &MT) const {
diff --git a/clang-tools-extra/clangd/index/Background.h b/clang-tools-extra/clangd/index/Background.h
index 448e911201575..1babc3f85edbb 100644
--- a/clang-tools-extra/clangd/index/Background.h
+++ b/clang-tools-extra/clangd/index/Background.h
@@ -211,6 +211,7 @@ class BackgroundIndex : public SwapIndex {
std::mutex ShardVersionsMu;
BackgroundIndexStorage::Factory IndexStorageFactory;
+ // XXX: `MainFiles` should be a vector of `Path`s
// Tries to load shards for the MainFiles and their dependencies.
std::vector<std::string> loadProject(std::vector<std::string> MainFiles);
diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp
index c09a5c3a3aeb8..4abe594e50e6f 100644
--- a/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp
+++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.cpp
@@ -48,17 +48,17 @@ class BackgroundIndexLoader {
std::pair<const LoadedShard &, std::vector<Path>>
BackgroundIndexLoader::loadShard(PathRef StartSourceFile, PathRef DependentTU) {
- auto It = LoadedShards.try_emplace(StartSourceFile);
+ auto It = LoadedShards.try_emplace(StartSourceFile.raw());
LoadedShard &LS = It.first->getValue();
std::vector<Path> Edges = {};
// Return the cached shard.
if (!It.second)
return {LS, Edges};
- LS.AbsolutePath = StartSourceFile.str();
- LS.DependentTU = std::string(DependentTU);
+ LS.AbsolutePath = StartSourceFile.owned();
+ LS.DependentTU = DependentTU.owned();
BackgroundIndexStorage *Storage = IndexStorageFactory(LS.AbsolutePath);
- auto Shard = Storage->loadShard(StartSourceFile);
+ auto Shard = Storage->loadShard(StartSourceFile.raw());
if (!Shard || !Shard->Sources) {
vlog("Failed to load shard: {0}", StartSourceFile);
return {LS, Edges};
@@ -66,7 +66,7 @@ BackgroundIndexLoader::loadShard(PathRef StartSourceFile, PathRef DependentTU) {
LS.Shard = std::move(Shard);
for (const auto &It : *LS.Shard->Sources) {
- auto AbsPath = URI::resolve(It.getKey(), StartSourceFile);
+ auto AbsPath = URI::resolve(It.getKey(), StartSourceFile.raw());
if (!AbsPath) {
elog("Failed to resolve URI: {0}", AbsPath.takeError());
continue;
@@ -91,7 +91,7 @@ void BackgroundIndexLoader::load(PathRef MainFile) {
llvm::StringSet<> InQueue;
// Following containers points to strings inside InQueue.
std::queue<PathRef> ToVisit;
- InQueue.insert(MainFile);
+ InQueue.insert(MainFile.raw());
ToVisit.push(MainFile);
while (!ToVisit.empty()) {
@@ -100,7 +100,7 @@ void BackgroundIndexLoader::load(PathRef MainFile) {
auto ShardAndEdges = loadShard(SourceFile, MainFile);
for (PathRef Edge : ShardAndEdges.second) {
- auto It = InQueue.insert(Edge);
+ auto It = InQueue.insert(Edge.raw());
if (It.second)
ToVisit.push(It.first->getKey());
}
@@ -117,7 +117,7 @@ std::vector<LoadedShard> BackgroundIndexLoader::takeResult() && {
} // namespace
std::vector<LoadedShard>
-loadIndexShards(llvm::ArrayRef<Path> MainFiles,
+loadIndexShards(llvm::ArrayRef<std::string> MainFiles,
BackgroundIndexStorage::Factory &IndexStorageFactory,
const GlobalCompilationDatabase &CDB) {
BackgroundIndexLoader Loader(IndexStorageFactory);
diff --git a/clang-tools-extra/clangd/index/BackgroundIndexLoader.h b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h
index 81033646b6a4e..bee5ce6c6974b 100644
--- a/clang-tools-extra/clangd/index/BackgroundIndexLoader.h
+++ b/clang-tools-extra/clangd/index/BackgroundIndexLoader.h
@@ -39,7 +39,7 @@ struct LoadedShard {
/// Loads all shards for the TU \p MainFile from \p Storage.
std::vector<LoadedShard>
-loadIndexShards(llvm::ArrayRef<Path> MainFiles,
+loadIndexShards(llvm::ArrayRef<std::string> MainFiles,
BackgroundIndexStorage::Factory &IndexStorageFactory,
const GlobalCompilationDatabase &CDB);
diff --git a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
index d887b09482a95..5c077c4ed9471 100644
--- a/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
+++ b/clang-tools-extra/clangd/index/BackgroundIndexStorage.cpp
@@ -109,7 +109,7 @@ class DiskBackedIndexStorageManager {
// Creates or fetches to storage from cache for the specified project.
BackgroundIndexStorage *operator()(PathRef File) {
std::lock_guard<std::mutex> Lock(*IndexStorageMapMu);
- llvm::SmallString<128> StorageDir(FallbackDir);
+ llvm::SmallString<128> StorageDir(FallbackDir.raw());
if (auto PI = GetProjectInfo(File)) {
StorageDir = PI->SourceRoot;
llvm::sys::path::append(StorageDir, ".cache", "clangd", "index");
@@ -126,7 +126,7 @@ class DiskBackedIndexStorageManager {
elog("Tried to create storage for empty directory!");
return std::make_unique<NullStorage>();
}
- return std::make_unique<DiskBackedIndexStorage>(CDBDirectory);
+ return std::make_unique<DiskBackedIndexStorage>(CDBDirectory.raw());
}
Path FallbackDir;
diff --git a/clang-tools-extra/clangd/index/FileIndex.cpp b/clang-tools-extra/clangd/index/FileIndex.cpp
index aa573e312a756..7714fdbdebe65 100644
--- a/clang-tools-extra/clangd/index/FileIndex.cpp
+++ b/clang-tools-extra/clangd/index/FileIndex.cpp
@@ -182,7 +182,7 @@ FileShardedIndex::FileShardedIndex(IndexFileIn Input)
std::vector<llvm::StringRef> FileShardedIndex::getAllSources() const {
// It should be enough to construct a vector with {Shards.keys().begin(),
// Shards.keys().end()} but MSVC fails to compile that.
- std::vector<PathRef> Result;
+ std::vector<llvm::StringRef> Result;
Result.reserve(Shards.size());
for (auto Key : Shards.keys())
Result.push_back(Key);
@@ -470,7 +470,7 @@ void FileIndex::updatePreamble(PathRef Path, llvm::StringRef Version,
void FileIndex::updateMain(PathRef Path, ParsedAST &AST) {
auto Contents = indexMainDecls(AST);
MainFileSymbols.update(
- URI::create(Path).toString(),
+ URI::create(Path.raw()).toString(),
std::make_unique<SymbolSlab>(std::move(std::get<0>(Contents))),
std::make_unique<RefSlab>(std::move(std::get<1>(Contents))),
std::make_unique<RelationSlab>(std::move(std::get<2>(Contents))),
diff --git a/clang-tools-extra/clangd/refactor/Rename.cpp b/clang-tools-extra/clangd/refactor/Rename.cpp
index 26059167208aa..436b6be40dbf6 100644
--- a/clang-tools-extra/clangd/refactor/Rename.cpp
+++ b/clang-tools-extra/clangd/refactor/Rename.cpp
@@ -784,7 +784,8 @@ renameObjCMethodWithinFile(ParsedAST &AST, const ObjCMethodDecl *MD,
auto FilePath = AST.tuPath();
auto RenameRanges = collectRenameIdentifierRanges(
RenameSymbolName(MD->getDeclName()), Code, LangOpts);
- auto RenameEdit = buildRenameEdit(FilePath, Code, RenameRanges, NewNames);
+ auto RenameEdit =
+ buildRenameEdit(FilePath.raw(), Code, RenameRanges, NewNames);
if (!RenameEdit)
return error("failed to rename in file {0}: {1}", FilePath,
RenameEdit.takeError());
@@ -891,7 +892,7 @@ findOccurrencesOutsideFile(const NamedDecl &RenameDecl,
if ((R.Kind & RefKind::Spelled) == RefKind::Unknown)
return;
if (auto RefFilePath = filePath(R.Location, /*HintFilePath=*/MainFile)) {
- if (!pathEqual(*RefFilePath, MainFile))
+ if (PathRef(*RefFilePath) != MainFile)
AffectedFiles[*RefFilePath].push_back(toRange(R.Location));
}
});
diff --git a/clang-tools-extra/clangd/refactor/Tweak.cpp b/clang-tools-extra/clangd/refactor/Tweak.cpp
index 840843d1bfc4b..683b8c5710448 100644
--- a/clang-tools-extra/clangd/refactor/Tweak.cpp
+++ b/clang-tools-extra/clangd/refactor/Tweak.cpp
@@ -100,7 +100,7 @@ prepareTweak(StringRef ID, const Tweak::Selection &S,
return error("tweak ID {0} is invalid", ID);
}
-llvm::Expected<std::pair<Path, Edit>>
+llvm::Expected<std::pair<std::string, Edit>>
Tweak::Effect::fileEdit(const SourceManager &SM, FileID FID,
tooling::Replacements Replacements) {
Edit Ed(SM.getBufferData(FID), std::move(Replacements));
diff --git a/clang-tools-extra/clangd/refactor/Tweak.h b/clang-tools-extra/clangd/refactor/Tweak.h
index 257f44a285f88..4e8269138eda9 100644
--- a/clang-tools-extra/clangd/refactor/Tweak.h
+++ b/clang-tools-extra/clangd/refactor/Tweak.h
@@ -85,10 +85,11 @@ class Tweak {
return E;
}
+ /// XXX: This should return Path instead of std::string
/// Path is the absolute, symlink-resolved path for the file pointed by FID
/// in SM. Edit is generated from Replacements.
/// Fails if cannot figure out absolute path for FID.
- static llvm::Expected<std::pair<Path, Edit>>
+ static llvm::Expected<std::pair<std::string, Edit>>
fileEdit(const SourceManager &SM, FileID FID,
tooling::Replacements Replacements);
diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
index d6556bba14725..52e8c9315de73 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/DefineInline.cpp
@@ -474,7 +474,7 @@ class DefineInline : public Tweak {
const tooling::Replacement DeleteFuncBody(SM, DefRange->getBegin(),
SourceLen, "");
- llvm::SmallVector<std::pair<std::string, Edit>> Edits;
+ llvm::SmallVector<std::pair<Path, Edit>> Edits;
// Edit for Target.
auto FE = Effect::fileEdit(SM, SM.getFileID(*Semicolon),
std::move(TargetFileReplacements));
@@ -499,7 +499,8 @@ class DefineInline : public Tweak {
Effect E;
for (auto &Pair : Edits)
- E.ApplyEdits.try_emplace(std::move(Pair.first), std::move(Pair.second));
+ E.ApplyEdits.try_emplace(std::move(Pair.first).raw(),
+ std::move(Pair.second));
return E;
}
diff --git a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
index e4eef228b6b99..6e87cc3ecfab1 100644
--- a/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
+++ b/clang-tools-extra/clangd/refactor/tweaks/DefineOutline.cpp
@@ -428,7 +428,7 @@ class DefineOutline : public Tweak {
}
bool prepare(const Selection &Sel) override {
- SameFile = !isHeaderFile(Sel.AST->tuPath(), Sel.AST->getLangOpts());
+ SameFile = !isHeaderFile(Sel.AST->tuPath().raw(), Sel.AST->getLangOpts());
Source = getSelectedFunction(Sel.ASTSelection.commonAncestor());
// Bail out if the selection is not a in-line function definition.
@@ -489,12 +489,12 @@ class DefineOutline : public Tweak {
Expected<Effect> apply(const Selection &Sel) override {
const SourceManager &SM = Sel.AST->getSourceManager();
- auto CCFile = SameFile ? Sel.AST->tuPath().str()
- : getSourceFile(Sel.AST->tuPath(), Sel);
+ auto CCFile = SameFile ? Sel.AST->tuPath().owned()
+ : getSourceFile(Sel.AST->tuPath().raw(), Sel);
if (!CCFile)
return error("Couldn't find a suitable implementation file.");
assert(Sel.FS && "FS Must be set in apply");
- auto Buffer = Sel.FS->getBufferForFile(*CCFile);
+ auto Buffer = Sel.FS->getBufferForFile(CCFile->raw());
// FIXME: Maybe we should consider creating the implementation file if it
// doesn't exist?
if (!Buffer)
@@ -507,13 +507,14 @@ class DefineOutline : public Tweak {
auto FuncDef = getFunctionSourceCode(
Source, InsertionPoint->EnclosingNamespace, Sel.AST->getTokens(),
Sel.AST->getHeuristicResolver(),
- SameFile && isHeaderFile(Sel.AST->tuPath(), Sel.AST->getLangOpts()));
+ SameFile &&
+ isHeaderFile(Sel.AST->tuPath().raw(), Sel.AST->getLangOpts()));
if (!FuncDef)
return FuncDef.takeError();
- SourceManagerForFile SMFF(*CCFile, Contents);
+ SourceManagerForFile SMFF(CCFile->raw(), Contents);
const tooling::Replacement InsertFunctionDef(
- *CCFile, InsertionPoint->Offset, 0, *FuncDef);
+ CCFile->raw(), InsertionPoint->Offset, 0, *FuncDef);
auto Effect = Effect::mainFileEdit(
SMFF.get(), tooling::Replacements(InsertFunctionDef));
if (!Effect)
@@ -536,7 +537,7 @@ class DefineOutline : public Tweak {
}
if (SameFile) {
- tooling::Replacements &R = Effect->ApplyEdits[*CCFile].Replacements;
+ tooling::Replacements &R = Effect->ApplyEdits[CCFile->raw()].Replacements;
R = R.merge(HeaderUpdates);
} else {
auto HeaderFE = Effect::fileEdit(SM, SM.getMainFileID(), HeaderUpdates);
diff --git a/clang-tools-extra/clangd/support/FileCache.cpp b/clang-tools-extra/clangd/support/FileCache.cpp
index cc59c648b062a..9c55c0499f427 100644
--- a/clang-tools-extra/clangd/support/FileCache.cpp
+++ b/clang-tools-extra/clangd/support/FileCache.cpp
@@ -22,10 +22,10 @@ static constexpr uint64_t CacheDiskMismatch =
// The cached value reflects that the file doesn't exist.
static constexpr uint64_t FileNotFound = CacheDiskMismatch - 1;
-FileCache::FileCache(llvm::StringRef Path)
- : Path(Path), ValidTime(std::chrono::steady_clock::time_point::min()),
+FileCache::FileCache(PathRef Path)
+ : Path(Path.raw()), ValidTime(std::chrono::steady_clock::time_point::min()),
ModifiedTime(), Size(CacheDiskMismatch) {
- assert(llvm::sys::path::is_absolute(Path));
+ assert(Path.isAbsolute());
}
void FileCache::read(
diff --git a/clang-tools-extra/clangd/support/Path.cpp b/clang-tools-extra/clangd/support/Path.cpp
index 1dd107cc6abef..9e9a1c308e36c 100644
--- a/clang-tools-extra/clangd/support/Path.cpp
+++ b/clang-tools-extra/clangd/support/Path.cpp
@@ -7,47 +7,151 @@
//===----------------------------------------------------------------------===//
#include "support/Path.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/StringExtras.h"
+#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FileSystem.h"
#include "llvm/Support/Path.h"
+
+#include <ostream>
+
namespace clang {
namespace clangd {
-#ifdef CLANGD_PATH_CASE_INSENSITIVE
-std::string maybeCaseFoldPath(PathRef Path) { return Path.lower(); }
-bool pathEqual(PathRef A, PathRef B) { return A.equals_insensitive(B); }
-#else // NOT CLANGD_PATH_CASE_INSENSITIVE
-std::string maybeCaseFoldPath(PathRef Path) { return Path.str(); }
-bool pathEqual(PathRef A, PathRef B) { return A == B; }
-#endif // CLANGD_PATH_CASE_INSENSITIVE
-
-PathRef absoluteParent(PathRef Path) {
- assert(llvm::sys::path::is_absolute(Path));
+PathRef PathRef::absoluteParent() const {
+ assert(llvm::sys::path::is_absolute(Data));
#if defined(_WIN32)
// llvm::sys says "C:\" is absolute, and its parent is "C:" which is relative.
// This unhelpful behavior seems to have been inherited from boost.
- if (llvm::sys::path::relative_path(Path).empty()) {
+ if (llvm::sys::path::relative_path(Data).empty()) {
return PathRef();
}
#endif
- PathRef Result = llvm::sys::path::parent_path(Path);
+ llvm::StringRef Result = llvm::sys::path::parent_path(Data);
assert(Result.empty() || llvm::sys::path::is_absolute(Result));
return Result;
}
-bool pathStartsWith(PathRef Ancestor, PathRef Path,
- llvm::sys::path::Style Style) {
- assert(llvm::sys::path::is_absolute(Ancestor) &&
- llvm::sys::path::is_absolute(Path));
+PathRef PathRef::parentPath(Style Style) const {
+ return llvm::sys::path::parent_path(Data, Style);
+}
+
+bool PathRef::startsWith(PathRef Path, Style Style) const {
+ assert(isAbsolute() && Path.isAbsolute()); // XXX: this doesn't pass the Style
+
// If ancestor ends with a separator drop that, so that we can match /foo/ as
// a parent of /foo.
- if (llvm::sys::path::is_separator(Ancestor.back(), Style))
- Ancestor = Ancestor.drop_back();
+ PathRef Ancestor = withoutTrailingSeparator(Style);
// Ensure Path starts with Ancestor.
- if (!pathEqual(Ancestor, Path.take_front(Ancestor.size())))
+ if (Ancestor != PathRef(Path.raw().take_front(Ancestor.size())))
return false;
- Path = Path.drop_front(Ancestor.size());
+ Path = Path.Data.drop_front(Ancestor.size());
// Then make sure either two paths are equal or Path has a separator
// afterwards.
- return Path.empty() || llvm::sys::path::is_separator(Path.front(), Style);
+ return Path.empty() ||
+ llvm::sys::path::is_separator(Path.raw().front(), Style);
+}
+
+llvm::StringRef PathRef::filename(Style Style) const {
+ return llvm::sys::path::filename(raw(), Style);
+}
+
+llvm::StringRef PathRef::extension(Style Style) const {
+ return llvm::sys::path::extension(raw(), Style);
+}
+
+PathRef PathRef::stem(Style Style) const {
+ return llvm::sys::path::stem(raw(), Style);
+}
+
+PathRef PathRef::withoutTrailingSeparator(Style Style) const {
+ if (llvm::sys::path::is_separator(Data.back(), Style))
+ return Data.drop_back();
+ return Data;
+}
+
+Path PathRef::removeDots() const {
+ llvm::SmallString<128> CanonPath(Data);
+ llvm::sys::path::remove_dots(CanonPath, /*remove_dot_dot=*/true);
+ return CanonPath.str().str();
+}
+
+Path PathRef::caseFolded() const {
+#ifdef CLANGD_PATH_CASE_INSENSITIVE
+ return Data.lower();
+#else
+ return Data.str();
+#endif
+}
+
+bool PathRef::isAbsolute(Style Style) const {
+ return llvm::sys::path::is_absolute(Data, Style);
+}
+
+bool PathRef::isRelative(Style Style) const {
+ return llvm::sys::path::is_relative(Data, Style);
+}
+
+bool PathRef::exists() const { return llvm::sys::fs::exists(Data); }
+
+std::ostream &operator<<(std::ostream &OS, PathRef Path) {
+ OS << std::string_view(Path.raw());
+ return OS;
+}
+
+bool operator==(PathRef LHS, PathRef RHS) {
+#ifdef CLANGD_PATH_CASE_INSENSITIVE
+ return LHS.raw().equals_insensitive(RHS.raw());
+#else
+ return LHS.raw() == RHS.raw();
+#endif
+}
+
+llvm::hash_code hash_value(PathRef P) {
+#ifdef CLANGD_PATH_CASE_INSENSITIVE
+ return hash_combine_range(llvm::map_iterator(P.raw().begin(), llvm::toLower),
+ llvm::map_iterator(P.raw().end(), llvm::toLower));
+#else
+ return hash_value(P.raw());
+#endif
}
+
} // namespace clangd
} // namespace clang
+
+namespace llvm {
+
+unsigned DenseMapInfo<clang::clangd::PathRef, void>::getHashValue(
+ clang::clangd::PathRef Val) {
+ assert(Val.Data.data() != getEmptyKey().Data.data() &&
+ "Cannot hash the empty key!");
+ assert(Val.Data.data() != getTombstoneKey().Data.data() &&
+ "Cannot hash the tombstone key!");
+ return (unsigned)(hash_value(Val));
+}
+
+namespace cl {
+
+void parser<clang::clangd::Path>::printOptionDiff(const Option &O,
+ clang::clangd::PathRef V,
+ const OptVal &Default,
+ size_t GlobalWidth) const {
+ constexpr static const size_t MaxOptWidth = 8;
+
+ printOptionName(O, GlobalWidth);
+ outs() << "= " << V.raw();
+ size_t NumSpaces = MaxOptWidth > V.size() ? MaxOptWidth - V.size() : 0;
+ outs().indent(NumSpaces) << " (default: ";
+ if (Default.hasValue())
+ outs() << Default.getValue().raw();
+ else
+ outs() << "*no default*";
+ outs() << ")\n";
+}
+
+void parser<clang::clangd::Path>::anchor() {}
+
+} // namespace cl
+
+} // namespace llvm
diff --git a/clang-tools-extra/clangd/support/Path.h b/clang-tools-extra/clangd/support/Path.h
index ff45a436e5f08..a6c3a8e345434 100644
--- a/clang-tools-extra/clangd/support/Path.h
+++ b/clang-tools-extra/clangd/support/Path.h
@@ -9,8 +9,15 @@
#ifndef LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H
#define LLVM_CLANG_TOOLS_EXTRA_CLANGD_SUPPORT_PATH_H
+#include "llvm/ADT/DenseMapInfo.h"
+#include "llvm/ADT/Hashing.h"
+#include "llvm/ADT/SmallString.h"
#include "llvm/ADT/StringRef.h"
+#include "llvm/Support/CommandLine.h"
+#include "llvm/Support/FormatProviders.h"
+#include "llvm/Support/JSON.h"
#include "llvm/Support/Path.h"
+
#include <string>
/// Whether current platform treats paths case insensitively.
@@ -21,30 +28,179 @@
namespace clang {
namespace clangd {
-/// A typedef to represent a file path. Used solely for more descriptive
-/// signatures.
-using Path = std::string;
-/// A typedef to represent a ref to file path. Used solely for more descriptive
-/// signatures.
-using PathRef = llvm::StringRef;
-
-// For platforms where paths are case-insensitive (but case-preserving),
-// we need to do case-insensitive comparisons and use lowercase keys.
-// FIXME: Make Path a real class with desired semantics instead.
-std::string maybeCaseFoldPath(PathRef Path);
-bool pathEqual(PathRef, PathRef);
-
-/// Checks if \p Ancestor is a proper ancestor of \p Path. This is just a
-/// smarter lexical prefix match, e.g: foo/bar/baz doesn't start with foo/./bar.
-/// Both \p Ancestor and \p Path must be absolute.
-bool pathStartsWith(
- PathRef Ancestor, PathRef Path,
- llvm::sys::path::Style Style = llvm::sys::path::Style::native);
-
-/// Variant of parent_path that operates only on absolute paths.
-/// Unlike parent_path doesn't consider C: a parent of C:\.
-PathRef absoluteParent(PathRef Path);
+class PathRef;
+class Path {
+public:
+ Path() = default;
+ Path(std::string Data) : Data(std::move(Data)) {}
+ Path(const char *Data) : Data(Data) {}
+
+ explicit Path(PathRef Ref);
+
+ operator PathRef() const;
+ PathRef ref() const;
+
+ [[nodiscard]] const std::string &raw() const & { return Data; }
+ [[nodiscard]] std::string &&raw() && { return std::move(Data); }
+
+ [[nodiscard]] size_t size() const { return Data.size(); }
+ [[nodiscard]] bool empty() const { return Data.empty(); }
+
+private:
+ std::string Data;
+
+ friend llvm::json::Value toJSON(const Path &Path) { return Path.Data; }
+
+ friend bool fromJSON(const llvm::json::Value &Value, Path &Path,
+ llvm::json::Path Cursor) {
+ return fromJSON(Value, Path.Data, Cursor);
+ }
+};
+
+class LLVM_GSL_POINTER PathRef {
+public:
+ using Style = llvm::sys::path::Style;
+
+ PathRef() = default;
+ PathRef(llvm::StringRef Ref) : Data(Ref) {}
+ PathRef(const std::string &Str) : Data(Str) {}
+ PathRef(const char *Str) : Data(Str) {}
+ template <unsigned int N>
+ PathRef(const llvm::SmallString<N> &Str) : Data(Str) {}
+
+ /// Variant of parent_path that operates only on absolute paths.
+ /// Unlike parent_path doesn't consider C: a parent of C:\.
+ [[nodiscard]] PathRef absoluteParent() const;
+
+ [[nodiscard]] PathRef parentPath(Style Style = Style::native) const;
+
+ /// Checks if \p this is a proper ancestor of \p Path. This is just a
+ /// smarter lexical prefix match, e.g: foo/bar/baz doesn't start with
+ /// foo/./bar. Both \p this and \p Path must be absolute.
+ [[nodiscard]] bool startsWith(PathRef Path,
+ Style Style = Style::native) const;
+
+ [[nodiscard]] llvm::StringRef filename(Style Style = Style::native) const;
+
+ [[nodiscard]] llvm::StringRef extension(Style Style = Style::native) const;
+
+ [[nodiscard]] PathRef stem(Style Style = Style::native) const;
+
+ /// Returns a version of \p File that doesn't contain dots and dot dots.
+ /// e.g /a/b/../c -> /a/c
+ /// /a/b/./c -> /a/b/c
+ /// FIXME: We should avoid encountering such paths in clangd internals by
+ /// filtering everything we get over LSP, CDB, etc.
+ [[nodiscard]] Path removeDots() const;
+
+ [[nodiscard]] Path caseFolded() const;
+
+ [[nodiscard]] Path owned() const { return Path(*this); }
+ [[nodiscard]] llvm::StringRef raw() const { return Data; }
+
+ [[nodiscard]] PathRef
+ withoutTrailingSeparator(Style Style = Style::native) const;
+
+ [[nodiscard]] size_t size() const { return Data.size(); }
+
+ [[nodiscard]] bool empty() const { return Data.empty(); }
+
+ [[nodiscard]] bool isAbsolute(Style Style = Style::native) const;
+ [[nodiscard]] bool isRelative(Style Style = Style::native) const;
+
+ [[nodiscard]] bool exists() const;
+
+private:
+ llvm::StringRef Data;
+
+ friend llvm::DenseMapInfo<clang::clangd::PathRef, void>;
+};
+
+inline Path::Path(PathRef Ref) : Data(Ref.raw().str()) {}
+
+// for gtest
+std::ostream &operator<<(std::ostream &OS, PathRef Path);
+
+inline Path::operator PathRef() const { return PathRef(Data); }
+inline PathRef Path::ref() const { return PathRef(Data); }
+
+bool operator==(PathRef LHS, PathRef RHS);
+inline bool operator!=(PathRef LHS, PathRef RHS) { return !(LHS == RHS); }
+
+inline bool operator==(Path LHS, Path RHS) {
+ return clang::clangd::PathRef(LHS) == clang::clangd::PathRef(RHS);
+}
+inline bool operator!=(Path LHS, Path RHS) { return !(LHS == RHS); }
+
+[[nodiscard]] llvm::hash_code hash_value(PathRef P);
+[[nodiscard]] inline llvm::hash_code hash_value(const Path &P) {
+ return hash_value(PathRef(P));
+}
+
+inline llvm::json::Value toJson(PathRef Path) { return Path.raw(); }
+
} // namespace clangd
} // namespace clang
+namespace llvm {
+
+template <> struct format_provider<clang::clangd::PathRef> {
+ static void format(const clang::clangd::PathRef &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ format_provider<llvm::StringRef>::format(V.raw(), Stream, Style);
+ }
+};
+
+template <> struct format_provider<clang::clangd::Path> {
+ static void format(const clang::clangd::Path &V, llvm::raw_ostream &Stream,
+ StringRef Style) {
+ format_provider<clang::clangd::PathRef>::format(V, Stream, Style);
+ }
+};
+
+template <> struct DenseMapInfo<clang::clangd::PathRef, void> {
+ static inline clang::clangd::PathRef getEmptyKey() {
+ return DenseMapInfo<llvm::StringRef>::getEmptyKey();
+ }
+
+ static inline clang::clangd::PathRef getTombstoneKey() {
+ return DenseMapInfo<llvm::StringRef>::getTombstoneKey();
+ }
+
+ static unsigned getHashValue(clang::clangd::PathRef Val);
+
+ static bool isEqual(clang::clangd::PathRef LHS, clang::clangd::PathRef RHS) {
+ if (RHS.Data.data() == getEmptyKey().Data.data())
+ return LHS.Data.data() == getEmptyKey().Data.data();
+ if (RHS.Data.data() == getTombstoneKey().Data.data())
+ return LHS.Data.data() == getTombstoneKey().Data.data();
+ return LHS == RHS;
+ }
+};
+
+namespace cl {
+
+template <>
+struct parser<clang::clangd::Path> : public basic_parser<clang::clangd::Path> {
+public:
+ parser(Option &O) : basic_parser(O) {}
+
+ bool parse(cl::Option &O, StringRef ArgName, StringRef ArgValue,
+ clang::clangd::Path &Val) {
+ Val = ArgValue.str();
+ return false;
+ }
+
+ StringRef getValueName() const override { return "path"; }
+
+ void printOptionDiff(const Option &O, clang::clangd::PathRef V,
+ const OptVal &Default, size_t GlobalWidth) const;
+
+ void anchor() override;
+};
+
+} // namespace cl
+
+} // namespace llvm
+
#endif
diff --git a/clang-tools-extra/clangd/support/ThreadsafeFS.cpp b/clang-tools-extra/clangd/support/ThreadsafeFS.cpp
index 7398e4258527b..8c78ad0fe088e 100644
--- a/clang-tools-extra/clangd/support/ThreadsafeFS.cpp
+++ b/clang-tools-extra/clangd/support/ThreadsafeFS.cpp
@@ -74,7 +74,7 @@ class VolatileFileSystem : public llvm::vfs::ProxyFileSystem {
llvm::IntrusiveRefCntPtr<llvm::vfs::FileSystem>
ThreadsafeFS::view(PathRef CWD) const {
auto FS = view(std::nullopt);
- if (auto EC = FS->setCurrentWorkingDirectory(CWD))
+ if (auto EC = FS->setCurrentWorkingDirectory(CWD.raw()))
elog("VFS: failed to set CWD to {0}: {1}", CWD, EC.message());
return FS;
}
diff --git a/clang-tools-extra/clangd/tool/ClangdMain.cpp b/clang-tools-extra/clangd/tool/ClangdMain.cpp
index 4bd256d6be22b..26b34e8dee3fc 100644
--- a/clang-tools-extra/clangd/tool/ClangdMain.cpp
+++ b/clang-tools-extra/clangd/tool/ClangdMain.cpp
@@ -673,12 +673,12 @@ class FlagsConfigProvider : public config::Provider {
// If --compile-commands-dir arg was invoked, check value and override
// default path.
if (!CompileCommandsDir.empty()) {
- if (llvm::sys::fs::exists(CompileCommandsDir)) {
+ if (CompileCommandsDir.ref().exists()) {
// We support passing both relative and absolute paths to the
// --compile-commands-dir argument, but we assume the path is absolute
// in the rest of clangd so we make sure the path is absolute before
// continuing.
- llvm::SmallString<128> Path(CompileCommandsDir);
+ llvm::SmallString<128> Path(CompileCommandsDir.raw());
if (std::error_code EC = llvm::sys::fs::make_absolute(Path)) {
elog("Error while converting the relative path specified by "
"--compile-commands-dir to an absolute path: {0}. The argument "
@@ -695,7 +695,7 @@ class FlagsConfigProvider : public config::Provider {
if (!IndexFile.empty()) {
Config::ExternalIndexSpec Spec;
Spec.Kind = Spec.File;
- Spec.Location = IndexFile;
+ Spec.Location = IndexFile.raw();
IndexSpec = std::move(Spec);
}
#if CLANGD_ENABLE_REMOTE
@@ -826,7 +826,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
std::optional<llvm::raw_fd_ostream> InputMirrorStream;
if (!InputMirrorFile.empty()) {
std::error_code EC;
- InputMirrorStream.emplace(InputMirrorFile, /*ref*/ EC,
+ InputMirrorStream.emplace(InputMirrorFile.raw(), /*ref*/ EC,
llvm::sys::fs::FA_Read | llvm::sys::fs::FA_Write);
if (EC) {
InputMirrorStream.reset();
@@ -911,7 +911,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
break;
}
if (!ResourceDir.empty())
- Opts.ResourceDir = ResourceDir;
+ Opts.ResourceDir = ResourceDir.raw();
Opts.BuildDynamicSymbolIndex = true;
std::vector<std::unique_ptr<SymbolIndex>> IdxStack;
#if CLANGD_ENABLE_REMOTE
@@ -1013,9 +1013,9 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
if (CheckFile.getNumOccurrences()) {
llvm::SmallString<256> Path;
- if (auto Error =
- llvm::sys::fs::real_path(CheckFile, Path, /*expand_tilde=*/true)) {
- elog("Failed to resolve path {0}: {1}", CheckFile, Error.message());
+ if (auto Error = llvm::sys::fs::real_path(CheckFile.raw(), Path,
+ /*expand_tilde=*/true)) {
+ elog("Failed to resolve path {0}: {1}", CheckFile.raw(), Error.message());
return 1;
}
log("Entering check mode (no LSP server)");
diff --git a/clang-tools-extra/clangd/unittests/ASTTests.cpp b/clang-tools-extra/clangd/unittests/ASTTests.cpp
index d0bc3c4d7db98..3eee66c02b851 100644
--- a/clang-tools-extra/clangd/unittests/ASTTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ASTTests.cpp
@@ -622,7 +622,7 @@ TEST(ClangdAST, HasReservedName) {
TEST(ClangdAST, PreferredIncludeDirective) {
auto ComputePreferredDirective = [](TestTU &TU) {
auto AST = TU.build();
- return preferredIncludeDirective(AST.tuPath(), AST.getLangOpts(),
+ return preferredIncludeDirective(AST.tuPath().raw(), AST.getLangOpts(),
AST.getIncludeStructure().MainFileIncludes,
AST.getLocalTopLevelDecls());
};
diff --git a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp
index ada14c9939318..2d26e1ac5656c 100644
--- a/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp
+++ b/clang-tools-extra/clangd/unittests/BackgroundIndexTests.cpp
@@ -98,7 +98,7 @@ TEST_F(BackgroundIndexTest, NoCrashOnErrorFile) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
tooling::CompileCommand Cmd;
@@ -132,11 +132,11 @@ TEST_F(BackgroundIndexTest, Config) {
BackgroundIndex::Options Opts;
Opts.ContextProvider = [](PathRef P) {
Config C;
- if (P.ends_with("foo.cpp"))
+ if (P.raw().ends_with("foo.cpp"))
C.CompileFlags.Edits.push_back([](std::vector<std::string> &Argv) {
Argv = tooling::getInsertArgumentAdjuster("-Done=two")(Argv, "");
});
- if (P.ends_with("baz.cpp"))
+ if (P.raw().ends_with("baz.cpp"))
C.Index.Background = Config::BackgroundPolicy::Skip;
return Context::current().derive(Config::Key, std::move(C));
};
@@ -148,8 +148,7 @@ TEST_F(BackgroundIndexTest, Config) {
OverlayCDB CDB(/*Base=*/nullptr, /*FallbackFlags=*/{},
CommandMangler::forTests());
- BackgroundIndex Idx(
- FS, CDB, [&](llvm::StringRef) { return &MSS; }, std::move(Opts));
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; }, std::move(Opts));
// Index the two files.
for (auto &Cmd : Cmds) {
std::string FullPath = testPath(Cmd.Filename);
@@ -191,8 +190,7 @@ TEST_F(BackgroundIndexTest, IndexTwoFiles) {
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
BackgroundIndex::Options Opts;
- BackgroundIndex Idx(
- FS, CDB, [&](llvm::StringRef) { return &MSS; }, Opts);
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; }, Opts);
tooling::CompileCommand Cmd;
Cmd.Filename = testPath("root/A.cc");
@@ -246,8 +244,7 @@ TEST_F(BackgroundIndexTest, MainFileRefs) {
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
BackgroundIndex::Options Opts;
- BackgroundIndex Idx(
- FS, CDB, [&](llvm::StringRef) { return &MSS; }, Opts);
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; }, Opts);
tooling::CompileCommand Cmd;
Cmd.Filename = testPath("root/A.cc");
@@ -286,7 +283,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) {
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -296,7 +293,7 @@ TEST_F(BackgroundIndexTest, ShardStorageTest) {
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -355,7 +352,7 @@ TEST_F(BackgroundIndexTest, DirectIncludesTest) {
Cmd.CommandLine = {"clang++", testPath("root/A.cc")};
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -405,7 +402,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
// Check nothing is loaded from Storage, but A.cc and A.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -420,7 +417,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
)cpp";
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -438,7 +435,7 @@ TEST_F(BackgroundIndexTest, ShardStorageLoad) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -479,7 +476,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
// Check that A.cc, A.h and B.h has been stored.
{
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -495,7 +492,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -511,7 +508,7 @@ TEST_F(BackgroundIndexTest, ShardStorageEmptyFile) {
{
CacheHits = 0;
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
CDB.setCompileCommand(testPath("root/A.cc"), Cmd);
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -529,7 +526,7 @@ TEST_F(BackgroundIndexTest, NoDotsInAbsPath) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
ASSERT_TRUE(Idx.blockUntilIdleForTest());
@@ -560,7 +557,7 @@ TEST_F(BackgroundIndexTest, UncompilableFiles) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
tooling::CompileCommand Cmd;
@@ -624,7 +621,7 @@ TEST_F(BackgroundIndexTest, CmdLineHash) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
tooling::CompileCommand Cmd;
@@ -652,7 +649,7 @@ TEST_F(BackgroundIndexTest, Reindex) {
size_t CacheHits = 0;
MemoryShardStorage MSS(Storage, CacheHits);
OverlayCDB CDB(/*Base=*/nullptr);
- BackgroundIndex Idx(FS, CDB, [&](llvm::StringRef) { return &MSS; },
+ BackgroundIndex Idx(FS, CDB, [&](PathRef) { return &MSS; },
/*Opts=*/{});
// Index a file.
@@ -901,7 +898,7 @@ TEST(BackgroundQueueTest, Progress) {
TEST(BackgroundIndex, Profile) {
MockFS FS;
MockCompilationDatabase CDB;
- BackgroundIndex Idx(FS, CDB, [](llvm::StringRef) { return nullptr; },
+ BackgroundIndex Idx(FS, CDB, [](PathRef) { return nullptr; },
/*Opts=*/{});
llvm::BumpPtrAllocator Alloc;
diff --git a/clang-tools-extra/clangd/unittests/ClangdTests.cpp b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
index 643b8e9f12d75..fce04fe711680 100644
--- a/clang-tools-extra/clangd/unittests/ClangdTests.cpp
+++ b/clang-tools-extra/clangd/unittests/ClangdTests.cpp
@@ -102,7 +102,7 @@ class MultipleErrorCheckingCallbacks : public ClangdServer::Callbacks {
bool HadError = diagsContainErrors(Diagnostics);
std::lock_guard<std::mutex> Lock(Mutex);
- LastDiagsHadError[File] = HadError;
+ LastDiagsHadError[File.raw()] = HadError;
}
/// Exposes all files consumed by onDiagnosticsReady in an unspecified order.
@@ -591,8 +591,8 @@ struct Something {
)cpp";
Path BarCpp = testPath("bar.cpp");
- FS.Files[FooCpp] = "";
- FS.Files[BarCpp] = "";
+ FS.Files[FooCpp.raw()] = "";
+ FS.Files[BarCpp.raw()] = "";
EXPECT_THAT(Server.fileStats(), IsEmpty());
@@ -691,7 +691,7 @@ int d;
void onDiagnosticsReady(PathRef File, llvm::StringRef Version,
llvm::ArrayRef<Diag> Diagnostics) override {
- StringRef FileIndexStr = llvm::sys::path::stem(File);
+ StringRef FileIndexStr = File.stem().raw();
ASSERT_TRUE(FileIndexStr.consume_front("Foo"));
unsigned long FileIndex = std::stoul(FileIndexStr.str());
@@ -1117,11 +1117,11 @@ TEST(ClangdServerTest, FallbackWhenWaitingForCompileCommand) {
// FIXME: make this timeout and fail instead of waiting forever in case
// something goes wrong.
CanReturnCommand.wait();
- auto FileName = llvm::sys::path::filename(File);
+ auto FileName = File.filename();
std::vector<std::string> CommandLine = {"clangd", "-ffreestanding",
- std::string(File)};
- return {tooling::CompileCommand(llvm::sys::path::parent_path(File),
- FileName, std::move(CommandLine), "")};
+ File.owned().raw()};
+ return {tooling::CompileCommand(File.parentPath().raw(), FileName,
+ std::move(CommandLine), "")};
}
std::vector<std::string> ExtraClangFlags;
diff --git a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
index 718bee2e40b11..c197c288a0f3d 100644
--- a/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
+++ b/clang-tools-extra/clangd/unittests/CodeCompleteTests.cpp
@@ -147,7 +147,7 @@ CodeCompleteResult completions(llvm::StringRef Text,
Annotations Test(Text);
auto TU = TestTU::withCode(Test.code());
// To make sure our tests for completiopns inside templates work on Windows.
- TU.Filename = FilePath.str();
+ TU.Filename = FilePath.owned().raw();
return completions(TU, Test.point(), std::move(IndexSymbols),
std::move(Opts));
}
diff --git a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
index c9e01e52dac1f..1fc72fb36a9ee 100644
--- a/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
+++ b/clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp
@@ -55,23 +55,23 @@ TEST(GlobalCompilationDatabaseTest, FallbackCommand) {
testPath("foo/bar")));
}
-static tooling::CompileCommand cmd(llvm::StringRef File, llvm::StringRef Arg) {
+static tooling::CompileCommand cmd(PathRef File, llvm::StringRef Arg) {
return tooling::CompileCommand(
- testRoot(), File, {"clang", std::string(Arg), std::string(File)}, "");
+ testRoot(), File.owned().raw(),
+ {"clang", std::string(Arg), File.owned().raw()}, "");
}
class OverlayCDBTest : public ::testing::Test {
class BaseCDB : public GlobalCompilationDatabase {
public:
std::optional<tooling::CompileCommand>
- getCompileCommand(llvm::StringRef File) const override {
+ getCompileCommand(PathRef File) const override {
if (File == testPath("foo.cc"))
return cmd(File, "-DA=1");
return std::nullopt;
}
- tooling::CompileCommand
- getFallbackCommand(llvm::StringRef File) const override {
+ tooling::CompileCommand getFallbackCommand(PathRef File) const override {
return cmd(File, "-DA=2");
}
diff --git a/clang-tools-extra/clangd/unittests/HeaderSourceSwitchTests.cpp b/clang-tools-extra/clangd/unittests/HeaderSourceSwitchTests.cpp
index e600207de458a..c9f95db7c923c 100644
--- a/clang-tools-extra/clangd/unittests/HeaderSourceSwitchTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeaderSourceSwitchTests.cpp
@@ -334,17 +334,17 @@ TEST(HeaderSourceSwitchTest, CaseSensitivity) {
// 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.
+// 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))));
+ llvm::ValueIs(Path(testPath(TU.Filename))));
#else
EXPECT_THAT(getCorrespondingHeaderOrSource(HeaderAbsPath, AST, Index.get()),
- llvm::ValueIs(testing::StrCaseEq(testPath(TU.HeaderFilename))));
+ llvm::ValueIs(Path(testPath(TU.HeaderFilename))));
#endif
}
diff --git a/clang-tools-extra/clangd/unittests/HeadersTests.cpp b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
index 751383e3b4650..fd62c72b9340b 100644
--- a/clang-tools-extra/clangd/unittests/HeadersTests.cpp
+++ b/clang-tools-extra/clangd/unittests/HeadersTests.cpp
@@ -111,7 +111,7 @@ class HeadersTest : public ::testing::Test {
QuotedHeaders, AngledHeaders);
for (const auto &Inc : Inclusions)
Inserter.addExisting(Inc);
- auto Inserted = ToHeaderFile(Preferred);
+ auto Inserted = ToHeaderFile(Preferred.raw());
if (!Inserter.shouldInsertInclude(Original, Inserted))
return "";
auto Path = Inserter.calculateIncludePath(Inserted, MainFile);
diff --git a/clang-tools-extra/clangd/unittests/PreambleTests.cpp b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
index 16a2f9448b1ec..330bed8d08a5c 100644
--- a/clang-tools-extra/clangd/unittests/PreambleTests.cpp
+++ b/clang-tools-extra/clangd/unittests/PreambleTests.cpp
@@ -883,14 +883,14 @@ TEST(PreamblePatch, PatchFileEntry) {
#define FOO)cpp");
{
auto AST = createPatchedAST(Code.code(), Code.code());
- EXPECT_EQ(
- PreamblePatch::getPatchEntry(AST->tuPath(), AST->getSourceManager()),
- nullptr);
+ EXPECT_EQ(PreamblePatch::getPatchEntry(AST->tuPath().raw(),
+ AST->getSourceManager()),
+ nullptr);
}
{
auto AST = createPatchedAST(Code.code(), NewCode.code());
- auto FE =
- PreamblePatch::getPatchEntry(AST->tuPath(), AST->getSourceManager());
+ auto FE = PreamblePatch::getPatchEntry(AST->tuPath().raw(),
+ AST->getSourceManager());
ASSERT_NE(FE, std::nullopt);
EXPECT_THAT(FE->getName().str(),
testing::EndsWith(PreamblePatch::HeaderName.str()));
diff --git a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
index 43f38e39c8952..27c39955035b4 100644
--- a/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
+++ b/clang-tools-extra/clangd/unittests/TUSchedulerTests.cpp
@@ -79,7 +79,7 @@ MATCHER_P2(TUState, PreambleActivity, ASTActivity, "") {
// Simple ContextProvider to verify the provider is invoked & contexts are used.
static Key<std::string> BoundPath;
Context bindPath(PathRef F) {
- return Context::current().derive(BoundPath, F.str());
+ return Context::current().derive(BoundPath, F.owned().raw());
}
llvm::StringRef boundPath() {
const std::string *V = Context::current().get(BoundPath);
@@ -155,7 +155,7 @@ class TUSchedulerTests : public ::testing::Test {
void updateWithDiags(TUScheduler &S, PathRef File, ParseInputs Inputs,
WantDiagnostics WD,
llvm::unique_function<void(std::vector<Diag>)> CB) {
- Path OrigFile = File.str();
+ Path OrigFile = File.owned();
WithContextValue Ctx(DiagsCallbackKey,
[OrigFile, CB = std::move(CB)](
PathRef File, std::vector<Diag> Diags) mutable {
@@ -1569,7 +1569,7 @@ TEST_F(TUSchedulerTests, PreambleThrottle) {
// Deliberately no synchronization.
// The PreambleThrottler should serialize these calls, if not then tsan
// will find a bug here.
- Filenames.emplace_back(Path);
+ Filenames.emplace_back(Path.owned().raw());
}
};
diff --git a/clang-tools-extra/clangd/unittests/TestFS.cpp b/clang-tools-extra/clangd/unittests/TestFS.cpp
index bb309609eda20..816d5e364d99b 100644
--- a/clang-tools-extra/clangd/unittests/TestFS.cpp
+++ b/clang-tools-extra/clangd/unittests/TestFS.cpp
@@ -21,8 +21,8 @@ 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))
+bool pathConsumeFront(llvm::StringRef &Path, PathRef Prefix) {
+ if (!Prefix.startsWith(Path))
return false;
Path = Path.drop_front(Prefix.size());
return true;
@@ -61,14 +61,14 @@ MockCompilationDatabase::getCompileCommand(PathRef File) const {
if (ExtraClangFlags.empty())
return std::nullopt;
- auto FileName = llvm::sys::path::filename(File);
+ auto FileName = File.filename();
// Build the compile command.
auto CommandLine = ExtraClangFlags;
CommandLine.insert(CommandLine.begin(), "clang");
if (RelPathPrefix.empty()) {
// Use the absolute path in the compile command.
- CommandLine.push_back(std::string(File));
+ CommandLine.push_back(File.owned().raw());
} else {
// Build a relative path using RelPathPrefix.
llvm::SmallString<32> RelativeFilePath(RelPathPrefix);
@@ -76,10 +76,9 @@ MockCompilationDatabase::getCompileCommand(PathRef File) const {
CommandLine.push_back(std::string(RelativeFilePath.str()));
}
- return {tooling::CompileCommand(Directory != llvm::StringRef()
- ? Directory
- : llvm::sys::path::parent_path(File),
- FileName, std::move(CommandLine), "")};
+ return {tooling::CompileCommand(
+ Directory != llvm::StringRef() ? Directory : File.parentPath().raw(),
+ FileName, std::move(CommandLine), "")};
}
const char *testRoot() {
@@ -91,9 +90,9 @@ const char *testRoot() {
}
std::string testPath(PathRef File, llvm::sys::path::Style Style) {
- assert(llvm::sys::path::is_relative(File) && "FileName should be relative");
+ assert(File.isRelative() && "FileName should be relative");
- llvm::SmallString<32> NativeFile = File;
+ llvm::SmallString<32> NativeFile = File.raw();
llvm::sys::path::native(NativeFile, Style);
llvm::SmallString<32> Path;
llvm::sys::path::append(Path, Style, testRoot(), NativeFile);
@@ -110,7 +109,7 @@ class TestScheme : public URIScheme {
llvm::Expected<std::string>
getAbsolutePath(llvm::StringRef /*Authority*/, llvm::StringRef Body,
llvm::StringRef HintPath) const override {
- if (!HintPath.empty() && !pathStartsWith(testRoot(), HintPath))
+ if (!HintPath.empty() && !PathRef(testRoot()).startsWith(HintPath))
return error("Hint path is not empty and doesn't start with {0}: {1}",
testRoot(), HintPath);
if (!Body.consume_front("/"))
diff --git a/clang-tools-extra/clangd/unittests/support/PathTests.cpp b/clang-tools-extra/clangd/unittests/support/PathTests.cpp
index 599c76926d30d..98f3d6a2cc6d7 100644
--- a/clang-tools-extra/clangd/unittests/support/PathTests.cpp
+++ b/clang-tools-extra/clangd/unittests/support/PathTests.cpp
@@ -15,21 +15,21 @@ namespace clang {
namespace clangd {
namespace {
TEST(PathTests, IsAncestor) {
- EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo")));
- EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo")));
+ EXPECT_TRUE(PathRef(testPath("foo")).startsWith(testPath("foo")));
+ EXPECT_TRUE(PathRef(testPath("foo/")).startsWith(testPath("foo")));
- EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fooz")));
- EXPECT_FALSE(pathStartsWith(testPath("foo/"), testPath("fooz")));
+ EXPECT_FALSE(PathRef(testPath("foo")).startsWith(testPath("fooz")));
+ EXPECT_FALSE(PathRef(testPath("foo/")).startsWith(testPath("fooz")));
- EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("foo/bar")));
- EXPECT_TRUE(pathStartsWith(testPath("foo/"), testPath("foo/bar")));
+ EXPECT_TRUE(PathRef(testPath("foo")).startsWith(testPath("foo/bar")));
+ EXPECT_TRUE(PathRef(testPath("foo/")).startsWith(testPath("foo/bar")));
#ifdef CLANGD_PATH_CASE_INSENSITIVE
- EXPECT_TRUE(pathStartsWith(testPath("fOo"), testPath("foo/bar")));
- EXPECT_TRUE(pathStartsWith(testPath("foo"), testPath("fOo/bar")));
+ EXPECT_TRUE(PathRef(testPath("fOo")).startsWith(testPath("foo/bar")));
+ EXPECT_TRUE(PathRef(testPath("foo")).startsWith(testPath("fOo/bar")));
#else
- EXPECT_FALSE(pathStartsWith(testPath("fOo"), testPath("foo/bar")));
- EXPECT_FALSE(pathStartsWith(testPath("foo"), testPath("fOo/bar")));
+ EXPECT_FALSE(PathRef(testPath("fOo")).startsWith(testPath("foo/bar")));
+ EXPECT_FALSE(PathRef(testPath("foo")).startsWith(testPath("fOo/bar")));
#endif
}
} // namespace
More information about the cfe-commits
mailing list