forked from qt-creator/qt-creator
ClangCodeModel: Use project-specific clangd client, if possible
If we open a file that does not belong to a currently open project, there is a good chance that the current project's parse context is a better fit for the file than the fallback client's. Fixes: QTCREATORBUG-26697 Change-Id: I6c17e275b047602c51364f3203b3f0a3e74a49fc Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org> Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -58,6 +58,7 @@
|
|||||||
#include <projectexplorer/buildsystem.h>
|
#include <projectexplorer/buildsystem.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
#include <projectexplorer/projectnodes.h>
|
#include <projectexplorer/projectnodes.h>
|
||||||
|
#include <projectexplorer/projecttree.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
#include <projectexplorer/target.h>
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
@@ -85,6 +86,13 @@ static CppEditor::CppModelManager *cppModelManager()
|
|||||||
return CppEditor::CppModelManager::instance();
|
return CppEditor::CppModelManager::instance();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static ProjectExplorer::Project *fallbackProject()
|
||||||
|
{
|
||||||
|
if (ProjectExplorer::Project * const p = ProjectExplorer::ProjectTree::currentProject())
|
||||||
|
return p;
|
||||||
|
return ProjectExplorer::SessionManager::startupProject();
|
||||||
|
}
|
||||||
|
|
||||||
static const QList<TextEditor::BaseTextEditor *> allCppEditors()
|
static const QList<TextEditor::BaseTextEditor *> allCppEditors()
|
||||||
{
|
{
|
||||||
QList<TextEditor::BaseTextEditor *> cppEditors;
|
QList<TextEditor::BaseTextEditor *> cppEditors;
|
||||||
@@ -148,10 +156,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
||||||
this, &ClangModelManagerSupport::onAboutToRemoveProject);
|
this, &ClangModelManagerSupport::onAboutToRemoveProject);
|
||||||
connect(sessionManager, &ProjectExplorer::SessionManager::projectRemoved,
|
connect(sessionManager, &ProjectExplorer::SessionManager::projectRemoved,
|
||||||
this, [this] {
|
this, [this] { claimNonProjectSources(clientForProject(fallbackProject())); });
|
||||||
if (ClangdClient * const fallbackClient = clientForProject(nullptr))
|
|
||||||
claimNonProjectSources(fallbackClient);
|
|
||||||
});
|
|
||||||
|
|
||||||
CppEditor::ClangdSettings::setDefaultClangdPath(Core::ICore::clangdExecutable(CLANG_BINDIR));
|
CppEditor::ClangdSettings::setDefaultClangdPath(Core::ICore::clangdExecutable(CLANG_BINDIR));
|
||||||
connect(&CppEditor::ClangdSettings::instance(), &CppEditor::ClangdSettings::changed,
|
connect(&CppEditor::ClangdSettings::instance(), &CppEditor::ClangdSettings::changed,
|
||||||
@@ -369,13 +374,16 @@ void ClangModelManagerSupport::updateLanguageClient(
|
|||||||
// Acquaint the client with all open C++ documents for this project.
|
// Acquaint the client with all open C++ documents for this project.
|
||||||
bool hasDocuments = false;
|
bool hasDocuments = false;
|
||||||
for (TextEditor::BaseTextEditor * const editor : allCppEditors()) {
|
for (TextEditor::BaseTextEditor * const editor : allCppEditors()) {
|
||||||
const Utils::FilePath filePath = editor->textDocument()->filePath();
|
TextEditor::TextDocument * const doc = editor->textDocument();
|
||||||
if (!project->isKnownFile(filePath))
|
const Client * const currentClient = LanguageClientManager::clientForDocument(doc);
|
||||||
continue;
|
if (!currentClient || !currentClient->project()
|
||||||
|
|| currentClient->state() != Client::Initialized
|
||||||
|
|| project->isKnownFile(doc->filePath())) {
|
||||||
LanguageClientManager::openDocumentWithClient(editor->textDocument(), client);
|
LanguageClientManager::openDocumentWithClient(editor->textDocument(), client);
|
||||||
ClangEditorDocumentProcessor::clearTextMarks(filePath);
|
ClangEditorDocumentProcessor::clearTextMarks(doc->filePath());
|
||||||
hasDocuments = true;
|
hasDocuments = true;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (client->state() == Client::Initialized)
|
if (client->state() == Client::Initialized)
|
||||||
updateParserConfig();
|
updateParserConfig();
|
||||||
@@ -443,7 +451,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject(
|
|||||||
|
|
||||||
ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) const
|
ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) const
|
||||||
{
|
{
|
||||||
return clientForProject(ProjectExplorer::SessionManager::projectForFile(file));
|
return qobject_cast<ClangdClient *>(LanguageClientManager::clientForFilePath(file));
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project,
|
ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project,
|
||||||
@@ -454,15 +462,19 @@ ClangdClient *ClangModelManagerSupport::createClient(ProjectExplorer::Project *p
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *fallbackClient)
|
void ClangModelManagerSupport::claimNonProjectSources(ClangdClient *client)
|
||||||
{
|
{
|
||||||
|
if (!client)
|
||||||
|
return;
|
||||||
for (TextEditor::BaseTextEditor * const editor : allCppEditors()) {
|
for (TextEditor::BaseTextEditor * const editor : allCppEditors()) {
|
||||||
if (ProjectExplorer::SessionManager::projectForFile(editor->textDocument()->filePath()))
|
if (Client * const currentClient = LanguageClientManager::clientForDocument(
|
||||||
|
editor->textDocument());
|
||||||
|
currentClient && currentClient->state() == Client::Initialized
|
||||||
|
&& (currentClient == client || currentClient->project())) {
|
||||||
continue;
|
continue;
|
||||||
if (!fallbackClient->documentOpen(editor->textDocument())) {
|
|
||||||
ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath());
|
|
||||||
fallbackClient->openDocument(editor->textDocument());
|
|
||||||
}
|
}
|
||||||
|
ClangEditorDocumentProcessor::clearTextMarks(editor->textDocument()->filePath());
|
||||||
|
client->openDocument(editor->textDocument());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -562,8 +574,10 @@ void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
|
|||||||
|
|
||||||
// TODO: Ensure that not fully loaded documents are updated?
|
// TODO: Ensure that not fully loaded documents are updated?
|
||||||
|
|
||||||
ProjectExplorer::Project * const project
|
ProjectExplorer::Project * project
|
||||||
= ProjectExplorer::SessionManager::projectForFile(document->filePath());
|
= ProjectExplorer::SessionManager::projectForFile(document->filePath());
|
||||||
|
if (!project)
|
||||||
|
project = fallbackProject();
|
||||||
if (ClangdClient * const client = clientForProject(project))
|
if (ClangdClient * const client = clientForProject(project))
|
||||||
LanguageClientManager::openDocumentWithClient(textDocument, client);
|
LanguageClientManager::openDocumentWithClient(textDocument, client);
|
||||||
}
|
}
|
||||||
|
@@ -134,7 +134,7 @@ private:
|
|||||||
void updateLanguageClient(ProjectExplorer::Project *project,
|
void updateLanguageClient(ProjectExplorer::Project *project,
|
||||||
const CppEditor::ProjectInfo::ConstPtr &projectInfo);
|
const CppEditor::ProjectInfo::ConstPtr &projectInfo);
|
||||||
ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir);
|
ClangdClient *createClient(ProjectExplorer::Project *project, const Utils::FilePath &jsonDbDir);
|
||||||
void claimNonProjectSources(ClangdClient *fallbackClient);
|
void claimNonProjectSources(ClangdClient *client);
|
||||||
void watchForExternalChanges();
|
void watchForExternalChanges();
|
||||||
void watchForInternalChanges();
|
void watchForInternalChanges();
|
||||||
|
|
||||||
|
@@ -2036,7 +2036,7 @@ void ClangdTestExternalChanges::test()
|
|||||||
QVERIFY(waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
|
QVERIFY(waitForSignalOrTimeout(ClangModelManagerSupport::instance(),
|
||||||
&ClangModelManagerSupport::createdClient, timeOutInMs()));
|
&ClangModelManagerSupport::createdClient, timeOutInMs()));
|
||||||
ClangdClient * const newClient = ClangModelManagerSupport::instance()
|
ClangdClient * const newClient = ClangModelManagerSupport::instance()
|
||||||
->clientForFile(filePath("main.cpp"));
|
->clientForProject(project());
|
||||||
QVERIFY(newClient);
|
QVERIFY(newClient);
|
||||||
QVERIFY(newClient != oldClient);
|
QVERIFY(newClient != oldClient);
|
||||||
newClient->enableTesting();
|
newClient->enableTesting();
|
||||||
|
Reference in New Issue
Block a user