diff --git a/src/libs/languageserverprotocol/lsptypes.h b/src/libs/languageserverprotocol/lsptypes.h index 3231f010a29..4348e4fd19d 100644 --- a/src/libs/languageserverprotocol/lsptypes.h +++ b/src/libs/languageserverprotocol/lsptypes.h @@ -40,6 +40,8 @@ #include #include +#include + namespace LanguageServerProtocol { class LANGUAGESERVERPROTOCOL_EXPORT DocumentUri : public QUrl @@ -560,6 +562,7 @@ enum class SymbolKind { TypeParameter = 26, LastSymbolKind = TypeParameter, }; +using SymbolStringifier = std::function; namespace CompletionItemKind { enum Kind { diff --git a/src/plugins/clangcodemodel/clangdclient.cpp b/src/plugins/clangcodemodel/clangdclient.cpp index 134d4bf6103..bbdbb9cec7a 100644 --- a/src/plugins/clangcodemodel/clangdclient.cpp +++ b/src/plugins/clangcodemodel/clangdclient.cpp @@ -732,6 +732,31 @@ 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); + hoverHandler()->setHelpItemProvider([this](const HoverRequest::Response &response, const DocumentUri &uri) { gatherHelpItemForTooltip(response, uri); diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp index db97618a1c3..90be3893dfc 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.cpp @@ -171,6 +171,11 @@ std::unique_ptr ClangModelManagerSupport::creat return std::make_unique(); } +bool ClangModelManagerSupport::supportsOutline(const TextEditor::TextDocument *document) const +{ + return !clientForFile(document->filePath()); +} + CppTools::BaseEditorDocumentProcessor *ClangModelManagerSupport::createEditorDocumentProcessor( TextEditor::TextDocument *baseTextDocument) { @@ -344,7 +349,7 @@ void ClangModelManagerSupport::updateLanguageClient(ProjectExplorer::Project *pr } ClangdClient *ClangModelManagerSupport::clientForProject( - const ProjectExplorer::Project *project) + const ProjectExplorer::Project *project) const { const QList clients = Utils::filtered( LanguageClientManager::clientsForProject(project), @@ -357,7 +362,7 @@ ClangdClient *ClangModelManagerSupport::clientForProject( return clients.empty() ? nullptr : qobject_cast(clients.first()); } -ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) +ClangdClient *ClangModelManagerSupport::clientForFile(const Utils::FilePath &file) const { return clientForProject(ProjectExplorer::SessionManager::projectForFile(file)); } diff --git a/src/plugins/clangcodemodel/clangmodelmanagersupport.h b/src/plugins/clangcodemodel/clangmodelmanagersupport.h index 9122e7a7a45..97a0bfaf275 100644 --- a/src/plugins/clangcodemodel/clangmodelmanagersupport.h +++ b/src/plugins/clangcodemodel/clangmodelmanagersupport.h @@ -72,6 +72,7 @@ public: CppTools::FollowSymbolInterface &followSymbolInterface() override; CppTools::RefactoringEngineInterface &refactoringEngineInterface() override; std::unique_ptr createOverviewModel() override; + bool supportsOutline(const TextEditor::TextDocument *document) const override; BackendCommunicator &communicator(); QString dummyUiHeaderOnDiskDirPath() const; @@ -79,8 +80,8 @@ public: ClangProjectSettings &projectSettings(ProjectExplorer::Project *project) const; - ClangdClient *clientForProject(const ProjectExplorer::Project *project); - ClangdClient *clientForFile(const Utils::FilePath &file); + ClangdClient *clientForProject(const ProjectExplorer::Project *project) const; + ClangdClient *clientForFile(const Utils::FilePath &file) const; static ClangModelManagerSupport *instance(); diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index 74ae3d5c843..ee242640bc0 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -118,7 +118,7 @@ public: QPointer m_modelManager; CppEditorDocument *m_cppEditorDocument; - CppEditorOutline *m_cppEditorOutline; + CppEditorOutline *m_cppEditorOutline = nullptr; QTimer m_updateFunctionDeclDefLinkTimer; SemanticInfo m_lastSemanticInfo; @@ -139,7 +139,6 @@ public: CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) : m_modelManager(CppModelManager::instance()) , m_cppEditorDocument(qobject_cast(q->textDocument())) - , m_cppEditorOutline(new CppEditorOutline(q)) , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q)) , m_localRenaming(q) , m_useSelectionsUpdater(q) @@ -160,8 +159,11 @@ void CppEditorWidget::finalizeInitialization() // clang-format off // function combo box sorting - connect(CppEditorPlugin::instance(), &CppEditorPlugin::outlineSortingChanged, - outline(), &CppEditorOutline::setSorted); + if (CppModelManager::supportsOutline(d->m_cppEditorDocument)) { + d->m_cppEditorOutline = new CppEditorOutline(this); + connect(CppEditorPlugin::instance(), &CppEditorPlugin::outlineSortingChanged, + outline(), &CppEditorOutline::setSorted); + } connect(d->m_cppEditorDocument, &CppEditorDocument::codeWarningsUpdated, this, &CppEditorWidget::onCodeWarningsUpdated); @@ -195,8 +197,10 @@ void CppEditorWidget::finalizeInitialization() }); connect(&d->m_localRenaming, &CppLocalRenaming::processKeyPressNormally, this, &CppEditorWidget::processKeyNormally); - connect(this, &QPlainTextEdit::cursorPositionChanged, - d->m_cppEditorOutline, &CppEditorOutline::updateIndex); + if (d->m_cppEditorOutline) { + connect(this, &QPlainTextEdit::cursorPositionChanged, + d->m_cppEditorOutline, &CppEditorOutline::updateIndex); + } connect(cppEditorDocument(), &CppEditorDocument::preprocessorSettingsChanged, this, [this](bool customSettings) { @@ -232,7 +236,8 @@ void CppEditorWidget::finalizeInitialization() }); // Toolbar: Outline/Overview combo box - insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget()); + if (d->m_cppEditorOutline) + insertExtraToolBarWidget(TextEditorWidget::Left, d->m_cppEditorOutline->widget()); // clang-format on // Toolbar: '#' Button @@ -266,7 +271,8 @@ void CppEditorWidget::finalizeInitializationAfterDuplication(TextEditorWidget *o if (cppEditorWidget->isSemanticInfoValidExceptLocalUses()) updateSemanticInfo(cppEditorWidget->semanticInfo()); - d->m_cppEditorOutline->update(); + if (d->m_cppEditorOutline) + d->m_cppEditorOutline->update(); const Id selectionKind = CodeWarningsSelection; setExtraSelections(selectionKind, cppEditorWidget->extraSelections(selectionKind)); @@ -325,7 +331,8 @@ void CppEditorWidget::selectAll() void CppEditorWidget::onCppDocumentUpdated() { - d->m_cppEditorOutline->update(); + if (d->m_cppEditorOutline) + d->m_cppEditorOutline->update(); } void CppEditorWidget::onCodeWarningsUpdated(unsigned revision, diff --git a/src/plugins/cppeditor/cppoutline.cpp b/src/plugins/cppeditor/cppoutline.cpp index c071f61a437..758b11b1fb3 100644 --- a/src/plugins/cppeditor/cppoutline.cpp +++ b/src/plugins/cppeditor/cppoutline.cpp @@ -28,6 +28,7 @@ #include "cppeditor.h" #include +#include #include #include @@ -212,7 +213,10 @@ bool CppOutlineWidget::syncCursor() bool CppOutlineWidgetFactory::supportsEditor(Core::IEditor *editor) const { - return qobject_cast(editor); + const auto cppEditor = qobject_cast(editor); + if (!cppEditor) + return false; + return CppTools::CppModelManager::supportsOutline(cppEditor->textDocument()); } TextEditor::IOutlineWidget *CppOutlineWidgetFactory::createWidget(Core::IEditor *editor) diff --git a/src/plugins/cpptools/cppmodelmanager.cpp b/src/plugins/cpptools/cppmodelmanager.cpp index fbee2cebbd5..f92248b2228 100644 --- a/src/plugins/cpptools/cppmodelmanager.cpp +++ b/src/plugins/cpptools/cppmodelmanager.cpp @@ -1310,6 +1310,11 @@ bool CppModelManager::isCppEditor(Core::IEditor *editor) return editor->context().contains(ProjectExplorer::Constants::CXX_LANGUAGE_ID); } +bool CppModelManager::supportsOutline(const TextEditor::TextDocument *document) +{ + return instance()->d->m_activeModelManagerSupport->supportsOutline(document); +} + bool CppModelManager::isClangCodeModelActive() const { return d->m_activeModelManagerSupport != d->m_builtinModelManagerSupport; diff --git a/src/plugins/cpptools/cppmodelmanager.h b/src/plugins/cpptools/cppmodelmanager.h index 98991f9c6ce..402f37bee6d 100644 --- a/src/plugins/cpptools/cppmodelmanager.h +++ b/src/plugins/cpptools/cppmodelmanager.h @@ -142,6 +142,7 @@ public: void emitAbstractEditorSupportRemoved(const QString &filePath); static bool isCppEditor(Core::IEditor *editor); + static bool supportsOutline(const TextEditor::TextDocument *document); bool isClangCodeModelActive() const; QSet abstractEditorSupports() const; diff --git a/src/plugins/cpptools/cppmodelmanagersupport.h b/src/plugins/cpptools/cppmodelmanagersupport.h index ccf7ee83de6..13b6108fab2 100644 --- a/src/plugins/cpptools/cppmodelmanagersupport.h +++ b/src/plugins/cpptools/cppmodelmanagersupport.h @@ -61,6 +61,7 @@ public: virtual FollowSymbolInterface &followSymbolInterface() = 0; virtual RefactoringEngineInterface &refactoringEngineInterface() = 0; virtual std::unique_ptr createOverviewModel() = 0; + virtual bool supportsOutline(const TextEditor::TextDocument *) const { return true; } }; class CPPTOOLS_EXPORT ModelManagerSupportProvider diff --git a/src/plugins/languageclient/client.cpp b/src/plugins/languageclient/client.cpp index 2930146cdc5..5f40a3cc852 100644 --- a/src/plugins/languageclient/client.cpp +++ b/src/plugins/languageclient/client.cpp @@ -1003,6 +1003,16 @@ void Client::setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator, m_diagnosticManager.setDiagnosticsHandlers(textMarkCreator, hideHandler); } +void Client::setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier) +{ + m_symbolStringifier = stringifier; +} + +SymbolStringifier Client::symbolStringifier() const +{ + return m_symbolStringifier; +} + void Client::start() { if (m_clientInterface->start()) diff --git a/src/plugins/languageclient/client.h b/src/plugins/languageclient/client.h index 6fd0f3f2934..f45e79bb995 100644 --- a/src/plugins/languageclient/client.h +++ b/src/plugins/languageclient/client.h @@ -174,6 +174,8 @@ public: const LanguageServerProtocol::Diagnostic &diag) const; void setDiagnosticsHandlers(const TextMarkCreator &textMarkCreator, const HideDiagnosticsHandler &hideHandler); + void setSymbolStringifier(const LanguageServerProtocol::SymbolStringifier &stringifier); + LanguageServerProtocol::SymbolStringifier symbolStringifier() const; // logging void log(const QString &message) const; @@ -270,6 +272,7 @@ private: SemanticTokenSupport m_tokentSupport; QString m_serverName; QString m_serverVersion; + LanguageServerProtocol::SymbolStringifier m_symbolStringifier; bool m_locatorsEnabled = true; }; diff --git a/src/plugins/languageclient/languageclientoutline.cpp b/src/plugins/languageclient/languageclientoutline.cpp index c83a35411f8..4257efb1ff8 100644 --- a/src/plugins/languageclient/languageclientoutline.cpp +++ b/src/plugins/languageclient/languageclientoutline.cpp @@ -55,14 +55,15 @@ public: , m_type(info.kind()) { } - LanguageClientOutlineItem(const DocumentSymbol &info) + LanguageClientOutlineItem(const DocumentSymbol &info, const SymbolStringifier &stringifier) : m_name(info.name()) , m_detail(info.detail().value_or(QString())) , m_range(info.range()) + , m_symbolStringifier(stringifier) , m_type(info.kind()) { for (const DocumentSymbol &child : info.children().value_or(QList())) - appendChild(new LanguageClientOutlineItem(child)); + appendChild(new LanguageClientOutlineItem(child, stringifier)); } // TreeItem interface @@ -72,7 +73,9 @@ public: case Qt::DecorationRole: return symbolIcon(m_type); case Qt::DisplayRole: - return m_name; + return m_symbolStringifier + ? m_symbolStringifier(static_cast(m_type), m_name, m_detail) + : m_name; default: return Utils::TreeItem::data(column, role); } @@ -85,6 +88,7 @@ private: QString m_name; QString m_detail; Range m_range; + SymbolStringifier m_symbolStringifier; int m_type = -1; }; @@ -102,8 +106,16 @@ public: { clear(); for (const DocumentSymbol &symbol : info) - rootItem()->appendChild(new LanguageClientOutlineItem(symbol)); + rootItem()->appendChild(new LanguageClientOutlineItem(symbol, m_symbolStringifier)); } + + void setSymbolStringifier(const SymbolStringifier &stringifier) + { + m_symbolStringifier = stringifier; + } + +private: + SymbolStringifier m_symbolStringifier; }; class LanguageClientOutlineWidget : public TextEditor::IOutlineWidget @@ -153,6 +165,7 @@ LanguageClientOutlineWidget::LanguageClientOutlineWidget(Client *client, layout->setSpacing(0); layout->addWidget(Core::ItemViewFind::createSearchableWrapper(&m_view)); setLayout(layout); + m_model.setSymbolStringifier(m_client->symbolStringifier()); m_view.setModel(&m_model); m_view.setHeaderHidden(true); m_view.setExpandsOnDoubleClick(false); @@ -295,6 +308,7 @@ OutlineComboBox::OutlineComboBox(Client *client, TextEditor::BaseTextEditor *edi , m_editorWidget(editor->editorWidget()) , m_uri(DocumentUri::fromFilePath(editor->document()->filePath())) { + m_model.setSymbolStringifier(client->symbolStringifier()); setModel(&m_model); setMinimumContentsLength(13); QSizePolicy policy = sizePolicy();