forked from qt-creator/qt-creator
CppEditor: Ensure "inline" specifier
... when creating functions in header files. Otherwise, we will likely cause linker failures in non-trivial projects. Fixes: QTCREATORBUG-15052 Change-Id: Ic0fff8779ba924f8b9943ab233a0cda409e73e9d Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
@@ -108,6 +108,7 @@ private slots:
|
|||||||
void test_quickfix_GenerateGetterSetter_onlyGetter();
|
void test_quickfix_GenerateGetterSetter_onlyGetter();
|
||||||
void test_quickfix_GenerateGetterSetter_onlyGetter_DontPreferGetterWithGet();
|
void test_quickfix_GenerateGetterSetter_onlyGetter_DontPreferGetterWithGet();
|
||||||
void test_quickfix_GenerateGetterSetter_onlySetter();
|
void test_quickfix_GenerateGetterSetter_onlySetter();
|
||||||
|
void test_quickfix_GenerateGetterSetter_onlySetterHeaderFile();
|
||||||
void test_quickfix_GenerateGetterSetter_offerGetterWhenSetterPresent();
|
void test_quickfix_GenerateGetterSetter_offerGetterWhenSetterPresent();
|
||||||
void test_quickfix_GenerateGetterSetter_offerSetterWhenGetterPresent();
|
void test_quickfix_GenerateGetterSetter_offerSetterWhenGetterPresent();
|
||||||
void test_quickfix_GenerateGettersSetters_data();
|
void test_quickfix_GenerateGettersSetters_data();
|
||||||
|
|||||||
@@ -2242,6 +2242,31 @@ void CppEditorPlugin::test_quickfix_GenerateGetterSetter_onlySetter()
|
|||||||
QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 2);
|
QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CppEditorPlugin::test_quickfix_GenerateGetterSetter_onlySetterHeaderFile()
|
||||||
|
{
|
||||||
|
QList<QuickFixTestDocument::Ptr> testDocuments;
|
||||||
|
const QByteArray original =
|
||||||
|
"class Foo\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" int bar@;\n"
|
||||||
|
"};\n";
|
||||||
|
const QByteArray expected =
|
||||||
|
"class Foo\n"
|
||||||
|
"{\n"
|
||||||
|
"public:\n"
|
||||||
|
" int bar@;\n"
|
||||||
|
" void setBar(int value);\n"
|
||||||
|
"};\n\n"
|
||||||
|
"inline void Foo::setBar(int value)\n"
|
||||||
|
"{\n"
|
||||||
|
" bar = value;\n"
|
||||||
|
"}\n";
|
||||||
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
||||||
|
GenerateGetterSetter factory;
|
||||||
|
QuickFixOperationTest(testDocuments, &factory, ProjectExplorer::HeaderPaths(), 2);
|
||||||
|
}
|
||||||
|
|
||||||
class CppCodeStyleSettingsChanger {
|
class CppCodeStyleSettingsChanger {
|
||||||
public:
|
public:
|
||||||
CppCodeStyleSettingsChanger(const CppCodeStyleSettings &settings);
|
CppCodeStyleSettingsChanger(const CppCodeStyleSettings &settings);
|
||||||
@@ -2457,17 +2482,17 @@ private:
|
|||||||
int bar2_;
|
int bar2_;
|
||||||
QString bar3;
|
QString bar3;
|
||||||
};
|
};
|
||||||
void Foo::setBar2(int bar2)
|
inline void Foo::setBar2(int bar2)
|
||||||
{
|
{
|
||||||
bar2_ = bar2;
|
bar2_ = bar2;
|
||||||
}
|
}
|
||||||
|
|
||||||
QString Foo::getBar3() const
|
inline QString Foo::getBar3() const
|
||||||
{
|
{
|
||||||
return bar3;
|
return bar3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Foo::setBar3(const QString &value)
|
inline void Foo::setBar3(const QString &value)
|
||||||
{
|
{
|
||||||
bar3 = value;
|
bar3 = value;
|
||||||
}
|
}
|
||||||
@@ -2513,7 +2538,7 @@ void CppEditorPlugin::test_quickfix_InsertDefFromDecl_afterClass()
|
|||||||
" void a();\n"
|
" void a();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void Foo::a()\n"
|
"inline void Foo::a()\n"
|
||||||
"{\n\n}\n"
|
"{\n\n}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"class Bar {};\n";
|
"class Bar {};\n";
|
||||||
@@ -4422,7 +4447,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_MemberFuncOutside2()
|
|||||||
" void f3();\n"
|
" void f3();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"int Foo::f2()\n"
|
"inline int Foo::f2()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return 1;\n"
|
" return 1;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
@@ -4728,7 +4753,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefOutside_afterClass()
|
|||||||
" void a();\n"
|
" void a();\n"
|
||||||
"};\n"
|
"};\n"
|
||||||
"\n"
|
"\n"
|
||||||
"void Foo::a() {}\n"
|
"inline void Foo::a() {}\n"
|
||||||
"\n"
|
"\n"
|
||||||
"class Bar {};\n";
|
"class Bar {};\n";
|
||||||
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
testDocuments << QuickFixTestDocument::create("file.h", original, expected);
|
||||||
@@ -5017,7 +5042,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCpp()
|
|||||||
// Header File
|
// Header File
|
||||||
original = "int number() const;\n";
|
original = "int number() const;\n";
|
||||||
expected =
|
expected =
|
||||||
"int number() const\n"
|
"inline int number() const\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return 5;\n"
|
" return 5;\n"
|
||||||
"}\n";
|
"}\n";
|
||||||
@@ -5053,7 +5078,7 @@ void CppEditorPlugin::test_quickfix_MoveFuncDefToDecl_FreeFuncToCppNS()
|
|||||||
"}\n";
|
"}\n";
|
||||||
expected =
|
expected =
|
||||||
"namespace MyNamespace {\n"
|
"namespace MyNamespace {\n"
|
||||||
"int number() const\n"
|
"inline int number() const\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" return 5;\n"
|
" return 5;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
@@ -5442,7 +5467,7 @@ void CppEditorPlugin::test_quickfix_ExtractFunction_data()
|
|||||||
"{\n"
|
"{\n"
|
||||||
" @{start}g();@{end}\n"
|
" @{start}g();@{end}\n"
|
||||||
"}\n")
|
"}\n")
|
||||||
<< _("void extracted()\n"
|
<< _("inline void extracted()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" g();\n"
|
" g();\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
@@ -5469,7 +5494,7 @@ void CppEditorPlugin::test_quickfix_ExtractFunction_data()
|
|||||||
"private:\n"
|
"private:\n"
|
||||||
" void bar();\n"
|
" void bar();\n"
|
||||||
"};\n\n"
|
"};\n\n"
|
||||||
"void Foo::extracted()\n"
|
"inline void Foo::extracted()\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" g();\n"
|
" g();\n"
|
||||||
"}\n\n"
|
"}\n\n"
|
||||||
@@ -5496,7 +5521,7 @@ void CppEditorPlugin::test_quickfix_ExtractFunction_data()
|
|||||||
" void extracted(NS::C &c);\n" // TODO: Remove non-required qualification
|
" void extracted(NS::C &c);\n" // TODO: Remove non-required qualification
|
||||||
"};\n"
|
"};\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
"void NS::C::extracted(NS::C &c)\n"
|
"inline void NS::C::extracted(NS::C &c)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
" C *c = &c;\n"
|
" C *c = &c;\n"
|
||||||
"}\n"
|
"}\n"
|
||||||
|
|||||||
@@ -114,6 +114,15 @@ const QList<CppQuickFixFactory *> &CppQuickFixFactory::cppQuickFixFactories()
|
|||||||
|
|
||||||
namespace Internal {
|
namespace Internal {
|
||||||
|
|
||||||
|
QString inlinePrefix(const QString &targetFile, const std::function<bool()> &extraCondition = {})
|
||||||
|
{
|
||||||
|
if (ProjectFile::isHeader(ProjectFile::classify(targetFile))
|
||||||
|
&& (!extraCondition || extraCondition())) {
|
||||||
|
return "inline ";
|
||||||
|
}
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
// 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
|
||||||
// different quick fixes.
|
// different quick fixes.
|
||||||
namespace {
|
namespace {
|
||||||
@@ -2831,8 +2840,10 @@ public:
|
|||||||
}
|
}
|
||||||
const QString name = oo.prettyName(LookupContext::minimalName(m_decl, targetCoN,
|
const QString name = oo.prettyName(LookupContext::minimalName(m_decl, targetCoN,
|
||||||
control));
|
control));
|
||||||
|
const QString defText = inlinePrefix(
|
||||||
const QString defText = oo.prettyType(tn, name) + QLatin1String("\n{\n\n}");
|
m_targetFileName, [this] { return m_defpos == DefPosOutsideClass; })
|
||||||
|
+ oo.prettyType(tn, name)
|
||||||
|
+ QLatin1String("\n{\n\n}");
|
||||||
|
|
||||||
const int targetPos = targetFile->position(m_loc.line(), m_loc.column());
|
const int targetPos = targetFile->position(m_loc.line(), m_loc.column());
|
||||||
const int targetPos2 = qMax(0, targetFile->position(m_loc.line(), 1) - 1);
|
const int targetPos2 = qMax(0, targetFile->position(m_loc.line(), 1) - 1);
|
||||||
@@ -3290,14 +3301,15 @@ public:
|
|||||||
// Construct implementation strings
|
// Construct implementation strings
|
||||||
const QString implementationGetterTypeAndNameString = oo.prettyType(
|
const QString implementationGetterTypeAndNameString = oo.prettyType(
|
||||||
getterType, QString::fromLatin1("%1::%2").arg(classString, getterName));
|
getterType, QString::fromLatin1("%1::%2").arg(classString, getterName));
|
||||||
const QString implementationGetter = QString::fromLatin1("%1()%2\n"
|
const QString inlineSpecifier = sameFile && wasHeader ? QString("inline") : QString();
|
||||||
|
const QString implementationGetter = QString::fromLatin1("%4 %1()%2\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"return %3;\n"
|
"return %3;\n"
|
||||||
"}")
|
"}")
|
||||||
.arg(implementationGetterTypeAndNameString,
|
.arg(implementationGetterTypeAndNameString,
|
||||||
isStatic ? QString() : QLatin1String(" const"),
|
isStatic ? QString() : QLatin1String(" const"),
|
||||||
rawName);
|
rawName, inlineSpecifier);
|
||||||
const QString implementationSetter = QString::fromLatin1("void %1::%2(%3)\n"
|
const QString implementationSetter = QString::fromLatin1("%6 void %1::%2(%3)\n"
|
||||||
"{\n"
|
"{\n"
|
||||||
"%4 = %5;\n"
|
"%4 = %5;\n"
|
||||||
"}")
|
"}")
|
||||||
@@ -3305,7 +3317,8 @@ public:
|
|||||||
setterName,
|
setterName,
|
||||||
paramString,
|
paramString,
|
||||||
rawName,
|
rawName,
|
||||||
paramName);
|
paramName,
|
||||||
|
inlineSpecifier);
|
||||||
|
|
||||||
QString implementation;
|
QString implementation;
|
||||||
if (generateGetter())
|
if (generateGetter())
|
||||||
@@ -3872,6 +3885,7 @@ public:
|
|||||||
}
|
}
|
||||||
funcDef.append(QLatin1String("\n}\n\n"));
|
funcDef.append(QLatin1String("\n}\n\n"));
|
||||||
funcDef.replace(QChar::ParagraphSeparator, QLatin1String("\n"));
|
funcDef.replace(QChar::ParagraphSeparator, QLatin1String("\n"));
|
||||||
|
funcDef.prepend(inlinePrefix(currentFile->fileName()));
|
||||||
funcCall.append(QLatin1Char(';'));
|
funcCall.append(QLatin1Char(';'));
|
||||||
|
|
||||||
// Get starting indentation from original code.
|
// Get starting indentation from original code.
|
||||||
@@ -5288,8 +5302,10 @@ public:
|
|||||||
Scope *scopeAtInsertPos = m_toFile->cppDocument()->scopeAt(l.line(), l.column());
|
Scope *scopeAtInsertPos = m_toFile->cppDocument()->scopeAt(l.line(), l.column());
|
||||||
|
|
||||||
// construct definition
|
// construct definition
|
||||||
const QString funcDec = definitionSignature(m_operation, funcAST, m_fromFile, m_toFile,
|
const QString funcDec = inlinePrefix(
|
||||||
scopeAtInsertPos);
|
m_toFile->fileName(), [this] { return m_type == MoveOutside; })
|
||||||
|
+ definitionSignature(m_operation, funcAST, m_fromFile, m_toFile,
|
||||||
|
scopeAtInsertPos);
|
||||||
QString funcDef = prefix + funcDec;
|
QString funcDef = prefix + funcDec;
|
||||||
const int startPosition = m_fromFile->endOf(funcAST->declarator);
|
const int startPosition = m_fromFile->endOf(funcAST->declarator);
|
||||||
const int endPosition = m_fromFile->endOf(funcAST);
|
const int endPosition = m_fromFile->endOf(funcAST);
|
||||||
@@ -5686,8 +5702,10 @@ void MoveFuncDefToDecl::match(const CppQuickFixInterface &interface, QuickFixOpe
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!declText.isEmpty())
|
if (!declText.isEmpty()) {
|
||||||
|
declText.prepend(inlinePrefix(declFileName));
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user