forked from qt-creator/qt-creator
CPlusPlus: Improve type name minimization
... for function parameters. These are located in the scope of the surrounding class or namespace. This uncovered a bug in the "Insert Virtual Functions of Base Classes" quickfix, which we also fix here. Fixes: QTCREATORBUG-8030 Change-Id: I7f11659dc8e252e3819df8178734e8958fa1b496 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -142,6 +142,17 @@ public:
|
|||||||
|
|
||||||
funTy->setReturnType(rewrite->rewriteType(type->returnType()));
|
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) {
|
for (unsigned i = 0, argc = type->argumentCount(); i < argc; ++i) {
|
||||||
Symbol *arg = type->argumentAt(i);
|
Symbol *arg = type->argumentAt(i);
|
||||||
|
|
||||||
@@ -156,6 +167,11 @@ public:
|
|||||||
funTy->addMember(newArg);
|
funTy->addMember(newArg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (target) {
|
||||||
|
rewrite->env->switchScope(scope);
|
||||||
|
rewrite->env->leave();
|
||||||
|
}
|
||||||
|
|
||||||
temps.append(funTy);
|
temps.append(funTy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -161,6 +161,7 @@ private slots:
|
|||||||
void test_quickfix_InsertDefFromDecl_templateClass();
|
void test_quickfix_InsertDefFromDecl_templateClass();
|
||||||
void test_quickfix_InsertDefFromDecl_templateFunction();
|
void test_quickfix_InsertDefFromDecl_templateFunction();
|
||||||
void test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc();
|
void test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc();
|
||||||
|
void test_quickfix_InsertDefFromDecl_minimalFunctionParameterType();
|
||||||
void test_quickfix_InsertDefsFromDecls_data();
|
void test_quickfix_InsertDefsFromDecls_data();
|
||||||
void test_quickfix_InsertDefsFromDecls();
|
void test_quickfix_InsertDefsFromDecls();
|
||||||
|
|
||||||
|
@@ -823,16 +823,31 @@ public:
|
|||||||
headerChangeSet.insert(m_insertPosDecl, comment);
|
headerChangeSet.insert(m_insertPosDecl, comment);
|
||||||
first = false;
|
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;
|
// Function type minimalization: As base class and derived class could be in
|
||||||
const FullySpecifiedType tn = rewriteType(funcItem->function->type(), &env, control);
|
// different namespaces, we must first make the type fully qualified before
|
||||||
declaration += printer.prettyType(tn, funcItem->function->unqualifiedName());
|
// it can get minimized.
|
||||||
|
Clone cloner(control);
|
||||||
|
Function newFunc(&cloner, nullptr, const_cast<Function *>(funcItem->function));
|
||||||
|
newFunc.setEnclosingScope(const_cast<Class *>(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)
|
if (m_factory->settings()->insertVirtualKeyword)
|
||||||
declaration = QLatin1String("virtual ") + declaration;
|
declaration = QLatin1String("virtual ") + declaration;
|
||||||
|
@@ -4593,6 +4593,68 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc(
|
|||||||
QuickFixOperationTest(singleDocument(contents, ""), &factory);
|
QuickFixOperationTest(singleDocument(contents, ""), &factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_quickfix_InsertDefFromDecl_minimalFunctionParameterType()
|
||||||
|
{
|
||||||
|
QList<QuickFixTestDocument::Ptr> 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()
|
void CppEditorPlugin::test_quickfix_InsertDefsFromDecls_data()
|
||||||
{
|
{
|
||||||
QTest::addColumn<QByteArrayList>("headers");
|
QTest::addColumn<QByteArrayList>("headers");
|
||||||
|
Reference in New Issue
Block a user