From eaecfb7e06cc4bae383f79194f2619c46507c1bb Mon Sep 17 00:00:00 2001
From: Roberto Raggi <roberto.raggi@nokia.com>
Date: Wed, 13 Jan 2010 13:51:01 +0100
Subject: [PATCH] Fixed auto-quote completion at the end of unfinished string
 literals.

---
 src/plugins/qmleditor/qmleditor.cpp           | 34 ++++++++++++++-----
 src/plugins/qtscripteditor/qtscripteditor.cpp | 34 ++++++++++++++-----
 2 files changed, 52 insertions(+), 16 deletions(-)

diff --git a/src/plugins/qmleditor/qmleditor.cpp b/src/plugins/qmleditor/qmleditor.cpp
index a83f18423a7..8598e36d2f8 100644
--- a/src/plugins/qmleditor/qmleditor.cpp
+++ b/src/plugins/qmleditor/qmleditor.cpp
@@ -691,6 +691,19 @@ void QmlTextEditor::unCommentSelection()
     Utils::unCommentSelection(this);
 }
 
+static bool isCompleteStringLiteral(const QStringRef &text)
+{
+    if (text.length() < 2)
+        return false;
+
+    const QChar quote = text.at(0);
+
+    if (text.at(text.length() - 1) == quote)
+        return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
+
+    return false;
+}
+
 bool QmlTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const
 {
     QChar ch;
@@ -727,18 +740,21 @@ bool QmlTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, cons
     const QList<QScriptIncrementalScanner::Token> tokens = tokenize(blockText, blockState);
     const int pos = cursor.columnNumber();
 
-    int tokenIndex = tokens.size() - 1;
-    for (; tokenIndex != -1; --tokenIndex) {
+    int tokenIndex = 0;
+    for (; tokenIndex < tokens.size(); ++tokenIndex) {
         const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
+
         if (pos >= token.begin()) {
             if (pos < token.end())
                 break;
-            else if (pos == token.end() && token.is(QScriptIncrementalScanner::Token::Comment))
+
+            else if (pos == token.end() && (token.is(QScriptIncrementalScanner::Token::Comment) ||
+                                            token.is(QScriptIncrementalScanner::Token::String)))
                 break;
         }
     }
 
-    if (tokenIndex != -1) {
+    if (tokenIndex != tokens.size()) {
         const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
 
         switch (token.kind) {
@@ -746,10 +762,12 @@ bool QmlTextEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, cons
             return false;
 
         case QScriptIncrementalScanner::Token::String: {
-            if (ch == blockText.at(token.begin())) {
-                if (token.end() - 1 == pos && blockText.at(token.end() - 2) != QLatin1Char('\\'))
-                    break;
-            }
+            const QStringRef tokenText = blockText.midRef(token.offset, token.length);
+            const QChar quote = tokenText.at(0);
+
+            if (ch == quote && isCompleteStringLiteral(tokenText))
+                break;
+
             return false;
         }
 
diff --git a/src/plugins/qtscripteditor/qtscripteditor.cpp b/src/plugins/qtscripteditor/qtscripteditor.cpp
index 670c5c747e8..a5fe7ecceee 100644
--- a/src/plugins/qtscripteditor/qtscripteditor.cpp
+++ b/src/plugins/qtscripteditor/qtscripteditor.cpp
@@ -402,6 +402,19 @@ void ScriptEditor::unCommentSelection()
     Utils::unCommentSelection(this);
 }
 
+static bool isCompleteStringLiteral(const QStringRef &text)
+{
+    if (text.length() < 2)
+        return false;
+
+    const QChar quote = text.at(0);
+
+    if (text.at(text.length() - 1) == quote)
+        return text.at(text.length() - 2) != QLatin1Char('\\'); // ### not exactly.
+
+    return false;
+}
+
 bool ScriptEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const QString &textToInsert) const
 {
     QChar ch;
@@ -442,18 +455,21 @@ bool ScriptEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const
     const QList<QScriptIncrementalScanner::Token> tokens = tokenize(blockText, blockState);
     const int pos = cursor.columnNumber();
 
-    int tokenIndex = tokens.size() - 1;
-    for (; tokenIndex != -1; --tokenIndex) {
+    int tokenIndex = 0;
+    for (; tokenIndex < tokens.size(); ++tokenIndex) {
         const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
+
         if (pos >= token.begin()) {
             if (pos < token.end())
                 break;
-            else if (pos == token.end() && token.is(QScriptIncrementalScanner::Token::Comment))
+
+            else if (pos == token.end() && (token.is(QScriptIncrementalScanner::Token::Comment) ||
+                                            token.is(QScriptIncrementalScanner::Token::String)))
                 break;
         }
     }
 
-    if (tokenIndex != -1) {
+    if (tokenIndex != tokens.size()) {
         const QScriptIncrementalScanner::Token &token = tokens.at(tokenIndex);
 
         switch (token.kind) {
@@ -461,10 +477,12 @@ bool ScriptEditor::contextAllowsAutoParentheses(const QTextCursor &cursor, const
             return false;
 
         case QScriptIncrementalScanner::Token::String: {
-            if (ch == blockText.at(token.begin())) {
-                if (token.end() - 1 == pos && blockText.at(token.end() - 2) != QLatin1Char('\\'))
-                    break;
-            }
+            const QStringRef tokenText = blockText.midRef(token.offset, token.length);
+            const QChar quote = tokenText.at(0);
+
+            if (ch == quote && isCompleteStringLiteral(tokenText))
+                break;
+
             return false;
         }
 
-- 
GitLab