diff --git a/src/plugins/clangcodemodel/CMakeLists.txt b/src/plugins/clangcodemodel/CMakeLists.txt index 9336c29d830..ace1b99575c 100644 --- a/src/plugins/clangcodemodel/CMakeLists.txt +++ b/src/plugins/clangcodemodel/CMakeLists.txt @@ -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 diff --git a/src/plugins/clangcodemodel/clangcodemodel.pro b/src/plugins/clangcodemodel/clangcodemodel.pro index 57eeb22d870..5675ea9d57e 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.pro +++ b/src/plugins/clangcodemodel/clangcodemodel.pro @@ -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 diff --git a/src/plugins/clangcodemodel/clangcodemodel.qbs b/src/plugins/clangcodemodel/clangcodemodel.qbs index 42c3e4df9d1..7b6689ad45f 100644 --- a/src/plugins/clangcodemodel/clangcodemodel.qbs +++ b/src/plugins/clangcodemodel/clangcodemodel.qbs @@ -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", diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 7a6c1045ec3..fea5314001e 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -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 &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 &locations) { const auto refData = runningFindUsages.find(key); diff --git a/src/plugins/clangcodemodel/clangdclient.h b/src/plugins/clangcodemodel/clangdclient.h index bec77b9261e..03675516616 100644 --- a/src/plugins/clangcodemodel/clangdclient.h +++ b/src/plugins/clangcodemodel/clangdclient.h @@ -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 &items); diff --git a/src/plugins/clangcodemodel/clanggloballocatorfilters.cpp b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp similarity index 67% rename from src/plugins/clangcodemodel/clanggloballocatorfilters.cpp rename to src/plugins/clangcodemodel/clangdlocatorfilters.cpp index 4bc23a974a1..cafd7633d7d 100644 --- a/src/plugins/clangcodemodel/clanggloballocatorfilters.cpp +++ b/src/plugins/clangcodemodel/clangdlocatorfilters.cpp @@ -23,15 +23,17 @@ ** ****************************************************************************/ -#include "clanggloballocatorfilters.h" +#include "clangdlocatorfilters.h" #include "clangdclient.h" #include "clangmodelmanagersupport.h" +#include "clangcurrentdocumentfilter.h" #include #include #include #include +#include #include #include #include @@ -39,6 +41,8 @@ #include #include +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(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 ClangdCurrentDocumentFilter::matchesFor( + QFutureInterface &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 diff --git a/src/plugins/clangcodemodel/clanggloballocatorfilters.h b/src/plugins/clangcodemodel/clangdlocatorfilters.h similarity index 79% rename from src/plugins/clangcodemodel/clanggloballocatorfilters.h rename to src/plugins/clangcodemodel/clangdlocatorfilters.h index e01ac4b3568..28341a6a573 100644 --- a/src/plugins/clangcodemodel/clanggloballocatorfilters.h +++ b/src/plugins/clangcodemodel/clangdlocatorfilters.h @@ -60,5 +60,22 @@ public: ClangFunctionsFilter(); }; +class ClangdCurrentDocumentFilter : public Core::ILocatorFilter +{ +public: + ClangdCurrentDocumentFilter(); + ~ClangdCurrentDocumentFilter() override; + +private: + void prepareSearch(const QString &entry) override; + QList matchesFor(QFutureInterface &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 diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index a2dca2aab35..52be361305a 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -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()); + cppModelManager()->setCurrentDocumentFilter(std::make_unique()); cppModelManager()->setLocatorFilter(std::make_unique()); cppModelManager()->setClassesFilter(std::make_unique()); cppModelManager()->setFunctionsFilter(std::make_unique()); diff --git a/src/plugins/languageclient/languageclientutils.h b/src/plugins/languageclient/languageclientutils.h index d73e052590d..c8120766077 100644 --- a/src/plugins/languageclient/languageclientutils.h +++ b/src/plugins/languageclient/languageclientutils.h @@ -61,6 +61,6 @@ updateCodeActionRefactoringMarker(Client *client, const LanguageServerProtocol::CodeAction &action, const LanguageServerProtocol::DocumentUri &uri); void updateEditorToolBar(Core::IEditor *editor); -const QIcon symbolIcon(int type); +const QIcon LANGUAGECLIENT_EXPORT symbolIcon(int type); } // namespace LanguageClient diff --git a/src/plugins/languageclient/locatorfilter.cpp b/src/plugins/languageclient/locatorfilter.cpp index d5cac61d669..11588cc2ad2 100644 --- a/src/plugins/languageclient/locatorfilter.cpp +++ b/src/plugins/languageclient/locatorfilter.cpp @@ -63,8 +63,8 @@ void DocumentLocatorFilter::updateCurrentClient() TextEditor::TextDocument *document = TextEditor::TextDocument::currentTextDocument(); if (Client *client = LanguageClientManager::clientForDocument(document); - client && client->locatorsEnabled()) { - setEnabled(true); + client && (client->locatorsEnabled() || m_forced)) { + setEnabled(!m_forced); if (m_symbolCache != client->documentSymbolCache()) { disconnect(m_updateSymbolsConnection); m_symbolCache = client->documentSymbolCache(); @@ -98,8 +98,8 @@ void DocumentLocatorFilter::resetSymbols() m_currentSymbols.reset(); } -Core::LocatorFilterEntry generateLocatorEntry(const SymbolInformation &info, - Core::ILocatorFilter *filter) +static Core::LocatorFilterEntry generateLocatorEntry(const SymbolInformation &info, + Core::ILocatorFilter *filter) { Core::LocatorFilterEntry entry; entry.filter = filter; @@ -109,22 +109,31 @@ Core::LocatorFilterEntry generateLocatorEntry(const SymbolInformation &info, entry.displayIcon = symbolIcon(info.kind()); entry.internalData = QVariant::fromValue(info.location().toLink()); return entry; + } -QList generateLocatorEntries(const SymbolInformation &info, - Core::ILocatorFilter *filter, - const QRegularExpression ®exp) +Core::LocatorFilterEntry DocumentLocatorFilter::generateLocatorEntry(const SymbolInformation &info) { - if (!regexp.match(info.name()).hasMatch()) - return { generateLocatorEntry(info, filter) }; + return LanguageClient::generateLocatorEntry(info, this); +} + +QList DocumentLocatorFilter::generateLocatorEntries( + const SymbolInformation &info, const QRegularExpression ®exp, + const Core::LocatorFilterEntry &parent) +{ + Q_UNUSED(parent) + if (regexp.match(info.name()).hasMatch()) + return {generateLocatorEntry(info)}; return {}; } -Core::LocatorFilterEntry generateLocatorEntry(const DocumentSymbol &info, - Core::ILocatorFilter *filter) +Core::LocatorFilterEntry DocumentLocatorFilter::generateLocatorEntry( + const DocumentSymbol &info, + const Core::LocatorFilterEntry &parent) { + Q_UNUSED(parent) Core::LocatorFilterEntry entry; - entry.filter = filter; + entry.filter = this; entry.displayName = info.name(); if (Utils::optional detail = info.detail()) entry.extraInfo = detail.value_or(QString()); @@ -134,16 +143,20 @@ Core::LocatorFilterEntry generateLocatorEntry(const DocumentSymbol &info, return entry; } -QList generateLocatorEntries(const DocumentSymbol &info, - Core::ILocatorFilter *filter, - const QRegularExpression ®exp) +QList DocumentLocatorFilter::generateLocatorEntries( + const DocumentSymbol &info, const QRegularExpression ®exp, + const Core::LocatorFilterEntry &parent) { QList entries; - if (regexp.match(info.name()).hasMatch()) - entries << generateLocatorEntry(info, filter); const QList children = info.children().value_or(QList()); + const bool hasMatch = regexp.match(info.name()).hasMatch(); + Core::LocatorFilterEntry entry; + if (hasMatch || !children.isEmpty()) + entry = generateLocatorEntry(info, parent); + if (hasMatch) + entries << entry; for (const DocumentSymbol &child : children) - entries << generateLocatorEntries(child, filter, regexp); + entries << generateLocatorEntries(child, regexp, entry); return entries; } @@ -161,7 +174,7 @@ QList DocumentLocatorFilter::generateEntries(const QLi return entries; for (const T &item : list) - entries << generateLocatorEntries(item, this, regexp); + entries << generateLocatorEntries(item, regexp, {}); return entries; } diff --git a/src/plugins/languageclient/locatorfilter.h b/src/plugins/languageclient/locatorfilter.h index 6ef079ec45f..ebc35de57a7 100644 --- a/src/plugins/languageclient/locatorfilter.h +++ b/src/plugins/languageclient/locatorfilter.h @@ -26,6 +26,7 @@ #pragma once #include "client.h" +#include "languageclient_global.h" #include #include @@ -38,7 +39,7 @@ namespace Core { class IEditor; } namespace LanguageClient { -class DocumentLocatorFilter : public Core::ILocatorFilter +class LANGUAGECLIENT_EXPORT DocumentLocatorFilter : public Core::ILocatorFilter { Q_OBJECT public: @@ -57,6 +58,8 @@ signals: void symbolsUpToDate(QPrivateSignal); protected: + void forceUse() { m_forced = true; } + QPointer m_symbolCache; LanguageServerProtocol::DocumentUri m_currentUri; @@ -67,11 +70,25 @@ private: template QList generateEntries(const QList &list, const QString &filter); + QList generateLocatorEntries( + const LanguageServerProtocol::SymbolInformation &info, + const QRegularExpression ®exp, + const Core::LocatorFilterEntry &parent); + QList generateLocatorEntries( + const LanguageServerProtocol::DocumentSymbol &info, + const QRegularExpression ®exp, + const Core::LocatorFilterEntry &parent); + virtual Core::LocatorFilterEntry generateLocatorEntry( + const LanguageServerProtocol::DocumentSymbol &info, + const Core::LocatorFilterEntry &parent); + virtual Core::LocatorFilterEntry generateLocatorEntry( + const LanguageServerProtocol::SymbolInformation &info); QMutex m_mutex; QMetaObject::Connection m_updateSymbolsConnection; QMetaObject::Connection m_resetSymbolsConnection; Utils::optional m_currentSymbols; + bool m_forced = false; }; class LANGUAGECLIENT_EXPORT WorkspaceLocatorFilter : public Core::ILocatorFilter