forked from qt-creator/qt-creator
CppEditor: Offer InsertDefsOperation quickfix for all classes
The check whether there are unimplemented member functions takes quite long, so Creator would freeze for several seconds when right-clicking on the name of even a medium-sized class. Therefore, we offer the operation for all classes with member functions and move the expensive check into the perform() method. Change-Id: Ie19958ba8c53493be859f9982d7d5697e6e9d88b Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -3653,6 +3653,23 @@ void CppEditorPlugin::test_quickfix_InsertDefsFromDecls_data()
|
|||||||
|
|
||||||
} // namespace N)";
|
} // namespace N)";
|
||||||
QTest::addRow("no candidates")
|
QTest::addRow("no candidates")
|
||||||
|
<< QByteArrayList{origHeader, origHeader}
|
||||||
|
<< QByteArrayList{origSource, origSource}
|
||||||
|
<< int(InsertDefsFromDecls::Mode::Alternating);
|
||||||
|
|
||||||
|
origHeader = R"(
|
||||||
|
namespace N {
|
||||||
|
class @C
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
friend void ignoredFriend();
|
||||||
|
void ignoredImplemented() {};
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void ignoredSignal();
|
||||||
|
};
|
||||||
|
} // namespace N)";
|
||||||
|
QTest::addRow("no member functions")
|
||||||
<< QByteArrayList{origHeader, ""}
|
<< QByteArrayList{origHeader, ""}
|
||||||
<< QByteArrayList{origSource, ""}
|
<< QByteArrayList{origSource, ""}
|
||||||
<< int(InsertDefsFromDecls::Mode::Alternating);
|
<< int(InsertDefsFromDecls::Mode::Alternating);
|
||||||
|
@@ -3479,12 +3479,11 @@ public:
|
|||||||
m_classAST = path.at(path.size() - 2)->asClassSpecifier();
|
m_classAST = path.at(path.size() - 2)->asClassSpecifier();
|
||||||
if (!m_classAST)
|
if (!m_classAST)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Class * const theClass = m_classAST->symbol;
|
const Class * const theClass = m_classAST->symbol;
|
||||||
if (!theClass)
|
if (!theClass)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
// Collect all member functions without an implementation.
|
// Collect all member functions.
|
||||||
for (auto it = theClass->memberBegin(); it != theClass->memberEnd(); ++it) {
|
for (auto it = theClass->memberBegin(); it != theClass->memberEnd(); ++it) {
|
||||||
Symbol * const s = *it;
|
Symbol * const s = *it;
|
||||||
if (!s->identifier() || !s->type() || !s->isDeclaration() || s->asFunction())
|
if (!s->identifier() || !s->type() || !s->isDeclaration() || s->asFunction())
|
||||||
@@ -3492,8 +3491,6 @@ public:
|
|||||||
Function * const func = s->type()->asFunctionType();
|
Function * const func = s->type()->asFunctionType();
|
||||||
if (!func || func->isSignal() || func->isFriend())
|
if (!func || func->isSignal() || func->isFriend())
|
||||||
continue;
|
continue;
|
||||||
if (SymbolFinder().findMatchingDefinition(s, interface.snapshot()))
|
|
||||||
continue;
|
|
||||||
m_declarations << s;
|
m_declarations << s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3504,7 +3501,14 @@ public:
|
|||||||
private:
|
private:
|
||||||
void perform() override
|
void perform() override
|
||||||
{
|
{
|
||||||
QTC_ASSERT(!m_declarations.isEmpty(), return);
|
QList<Symbol *> unimplemented;
|
||||||
|
SymbolFinder symbolFinder;
|
||||||
|
for (Symbol * const s : qAsConst(m_declarations)) {
|
||||||
|
if (!symbolFinder.findMatchingDefinition(s, snapshot()))
|
||||||
|
unimplemented << s;
|
||||||
|
}
|
||||||
|
if (unimplemented.isEmpty())
|
||||||
|
return;
|
||||||
|
|
||||||
CppRefactoringChanges refactoring(snapshot());
|
CppRefactoringChanges refactoring(snapshot());
|
||||||
const bool isHeaderFile = ProjectFile::isHeader(ProjectFile::classify(filePath().toString()));
|
const bool isHeaderFile = ProjectFile::isHeader(ProjectFile::classify(filePath().toString()));
|
||||||
@@ -3512,7 +3516,7 @@ private:
|
|||||||
if (isHeaderFile) {
|
if (isHeaderFile) {
|
||||||
InsertionPointLocator locator(refactoring);
|
InsertionPointLocator locator(refactoring);
|
||||||
for (const InsertionLocation &location
|
for (const InsertionLocation &location
|
||||||
: locator.methodDefinition(m_declarations.first(), false, {})) {
|
: locator.methodDefinition(unimplemented.first(), false, {})) {
|
||||||
if (!location.isValid())
|
if (!location.isValid())
|
||||||
continue;
|
continue;
|
||||||
const QString fileName = location.fileName();
|
const QString fileName = location.fileName();
|
||||||
@@ -3530,7 +3534,7 @@ private:
|
|||||||
MemberFunctionImplSettings settings;
|
MemberFunctionImplSettings settings;
|
||||||
switch (m_mode) {
|
switch (m_mode) {
|
||||||
case InsertDefsFromDecls::Mode::User: {
|
case InsertDefsFromDecls::Mode::User: {
|
||||||
AddImplementationsDialog dlg(m_declarations, Utils::FilePath::fromString(cppFile));
|
AddImplementationsDialog dlg(unimplemented, Utils::FilePath::fromString(cppFile));
|
||||||
if (dlg.exec() == QDialog::Accepted)
|
if (dlg.exec() == QDialog::Accepted)
|
||||||
settings = dlg.settings();
|
settings = dlg.settings();
|
||||||
break;
|
break;
|
||||||
@@ -3540,7 +3544,7 @@ private:
|
|||||||
const auto incDefPos = [&defPos] {
|
const auto incDefPos = [&defPos] {
|
||||||
defPos = (defPos + 1) % (DefPosImplementationFile + 2);
|
defPos = (defPos + 1) % (DefPosImplementationFile + 2);
|
||||||
};
|
};
|
||||||
for (Symbol * const func : qAsConst(m_declarations)) {
|
for (Symbol * const func : qAsConst(unimplemented)) {
|
||||||
incDefPos();
|
incDefPos();
|
||||||
if (defPos > DefPosImplementationFile)
|
if (defPos > DefPosImplementationFile)
|
||||||
continue;
|
continue;
|
||||||
@@ -3610,8 +3614,8 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ClassSpecifierAST *m_classAST = nullptr;
|
ClassSpecifierAST *m_classAST = nullptr;
|
||||||
QList<Symbol *> m_declarations;
|
|
||||||
InsertDefsFromDecls::Mode m_mode;
|
InsertDefsFromDecls::Mode m_mode;
|
||||||
|
QList<Symbol *> m_declarations;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user