branch: elpa/rust-mode
commit 53c558cf7241cbeca93f18e04a81a25ef8675313
Author: Micah Chalmer <[email protected]>
Commit: Micah Chalmer <[email protected]>

    Factor out rust-conditional-re-search-forward
    
    Factor out the method of looking for a match for a regexp, but filtering
    out some of the matches with a filtering function.  This will be used
    again for angle bracket filtering.
    
    This also fixes an issue with raw string handling.
---
 rust-mode-tests.el | 23 +++++++++++++++++++++++
 rust-mode.el       | 53 ++++++++++++++++++++++++++++++++++++-----------------
 2 files changed, 59 insertions(+), 17 deletions(-)

diff --git a/rust-mode-tests.el b/rust-mode-tests.el
index 58fcaaf..c7446d6 100644
--- a/rust-mode-tests.el
+++ b/rust-mode-tests.el
@@ -362,6 +362,29 @@ use foo::bar::baz;
 fn foo() { }
 "))
 
+(ert-deftest font-lock-multi-raw-strings-in-a-row ()
+  (rust-test-font-lock
+   "
+r\"foo\\\", \"bar\", r\"bar\";
+r\"foo\\.\", \"bar\", r\"bar\";
+r\"foo\\..\", \"bar\", r\"foo\\..\\bar\";
+r\"\\\", \"foo\", r\"\\foo\";
+not_a_string();
+
+"
+
+   (apply 'append (mapcar (lambda (s) (list s 'font-lock-string-face))
+                          '("r\"foo\\\"" "\"bar\"" "r\"bar\""
+                            "r\"foo\\.\"" "\"bar\"" "r\"bar\""
+                            "r\"foo\\..\"" "\"bar\"" "r\"foo\\..\\bar\""
+                            "r\"\\\"" "\"foo\"" "r\"\\foo\"")))
+   ))
+
+(ert-deftest font-lock-raw-string-after-normal-string-ending-in-r ()
+  (rust-test-font-lock
+   "\"bar\" r\"foo\""
+   '("\"bar\"" font-lock-string-face "r\"foo\"" font-lock-string-face)))
+
 (ert-deftest indent-params-no-align ()
   (test-indent
    "
diff --git a/rust-mode.el b/rust-mode.el
index 7fcc09e..ae42052 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -411,6 +411,32 @@
         (/= font-lock-end orig-end))
     ))
 
+(defun rust-conditional-re-search-forward (regexp bound condition)
+  ;; Search forward for regexp (with bound).  If found, call condition and 
return the found
+  ;; match only if it returns true.
+  (let* (found
+         found-ret-list
+         (ret-list (save-excursion
+                     (while (and (not found) (re-search-forward regexp bound 
t))
+                       (setq
+                        found-ret-list (list (point) (match-data))
+                        found (save-match-data (save-excursion (ignore-errors 
(funcall condition)))))
+                       ;; If the condition filters out a match, need to search
+                       ;; again just after its beginning.  This will allow
+                       ;; cases such as:
+                       ;;    "bar" r"foo"
+                       ;; where the filtered out search (r" r") should not
+                       ;; prevent finding another one that begins in the middle
+                       ;; of it (r"foo")
+                       (when (not found)
+                         (goto-char (1+ (match-beginning 0))))
+                       )
+                     (when found found-ret-list))))
+    (when ret-list
+      (goto-char (nth 0 ret-list))
+      (set-match-data (nth 1 ret-list))
+      (nth 0 ret-list))))
+
 (defun rust-look-for-raw-string (bound)
   ;; Find a raw string, but only if it's not in the middle of another string or
   ;; a comment
@@ -450,23 +476,16 @@
 
              ;; No "#"s - capture the ending quote (using a backref to group 3,
              ;; so that we can't match a quote if we had "#"s) as group 6
-             (group (backref 3))))))
-         ;; If it matches, it ends up with the starting character of the string
-         ;; as group 1, any ending backslashes as group 4, and the ending
-         ;; character as either group 5 or group 6.
-
-         (ret-list (save-excursion
-                    (let* ((match-end (re-search-forward raw-str-regexp bound 
t))
-                           (ret-list (and match-end (list match-end 
(match-beginning 0) (match-data) (point)))))
-                      (when (and ret-list
-                                 (save-excursion
-                                   (goto-char (nth 1 ret-list))
-                                   (not (rust-in-str-or-cmnt))))
-                        ret-list)))))
-    (when ret-list
-      (goto-char (nth 3 ret-list))
-      (set-match-data (nth 2 ret-list))
-      (nth 0 ret-list))))
+             (group (backref 3))))
+           ;; If it matches, it ends up with the starting character of the 
string
+           ;; as group 1, any ending backslashes as group 4, and the ending
+           ;; character as either group 5 or group 6.
+           )))
+    (rust-conditional-re-search-forward
+     raw-str-regexp bound
+     (lambda () (save-excursion
+                  (goto-char (match-beginning 0))
+                  (not (rust-in-str-or-cmnt)))))))
 
 (defvar rust-mode-font-lock-syntactic-keywords
   (append

Reply via email to