Rust ts: fontify as type the possible suffix of number literals
authorChristophe Troestler <Christophe.Troestler@umons.ac.be>
Fri, 18 Oct 2024 21:50:06 +0000 (23:50 +0200)
committerEshel Yaron <me@eshelyaron.com>
Wed, 27 Nov 2024 19:52:49 +0000 (20:52 +0100)
* lisp/progmodes/rust-ts-mode.el
(rust-ts-mode--fontify-number-literal): Perform the improved
fontification of numbers.  (Bug#73877)
* test/lisp/progmodes/rust-ts-mode-tests.el:
* test/lisp/progmodes/rust-ts-mode-resources/font-lock.rs:
* test/lisp/progmodes/rust-ts-mode-resources/font-lock-number.rs:
Add tests for the new optional fontification of the possible type
suffix of numbers.

(cherry picked from commit 902696c3ae3ed046208c57de923362bb609da6df)

etc/NEWS
lisp/progmodes/rust-ts-mode.el
test/lisp/progmodes/rust-ts-mode-resources/font-lock-number.rs [new file with mode: 0644]
test/lisp/progmodes/rust-ts-mode-resources/font-lock.rs
test/lisp/progmodes/rust-ts-mode-tests.el

index e89133fec03c51f42936a733633d99b0be6bae8b..37964bbd178e87f474e2e51c50797dfe18d91533 100644 (file)
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -497,6 +497,13 @@ the built-in Web server.  Interactively, when invoked with a prefix
 argument, 'php-ts-mode-run-php-webserver' prompts for the config file as
 well as for other connection parameters.
 
+** Rust-ts mode
+
+---
+*** New user option 'rust-ts-mode-fontify-number-suffix-as-type'.
+Rust number literals may have an optional type suffix.  When this option
+is non-nil, this suffix is fontified using 'font-lock-type-face'.
+
 ** Ediff
 
 +++
index e52ea3b125a7fd2b36d8ea8b135e1c1570428972..7a421eb506bbe5c6b4975e9bf3ba0972897a483f 100644 (file)
@@ -62,6 +62,15 @@ to be checked as its standard input."
                  (repeat :tag "Custom command" string))
   :group 'rust)
 
+(defcustom rust-ts-mode-fontify-number-suffix-as-type nil
+  "If non-nil, suffixes of number literals are fontified as types.
+In Rust, number literals can possess an optional type suffix.  When this
+variable is non-nil, these suffixes are fontified using
+`font-lock-type-face' instead of `font-lock-number-face'."
+  :version "31.1"
+  :type 'boolean
+  :group 'rust)
+
 (defvar rust-ts-mode-prettify-symbols-alist
   '(("&&" . ?∧) ("||" . ?∨)
     ("<=" . ?≤)  (">=" . ?≥) ("!=" . ?≠)
@@ -116,6 +125,12 @@ to be checked as its standard input."
      ((parent-is "use_list") parent-bol rust-ts-mode-indent-offset)))
   "Tree-sitter indent rules for `rust-ts-mode'.")
 
+(defconst rust-ts-mode--number-types
+  (regexp-opt '("u8" "i8" "u16" "i16" "u32" "i32" "u64"
+                "i64" "u128" "i128" "usize" "isize" "f32" "f64"))
+  "Regexp matching type suffixes of number literals.
+See https://doc.rust-lang.org/reference/tokens.html#suffixes.")
+
 (defvar rust-ts-mode--builtin-macros
   '("concat_bytes" "concat_idents" "const_format_args"
     "format_args_nl" "log_syntax" "trace_macros" "assert" "assert_eq"
@@ -221,7 +236,8 @@ to be checked as its standard input."
 
    :language 'rust
    :feature 'number
-   '([(float_literal) (integer_literal)] @font-lock-number-face)
+   '([(float_literal) (integer_literal)]
+     @rust-ts-mode--fontify-number-literal)
 
    :language 'rust
    :feature 'operator
@@ -369,6 +385,25 @@ to be checked as its standard input."
              (treesit-node-start id) (treesit-node-end id)
              'font-lock-variable-name-face override start end)))))))
 
+(defun rust-ts-mode--fontify-number-literal (node override start stop &rest _)
+  "Fontify number literals, highlighting the optional type suffix.
+If `rust-ts-mode-fontify-number-suffix-as-type' is non-nil, use
+`font-lock-type-face' to highlight the suffix."
+  (let* ((beg (treesit-node-start node))
+         (end (treesit-node-end node)))
+    (save-excursion
+      (goto-char end)
+      (if (and rust-ts-mode-fontify-number-suffix-as-type
+               (looking-back rust-ts-mode--number-types beg))
+          (let* ((ty (match-beginning 0))
+                 (nb (if (eq (char-before ty) ?_) (1- ty) ty)))
+            (treesit-fontify-with-override
+             ty end 'font-lock-type-face override start stop)
+            (treesit-fontify-with-override
+             beg nb 'font-lock-number-face override start stop))
+          (treesit-fontify-with-override
+           beg end 'font-lock-number-face override start stop)))))
+
 (defun rust-ts-mode--defun-name (node)
   "Return the defun name of NODE.
 Return nil if there is no name or if NODE is not a defun node."
diff --git a/test/lisp/progmodes/rust-ts-mode-resources/font-lock-number.rs b/test/lisp/progmodes/rust-ts-mode-resources/font-lock-number.rs
new file mode 100644 (file)
index 0000000..ed5b222
--- /dev/null
@@ -0,0 +1,17 @@
+fn main() {
+    let x = 1usize;
+//          ^ font-lock-number-face
+//             ^ font-lock-type-face
+    let x = 1_usize;
+//          ^ font-lock-number-face
+//             ^ font-lock-type-face
+    let x = 1_f64;
+//          ^ font-lock-number-face
+//             ^ font-lock-type-face
+    let x = 1.0f64;
+//          ^ font-lock-number-face
+//              ^ font-lock-type-face
+    let x = 1.0_f64;
+//          ^ font-lock-number-face
+//              ^ font-lock-type-face
+}
index 377cda0e3b91b30ca5a8e8b49748943734d4e97b..1f549085e3f4e7b60264a7153ef3c75c7131b109 100644 (file)
@@ -23,3 +23,21 @@ macro_rules! unsafe_foo {
 //                                     ^ font-lock-operator-face
         }
     };
+
+fn main() {
+    let x = 1usize;
+//          ^ font-lock-number-face
+//             ^ font-lock-number-face
+    let x = 1_usize;
+//          ^ font-lock-number-face
+//             ^ font-lock-number-face
+    let x = 1_f64;
+//          ^ font-lock-number-face
+//             ^ font-lock-number-face
+    let x = 1.0f64;
+//          ^ font-lock-number-face
+//              ^ font-lock-number-face
+    let x = 1.0_f64;
+//            ^ font-lock-number-face
+//               ^ font-lock-number-face
+}
index f718a57fc9e78c0e8dea4bc887f29fa1a86568f5..3a710b3af3bb84ac4a4e92108a847c6a8851f7c3 100644 (file)
 (require 'ert-font-lock)
 (require 'ert-x)
 (require 'treesit)
+(require 'rust-ts-mode)
 
 (ert-deftest rust-ts-test-font-lock ()
   (skip-unless (treesit-ready-p 'rust))
-  (let ((treesit-font-lock-level 4))
-    (ert-font-lock-test-file (ert-resource-file "font-lock.rs") 'rust-ts-mode)))
+  (let ((treesit-font-lock-level 4)
+        (rust-ts-mode-fontify-number-suffix-as-type nil))
+    (ert-font-lock-test-file (ert-resource-file "font-lock.rs")
+                             'rust-ts-mode)))
+
+(ert-deftest rust-ts-test-font-lock-number ()
+  (skip-unless (treesit-ready-p 'rust))
+  (let ((treesit-font-lock-level 4)
+        (rust-ts-mode-fontify-number-suffix-as-type t))
+    (ert-font-lock-test-file (ert-resource-file "font-lock-number.rs")
+                             'rust-ts-mode)))
 
 (provide 'rust-ts-mode-tests)