summaryrefslogtreecommitdiff
path: root/src/libs
diff options
context:
space:
mode:
authorChristian Kamm <christian.d.kamm@nokia.com>2011-10-25 10:23:01 +0200
committerChristian Kamm <christian.d.kamm@nokia.com>2011-10-31 09:37:46 +0100
commit4521be25cd6888f9412c0a6350171dd0383ede0a (patch)
tree3a22b5ca0d92ecad84aa635d44a33bcb65c7f616 /src/libs
parenta9553c494ef6012cc4c34bd469ff0f20ee2e2671 (diff)
downloadqt-creator-4521be25cd6888f9412c0a6350171dd0383ede0a.tar.gz
QmlJS: Avoid an infinite loop if a qmltypes file has a cycle.
The qmltypes files shipped with libraries shouldn't, but could define components that form a prototype cycle. Use of the new QmlObjectValue::prototypes() function avoids the code model getting stuck in an infinite loop for these cases. For plain ObjectValues this is already solved by using PrototypeIterator. Change-Id: I0f562672ab99b454bc3a0121c7a1b9eca43476bb Reviewed-by: Fawzi Mohamed <fawzi.mohamed@nokia.com>
Diffstat (limited to 'src/libs')
-rw-r--r--src/libs/qmljs/qmljsinterpreter.cpp32
-rw-r--r--src/libs/qmljs/qmljsinterpreter.h1
2 files changed, 25 insertions, 8 deletions
diff --git a/src/libs/qmljs/qmljsinterpreter.cpp b/src/libs/qmljs/qmljsinterpreter.cpp
index 581f240b0b..529b66e3a2 100644
--- a/src/libs/qmljs/qmljsinterpreter.cpp
+++ b/src/libs/qmljs/qmljsinterpreter.cpp
@@ -338,6 +338,22 @@ const QmlObjectValue *QmlObjectValue::prototype() const
return static_cast<const QmlObjectValue *>(_prototype);
}
+/*!
+ \returns a list started by this object and followed by all its prototypes
+
+ Prefer to use this over calling prototype() in a loop, as it avoids cycles.
+*/
+QList<const QmlObjectValue *> QmlObjectValue::prototypes() const
+{
+ QList<const QmlObjectValue *> protos;
+ for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ if (protos.contains(it))
+ break;
+ protos += it;
+ }
+ return protos;
+}
+
const QmlObjectValue *QmlObjectValue::attachedType() const
{
return _attachedType;
@@ -367,7 +383,7 @@ QString QmlObjectValue::defaultPropertyName() const
QString QmlObjectValue::propertyType(const QString &propertyName) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
@@ -379,7 +395,7 @@ QString QmlObjectValue::propertyType(const QString &propertyName) const
bool QmlObjectValue::isListProperty(const QString &propertyName) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
@@ -391,7 +407,7 @@ bool QmlObjectValue::isListProperty(const QString &propertyName) const
FakeMetaEnum QmlObjectValue::getEnum(const QString &typeName, const QmlObjectValue **foundInScope) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
const int index = iter->enumeratorIndex(typeName);
if (index != -1) {
@@ -407,7 +423,7 @@ FakeMetaEnum QmlObjectValue::getEnum(const QString &typeName, const QmlObjectVal
const QmlEnumValue *QmlObjectValue::getEnumValue(const QString &typeName, const QmlObjectValue **foundInScope) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
if (const QmlEnumValue *e = it->_enums.value(typeName)) {
if (foundInScope)
*foundInScope = it;
@@ -421,7 +437,7 @@ const QmlEnumValue *QmlObjectValue::getEnumValue(const QString &typeName, const
bool QmlObjectValue::isWritable(const QString &propertyName) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
@@ -433,7 +449,7 @@ bool QmlObjectValue::isWritable(const QString &propertyName) const
bool QmlObjectValue::isPointer(const QString &propertyName) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
@@ -453,7 +469,7 @@ bool QmlObjectValue::hasLocalProperty(const QString &typeName) const
bool QmlObjectValue::hasProperty(const QString &propertyName) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
int propIdx = iter->propertyIndex(propertyName);
if (propIdx != -1) {
@@ -465,7 +481,7 @@ bool QmlObjectValue::hasProperty(const QString &propertyName) const
bool QmlObjectValue::isDerivedFrom(FakeMetaObject::ConstPtr base) const
{
- for (const QmlObjectValue *it = this; it; it = it->prototype()) {
+ foreach (const QmlObjectValue *it, prototypes()) {
FakeMetaObject::ConstPtr iter = it->_metaObject;
if (iter == base)
return true;
diff --git a/src/libs/qmljs/qmljsinterpreter.h b/src/libs/qmljs/qmljsinterpreter.h
index 8f9ec41da6..aa484598f0 100644
--- a/src/libs/qmljs/qmljsinterpreter.h
+++ b/src/libs/qmljs/qmljsinterpreter.h
@@ -428,6 +428,7 @@ public:
using ObjectValue::prototype;
const QmlObjectValue *prototype() const;
+ QList<const QmlObjectValue *> prototypes() const;
const QmlObjectValue *attachedType() const;
void setAttachedType(QmlObjectValue *value);