From bddaab248bce70b8aac2e91fc67c3d70a94eab2f Mon Sep 17 00:00:00 2001 From: Lorenz Haas <lykurg@gmail.com> Date: Fri, 24 May 2013 09:43:41 +0200 Subject: [PATCH] CppEditor: Consider base class namespace in "Insert Virtual Methods" Change-Id: Ife5f34d410781d3c1ae75a3bf1c412f7d76dca80 Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com> --- src/plugins/cppeditor/cppeditorplugin.h | 1 + src/plugins/cppeditor/cppquickfix_test.cpp | 53 +++++++++++++++ src/plugins/cppeditor/cppquickfixes.cpp | 79 ++++++++-------------- 3 files changed, 84 insertions(+), 49 deletions(-) diff --git a/src/plugins/cppeditor/cppeditorplugin.h b/src/plugins/cppeditor/cppeditorplugin.h index 301aa880cdc..239e6dc8441 100644 --- a/src/plugins/cppeditor/cppeditorplugin.h +++ b/src/plugins/cppeditor/cppeditorplugin.h @@ -213,6 +213,7 @@ private slots: void test_quickfix_InsertVirtualMethods_outside(); void test_quickfix_InsertVirtualMethods_implementationFile(); void test_quickfix_InsertVirtualMethods_notrigger_allImplemented(); + void test_quickfix_InsertVirtualMethods_BaseClassInNamespace(); // The following tests depend on the projects that are loaded on startup // and will be skipped in case no projects are loaded. diff --git a/src/plugins/cppeditor/cppquickfix_test.cpp b/src/plugins/cppeditor/cppquickfix_test.cpp index b68458b81e0..17823ecadef 100644 --- a/src/plugins/cppeditor/cppquickfix_test.cpp +++ b/src/plugins/cppeditor/cppquickfix_test.cpp @@ -2477,3 +2477,56 @@ void CppEditorPlugin::test_quickfix_InsertVirtualMethods_notrigger_allImplemente TestCase data(original, expected); data.run(&factory); } + +/// Check: Qualified names. +void CppEditorPlugin::test_quickfix_InsertVirtualMethods_BaseClassInNamespace() +{ + QList<TestDocumentPtr> testFiles; + QByteArray original; + QByteArray expected; + + // Header File + original = + "namespace BaseNS {enum BaseEnum {EnumA = 1};}\n" + "namespace BaseNS {\n" + "class Base {\n" + "public:\n" + " virtual BaseEnum a(BaseEnum e);\n" + "};\n" + "}\n" + "class Deri@ved : public BaseNS::Base {\n" + "public:\n" + " Derived();\n" + "};"; + expected = + "namespace BaseNS {enum BaseEnum {EnumA = 1};}\n" + "namespace BaseNS {\n" + "class Base {\n" + "public:\n" + " virtual BaseEnum a(BaseEnum e);\n" + "};\n" + "}\n" + "class Deri@ved : public BaseNS::Base {\n" + "public:\n" + " Derived();\n" + "\n" + " // Base interface\n" + "public:\n" + " virtual BaseNS::BaseEnum a(BaseNS::BaseEnum e);\n" + "};\n"; + testFiles << TestDocument::create(original, expected, QLatin1String("file.h")); + + // Source File + original = "#include \"file.h\"\n"; + expected = + "#include \"file.h\"\n" + "\n\n" + "BaseNS::BaseEnum Derived::a(BaseNS::BaseEnum e)\n" + "{\n}\n"; + testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp")); + + InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest( + InsertVirtualMethodsDialog::ModeImplementationFile, true)); + TestCase data(testFiles); + data.run(&factory); +} diff --git a/src/plugins/cppeditor/cppquickfixes.cpp b/src/plugins/cppeditor/cppquickfixes.cpp index b577a808604..1058fdad058 100644 --- a/src/plugins/cppeditor/cppquickfixes.cpp +++ b/src/plugins/cppeditor/cppquickfixes.cpp @@ -4585,12 +4585,23 @@ public: QLatin1String("QuickFix/InsertVirtualMethods/hideReimplementedFunctions"), m_factory->hideReimplementedFunctions()); - // Insert declarations (and definition if InsideClass) + // Insert declarations (and definition if Inside-/OutsideClass) Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview(); printer.showFunctionSignatures = true; printer.showReturnTypes = true; printer.showArgumentNames = true; ChangeSet headerChangeSet; + const CppRefactoringChanges refactoring(assistInterface()->snapshot()); + const QString filename = assistInterface()->currentFile()->fileName(); + const CppRefactoringFilePtr headerFile = refactoring.file(filename); + const LookupContext targetContext(headerFile->cppDocument(), assistInterface()->snapshot()); + + const Class *targetClass = m_classAST->symbol; + ClassOrNamespace *targetCoN = targetContext.lookupType(targetClass->scope()); + if (!targetCoN) + targetCoN = targetContext.globalNamespace(); + UseMinimalNames useMinimalNames(targetCoN); + Control *control = assistInterface()->context().bindings()->control().data(); for (int i = 0; i < m_factory->classFunctionModel->rowCount(); ++i) { const QStandardItem *parent = m_factory->classFunctionModel->invisibleRootItem()->child(i, 0); @@ -4614,11 +4625,23 @@ public: item->data(InsertVirtualMethodsDialog::ClassOrFunction).value<void *>(); // Construct declaration - QString declaration = InsertDeclOperation::generateDeclaration(func); + // setup rewriting to get minimally qualified names + SubstitutionEnvironment env; + env.setContext(assistInterface()->context()); + env.switchScope(clazz->enclosingScope()); + env.enter(&useMinimalNames); + + QString declaration; + const FullySpecifiedType tn = rewriteType(func->type(), &env, control); + declaration += printer.prettyType(tn, func->unqualifiedName()); + if (m_factory->insertKeywordVirtual()) declaration = QLatin1String("virtual ") + declaration; if (m_factory->implementationMode() & InsertVirtualMethodsDialog::ModeInsideClass) - declaration.replace(declaration.size() - 2, 2, QLatin1String("\n{\n}\n")); + declaration += QLatin1String("\n{\n}\n"); + else + declaration += QLatin1String(";\n"); + const InsertionPointLocator::AccessSpec spec = static_cast<InsertionPointLocator::AccessSpec>( item->data(InsertVirtualMethodsDialog::AccessSpec).toInt()); @@ -4630,54 +4653,12 @@ public: lastAccessSpecString = accessSpecString; } headerChangeSet.insert(m_insertPosDecl, declaration); - } - } - // Insert outside class - const QString filename = assistInterface()->currentFile()->fileName(); - const CppRefactoringChanges refactoring(assistInterface()->snapshot()); - const CppRefactoringFilePtr headerFile = refactoring.file(filename); - const Document::Ptr headerDoc = headerFile->cppDocument(); - Class *targetClass = m_classAST->symbol; - if (m_factory->implementationMode() & InsertVirtualMethodsDialog::ModeOutsideClass) { - // make target lookup context - unsigned line, column; - headerDoc->translationUnit()->getPosition(m_insertPosOutside, &line, &column); - Scope *targetScope = headerDoc->scopeAt(line, column); - const LookupContext targetContext(headerDoc, assistInterface()->snapshot()); - ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope); - if (!targetCoN) - targetCoN = targetContext.globalNamespace(); - - // setup rewriting to get minimally qualified names - SubstitutionEnvironment env; - env.setContext(assistInterface()->context()); - env.switchScope(targetClass); - UseMinimalNames q(targetCoN); - env.enter(&q); - Control *control = assistInterface()->context().bindings()->control().data(); - const QString fullClassName = printer.prettyName(LookupContext::minimalName( - targetClass, targetCoN, control)); - - for (int i = 0; i < m_factory->classFunctionModel->rowCount(); ++i) { - const QStandardItem *parent = - m_factory->classFunctionModel->invisibleRootItem()->child(i, 0); - if (!parent->isCheckable() || parent->checkState() == Qt::Unchecked) - continue; - - for (int j = 0; j < parent->rowCount(); ++j) { - const QStandardItem *item = parent->child(j, 0); - if (!item->isCheckable() || item->checkState() == Qt::Unchecked) - continue; - const Function *func = (const Function *) - item->data(InsertVirtualMethodsDialog::ClassOrFunction).value<void *>(); - - // rewrite the function type and name - const FullySpecifiedType tn = rewriteType(func->type(), &env, control); - const QString name = fullClassName + QLatin1String("::") + - printer.prettyName(func->name()); + // Insert definition outside class + if (m_factory->implementationMode() & InsertVirtualMethodsDialog::ModeOutsideClass) { + const QString name = printer.prettyName(targetClass->name()) + + QLatin1String("::") + printer.prettyName(func->name()); const QString defText = printer.prettyType(tn, name) + QLatin1String("\n{\n}"); - headerChangeSet.insert(m_insertPosOutside, QLatin1String("\n\n") + defText); } } -- GitLab