From 5e73bacb0ef260c841fb62875948b8f2f9770ca3 Mon Sep 17 00:00:00 2001 From: Christian Kandeler Date: Tue, 25 Apr 2023 17:51:25 +0200 Subject: [PATCH] CppEditor: Merge two factories They are closely related, and we might want to add more variants of this functionality. Change-Id: Ida83cce018fad5a84d5f6d24a0fa4ff2bca5a67b Reviewed-by: Christian Stenger --- src/plugins/cppeditor/cppquickfix_test.cpp | 4 +- src/plugins/cppeditor/cppquickfixes.cpp | 107 +++++++++++---------- src/plugins/cppeditor/cppquickfixes.h | 26 +---- 3 files changed, 62 insertions(+), 75 deletions(-) diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index 9c2c011dc5a..badf896a5c9 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -1725,7 +1725,7 @@ void QuickfixTest::testGeneric_data() << _(R"(const char *str = @"\xc3\xa0""f23\xd0\xb1g\xd0\xb1""1";)") << _(R"(const char *str = "àf23бgб1";)"); QTest::newRow("AddLocalDeclaration_QTCREATORBUG-26004") - << CppQuickFixFactoryPtr(new AddLocalDeclaration) + << CppQuickFixFactoryPtr(new AddDeclarationForUndeclaredIdentifier) << _("void func() {\n" " QStringList list;\n" " @it = list.cbegin();\n" @@ -3863,7 +3863,7 @@ void QuickfixTest::testInsertMemberFromInitialization() CppTestDocument::create("file.h", original, expected) }); - InsertMemberFromInitialization factory; + AddDeclarationForUndeclaredIdentifier factory; QuickFixOperationTest(testDocuments, &factory); } diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index 1c76f8f2c57..e0671d6412f 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -1646,42 +1646,6 @@ private: } // anonymous namespace -void AddLocalDeclaration::match(const CppQuickFixInterface &interface, QuickFixOperations &result) -{ - const QList &path = interface.path(); - CppRefactoringFilePtr file = interface.currentFile(); - - for (int index = path.size() - 1; index != -1; --index) { - if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) { - if (binary->left_expression && binary->right_expression - && file->tokenAt(binary->binary_op_token).is(T_EQUAL)) { - IdExpressionAST *idExpr = binary->left_expression->asIdExpression(); - if (interface.isCursorOn(binary->left_expression) && idExpr - && idExpr->name->asSimpleName() != nullptr) { - SimpleNameAST *nameAST = idExpr->name->asSimpleName(); - const QList results = interface.context().lookup(nameAST->name, file->scopeAt(nameAST->firstToken())); - Declaration *decl = nullptr; - for (const LookupItem &r : results) { - if (!r.declaration()) - continue; - if (Declaration *d = r.declaration()->asDeclaration()) { - if (!d->type()->asFunctionType()) { - decl = d; - break; - } - } - } - - if (!decl) { - result << new AddLocalDeclarationOp(interface, index, binary, nameAST); - return; - } - } - } - } - } -} - namespace { class ConvertToCamelCaseOp: public CppQuickFixOperation @@ -2980,25 +2944,64 @@ private: const QString m_type; }; -void InsertMemberFromInitialization::match(const CppQuickFixInterface &interface, +void AddDeclarationForUndeclaredIdentifier::match(const CppQuickFixInterface &interface, QuickFixOperations &result) { - // First check whether we are on a member initialization. + if (!checkForMemberInitializer(interface, result)) + return; + + const CppRefactoringFilePtr &file = interface.currentFile(); const QList path = interface.path(); + for (int index = path.size() - 1; index != -1; --index) { + if (BinaryExpressionAST *binary = path.at(index)->asBinaryExpression()) { + if (binary->left_expression && binary->right_expression + && file->tokenAt(binary->binary_op_token).is(T_EQUAL)) { + IdExpressionAST *idExpr = binary->left_expression->asIdExpression(); + if (interface.isCursorOn(binary->left_expression) && idExpr + && idExpr->name->asSimpleName() != nullptr) { + SimpleNameAST *nameAST = idExpr->name->asSimpleName(); + const QList results = interface.context().lookup( + nameAST->name, file->scopeAt(nameAST->firstToken())); + Declaration *decl = nullptr; + for (const LookupItem &r : results) { + if (!r.declaration()) + continue; + if (Declaration *d = r.declaration()->asDeclaration()) { + if (!d->type()->asFunctionType()) { + decl = d; + break; + } + } + } + + if (!decl) { + result << new AddLocalDeclarationOp(interface, index, binary, nameAST); + return; + } + } + } + } + } +} + +bool AddDeclarationForUndeclaredIdentifier::checkForMemberInitializer( + const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result) +{ + const QList &path = interface.path(); const int size = path.size(); if (size < 4) - return; + return true; const SimpleNameAST * const name = path.at(size - 1)->asSimpleName(); if (!name) - return; + return true; const MemInitializerAST * const memInitializer = path.at(size - 2)->asMemInitializer(); if (!memInitializer) - return; + return true; if (!path.at(size - 3)->asCtorInitializer()) - return; + return true; const FunctionDefinitionAST * ctor = path.at(size - 4)->asFunctionDefinition(); if (!ctor) - return; + return false; // Now find the class. const Class *theClass = nullptr; @@ -3011,30 +3014,31 @@ void InsertMemberFromInitialization::match(const CppQuickFixInterface &interface // Out-of-line constructor. We need to find the class. SymbolFinder finder; const QList matches = finder.findMatchingDeclaration( - LookupContext(interface.currentFile()->cppDocument(), interface.snapshot()), - ctor->symbol); + LookupContext(interface.currentFile()->cppDocument(), interface.snapshot()), + ctor->symbol); if (!matches.isEmpty()) theClass = matches.first()->enclosingClass(); } if (!theClass) - return; + return false; // Check whether the member exists already. if (theClass->find(interface.currentFile()->cppDocument()->translationUnit()->identifier( - name->identifier_token))) { - return; + name->identifier_token))) { + return false; } const QString type = getType(interface, memInitializer, ctor); const Identifier * const memberId = interface.currentFile()->cppDocument() - ->translationUnit()->identifier(name->identifier_token); + ->translationUnit()->identifier(name->identifier_token); const QString member = QString::fromUtf8(memberId->chars(), memberId->size()); result << new InsertMemberFromInitializationOp(interface, theClass, member, type); + return false; } -QString InsertMemberFromInitialization::getType( +QString AddDeclarationForUndeclaredIdentifier::getType( const CppQuickFixInterface &interface, const MemInitializerAST *memInitializer, const FunctionDefinitionAST *ctor) const @@ -9072,7 +9076,6 @@ void createCppQuickFixes() new SplitIfStatement; new SplitSimpleDeclaration; - new AddLocalDeclaration; new AddBracesToIf; new RearrangeParamDeclarationList; new ReformatPointerDeclaration; @@ -9089,7 +9092,7 @@ void createCppQuickFixes() new GenerateGettersSettersForClass; new InsertDeclFromDef; new InsertDefFromDecl; - new InsertMemberFromInitialization; + new AddDeclarationForUndeclaredIdentifier; new InsertDefsFromDecls; new MoveFuncDefOutside; diff --git a/src/plugins/cppeditor/cppquickfixes.h b/src/plugins/cppeditor/cppquickfixes.h index 376bfa99bf4..c6d4c8eb136 100644 --- a/src/plugins/cppeditor/cppquickfixes.h +++ b/src/plugins/cppeditor/cppquickfixes.h @@ -284,23 +284,6 @@ public: void match(const CppQuickFixInterface &interface, QuickFixOperations &result) override; }; -/*! - Rewrites - a = foo(); - - As - Type a = foo(); - - Where Type is the return type of foo() - - Activates on: the assignee, if the type of the right-hand side of the assignment is known. -*/ -class AddLocalDeclaration: public CppQuickFixFactory -{ -public: - void match(const CppQuickFixInterface &interface, QuickFixOperations &result) override; -}; - /*! Add curly braces to a if statement that doesn't already contain a compound statement. I.e. @@ -374,16 +357,17 @@ public: void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result) override; }; -/*! - Adds a class member from an initialization in the constructor. - */ -class InsertMemberFromInitialization : public CppQuickFixFactory +class AddDeclarationForUndeclaredIdentifier : public CppQuickFixFactory { public: void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result) override; private: + // Returns whether to still do other checks. + bool checkForMemberInitializer(const CppQuickFixInterface &interface, + TextEditor::QuickFixOperations &result); + QString getType( const CppQuickFixInterface &interface, const CPlusPlus::MemInitializerAST *memInitializer,