forked from qt-creator/qt-creator
CppEditor: Fix "insert def from decl" for template return types
Fixes: QTCREATORBUG-26397 Change-Id: Ia215f2c2b5da708b0fd7c894987683b305f4ccec Reviewed-by: Christian Stenger <christian.stenger@qt.io>
This commit is contained in:
12
src/libs/3rdparty/cplusplus/Control.cpp
vendored
12
src/libs/3rdparty/cplusplus/Control.cpp
vendored
@@ -844,3 +844,15 @@ void Control::addSymbol(Symbol *symbol)
|
||||
{
|
||||
d->symbols.push_back(symbol);
|
||||
}
|
||||
|
||||
const Name *Control::toName(const QList<const Name *> &names)
|
||||
{
|
||||
const Name *n = nullptr;
|
||||
for (int i = names.size() - 1; i >= 0; --i) {
|
||||
if (! n)
|
||||
n = names.at(i);
|
||||
else
|
||||
n = qualifiedNameId(names.at(i), n);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
2
src/libs/3rdparty/cplusplus/Control.h
vendored
2
src/libs/3rdparty/cplusplus/Control.h
vendored
@@ -218,6 +218,8 @@ public:
|
||||
bool hasSymbol(Symbol *symbol) const;
|
||||
void addSymbol(Symbol *symbol);
|
||||
|
||||
const Name *toName(const QList<const Name *> &names);
|
||||
|
||||
private:
|
||||
class Data;
|
||||
friend class Data;
|
||||
|
@@ -283,8 +283,21 @@ public:
|
||||
number->size()));
|
||||
}
|
||||
}
|
||||
temps.append(control()->templateNameId(identifier(name->identifier()), name->isSpecialization(),
|
||||
args.data(), args.size()));
|
||||
|
||||
const FullySpecifiedType ty = rewrite->env->apply(name->identifier(), rewrite);
|
||||
const Name * const minName = ty->isNamedType() ? ty->asNamedType()->name() : name;
|
||||
const TemplateNameId * const newTemplateNameId = control()->templateNameId(
|
||||
identifier(minName->identifier()), name->isSpecialization(), args.data(),
|
||||
args.size());
|
||||
const QList<const Name *> names = disassembledName(minName);
|
||||
if (names.size() == 1) {
|
||||
temps.append(newTemplateNameId);
|
||||
} else {
|
||||
const Name * const newBaseName = control()->toName(names.mid(0, names.size() - 1));
|
||||
const Name * const fullName = control()->qualifiedNameId(newBaseName,
|
||||
newTemplateNameId);
|
||||
temps.append(fullName);
|
||||
}
|
||||
}
|
||||
|
||||
void visit(const DestructorNameId *name) override
|
||||
@@ -317,6 +330,36 @@ public: // attributes
|
||||
SubstitutionEnvironment *env;
|
||||
RewriteType rewriteType;
|
||||
RewriteName rewriteName;
|
||||
|
||||
private:
|
||||
static QList<const Name *> disassembledName(const Name *name)
|
||||
{
|
||||
class NameDisassembler : public NameVisitor
|
||||
{
|
||||
public:
|
||||
QList<const Name *> names() const { return m_names; }
|
||||
|
||||
void visit(const AnonymousNameId *n) override { m_names << n; }
|
||||
virtual void visit(const Identifier *n) override { m_names << n; }
|
||||
virtual void visit(const TemplateNameId *n) override { m_names << n; }
|
||||
virtual void visit(const DestructorNameId *n) override { m_names << n; }
|
||||
virtual void visit(const OperatorNameId *n) override { m_names << n; }
|
||||
virtual void visit(const ConversionNameId *n) override { m_names << n; }
|
||||
virtual void visit(const SelectorNameId *n) override { m_names << n; }
|
||||
virtual void visit(const QualifiedNameId *n) override
|
||||
{
|
||||
if (n->base())
|
||||
n->base()->accept(this);
|
||||
n->name()->accept(this);
|
||||
}
|
||||
private:
|
||||
QList<const Name *> m_names;
|
||||
};
|
||||
|
||||
NameDisassembler nd;
|
||||
nd.accept(name);
|
||||
return nd.names();
|
||||
}
|
||||
};
|
||||
|
||||
SubstitutionEnvironment::SubstitutionEnvironment()
|
||||
|
@@ -241,19 +241,6 @@ static bool symbolIdentical(Symbol *s1, Symbol *s2)
|
||||
return QByteArray(s1->fileName()) == QByteArray(s2->fileName());
|
||||
}
|
||||
|
||||
static const Name *toName(const QList<const Name *> &names, Control *control)
|
||||
{
|
||||
const Name *n = nullptr;
|
||||
for (int i = names.size() - 1; i >= 0; --i) {
|
||||
if (! n)
|
||||
n = names.at(i);
|
||||
else
|
||||
n = control->qualifiedNameId(names.at(i), n);
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
static bool isInlineNamespace(ClassOrNamespace *con, const Name *name)
|
||||
{
|
||||
const QList<LookupItem> items = con->find(name);
|
||||
@@ -282,12 +269,12 @@ const Name *LookupContext::minimalName(Symbol *symbol, ClassOrNamespace *target,
|
||||
// eliminate inline namespaces
|
||||
QList<const Name *> minimal = names;
|
||||
for (int i = minimal.size() - 2; i >= 0; --i) {
|
||||
const Name *candidate = toName(minimal.mid(0, i + 1), control);
|
||||
const Name *candidate = control->toName(minimal.mid(0, i + 1));
|
||||
if (isInlineNamespace(target, candidate))
|
||||
minimal.removeAt(i);
|
||||
}
|
||||
|
||||
return toName(minimal, control);
|
||||
return control->toName(minimal);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
|
@@ -4707,6 +4707,43 @@ N::S N::foo(const S &s)
|
||||
QuickFixOperationTest(testDocuments, &factory);
|
||||
}
|
||||
|
||||
void QuickfixTest::testInsertDefFromDeclAliasTemplateAsReturnType()
|
||||
{
|
||||
QList<TestDocumentPtr> testDocuments;
|
||||
|
||||
QByteArray original;
|
||||
QByteArray expected;
|
||||
|
||||
// Header File
|
||||
original = R"(
|
||||
struct foo {
|
||||
struct foo2 {
|
||||
template <typename T> using MyType = T;
|
||||
MyType<int> @bar();
|
||||
};
|
||||
};
|
||||
)";
|
||||
expected = original;
|
||||
testDocuments << CppTestDocument::create("file.h", original, expected);
|
||||
|
||||
// Source File
|
||||
original = R"(
|
||||
#include "file.h"
|
||||
)";
|
||||
expected = R"(
|
||||
#include "file.h"
|
||||
|
||||
foo::foo2::MyType<int> foo::foo2::bar()
|
||||
{
|
||||
|
||||
}
|
||||
)";
|
||||
testDocuments << CppTestDocument::create("file.cpp", original, expected);
|
||||
|
||||
InsertDefFromDecl factory;
|
||||
QuickFixOperationTest(testDocuments, &factory);
|
||||
}
|
||||
|
||||
void QuickfixTest::testInsertDefsFromDecls_data()
|
||||
{
|
||||
QTest::addColumn<QByteArrayList>("headers");
|
||||
|
@@ -155,6 +155,7 @@ private slots:
|
||||
void testInsertDefFromDeclTemplateFunction();
|
||||
void testInsertDefFromDeclNotTriggeredForFriendFunc();
|
||||
void testInsertDefFromDeclMinimalFunctionParameterType();
|
||||
void testInsertDefFromDeclAliasTemplateAsReturnType();
|
||||
void testInsertDefsFromDecls_data();
|
||||
void testInsertDefsFromDecls();
|
||||
|
||||
|
Reference in New Issue
Block a user