Skip to content

Commit 03b26a6

Browse files
committed
[clangd] Fallback working directory code cleanup
1 parent 82f80c0 commit 03b26a6

File tree

8 files changed

+74
-36
lines changed

8 files changed

+74
-36
lines changed

clang-tools-extra/clangd/ClangdLSPServer.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -554,6 +554,8 @@ void ClangdLSPServer::onInitialize(const InitializeParams &Params,
554554
if (const auto &Dir = Params.initializationOptions.compilationDatabasePath)
555555
CDBOpts.CompileCommandsDir = Dir;
556556
CDBOpts.ContextProvider = Opts.ContextProvider;
557+
if (Opts.StrongWorkspaceMode)
558+
CDBOpts.applyWorkingDirectory(std::move(Opts.WorkspaceRoot));
557559
BaseCDB =
558560
std::make_unique<DirectoryBasedGlobalCompilationDatabase>(CDBOpts);
559561
}

clang-tools-extra/clangd/ClangdServer.cpp

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,6 @@ ClangdServer::Options::operator TUScheduler::Options() const {
208208
Opts.UpdateDebounce = UpdateDebounce;
209209
Opts.ContextProvider = ContextProvider;
210210
Opts.PreambleThrottler = PreambleThrottler;
211-
Opts.StrongWorkspaceMode = StrongWorkspaceMode;
212211
return Opts;
213212
}
214213

clang-tools-extra/clangd/GlobalCompilationDatabase.cpp

Lines changed: 32 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
5555
} // namespace
5656

5757
tooling::CompileCommand
58-
GlobalCompilationDatabase::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
58+
GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
5959
std::vector<std::string> Argv = {"clang"};
6060
// Clang treats .h files as C by default and files without extension as linker
6161
// input, resulting in unhelpful diagnostics.
@@ -64,14 +64,10 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File, bool StrongWorkspace
6464
if (FileExtension.empty() || FileExtension == ".h")
6565
Argv.push_back("-xobjective-c++-header");
6666
Argv.push_back(std::string(File));
67-
SmallString<256> WorkingDir;
68-
if (StrongWorkspaceMode)
69-
llvm::sys::fs::current_path(WorkingDir);
70-
else
71-
WorkingDir = llvm::sys::path::parent_path(File);
72-
tooling::CompileCommand Cmd(WorkingDir,
73-
llvm::sys::path::filename(File), std::move(Argv),
74-
/*Output=*/"");
67+
tooling::CompileCommand Cmd(
68+
WorkingDirectory ? *WorkingDirectory : llvm::sys::path::parent_path(File),
69+
llvm::sys::path::filename(File), std::move(Argv),
70+
/*Output=*/"");
7571
Cmd.Heuristic = "clangd fallback";
7672
return Cmd;
7773
}
@@ -354,7 +350,8 @@ bool DirectoryBasedGlobalCompilationDatabase::DirectoryCache::load(
354350

355351
DirectoryBasedGlobalCompilationDatabase::
356352
DirectoryBasedGlobalCompilationDatabase(const Options &Opts)
357-
: Opts(Opts), Broadcaster(std::make_unique<BroadcastThread>(*this)) {
353+
: GlobalCompilationDatabase(Opts.WorkingDirectory), Opts(Opts),
354+
Broadcaster(std::make_unique<BroadcastThread>(*this)) {
358355
if (!this->Opts.ContextProvider)
359356
this->Opts.ContextProvider = [](llvm::StringRef) {
360357
return Context::current().clone();
@@ -465,6 +462,17 @@ DirectoryBasedGlobalCompilationDatabase::lookupCDB(
465462
return Result;
466463
}
467464

465+
void DirectoryBasedGlobalCompilationDatabase::Options::applyWorkingDirectory(
466+
const std::optional<std::string> &&WorkingDirectory) {
467+
if (WorkingDirectory)
468+
this->WorkingDirectory = *WorkingDirectory;
469+
else {
470+
SmallString<256> CWD;
471+
llvm::sys::fs::current_path(CWD);
472+
this->WorkingDirectory = std::string(CWD);
473+
}
474+
}
475+
468476
// The broadcast thread announces files with new compile commands to the world.
469477
// Primarily this is used to enqueue them for background indexing.
470478
//
@@ -764,8 +772,9 @@ DirectoryBasedGlobalCompilationDatabase::getProjectModules(PathRef File) const {
764772

765773
OverlayCDB::OverlayCDB(const GlobalCompilationDatabase *Base,
766774
std::vector<std::string> FallbackFlags,
767-
CommandMangler Mangler)
768-
: DelegatingCDB(Base), Mangler(std::move(Mangler)),
775+
CommandMangler Mangler,
776+
std::optional<std::string> WorkingDirectory)
777+
: DelegatingCDB(Base, WorkingDirectory), Mangler(std::move(Mangler)),
769778
FallbackFlags(std::move(FallbackFlags)) {}
770779

771780
std::optional<tooling::CompileCommand>
@@ -802,8 +811,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
802811
return Cmd;
803812
}
804813

805-
tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
806-
auto Cmd = DelegatingCDB::getFallbackCommand(File, StrongWorkspaceMode);
814+
tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
815+
auto Cmd = DelegatingCDB::getFallbackCommand(File);
807816
std::lock_guard<std::mutex> Lock(Mutex);
808817
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
809818
FallbackFlags.end());
@@ -849,16 +858,18 @@ OverlayCDB::getProjectModules(PathRef File) const {
849858
return MDB;
850859
}
851860

852-
DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base)
853-
: Base(Base) {
861+
DelegatingCDB::DelegatingCDB(const GlobalCompilationDatabase *Base,
862+
std::optional<std::string> WorkingDirectory)
863+
: GlobalCompilationDatabase(WorkingDirectory), Base(Base) {
854864
if (Base)
855865
BaseChanged = Base->watch([this](const std::vector<std::string> Changes) {
856866
OnCommandChanged.broadcast(Changes);
857867
});
858868
}
859869

860-
DelegatingCDB::DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base)
861-
: DelegatingCDB(Base.get()) {
870+
DelegatingCDB::DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base,
871+
std::optional<std::string> WorkingDirectory)
872+
: DelegatingCDB(Base.get(), WorkingDirectory) {
862873
BaseOwner = std::move(Base);
863874
}
864875

@@ -882,10 +893,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
882893
return Base->getProjectModules(File);
883894
}
884895

885-
tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
896+
tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
886897
if (!Base)
887-
return GlobalCompilationDatabase::getFallbackCommand(File, StrongWorkspaceMode);
888-
return Base->getFallbackCommand(File, StrongWorkspaceMode);
898+
return GlobalCompilationDatabase::getFallbackCommand(File);
899+
return Base->getFallbackCommand(File);
889900
}
890901

891902
bool DelegatingCDB::blockUntilIdle(Deadline D) const {

clang-tools-extra/clangd/GlobalCompilationDatabase.h

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@ struct ProjectInfo {
3535
/// Provides compilation arguments used for parsing C and C++ files.
3636
class GlobalCompilationDatabase {
3737
public:
38+
GlobalCompilationDatabase(std::optional<std::string> WorkingDirectory)
39+
: WorkingDirectory(WorkingDirectory) {}
3840
virtual ~GlobalCompilationDatabase() = default;
3941

4042
/// If there are any known-good commands for building this file, returns one.
@@ -55,7 +57,7 @@ class GlobalCompilationDatabase {
5557
/// Makes a guess at how to build a file.
5658
/// The default implementation just runs clang on the file.
5759
/// Clangd should treat the results as unreliable.
58-
virtual tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const;
60+
virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
5961

6062
/// If the CDB does any asynchronous work, wait for it to complete.
6163
/// For use in tests.
@@ -69,14 +71,17 @@ class GlobalCompilationDatabase {
6971
}
7072

7173
protected:
74+
std::optional<std::string> WorkingDirectory;
7275
mutable CommandChanged OnCommandChanged;
7376
};
7477

7578
// Helper class for implementing GlobalCompilationDatabases that wrap others.
7679
class DelegatingCDB : public GlobalCompilationDatabase {
7780
public:
78-
DelegatingCDB(const GlobalCompilationDatabase *Base);
79-
DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base);
81+
DelegatingCDB(const GlobalCompilationDatabase *Base,
82+
std::optional<std::string> WorkingDirectory);
83+
DelegatingCDB(std::unique_ptr<GlobalCompilationDatabase> Base,
84+
std::optional<std::string> WorkingDirectory);
8085

8186
std::optional<tooling::CompileCommand>
8287
getCompileCommand(PathRef File) const override;
@@ -86,7 +91,7 @@ class DelegatingCDB : public GlobalCompilationDatabase {
8691
std::unique_ptr<ProjectModules>
8792
getProjectModules(PathRef File) const override;
8893

89-
tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const override;
94+
tooling::CompileCommand getFallbackCommand(PathRef File) const override;
9095

9196
bool blockUntilIdle(Deadline D) const override;
9297

@@ -117,6 +122,12 @@ class DirectoryBasedGlobalCompilationDatabase
117122
// Only look for a compilation database in this one fixed directory.
118123
// FIXME: fold this into config/context mechanism.
119124
std::optional<Path> CompileCommandsDir;
125+
// Working directory for fallback commands
126+
// If unset, parent directory of file should be used
127+
std::optional<std::string> WorkingDirectory;
128+
129+
void
130+
applyWorkingDirectory(const std::optional<std::string> &&WorkingDirectory);
120131
};
121132

122133
DirectoryBasedGlobalCompilationDatabase(const Options &Opts);
@@ -196,11 +207,12 @@ class OverlayCDB : public DelegatingCDB {
196207
// Adjuster is applied to all commands, fallback or not.
197208
OverlayCDB(const GlobalCompilationDatabase *Base,
198209
std::vector<std::string> FallbackFlags = {},
199-
CommandMangler Mangler = nullptr);
210+
CommandMangler Mangler = nullptr,
211+
std::optional<std::string> WorkingDirectory = std::nullopt);
200212

201213
std::optional<tooling::CompileCommand>
202214
getCompileCommand(PathRef File) const override;
203-
tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const override;
215+
tooling::CompileCommand getFallbackCommand(PathRef File) const override;
204216

205217
/// Sets or clears the compilation command for a particular file.
206218
/// Returns true if the command was changed (including insertion and removal),

clang-tools-extra/clangd/TUScheduler.cpp

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -841,14 +841,13 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
841841
: IdleASTs(LRUCache), HeaderIncluders(HeaderIncluders), RunSync(RunSync),
842842
UpdateDebounce(Opts.UpdateDebounce), FileName(FileName),
843843
ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks),
844-
StrongWorkspaceMode(Opts.StrongWorkspaceMode),
845844
Barrier(Barrier), Done(false), Status(FileName, Callbacks),
846845
PreamblePeer(FileName, Callbacks, Opts.StorePreamblesInMemory, RunSync,
847846
Opts.PreambleThrottler, Status, HeaderIncluders, *this) {
848847
// Set a fallback command because compile command can be accessed before
849848
// `Inputs` is initialized. Other fields are only used after initialization
850849
// from client inputs.
851-
FileInputs.CompileCommand = CDB.getFallbackCommand(FileName, StrongWorkspaceMode);
850+
FileInputs.CompileCommand = CDB.getFallbackCommand(FileName);
852851
}
853852

854853
ASTWorker::~ASTWorker() {
@@ -890,7 +889,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
890889
if (Cmd)
891890
Inputs.CompileCommand = std::move(*Cmd);
892891
else
893-
Inputs.CompileCommand = CDB.getFallbackCommand(FileName, StrongWorkspaceMode);
892+
Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
894893

895894
bool InputsAreTheSame =
896895
std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==

clang-tools-extra/clangd/TUScheduler.h

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -236,9 +236,6 @@ class TUScheduler {
236236
/// Typically to inject per-file configuration.
237237
/// If the path is empty, context sholud be "generic".
238238
std::function<Context(PathRef)> ContextProvider;
239-
240-
/// Sets an alterante mode of operation. See ClangdServer::Options::StrongWorkspaceMode.
241-
bool StrongWorkspaceMode;
242239
};
243240

244241
TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,

clang-tools-extra/clangd/tool/Check.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -169,6 +169,8 @@ class Checker {
169169
bool buildCommand(const ThreadsafeFS &TFS) {
170170
log("Loading compilation database...");
171171
DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
172+
if (Opts.StrongWorkspaceMode)
173+
CDBOpts.applyWorkingDirectory(std::move(Opts.WorkspaceRoot));
172174
CDBOpts.CompileCommandsDir =
173175
Config::current().CompileFlags.CDBSearch.FixedCDBPath;
174176
BaseCDB =
@@ -178,16 +180,18 @@ class Checker {
178180
getSystemIncludeExtractor(llvm::ArrayRef(Opts.QueryDriverGlobs));
179181
if (Opts.ResourceDir)
180182
Mangler.ResourceDir = *Opts.ResourceDir;
183+
181184
CDB = std::make_unique<OverlayCDB>(
182-
BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler));
185+
BaseCDB.get(), std::vector<std::string>{}, std::move(Mangler),
186+
CDBOpts.WorkingDirectory);
183187

184188
if (auto TrueCmd = CDB->getCompileCommand(File)) {
185189
Cmd = std::move(*TrueCmd);
186190
log("Compile command {0} is: [{1}] {2}",
187191
Cmd.Heuristic.empty() ? "from CDB" : Cmd.Heuristic, Cmd.Directory,
188192
printArgv(Cmd.CommandLine));
189193
} else {
190-
Cmd = CDB->getFallbackCommand(File, Opts.StrongWorkspaceMode);
194+
Cmd = CDB->getFallbackCommand(File);
191195
log("Generic fallback command is: [{0}] {1}", Cmd.Directory,
192196
printArgv(Cmd.CommandLine));
193197
}

clang-tools-extra/clangd/unittests/GlobalCompilationDatabaseTests.cpp

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,20 @@ TEST(GlobalCompilationDatabaseTest, FallbackCommand) {
5555
testPath("foo/bar")));
5656
}
5757

58+
TEST(GlobalCompilationDatabaseTest, FallbackWorkingDirectory) {
59+
MockFS TFS;
60+
DirectoryBasedGlobalCompilationDatabase::Options CDBOpts(TFS);
61+
CDBOpts.applyWorkingDirectory(testPath("foo"));
62+
EXPECT_EQ(CDBOpts.WorkingDirectory, testPath("foo"));
63+
64+
DirectoryBasedGlobalCompilationDatabase DB(CDBOpts);
65+
auto Cmd = DB.getFallbackCommand(testPath("foo/src/bar.cc"));
66+
EXPECT_EQ(Cmd.Directory, testPath("foo"));
67+
EXPECT_THAT(Cmd.CommandLine,
68+
ElementsAre("clang", testPath("foo/src/bar.cc")));
69+
EXPECT_EQ(Cmd.Output, "");
70+
}
71+
5872
static tooling::CompileCommand cmd(llvm::StringRef File, llvm::StringRef Arg) {
5973
return tooling::CompileCommand(
6074
testRoot(), File, {"clang", std::string(Arg), std::string(File)}, "");

0 commit comments

Comments
 (0)