diff options
author | Christian Kandeler <christian.kandeler@qt.io> | 2023-11-28 14:40:53 +0100 |
---|---|---|
committer | Christian Kandeler <christian.kandeler@qt.io> | 2023-11-30 12:42:04 +0000 |
commit | a6150da07668759382701546695eea53d9ec102e (patch) | |
tree | 680bac0375bf053636b76120ebe6b0a4426026dc | |
parent | 2bb29fd9b03b090f896ff2e61a1436bb73843298 (diff) |
CppEditor: Adapt function declaration
... when changing the name of a function parameter from a point of use,
rather than from the definition.
The normal function decl/def link mechanism only covers editing in the
signature.
Task-number: QTCREATORBUG-29925
Change-Id: I34ff90117685184b9fc72937b401976274f4876c
Reviewed-by: Christian Stenger <christian.stenger@qt.io>
Reviewed-by: <github-actions-qt-creator@cristianadam.eu>
-rw-r--r-- | src/plugins/cppeditor/CMakeLists.txt | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditor.qbs | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppeditorwidget.cpp | 4 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppfunctionparamrenaminghandler.cpp | 112 | ||||
-rw-r--r-- | src/plugins/cppeditor/cppfunctionparamrenaminghandler.h | 25 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpplocalrenaming.cpp | 1 | ||||
-rw-r--r-- | src/plugins/cppeditor/cpplocalrenaming.h | 1 |
7 files changed, 146 insertions, 2 deletions
diff --git a/src/plugins/cppeditor/CMakeLists.txt b/src/plugins/cppeditor/CMakeLists.txt index 49fe02c17e..66e25f08fe 100644 --- a/src/plugins/cppeditor/CMakeLists.txt +++ b/src/plugins/cppeditor/CMakeLists.txt @@ -48,6 +48,7 @@ add_qtc_plugin(CppEditor cppfindreferences.cpp cppfindreferences.h cppfollowsymbolundercursor.cpp cppfollowsymbolundercursor.h cppfunctiondecldeflink.cpp cppfunctiondecldeflink.h + cppfunctionparamrenaminghandler.cpp cppfunctionparamrenaminghandler.h cpphighlighter.cpp cpphighlighter.h cppincludehierarchy.cpp cppincludehierarchy.h cppincludesfilter.cpp cppincludesfilter.h diff --git a/src/plugins/cppeditor/cppeditor.qbs b/src/plugins/cppeditor/cppeditor.qbs index 45a7901817..2e8581a50c 100644 --- a/src/plugins/cppeditor/cppeditor.qbs +++ b/src/plugins/cppeditor/cppeditor.qbs @@ -108,6 +108,8 @@ QtcPlugin { "cppfollowsymbolundercursor.h", "cppfunctiondecldeflink.cpp", "cppfunctiondecldeflink.h", + "cppfunctionparamrenaminghandler.cpp", + "cppfunctionparamrenaminghandler.h", "cpphighlighter.cpp", "cpphighlighter.h", "cppincludehierarchy.cpp", @@ -226,7 +228,7 @@ QtcPlugin { "symbolsfindfilter.h", "typehierarchybuilder.cpp", "typehierarchybuilder.h", - "wrappablelineedit.cpp", // FIXME: Is this used? + "wrappablelineedit.cpp", "wrappablelineedit.h", ] diff --git a/src/plugins/cppeditor/cppeditorwidget.cpp b/src/plugins/cppeditor/cppeditorwidget.cpp index dd49bbec90..aa112e0b48 100644 --- a/src/plugins/cppeditor/cppeditorwidget.cpp +++ b/src/plugins/cppeditor/cppeditorwidget.cpp @@ -11,13 +11,13 @@ #include "cppeditorplugin.h" #include "cppeditortr.h" #include "cppfunctiondecldeflink.h" +#include "cppfunctionparamrenaminghandler.h" #include "cpplocalrenaming.h" #include "cppmodelmanager.h" #include "cpppreprocessordialog.h" #include "cppquickfixassistant.h" #include "cppselectionchanger.h" #include "cppsemanticinfo.h" -#include "cpptoolssettings.h" #include "cppuseselectionsupdater.h" #include "doxygengenerator.h" @@ -396,6 +396,7 @@ public: QToolButton *m_preprocessorButton = nullptr; CppLocalRenaming m_localRenaming; + CppFunctionParamRenamingHandler m_paramRenamingHandler; CppUseSelectionsUpdater m_useSelectionsUpdater; CppSelectionChanger m_cppSelectionChanger; bool inTestMode = false; @@ -405,6 +406,7 @@ CppEditorWidgetPrivate::CppEditorWidgetPrivate(CppEditorWidget *q) : m_cppEditorDocument(qobject_cast<CppEditorDocument *>(q->textDocument())) , m_declDefLinkFinder(new FunctionDeclDefLinkFinder(q)) , m_localRenaming(q) + , m_paramRenamingHandler(*q, m_localRenaming) , m_useSelectionsUpdater(q) , m_cppSelectionChanger() {} diff --git a/src/plugins/cppeditor/cppfunctionparamrenaminghandler.cpp b/src/plugins/cppeditor/cppfunctionparamrenaminghandler.cpp new file mode 100644 index 0000000000..092e216b2d --- /dev/null +++ b/src/plugins/cppeditor/cppfunctionparamrenaminghandler.cpp @@ -0,0 +1,112 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include "cppfunctionparamrenaminghandler.h" + +#include "cppeditorwidget.h" +#include "cpplocalrenaming.h" +#include "cppfunctiondecldeflink.h" + +#include <cplusplus/AST.h> +#include <cplusplus/ASTPath.h> +#include <texteditor/textdocument.h> + +#include <memory> + +using namespace CPlusPlus; + +namespace CppEditor::Internal { + +using DeclDefLinkPtr = QSharedPointer<FunctionDeclDefLink>; + +class CppFunctionParamRenamingHandler::Private +{ +public: + Private(CppEditorWidget &editorWidget, CppLocalRenaming &localRenaming); + + void handleRenamingStarted(); + void handleRenamingFinished(); + void handleLinkFound(const DeclDefLinkPtr &link); + void findLink(FunctionDefinitionAST &func, const SemanticInfo &semanticInfo); + + CppEditorWidget &editorWidget; + CppLocalRenaming &localRenaming; + std::unique_ptr<FunctionDeclDefLinkFinder> linkFinder; + DeclDefLinkPtr link; +}; + +CppFunctionParamRenamingHandler::CppFunctionParamRenamingHandler( + CppEditorWidget &editorWidget, CppLocalRenaming &localRenaming) + : d(new Private(editorWidget, localRenaming)) {} + +CppFunctionParamRenamingHandler::~CppFunctionParamRenamingHandler() { delete d; } + +CppFunctionParamRenamingHandler::Private::Private( + CppEditorWidget &editorWidget, CppLocalRenaming &localRenaming) + : editorWidget(editorWidget), localRenaming(localRenaming) +{ + QObject::connect(&localRenaming, &CppLocalRenaming::started, + &editorWidget, [this] { handleRenamingStarted(); }); + QObject::connect(&localRenaming, &CppLocalRenaming::finished, + &editorWidget, [this] { handleRenamingFinished(); }); +} + +void CppFunctionParamRenamingHandler::Private::handleRenamingStarted() +{ + linkFinder.reset(); + link.clear(); + + // Are we currently on the function signature? In this case, the normal decl/def link + // mechanism kicks in and we don't have to do anything. + if (editorWidget.declDefLink()) + return; + + // If we find a surrounding function definition, start up the decl/def link finder. + const SemanticInfo semanticInfo = editorWidget.semanticInfo(); + if (!semanticInfo.doc || !semanticInfo.doc->translationUnit()) + return; + const QList<AST *> astPath = ASTPath(semanticInfo.doc)(editorWidget.textCursor()); + for (auto it = astPath.rbegin(); it != astPath.rend(); ++it) { + if (const auto func = (*it)->asFunctionDefinition()) { + findLink(*func, semanticInfo); + return; + } + } +} + +void CppFunctionParamRenamingHandler::Private::handleRenamingFinished() +{ + if (link) { + link->apply(&editorWidget, false); + link.clear(); + } +} + +void CppFunctionParamRenamingHandler::Private::handleLinkFound(const DeclDefLinkPtr &link) +{ + if (localRenaming.isActive()) + this->link = link; + linkFinder.reset(); +} + +void CppFunctionParamRenamingHandler::Private::findLink(FunctionDefinitionAST &func, + const SemanticInfo &semanticInfo) +{ + if (!func.declarator) + return; + + // The finder needs a cursor that points to the signature, so provide one. + QTextDocument * const doc = editorWidget.textDocument()->document(); + const int pos = semanticInfo.doc->translationUnit()->getTokenEndPositionInDocument( + func.declarator->firstToken(), doc); + QTextCursor cursor(doc); + cursor.setPosition(pos); + linkFinder.reset(new FunctionDeclDefLinkFinder); + QObject::connect(linkFinder.get(), &FunctionDeclDefLinkFinder::foundLink, + &editorWidget, [this](const DeclDefLinkPtr &link) { + handleLinkFound(link); + }); + linkFinder->startFindLinkAt(cursor, semanticInfo.doc, semanticInfo.snapshot); +} + +} // namespace CppEditor::Internal diff --git a/src/plugins/cppeditor/cppfunctionparamrenaminghandler.h b/src/plugins/cppeditor/cppfunctionparamrenaminghandler.h new file mode 100644 index 0000000000..e923855ca6 --- /dev/null +++ b/src/plugins/cppeditor/cppfunctionparamrenaminghandler.h @@ -0,0 +1,25 @@ +// Copyright (C) 2023 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#pragma once + +namespace CppEditor { +class CppEditorWidget; + +namespace Internal { +class CppLocalRenaming; + +// Watches local renamings and adapts the declaration if a function parameter was renamed. +class CppFunctionParamRenamingHandler +{ +public: + CppFunctionParamRenamingHandler(CppEditorWidget &editorWidget, CppLocalRenaming &localRenaming); + ~CppFunctionParamRenamingHandler(); + +private: + class Private; + Private * const d; +}; + +} // namespace Internal +} // namespace CppEditor diff --git a/src/plugins/cppeditor/cpplocalrenaming.cpp b/src/plugins/cppeditor/cpplocalrenaming.cpp index f23b9d80a6..5bad16a0b6 100644 --- a/src/plugins/cppeditor/cpplocalrenaming.cpp +++ b/src/plugins/cppeditor/cpplocalrenaming.cpp @@ -62,6 +62,7 @@ bool CppLocalRenaming::start() updateRenamingSelectionFormat(textCharFormat(TextEditor::C_OCCURRENCES_RENAME)); m_firstRenameChangeExpected = true; updateEditorWidgetWithSelections(); + emit started(); return true; } diff --git a/src/plugins/cppeditor/cpplocalrenaming.h b/src/plugins/cppeditor/cpplocalrenaming.h index 082d4648a8..56ff153044 100644 --- a/src/plugins/cppeditor/cpplocalrenaming.h +++ b/src/plugins/cppeditor/cpplocalrenaming.h @@ -41,6 +41,7 @@ public: bool isSameSelection(int cursorPosition) const; signals: + void started(); void finished(); void processKeyPressNormally(QKeyEvent *e); |