ClangCodeModel: Add clangd-based document locator filter

Change-Id: I2811be80e740cacf57eccd19e47560af746ad0c1
Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
Reviewed-by: David Schulz <david.schulz@qt.io>
This commit is contained in:
Christian Kandeler
2021-09-30 13:19:50 +02:00
parent a38a703368
commit 2fcd764d56
11 changed files with 207 additions and 56 deletions

View File

@@ -36,7 +36,7 @@ add_qtc_plugin(ClangCodeModel
clangfixitoperationsextractor.cpp clangfixitoperationsextractor.h
clangfollowsymbol.cpp clangfollowsymbol.h
clangfunctionhintmodel.cpp clangfunctionhintmodel.h
clanggloballocatorfilters.cpp clanggloballocatorfilters.h
clangdlocatorfilters.cpp clangdlocatorfilters.h
clanghighlightingresultreporter.cpp clanghighlightingresultreporter.h
clanghoverhandler.cpp clanghoverhandler.h
clangisdiagnosticrelatedtolocation.h

View File

@@ -43,7 +43,7 @@ SOURCES += \
clangoverviewmodel.cpp \
clangdclient.cpp \
clangdquickfixfactory.cpp \
clanggloballocatorfilters.cpp \
clangdlocatorfilters.cpp \
HEADERS += \
clangactivationsequencecontextprocessor.h \
@@ -85,7 +85,7 @@ HEADERS += \
clangoverviewmodel.h \
clangdclient.h \
clangdquickfixfactory.h \
clanggloballocatorfilters.h \
clangdlocatorfilters.h \
FORMS += clangprojectsettingswidget.ui

View File

@@ -64,6 +64,8 @@ QtcPlugin {
"clangdiagnosticmanager.h",
"clangdiagnostictooltipwidget.cpp",
"clangdiagnostictooltipwidget.h",
"clangdlocatorfilters.cpp",
"clangdlocatorfilters.h",
"clangdquickfixfactory.cpp",
"clangdquickfixfactory.h",
"clangeditordocumentparser.cpp",
@@ -78,8 +80,6 @@ QtcPlugin {
"clangfollowsymbol.h",
"clangfunctionhintmodel.cpp",
"clangfunctionhintmodel.h",
"clanggloballocatorfilters.cpp",
"clanggloballocatorfilters.h",
"clanghighlightingresultreporter.cpp",
"clanghighlightingresultreporter.h",
"clanghoverhandler.cpp",

View File

@@ -978,31 +978,7 @@ ClangdClient::ClangdClient(Project *project, const Utils::FilePath &jsonDbDir)
};
const auto hideDiagsHandler = []{ ClangDiagnosticManager::clearTaskHubIssues(); };
setDiagnosticsHandlers(textMarkCreator, hideDiagsHandler);
static const auto symbolStringifier = [](SymbolKind kind, const QString &name,
const QString &detail) -> QString
{
switch (kind) {
case LanguageServerProtocol::SymbolKind::Constructor:
return name + detail;
case LanguageServerProtocol::SymbolKind::Method:
case LanguageServerProtocol::SymbolKind::Function: {
const int parenOffset = detail.indexOf(" (");
if (parenOffset == -1)
return name;
return name + detail.mid(parenOffset + 1) + " -> " + detail.mid(0, parenOffset);
}
case LanguageServerProtocol::SymbolKind::Variable:
case LanguageServerProtocol::SymbolKind::Field:
case LanguageServerProtocol::SymbolKind::Constant:
if (detail.isEmpty())
return name;
return name + " -> " + detail;
default:
return name;
}
};
setSymbolStringifier(symbolStringifier);
setSymbolStringifier(displayNameFromDocumentSymbol);
setSemanticTokensHandler([this](TextDocument *doc, const QList<ExpandedSemanticToken> &tokens) {
d->handleSemanticTokens(doc, tokens);
});
@@ -1236,6 +1212,30 @@ bool ClangdClient::testingEnabled() const
return d->isTesting;
}
QString ClangdClient::displayNameFromDocumentSymbol(SymbolKind kind, const QString &name,
const QString &detail)
{
switch (kind) {
case SymbolKind::Constructor:
return name + detail;
case SymbolKind::Method:
case LanguageServerProtocol::SymbolKind::Function: {
const int parenOffset = detail.indexOf(" (");
if (parenOffset == -1)
return name;
return name + detail.mid(parenOffset + 1) + " -> " + detail.mid(0, parenOffset);
}
case SymbolKind::Variable:
case SymbolKind::Field:
case SymbolKind::Constant:
if (detail.isEmpty())
return name;
return name + " -> " + detail;
default:
return name;
}
}
void ClangdClient::Private::handleFindUsagesResult(quint64 key, const QList<Location> &locations)
{
const auto refData = runningFindUsages.find(key);

View File

@@ -79,6 +79,9 @@ public:
void enableTesting();
bool testingEnabled() const;
static QString displayNameFromDocumentSymbol(LanguageServerProtocol::SymbolKind kind,
const QString &name, const QString &detail);
signals:
void indexingFinished();
void foundReferences(const QList<Core::SearchResultItem> &items);

View File

@@ -23,15 +23,17 @@
**
****************************************************************************/
#include "clanggloballocatorfilters.h"
#include "clangdlocatorfilters.h"
#include "clangdclient.h"
#include "clangmodelmanagersupport.h"
#include "clangcurrentdocumentfilter.h"
#include <cppeditor/cppeditorconstants.h>
#include <cppeditor/cpplocatorfilter.h>
#include <cppeditor/cppmodelmanager.h>
#include <cppeditor/indexitem.h>
#include <languageclient/languageclientutils.h>
#include <languageclient/locatorfilter.h>
#include <projectexplorer/session.h>
#include <utils/link.h>
@@ -39,6 +41,8 @@
#include <set>
#include <tuple>
using namespace LanguageServerProtocol;
namespace ClangCodeModel {
namespace Internal {
@@ -222,5 +226,104 @@ ClangFunctionsFilter::ClangFunctionsFilter()
setDefaultIncludedByDefault(false);
}
class CppCurrentDocumentFilter : public ClangCurrentDocumentFilter
{
public:
CppCurrentDocumentFilter()
{
setId({});
setDisplayName({});
setDefaultShortcutString({});
setEnabled(false);
setHidden(true);
}
};
class LspCurrentDocumentFilter : public LanguageClient::DocumentLocatorFilter
{
public:
LspCurrentDocumentFilter()
{
setId({});
setDisplayName({});
setDefaultShortcutString({});
setEnabled(false);
setHidden(true);
forceUse();
}
private:
Core::LocatorFilterEntry generateLocatorEntry(const DocumentSymbol &info,
const Core::LocatorFilterEntry &parent) override
{
Core::LocatorFilterEntry entry;
entry.filter = this;
entry.displayName = ClangdClient::displayNameFromDocumentSymbol(
static_cast<SymbolKind>(info.kind()), info.name(),
info.detail().value_or(QString()));
const Position &pos = info.range().start();
entry.internalData = QVariant::fromValue(Utils::LineColumn(pos.line(), pos.character()));
entry.extraInfo = parent.extraInfo;
if (!entry.extraInfo.isEmpty())
entry.extraInfo.append("::");
entry.extraInfo.append(parent.displayName);
// TODO: Can we extend clangd to send visibility information?
entry.displayIcon = LanguageClient::symbolIcon(info.kind());
return entry;
}
};
class ClangdCurrentDocumentFilter::Private
{
public:
CppCurrentDocumentFilter cppFilter;
LspCurrentDocumentFilter lspFilter;
Core::ILocatorFilter *activeFilter = nullptr;
};
ClangdCurrentDocumentFilter::ClangdCurrentDocumentFilter() : d(new Private)
{
setId(CppEditor::Constants::CURRENT_DOCUMENT_FILTER_ID);
setDisplayName(CppEditor::Constants::CURRENT_DOCUMENT_FILTER_DISPLAY_NAME);
setDefaultShortcutString(".");
setPriority(High);
setDefaultIncludedByDefault(false);
setEnabled(false);
connect(Core::EditorManager::instance(), &Core::EditorManager::currentEditorChanged,
this, [this](const Core::IEditor *editor) { setEnabled(editor); });
}
ClangdCurrentDocumentFilter::~ClangdCurrentDocumentFilter() { delete d; }
void ClangdCurrentDocumentFilter::prepareSearch(const QString &entry)
{
const auto doc = TextEditor::TextDocument::currentTextDocument();
QTC_ASSERT(doc, return);
if (const ClangdClient * const client = ClangModelManagerSupport::instance()
->clientForFile(doc->filePath()); client && client->reachable()) {
d->activeFilter = &d->lspFilter;
} else {
d->activeFilter = &d->cppFilter;
}
d->activeFilter->prepareSearch(entry);
}
QList<Core::LocatorFilterEntry> ClangdCurrentDocumentFilter::matchesFor(
QFutureInterface<Core::LocatorFilterEntry> &future, const QString &entry)
{
QTC_ASSERT(d->activeFilter, return {});
return d->activeFilter->matchesFor(future, entry);
}
void ClangdCurrentDocumentFilter::accept(Core::LocatorFilterEntry selection, QString *newText,
int *selectionStart, int *selectionLength) const
{
QTC_ASSERT(d->activeFilter, return);
d->activeFilter->accept(selection, newText, selectionStart, selectionLength);
}
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -60,5 +60,22 @@ public:
ClangFunctionsFilter();
};
class ClangdCurrentDocumentFilter : public Core::ILocatorFilter
{
public:
ClangdCurrentDocumentFilter();
~ClangdCurrentDocumentFilter() 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;
class Private;
Private * const d;
};
} // namespace Internal
} // namespace ClangCodeModel

View File

@@ -26,12 +26,11 @@
#include "clangmodelmanagersupport.h"
#include "clangconstants.h"
#include "clangcurrentdocumentfilter.h"
#include "clangdclient.h"
#include "clangdquickfixfactory.h"
#include "clangeditordocumentprocessor.h"
#include "clangfollowsymbol.h"
#include "clanggloballocatorfilters.h"
#include "clangdlocatorfilters.h"
#include "clanghoverhandler.h"
#include "clangoverviewmodel.h"
#include "clangprojectsettings.h"
@@ -113,8 +112,7 @@ ClangModelManagerSupport::ClangModelManagerSupport()
m_instance = this;
watchForExternalChanges();
CppEditor::CppModelManager::instance()->setCurrentDocumentFilter(
std::make_unique<ClangCurrentDocumentFilter>());
cppModelManager()->setCurrentDocumentFilter(std::make_unique<ClangdCurrentDocumentFilter>());
cppModelManager()->setLocatorFilter(std::make_unique<ClangGlobalSymbolFilter>());
cppModelManager()->setClassesFilter(std::make_unique<ClangClassesFilter>());
cppModelManager()->setFunctionsFilter(std::make_unique<ClangFunctionsFilter>());