Skip to content
1 change: 1 addition & 0 deletions clang-tools-extra/clangd/ClangdServer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ ClangdServer::Options::operator TUScheduler::Options() const {
Opts.UpdateDebounce = UpdateDebounce;
Opts.ContextProvider = ContextProvider;
Opts.PreambleThrottler = PreambleThrottler;
Opts.StrongWorkspaceMode = StrongWorkspaceMode;
return Opts;
}

Expand Down
4 changes: 4 additions & 0 deletions clang-tools-extra/clangd/ClangdServer.h
Original file line number Diff line number Diff line change
Expand Up @@ -152,6 +152,10 @@ class ClangdServer {
/// FIXME: If not set, should use the current working directory.
std::optional<std::string> WorkspaceRoot;

/// Sets an alterante mode of operation. Current effects are:
/// - Using the current working directory as the working directory for fallback commands
bool StrongWorkspaceMode;

/// The resource directory is used to find internal headers, overriding
/// defaults and -resource-dir compiler flag).
/// If std::nullopt, ClangdServer calls
Expand Down
19 changes: 12 additions & 7 deletions clang-tools-extra/clangd/GlobalCompilationDatabase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void actOnAllParentDirectories(PathRef FileName,
} // namespace

tooling::CompileCommand
GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
GlobalCompilationDatabase::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
std::vector<std::string> Argv = {"clang"};
// Clang treats .h files as C by default and files without extension as linker
// input, resulting in unhelpful diagnostics.
Expand All @@ -64,7 +64,12 @@ GlobalCompilationDatabase::getFallbackCommand(PathRef File) const {
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),
SmallString<256> WorkingDir;
if (StrongWorkspaceMode)
llvm::sys::fs::current_path(WorkingDir);
else
WorkingDir = llvm::sys::path::parent_path(File);
tooling::CompileCommand Cmd(WorkingDir,
llvm::sys::path::filename(File), std::move(Argv),
/*Output=*/"");
Cmd.Heuristic = "clangd fallback";
Expand Down Expand Up @@ -797,8 +802,8 @@ OverlayCDB::getCompileCommand(PathRef File) const {
return Cmd;
}

tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File) const {
auto Cmd = DelegatingCDB::getFallbackCommand(File);
tooling::CompileCommand OverlayCDB::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
auto Cmd = DelegatingCDB::getFallbackCommand(File, StrongWorkspaceMode);
std::lock_guard<std::mutex> Lock(Mutex);
Cmd.CommandLine.insert(Cmd.CommandLine.end(), FallbackFlags.begin(),
FallbackFlags.end());
Expand Down Expand Up @@ -877,10 +882,10 @@ DelegatingCDB::getProjectModules(PathRef File) const {
return Base->getProjectModules(File);
}

tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File) const {
tooling::CompileCommand DelegatingCDB::getFallbackCommand(PathRef File, bool StrongWorkspaceMode) const {
if (!Base)
return GlobalCompilationDatabase::getFallbackCommand(File);
return Base->getFallbackCommand(File);
return GlobalCompilationDatabase::getFallbackCommand(File, StrongWorkspaceMode);
return Base->getFallbackCommand(File, StrongWorkspaceMode);
}

bool DelegatingCDB::blockUntilIdle(Deadline D) const {
Expand Down
6 changes: 3 additions & 3 deletions clang-tools-extra/clangd/GlobalCompilationDatabase.h
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ class GlobalCompilationDatabase {
/// Makes a guess at how to build a file.
/// The default implementation just runs clang on the file.
/// Clangd should treat the results as unreliable.
virtual tooling::CompileCommand getFallbackCommand(PathRef File) const;
virtual tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const;

/// If the CDB does any asynchronous work, wait for it to complete.
/// For use in tests.
Expand Down Expand Up @@ -86,7 +86,7 @@ class DelegatingCDB : public GlobalCompilationDatabase {
std::unique_ptr<ProjectModules>
getProjectModules(PathRef File) const override;

tooling::CompileCommand getFallbackCommand(PathRef File) const override;
tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const override;

bool blockUntilIdle(Deadline D) const override;

Expand Down Expand Up @@ -200,7 +200,7 @@ class OverlayCDB : public DelegatingCDB {

std::optional<tooling::CompileCommand>
getCompileCommand(PathRef File) const override;
tooling::CompileCommand getFallbackCommand(PathRef File) const override;
tooling::CompileCommand getFallbackCommand(PathRef File, bool StrongWorkspaceMode = false) const override;

/// Sets or clears the compilation command for a particular file.
/// Returns true if the command was changed (including insertion and removal),
Expand Down
6 changes: 4 additions & 2 deletions clang-tools-extra/clangd/TUScheduler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -723,6 +723,7 @@ class ASTWorker {
const GlobalCompilationDatabase &CDB;
/// Callback invoked when preamble or main file AST is built.
ParsingCallbacks &Callbacks;
bool StrongWorkspaceMode;

Semaphore &Barrier;
/// Whether the 'onMainAST' callback ran for the current FileInputs.
Expand Down Expand Up @@ -840,13 +841,14 @@ ASTWorker::ASTWorker(PathRef FileName, const GlobalCompilationDatabase &CDB,
: IdleASTs(LRUCache), HeaderIncluders(HeaderIncluders), RunSync(RunSync),
UpdateDebounce(Opts.UpdateDebounce), FileName(FileName),
ContextProvider(Opts.ContextProvider), CDB(CDB), Callbacks(Callbacks),
StrongWorkspaceMode(Opts.StrongWorkspaceMode),
Barrier(Barrier), Done(false), Status(FileName, Callbacks),
PreamblePeer(FileName, 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.
FileInputs.CompileCommand = CDB.getFallbackCommand(FileName);
FileInputs.CompileCommand = CDB.getFallbackCommand(FileName, StrongWorkspaceMode);
}

ASTWorker::~ASTWorker() {
Expand Down Expand Up @@ -888,7 +890,7 @@ void ASTWorker::update(ParseInputs Inputs, WantDiagnostics WantDiags,
if (Cmd)
Inputs.CompileCommand = std::move(*Cmd);
else
Inputs.CompileCommand = CDB.getFallbackCommand(FileName);
Inputs.CompileCommand = CDB.getFallbackCommand(FileName, StrongWorkspaceMode);

bool InputsAreTheSame =
std::tie(FileInputs.CompileCommand, FileInputs.Contents) ==
Expand Down
3 changes: 3 additions & 0 deletions clang-tools-extra/clangd/TUScheduler.h
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ class TUScheduler {
/// Typically to inject per-file configuration.
/// If the path is empty, context sholud be "generic".
std::function<Context(PathRef)> ContextProvider;

/// Sets an alterante mode of operation. See ClangdServer::Options::StrongWorkspaceMode.
bool StrongWorkspaceMode;
};

TUScheduler(const GlobalCompilationDatabase &CDB, const Options &Opts,
Expand Down
4 changes: 2 additions & 2 deletions clang-tools-extra/clangd/tool/Check.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -187,7 +187,7 @@ class Checker {
Cmd.Heuristic.empty() ? "from CDB" : Cmd.Heuristic, Cmd.Directory,
printArgv(Cmd.CommandLine));
} else {
Cmd = CDB->getFallbackCommand(File);
Cmd = CDB->getFallbackCommand(File, Opts.StrongWorkspaceMode);
log("Generic fallback command is: [{0}] {1}", Cmd.Directory,
printArgv(Cmd.CommandLine));
}
Expand Down Expand Up @@ -502,7 +502,7 @@ bool check(llvm::StringRef File, const ThreadsafeFS &TFS,
config::DiagnosticCallback Diag) const override {
config::Fragment F;
// If we're timing clang-tidy checks, implicitly disabling the slow ones
// is counterproductive!
// is counterproductive!
if (CheckTidyTime.getNumOccurrences())
F.Diagnostics.ClangTidy.FastCheckFilter.emplace("None");
return {std::move(F).compile(Diag)};
Expand Down
10 changes: 10 additions & 0 deletions clang-tools-extra/clangd/tool/ClangdMain.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -500,6 +500,15 @@ opt<bool> EnableConfig{
init(true),
};

opt<bool> StrongWorkspaceMode{
"strong-workspace-mode",
cat(Features),
desc(
"An alternate mode of operation for clangd, operating more closely to the workspace.\n"
"When enabled, fallback commands use the workspace directory as their working directory instead of the parent folder."),
init(false),
};

opt<bool> UseDirtyHeaders{"use-dirty-headers", cat(Misc),
desc("Use files open in the editor when parsing "
"headers instead of reading from the disk"),
Expand Down Expand Up @@ -907,6 +916,7 @@ clangd accepts flags on the commandline, and in the CLANGD_FLAGS environment var
}
if (!ResourceDir.empty())
Opts.ResourceDir = ResourceDir;
Opts.StrongWorkspaceMode = StrongWorkspaceMode;
Opts.BuildDynamicSymbolIndex = true;
#if CLANGD_ENABLE_REMOTE
if (RemoteIndexAddress.empty() != ProjectRoot.empty()) {
Expand Down
Loading