forked from qt-creator/qt-creator
QmlJS: Fix reference lookup cycles.
Since several reference lookups involve Evaluate which may cause further reference lookups, we need to be able to pass the existing ReferenceContext to avoid cycles. Change-Id: I2f1eeaad4d6b6ff094413d51077b03c985f6fab4 Reviewed-on: http://codereview.qt-project.org/4653 Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
This commit is contained in:
@@ -39,9 +39,10 @@
|
|||||||
|
|
||||||
using namespace QmlJS;
|
using namespace QmlJS;
|
||||||
|
|
||||||
Evaluate::Evaluate(const ScopeChain *scopeChain)
|
Evaluate::Evaluate(const ScopeChain *scopeChain, ReferenceContext *referenceContext)
|
||||||
: _valueOwner(scopeChain->context()->valueOwner()),
|
: _valueOwner(scopeChain->context()->valueOwner()),
|
||||||
_context(scopeChain->context()),
|
_context(scopeChain->context()),
|
||||||
|
_referenceContext(referenceContext),
|
||||||
_scopeChain(scopeChain),
|
_scopeChain(scopeChain),
|
||||||
_scope(_valueOwner->globalObject()),
|
_scope(_valueOwner->globalObject()),
|
||||||
_result(0)
|
_result(0)
|
||||||
@@ -61,8 +62,12 @@ const Value *Evaluate::value(AST::Node *ast)
|
|||||||
{
|
{
|
||||||
const Value *result = reference(ast);
|
const Value *result = reference(ast);
|
||||||
|
|
||||||
if (const Reference *ref = value_cast<const Reference *>(result))
|
if (const Reference *ref = value_cast<const Reference *>(result)) {
|
||||||
result = _context->lookupReference(ref);
|
if (_referenceContext)
|
||||||
|
result = _referenceContext->lookupReference(ref);
|
||||||
|
else
|
||||||
|
result = _context->lookupReference(ref);
|
||||||
|
}
|
||||||
|
|
||||||
if (! result)
|
if (! result)
|
||||||
result = _valueOwner->undefinedValue();
|
result = _valueOwner->undefinedValue();
|
||||||
|
@@ -48,7 +48,7 @@ class FunctionValue;
|
|||||||
class QMLJS_EXPORT Evaluate: protected AST::Visitor
|
class QMLJS_EXPORT Evaluate: protected AST::Visitor
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
Evaluate(const ScopeChain *scopeChain);
|
Evaluate(const ScopeChain *scopeChain, ReferenceContext *referenceContext = 0);
|
||||||
virtual ~Evaluate();
|
virtual ~Evaluate();
|
||||||
|
|
||||||
// same as value()
|
// same as value()
|
||||||
@@ -164,6 +164,7 @@ private:
|
|||||||
QmlJS::Document::Ptr _doc;
|
QmlJS::Document::Ptr _doc;
|
||||||
ValueOwner *_valueOwner;
|
ValueOwner *_valueOwner;
|
||||||
ContextPtr _context;
|
ContextPtr _context;
|
||||||
|
ReferenceContext *_referenceContext;
|
||||||
const ScopeChain *_scopeChain;
|
const ScopeChain *_scopeChain;
|
||||||
const ObjectValue *_scope;
|
const ObjectValue *_scope;
|
||||||
const Value *_result;
|
const Value *_result;
|
||||||
|
@@ -727,7 +727,7 @@ void Reference::accept(ValueVisitor *visitor) const
|
|||||||
visitor->visit(this);
|
visitor->visit(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *Reference::value(const ReferenceContext *) const
|
const Value *Reference::value(ReferenceContext *) const
|
||||||
{
|
{
|
||||||
return _valueOwner->undefinedValue();
|
return _valueOwner->undefinedValue();
|
||||||
}
|
}
|
||||||
@@ -1745,7 +1745,7 @@ ASTVariableReference::~ASTVariableReference()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *ASTVariableReference::value(const ReferenceContext *referenceContext) const
|
const Value *ASTVariableReference::value(ReferenceContext *referenceContext) const
|
||||||
{
|
{
|
||||||
if (!_ast->expression)
|
if (!_ast->expression)
|
||||||
return valueOwner()->undefinedValue();
|
return valueOwner()->undefinedValue();
|
||||||
@@ -1755,7 +1755,7 @@ const Value *ASTVariableReference::value(const ReferenceContext *referenceContex
|
|||||||
ScopeBuilder builder(&scopeChain);
|
ScopeBuilder builder(&scopeChain);
|
||||||
builder.push(ScopeAstPath(doc)(_ast->expression->firstSourceLocation().begin()));
|
builder.push(ScopeAstPath(doc)(_ast->expression->firstSourceLocation().begin()));
|
||||||
|
|
||||||
Evaluate evaluator(&scopeChain);
|
Evaluate evaluator(&scopeChain, referenceContext);
|
||||||
return evaluator(_ast->expression);
|
return evaluator(_ast->expression);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1832,7 +1832,7 @@ UiQualifiedId *QmlPrototypeReference::qmlTypeName() const
|
|||||||
return _qmlTypeName;
|
return _qmlTypeName;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *QmlPrototypeReference::value(const ReferenceContext *referenceContext) const
|
const Value *QmlPrototypeReference::value(ReferenceContext *referenceContext) const
|
||||||
{
|
{
|
||||||
return referenceContext->context()->lookupType(_doc, _qmlTypeName);
|
return referenceContext->context()->lookupType(_doc, _qmlTypeName);
|
||||||
}
|
}
|
||||||
@@ -1859,7 +1859,7 @@ bool ASTPropertyReference::getSourceLocation(QString *fileName, int *line, int *
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *ASTPropertyReference::value(const ReferenceContext *referenceContext) const
|
const Value *ASTPropertyReference::value(ReferenceContext *referenceContext) const
|
||||||
{
|
{
|
||||||
if (_ast->statement
|
if (_ast->statement
|
||||||
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant")
|
&& (!_ast->memberType || _ast->memberType->asString() == QLatin1String("variant")
|
||||||
@@ -1875,7 +1875,7 @@ const Value *ASTPropertyReference::value(const ReferenceContext *referenceContex
|
|||||||
int offset = _ast->statement->firstSourceLocation().begin();
|
int offset = _ast->statement->firstSourceLocation().begin();
|
||||||
builder.push(ScopeAstPath(doc)(offset));
|
builder.push(ScopeAstPath(doc)(offset));
|
||||||
|
|
||||||
Evaluate evaluator(&scopeChain);
|
Evaluate evaluator(&scopeChain, referenceContext);
|
||||||
return evaluator(_ast->statement);
|
return evaluator(_ast->statement);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1906,7 +1906,7 @@ bool ASTSignalReference::getSourceLocation(QString *fileName, int *line, int *co
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Value *ASTSignalReference::value(const ReferenceContext *) const
|
const Value *ASTSignalReference::value(ReferenceContext *) const
|
||||||
{
|
{
|
||||||
return valueOwner()->undefinedValue();
|
return valueOwner()->undefinedValue();
|
||||||
}
|
}
|
||||||
|
@@ -296,7 +296,7 @@ public:
|
|||||||
virtual void accept(ValueVisitor *) const;
|
virtual void accept(ValueVisitor *) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const Value *value(const ReferenceContext *referenceContext) const;
|
virtual const Value *value(ReferenceContext *referenceContext) const;
|
||||||
|
|
||||||
ValueOwner *_valueOwner;
|
ValueOwner *_valueOwner;
|
||||||
friend class ReferenceContext;
|
friend class ReferenceContext;
|
||||||
@@ -699,7 +699,7 @@ public:
|
|||||||
AST::UiQualifiedId *qmlTypeName() const;
|
AST::UiQualifiedId *qmlTypeName() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const Value *value(const ReferenceContext *referenceContext) const;
|
virtual const Value *value(ReferenceContext *referenceContext) const;
|
||||||
|
|
||||||
AST::UiQualifiedId *_qmlTypeName;
|
AST::UiQualifiedId *_qmlTypeName;
|
||||||
const Document *_doc;
|
const Document *_doc;
|
||||||
@@ -715,7 +715,7 @@ public:
|
|||||||
virtual ~ASTVariableReference();
|
virtual ~ASTVariableReference();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const Value *value(const ReferenceContext *referenceContext) const;
|
virtual const Value *value(ReferenceContext *referenceContext) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
|
class QMLJS_EXPORT ASTFunctionValue: public FunctionValue
|
||||||
@@ -755,7 +755,7 @@ public:
|
|||||||
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const Value *value(const ReferenceContext *referenceContext) const;
|
virtual const Value *value(ReferenceContext *referenceContext) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMLJS_EXPORT ASTSignalReference: public Reference
|
class QMLJS_EXPORT ASTSignalReference: public Reference
|
||||||
@@ -774,7 +774,7 @@ public:
|
|||||||
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
virtual bool getSourceLocation(QString *fileName, int *line, int *column) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
virtual const Value *value(const ReferenceContext *referenceContext) const;
|
virtual const Value *value(ReferenceContext *referenceContext) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QMLJS_EXPORT ASTObjectValue: public ObjectValue
|
class QMLJS_EXPORT ASTObjectValue: public ObjectValue
|
||||||
|
Reference in New Issue
Block a user