forked from qt-creator/qt-creator
CppEditor: Fix qualification of return type in getter quickfix
We need to differentiate between "inside class" and "outside class" contexts. Fixes: QTCREATORBUG-32473 Change-Id: Idc763b35f69e85be6f088767b7c96c7e4bfab1e2 Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -1883,9 +1883,26 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
|
|||||||
return; // Maybe report error to the user
|
return; // Maybe report error to the user
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
const FullySpecifiedType returnTypeHeader = [&] {
|
|
||||||
if (!getSetTemplate.returnTypeTemplate.has_value())
|
enum class HeaderContext { InsideClass, OutsideClass };
|
||||||
return m_settings->returnByConstRef ? parameterType : memberVariableType;
|
const auto getReturnTypeHeader = [&](HeaderContext headerContext) {
|
||||||
|
Control *control = m_operation->currentFile()->cppDocument()->control();
|
||||||
|
if (!getSetTemplate.returnTypeTemplate.has_value()) {
|
||||||
|
const FullySpecifiedType &t = m_settings->returnByConstRef ? parameterType
|
||||||
|
: memberVariableType;
|
||||||
|
if (headerContext == HeaderContext::InsideClass)
|
||||||
|
return t;
|
||||||
|
LookupContext context(m_operation->currentFile()->cppDocument(), m_changes.snapshot());
|
||||||
|
SubstitutionEnvironment env;
|
||||||
|
env.setContext(context);
|
||||||
|
env.switchScope(m_class);
|
||||||
|
ClassOrNamespace *targetCoN = context.lookupType(m_class->enclosingScope());
|
||||||
|
if (!targetCoN)
|
||||||
|
targetCoN = context.globalNamespace();
|
||||||
|
UseMinimalNames q(targetCoN);
|
||||||
|
env.enter(&q);
|
||||||
|
return rewriteType(t, &env, control);
|
||||||
|
}
|
||||||
QString typeTemplate = getSetTemplate.returnTypeTemplate.value();
|
QString typeTemplate = getSetTemplate.returnTypeTemplate.value();
|
||||||
if (returnTypeTemplateParameter.has_value())
|
if (returnTypeTemplateParameter.has_value())
|
||||||
typeTemplate.replace(Pattern::TEMPLATE_PARAMETER_PATTERN,
|
typeTemplate.replace(Pattern::TEMPLATE_PARAMETER_PATTERN,
|
||||||
@@ -1893,10 +1910,11 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
|
|||||||
if (typeTemplate.contains(Pattern::TYPE_PATTERN))
|
if (typeTemplate.contains(Pattern::TYPE_PATTERN))
|
||||||
typeTemplate.replace(Pattern::TYPE_PATTERN,
|
typeTemplate.replace(Pattern::TYPE_PATTERN,
|
||||||
overview.prettyType(data.declarationSymbol->type()));
|
overview.prettyType(data.declarationSymbol->type()));
|
||||||
Control *control = m_operation->currentFile()->cppDocument()->control();
|
|
||||||
std::string utf8TypeName = typeTemplate.toUtf8().toStdString();
|
std::string utf8TypeName = typeTemplate.toUtf8().toStdString();
|
||||||
return FullySpecifiedType(control->namedType(control->identifier(utf8TypeName.c_str())));
|
return FullySpecifiedType(control->namedType(control->identifier(utf8TypeName.c_str())));
|
||||||
}();
|
};
|
||||||
|
const FullySpecifiedType returnTypeHeader = getReturnTypeHeader(HeaderContext::OutsideClass);
|
||||||
|
const FullySpecifiedType returnTypeClass = getReturnTypeHeader(HeaderContext::InsideClass);
|
||||||
|
|
||||||
// getter declaration
|
// getter declaration
|
||||||
if (generateFlags & Flag::GenerateGetter) {
|
if (generateFlags & Flag::GenerateGetter) {
|
||||||
@@ -1904,7 +1922,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
|
|||||||
// but here the 'this->' is not needed
|
// but here the 'this->' is not needed
|
||||||
const QString returnExpression = QString{getSetTemplate.returnExpression}.replace("this->",
|
const QString returnExpression = QString{getSetTemplate.returnExpression}.replace("this->",
|
||||||
"");
|
"");
|
||||||
QString getterInClassDeclaration = overview.prettyType(returnTypeHeader, data.getterName)
|
QString getterInClassDeclaration = overview.prettyType(returnTypeClass, data.getterName)
|
||||||
+ QLatin1String("()");
|
+ QLatin1String("()");
|
||||||
if (isMemberVariableStatic)
|
if (isMemberVariableStatic)
|
||||||
getterInClassDeclaration.prepend(QLatin1String("static "));
|
getterInClassDeclaration.prepend(QLatin1String("static "));
|
||||||
@@ -2162,7 +2180,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
|
|||||||
|
|
||||||
// signal declaration
|
// signal declaration
|
||||||
if (generateFlags & Flag::GenerateSignal) {
|
if (generateFlags & Flag::GenerateSignal) {
|
||||||
const auto ¶meter = overview.prettyType(returnTypeHeader, data.qPropertyName);
|
const auto ¶meter = overview.prettyType(returnTypeClass, data.qPropertyName);
|
||||||
const QString newValue = m_settings->signalWithNewValue ? parameter : QString();
|
const QString newValue = m_settings->signalWithNewValue ? parameter : QString();
|
||||||
const QString declaration = QString("void %1(%2);\n").arg(data.signalName, newValue);
|
const QString declaration = QString("void %1(%2);\n").arg(data.signalName, newValue);
|
||||||
addHeaderCode(InsertionPointLocator::Signals, declaration);
|
addHeaderCode(InsertionPointLocator::Signals, declaration);
|
||||||
@@ -2183,7 +2201,7 @@ void GetterSetterRefactoringHelper::performGeneration(ExistingGetterSetterData d
|
|||||||
if (generateFlags & Flag::GenerateProperty || generateFlags & Flag::GenerateConstantProperty) {
|
if (generateFlags & Flag::GenerateProperty || generateFlags & Flag::GenerateConstantProperty) {
|
||||||
// Use the returnTypeHeader as base because of custom types in getSetTemplates.
|
// Use the returnTypeHeader as base because of custom types in getSetTemplates.
|
||||||
// Remove const reference from type.
|
// Remove const reference from type.
|
||||||
FullySpecifiedType type = returnTypeHeader;
|
FullySpecifiedType type = returnTypeClass;
|
||||||
if (ReferenceType *ref = type.type()->asReferenceType())
|
if (ReferenceType *ref = type.type()->asReferenceType())
|
||||||
type = ref->elementType();
|
type = ref->elementType();
|
||||||
type.setConst(false);
|
type.setConst(false);
|
||||||
@@ -4275,6 +4293,58 @@ void Foo::setBar(const custom<N2::test> &newBar)
|
|||||||
GenerateGetterSetter factory;
|
GenerateGetterSetter factory;
|
||||||
QuickFixOperationTest({CppTestDocument::create("file.h", input, {})}, &factory);
|
QuickFixOperationTest({CppTestDocument::create("file.h", input, {})}, &factory);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void testGetterSetterReturnTypeClassScope()
|
||||||
|
{
|
||||||
|
const QByteArray headerInput = R"cpp(
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Bar { b1, b2 };
|
||||||
|
|
||||||
|
private:
|
||||||
|
Bar @m_bar;
|
||||||
|
};
|
||||||
|
)cpp";
|
||||||
|
const QByteArray headerOutput = R"cpp(
|
||||||
|
class Foo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum Bar { b1, b2 };
|
||||||
|
|
||||||
|
Bar bar() const;
|
||||||
|
void setBar(Bar newBar);
|
||||||
|
|
||||||
|
private:
|
||||||
|
Bar m_bar;
|
||||||
|
};
|
||||||
|
)cpp";
|
||||||
|
const QByteArray srcInput = "#include \"foo.h\"\n";
|
||||||
|
const QByteArray srcOutput = R"cpp(#include "foo.h"
|
||||||
|
|
||||||
|
Foo::Bar Foo::bar() const
|
||||||
|
{
|
||||||
|
return m_bar;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Foo::setBar(Bar newBar)
|
||||||
|
{
|
||||||
|
m_bar = newBar;
|
||||||
|
}
|
||||||
|
)cpp";
|
||||||
|
|
||||||
|
QList<TestDocumentPtr> testDocuments{
|
||||||
|
CppTestDocument::create("foo.h", headerInput, headerOutput),
|
||||||
|
CppTestDocument::create("foo.cpp", srcInput, srcOutput),
|
||||||
|
};
|
||||||
|
|
||||||
|
// QuickFixSettings s;
|
||||||
|
// s->getterOutsideClassFrom = 0;
|
||||||
|
// s->getterInCppFileFrom = 0;
|
||||||
|
|
||||||
|
GenerateGetterSetter factory;
|
||||||
|
QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 2);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class GenerateGettersSettersTest : public QObject
|
class GenerateGettersSettersTest : public QObject
|
||||||
|
Reference in New Issue
Block a user