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()));
|
||||
|
||||
// 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);
|
||||
}
|
||||
|
||||
|
@@ -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();
|
||||
|
||||
|
@@ -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<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)
|
||||
declaration = QLatin1String("virtual ") + declaration;
|
||||
|
@@ -4593,6 +4593,68 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_notTriggeredForFriendFunc(
|
||||
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()
|
||||
{
|
||||
QTest::addColumn<QByteArrayList>("headers");
|
||||
|
Reference in New Issue
Block a user