Repository: rust-lang/rust-mode (language: rust)

Issue:
(right-word) gets confused on strings that end with "r"
Is anyone else seeing this? Put the following string into a buffer, put point on the left column (on the "f") and then use right-word (aka C-right) to jump to the end of each string:

```
foo("error", "erroq");
```

On my system, in rust-mode, it stops on the open-parenthesis, on the last "r" in "error", and then on the closing quote after the "q". In any other mode the second stop is on the closing quote after "error", not on the final "r".

I'm guessing that the syntax table is a bit confused, and that it sees `r"` as the beginning of a raw string (rather than the end of a normal string).

I'm using FSF emacs-25.3.1 on OS-X (hand compiled, not Homebrew), and the ELPA packaged version of rust-mode, whose `rust-mode.el` matches the contents of this repo as of the latest commit to master (07e16c6364bf0362f76c6aa46604453dec3ac640, from 22-mar-2018).

thanks!



Discussion / hints:

Fix patch:
diff --git a/rust-mode.el b/rust-mode.el
index 4ded41af..d8092ab2 100644
--- a/rust-mode.el
+++ b/rust-mode.el
@@ -1105,41 +1105,44 @@ should be considered a paired angle bracket."
 	 (group "'")))
     "A regular expression matching a character literal."))
 
-(defun rust--syntax-propertize-raw-string (end)
+(defun rust--syntax-propertize-raw-string (str-start end)
   "A helper for rust-syntax-propertize.
 
-If point is already in a raw string, this will apply the
-appropriate string syntax to the character up to the end of the
-raw string, or to END, whichever comes first."
-  (let ((str-start (nth 8 (syntax-ppss))))
-    (when str-start
-      (when (save-excursion
-	      (goto-char str-start)
-	      (looking-at "r\\(#*\\)\\(\"\\)"))
-	;; In a raw string, so try to find the end.
-	(let ((hashes (match-string 1)))
-	  ;; Match \ characters at the end of the string to suppress
-	  ;; their normal character-quote syntax.
-	  (when (re-search-forward (concat "\\(\\\\*\\)\\(\"" hashes "\\)") end t)
-	    (put-text-property (match-beginning 1) (match-end 1)
-			       'syntax-table (string-to-syntax "_"))
-	    (put-text-property (1- (match-end 2)) (match-end 2)
-			       'syntax-table (string-to-syntax "|"))
-	    (goto-char (match-end 0))))))))
+This will apply the appropriate string syntax to the character
+from the STR-START up to the end of the raw string, or to END,
+whichever comes first."
+  (when (save-excursion
+	  (goto-char str-start)
+	  (looking-at "r\\(#*\\)\\(\"\\)"))
+    ;; In a raw string, so try to find the end.
+    (let ((hashes (match-string 1)))
+      ;; Match \ characters at the end of the string to suppress
+      ;; their normal character-quote syntax.
+      (when (re-search-forward (concat "\\(\\\\*\\)\\(\"" hashes "\\)") end t)
+	(put-text-property (match-beginning 1) (match-end 1)
+			   'syntax-table (string-to-syntax "_"))
+	(put-text-property (1- (match-end 2)) (match-end 2)
+			   'syntax-table (string-to-syntax "|"))
+	(goto-char (match-end 0))))))
 
 (defun rust-syntax-propertize (start end)
   "A `syntax-propertize-function' to apply properties from START to END."
   (goto-char start)
-  (rust--syntax-propertize-raw-string end)
+  (let ((str-start (rust-in-str-or-cmnt)))
+    (when str-start
+      (rust--syntax-propertize-raw-string str-start end)))
   (funcall
    (syntax-propertize-rules
     ;; Character literals.
     (rust--char-literal-rx (1 "\"") (2 "\""))
     ;; Raw strings.
     ("\\(r\\)#*\""
-     (1 (prog1 "|"
-	  (goto-char (match-end 0))
-	  (rust--syntax-propertize-raw-string end))))
+     (0 (ignore
+          (goto-char (match-end 0))
+          (unless (save-excursion (nth 8 (syntax-ppss (match-beginning 0))))
+            (put-text-property (match-beginning 1) (match-end 1)
+			       'syntax-table (string-to-syntax "|"))
+            (rust--syntax-propertize-raw-string (match-beginning 0) end)))))
     ("[<>]"
      (0 (ignore
 	 (when (save-match-data


Test patch:
diff --git a/rust-mode-tests.el b/rust-mode-tests.el
index 72a9e4e3..b21202a3 100644
--- a/rust-mode-tests.el
+++ b/rust-mode-tests.el
@@ -1452,6 +1452,19 @@ fn g() {
      "g" font-lock-function-name-face
      "\"xs\"" font-lock-string-face)))
 
+(ert-deftest font-lock-string-ending-with-r-word-boundary ()
+  (with-temp-buffer
+    (rust-mode)
+    (insert "const foo = \"foo bar\"")
+    (font-lock-fontify-buffer)
+    ;; right-word should move the point to the end of the words.
+    (goto-char 14)
+    (right-word)
+    (should (equal 17 (point)))
+    (right-word)
+    (should (equal 21 (point)))
+    ))
+
 (ert-deftest font-lock-raw-string-trick-ending-followed-by-string-with-quote ()
   (rust-test-font-lock
    "r\"With what looks like the start of a raw string at the end r#\";