forked from qt-creator/qt-creator
C++: Handle recursive auto declarations
Remember auto declarations we have already looked up and stop if we try
it again.
Task-number: QTCREATORBUG-9503
Change-Id: I989b11609c98bf197ce916d79c9d452294355053
Reviewed-by: Przemyslaw Gorszkowski <pgorszkowski@gmail.com>
Reviewed-by: Erik Verbruggen <erik.verbruggen@digia.com>
(cherry picked from commit 8f1b665667
)
This commit is contained in:
@@ -75,11 +75,13 @@ static QList<_Tp> removeDuplicates(const QList<_Tp> &results)
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
// ResolveExpression
|
||||
/////////////////////////////////////////////////////////////////////
|
||||
ResolveExpression::ResolveExpression(const LookupContext &context)
|
||||
ResolveExpression::ResolveExpression(const LookupContext &context,
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
|
||||
: ASTVisitor(context.expressionDocument()->translationUnit()),
|
||||
_scope(0),
|
||||
_context(context),
|
||||
bind(context.expressionDocument()->translationUnit()),
|
||||
_autoDeclarationsBeingResolved(autoDeclarationsBeingResolved),
|
||||
_reference(false)
|
||||
{ }
|
||||
|
||||
@@ -519,6 +521,10 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
if (!decl)
|
||||
continue;
|
||||
|
||||
// Stop on recursive auto declarations
|
||||
if (_autoDeclarationsBeingResolved.contains(decl))
|
||||
continue;
|
||||
|
||||
const StringLiteral *initializationString = decl->getInitializer();
|
||||
if (initializationString == 0)
|
||||
continue;
|
||||
@@ -533,7 +539,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
|
||||
TypeOfExpression exprTyper;
|
||||
Document::Ptr doc = _context.snapshot().document(QString::fromLocal8Bit(decl->fileName()));
|
||||
exprTyper.init(doc, _context.snapshot(), _context.bindings());
|
||||
exprTyper.init(doc, _context.snapshot(), _context.bindings(),
|
||||
QSet<const Declaration* >(_autoDeclarationsBeingResolved) << decl);
|
||||
|
||||
Document::Ptr exprDoc =
|
||||
documentForExpression(exprTyper.preprocessedExpression(initializer));
|
||||
@@ -543,8 +550,8 @@ bool ResolveExpression::visit(SimpleNameAST *ast)
|
||||
if (deduceAuto._block)
|
||||
continue;
|
||||
|
||||
const QList<LookupItem> &typeItems =
|
||||
exprTyper(extractExpressionAST(exprDoc), exprDoc, decl->enclosingScope());
|
||||
const QList<LookupItem> &typeItems = exprTyper(extractExpressionAST(exprDoc), exprDoc,
|
||||
decl->enclosingScope());
|
||||
if (typeItems.empty())
|
||||
continue;
|
||||
|
||||
|
@@ -42,7 +42,9 @@ namespace CPlusPlus {
|
||||
class CPLUSPLUS_EXPORT ResolveExpression: protected ASTVisitor
|
||||
{
|
||||
public:
|
||||
ResolveExpression(const LookupContext &context);
|
||||
ResolveExpression(const LookupContext &context,
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved
|
||||
= QSet<const Declaration *>());
|
||||
virtual ~ResolveExpression();
|
||||
|
||||
QList<LookupItem> operator()(ExpressionAST *ast, Scope *scope);
|
||||
@@ -125,6 +127,7 @@ private:
|
||||
const LookupContext& _context;
|
||||
Bind bind;
|
||||
QList<LookupItem> _results;
|
||||
QSet<const Declaration *> _autoDeclarationsBeingResolved;
|
||||
bool _reference;
|
||||
};
|
||||
|
||||
|
@@ -58,7 +58,8 @@ void TypeOfExpression::reset()
|
||||
}
|
||||
|
||||
void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot,
|
||||
QSharedPointer<CreateBindings> bindings)
|
||||
QSharedPointer<CreateBindings> bindings,
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved)
|
||||
{
|
||||
m_thisDocument = thisDocument;
|
||||
m_snapshot = snapshot;
|
||||
@@ -67,6 +68,7 @@ void TypeOfExpression::init(Document::Ptr thisDocument, const Snapshot &snapshot
|
||||
m_lookupContext = LookupContext();
|
||||
m_bindings = bindings;
|
||||
m_environment.clear();
|
||||
m_autoDeclarationsBeingResolved = autoDeclarationsBeingResolved;
|
||||
}
|
||||
|
||||
QList<LookupItem> TypeOfExpression::operator()(const QByteArray &utf8code,
|
||||
@@ -111,7 +113,7 @@ QList<LookupItem> TypeOfExpression::operator()(ExpressionAST *expression,
|
||||
m_lookupContext.setBindings(m_bindings);
|
||||
m_lookupContext.setExpandTemplates(m_expandTemplates);
|
||||
|
||||
ResolveExpression resolve(m_lookupContext);
|
||||
ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved);
|
||||
const QList<LookupItem> items = resolve(m_ast, scope);
|
||||
|
||||
if (! m_bindings)
|
||||
@@ -133,7 +135,7 @@ QList<LookupItem> TypeOfExpression::reference(ExpressionAST *expression,
|
||||
m_lookupContext.setBindings(m_bindings);
|
||||
m_lookupContext.setExpandTemplates(m_expandTemplates);
|
||||
|
||||
ResolveExpression resolve(m_lookupContext);
|
||||
ResolveExpression resolve(m_lookupContext, m_autoDeclarationsBeingResolved);
|
||||
const QList<LookupItem> items = resolve.reference(m_ast, scope);
|
||||
|
||||
if (! m_bindings)
|
||||
|
@@ -58,8 +58,11 @@ public:
|
||||
* Also clears the lookup context, so can be used to make sure references
|
||||
* to the documents previously used are removed.
|
||||
*/
|
||||
void init(Document::Ptr thisDocument, const Snapshot &snapshot,
|
||||
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>());
|
||||
void init(Document::Ptr thisDocument,
|
||||
const Snapshot &snapshot,
|
||||
QSharedPointer<CreateBindings> bindings = QSharedPointer<CreateBindings>(),
|
||||
const QSet<const Declaration *> &autoDeclarationsBeingResolved
|
||||
= QSet<const Declaration *>());
|
||||
|
||||
void reset();
|
||||
|
||||
@@ -151,6 +154,8 @@ private:
|
||||
// Keep the expression documents and thus all the symbols and
|
||||
// their types alive until they are not needed any more.
|
||||
QList<Document::Ptr> m_documents;
|
||||
|
||||
QSet<const Declaration *> m_autoDeclarationsBeingResolved;
|
||||
};
|
||||
|
||||
ExpressionAST CPLUSPLUS_EXPORT *extractExpressionAST(Document::Ptr doc);
|
||||
|
@@ -1832,3 +1832,56 @@ void CppToolsPlugin::test_completion_crash_cloning_template_class_QTCREATORBUG93
|
||||
QVERIFY(completions.contains(QLatin1String("Templ")));
|
||||
QVERIFY(completions.contains(QLatin1String("f")));
|
||||
}
|
||||
|
||||
void CppToolsPlugin::test_completion_recursive_auto_declarations1_QTCREATORBUG9503()
|
||||
{
|
||||
TestData data;
|
||||
data.srcText =
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" auto object2 = object1;\n"
|
||||
" auto object1 = object2;\n"
|
||||
" @;\n"
|
||||
" // padding so we get the scope right\n"
|
||||
"}\n"
|
||||
;
|
||||
setup(&data);
|
||||
|
||||
Utils::ChangeSet change;
|
||||
QString txt = QLatin1String("object1.");
|
||||
change.insert(data.pos, txt);
|
||||
QTextCursor cursor(data.doc);
|
||||
change.apply(&cursor);
|
||||
data.pos += txt.length();
|
||||
|
||||
QStringList completions = getCompletions(data);
|
||||
|
||||
QCOMPARE(completions.size(), 0);
|
||||
}
|
||||
|
||||
void CppToolsPlugin::test_completion_recursive_auto_declarations2_QTCREATORBUG9503()
|
||||
{
|
||||
TestData data;
|
||||
data.srcText =
|
||||
"void f()\n"
|
||||
"{\n"
|
||||
" auto object3 = object1;\n"
|
||||
" auto object2 = object3;\n"
|
||||
" auto object1 = object2;\n"
|
||||
" @;\n"
|
||||
" // padding so we get the scope right\n"
|
||||
"}\n"
|
||||
;
|
||||
setup(&data);
|
||||
|
||||
Utils::ChangeSet change;
|
||||
QString txt = QLatin1String("object1.");
|
||||
change.insert(data.pos, txt);
|
||||
QTextCursor cursor(data.doc);
|
||||
change.apply(&cursor);
|
||||
data.pos += txt.length();
|
||||
|
||||
QStringList completions = getCompletions(data);
|
||||
|
||||
QCOMPARE(completions.size(), 0);
|
||||
}
|
||||
|
@@ -128,6 +128,8 @@ private slots:
|
||||
void test_completion_typedef_using_templates2();
|
||||
void test_completion_namespace_alias_with_many_namespace_declarations();
|
||||
void test_completion_crash_cloning_template_class_QTCREATORBUG9329();
|
||||
void test_completion_recursive_auto_declarations1_QTCREATORBUG9503();
|
||||
void test_completion_recursive_auto_declarations2_QTCREATORBUG9503();
|
||||
|
||||
void test_format_pointerdeclaration_in_simpledeclarations();
|
||||
void test_format_pointerdeclaration_in_simpledeclarations_data();
|
||||
|
Reference in New Issue
Block a user