diff --git a/src/libs/cplusplus/CppRewriter.cpp b/src/libs/cplusplus/CppRewriter.cpp index c760809aa5f..174004fbfff 100644 --- a/src/libs/cplusplus/CppRewriter.cpp +++ b/src/libs/cplusplus/CppRewriter.cpp @@ -142,6 +142,17 @@ public: funTy->setReturnType(rewrite->rewriteType(type->returnType())); + // Function parameters have the function's enclosing scope. + Scope *scope = nullptr; + ClassOrNamespace *target = nullptr; + if (rewrite->env->context().bindings()) + target = rewrite->env->context().lookupType(type->enclosingScope()); + UseMinimalNames useMinimalNames(target); + if (target) { + scope = rewrite->env->switchScope(type->enclosingScope()); + rewrite->env->enter(&useMinimalNames); + } + for (unsigned i = 0, argc = type->argumentCount(); i < argc; ++i) { Symbol *arg = type->argumentAt(i); @@ -156,6 +167,11 @@ public: funTy->addMember(newArg); } + if (target) { + rewrite->env->switchScope(scope); + rewrite->env->leave(); + } + temps.append(funTy); } diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 13e33cfb2c0..9666b6c2f96 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -161,6 +161,7 @@ private slots: void test_quickfix_InsertDefFromDecl_templateClass(); void test_quickfix_InsertDefFromDecl_templateFunction(); void test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc(); + void test_quickfix_InsertDefFromDecl_minimalFunctionParameterType(); void test_quickfix_InsertDefsFromDecls_data(); void test_quickfix_InsertDefsFromDecls(); diff --git a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp index 7b2c36145c9..6a6743d7b3c 100644 --- a/src/plugins/cppeditor/cppinsertvirtualmethods.cpp +++ b/src/plugins/cppeditor/cppinsertvirtualmethods.cpp @@ -823,16 +823,31 @@ public: headerChangeSet.insert(m_insertPosDecl, comment); first = false; } - // Construct declaration - // setup rewriting to get minimally qualified names - SubstitutionEnvironment env; - env.setContext(context()); - env.switchScope(classItem->klass->enclosingScope()); - env.enter(&useMinimalNames); - QString declaration; - const FullySpecifiedType tn = rewriteType(funcItem->function->type(), &env, control); - declaration += printer.prettyType(tn, funcItem->function->unqualifiedName()); + // Function type minimalization: As base class and derived class could be in + // different namespaces, we must first make the type fully qualified before + // it can get minimized. + Clone cloner(control); + Function newFunc(&cloner, nullptr, const_cast(funcItem->function)); + newFunc.setEnclosingScope(const_cast(targetClass)); + SubstitutionEnvironment envQualified; + envQualified.setContext(context()); + envQualified.switchScope(classItem->klass->enclosingScope()); + UseQualifiedNames useQualifiedNames; + envQualified.enter(&useQualifiedNames); + newFunc.setReturnType(rewriteType(newFunc.returnType(), &envQualified, control)); + const int argc = newFunc.argumentCount(); + for (int i = 0; i < argc; ++i) { + Argument * const arg = newFunc.argumentAt(i)->asArgument(); + QTC_ASSERT(arg, continue); + arg->setType(rewriteType(arg->type(), &envQualified, control)); + } + SubstitutionEnvironment envMinimized; + envMinimized.setContext(context()); + envMinimized.switchScope(targetClass->enclosingScope()); + envMinimized.enter(&useMinimalNames); + const FullySpecifiedType tn = rewriteType(newFunc.type(), &envMinimized, control); + QString declaration = printer.prettyType(tn, newFunc.unqualifiedName()); if (m_factory->settings()->insertVirtualKeyword) declaration = QLatin1String("virtual ") + declaration; diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index ac408b154d4..37ca090f7ea 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -4593,6 +4593,68 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc( QuickFixOperationTest(singleDocument(contents, ""), &factory); } +void CppEditorPlugin::test_quickfix_InsertDefFromDecl_minimalFunctionParameterType() +{ + QList testDocuments; + + QByteArray original; + QByteArray expected; + + // Header File + original = R"( +class C { + typedef int A; + A @foo(A); +}; +)"; + expected = original; + testDocuments << QuickFixTestDocument::create("file.h", original, expected); + + // Source File + original = R"( +#include "file.h" +)"; + expected = R"( +#include "file.h" + +C::A C::foo(A) +{ + +} +)"; + testDocuments << QuickFixTestDocument::create("file.cpp", original, expected); + + InsertDefFromDecl factory; + QuickFixOperationTest(testDocuments, &factory); + + testDocuments.clear(); + // Header File + original = R"( +namespace N { + struct S; + S @foo(const S &s); +}; +)"; + expected = original; + testDocuments << QuickFixTestDocument::create("file.h", original, expected); + + // Source File + original = R"( +#include "file.h" +)"; + expected = R"( +#include "file.h" + +N::S N::foo(const S &s) +{ + +} +)"; + testDocuments << QuickFixTestDocument::create("file.cpp", original, expected); + + QuickFixOperationTest(testDocuments, &factory); +} + void CppEditorPlugin::test_quickfix_InsertDefsFromDecls_data() { QTest::addColumn("headers");