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 <christian.stenger@qt.io>
This commit is contained in:
Christian Kandeler
2020-10-20 17:08:31 +02:00
parent ffb5a3977f
commit f515672ffd
3 changed files with 34 additions and 35 deletions

View File

@@ -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;

View File

@@ -3108,13 +3108,13 @@ void CppEditorPlugin::test_quickfix_GenerateGettersSetters_data()
QTest::addColumn<QByteArray>("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"

View File

@@ -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<AST *> &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<AST *> &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<AST *> &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<AST *> &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;