From f515672ffddb12d894251a6584154ee60abdf07f Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 20 Oct 2020 17:08:31 +0200 Subject: CppEditor: Offer class-level quickfixes also when clicking "in class" That is, allow the cursor to on some "neutral" place in the body of the declaration, not only strictly on the class name. Fixes: QTCREATORBUG-15699 Change-Id: I74ad6048c16c19d418446c990178535d878fc630 Reviewed-by: Christian Stenger --- src/plugins/cppeditor/cppinsertvirtualmethods.cpp | 5 ++ src/plugins/cppeditor/cppquickfix_test.cpp | 6 +-- src/plugins/cppeditor/cppquickfixes.cpp | 58 ++++++++++------------- 3 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp index 209ad213a9..1b23618b62 100644 --- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp +++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp @@ -538,6 +538,11 @@ public: m_classAST = path.at(index)->asClassSpecifier(); } } + + // Also offer the operation if we are on some "empty" part of the class declaration. + if (!m_classAST) + m_classAST = path.at(pathSize - 1)->asClassSpecifier(); + if (!m_classAST || !m_classAST->base_clause_list) return; diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index a023342e3f..da2e62e676 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -3108,13 +3108,13 @@ void CppEditorPlugin::test_quickfix_GenerateGettersSetters_data() QTest::addColumn("expected"); const QByteArray onlyReset = R"( -class @Foo { +class Foo { public: int bar() const; void setBar(int bar); private: int m_bar; -};)"; +@};)"; const QByteArray onlyResetAfter = R"( class @Foo { @@ -6374,7 +6374,7 @@ void CppEditorPlugin::test_quickfix_MoveAllFuncDefOutside_MemberFuncToCpp() // Header File original = - "class Fo@o {\n" + "class Foo {@\n" " int numberA() const\n" " {\n" " return 5;\n" diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 867740aea8..1e0fbd9f07 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -641,6 +641,28 @@ QString memberBaseName(const QString &name) return baseName; } +// Returns a non-null value if and only if the cursor is on the name of a (proper) class +// declaration or at some place inside the body of a class declaration that does not +// correspond to an AST of its own, i.e. on "empty space". +ClassSpecifierAST *astForClassOperations(const CppQuickFixInterface &interface) +{ + const QList &path = interface.path(); + if (path.isEmpty()) + return nullptr; + if (const auto classSpec = path.last()->asClassSpecifier()) // Cursor inside class decl? + return classSpec; + + // Cursor on a class name? + if (path.size() < 2) + return nullptr; + const SimpleNameAST * const nameAST = path.at(path.size() - 1)->asSimpleName(); + if (!nameAST || !interface.isCursorOn(nameAST)) + return nullptr; + if (const auto classSpec = path.at(path.size() - 2)->asClassSpecifier()) + return classSpec; + return nullptr; +} + } // anonymous namespace namespace { @@ -3476,15 +3498,7 @@ public: { setDescription(CppQuickFixFactory::tr("Create Implementations for Member Functions")); - const QList &path = interface.path(); - if (path.size() < 2) - return; - - // Determine if cursor is on a class - const SimpleNameAST * const nameAST = path.at(path.size() - 1)->asSimpleName(); - if (!nameAST || !interface.isCursorOn(nameAST)) - return; - m_classAST = path.at(path.size() - 2)->asClassSpecifier(); + m_classAST = astForClassOperations(interface); if (!m_classAST) return; const Class * const theClass = m_classAST->symbol; @@ -4834,19 +4848,10 @@ public: { setDescription(CppQuickFixFactory::tr("Create Getter and Setter Member Functions")); - const QList &path = interface.path(); - if (path.size() < 2) - return; - - // Determine if cursor is on a class - const SimpleNameAST *const nameAST = path.at(path.size() - 1)->asSimpleName(); - if (!nameAST || !interface.isCursorOn(nameAST)) - return; - m_classAST = path.at(path.size() - 2)->asClassSpecifier(); + m_classAST = astForClassOperations(interface); if (!m_classAST) return; - - Class *const theClass = m_classAST->symbol; + Class * const theClass = m_classAST->symbol; if (!theClass) return; @@ -6682,18 +6687,7 @@ private: void MoveAllFuncDefOutside::match(const CppQuickFixInterface &interface, QuickFixOperations &result) { - const QList &path = interface.path(); - const int pathSize = path.size(); - if (pathSize < 2) - return; - - // Determine if cursor is on a class which is not a base class - ClassSpecifierAST *classAST = nullptr; - if (SimpleNameAST *nameAST = path.at(pathSize - 1)->asSimpleName()) { - if (!interface.isCursorOn(nameAST)) - return; - classAST = path.at(pathSize - 2)->asClassSpecifier(); - } + ClassSpecifierAST * const classAST = astForClassOperations(interface); if (!classAST) return; -- cgit v1.2.3