CppEditor: Quick fix "Insert (Pure) Virtual Methods"

This quick fix inserts (pure) virtual functions of base classes to the
current class. For selecting the functions which should be inserted and
for choosing the insertion mode (only declarations or with definitions
inside, outside or in the implementation file) a dialog is shown.

Task-number: QTCREATORBUG-2210
Task-number: QTCREATORBUG-2692
Task-number: QTCREATORBUG-3908
Task-number: QTCREATORBUG-5868
Task-number: QTCREATORBUG-7982
Change-Id: I8e94905afcae4778986f4c3925a494e0c6b3b8ee
Reviewed-by: Nikolai Kosjar <nikolai.kosjar@digia.com>
This commit is contained in:
Lorenz Haas
2013-04-29 23:15:50 +02:00
committed by Nikolai Kosjar
parent 7ef611047f
commit d288e3999b
8 changed files with 1307 additions and 30 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

View File

@@ -1957,6 +1957,19 @@
\endcode \endcode
\li Function call or class name \li Function call or class name
\row
\li Insert (Pure) Virtual Functions
\li Select an insertion mode:
\list
\li Insert only declarations.
\li Insert declarations and the corresponding definitions inside the class.
\li Insert declarations and the corresponding definitions outside the class.
\li Insert declarations and the corresponding definitions in the implementation file
(only if an implementation file exists).
\endlist
\image qtcreator-refactoring-virtual-function-dialog.png
\li Class or base class name
\endtable \endtable

View File

@@ -199,6 +199,18 @@ private slots:
void test_quickfix_AssignToLocalVariable_noReturnClass(); void test_quickfix_AssignToLocalVariable_noReturnClass();
void test_quickfix_AssignToLocalVariable_noReturnFunc(); void test_quickfix_AssignToLocalVariable_noReturnFunc();
void test_quickfix_InsertVirtualMethods_onlyDecl();
void test_quickfix_InsertVirtualMethods_onlyDeclWithoutVirtual();
void test_quickfix_InsertVirtualMethods_Access();
void test_quickfix_InsertVirtualMethods_Superclass();
void test_quickfix_InsertVirtualMethods_SuperclassOverride();
void test_quickfix_InsertVirtualMethods_PureVirtualOnlyDecl();
void test_quickfix_InsertVirtualMethods_PureVirtualInside();
void test_quickfix_InsertVirtualMethods_inside();
void test_quickfix_InsertVirtualMethods_outside();
void test_quickfix_InsertVirtualMethods_implementationFile();
void test_quickfix_InsertVirtualMethods_notrigger_allImplemented();
// The following tests depend on the projects that are loaded on startup // The following tests depend on the projects that are loaded on startup
// and will be skipped in case no projects are loaded. // and will be skipped in case no projects are loaded.
void test_openEachFile(); void test_openEachFile();

View File

@@ -2014,3 +2014,420 @@ void CppEditorPlugin::test_quickfix_AssignToLocalVariable_noReturnFunc()
TestCase data(original, expected); TestCase data(original, expected);
data.run(&factory); data.run(&factory);
} }
/// Test dialog for insert virtual functions
class InsertVirtualMethodsDialogTest : public InsertVirtualMethodsDialog
{
public:
InsertVirtualMethodsDialogTest(ImplementationMode mode, bool virt, QWidget *parent = 0)
: InsertVirtualMethodsDialog(parent)
{
setImplementationsMode(mode);
setInsertKeywordVirtual(virt);
}
bool gather()
{
return true;
}
ImplementationMode implementationMode() const
{
return m_implementationMode;
}
bool insertKeywordVirtual() const
{
return m_insertKeywordVirtual;
}
};
/// Check: Insert only declarations
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_onlyDecl()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert only declarations vithout virtual keyword
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_onlyDeclWithoutVirtual()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" int virtualFuncA();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, false));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Are access specifiers considered
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_Access()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"protected:\n"
" virtual int b();\n"
"private:\n"
" virtual int c();\n"
"public slots:\n"
" virtual int d();\n"
"protected slots:\n"
" virtual int e();\n"
"private slots:\n"
" virtual int f();\n"
"signals:\n"
" virtual int g();\n"
"};\n\n"
"class Der@ived : public BaseA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"protected:\n"
" virtual int b();\n"
"private:\n"
" virtual int c();\n"
"public slots:\n"
" virtual int d();\n"
"protected slots:\n"
" virtual int e();\n"
"private slots:\n"
" virtual int f();\n"
"signals:\n"
" virtual int g();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int a();\n\n"
"protected:\n"
" virtual int b();\n\n"
"private:\n"
" virtual int c();\n\n"
"public slots:\n"
" virtual int d();\n\n"
"protected slots:\n"
" virtual int e();\n\n"
"private slots:\n"
" virtual int f();\n\n"
"signals:\n"
" virtual int g();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Is a base class of a base class considered.
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_Superclass()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class BaseB : public BaseA {\n"
"public:\n"
" virtual int b();\n"
"};\n\n"
"class Der@ived : public BaseB {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class BaseB : public BaseA {\n"
"public:\n"
" virtual int b();\n"
"};\n\n"
"class Der@ived : public BaseB {\n"
"\n"
" // BaseB interface\n"
"public:\n"
" virtual int b();\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int a();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Do not insert reimplemented functions twice.
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_SuperclassOverride()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class BaseB : public BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class Der@ived : public BaseB {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class BaseB : public BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class Der@ived : public BaseB {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int a();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert only declarations for pure virtual function
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_PureVirtualOnlyDecl()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA() = 0;\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA() = 0;\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOnlyDeclarations, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert pure virtual functions inside class
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_PureVirtualInside()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA() = 0;\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA() = 0;\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int virtualFuncA()\n"
" {\n"
" }\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeInsideClass, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert inside class
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_inside()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int virtualFuncA()\n"
" {\n"
" }\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeInsideClass, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert outside class
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_outside()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"int Derived::virtualFuncA()\n"
"{\n"
"}\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOutsideClass, true));
TestCase data(original, expected);
data.run(&factory);
}
/// Check: Insert in implementation file
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_implementationFile()
{
QList<TestDocumentPtr> testFiles;
QByteArray original;
QByteArray expected;
// Header File
original =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"public:\n"
" Derived();\n"
"};";
expected =
"class BaseA {\n"
"public:\n"
" virtual int a();\n"
"};\n\n"
"class Derived : public BaseA {\n"
"public:\n"
" Derived();\n"
"\n"
" // BaseA interface\n"
"public:\n"
" virtual int a();\n"
"};\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.h"));
// Source File
original = "#include \"file.h\"\n";
expected =
"#include \"file.h\"\n"
"\n\n"
"int Derived::a()\n"
"{\n}\n";
testFiles << TestDocument::create(original, expected, QLatin1String("file.cpp"));
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeImplementationFile, true));
TestCase data(testFiles);
data.run(&factory);
}
/// Check: No trigger: all implemented
void CppEditorPlugin::test_quickfix_InsertVirtualMethods_notrigger_allImplemented()
{
const QByteArray original =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};";
const QByteArray expected =
"class BaseA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n\n"
"class Derived : public Bas@eA {\n"
"public:\n"
" virtual int virtualFuncA();\n"
"};\n";
InsertVirtualMethods factory(new InsertVirtualMethodsDialogTest(
InsertVirtualMethodsDialog::ModeOutsideClass, true));
TestCase data(original, expected);
data.run(&factory);
}

View File

@@ -33,6 +33,8 @@
#include "cppfunctiondecldeflink.h" #include "cppfunctiondecldeflink.h"
#include "cppquickfixassistant.h" #include "cppquickfixassistant.h"
#include <coreplugin/icore.h>
#include <cpptools/cppclassesfilter.h> #include <cpptools/cppclassesfilter.h>
#include <cpptools/cppcodestylesettings.h> #include <cpptools/cppcodestylesettings.h>
#include <cpptools/cpppointerdeclarationformatter.h> #include <cpptools/cpppointerdeclarationformatter.h>
@@ -49,16 +51,33 @@
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
#include <texteditor/fontsettings.h>
#include <texteditor/texteditorsettings.h>
#include <utils/qtcassert.h> #include <utils/qtcassert.h>
#include <QApplication> #include <QApplication>
#include <QCheckBox>
#include <QComboBox>
#include <QDialogButtonBox>
#include <QDir> #include <QDir>
#include <QFileInfo> #include <QFileInfo>
#include <QGroupBox>
#include <QHBoxLayout>
#include <QInputDialog> #include <QInputDialog>
#include <QItemDelegate>
#include <QLabel>
#include <QMessageBox> #include <QMessageBox>
#include <QPointer>
#include <QPushButton>
#include <QQueue>
#include <QSharedPointer> #include <QSharedPointer>
#include <QSortFilterProxyModel>
#include <QStandardItemModel>
#include <QTextBlock> #include <QTextBlock>
#include <QTextCursor> #include <QTextCursor>
#include <QTreeView>
#include <QVBoxLayout>
#include <cctype> #include <cctype>
@@ -109,6 +128,8 @@ void CppEditor::Internal::registerQuickFixes(ExtensionSystem::IPlugin *plugIn)
plugIn->addAutoReleasedObject(new MoveFuncDefToDecl); plugIn->addAutoReleasedObject(new MoveFuncDefToDecl);
plugIn->addAutoReleasedObject(new AssignToLocalVariable); plugIn->addAutoReleasedObject(new AssignToLocalVariable);
plugIn->addAutoReleasedObject(new InsertVirtualMethods);
} }
// In the following anonymous namespace all functions are collected, which could be of interest for // In the following anonymous namespace all functions are collected, which could be of interest for
@@ -2356,7 +2377,7 @@ public:
targetFile->apply(); targetFile->apply();
} }
static QString generateDeclaration(Function *function); static QString generateDeclaration(const Function *function);
private: private:
QString m_targetFileName; QString m_targetFileName;
@@ -2450,7 +2471,7 @@ void InsertDeclFromDef::match(const CppQuickFixInterface &interface, QuickFixOpe
} }
} }
QString InsertDeclOperation::generateDeclaration(Function *function) QString InsertDeclOperation::generateDeclaration(const Function *function)
{ {
Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview(); Overview oo = CppCodeStyleSettings::currentProjectCodeStyleOverview();
oo.showFunctionSignatures = true; oo.showFunctionSignatures = true;
@@ -4284,3 +4305,735 @@ void AssignToLocalVariable::match(const CppQuickFixInterface &interface, QuickFi
} }
} }
} }
namespace {
class InsertVirtualMethodsOp : public CppQuickFixOperation
{
public:
InsertVirtualMethodsOp(const QSharedPointer<const CppQuickFixAssistInterface> &interface,
InsertVirtualMethodsDialog *factory)
: CppQuickFixOperation(interface, 0)
, m_factory(factory)
, m_classAST(0)
, m_valid(false)
, m_cppFileName(QString::null)
, m_insertPosDecl(0)
, m_insertPosOutside(0)
, m_functionCount(0)
, m_implementedFunctionCount(0)
{
setDescription(QCoreApplication::translate(
"CppEditor::QuickFix", "Insert Virtual Functions of Base Classes"));
const QList<AST *> &path = interface->path();
const int pathSize = path.size();
if (pathSize < 2)
return;
// Determine if cursor is on a class or a base class
if (SimpleNameAST *nameAST = path.at(pathSize - 1)->asSimpleName()) {
if (!interface->isCursorOn(nameAST))
return;
if (!(m_classAST = path.at(pathSize - 2)->asClassSpecifier())) { // normal class
int index = pathSize - 2;
const BaseSpecifierAST *baseAST = path.at(index)->asBaseSpecifier();// simple bclass
if (!baseAST) {
if (index > 0 && path.at(index)->asQualifiedName()) // namespaced base class
baseAST = path.at(--index)->asBaseSpecifier();
}
--index;
if (baseAST && index >= 0)
m_classAST = path.at(index)->asClassSpecifier();
}
}
if (!m_classAST || !m_classAST->base_clause_list)
return;
// Determine insert positions
const int endOfClassAST = interface->currentFile()->endOf(m_classAST);
m_insertPosDecl = endOfClassAST - 1; // Skip last "}"
m_insertPosOutside = endOfClassAST + 1; // Step over ";"
// Determine base classes
QList<const Class *> baseClasses;
QQueue<ClassOrNamespace *> baseClassQueue;
QSet<ClassOrNamespace *> visitedBaseClasses;
if (ClassOrNamespace *clazz = interface->context().lookupType(m_classAST->symbol))
baseClassQueue.enqueue(clazz);
while (!baseClassQueue.isEmpty()) {
ClassOrNamespace *clazz = baseClassQueue.dequeue();
visitedBaseClasses.insert(clazz);
const QList<ClassOrNamespace *> bases = clazz->usings();
foreach (ClassOrNamespace *baseClass, bases) {
foreach (Symbol *symbol, baseClass->symbols()) {
Class *base = symbol->asClass();
if (base
&& (clazz = interface->context().lookupType(symbol))
&& !visitedBaseClasses.contains(clazz)
&& !baseClasses.contains(base)) {
baseClasses << base;
baseClassQueue.enqueue(clazz);
}
}
}
}
// Determine virtual functions
m_factory->classFunctionModel->clear();
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
printer.showFunctionSignatures = true;
const TextEditor::FontSettings &fs =
TextEditor::TextEditorSettings::instance()->fontSettings();
const Format formatReimpFunc = fs.formatFor(C_DISABLED_CODE);
foreach (const Class *clazz, baseClasses) {
QStandardItem *itemBase = new QStandardItem(printer.prettyName(clazz->name()));
itemBase->setData(false, InsertVirtualMethodsDialog::Implemented);
itemBase->setData(qVariantFromValue((void *) clazz),
InsertVirtualMethodsDialog::ClassOrFunction);
const QString baseClassName = printer.prettyName(clazz->name());
for (Scope::iterator it = clazz->firstMember(); it != clazz->lastMember(); ++it) {
if (const Function *func = (*it)->type()->asFunctionType()) {
if (!func->isVirtual())
continue;
// Filter virtual destructors
if (printer.prettyName(func->name()).startsWith(QLatin1Char('~')))
continue;
// Filter OQbject's
// - virtual const QMetaObject *metaObject() const;
// - virtual void *qt_metacast(const char *);
// - virtual int qt_metacall(QMetaObject::Call, int, void **);
if (baseClassName == QLatin1String("QObject")) {
if (printer.prettyName(func->name()) == QLatin1String("metaObject"))
continue;
if (printer.prettyName(func->name()) == QLatin1String("qt_metacast"))
continue;
if (printer.prettyName(func->name()) == QLatin1String("qt_metacall"))
continue;
}
// Do not implement existing functions inside target class
bool funcExistsInClass = false;
const Name *funcName = func->name();
for (Symbol *symbol = m_classAST->symbol->find(funcName->identifier());
symbol; symbol = symbol->next()) {
if (!symbol->name()
|| !funcName->identifier()->isEqualTo(symbol->identifier())) {
continue;
}
if (symbol->type().isEqualTo(func->type())) {
funcExistsInClass = true;
break;
}
}
// Do not show when reimplemented from an other class
bool funcReimplemented = false;
for (int i = baseClasses.count() - 1; i >= 0; --i) {
const Class *prevClass = baseClasses.at(i);
if (clazz == prevClass)
break; // reached current class
for (const Symbol *symbol = prevClass->find(funcName->identifier());
symbol; symbol = symbol->next()) {
if (!symbol->name()
|| !funcName->identifier()->isEqualTo(symbol->identifier())) {
continue;
}
if (symbol->type().isEqualTo(func->type())) {
funcReimplemented = true;
break;
}
}
}
if (funcReimplemented)
continue;
// Construct function item
const bool isPureVirtual = func->isPureVirtual();
QString itemName = printer.prettyType(func->type(), func->name());
if (isPureVirtual)
itemName += QLatin1String(" = 0");
const QString itemReturnTypeString = printer.prettyType(func->returnType());
QStandardItem *funcItem = new QStandardItem(
itemName + QLatin1String(" : ") + itemReturnTypeString);
if (!funcExistsInClass) {
funcItem->setCheckable(true);
funcItem->setCheckState(Qt::Checked);
} else {
funcItem->setEnabled(false);
funcItem->setData(formatReimpFunc.foreground(), Qt::ForegroundRole);
if (formatReimpFunc.background().isValid())
funcItem->setData(formatReimpFunc.background(), Qt::BackgroundRole);
}
funcItem->setData(qVariantFromValue((void *) func),
InsertVirtualMethodsDialog::ClassOrFunction);
funcItem->setData(isPureVirtual, InsertVirtualMethodsDialog::PureVirtual);
funcItem->setData(acessSpec(*it), InsertVirtualMethodsDialog::AccessSpec);
funcItem->setData(funcExistsInClass, InsertVirtualMethodsDialog::Implemented);
itemBase->appendRow(funcItem);
// update internal counters
if (funcExistsInClass)
++m_implementedFunctionCount;
else
++m_functionCount;
}
}
if (itemBase->hasChildren()) {
for (int i = 0; i < itemBase->rowCount(); ++i) {
if (itemBase->child(i, 0)->isCheckable()) {
itemBase->setCheckable(true);
itemBase->setTristate(true);
itemBase->setCheckState(Qt::Checked);
itemBase->setData(false, InsertVirtualMethodsDialog::Implemented);
break;
}
}
m_factory->classFunctionModel->invisibleRootItem()->appendRow(itemBase);
}
}
if (!m_factory->classFunctionModel->invisibleRootItem()->hasChildren()
|| m_functionCount == 0) {
return;
}
bool isHeaderFile = false;
m_cppFileName = correspondingHeaderOrSource(interface->fileName(), &isHeaderFile);
m_factory->setHasImplementationFile(isHeaderFile && !m_cppFileName.isEmpty());
m_factory->setHasReimplementedFunctions(m_implementedFunctionCount != 0);
m_valid = true;
}
bool isValid() const
{
return m_valid;
}
InsertionPointLocator::AccessSpec acessSpec(const Symbol *symbol)
{
const Function *func = symbol->type()->asFunctionType();
if (!func)
return InsertionPointLocator::Invalid;
if (func->isSignal())
return InsertionPointLocator::Signals;
InsertionPointLocator::AccessSpec spec = InsertionPointLocator::Invalid;
if (symbol->isPrivate())
spec = InsertionPointLocator::Private;
else if (symbol->isProtected())
spec = InsertionPointLocator::Protected;
else if (symbol->isPublic())
spec = InsertionPointLocator::Public;
else
return InsertionPointLocator::Invalid;
if (func->isSlot()) {
switch (spec) {
case InsertionPointLocator::Private:
return InsertionPointLocator::PrivateSlot;
break;
case InsertionPointLocator::Protected:
return InsertionPointLocator::ProtectedSlot;
break;
case InsertionPointLocator::Public:
return InsertionPointLocator::PublicSlot;
break;
default:
return spec;
break;
}
}
return spec;
}
void perform()
{
if (!m_factory->gather())
return;
Core::ICore::settings()->setValue(
QLatin1String("QuickFix/InsertVirtualMethods/insertKeywordVirtual"),
m_factory->insertKeywordVirtual());
Core::ICore::settings()->setValue(
QLatin1String("QuickFix/InsertVirtualMethods/implementationMode"),
m_factory->implementationMode());
Core::ICore::settings()->setValue(
QLatin1String("QuickFix/InsertVirtualMethods/hideReimplementedFunctions"),
m_factory->hideReimplementedFunctions());
// Insert declarations (and definition if InsideClass)
Overview printer = CppCodeStyleSettings::currentProjectCodeStyleOverview();
printer.showFunctionSignatures = true;
printer.showReturnTypes = true;
printer.showArgumentNames = true;
ChangeSet headerChangeSet;
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;
const Class *clazz = (const Class *)
parent->data(InsertVirtualMethodsDialog::ClassOrFunction).value<void *>();
// Add comment
const QString comment = QLatin1String("\n// ") + printer.prettyName(clazz->name()) +
QLatin1String(" interface\n");
headerChangeSet.insert(m_insertPosDecl, comment);
// Insert Declarations (+ definitions)
QString lastAccessSpecString;
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 *>();
// Construct declaration
QString declaration = InsertDeclOperation::generateDeclaration(func);
if (m_factory->insertKeywordVirtual())
declaration = QLatin1String("virtual ") + declaration;
if (m_factory->implementationMode() & InsertVirtualMethodsDialog::ModeInsideClass)
declaration.replace(declaration.size() - 2, 2, QLatin1String("\n{\n}\n"));
const InsertionPointLocator::AccessSpec spec =
static_cast<InsertionPointLocator::AccessSpec>(
item->data(InsertVirtualMethodsDialog::AccessSpec).toInt());
const QString accessSpecString = InsertionPointLocator::accessSpecToString(spec);
if (accessSpecString != lastAccessSpecString) {
declaration = accessSpecString + declaration;
if (!lastAccessSpecString.isEmpty()) // separate if not direct after the comment
declaration = QLatin1String("\n") + declaration;
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().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());
const QString defText = printer.prettyType(tn, name) + QLatin1String("\n{\n}");
headerChangeSet.insert(m_insertPosOutside, QLatin1String("\n\n") + defText);
}
}
}
// Write header file
headerFile->setChangeSet(headerChangeSet);
headerFile->appendIndentRange(ChangeSet::Range(m_insertPosDecl, m_insertPosDecl + 1));
headerFile->setOpenEditor(true, m_insertPosDecl);
headerFile->apply();
// Insert in implementation file
if (m_factory->implementationMode() & InsertVirtualMethodsDialog::ModeImplementationFile) {
const Symbol *symbol = headerFile->cppDocument()->lastVisibleSymbolAt(
targetClass->line(), targetClass->column());
if (!symbol)
return;
const Class *clazz = symbol->asClass();
if (!clazz)
return;
CppRefactoringFilePtr implementationFile = refactoring.file(m_cppFileName);
ChangeSet implementationChangeSet;
const int insertPos = qMax(0, implementationFile->document()->characterCount() - 1);
// make target lookup context
Document::Ptr implementationDoc = implementationFile->cppDocument();
unsigned line, column;
implementationDoc->translationUnit()->getPosition(insertPos, &line, &column);
Scope *targetScope = implementationDoc->scopeAt(line, column);
const LookupContext targetContext(implementationDoc, assistInterface()->snapshot());
ClassOrNamespace *targetCoN = targetContext.lookupType(targetScope);
if (!targetCoN)
targetCoN = targetContext.globalNamespace();
// Loop through inserted declarations
for (unsigned i = targetClass->memberCount(); i < clazz->memberCount(); ++i) {
Declaration *decl = clazz->memberAt(i)->asDeclaration();
if (!decl)
continue;
// setup rewriting to get minimally qualified names
SubstitutionEnvironment env;
env.setContext(assistInterface()->context());
env.switchScope(decl->enclosingScope());
UseMinimalNames q(targetCoN);
env.enter(&q);
Control *control = assistInterface()->context().control().data();
// rewrite the function type and name + create definition
const FullySpecifiedType type = rewriteType(decl->type(), &env, control);
const QString name = printer.prettyName(
LookupContext::minimalName(decl, targetCoN, control));
const QString defText = printer.prettyType(type, name) + QLatin1String("\n{\n}");
implementationChangeSet.insert(insertPos, QLatin1String("\n\n") + defText);
}
implementationFile->setChangeSet(implementationChangeSet);
implementationFile->appendIndentRange(ChangeSet::Range(insertPos, insertPos + 1));
implementationFile->apply();
}
}
private:
InsertVirtualMethodsDialog *m_factory;
const ClassSpecifierAST *m_classAST;
bool m_valid;
QString m_cppFileName;
int m_insertPosDecl;
int m_insertPosOutside;
unsigned m_functionCount;
unsigned m_implementedFunctionCount;
};
class InsertVirtualMethodsFilterModel : public QSortFilterProxyModel
{
Q_OBJECT
public:
InsertVirtualMethodsFilterModel(QObject *parent = 0)
: QSortFilterProxyModel(parent)
, m_hideReimplemented(false)
{}
bool filterAcceptsRow(int sourceRow, const QModelIndex &sourceParent) const
{
QModelIndex index = sourceModel()->index(sourceRow, 0, sourceParent);
// Handle base class
if (!sourceParent.isValid()) {
// check if any child is valid
if (!sourceModel()->hasChildren(index))
return false;
if (!m_hideReimplemented)
return true;
for (int i = 0; i < sourceModel()->rowCount(index); ++i) {
const QModelIndex child = sourceModel()->index(i, 0, index);
if (!child.data(InsertVirtualMethodsDialog::Implemented).toBool())
return true;
}
return false;
}
if (m_hideReimplemented)
return !index.data(InsertVirtualMethodsDialog::Implemented).toBool();
return true;
}
bool hideReimplemented() const
{
return m_hideReimplemented;
}
void setHideReimplementedFunctions(bool show)
{
m_hideReimplemented = show;
invalidateFilter();
}
private:
bool m_hideReimplemented;
};
} // anonymous namespace
InsertVirtualMethodsDialog::InsertVirtualMethodsDialog(QWidget *parent)
: QDialog(parent)
, m_view(0)
, m_hideReimplementedFunctions(0)
, m_insertMode(0)
, m_virtualKeyword(0)
, m_buttons(0)
, m_hasImplementationFile(false)
, m_hasReimplementedFunctions(false)
, m_implementationMode(ModeOnlyDeclarations)
, m_insertKeywordVirtual(false)
, classFunctionModel(new QStandardItemModel(this))
, classFunctionFilterModel(new InsertVirtualMethodsFilterModel(this))
{
classFunctionFilterModel->setSourceModel(classFunctionModel);
}
void InsertVirtualMethodsDialog::initGui()
{
if (m_view)
return;
setWindowTitle(tr("Insert Virtual Functions"));
QVBoxLayout *globalVerticalLayout = new QVBoxLayout;
// View
QGroupBox *groupBoxView = new QGroupBox(tr("&Functions to insert:"), this);
QVBoxLayout *groupBoxViewLayout = new QVBoxLayout(groupBoxView);
m_view = new QTreeView(this);
m_view->setEditTriggers(QAbstractItemView::NoEditTriggers);
m_view->setHeaderHidden(true);
groupBoxViewLayout->addWidget(m_view);
m_hideReimplementedFunctions =
new QCheckBox(tr("&Hide already implemented functions of current class"), this);
groupBoxViewLayout->addWidget(m_hideReimplementedFunctions);
// Insertion options
QGroupBox *groupBoxImplementation = new QGroupBox(tr("&Insertion options:"), this);
QVBoxLayout *groupBoxImplementationLayout = new QVBoxLayout(groupBoxImplementation);
m_insertMode = new QComboBox(this);
m_insertMode->addItem(tr("Insert only declarations"), ModeOnlyDeclarations);
m_insertMode->addItem(tr("Insert definitions inside class"), ModeInsideClass);
m_insertMode->addItem(tr("Insert definitions outside class"), ModeOutsideClass);
m_insertMode->addItem(tr("Insert definitions in implementation file"), ModeImplementationFile);
m_virtualKeyword = new QCheckBox(tr("&Add keyword 'virtual' to function declaration"), this);
groupBoxImplementationLayout->addWidget(m_insertMode);
groupBoxImplementationLayout->addWidget(m_virtualKeyword);
groupBoxImplementationLayout->addStretch(99);
// Bottom button box
m_buttons = new QDialogButtonBox(this);
m_buttons->setStandardButtons(QDialogButtonBox::Ok | QDialogButtonBox::Cancel);
connect(m_buttons, SIGNAL(accepted()), this, SLOT(accept()));
connect(m_buttons, SIGNAL(rejected()), this, SLOT(reject()));
globalVerticalLayout->addWidget(groupBoxView, 9);
globalVerticalLayout->addWidget(groupBoxImplementation, 0);
globalVerticalLayout->addWidget(m_buttons, 0);
setLayout(globalVerticalLayout);
connect(classFunctionModel, SIGNAL(itemChanged(QStandardItem *)),
this, SLOT(updateCheckBoxes(QStandardItem *)));
connect(m_hideReimplementedFunctions, SIGNAL(toggled(bool)),
this, SLOT(setHideReimplementedFunctions(bool)));
}
void InsertVirtualMethodsDialog::initData()
{
m_insertKeywordVirtual = Core::ICore::settings()->value(
QLatin1String("QuickFix/InsertVirtualMethods/insertKeywordVirtual"),
false).toBool();
m_implementationMode = static_cast<InsertVirtualMethodsDialog::ImplementationMode>(
Core::ICore::settings()->value(
QLatin1String("QuickFix/InsertVirtualMethods/implementationMode"), 1).toInt());
m_hideReimplementedFunctions->setChecked(
Core::ICore::settings()->value(
QLatin1String("QuickFix/InsertVirtualMethods/hideReimplementedFunctions"),
false).toBool());
m_view->setModel(classFunctionFilterModel);
m_expansionStateNormal.clear();
m_expansionStateReimp.clear();
m_hideReimplementedFunctions->setVisible(m_hasReimplementedFunctions);
m_virtualKeyword->setChecked(m_insertKeywordVirtual);
m_insertMode->setCurrentIndex(m_insertMode->findData(m_implementationMode));
setHideReimplementedFunctions(m_hideReimplementedFunctions->isChecked());
if (m_hasImplementationFile) {
if (m_insertMode->count() == 3) {
m_insertMode->addItem(tr("Insert definitions in implementation file"),
ModeImplementationFile);
}
} else {
if (m_insertMode->count() == 4)
m_insertMode->removeItem(3);
}
}
bool InsertVirtualMethodsDialog::gather()
{
initGui();
initData();
// Expand the dialog a little bit
adjustSize();
resize(size() * 1.5);
QPointer<InsertVirtualMethodsDialog> that(this);
const int ret = exec();
if (!that)
return false;
m_implementationMode = implementationMode();
m_insertKeywordVirtual = insertKeywordVirtual();
return (ret == QDialog::Accepted);
}
InsertVirtualMethodsDialog::ImplementationMode
InsertVirtualMethodsDialog::implementationMode() const
{
return static_cast<InsertVirtualMethodsDialog::ImplementationMode>(
m_insertMode->itemData(m_insertMode->currentIndex()).toInt());
}
void InsertVirtualMethodsDialog::setImplementationsMode(InsertVirtualMethodsDialog::ImplementationMode mode)
{
m_implementationMode = mode;
}
bool InsertVirtualMethodsDialog::insertKeywordVirtual() const
{
return m_virtualKeyword->isChecked();
}
void InsertVirtualMethodsDialog::setInsertKeywordVirtual(bool insert)
{
m_insertKeywordVirtual = insert;
}
void InsertVirtualMethodsDialog::setHasImplementationFile(bool file)
{
m_hasImplementationFile = file;
}
void InsertVirtualMethodsDialog::setHasReimplementedFunctions(bool functions)
{
m_hasReimplementedFunctions = functions;
}
bool InsertVirtualMethodsDialog::hideReimplementedFunctions() const
{
// Safty check necessary because of testing class
return (m_hideReimplementedFunctions && m_hideReimplementedFunctions->isChecked());
}
void InsertVirtualMethodsDialog::updateCheckBoxes(QStandardItem *item)
{
if (item->hasChildren()) {
const Qt::CheckState state = item->checkState();
if (!item->isCheckable() || state == Qt::PartiallyChecked)
return;
for (int i = 0; i < item->rowCount(); ++i) {
if (item->child(i, 0)->isCheckable())
item->child(i, 0)->setCheckState(state);
}
} else {
QStandardItem *parent = item->parent();
if (!parent->isCheckable())
return;
const Qt::CheckState state = item->checkState();
for (int i = 0; i < parent->rowCount(); ++i) {
if (state != parent->child(i, 0)->checkState()) {
parent->setCheckState(Qt::PartiallyChecked);
return;
}
}
parent->setCheckState(state);
}
}
void InsertVirtualMethodsDialog::setHideReimplementedFunctions(bool hide)
{
InsertVirtualMethodsFilterModel *model =
qobject_cast<InsertVirtualMethodsFilterModel *>(classFunctionFilterModel);
if (m_expansionStateNormal.isEmpty() && m_expansionStateReimp.isEmpty()) {
model->setHideReimplementedFunctions(hide);
m_view->expandAll();
saveExpansionState();
return;
}
if (model->hideReimplemented() == hide)
return;
saveExpansionState();
model->setHideReimplementedFunctions(hide);
restoreExpansionState();
}
void InsertVirtualMethodsDialog::saveExpansionState()
{
InsertVirtualMethodsFilterModel *model =
qobject_cast<InsertVirtualMethodsFilterModel *>(classFunctionFilterModel);
QList<bool> &state = model->hideReimplemented() ? m_expansionStateReimp
: m_expansionStateNormal;
state.clear();
for (int i = 0; i < model->rowCount(); ++i)
state << m_view->isExpanded(model->index(i, 0));
}
void InsertVirtualMethodsDialog::restoreExpansionState()
{
InsertVirtualMethodsFilterModel *model =
qobject_cast<InsertVirtualMethodsFilterModel *>(classFunctionFilterModel);
const QList<bool> &state = model->hideReimplemented() ? m_expansionStateReimp
: m_expansionStateNormal;
const int stateCount = state.count();
for (int i = 0; i < model->rowCount(); ++i) {
if (i < stateCount && !state.at(i)) {
m_view->collapse(model->index(i, 0));
continue;
}
m_view->expand(model->index(i, 0));
}
}
InsertVirtualMethods::InsertVirtualMethods(InsertVirtualMethodsDialog *dialog)
: m_dialog(dialog)
{}
InsertVirtualMethods::~InsertVirtualMethods()
{
if (m_dialog)
m_dialog->deleteLater();
}
void InsertVirtualMethods::match(const CppQuickFixInterface &interface, QuickFixOperations &result)
{
InsertVirtualMethodsOp *op = new InsertVirtualMethodsOp(interface, m_dialog);
if (op->isValid())
result.append(QuickFixOperation::Ptr(op));
else
delete op;
}
#include "cppquickfixes.moc"

View File

@@ -36,9 +36,18 @@
#include <extensionsystem/iplugin.h> #include <extensionsystem/iplugin.h>
#include <QDialog>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QByteArray; class QByteArray;
class QCheckBox;
class QComboBox;
class QDialogButtonBox;
class QStandardItem;
class QSortFilterProxyModel;
class QStandardItemModel;
class QString; class QString;
class QTreeView;
template <class> class QList; template <class> class QList;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -482,6 +491,78 @@ public:
void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result); void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result);
}; };
/*!
Insert (pure) virtual functions of a base class.
*/
class InsertVirtualMethodsDialog : public QDialog
{
Q_OBJECT
public:
enum CustomItemRoles {
ClassOrFunction = Qt::UserRole + 1,
Implemented = Qt::UserRole + 2,
PureVirtual = Qt::UserRole + 3,
AccessSpec = Qt::UserRole + 4
};
enum ImplementationMode {
ModeOnlyDeclarations = 0x00000001,
ModeInsideClass = 0x00000002,
ModeOutsideClass = 0x00000004,
ModeImplementationFile = 0x00000008
};
InsertVirtualMethodsDialog(QWidget *parent = 0);
void initGui();
void initData();
virtual ImplementationMode implementationMode() const;
void setImplementationsMode(ImplementationMode mode);
virtual bool insertKeywordVirtual() const;
void setInsertKeywordVirtual(bool insert);
void setHasImplementationFile(bool file);
void setHasReimplementedFunctions(bool functions);
bool hideReimplementedFunctions() const;
virtual bool gather();
private slots:
void updateCheckBoxes(QStandardItem *item);
void setHideReimplementedFunctions(bool hide);
private:
QTreeView *m_view;
QCheckBox *m_hideReimplementedFunctions;
QComboBox *m_insertMode;
QCheckBox *m_virtualKeyword;
QDialogButtonBox *m_buttons;
QList<bool> m_expansionStateNormal;
QList<bool> m_expansionStateReimp;
bool m_hasImplementationFile;
bool m_hasReimplementedFunctions;
void saveExpansionState();
void restoreExpansionState();
protected:
ImplementationMode m_implementationMode;
bool m_insertKeywordVirtual;
public:
QStandardItemModel *classFunctionModel;
QSortFilterProxyModel *classFunctionFilterModel;
};
class InsertVirtualMethods: public CppQuickFixFactory
{
Q_OBJECT
public:
InsertVirtualMethods(InsertVirtualMethodsDialog *dialog = new InsertVirtualMethodsDialog);
~InsertVirtualMethods();
void match(const CppQuickFixInterface &interface, TextEditor::QuickFixOperations &result);
private:
InsertVirtualMethodsDialog *m_dialog;
};
} // namespace Internal } // namespace Internal
} // namespace CppEditor } // namespace CppEditor

View File

@@ -42,33 +42,6 @@ using namespace CppTools;
namespace { namespace {
static QString generate(InsertionPointLocator::AccessSpec xsSpec)
{
switch (xsSpec) {
default:
case InsertionPointLocator::Public:
return QLatin1String("public:\n");
case InsertionPointLocator::Protected:
return QLatin1String("protected:\n");
case InsertionPointLocator::Private:
return QLatin1String("private:\n");
case InsertionPointLocator::PublicSlot:
return QLatin1String("public slots:\n");
case InsertionPointLocator::ProtectedSlot:
return QLatin1String("protected slots:\n");
case InsertionPointLocator::PrivateSlot:
return QLatin1String("private slots:\n");
case InsertionPointLocator::Signals:
return QLatin1String("signals:\n");
}
}
static int ordering(InsertionPointLocator::AccessSpec xsSpec) static int ordering(InsertionPointLocator::AccessSpec xsSpec)
{ {
static QList<InsertionPointLocator::AccessSpec> order = QList<InsertionPointLocator::AccessSpec>() static QList<InsertionPointLocator::AccessSpec> order = QList<InsertionPointLocator::AccessSpec>()
@@ -161,7 +134,7 @@ protected:
if (needsLeadingEmptyLine) if (needsLeadingEmptyLine)
prefix += QLatin1String("\n"); prefix += QLatin1String("\n");
if (needsPrefix) if (needsPrefix)
prefix += generate(_xsSpec); prefix += InsertionPointLocator::accessSpecToString(_xsSpec);
QString suffix; QString suffix;
if (needsSuffix) if (needsSuffix)
@@ -299,6 +272,33 @@ InsertionLocation::InsertionLocation(const QString &fileName,
, m_column(column) , m_column(column)
{} {}
QString InsertionPointLocator::accessSpecToString(InsertionPointLocator::AccessSpec xsSpec)
{
switch (xsSpec) {
default:
case InsertionPointLocator::Public:
return QLatin1String("public:\n");
case InsertionPointLocator::Protected:
return QLatin1String("protected:\n");
case InsertionPointLocator::Private:
return QLatin1String("private:\n");
case InsertionPointLocator::PublicSlot:
return QLatin1String("public slots:\n");
case InsertionPointLocator::ProtectedSlot:
return QLatin1String("protected slots:\n");
case InsertionPointLocator::PrivateSlot:
return QLatin1String("private slots:\n");
case InsertionPointLocator::Signals:
return QLatin1String("signals:\n");
}
}
InsertionPointLocator::InsertionPointLocator(const CppRefactoringChanges &refactoringChanges) InsertionPointLocator::InsertionPointLocator(const CppRefactoringChanges &refactoringChanges)
: m_refactoringChanges(refactoringChanges) : m_refactoringChanges(refactoringChanges)
{ {

View File

@@ -89,6 +89,7 @@ public:
ProtectedSlot = Protected | SlotBit, ProtectedSlot = Protected | SlotBit,
PrivateSlot = Private | SlotBit PrivateSlot = Private | SlotBit
}; };
static QString accessSpecToString(InsertionPointLocator::AccessSpec xsSpec);
public: public:
InsertionPointLocator(const CppRefactoringChanges &refactoringChanges); InsertionPointLocator(const CppRefactoringChanges &refactoringChanges);