LanguageClient: Add signal to inform about WorkDoneProgressEnd

... and make use of it in the clangd client to be able tell when
background indexing has finished.

Change-Id: I0f3c6f9646fd66ababd08c12b2f347da5f1a3729
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-04-20 15:46:35 +02:00
parent 8e352af0ec
commit 91b6c58518
10 changed files with 35 additions and 17 deletions

View File

@@ -30,12 +30,15 @@
#include <languageclient/languageclientinterface.h>
using namespace LanguageClient;
using namespace LanguageServerProtocol;
namespace ClangCodeModel {
namespace Internal {
static Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
static QString indexingToken() { return "backgroundIndexProgress"; }
static BaseClientInterface *clientInterface(const Utils::FilePath &jsonDbDir)
{
QString clangdArgs = "--index --background-index --limit-results=0";
@@ -63,8 +66,13 @@ ClangdClient::ClangdClient(ProjectExplorer::Project *project, const Utils::FileP
setClientCapabilities(caps);
setLocatorsEnabled(false);
setDocumentActionsEnabled(false);
setProgressTitleForToken("backgroundIndexProgress", tr("Parsing C/C++ Files (clangd)"));
setProgressTitleForToken(indexingToken(), tr("Parsing C/C++ Files (clangd)"));
setCurrentProject(project);
connect(this, &Client::workDone, this, [this](const ProgressToken &token) {
const QString * const val = Utils::get_if<QString>(&token);
if (val && *val == indexingToken())
m_isFullyIndexed = true;
});
start();
}

View File

@@ -37,6 +37,11 @@ class ClangdClient : public LanguageClient::Client
Q_OBJECT
public:
ClangdClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir);
bool isFullyIndexed() const { return m_isFullyIndexed; }
private:
bool m_isFullyIndexed = false;
};
} // namespace Internal

View File

@@ -25,6 +25,7 @@
#include "clanggloballocatorfilters.h"
#include "clangdclient.h"
#include "clangmodelmanagersupport.h"
#include <cpptools/cppclassesfilter.h>

View File

@@ -326,7 +326,7 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr
CompilationDbPurpose::CodeModel));
}
LanguageClient::Client *ClangModelManagerSupport::clientForProject(
ClangdClient *ClangModelManagerSupport::clientForProject(
const ProjectExplorer::Project *project)
{
const QList<Client *> clients = Utils::filtered(
@@ -337,10 +337,10 @@ LanguageClient::Client *ClangModelManagerSupport::clientForProject(
&& c->state() != Client::Shutdown;
});
QTC_CHECK(clients.size() <= 1);
return clients.empty() ? nullptr : clients.first();
return clients.empty() ? nullptr : qobject_cast<ClangdClient *>(clients.first());
}
Client *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project,
ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project,
const Utils::FilePath &jsonDbDir)
{
return new ClangdClient(project, jsonDbDir);

View File

@@ -47,11 +47,10 @@ class FollowSymbolInterface;
class RefactoringEngineInterface;
} // namespace CppTools
namespace LanguageClient { class Client; }
namespace ClangCodeModel {
namespace Internal {
class ClangdClient;
class ClangProjectSettings;
class ClangModelManagerSupport:
@@ -79,7 +78,7 @@ public:
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
LanguageClient::Client *clientForProject(const ProjectExplorer::Project *project);
ClangdClient *clientForProject(const ProjectExplorer::Project *project);
static ClangModelManagerSupport *instance();
@@ -124,8 +123,7 @@ private:
void updateLanguageClient(ProjectExplorer::Project *project,
const CppTools::ProjectInfo &projectInfo);
LanguageClient::Client *createClient(ProjectExplorer::Project *project,
const Utils::FilePath &jsonDbDir);
ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir);
private:
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;

View File

@@ -26,10 +26,10 @@
#include "clangrefactoringengine.h"
#include "clangeditordocumentprocessor.h"
#include "clangdclient.h"
#include "clangmodelmanagersupport.h"
#include <cpptools/cppmodelmanager.h>
#include <languageclient/client.h>
#include <languageclient/languageclientsymbolsupport.h>
#include <projectexplorer/session.h>
#include <utils/textutils.h>
@@ -91,12 +91,8 @@ void RefactoringEngine::findUsages(const CppTools::CursorInEditor &cursor,
{
ProjectExplorer::Project * const project
= ProjectExplorer::SessionManager::projectForFile(cursor.filePath());
LanguageClient::Client * const client
= ClangModelManagerSupport::instance()->clientForProject(project);
if (!client || client->state() != LanguageClient::Client::Initialized) {
// TODO: Also forward to built-in if index is not ready.
// This requires us to keep track of workDone status in the client.
// Related: Also allow to override the server string for progress info
ClangdClient * const client = ClangModelManagerSupport::instance()->clientForProject(project);
if (!client || !client->isFullyIndexed()) {
CppTools::CppModelManager::builtinRefactoringEngine()
->findUsages(cursor, std::move(callback));
return;

View File

@@ -1250,6 +1250,8 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon
if (!params->isValid())
logError(*params);
m_progressManager.handleProgress(*params);
if (ProgressManager::isProgressEndMessage(*params))
emit workDone(params->token());
}
} else if (id.isValid()) {
Response<JsonObject, JsonObject> response(id);

View File

@@ -178,6 +178,7 @@ signals:
void initialized(const LanguageServerProtocol::ServerCapabilities &capabilities);
void capabilitiesChanged(const DynamicCapabilities &capabilities);
void documentUpdated(TextEditor::TextDocument *document);
void workDone(const LanguageServerProtocol::ProgressToken &token);
void finished();
protected:

View File

@@ -61,6 +61,11 @@ void ProgressManager::setTitleForToken(const LanguageServerProtocol::ProgressTok
m_titles.insert(token, message);
}
bool ProgressManager::isProgressEndMessage(const LanguageServerProtocol::ProgressParams &params)
{
return Utils::holds_alternative<WorkDoneProgressEnd>(params.value());
}
Utils::Id languageClientProgressId(const ProgressToken &token)
{
constexpr char k_LanguageClientProgressId[] = "LanguageClient.ProgressId.";

View File

@@ -49,6 +49,8 @@ public:
void setTitleForToken(const LanguageServerProtocol::ProgressToken &token,
const QString &message);
static bool isProgressEndMessage(const LanguageServerProtocol::ProgressParams &params);
private:
void beginProgress(const LanguageServerProtocol::ProgressToken &token,
const LanguageServerProtocol::WorkDoneProgressBegin &begin);