forked from qt-creator/qt-creator
ClangCodeModel: Add experimental clangd support
If the user has enabled clangd (default is off), we start up one instance per project when it is opened/changed (including build config switches), and trigger background indexing. So far, the index is used to provide results for locators and "Find Usages". Per-document functionality such as semantic highlighting and completion is still provided by libclang. Change-Id: I12532fca1b9c6278baab560e7238cba6189cde9f Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
@@ -138,6 +138,10 @@
|
|||||||
edit the value for the \uicontrol {Do not index files greater than}
|
edit the value for the \uicontrol {Do not index files greater than}
|
||||||
check box. To index all files, deselect the check box.
|
check box. To index all files, deselect the check box.
|
||||||
|
|
||||||
|
\li To use clangd instead of the built-in code model for features such as
|
||||||
|
\e {Find References to Symbol}, check the \uicontrol {Use clangd} checkbox.
|
||||||
|
\note This is an experimental feature, which might not work reliably yet.
|
||||||
|
|
||||||
\li The \uicontrol {Diagnostic Configuration} field shows the Clang
|
\li The \uicontrol {Diagnostic Configuration} field shows the Clang
|
||||||
checks to perform. Click the value of the field to open the
|
checks to perform. Click the value of the field to open the
|
||||||
\uicontrol {Diagnostic Configurations} dialog, where you can
|
\uicontrol {Diagnostic Configurations} dialog, where you can
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
add_qtc_plugin(ClangCodeModel
|
add_qtc_plugin(ClangCodeModel
|
||||||
CONDITION TARGET libclang
|
CONDITION TARGET libclang
|
||||||
DEPENDS ClangSupport CPlusPlus
|
DEPENDS ClangSupport CPlusPlus
|
||||||
PLUGIN_DEPENDS Core CppTools TextEditor
|
PLUGIN_DEPENDS Core CppTools LanguageClient TextEditor
|
||||||
PLUGIN_TEST_DEPENDS CppEditor QmakeProjectManager
|
PLUGIN_TEST_DEPENDS CppEditor QmakeProjectManager
|
||||||
SOURCES
|
SOURCES
|
||||||
clangactivationsequencecontextprocessor.cpp clangactivationsequencecontextprocessor.h
|
clangactivationsequencecontextprocessor.cpp clangactivationsequencecontextprocessor.h
|
||||||
@@ -29,6 +29,7 @@ add_qtc_plugin(ClangCodeModel
|
|||||||
clangfixitoperationsextractor.cpp clangfixitoperationsextractor.h
|
clangfixitoperationsextractor.cpp clangfixitoperationsextractor.h
|
||||||
clangfollowsymbol.cpp clangfollowsymbol.h
|
clangfollowsymbol.cpp clangfollowsymbol.h
|
||||||
clangfunctionhintmodel.cpp clangfunctionhintmodel.h
|
clangfunctionhintmodel.cpp clangfunctionhintmodel.h
|
||||||
|
clanggloballocatorfilters.cpp clanggloballocatorfilters.h
|
||||||
clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
|
clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
|
||||||
clanghoverhandler.cpp clanghoverhandler.h
|
clanghoverhandler.cpp clanghoverhandler.h
|
||||||
clangisdiagnosticrelatedtolocation.h
|
clangisdiagnosticrelatedtolocation.h
|
||||||
|
@@ -40,7 +40,8 @@ SOURCES += \
|
|||||||
clangtextmark.cpp \
|
clangtextmark.cpp \
|
||||||
clanguiheaderondiskmanager.cpp \
|
clanguiheaderondiskmanager.cpp \
|
||||||
clangutils.cpp \
|
clangutils.cpp \
|
||||||
clangoverviewmodel.cpp
|
clangoverviewmodel.cpp \
|
||||||
|
clanggloballocatorfilters.cpp
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
clangactivationsequencecontextprocessor.h \
|
clangactivationsequencecontextprocessor.h \
|
||||||
@@ -79,7 +80,8 @@ HEADERS += \
|
|||||||
clangtextmark.h \
|
clangtextmark.h \
|
||||||
clanguiheaderondiskmanager.h \
|
clanguiheaderondiskmanager.h \
|
||||||
clangutils.h \
|
clangutils.h \
|
||||||
clangoverviewmodel.h
|
clangoverviewmodel.h \
|
||||||
|
clanggloballocatorfilters.h
|
||||||
|
|
||||||
FORMS += clangprojectsettingswidget.ui
|
FORMS += clangprojectsettingswidget.ui
|
||||||
|
|
||||||
|
@@ -11,6 +11,7 @@ QtcPlugin {
|
|||||||
Depends { name: "TextEditor" }
|
Depends { name: "TextEditor" }
|
||||||
Depends { name: "Utils" }
|
Depends { name: "Utils" }
|
||||||
Depends { name: "ClangSupport" }
|
Depends { name: "ClangSupport" }
|
||||||
|
Depends { name: "LanguageClient" }
|
||||||
|
|
||||||
Depends { name: "libclang"; required: false }
|
Depends { name: "libclang"; required: false }
|
||||||
Depends { name: "clang_defines" }
|
Depends { name: "clang_defines" }
|
||||||
@@ -72,6 +73,8 @@ QtcPlugin {
|
|||||||
"clangfollowsymbol.h",
|
"clangfollowsymbol.h",
|
||||||
"clangfunctionhintmodel.cpp",
|
"clangfunctionhintmodel.cpp",
|
||||||
"clangfunctionhintmodel.h",
|
"clangfunctionhintmodel.h",
|
||||||
|
"clanggloballocatorfilters.cpp",
|
||||||
|
"clanggloballocatorfilters.h",
|
||||||
"clanghighlightingresultreporter.cpp",
|
"clanghighlightingresultreporter.cpp",
|
||||||
"clanghighlightingresultreporter.h",
|
"clanghighlightingresultreporter.h",
|
||||||
"clanghoverhandler.cpp",
|
"clanghoverhandler.cpp",
|
||||||
|
@@ -5,6 +5,7 @@ QTC_LIB_DEPENDS += \
|
|||||||
QTC_PLUGIN_DEPENDS += \
|
QTC_PLUGIN_DEPENDS += \
|
||||||
coreplugin \
|
coreplugin \
|
||||||
cpptools \
|
cpptools \
|
||||||
|
languageclient \
|
||||||
texteditor
|
texteditor
|
||||||
QTC_TEST_DEPENDS += \
|
QTC_TEST_DEPENDS += \
|
||||||
cppeditor \
|
cppeditor \
|
||||||
|
@@ -77,7 +77,8 @@ void ClangCodeModelPlugin::generateCompilationDB()
|
|||||||
|
|
||||||
QFuture<GenerateCompilationDbResult> task
|
QFuture<GenerateCompilationDbResult> task
|
||||||
= QtConcurrent::run(&Internal::generateCompilationDB,
|
= QtConcurrent::run(&Internal::generateCompilationDB,
|
||||||
CppModelManager::instance()->projectInfo(target->project()));
|
CppModelManager::instance()->projectInfo(target->project()),
|
||||||
|
CompilationDbPurpose::Project);
|
||||||
Core::ProgressManager::addTask(task, tr("Generating Compilation DB"), "generate compilation db");
|
Core::ProgressManager::addTask(task, tr("Generating Compilation DB"), "generate compilation db");
|
||||||
m_generatorWatcher.setFuture(task);
|
m_generatorWatcher.setFuture(task);
|
||||||
}
|
}
|
||||||
|
@@ -31,7 +31,6 @@
|
|||||||
#include "clangfixitoperationsextractor.h"
|
#include "clangfixitoperationsextractor.h"
|
||||||
#include "clangmodelmanagersupport.h"
|
#include "clangmodelmanagersupport.h"
|
||||||
#include "clanghighlightingresultreporter.h"
|
#include "clanghighlightingresultreporter.h"
|
||||||
#include "clangprojectsettings.h"
|
|
||||||
#include "clangutils.h"
|
#include "clangutils.h"
|
||||||
|
|
||||||
#include <diagnosticcontainer.h>
|
#include <diagnosticcontainer.h>
|
||||||
@@ -66,12 +65,6 @@
|
|||||||
namespace ClangCodeModel {
|
namespace ClangCodeModel {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project)
|
|
||||||
{
|
|
||||||
QTC_CHECK(project);
|
|
||||||
return ClangModelManagerSupport::instance()->projectSettings(project);
|
|
||||||
}
|
|
||||||
|
|
||||||
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
ClangEditorDocumentProcessor::ClangEditorDocumentProcessor(
|
||||||
BackendCommunicator &communicator,
|
BackendCommunicator &communicator,
|
||||||
TextEditor::TextDocument *document)
|
TextEditor::TextDocument *document)
|
||||||
@@ -439,123 +432,6 @@ void ClangEditorDocumentProcessor::onParserFinished()
|
|||||||
updateBackendProjectPartAndDocument();
|
updateBackendProjectPartAndDocument();
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
|
||||||
// TODO: Can we marry this with CompilerOptionsBuilder?
|
|
||||||
class FileOptionsBuilder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FileOptionsBuilder(const QString &filePath, CppTools::ProjectPart &projectPart)
|
|
||||||
: m_filePath(filePath)
|
|
||||||
, m_projectPart(projectPart)
|
|
||||||
, m_builder(projectPart)
|
|
||||||
{
|
|
||||||
// Determine the driver mode from toolchain and flags.
|
|
||||||
m_builder.evaluateCompilerFlags();
|
|
||||||
m_isClMode = m_builder.isClStyle();
|
|
||||||
|
|
||||||
addLanguageOptions();
|
|
||||||
addGlobalDiagnosticOptions(); // Before addDiagnosticOptions() so users still can overwrite.
|
|
||||||
addDiagnosticOptions();
|
|
||||||
addGlobalOptions();
|
|
||||||
addPrecompiledHeaderOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
const QStringList &options() const { return m_options; }
|
|
||||||
const ::Utils::Id &diagnosticConfigId() const { return m_diagnosticConfigId; }
|
|
||||||
CppTools::UseBuildSystemWarnings useBuildSystemWarnings() const
|
|
||||||
{
|
|
||||||
return m_useBuildSystemWarnings;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
void addLanguageOptions()
|
|
||||||
{
|
|
||||||
// Determine file kind with respect to ambiguous headers.
|
|
||||||
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(m_filePath);
|
|
||||||
if (fileKind == CppTools::ProjectFile::AmbiguousHeader) {
|
|
||||||
fileKind = m_projectPart.languageVersion <= ::Utils::LanguageVersion::LatestC
|
|
||||||
? CppTools::ProjectFile::CHeader
|
|
||||||
: CppTools::ProjectFile::CXXHeader;
|
|
||||||
}
|
|
||||||
|
|
||||||
m_builder.reset();
|
|
||||||
m_builder.updateFileLanguage(fileKind);
|
|
||||||
|
|
||||||
m_options.append(m_builder.options());
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDiagnosticOptions()
|
|
||||||
{
|
|
||||||
if (m_projectPart.project) {
|
|
||||||
ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project);
|
|
||||||
if (!projectSettings.useGlobalConfig()) {
|
|
||||||
const ::Utils::Id warningConfigId = projectSettings.warningConfigId();
|
|
||||||
const CppTools::ClangDiagnosticConfigsModel configsModel
|
|
||||||
= CppTools::diagnosticConfigsModel();
|
|
||||||
if (configsModel.hasConfigWithId(warningConfigId)) {
|
|
||||||
addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig());
|
|
||||||
}
|
|
||||||
|
|
||||||
void addDiagnosticOptionsForConfig(const CppTools::ClangDiagnosticConfig &diagnosticConfig)
|
|
||||||
{
|
|
||||||
m_diagnosticConfigId = diagnosticConfig.id();
|
|
||||||
m_useBuildSystemWarnings = diagnosticConfig.useBuildSystemWarnings()
|
|
||||||
? CppTools::UseBuildSystemWarnings::Yes
|
|
||||||
: CppTools::UseBuildSystemWarnings::No;
|
|
||||||
|
|
||||||
const QStringList options = m_isClMode
|
|
||||||
? CppTools::clangArgsForCl(diagnosticConfig.clangOptions())
|
|
||||||
: diagnosticConfig.clangOptions();
|
|
||||||
m_options.append(options);
|
|
||||||
}
|
|
||||||
|
|
||||||
void addGlobalDiagnosticOptions()
|
|
||||||
{
|
|
||||||
m_options += CppTools::ClangDiagnosticConfigsModel::globalDiagnosticOptions();
|
|
||||||
}
|
|
||||||
|
|
||||||
void addGlobalOptions()
|
|
||||||
{
|
|
||||||
if (!m_projectPart.project)
|
|
||||||
m_options.append(ClangProjectSettings::globalCommandLineOptions());
|
|
||||||
else
|
|
||||||
m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions());
|
|
||||||
}
|
|
||||||
|
|
||||||
void addPrecompiledHeaderOptions()
|
|
||||||
{
|
|
||||||
using namespace CppTools;
|
|
||||||
|
|
||||||
if (getPchUsage() == UsePrecompiledHeaders::No)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (m_projectPart.precompiledHeaders.contains(m_filePath))
|
|
||||||
return;
|
|
||||||
|
|
||||||
m_builder.reset();
|
|
||||||
m_builder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes);
|
|
||||||
|
|
||||||
m_options.append(m_builder.options());
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const QString &m_filePath;
|
|
||||||
const CppTools::ProjectPart &m_projectPart;
|
|
||||||
|
|
||||||
::Utils::Id m_diagnosticConfigId;
|
|
||||||
CppTools::UseBuildSystemWarnings m_useBuildSystemWarnings = CppTools::UseBuildSystemWarnings::No;
|
|
||||||
CppTools::CompilerOptionsBuilder m_builder;
|
|
||||||
bool m_isClMode = false;
|
|
||||||
QStringList m_options;
|
|
||||||
};
|
|
||||||
} // namespace
|
|
||||||
|
|
||||||
void ClangEditorDocumentProcessor::updateBackendDocument(CppTools::ProjectPart &projectPart)
|
void ClangEditorDocumentProcessor::updateBackendDocument(CppTools::ProjectPart &projectPart)
|
||||||
{
|
{
|
||||||
// On registration we send the document content immediately as an unsaved
|
// On registration we send the document content immediately as an unsaved
|
||||||
@@ -572,17 +448,11 @@ void ClangEditorDocumentProcessor::updateBackendDocument(CppTools::ProjectPart &
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const FileOptionsBuilder fileOptions(filePath(), projectPart);
|
const auto clangOptions = createClangOptions(projectPart, filePath());
|
||||||
m_diagnosticConfigId = fileOptions.diagnosticConfigId();
|
m_diagnosticConfigId = clangOptions.first;
|
||||||
|
|
||||||
const QStringList projectPartOptions = createClangOptions(
|
|
||||||
projectPart, fileOptions.useBuildSystemWarnings(),
|
|
||||||
CppTools::ProjectFile::Unsupported); // No language option as FileOptionsBuilder adds it.
|
|
||||||
|
|
||||||
const QStringList compilationArguments = projectPartOptions + fileOptions.options();
|
|
||||||
|
|
||||||
m_communicator.documentsOpened(
|
m_communicator.documentsOpened(
|
||||||
{fileContainerWithOptionsAndDocumentContent(compilationArguments, projectPart.headerPaths)});
|
{fileContainerWithOptionsAndDocumentContent(clangOptions.second, projectPart.headerPaths)});
|
||||||
setLastSentDocumentRevision(filePath(), revision());
|
setLastSentDocumentRevision(filePath(), revision());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
213
src/plugins/clangcodemodel/clanggloballocatorfilters.cpp
Normal file
213
src/plugins/clangcodemodel/clanggloballocatorfilters.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#include "clanggloballocatorfilters.h"
|
||||||
|
|
||||||
|
#include "clangmodelmanagersupport.h"
|
||||||
|
|
||||||
|
#include <cpptools/cppclassesfilter.h>
|
||||||
|
#include <cpptools/cppfunctionsfilter.h>
|
||||||
|
#include <cpptools/cppmodelmanager.h>
|
||||||
|
#include <cpptools/cpptoolsconstants.h>
|
||||||
|
#include <cpptools/indexitem.h>
|
||||||
|
#include <languageclient/locatorfilter.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
|
#include <utils/link.h>
|
||||||
|
|
||||||
|
#include <set>
|
||||||
|
#include <tuple>
|
||||||
|
|
||||||
|
namespace ClangCodeModel {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class CppLocatorFilter : public CppTools::CppLocatorFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CppLocatorFilter()
|
||||||
|
: CppTools::CppLocatorFilter(CppTools::CppModelManager::instance()->locatorData())
|
||||||
|
{
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LspWorkspaceFilter : public LanguageClient::WorkspaceLocatorFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LspWorkspaceFilter()
|
||||||
|
{
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class CppClassesFilter : public CppTools::CppClassesFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CppClassesFilter()
|
||||||
|
: CppTools::CppClassesFilter(CppTools::CppModelManager::instance()->locatorData())
|
||||||
|
{
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LspClassesFilter : public LanguageClient::WorkspaceClassLocatorFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LspClassesFilter() {
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class CppFunctionsFilter : public CppTools::CppFunctionsFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CppFunctionsFilter()
|
||||||
|
: CppTools::CppFunctionsFilter(CppTools::CppModelManager::instance()->locatorData())
|
||||||
|
{
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class LspFunctionsFilter : public LanguageClient::WorkspaceMethodLocatorFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
LspFunctionsFilter()
|
||||||
|
{
|
||||||
|
setId({});
|
||||||
|
setDisplayName({});
|
||||||
|
setDefaultShortcutString({});
|
||||||
|
setEnabled(false);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
ClangGlobalSymbolFilter::ClangGlobalSymbolFilter()
|
||||||
|
: ClangGlobalSymbolFilter(new CppLocatorFilter, new LspWorkspaceFilter)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangGlobalSymbolFilter::ClangGlobalSymbolFilter(ILocatorFilter *cppFilter,
|
||||||
|
ILocatorFilter *lspFilter)
|
||||||
|
: m_cppFilter(cppFilter), m_lspFilter(lspFilter)
|
||||||
|
{
|
||||||
|
setId(CppTools::Constants::LOCATOR_FILTER_ID);
|
||||||
|
setDisplayName(CppTools::Constants::LOCATOR_FILTER_DISPLAY_NAME);
|
||||||
|
setDefaultShortcutString(":");
|
||||||
|
setDefaultIncludedByDefault(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangGlobalSymbolFilter::~ClangGlobalSymbolFilter()
|
||||||
|
{
|
||||||
|
delete m_cppFilter;
|
||||||
|
delete m_lspFilter;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangGlobalSymbolFilter::prepareSearch(const QString &entry)
|
||||||
|
{
|
||||||
|
m_cppFilter->prepareSearch(entry);
|
||||||
|
QVector<LanguageClient::Client *> clients;
|
||||||
|
for (ProjectExplorer::Project * const project : ProjectExplorer::SessionManager::projects()) {
|
||||||
|
LanguageClient::Client * const client
|
||||||
|
= ClangModelManagerSupport::instance()->clientForProject(project);
|
||||||
|
if (client)
|
||||||
|
clients << client;
|
||||||
|
}
|
||||||
|
if (!clients.isEmpty()) {
|
||||||
|
static_cast<LanguageClient::WorkspaceLocatorFilter *>(m_lspFilter)
|
||||||
|
->prepareSearch(entry, clients);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
QList<Core::LocatorFilterEntry> ClangGlobalSymbolFilter::matchesFor(
|
||||||
|
QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
|
||||||
|
{
|
||||||
|
QList<Core::LocatorFilterEntry> matches = m_cppFilter->matchesFor(future, entry);
|
||||||
|
const QList<Core::LocatorFilterEntry> lspMatches = m_lspFilter->matchesFor(future, entry);
|
||||||
|
if (!lspMatches.isEmpty()) {
|
||||||
|
std::set<std::tuple<QString, int, int>> locations;
|
||||||
|
for (const auto &entry : qAsConst(matches)) {
|
||||||
|
const CppTools::IndexItem::Ptr item
|
||||||
|
= qvariant_cast<CppTools::IndexItem::Ptr>(entry.internalData);
|
||||||
|
locations.insert(std::make_tuple(item->fileName(), item->line(), item->column()));
|
||||||
|
}
|
||||||
|
for (const auto &entry : lspMatches) {
|
||||||
|
if (!entry.internalData.canConvert<Utils::Link>())
|
||||||
|
continue;
|
||||||
|
const auto link = qvariant_cast<Utils::Link>(entry.internalData);
|
||||||
|
if (locations.find(std::make_tuple(link.targetFileName, link.targetLine,
|
||||||
|
link.targetColumn)) == locations.cend()) {
|
||||||
|
matches << entry; // TODO: Insert sorted?
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return matches;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClangGlobalSymbolFilter::accept(Core::LocatorFilterEntry selection, QString *newText,
|
||||||
|
int *selectionStart, int *selectionLength) const
|
||||||
|
{
|
||||||
|
if (qvariant_cast<CppTools::IndexItem::Ptr>(selection.internalData))
|
||||||
|
m_cppFilter->accept(selection, newText, selectionStart, selectionLength);
|
||||||
|
else
|
||||||
|
m_lspFilter->accept(selection, newText, selectionStart, selectionLength);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
ClangClassesFilter::ClangClassesFilter()
|
||||||
|
: ClangGlobalSymbolFilter(new CppClassesFilter, new LspClassesFilter)
|
||||||
|
{
|
||||||
|
setId(CppTools::Constants::CLASSES_FILTER_ID);
|
||||||
|
setDisplayName(CppTools::Constants::CLASSES_FILTER_DISPLAY_NAME);
|
||||||
|
setDefaultShortcutString("c");
|
||||||
|
setDefaultIncludedByDefault(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
ClangFunctionsFilter::ClangFunctionsFilter()
|
||||||
|
: ClangGlobalSymbolFilter(new CppFunctionsFilter, new LspFunctionsFilter)
|
||||||
|
{
|
||||||
|
setId(CppTools::Constants::FUNCTIONS_FILTER_ID);
|
||||||
|
setDisplayName(CppTools::Constants::FUNCTIONS_FILTER_DISPLAY_NAME);
|
||||||
|
setDefaultShortcutString("m");
|
||||||
|
setDefaultIncludedByDefault(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangCodeModel
|
64
src/plugins/clangcodemodel/clanggloballocatorfilters.h
Normal file
64
src/plugins/clangcodemodel/clanggloballocatorfilters.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
/****************************************************************************
|
||||||
|
**
|
||||||
|
** Copyright (C) 2021 The Qt Company Ltd.
|
||||||
|
** Contact: https://www.qt.io/licensing/
|
||||||
|
**
|
||||||
|
** This file is part of Qt Creator.
|
||||||
|
**
|
||||||
|
** Commercial License Usage
|
||||||
|
** Licensees holding valid commercial Qt licenses may use this file in
|
||||||
|
** accordance with the commercial license agreement provided with the
|
||||||
|
** Software or, alternatively, in accordance with the terms contained in
|
||||||
|
** a written agreement between you and The Qt Company. For licensing terms
|
||||||
|
** and conditions see https://www.qt.io/terms-conditions. For further
|
||||||
|
** information use the contact form at https://www.qt.io/contact-us.
|
||||||
|
**
|
||||||
|
** GNU General Public License Usage
|
||||||
|
** Alternatively, this file may be used under the terms of the GNU
|
||||||
|
** General Public License version 3 as published by the Free Software
|
||||||
|
** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
|
||||||
|
** included in the packaging of this file. Please review the following
|
||||||
|
** information to ensure the GNU General Public License requirements will
|
||||||
|
** be met: https://www.gnu.org/licenses/gpl-3.0.html.
|
||||||
|
**
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <coreplugin/locator/ilocatorfilter.h>
|
||||||
|
|
||||||
|
namespace ClangCodeModel {
|
||||||
|
namespace Internal {
|
||||||
|
|
||||||
|
class ClangGlobalSymbolFilter : public Core::ILocatorFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClangGlobalSymbolFilter();
|
||||||
|
ClangGlobalSymbolFilter(Core::ILocatorFilter *cppFilter, Core::ILocatorFilter *lspFilter);
|
||||||
|
~ClangGlobalSymbolFilter() override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
void prepareSearch(const QString &entry) override;
|
||||||
|
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
|
||||||
|
const QString &entry) override;
|
||||||
|
void accept(Core::LocatorFilterEntry selection, QString *newText,
|
||||||
|
int *selectionStart, int *selectionLength) const override;
|
||||||
|
|
||||||
|
Core::ILocatorFilter * const m_cppFilter;
|
||||||
|
Core::ILocatorFilter * const m_lspFilter;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClangClassesFilter : public ClangGlobalSymbolFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClangClassesFilter();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ClangFunctionsFilter : public ClangGlobalSymbolFilter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ClangFunctionsFilter();
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Internal
|
||||||
|
} // namespace ClangCodeModel
|
@@ -33,9 +33,12 @@
|
|||||||
#include "clangprojectsettings.h"
|
#include "clangprojectsettings.h"
|
||||||
#include "clangrefactoringengine.h"
|
#include "clangrefactoringengine.h"
|
||||||
#include "clangcurrentdocumentfilter.h"
|
#include "clangcurrentdocumentfilter.h"
|
||||||
|
#include "clanggloballocatorfilters.h"
|
||||||
#include "clangoverviewmodel.h"
|
#include "clangoverviewmodel.h"
|
||||||
|
|
||||||
#include <coreplugin/editormanager/editormanager.h>
|
#include <coreplugin/editormanager/editormanager.h>
|
||||||
|
#include <coreplugin/icore.h>
|
||||||
|
#include <coreplugin/messagemanager.h>
|
||||||
|
|
||||||
#include <cpptools/cppcodemodelsettings.h>
|
#include <cpptools/cppcodemodelsettings.h>
|
||||||
#include <cpptools/cppfollowsymbolundercursor.h>
|
#include <cpptools/cppfollowsymbolundercursor.h>
|
||||||
@@ -44,23 +47,34 @@
|
|||||||
#include <cpptools/editordocumenthandle.h>
|
#include <cpptools/editordocumenthandle.h>
|
||||||
#include <cpptools/projectinfo.h>
|
#include <cpptools/projectinfo.h>
|
||||||
|
|
||||||
|
#include <languageclient/client.h>
|
||||||
|
#include <languageclient/languageclientinterface.h>
|
||||||
|
#include <languageclient/languageclientmanager.h>
|
||||||
|
|
||||||
#include <texteditor/quickfix.h>
|
#include <texteditor/quickfix.h>
|
||||||
|
|
||||||
|
#include <projectexplorer/buildconfiguration.h>
|
||||||
#include <projectexplorer/project.h>
|
#include <projectexplorer/project.h>
|
||||||
|
#include <projectexplorer/projectnodes.h>
|
||||||
#include <projectexplorer/session.h>
|
#include <projectexplorer/session.h>
|
||||||
|
#include <projectexplorer/target.h>
|
||||||
|
|
||||||
#include <clangsupport/filecontainer.h>
|
#include <clangsupport/filecontainer.h>
|
||||||
#include <utils/algorithm.h>
|
#include <utils/algorithm.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
#include <utils/runextensions.h>
|
||||||
|
|
||||||
#include <QApplication>
|
#include <QApplication>
|
||||||
|
#include <QFile>
|
||||||
#include <QMenu>
|
#include <QMenu>
|
||||||
#include <QTextBlock>
|
#include <QTextBlock>
|
||||||
#include <QTimer>
|
#include <QTimer>
|
||||||
|
|
||||||
using namespace ClangCodeModel;
|
using namespace ClangCodeModel;
|
||||||
using namespace ClangCodeModel::Internal;
|
using namespace ClangCodeModel::Internal;
|
||||||
|
using namespace LanguageClient;
|
||||||
|
|
||||||
|
static Q_LOGGING_CATEGORY(clangdLog, "qtc.clangcodemodel.clangd", QtWarningMsg);
|
||||||
static ClangModelManagerSupport *m_instance = nullptr;
|
static ClangModelManagerSupport *m_instance = nullptr;
|
||||||
|
|
||||||
static CppTools::CppModelManager *cppModelManager()
|
static CppTools::CppModelManager *cppModelManager()
|
||||||
@@ -79,6 +93,9 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
|
|
||||||
CppTools::CppModelManager::instance()->setCurrentDocumentFilter(
|
CppTools::CppModelManager::instance()->setCurrentDocumentFilter(
|
||||||
std::make_unique<ClangCurrentDocumentFilter>());
|
std::make_unique<ClangCurrentDocumentFilter>());
|
||||||
|
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
|
||||||
|
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
|
||||||
|
cppModelManager()->setFunctionsFilter(std::make_unique<ClangFunctionsFilter>());
|
||||||
|
|
||||||
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
Core::EditorManager *editorManager = Core::EditorManager::instance();
|
||||||
connect(editorManager, &Core::EditorManager::editorOpened,
|
connect(editorManager, &Core::EditorManager::editorOpened,
|
||||||
@@ -104,9 +121,14 @@ ClangModelManagerSupport::ClangModelManagerSupport()
|
|||||||
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
connect(sessionManager, &ProjectExplorer::SessionManager::aboutToRemoveProject,
|
||||||
this, &ClangModelManagerSupport::onAboutToRemoveProject);
|
this, &ClangModelManagerSupport::onAboutToRemoveProject);
|
||||||
|
|
||||||
|
CppTools::CppCodeModelSettings::setDefaultClangdPath(Utils::FilePath::fromString(
|
||||||
|
Core::ICore::clangdExecutable(CLANG_BINDIR)));
|
||||||
CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings();
|
CppTools::CppCodeModelSettings *settings = CppTools::codeModelSettings();
|
||||||
connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
|
connect(settings, &CppTools::CppCodeModelSettings::clangDiagnosticConfigsInvalidated,
|
||||||
this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated);
|
this, &ClangModelManagerSupport::onDiagnosticConfigsInvalidated);
|
||||||
|
|
||||||
|
// TODO: Enable this once we do document-level stuff with clangd (highlighting etc)
|
||||||
|
// createClient(nullptr, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
ClangModelManagerSupport::~ClangModelManagerSupport()
|
ClangModelManagerSupport::~ClangModelManagerSupport()
|
||||||
@@ -220,6 +242,136 @@ void ClangModelManagerSupport::connectToWidgetsMarkContextMenuRequested(QWidget
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static QString clientName() { return "ccm-clangd"; }
|
||||||
|
|
||||||
|
void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *project,
|
||||||
|
const CppTools::ProjectInfo &projectInfo)
|
||||||
|
{
|
||||||
|
if (!CppTools::codeModelSettings()->useClangd())
|
||||||
|
return;
|
||||||
|
const auto getJsonDbDir = [project] {
|
||||||
|
if (const ProjectExplorer::Target * const target = project->activeTarget()) {
|
||||||
|
if (const ProjectExplorer::BuildConfiguration * const bc
|
||||||
|
= target->activeBuildConfiguration()) {
|
||||||
|
return bc->buildDirectory();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Utils::FilePath();
|
||||||
|
};
|
||||||
|
|
||||||
|
const Utils::FilePath jsonDbDir = getJsonDbDir();
|
||||||
|
if (jsonDbDir.isEmpty())
|
||||||
|
return;
|
||||||
|
const auto generatorWatcher = new QFutureWatcher<GenerateCompilationDbResult>;
|
||||||
|
connect(generatorWatcher, &QFutureWatcher<GenerateCompilationDbResult>::finished,
|
||||||
|
[this, project, projectInfo, getJsonDbDir, jsonDbDir, generatorWatcher] {
|
||||||
|
generatorWatcher->deleteLater();
|
||||||
|
if (!CppTools::codeModelSettings()->useClangd())
|
||||||
|
return;
|
||||||
|
if (!ProjectExplorer::SessionManager::hasProject(project))
|
||||||
|
return;
|
||||||
|
if (cppModelManager()->projectInfo(project) != projectInfo)
|
||||||
|
return;
|
||||||
|
if (getJsonDbDir() != jsonDbDir)
|
||||||
|
return;
|
||||||
|
const GenerateCompilationDbResult result = generatorWatcher->result();
|
||||||
|
if (!result.error.isEmpty()) {
|
||||||
|
Core::MessageManager::writeDisrupting(
|
||||||
|
tr("Cannot use clangd: Failed to generate compilation database:\n%1")
|
||||||
|
.arg(result.error));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (Client * const oldClient = clientForProject(project))
|
||||||
|
LanguageClientManager::shutdownClient(oldClient);
|
||||||
|
Client * const client = createClient(project, jsonDbDir);
|
||||||
|
connect(client, &Client::initialized, this, [client, project, projectInfo, jsonDbDir] {
|
||||||
|
using namespace ProjectExplorer;
|
||||||
|
if (!CppTools::codeModelSettings()->useClangd())
|
||||||
|
return;
|
||||||
|
if (!SessionManager::hasProject(project))
|
||||||
|
return;
|
||||||
|
if (cppModelManager()->projectInfo(project) != projectInfo)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// TODO: We'd like to add all open editor documents for the project to the client here,
|
||||||
|
// but there doesn't seem to be such an interface.
|
||||||
|
|
||||||
|
// clangd oddity: Background indexing only starts after opening a random file.
|
||||||
|
// TODO: changes to the compilation db do not seem to trigger re-indexing.
|
||||||
|
// How to force it?
|
||||||
|
ProjectNode * const rootNode = project->rootProjectNode();
|
||||||
|
if (!rootNode)
|
||||||
|
return;
|
||||||
|
const Node * const cxxNode = rootNode->findNode([](Node *n) {
|
||||||
|
const FileNode * const fileNode = n->asFileNode();
|
||||||
|
return fileNode && (fileNode->fileType() == FileType::Source
|
||||||
|
|| fileNode->fileType() == FileType::Header)
|
||||||
|
&& fileNode->filePath().exists();
|
||||||
|
});
|
||||||
|
if (!cxxNode)
|
||||||
|
return;
|
||||||
|
|
||||||
|
QFile cxxFile(cxxNode->filePath().toString());
|
||||||
|
if (!cxxFile.open(QIODevice::ReadOnly))
|
||||||
|
return;
|
||||||
|
using namespace LanguageServerProtocol;
|
||||||
|
TextDocumentItem item;
|
||||||
|
item.setLanguageId("text/x-c++src");
|
||||||
|
item.setUri(DocumentUri::fromFilePath(cxxNode->filePath()));
|
||||||
|
item.setText(QString::fromUtf8(cxxFile.readAll()));
|
||||||
|
item.setVersion(0);
|
||||||
|
client->sendContent(DidOpenTextDocumentNotification(DidOpenTextDocumentParams(item)));
|
||||||
|
client->sendContent(DidCloseTextDocumentNotification(DidCloseTextDocumentParams(
|
||||||
|
TextDocumentIdentifier{item.uri()})));
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
generatorWatcher->setFuture(Utils::runAsync(&Internal::generateCompilationDB, projectInfo,
|
||||||
|
CompilationDbPurpose::CodeModel));
|
||||||
|
}
|
||||||
|
|
||||||
|
LanguageClient::Client *ClangModelManagerSupport::clientForProject(
|
||||||
|
const ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
const QList<Client *> clients = Utils::filtered(
|
||||||
|
LanguageClientManager::clientsForProject(project),
|
||||||
|
[](const LanguageClient::Client *c) {
|
||||||
|
return c->name().startsWith(clientName())
|
||||||
|
&& c->state() != Client::ShutdownRequested
|
||||||
|
&& c->state() != Client::Shutdown;
|
||||||
|
});
|
||||||
|
QTC_CHECK(clients.size() <= 1);
|
||||||
|
return clients.empty() ? nullptr : clients.first();
|
||||||
|
}
|
||||||
|
|
||||||
|
Client *ClangModelManagerSupport::createClient(ProjectExplorer::Project *project,
|
||||||
|
const Utils::FilePath &jsonDbDir)
|
||||||
|
{
|
||||||
|
QString clangdArgs = "--index --background-index --limit-results=0";
|
||||||
|
if (!jsonDbDir.isEmpty())
|
||||||
|
clangdArgs += " --compile-commands-dir=" + jsonDbDir.toString();
|
||||||
|
if (clangdLog().isDebugEnabled())
|
||||||
|
clangdArgs += " --log=verbose --pretty";
|
||||||
|
const auto clientInterface = new StdIOClientInterface;
|
||||||
|
clientInterface->setExecutable(CppTools::codeModelSettings()->clangdFilePath().toString());
|
||||||
|
clientInterface->setArguments(clangdArgs);
|
||||||
|
const auto client = new Client(clientInterface);
|
||||||
|
client->setName(clientName());
|
||||||
|
LanguageFilter langFilter;
|
||||||
|
langFilter.mimeTypes = QStringList{"text/x-chdr", "text/x-c++hdr", "text/x-c++src",
|
||||||
|
"text/x-objc++src", "text/x-objcsrc"};
|
||||||
|
client->setSupportedLanguage(langFilter);
|
||||||
|
LanguageServerProtocol::ClientCapabilities caps = Client::defaultClientCapabilities();
|
||||||
|
caps.clearExperimental();
|
||||||
|
caps.clearTextDocument();
|
||||||
|
client->setClientCapabilities(caps);
|
||||||
|
client->setLocatorsEnabled(false);
|
||||||
|
client->setDocumentActionsEnabled(false);
|
||||||
|
client->setCurrentProject(project);
|
||||||
|
client->start();
|
||||||
|
return client;
|
||||||
|
}
|
||||||
|
|
||||||
void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
|
void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(editor, return);
|
QTC_ASSERT(editor, return);
|
||||||
@@ -232,6 +384,11 @@ void ClangModelManagerSupport::onEditorOpened(Core::IEditor *editor)
|
|||||||
connectToWidgetsMarkContextMenuRequested(editor->widget());
|
connectToWidgetsMarkContextMenuRequested(editor->widget());
|
||||||
|
|
||||||
// TODO: Ensure that not fully loaded documents are updated?
|
// TODO: Ensure that not fully loaded documents are updated?
|
||||||
|
|
||||||
|
ProjectExplorer::Project * const project
|
||||||
|
= ProjectExplorer::SessionManager::projectForFile(document->filePath());
|
||||||
|
if (Client * const client = clientForProject(project))
|
||||||
|
client->openDocument(textDocument);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -420,6 +577,8 @@ void ClangModelManagerSupport::onProjectPartsUpdated(ProjectExplorer::Project *p
|
|||||||
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
|
const CppTools::ProjectInfo projectInfo = cppModelManager()->projectInfo(project);
|
||||||
QTC_ASSERT(projectInfo.isValid(), return);
|
QTC_ASSERT(projectInfo.isValid(), return);
|
||||||
|
|
||||||
|
updateLanguageClient(project, projectInfo);
|
||||||
|
|
||||||
QStringList projectPartIds;
|
QStringList projectPartIds;
|
||||||
for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo.projectParts())
|
for (const CppTools::ProjectPart::Ptr &projectPart : projectInfo.projectParts())
|
||||||
projectPartIds.append(projectPart->id());
|
projectPartIds.append(projectPart->id());
|
||||||
|
@@ -47,6 +47,8 @@ class FollowSymbolInterface;
|
|||||||
class RefactoringEngineInterface;
|
class RefactoringEngineInterface;
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
|
||||||
|
namespace LanguageClient { class Client; }
|
||||||
|
|
||||||
namespace ClangCodeModel {
|
namespace ClangCodeModel {
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
@@ -77,6 +79,8 @@ public:
|
|||||||
|
|
||||||
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
|
ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const;
|
||||||
|
|
||||||
|
LanguageClient::Client *clientForProject(const ProjectExplorer::Project *project);
|
||||||
|
|
||||||
static ClangModelManagerSupport *instance();
|
static ClangModelManagerSupport *instance();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
@@ -118,6 +122,11 @@ private:
|
|||||||
void connectToTextDocumentContentsChangedForUnsavedFile(TextEditor::TextDocument *textDocument);
|
void connectToTextDocumentContentsChangedForUnsavedFile(TextEditor::TextDocument *textDocument);
|
||||||
void connectToWidgetsMarkContextMenuRequested(QWidget *editorWidget);
|
void connectToWidgetsMarkContextMenuRequested(QWidget *editorWidget);
|
||||||
|
|
||||||
|
void updateLanguageClient(ProjectExplorer::Project *project,
|
||||||
|
const CppTools::ProjectInfo &projectInfo);
|
||||||
|
LanguageClient::Client *createClient(ProjectExplorer::Project *project,
|
||||||
|
const Utils::FilePath &jsonDbDir);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
|
UiHeaderOnDiskManager m_uiHeaderOnDiskManager;
|
||||||
BackendCommunicator m_communicator;
|
BackendCommunicator m_communicator;
|
||||||
|
@@ -26,6 +26,12 @@
|
|||||||
#include "clangrefactoringengine.h"
|
#include "clangrefactoringengine.h"
|
||||||
#include "clangeditordocumentprocessor.h"
|
#include "clangeditordocumentprocessor.h"
|
||||||
|
|
||||||
|
#include "clangmodelmanagersupport.h"
|
||||||
|
|
||||||
|
#include <cpptools/cppmodelmanager.h>
|
||||||
|
#include <languageclient/client.h>
|
||||||
|
#include <languageclient/languageclientsymbolsupport.h>
|
||||||
|
#include <projectexplorer/session.h>
|
||||||
#include <utils/textutils.h>
|
#include <utils/textutils.h>
|
||||||
#include <utils/qtcassert.h>
|
#include <utils/qtcassert.h>
|
||||||
|
|
||||||
@@ -80,5 +86,27 @@ void RefactoringEngine::startLocalRenaming(const CppTools::CursorInEditor &data,
|
|||||||
m_watcher->setFuture(cursorFuture);
|
m_watcher->setFuture(cursorFuture);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void RefactoringEngine::findUsages(const CppTools::CursorInEditor &cursor,
|
||||||
|
CppTools::UsagesCallback &&callback) const
|
||||||
|
{
|
||||||
|
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
|
||||||
|
CppTools::CppModelManager::builtinRefactoringEngine()
|
||||||
|
->findUsages(cursor, std::move(callback));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// TODO: We want to keep our "access type info" feature.
|
||||||
|
// Check whether we can support it using clang 12's textDocument/ast request
|
||||||
|
if (!client->documentOpen(cursor.textDocument()))
|
||||||
|
client->openDocument(cursor.textDocument()); // TODO: Just a workaround
|
||||||
|
client->symbolSupport().findUsages(cursor.textDocument(), cursor.cursor());
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace ClangCodeModel
|
} // namespace ClangCodeModel
|
||||||
|
@@ -46,7 +46,8 @@ public:
|
|||||||
RenameCallback &&renameSymbolsCallback) override;
|
RenameCallback &&renameSymbolsCallback) override;
|
||||||
void globalRename(const CppTools::CursorInEditor &, CppTools::UsagesCallback &&,
|
void globalRename(const CppTools::CursorInEditor &, CppTools::UsagesCallback &&,
|
||||||
const QString &) override {}
|
const QString &) override {}
|
||||||
void findUsages(const CppTools::CursorInEditor &, CppTools::UsagesCallback &&) const override {}
|
void findUsages(const CppTools::CursorInEditor &cursor,
|
||||||
|
CppTools::UsagesCallback &&callback) const override;
|
||||||
void globalFollowSymbol(const CppTools::CursorInEditor &,
|
void globalFollowSymbol(const CppTools::CursorInEditor &,
|
||||||
::Utils::ProcessLinkCallback &&,
|
::Utils::ProcessLinkCallback &&,
|
||||||
const CPlusPlus::Snapshot &,
|
const CPlusPlus::Snapshot &,
|
||||||
|
@@ -27,6 +27,7 @@
|
|||||||
|
|
||||||
#include "clangeditordocumentprocessor.h"
|
#include "clangeditordocumentprocessor.h"
|
||||||
#include "clangmodelmanagersupport.h"
|
#include "clangmodelmanagersupport.h"
|
||||||
|
#include "clangprojectsettings.h"
|
||||||
|
|
||||||
#include <clangsupport/tokeninfocontainer.h>
|
#include <clangsupport/tokeninfocontainer.h>
|
||||||
|
|
||||||
@@ -104,14 +105,6 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
QStringList createClangOptions(const ProjectPart &projectPart,
|
|
||||||
UseBuildSystemWarnings useBuildSystemWarnings,
|
|
||||||
ProjectFile::Kind fileKind)
|
|
||||||
{
|
|
||||||
return LibClangOptionsBuilder(projectPart, useBuildSystemWarnings)
|
|
||||||
.build(fileKind, UsePrecompiledHeaders::No);
|
|
||||||
}
|
|
||||||
|
|
||||||
ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
ProjectPart::Ptr projectPartForFile(const QString &filePath)
|
||||||
{
|
{
|
||||||
if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath))
|
if (const auto parser = CppTools::BaseEditorDocumentParser::get(filePath))
|
||||||
@@ -354,11 +347,15 @@ static QStringList projectPartArguments(const ProjectPart &projectPart)
|
|||||||
static QJsonObject createFileObject(const FilePath &buildDir,
|
static QJsonObject createFileObject(const FilePath &buildDir,
|
||||||
const QStringList &arguments,
|
const QStringList &arguments,
|
||||||
const ProjectPart &projectPart,
|
const ProjectPart &projectPart,
|
||||||
const ProjectFile &projFile)
|
const ProjectFile &projFile,
|
||||||
|
CompilationDbPurpose purpose)
|
||||||
{
|
{
|
||||||
QJsonObject fileObject;
|
QJsonObject fileObject;
|
||||||
fileObject["file"] = projFile.path;
|
fileObject["file"] = projFile.path;
|
||||||
QJsonArray args = QJsonArray::fromStringList(arguments);
|
QJsonArray args;
|
||||||
|
|
||||||
|
if (purpose == CompilationDbPurpose::Project) {
|
||||||
|
args = QJsonArray::fromStringList(arguments);
|
||||||
|
|
||||||
const ProjectFile::Kind kind = ProjectFile::classify(projFile.path);
|
const ProjectFile::Kind kind = ProjectFile::classify(projFile.path);
|
||||||
if (projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|
if (projectPart.toolchainType == ProjectExplorer::Constants::MSVC_TOOLCHAIN_TYPEID
|
||||||
@@ -375,13 +372,20 @@ static QJsonObject createFileObject(const FilePath &buildDir,
|
|||||||
for (const QString &langOptionPart : langOption)
|
for (const QString &langOptionPart : langOption)
|
||||||
args.append(langOptionPart);
|
args.append(langOptionPart);
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// TODO: Do we really need to re-calculate the project part options per source file?
|
||||||
|
args = QJsonArray::fromStringList(createClangOptions(projectPart, projFile.path).second);
|
||||||
|
args.prepend("clang"); // TODO: clang-cl for MSVC targets? Does it matter at all what we put here?
|
||||||
|
}
|
||||||
|
|
||||||
args.append(QDir::toNativeSeparators(projFile.path));
|
args.append(QDir::toNativeSeparators(projFile.path));
|
||||||
fileObject["arguments"] = args;
|
fileObject["arguments"] = args;
|
||||||
fileObject["directory"] = buildDir.toString();
|
fileObject["directory"] = buildDir.toString();
|
||||||
return fileObject;
|
return fileObject;
|
||||||
}
|
}
|
||||||
|
|
||||||
GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo)
|
GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo,
|
||||||
|
CompilationDbPurpose purpose)
|
||||||
{
|
{
|
||||||
const FilePath buildDir = buildDirectory(*projectInfo.project());
|
const FilePath buildDir = buildDirectory(*projectInfo.project());
|
||||||
QTC_ASSERT(!buildDir.isEmpty(), return GenerateCompilationDbResult(QString(),
|
QTC_ASSERT(!buildDir.isEmpty(), return GenerateCompilationDbResult(QString(),
|
||||||
@@ -400,9 +404,12 @@ GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectI
|
|||||||
compileCommandsFile.write("[");
|
compileCommandsFile.write("[");
|
||||||
|
|
||||||
for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
|
for (ProjectPart::Ptr projectPart : projectInfo.projectParts()) {
|
||||||
const QStringList args = projectPartArguments(*projectPart);
|
QStringList args;
|
||||||
|
if (purpose == CompilationDbPurpose::Project)
|
||||||
|
args = projectPartArguments(*projectPart);
|
||||||
for (const ProjectFile &projFile : projectPart->files) {
|
for (const ProjectFile &projFile : projectPart->files) {
|
||||||
const QJsonObject json = createFileObject(buildDir, args, *projectPart, projFile);
|
const QJsonObject json = createFileObject(buildDir, args, *projectPart, projFile,
|
||||||
|
purpose);
|
||||||
if (compileCommandsFile.size() > 1)
|
if (compileCommandsFile.size() > 1)
|
||||||
compileCommandsFile.write(",");
|
compileCommandsFile.write(",");
|
||||||
compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed());
|
compileCommandsFile.write('\n' + QJsonDocument(json).toJson().trimmed());
|
||||||
@@ -474,5 +481,142 @@ QString DiagnosticTextInfo::clazyCheckName(const QString &option)
|
|||||||
return option;
|
return option;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
static ClangProjectSettings &getProjectSettings(ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
QTC_CHECK(project);
|
||||||
|
return ClangModelManagerSupport::instance()->projectSettings(project);
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Can we marry this with CompilerOptionsBuilder?
|
||||||
|
class FileOptionsBuilder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
FileOptionsBuilder(const QString &filePath, const CppTools::ProjectPart &projectPart)
|
||||||
|
: m_filePath(filePath)
|
||||||
|
, m_projectPart(projectPart)
|
||||||
|
, m_builder(projectPart)
|
||||||
|
{
|
||||||
|
// Determine the driver mode from toolchain and flags.
|
||||||
|
m_builder.evaluateCompilerFlags();
|
||||||
|
m_isClMode = m_builder.isClStyle();
|
||||||
|
|
||||||
|
addLanguageOptions();
|
||||||
|
addGlobalDiagnosticOptions(); // Before addDiagnosticOptions() so users still can overwrite.
|
||||||
|
addDiagnosticOptions();
|
||||||
|
addGlobalOptions();
|
||||||
|
addPrecompiledHeaderOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
const QStringList &options() const { return m_options; }
|
||||||
|
const ::Utils::Id &diagnosticConfigId() const { return m_diagnosticConfigId; }
|
||||||
|
CppTools::UseBuildSystemWarnings useBuildSystemWarnings() const
|
||||||
|
{
|
||||||
|
return m_useBuildSystemWarnings;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void addLanguageOptions()
|
||||||
|
{
|
||||||
|
// Determine file kind with respect to ambiguous headers.
|
||||||
|
CppTools::ProjectFile::Kind fileKind = CppTools::ProjectFile::classify(m_filePath);
|
||||||
|
if (fileKind == CppTools::ProjectFile::AmbiguousHeader) {
|
||||||
|
fileKind = m_projectPart.languageVersion <= ::Utils::LanguageVersion::LatestC
|
||||||
|
? CppTools::ProjectFile::CHeader
|
||||||
|
: CppTools::ProjectFile::CXXHeader;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_builder.reset();
|
||||||
|
m_builder.updateFileLanguage(fileKind);
|
||||||
|
|
||||||
|
m_options.append(m_builder.options());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDiagnosticOptions()
|
||||||
|
{
|
||||||
|
if (m_projectPart.project) {
|
||||||
|
ClangProjectSettings &projectSettings = getProjectSettings(m_projectPart.project);
|
||||||
|
if (!projectSettings.useGlobalConfig()) {
|
||||||
|
const ::Utils::Id warningConfigId = projectSettings.warningConfigId();
|
||||||
|
const CppTools::ClangDiagnosticConfigsModel configsModel
|
||||||
|
= CppTools::diagnosticConfigsModel();
|
||||||
|
if (configsModel.hasConfigWithId(warningConfigId)) {
|
||||||
|
addDiagnosticOptionsForConfig(configsModel.configWithId(warningConfigId));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addDiagnosticOptionsForConfig(CppTools::codeModelSettings()->clangDiagnosticConfig());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addDiagnosticOptionsForConfig(const CppTools::ClangDiagnosticConfig &diagnosticConfig)
|
||||||
|
{
|
||||||
|
m_diagnosticConfigId = diagnosticConfig.id();
|
||||||
|
m_useBuildSystemWarnings = diagnosticConfig.useBuildSystemWarnings()
|
||||||
|
? CppTools::UseBuildSystemWarnings::Yes
|
||||||
|
: CppTools::UseBuildSystemWarnings::No;
|
||||||
|
|
||||||
|
const QStringList options = m_isClMode
|
||||||
|
? CppTools::clangArgsForCl(diagnosticConfig.clangOptions())
|
||||||
|
: diagnosticConfig.clangOptions();
|
||||||
|
m_options.append(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
void addGlobalDiagnosticOptions()
|
||||||
|
{
|
||||||
|
m_options += CppTools::ClangDiagnosticConfigsModel::globalDiagnosticOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
void addGlobalOptions()
|
||||||
|
{
|
||||||
|
if (!m_projectPart.project)
|
||||||
|
m_options.append(ClangProjectSettings::globalCommandLineOptions());
|
||||||
|
else
|
||||||
|
m_options.append(getProjectSettings(m_projectPart.project).commandLineOptions());
|
||||||
|
}
|
||||||
|
|
||||||
|
void addPrecompiledHeaderOptions()
|
||||||
|
{
|
||||||
|
using namespace CppTools;
|
||||||
|
|
||||||
|
if (getPchUsage() == UsePrecompiledHeaders::No)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (m_projectPart.precompiledHeaders.contains(m_filePath))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_builder.reset();
|
||||||
|
m_builder.addPrecompiledHeaderOptions(UsePrecompiledHeaders::Yes);
|
||||||
|
|
||||||
|
m_options.append(m_builder.options());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const QString &m_filePath;
|
||||||
|
const CppTools::ProjectPart &m_projectPart;
|
||||||
|
|
||||||
|
::Utils::Id m_diagnosticConfigId;
|
||||||
|
CppTools::UseBuildSystemWarnings m_useBuildSystemWarnings = CppTools::UseBuildSystemWarnings::No;
|
||||||
|
CppTools::CompilerOptionsBuilder m_builder;
|
||||||
|
bool m_isClMode = false;
|
||||||
|
QStringList m_options;
|
||||||
|
};
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
QPair<Utils::Id, QStringList> createClangOptions(const CppTools::ProjectPart &projectPart,
|
||||||
|
const QString &filePath)
|
||||||
|
{
|
||||||
|
QPair<Utils::Id, QStringList> value;
|
||||||
|
const FileOptionsBuilder fileOptions(filePath, projectPart);
|
||||||
|
value.first = fileOptions.diagnosticConfigId();
|
||||||
|
LibClangOptionsBuilder optionsBuilder(projectPart, fileOptions.useBuildSystemWarnings());
|
||||||
|
const QStringList projectPartOptions = optionsBuilder.build(CppTools::ProjectFile::Unsupported,
|
||||||
|
UsePrecompiledHeaders::No);
|
||||||
|
value.second = projectPartOptions + fileOptions.options();
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Clang
|
} // namespace Clang
|
||||||
|
@@ -30,6 +30,7 @@
|
|||||||
#include <cpptools/projectpart.h>
|
#include <cpptools/projectpart.h>
|
||||||
#include <cpptools/compileroptionsbuilder.h>
|
#include <cpptools/compileroptionsbuilder.h>
|
||||||
|
|
||||||
|
#include <QPair>
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@@ -49,9 +50,8 @@ namespace Internal {
|
|||||||
CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath);
|
CppTools::CppEditorDocumentHandle *cppDocument(const QString &filePath);
|
||||||
void setLastSentDocumentRevision(const QString &filePath, uint revision);
|
void setLastSentDocumentRevision(const QString &filePath, uint revision);
|
||||||
|
|
||||||
QStringList createClangOptions(const CppTools::ProjectPart &projectPart,
|
QPair<Utils::Id, QStringList> createClangOptions(const CppTools::ProjectPart &projectPart,
|
||||||
CppTools::UseBuildSystemWarnings useBuildSystemWarnings,
|
const QString &filePath);
|
||||||
CppTools::ProjectFile::Kind fileKind);
|
|
||||||
|
|
||||||
CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath);
|
CppTools::ProjectPart::Ptr projectPartForFile(const QString &filePath);
|
||||||
CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath);
|
CppTools::ProjectPart::Ptr projectPartForFileBasedOnProcessor(const QString &filePath);
|
||||||
@@ -78,7 +78,9 @@ public:
|
|||||||
QString error;
|
QString error;
|
||||||
};
|
};
|
||||||
|
|
||||||
GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo);
|
enum CompilationDbPurpose { Project, CodeModel };
|
||||||
|
GenerateCompilationDbResult generateCompilationDB(CppTools::ProjectInfo projectInfo,
|
||||||
|
CompilationDbPurpose purpose);
|
||||||
|
|
||||||
class DiagnosticTextInfo
|
class DiagnosticTextInfo
|
||||||
{
|
{
|
||||||
|
@@ -531,6 +531,14 @@ QString ICore::clangExecutable(const QString &clangBinDirectory)
|
|||||||
return clangBinary("clang", clangBinDirectory);
|
return clangBinary("clang", clangBinDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
\internal
|
||||||
|
*/
|
||||||
|
QString ICore::clangdExecutable(const QString &clangBinDirectory)
|
||||||
|
{
|
||||||
|
return clangBinary("clangd", clangBinDirectory);
|
||||||
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
\internal
|
\internal
|
||||||
*/
|
*/
|
||||||
|
@@ -164,6 +164,7 @@ public:
|
|||||||
static QString pluginPath();
|
static QString pluginPath();
|
||||||
static QString userPluginPath();
|
static QString userPluginPath();
|
||||||
static QString clangExecutable(const QString &clangBinDirectory);
|
static QString clangExecutable(const QString &clangBinDirectory);
|
||||||
|
static QString clangdExecutable(const QString &clangBinDirectory);
|
||||||
static QString clangTidyExecutable(const QString &clangBinDirectory);
|
static QString clangTidyExecutable(const QString &clangBinDirectory);
|
||||||
static QString clazyStandaloneExecutable(const QString &clangBinDirectory);
|
static QString clazyStandaloneExecutable(const QString &clangBinDirectory);
|
||||||
static QString clangIncludeDirectory(const QString &clangVersion,
|
static QString clangIncludeDirectory(const QString &clangVersion,
|
||||||
|
@@ -472,7 +472,8 @@ void CppEditorWidget::findUsages()
|
|||||||
void CppEditorWidget::findUsages(QTextCursor cursor)
|
void CppEditorWidget::findUsages(QTextCursor cursor)
|
||||||
{
|
{
|
||||||
// 'this' in cursorInEditor is never used (and must never be used) asynchronously.
|
// 'this' in cursorInEditor is never used (and must never be used) asynchronously.
|
||||||
const CppTools::CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this};
|
const CppTools::CursorInEditor cursorInEditor{cursor, textDocument()->filePath(), this,
|
||||||
|
textDocument()};
|
||||||
QPointer<CppEditorWidget> cppEditorWidget = this;
|
QPointer<CppEditorWidget> cppEditorWidget = this;
|
||||||
d->m_modelManager->findUsages(cursorInEditor,
|
d->m_modelManager->findUsages(cursorInEditor,
|
||||||
[=](const CppTools::Usages &usages) {
|
[=](const CppTools::Usages &usages) {
|
||||||
|
@@ -2068,7 +2068,7 @@ void AddIncludeForUndefinedIdentifier::match(const CppQuickFixInterface &interfa
|
|||||||
const Snapshot forwardHeaders = forwardingHeaders(interface);
|
const Snapshot forwardHeaders = forwardingHeaders(interface);
|
||||||
foreach (const Core::LocatorFilterEntry &entry, matches) {
|
foreach (const Core::LocatorFilterEntry &entry, matches) {
|
||||||
IndexItem::Ptr info = entry.internalData.value<IndexItem::Ptr>();
|
IndexItem::Ptr info = entry.internalData.value<IndexItem::Ptr>();
|
||||||
if (info->symbolName() != className)
|
if (!info || info->symbolName() != className)
|
||||||
continue;
|
continue;
|
||||||
indexItems << info;
|
indexItems << info;
|
||||||
|
|
||||||
|
@@ -32,7 +32,7 @@
|
|||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
class CppLocatorData;
|
class CppLocatorData;
|
||||||
|
|
||||||
class CppClassesFilter : public Internal::CppLocatorFilter
|
class CPPTOOLS_EXPORT CppClassesFilter : public CppLocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@@ -35,6 +35,7 @@
|
|||||||
#include <QSettings>
|
#include <QSettings>
|
||||||
|
|
||||||
using namespace CppTools;
|
using namespace CppTools;
|
||||||
|
using namespace Utils;
|
||||||
|
|
||||||
static Utils::Id initialClangDiagnosticConfigId()
|
static Utils::Id initialClangDiagnosticConfigId()
|
||||||
{ return Constants::CPP_CLANG_DIAG_CONFIG_BUILDSYSTEM; }
|
{ return Constants::CPP_CLANG_DIAG_CONFIG_BUILDSYSTEM; }
|
||||||
@@ -60,6 +61,17 @@ static QString skipIndexingBigFilesKey()
|
|||||||
static QString indexerFileSizeLimitKey()
|
static QString indexerFileSizeLimitKey()
|
||||||
{ return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); }
|
{ return QLatin1String(Constants::CPPTOOLS_INDEXER_FILE_SIZE_LIMIT); }
|
||||||
|
|
||||||
|
static QString useClangdKey() { return QLatin1String("UseClangd"); }
|
||||||
|
static QString clangdPathKey() { return QLatin1String("ClangdPath"); }
|
||||||
|
|
||||||
|
static FilePath g_defaultClangdFilePath;
|
||||||
|
static FilePath fallbackClangdFilePath()
|
||||||
|
{
|
||||||
|
if (g_defaultClangdFilePath.exists())
|
||||||
|
return g_defaultClangdFilePath;
|
||||||
|
return FilePath::fromString("clangd");
|
||||||
|
}
|
||||||
|
|
||||||
static Utils::Id clangDiagnosticConfigIdFromSettings(QSettings *s)
|
static Utils::Id clangDiagnosticConfigIdFromSettings(QSettings *s)
|
||||||
{
|
{
|
||||||
QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Utils::Id());
|
QTC_ASSERT(s->group() == QLatin1String(Constants::CPPTOOLS_SETTINGSGROUP), return Utils::Id());
|
||||||
@@ -160,6 +172,9 @@ void CppCodeModelSettings::fromSettings(QSettings *s)
|
|||||||
const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5);
|
const QVariant indexerFileSizeLimit = s->value(indexerFileSizeLimitKey(), 5);
|
||||||
setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt());
|
setIndexerFileSizeLimitInMb(indexerFileSizeLimit.toInt());
|
||||||
|
|
||||||
|
setUseClangd(s->value(useClangdKey(), false).toBool());
|
||||||
|
setClangdFilePath(FilePath::fromString(s->value(clangdPathKey()).toString()));
|
||||||
|
|
||||||
s->endGroup();
|
s->endGroup();
|
||||||
|
|
||||||
if (write)
|
if (write)
|
||||||
@@ -183,6 +198,8 @@ void CppCodeModelSettings::toSettings(QSettings *s)
|
|||||||
s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders());
|
s->setValue(interpretAmbiguousHeadersAsCHeadersKey(), interpretAmbigiousHeadersAsCHeaders());
|
||||||
s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles());
|
s->setValue(skipIndexingBigFilesKey(), skipIndexingBigFiles());
|
||||||
s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb());
|
s->setValue(indexerFileSizeLimitKey(), indexerFileSizeLimitInMb());
|
||||||
|
s->setValue(useClangdKey(), useClangd());
|
||||||
|
s->setValue(clangdPathKey(), m_clangdFilePath.toString());
|
||||||
|
|
||||||
s->endGroup();
|
s->endGroup();
|
||||||
|
|
||||||
@@ -282,3 +299,15 @@ void CppCodeModelSettings::setEnableLowerClazyLevels(bool yesno)
|
|||||||
{
|
{
|
||||||
m_enableLowerClazyLevels = yesno;
|
m_enableLowerClazyLevels = yesno;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppCodeModelSettings::setDefaultClangdPath(const Utils::FilePath &filePath)
|
||||||
|
{
|
||||||
|
g_defaultClangdFilePath = filePath;
|
||||||
|
}
|
||||||
|
|
||||||
|
FilePath CppCodeModelSettings::clangdFilePath() const
|
||||||
|
{
|
||||||
|
if (!m_clangdFilePath.isEmpty())
|
||||||
|
return m_clangdFilePath;
|
||||||
|
return fallbackClangdFilePath();
|
||||||
|
}
|
||||||
|
@@ -29,6 +29,8 @@
|
|||||||
|
|
||||||
#include "clangdiagnosticconfigsmodel.h"
|
#include "clangdiagnosticconfigsmodel.h"
|
||||||
|
|
||||||
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
#include <QObject>
|
#include <QObject>
|
||||||
#include <QStringList>
|
#include <QStringList>
|
||||||
|
|
||||||
@@ -76,6 +78,13 @@ public:
|
|||||||
int indexerFileSizeLimitInMb() const;
|
int indexerFileSizeLimitInMb() const;
|
||||||
void setIndexerFileSizeLimitInMb(int sizeInMB);
|
void setIndexerFileSizeLimitInMb(int sizeInMB);
|
||||||
|
|
||||||
|
void setUseClangd(bool use) { m_useClangd = use; }
|
||||||
|
bool useClangd() const { return m_useClangd; }
|
||||||
|
|
||||||
|
static void setDefaultClangdPath(const Utils::FilePath &filePath);
|
||||||
|
void setClangdFilePath(const Utils::FilePath &filePath) { m_clangdFilePath = filePath; }
|
||||||
|
Utils::FilePath clangdFilePath() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void clangDiagnosticConfigsInvalidated(const QVector<Utils::Id> &configId);
|
void clangDiagnosticConfigsInvalidated(const QVector<Utils::Id> &configId);
|
||||||
void changed();
|
void changed();
|
||||||
@@ -88,6 +97,8 @@ private:
|
|||||||
ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs;
|
ClangDiagnosticConfigs m_clangCustomDiagnosticConfigs;
|
||||||
Utils::Id m_clangDiagnosticConfigId;
|
Utils::Id m_clangDiagnosticConfigId;
|
||||||
bool m_enableLowerClazyLevels = true; // For UI behavior only
|
bool m_enableLowerClazyLevels = true; // For UI behavior only
|
||||||
|
Utils::FilePath m_clangdFilePath;
|
||||||
|
bool m_useClangd = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -100,6 +100,9 @@ void CppCodeModelSettingsWidget::setupClangCodeModelWidgets()
|
|||||||
const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive();
|
const bool isClangActive = CppModelManager::instance()->isClangCodeModelActive();
|
||||||
m_ui->clangCodeModelIsDisabledHint->setVisible(!isClangActive);
|
m_ui->clangCodeModelIsDisabledHint->setVisible(!isClangActive);
|
||||||
m_ui->clangCodeModelIsEnabledHint->setVisible(isClangActive);
|
m_ui->clangCodeModelIsEnabledHint->setVisible(isClangActive);
|
||||||
|
m_ui->clangdCheckBox->setVisible(isClangActive);
|
||||||
|
m_ui->clangdChooser->setVisible(isClangActive);
|
||||||
|
|
||||||
for (int i = 0; i < m_ui->clangDiagnosticConfigsSelectionWidget->layout()->count(); ++i) {
|
for (int i = 0; i < m_ui->clangDiagnosticConfigsSelectionWidget->layout()->count(); ++i) {
|
||||||
QWidget *widget = m_ui->clangDiagnosticConfigsSelectionWidget->layout()->itemAt(i)->widget();
|
QWidget *widget = m_ui->clangDiagnosticConfigsSelectionWidget->layout()->itemAt(i)->widget();
|
||||||
if (widget)
|
if (widget)
|
||||||
@@ -117,6 +120,16 @@ void CppCodeModelSettingsWidget::setupGeneralWidgets()
|
|||||||
|
|
||||||
const bool ignorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None;
|
const bool ignorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None;
|
||||||
m_ui->ignorePCHCheckBox->setChecked(ignorePch);
|
m_ui->ignorePCHCheckBox->setChecked(ignorePch);
|
||||||
|
|
||||||
|
m_ui->clangdCheckBox->setChecked(m_settings->useClangd());
|
||||||
|
m_ui->clangdCheckBox->setToolTip(tr("Use clangd for locators and \"Find References\".\n"
|
||||||
|
"Changing this option does not affect projects that are already open."));
|
||||||
|
m_ui->clangdChooser->setExpectedKind(Utils::PathChooser::ExistingCommand);
|
||||||
|
m_ui->clangdChooser->setFilePath(codeModelSettings()->clangdFilePath());
|
||||||
|
m_ui->clangdChooser->setEnabled(m_ui->clangdCheckBox->isChecked());
|
||||||
|
connect(m_ui->clangdCheckBox, &QCheckBox::toggled, m_ui->clangdChooser, [this](bool checked) {
|
||||||
|
m_ui->clangdChooser->setEnabled(checked);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
|
bool CppCodeModelSettingsWidget::applyClangCodeModelWidgetsToSettings() const
|
||||||
@@ -163,6 +176,16 @@ bool CppCodeModelSettingsWidget::applyGeneralWidgetsToSettings() const
|
|||||||
m_settings->setIndexerFileSizeLimitInMb(newFileSizeLimit);
|
m_settings->setIndexerFileSizeLimitInMb(newFileSizeLimit);
|
||||||
settingsChanged = true;
|
settingsChanged = true;
|
||||||
}
|
}
|
||||||
|
const bool newUseClangd = m_ui->clangdCheckBox->isChecked();
|
||||||
|
if (m_settings->useClangd() != newUseClangd) {
|
||||||
|
m_settings->setUseClangd(newUseClangd);
|
||||||
|
settingsChanged = true;
|
||||||
|
}
|
||||||
|
const Utils::FilePath newClangdPath = m_ui->clangdChooser->rawFilePath();
|
||||||
|
if (m_settings->clangdFilePath() != newClangdPath) {
|
||||||
|
m_settings->setClangdFilePath(newClangdPath);
|
||||||
|
settingsChanged = true;
|
||||||
|
}
|
||||||
|
|
||||||
const bool newIgnorePch = m_ui->ignorePCHCheckBox->isChecked();
|
const bool newIgnorePch = m_ui->ignorePCHCheckBox->isChecked();
|
||||||
const bool previousIgnorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None;
|
const bool previousIgnorePch = m_settings->pchUsage() == CppCodeModelSettings::PchUse_None;
|
||||||
|
@@ -6,7 +6,7 @@
|
|||||||
<rect>
|
<rect>
|
||||||
<x>0</x>
|
<x>0</x>
|
||||||
<y>0</y>
|
<y>0</y>
|
||||||
<width>647</width>
|
<width>697</width>
|
||||||
<height>440</height>
|
<height>440</height>
|
||||||
</rect>
|
</rect>
|
||||||
</property>
|
</property>
|
||||||
@@ -80,6 +80,33 @@
|
|||||||
</item>
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</item>
|
</item>
|
||||||
|
<item>
|
||||||
|
<layout class="QHBoxLayout" name="horizontalLayout_3">
|
||||||
|
<item>
|
||||||
|
<widget class="QCheckBox" name="clangdCheckBox">
|
||||||
|
<property name="text">
|
||||||
|
<string>Use clangd (EXPERIMENTAL)</string>
|
||||||
|
</property>
|
||||||
|
</widget>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<widget class="Utils::PathChooser" name="clangdChooser"/>
|
||||||
|
</item>
|
||||||
|
<item>
|
||||||
|
<spacer name="horizontalSpacer_3">
|
||||||
|
<property name="orientation">
|
||||||
|
<enum>Qt::Horizontal</enum>
|
||||||
|
</property>
|
||||||
|
<property name="sizeHint" stdset="0">
|
||||||
|
<size>
|
||||||
|
<width>40</width>
|
||||||
|
<height>20</height>
|
||||||
|
</size>
|
||||||
|
</property>
|
||||||
|
</spacer>
|
||||||
|
</item>
|
||||||
|
</layout>
|
||||||
|
</item>
|
||||||
</layout>
|
</layout>
|
||||||
</widget>
|
</widget>
|
||||||
</item>
|
</item>
|
||||||
@@ -147,6 +174,11 @@
|
|||||||
<extends>QWidget</extends>
|
<extends>QWidget</extends>
|
||||||
<header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
|
<header>cpptools/clangdiagnosticconfigsselectionwidget.h</header>
|
||||||
</customwidget>
|
</customwidget>
|
||||||
|
<customwidget>
|
||||||
|
<class>Utils::PathChooser</class>
|
||||||
|
<extends>QLineEdit</extends>
|
||||||
|
<header location="global">utils/pathchooser.h</header>
|
||||||
|
</customwidget>
|
||||||
</customwidgets>
|
</customwidgets>
|
||||||
<resources/>
|
<resources/>
|
||||||
<connections/>
|
<connections/>
|
||||||
|
@@ -30,7 +30,6 @@
|
|||||||
#include <utils/fileutils.h>
|
#include <utils/fileutils.h>
|
||||||
|
|
||||||
using namespace CppTools;
|
using namespace CppTools;
|
||||||
using namespace CppTools::Internal;
|
|
||||||
|
|
||||||
CppFunctionsFilter::CppFunctionsFilter(CppLocatorData *locatorData)
|
CppFunctionsFilter::CppFunctionsFilter(CppLocatorData *locatorData)
|
||||||
: CppLocatorFilter(locatorData)
|
: CppLocatorFilter(locatorData)
|
||||||
|
@@ -30,9 +30,8 @@
|
|||||||
|
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class CppFunctionsFilter : public CppLocatorFilter
|
class CPPTOOLS_EXPORT CppFunctionsFilter : public CppLocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -45,5 +44,4 @@ protected:
|
|||||||
Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info) override;
|
Core::LocatorFilterEntry filterEntryFromIndexItem(IndexItem::Ptr info) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -35,7 +35,7 @@
|
|||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
|
|
||||||
class CppLocatorData : public QObject
|
class CPPTOOLS_EXPORT CppLocatorData : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@@ -35,8 +35,7 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <numeric>
|
#include <numeric>
|
||||||
|
|
||||||
using namespace CppTools;
|
namespace CppTools {
|
||||||
using namespace CppTools::Internal;
|
|
||||||
|
|
||||||
CppLocatorFilter::CppLocatorFilter(CppLocatorData *locatorData)
|
CppLocatorFilter::CppLocatorFilter(CppLocatorData *locatorData)
|
||||||
: m_data(locatorData)
|
: m_data(locatorData)
|
||||||
@@ -145,3 +144,5 @@ void CppLocatorFilter::accept(Core::LocatorFilterEntry selection,
|
|||||||
IndexItem::Ptr info = qvariant_cast<IndexItem::Ptr>(selection.internalData);
|
IndexItem::Ptr info = qvariant_cast<IndexItem::Ptr>(selection.internalData);
|
||||||
Core::EditorManager::openEditorAt(info->fileName(), info->line(), info->column());
|
Core::EditorManager::openEditorAt(info->fileName(), info->line(), info->column());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace CppTools
|
||||||
|
@@ -25,15 +25,15 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "cpptools_global.h"
|
||||||
#include "cpplocatordata.h"
|
#include "cpplocatordata.h"
|
||||||
#include "searchsymbols.h"
|
#include "searchsymbols.h"
|
||||||
|
|
||||||
#include <coreplugin/locator/ilocatorfilter.h>
|
#include <coreplugin/locator/ilocatorfilter.h>
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
namespace Internal {
|
|
||||||
|
|
||||||
class CppLocatorFilter : public Core::ILocatorFilter
|
class CPPTOOLS_EXPORT CppLocatorFilter : public Core::ILocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
@@ -54,5 +54,4 @@ protected:
|
|||||||
CppLocatorData *m_data = nullptr;
|
CppLocatorData *m_data = nullptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Internal
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -328,7 +328,7 @@ void CppModelManager::globalRename(const CursorInEditor &data, UsagesCallback &&
|
|||||||
void CppModelManager::findUsages(const CppTools::CursorInEditor &data,
|
void CppModelManager::findUsages(const CppTools::CursorInEditor &data,
|
||||||
UsagesCallback &&showUsagesCallback) const
|
UsagesCallback &&showUsagesCallback) const
|
||||||
{
|
{
|
||||||
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines);
|
RefactoringEngineInterface *engine = getRefactoringEngine(d->m_refactoringEngines, false);
|
||||||
QTC_ASSERT(engine, return;);
|
QTC_ASSERT(engine, return;);
|
||||||
engine->findUsages(data, std::move(showUsagesCallback));
|
engine->findUsages(data, std::move(showUsagesCallback));
|
||||||
}
|
}
|
||||||
@@ -466,6 +466,11 @@ void CppModelManager::removeRefactoringEngine(RefactoringEngineType type)
|
|||||||
instance()->d->m_refactoringEngines.remove(type);
|
instance()->d->m_refactoringEngines.remove(type);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
RefactoringEngineInterface *CppModelManager::builtinRefactoringEngine()
|
||||||
|
{
|
||||||
|
return instance()->d->m_refactoringEngines.value(RefactoringEngineType::BuiltIn);
|
||||||
|
}
|
||||||
|
|
||||||
template<class FilterClass>
|
template<class FilterClass>
|
||||||
static void setFilter(std::unique_ptr<FilterClass> &filter,
|
static void setFilter(std::unique_ptr<FilterClass> &filter,
|
||||||
std::unique_ptr<FilterClass> &&newFilter)
|
std::unique_ptr<FilterClass> &&newFilter)
|
||||||
@@ -917,6 +922,11 @@ QByteArray CppModelManager::codeModelConfiguration() const
|
|||||||
return QByteArray::fromRawData(pp_configuration, qstrlen(pp_configuration));
|
return QByteArray::fromRawData(pp_configuration, qstrlen(pp_configuration));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CppLocatorData *CppModelManager::locatorData() const
|
||||||
|
{
|
||||||
|
return &d->m_locatorData;
|
||||||
|
}
|
||||||
|
|
||||||
static QSet<QString> tooBigFilesRemoved(const QSet<QString> &files, int fileSizeLimitInMb)
|
static QSet<QString> tooBigFilesRemoved(const QSet<QString> &files, int fileSizeLimitInMb)
|
||||||
{
|
{
|
||||||
if (fileSizeLimitInMb <= 0)
|
if (fileSizeLimitInMb <= 0)
|
||||||
|
@@ -60,6 +60,7 @@ class BaseEditorDocumentProcessor;
|
|||||||
class CppCompletionAssistProvider;
|
class CppCompletionAssistProvider;
|
||||||
class CppEditorDocumentHandle;
|
class CppEditorDocumentHandle;
|
||||||
class CppIndexingSupport;
|
class CppIndexingSupport;
|
||||||
|
class CppLocatorData;
|
||||||
class ModelManagerSupportProvider;
|
class ModelManagerSupportProvider;
|
||||||
class FollowSymbolInterface;
|
class FollowSymbolInterface;
|
||||||
class SymbolFinder;
|
class SymbolFinder;
|
||||||
@@ -111,6 +112,7 @@ public:
|
|||||||
void updateCppEditorDocuments(bool projectsUpdated = false) const;
|
void updateCppEditorDocuments(bool projectsUpdated = false) const;
|
||||||
WorkingCopy workingCopy() const;
|
WorkingCopy workingCopy() const;
|
||||||
QByteArray codeModelConfiguration() const;
|
QByteArray codeModelConfiguration() const;
|
||||||
|
CppLocatorData *locatorData() const;
|
||||||
|
|
||||||
QList<ProjectInfo> projectInfos() const;
|
QList<ProjectInfo> projectInfos() const;
|
||||||
ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
|
ProjectInfo projectInfo(ProjectExplorer::Project *project) const;
|
||||||
@@ -215,6 +217,7 @@ public:
|
|||||||
static void addRefactoringEngine(RefactoringEngineType type,
|
static void addRefactoringEngine(RefactoringEngineType type,
|
||||||
RefactoringEngineInterface *refactoringEngine);
|
RefactoringEngineInterface *refactoringEngine);
|
||||||
static void removeRefactoringEngine(RefactoringEngineType type);
|
static void removeRefactoringEngine(RefactoringEngineType type);
|
||||||
|
static RefactoringEngineInterface *builtinRefactoringEngine();
|
||||||
|
|
||||||
void setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
|
void setLocatorFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
|
||||||
void setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
|
void setClassesFilter(std::unique_ptr<Core::ILocatorFilter> &&filter);
|
||||||
|
@@ -31,24 +31,30 @@
|
|||||||
|
|
||||||
#include <QTextCursor>
|
#include <QTextCursor>
|
||||||
|
|
||||||
|
namespace TextEditor { class TextDocument; }
|
||||||
|
|
||||||
namespace CppTools {
|
namespace CppTools {
|
||||||
|
|
||||||
class CursorInEditor
|
class CursorInEditor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CursorInEditor(const QTextCursor &cursor, const Utils::FilePath &filePath,
|
CursorInEditor(const QTextCursor &cursor, const Utils::FilePath &filePath,
|
||||||
CppEditorWidgetInterface *editorWidget = nullptr)
|
CppEditorWidgetInterface *editorWidget = nullptr,
|
||||||
|
TextEditor::TextDocument *textDocument = nullptr)
|
||||||
: m_cursor(cursor)
|
: m_cursor(cursor)
|
||||||
, m_filePath(filePath)
|
, m_filePath(filePath)
|
||||||
, m_editorWidget(editorWidget)
|
, m_editorWidget(editorWidget)
|
||||||
|
, m_textDocument(textDocument)
|
||||||
{}
|
{}
|
||||||
CppEditorWidgetInterface *editorWidget() const { return m_editorWidget; }
|
CppEditorWidgetInterface *editorWidget() const { return m_editorWidget; }
|
||||||
|
TextEditor::TextDocument *textDocument() const { return m_textDocument; }
|
||||||
const QTextCursor &cursor() const { return m_cursor; }
|
const QTextCursor &cursor() const { return m_cursor; }
|
||||||
const Utils::FilePath &filePath() const { return m_filePath; }
|
const Utils::FilePath &filePath() const { return m_filePath; }
|
||||||
private:
|
private:
|
||||||
QTextCursor m_cursor;
|
QTextCursor m_cursor;
|
||||||
Utils::FilePath m_filePath;
|
Utils::FilePath m_filePath;
|
||||||
CppEditorWidgetInterface *m_editorWidget = nullptr;
|
CppEditorWidgetInterface *m_editorWidget = nullptr;
|
||||||
|
TextEditor::TextDocument * const m_textDocument;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CppTools
|
} // namespace CppTools
|
||||||
|
@@ -292,7 +292,7 @@ void Client::initialize()
|
|||||||
QTC_ASSERT(m_state == Uninitialized, return);
|
QTC_ASSERT(m_state == Uninitialized, return);
|
||||||
qCDebug(LOGLSPCLIENT) << "initializing language server " << m_displayName;
|
qCDebug(LOGLSPCLIENT) << "initializing language server " << m_displayName;
|
||||||
InitializeParams params;
|
InitializeParams params;
|
||||||
params.setCapabilities(generateClientCapabilities());
|
params.setCapabilities(m_clientCapabilities);
|
||||||
params.setInitializationOptions(m_initializationOptions);
|
params.setInitializationOptions(m_initializationOptions);
|
||||||
if (m_project) {
|
if (m_project) {
|
||||||
params.setRootUri(DocumentUri::fromFilePath(m_project->projectDirectory()));
|
params.setRootUri(DocumentUri::fromFilePath(m_project->projectDirectory()));
|
||||||
@@ -333,6 +333,16 @@ Client::State Client::state() const
|
|||||||
return m_state;
|
return m_state;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ClientCapabilities Client::defaultClientCapabilities()
|
||||||
|
{
|
||||||
|
return generateClientCapabilities();
|
||||||
|
}
|
||||||
|
|
||||||
|
void Client::setClientCapabilities(const LanguageServerProtocol::ClientCapabilities &caps)
|
||||||
|
{
|
||||||
|
m_clientCapabilities = caps;
|
||||||
|
}
|
||||||
|
|
||||||
void Client::openDocument(TextEditor::TextDocument *document)
|
void Client::openDocument(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
@@ -532,6 +542,9 @@ void Client::requestDocumentHighlights(TextEditor::TextEditorWidget *widget)
|
|||||||
|
|
||||||
void Client::activateDocument(TextEditor::TextDocument *document)
|
void Client::activateDocument(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
|
if (!m_documentActionsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
auto uri = DocumentUri::fromFilePath(document->filePath());
|
auto uri = DocumentUri::fromFilePath(document->filePath());
|
||||||
m_diagnosticManager.showDiagnostics(uri);
|
m_diagnosticManager.showDiagnostics(uri);
|
||||||
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
|
SemanticHighligtingSupport::applyHighlight(document, m_highlights.value(uri), capabilities());
|
||||||
@@ -558,6 +571,9 @@ void Client::activateDocument(TextEditor::TextDocument *document)
|
|||||||
|
|
||||||
void Client::deactivateDocument(TextEditor::TextDocument *document)
|
void Client::deactivateDocument(TextEditor::TextDocument *document)
|
||||||
{
|
{
|
||||||
|
if (!m_documentActionsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
m_diagnosticManager.hideDiagnostics(document);
|
m_diagnosticManager.hideDiagnostics(document);
|
||||||
resetAssistProviders(document);
|
resetAssistProviders(document);
|
||||||
document->setFormatter(nullptr);
|
document->setFormatter(nullptr);
|
||||||
@@ -1241,6 +1257,9 @@ void Client::handleMethod(const QString &method, const MessageId &id, const ICon
|
|||||||
|
|
||||||
void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
||||||
{
|
{
|
||||||
|
if (!m_documentActionsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
const DocumentUri &uri = params.uri();
|
const DocumentUri &uri = params.uri();
|
||||||
|
|
||||||
const QList<Diagnostic> &diagnostics = params.diagnostics();
|
const QList<Diagnostic> &diagnostics = params.diagnostics();
|
||||||
@@ -1253,6 +1272,9 @@ void Client::handleDiagnostics(const PublishDiagnosticsParams ¶ms)
|
|||||||
|
|
||||||
void Client::handleSemanticHighlight(const SemanticHighlightingParams ¶ms)
|
void Client::handleSemanticHighlight(const SemanticHighlightingParams ¶ms)
|
||||||
{
|
{
|
||||||
|
if (!m_documentActionsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
DocumentUri uri;
|
DocumentUri uri;
|
||||||
LanguageClientValue<int> version;
|
LanguageClientValue<int> version;
|
||||||
auto textDocument = params.textDocument();
|
auto textDocument = params.textDocument();
|
||||||
@@ -1283,6 +1305,9 @@ void Client::handleSemanticHighlight(const SemanticHighlightingParams ¶ms)
|
|||||||
|
|
||||||
void Client::rehighlight()
|
void Client::rehighlight()
|
||||||
{
|
{
|
||||||
|
if (!m_documentActionsEnabled)
|
||||||
|
return;
|
||||||
|
|
||||||
using namespace TextEditor;
|
using namespace TextEditor;
|
||||||
for (auto it = m_highlights.begin(), end = m_highlights.end(); it != end; ++it) {
|
for (auto it = m_highlights.begin(), end = m_highlights.end(); it != end; ++it) {
|
||||||
if (TextDocument *doc = TextDocument::textDocumentForFilePath(it.key().toFilePath())) {
|
if (TextDocument *doc = TextDocument::textDocumentForFilePath(it.key().toFilePath())) {
|
||||||
|
@@ -113,11 +113,17 @@ public:
|
|||||||
bool reachable() const { return m_state == Initialized; }
|
bool reachable() const { return m_state == Initialized; }
|
||||||
|
|
||||||
// capabilities
|
// capabilities
|
||||||
|
static LanguageServerProtocol::ClientCapabilities defaultClientCapabilities();
|
||||||
|
void setClientCapabilities(const LanguageServerProtocol::ClientCapabilities &caps);
|
||||||
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
|
const LanguageServerProtocol::ServerCapabilities &capabilities() const;
|
||||||
const DynamicCapabilities &dynamicCapabilities() const;
|
const DynamicCapabilities &dynamicCapabilities() const;
|
||||||
void registerCapabilities(const QList<LanguageServerProtocol::Registration> ®istrations);
|
void registerCapabilities(const QList<LanguageServerProtocol::Registration> ®istrations);
|
||||||
void unregisterCapabilities(const QList<LanguageServerProtocol::Unregistration> &unregistrations);
|
void unregisterCapabilities(const QList<LanguageServerProtocol::Unregistration> &unregistrations);
|
||||||
|
|
||||||
|
void setLocatorsEnabled(bool enabled) { m_locatorsEnabled = enabled; }
|
||||||
|
bool locatorsEnabled() const { return m_locatorsEnabled; }
|
||||||
|
void setDocumentActionsEnabled(bool enabled) { m_documentActionsEnabled = enabled; }
|
||||||
|
|
||||||
// document synchronization
|
// document synchronization
|
||||||
void setSupportedLanguage(const LanguageFilter &filter);
|
void setSupportedLanguage(const LanguageFilter &filter);
|
||||||
void setActivateDocumentAutomatically(bool enabled);
|
void setActivateDocumentAutomatically(bool enabled);
|
||||||
@@ -226,6 +232,7 @@ private:
|
|||||||
QMap<TextEditor::TextEditorWidget *, QTimer *> m_documentHighlightsTimer;
|
QMap<TextEditor::TextEditorWidget *, QTimer *> m_documentHighlightsTimer;
|
||||||
QTimer m_documentUpdateTimer;
|
QTimer m_documentUpdateTimer;
|
||||||
Utils::Id m_id;
|
Utils::Id m_id;
|
||||||
|
LanguageServerProtocol::ClientCapabilities m_clientCapabilities = defaultClientCapabilities();
|
||||||
LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
|
LanguageServerProtocol::ServerCapabilities m_serverCapabilities;
|
||||||
DynamicCapabilities m_dynamicCapabilities;
|
DynamicCapabilities m_dynamicCapabilities;
|
||||||
struct AssistProviders
|
struct AssistProviders
|
||||||
@@ -250,6 +257,8 @@ private:
|
|||||||
ProgressManager m_progressManager;
|
ProgressManager m_progressManager;
|
||||||
bool m_activateDocAutomatically = false;
|
bool m_activateDocAutomatically = false;
|
||||||
SemanticTokenSupport m_tokentSupport;
|
SemanticTokenSupport m_tokentSupport;
|
||||||
|
bool m_locatorsEnabled = true;
|
||||||
|
bool m_documentActionsEnabled = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace LanguageClient
|
} // namespace LanguageClient
|
||||||
|
@@ -57,4 +57,6 @@ QtcPlugin {
|
|||||||
"semantichighlightsupport.cpp",
|
"semantichighlightsupport.cpp",
|
||||||
"semantichighlightsupport.h",
|
"semantichighlightsupport.h",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
Export { Depends { name: "LanguageServerProtocol" } }
|
||||||
}
|
}
|
||||||
|
@@ -40,6 +40,7 @@
|
|||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
#include <texteditor/texteditor.h>
|
#include <texteditor/texteditor.h>
|
||||||
#include <texteditor/textmark.h>
|
#include <texteditor/textmark.h>
|
||||||
|
#include <utils/algorithm.h>
|
||||||
#include <utils/executeondestruction.h>
|
#include <utils/executeondestruction.h>
|
||||||
#include <utils/mimetypes/mimedatabase.h>
|
#include <utils/mimetypes/mimedatabase.h>
|
||||||
#include <utils/theme/theme.h>
|
#include <utils/theme/theme.h>
|
||||||
@@ -375,6 +376,14 @@ Client *LanguageClientManager::clientForUri(const DocumentUri &uri)
|
|||||||
return clientForFilePath(uri.toFilePath());
|
return clientForFilePath(uri.toFilePath());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const QList<Client *> LanguageClientManager::clientsForProject(
|
||||||
|
const ProjectExplorer::Project *project)
|
||||||
|
{
|
||||||
|
return Utils::filtered(managerInstance->m_clients, [project](const Client *c) {
|
||||||
|
return c->project() == project;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
|
||||||
void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *document, Client *client)
|
void LanguageClientManager::openDocumentWithClient(TextEditor::TextDocument *document, Client *client)
|
||||||
{
|
{
|
||||||
Client *currentClient = clientForDocument(document);
|
Client *currentClient = clientForDocument(document);
|
||||||
|
@@ -84,6 +84,7 @@ public:
|
|||||||
static Client *clientForDocument(TextEditor::TextDocument *document);
|
static Client *clientForDocument(TextEditor::TextDocument *document);
|
||||||
static Client *clientForFilePath(const Utils::FilePath &filePath);
|
static Client *clientForFilePath(const Utils::FilePath &filePath);
|
||||||
static Client *clientForUri(const LanguageServerProtocol::DocumentUri &uri);
|
static Client *clientForUri(const LanguageServerProtocol::DocumentUri &uri);
|
||||||
|
static const QList<Client *> clientsForProject(const ProjectExplorer::Project *project);
|
||||||
|
|
||||||
///
|
///
|
||||||
/// \brief openDocumentWithClient
|
/// \brief openDocumentWithClient
|
||||||
|
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
#include "languageclient_global.h"
|
||||||
|
|
||||||
#include <texteditor/textdocument.h>
|
#include <texteditor/textdocument.h>
|
||||||
|
|
||||||
#include <languageserverprotocol/languagefeatures.h>
|
#include <languageserverprotocol/languagefeatures.h>
|
||||||
@@ -38,7 +40,7 @@ namespace LanguageClient {
|
|||||||
|
|
||||||
class Client;
|
class Client;
|
||||||
|
|
||||||
class SymbolSupport
|
class LANGUAGECLIENT_EXPORT SymbolSupport
|
||||||
{
|
{
|
||||||
Q_DECLARE_TR_FUNCTIONS(SymbolSupport)
|
Q_DECLARE_TR_FUNCTIONS(SymbolSupport)
|
||||||
public:
|
public:
|
||||||
|
@@ -214,6 +214,18 @@ WorkspaceLocatorFilter::WorkspaceLocatorFilter(const QVector<SymbolKind> &filter
|
|||||||
}
|
}
|
||||||
|
|
||||||
void WorkspaceLocatorFilter::prepareSearch(const QString &entry)
|
void WorkspaceLocatorFilter::prepareSearch(const QString &entry)
|
||||||
|
{
|
||||||
|
prepareSearch(entry, LanguageClientManager::clients(), false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceLocatorFilter::prepareSearch(const QString &entry, const QVector<Client *> &clients)
|
||||||
|
{
|
||||||
|
prepareSearch(entry, clients, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WorkspaceLocatorFilter::prepareSearch(const QString &entry,
|
||||||
|
const QVector<Client *> &clients,
|
||||||
|
bool force)
|
||||||
{
|
{
|
||||||
m_pendingRequests.clear();
|
m_pendingRequests.clear();
|
||||||
m_results.clear();
|
m_results.clear();
|
||||||
@@ -222,7 +234,11 @@ void WorkspaceLocatorFilter::prepareSearch(const QString &entry)
|
|||||||
params.setQuery(entry);
|
params.setQuery(entry);
|
||||||
|
|
||||||
QMutexLocker locker(&m_mutex);
|
QMutexLocker locker(&m_mutex);
|
||||||
for (auto client : Utils::filtered(LanguageClientManager::clients(), &Client::reachable)) {
|
for (auto client : qAsConst(clients)) {
|
||||||
|
if (!client->reachable())
|
||||||
|
continue;
|
||||||
|
if (!(force || client->locatorsEnabled()))
|
||||||
|
continue;
|
||||||
Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> capability
|
Utils::optional<Utils::variant<bool, WorkDoneProgressOptions>> capability
|
||||||
= client->capabilities().workspaceSymbolProvider();
|
= client->capabilities().workspaceSymbolProvider();
|
||||||
if (!capability.has_value())
|
if (!capability.has_value())
|
||||||
|
@@ -74,13 +74,16 @@ private:
|
|||||||
Utils::optional<LanguageServerProtocol::DocumentSymbolsResult> m_currentSymbols;
|
Utils::optional<LanguageServerProtocol::DocumentSymbolsResult> m_currentSymbols;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceLocatorFilter : public Core::ILocatorFilter
|
class LANGUAGECLIENT_EXPORT WorkspaceLocatorFilter : public Core::ILocatorFilter
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
public:
|
public:
|
||||||
WorkspaceLocatorFilter();
|
WorkspaceLocatorFilter();
|
||||||
|
|
||||||
|
/// request workspace symbols for all clients with enabled locator
|
||||||
void prepareSearch(const QString &entry) override;
|
void prepareSearch(const QString &entry) override;
|
||||||
|
/// force request workspace symbols for all given clients
|
||||||
|
void prepareSearch(const QString &entry, const QVector<Client *> &clients);
|
||||||
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
|
QList<Core::LocatorFilterEntry> matchesFor(QFutureInterface<Core::LocatorFilterEntry> &future,
|
||||||
const QString &entry) override;
|
const QString &entry) override;
|
||||||
void accept(Core::LocatorFilterEntry selection,
|
void accept(Core::LocatorFilterEntry selection,
|
||||||
@@ -95,6 +98,7 @@ protected:
|
|||||||
explicit WorkspaceLocatorFilter(const QVector<LanguageServerProtocol::SymbolKind> &filter);
|
explicit WorkspaceLocatorFilter(const QVector<LanguageServerProtocol::SymbolKind> &filter);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
void prepareSearch(const QString &entry, const QVector<Client *> &clients, bool force);
|
||||||
void handleResponse(Client *client,
|
void handleResponse(Client *client,
|
||||||
const LanguageServerProtocol::WorkspaceSymbolRequest::Response &response);
|
const LanguageServerProtocol::WorkspaceSymbolRequest::Response &response);
|
||||||
|
|
||||||
@@ -104,13 +108,13 @@ private:
|
|||||||
QVector<LanguageServerProtocol::SymbolKind> m_filterKinds;
|
QVector<LanguageServerProtocol::SymbolKind> m_filterKinds;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceClassLocatorFilter : public WorkspaceLocatorFilter
|
class LANGUAGECLIENT_EXPORT WorkspaceClassLocatorFilter : public WorkspaceLocatorFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WorkspaceClassLocatorFilter();
|
WorkspaceClassLocatorFilter();
|
||||||
};
|
};
|
||||||
|
|
||||||
class WorkspaceMethodLocatorFilter : public WorkspaceLocatorFilter
|
class LANGUAGECLIENT_EXPORT WorkspaceMethodLocatorFilter : public WorkspaceLocatorFilter
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
WorkspaceMethodLocatorFilter();
|
WorkspaceMethodLocatorFilter();
|
||||||
|
Reference in New Issue
Block a user