From aa78a1fc5df11cfd0c32847b97160bf6640932b6 Mon Sep 17 00:00:00 2001
From: Erik Verbruggen <erik.verbruggen@nokia.com>
Date: Fri, 26 Mar 2010 13:53:46 +0100
Subject: [PATCH] Fixed ObjectLengthCalculator to handle incorrect QML.

Task-number: QTCREATORBUG-961
---
 .../filemanager/objectlengthcalculator.cpp    | 21 ++++++++++-------
 .../core/filemanager/objectlengthcalculator.h |  4 ++--
 .../qmldesigner/core/model/rewriterview.cpp   | 23 +++++++++++++++----
 .../core/model/texttomodelmerger.cpp          | 11 +++++----
 4 files changed, 40 insertions(+), 19 deletions(-)

diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp
index f748788aad1..cbd8fd9e248 100644
--- a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp
+++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp
@@ -35,23 +35,28 @@ using namespace QmlJS;
 using namespace QmlDesigner;
 using namespace QmlJS::AST;
 
-ObjectLengthCalculator::ObjectLengthCalculator(const QString &text):
+ObjectLengthCalculator::ObjectLengthCalculator():
         m_doc(Document::create("<internal>"))
 {
-    m_doc->setSource(text);
-    bool ok = m_doc->parseQml();
-
-    Q_ASSERT(ok);
 }
 
-quint32 ObjectLengthCalculator::operator()(quint32 offset)
+bool ObjectLengthCalculator::operator()(const QString &text, quint32 offset,
+                                        quint32 &length)
 {
     m_offset = offset;
     m_length = 0;
+    m_doc->setSource(text);
 
-    Node::accept(m_doc->qmlProgram(), this);
+    if (!m_doc->parseQml())
+        return false;
 
-    return m_length;
+    Node::accept(m_doc->qmlProgram(), this);
+    if (m_length) {
+        length = m_length;
+        return true;
+    } else {
+        return false;
+    }
 }
 
 bool ObjectLengthCalculator::visit(QmlJS::AST::UiObjectBinding *ast)
diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h
index 957336805be..c28d75ced33 100644
--- a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h
+++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h
@@ -38,9 +38,9 @@ namespace QmlDesigner {
 class ObjectLengthCalculator: protected QmlJS::AST::Visitor
 {
 public:
-    ObjectLengthCalculator(const QString &text);
+    ObjectLengthCalculator();
 
-    quint32 operator()(quint32 offset);
+    bool operator()(const QString &text, quint32 offset, quint32 &length);
 
 protected:
     using QmlJS::AST::Visitor::visit;
diff --git a/src/plugins/qmldesigner/core/model/rewriterview.cpp b/src/plugins/qmldesigner/core/model/rewriterview.cpp
index 9fa5b1e46c3..fc4f608af58 100644
--- a/src/plugins/qmldesigner/core/model/rewriterview.cpp
+++ b/src/plugins/qmldesigner/core/model/rewriterview.cpp
@@ -477,10 +477,18 @@ int RewriterView::nodeOffset(const ModelNode &node) const
     return m_positionStorage->nodeOffset(node);
 }
 
+/**
+ * \return the length of the node's text, or -1 if it wasn't found or if an error
+ *         occurred.
+ */
 int RewriterView::nodeLength(const ModelNode &node) const
 {
-    ObjectLengthCalculator objectLengthCalculator(m_textModifier->text());
-    return objectLengthCalculator(nodeOffset(node));
+    ObjectLengthCalculator objectLengthCalculator;
+    unsigned length;
+    if (objectLengthCalculator(m_textModifier->text(), nodeOffset(node), length))
+        return (int) length;
+    else
+        return -1;
 }
 
 int RewriterView::firstDefinitionInsideOffset(const ModelNode &node) const
@@ -492,9 +500,14 @@ int RewriterView::firstDefinitionInsideOffset(const ModelNode &node) const
 int RewriterView::firstDefinitionInsideLength(const ModelNode &node) const
 {
     FirstDefinitionFinder firstDefinitionFinder(m_textModifier->text());
-    int offset =  firstDefinitionFinder(nodeOffset(node));
-    ObjectLengthCalculator objectLengthCalculator(m_textModifier->text());
-    return objectLengthCalculator(offset);
+    const int offset =  firstDefinitionFinder(nodeOffset(node));
+
+    ObjectLengthCalculator objectLengthCalculator;
+    unsigned length;
+    if (objectLengthCalculator(m_textModifier->text(), offset, length))
+        return length;
+    else
+        return -1;
 }
 
 bool RewriterView::modificationGroupActive()
diff --git a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp
index 11bbaed7115..7439cbf97ba 100644
--- a/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp
+++ b/src/plugins/qmldesigner/core/model/texttomodelmerger.cpp
@@ -952,10 +952,13 @@ void TextToModelMerger::setupComponent(const ModelNode &node)
     if (componentText.contains("Component")) { //explicit component
         FirstDefinitionFinder firstDefinitionFinder(componentText);
         int offset = firstDefinitionFinder(0);
-        ObjectLengthCalculator objectLengthCalculator(componentText);
-        int length = objectLengthCalculator(offset);
-        for (int i = offset;i<offset + length;i++)
-            result.append(componentText.at(i));
+        ObjectLengthCalculator objectLengthCalculator;
+        unsigned length;
+        if (objectLengthCalculator(componentText, offset, length)) {
+            result = componentText.mid(offset, length);
+        } else {
+            result = componentText;
+        }
     } else {
         result = componentText; //implicit component
     }
-- 
GitLab