Subject: bug#59397: [PATCH] feature/tree-sitter: Utilize new font-lock faces for more tree-sitter backed modes

From: Randy Taylor <[email-masked]>
Date: Sun, 20 Nov 2022 03:42:19 +0000

X-Debbugs-CC: [email-masked], [email-masked]

This patch adds support for using the new font-lock faces for more tree-sitter backed modes.

js.el:
- For the number feature, is there a better way to match for exactly NaN or Infinity?
- It might be a good idea to make a parent/base mode (ECMA?) like done in c-ts-mode for JS and TS, since there's a bit of overlap. I'm not volunteering though, since I don't use JS or TS ;).

From a157d87327fe5af206a9282f582cfe92605f0667 Mon Sep 17 00:00:00 2001
From: Randy Taylor <[email-masked]>
Date: Sat, 19 Nov 2022 22:30:13 -0500
Subject: [PATCH] Utilize new font-lock faces for more tree-sitter backed modes

* lisp/progmodes/java-ts-mode.el (java-ts-mode--font-lock-settings):
Use operator and number font-lock faces.
(java-ts-mode): Alphabetize.
* lisp/progmodes/js.el (js--treesit-operators): Define operators.
(js--treesit-font-lock-settings): Use bracket, delimiter,
escape-sequence, property, number, and operator font-lock faces.
(js-mode): Add them to the feature list and alphabetize.
* lisp/progmodes/json-ts-mode.el (json-ts-mode--font-lock-settings):
Use bracket, delimiter, escape-sequence, and number faces.  Remove
unused features.
(json-ts-mode): Add them to the feature list and alphabetize.
* lisp/progmodes/sh-script.el (sh-mode--treesit-settings): Use number
and operator font-lock faces.
(sh-mode): Add them to the feature list and alphabetize.
* lisp/progmodes/ts-mode.el (ts-mode--operators): Define operators.
(ts-mode--font-lock-settings): Use bracket, delimiter,
escape-sequence, property, number, and operator font-lock faces.
(ts-mode): Add them to the feature list and alphabetize.
---
 lisp/progmodes/java-ts-mode.el | 17 ++++----
 lisp/progmodes/js.el           | 69 +++++++++++++++++++++++----------
 lisp/progmodes/json-ts-mode.el | 32 ++++++++-------
 lisp/progmodes/sh-script.el    | 15 ++++---
 lisp/progmodes/ts-mode.el      | 71 ++++++++++++++++++++++------------
 5 files changed, 133 insertions(+), 71 deletions(-)

diff --git a/lisp/progmodes/java-ts-mode.el b/lisp/progmodes/java-ts-mode.el
index 6a800d292c..5b8d026da4 100644
--- a/lisp/progmodes/java-ts-mode.el
+++ b/lisp/progmodes/java-ts-mode.el
@@ -133,8 +133,7 @@ java-ts-mode--font-lock-settings
    :feature 'constant
    `(((identifier) @font-lock-constant-face
       (:match "^[A-Z_][A-Z_\\d]*$" @font-lock-constant-face))
-     (true) @font-lock-constant-face
-     (false) @font-lock-constant-face)
+     [(true) (false)] @font-lock-constant-face)
    :language 'java
    :override t
    :feature 'keyword
@@ -144,7 +143,7 @@ java-ts-mode--font-lock-settings
    :language 'java
    :override t
    :feature 'operator
-   `([,@java-ts-mode--operators] @font-lock-builtin-face)
+   `([,@java-ts-mode--operators] @font-lock-operator-face)
    :language 'java
    :override t
    :feature 'annotation
@@ -161,8 +160,12 @@ java-ts-mode--font-lock-settings
    :override t
    :feature 'literal
    `((null_literal) @font-lock-constant-face
-     (decimal_floating_point_literal)  @font-lock-constant-face
-     (hex_floating_point_literal) @font-lock-constant-face)
+     (binary_integer_literal)  @font-lock-number-face
+     (decimal_integer_literal) @font-lock-number-face
+     (hex_integer_literal) @font-lock-number-face
+     (octal_integer_literal) @font-lock-number-face
+     (decimal_floating_point_literal) @font-lock-number-face
+     (hex_floating_point_literal) @font-lock-number-face)
    :language 'java
    :override t
    :feature 'type
@@ -302,8 +305,8 @@ java-ts-mode
   ;; Font-lock.
   (setq-local treesit-font-lock-settings java-ts-mode--font-lock-settings)
   (setq-local treesit-font-lock-feature-list
-              '((basic comment keyword constant string operator)
-                (type definition expression literal annotation)
+              '((basic comment constant keyword operator string)
+                (annotation definition expression literal type)
                 ()))
 
   ;; Imenu.
diff --git a/lisp/progmodes/js.el b/lisp/progmodes/js.el
index 4b07c0d12c..39c4845c4e 100644
--- a/lisp/progmodes/js.el
+++ b/lisp/progmodes/js.el
@@ -3452,6 +3452,13 @@ js--treesit-keywords
     "typeof" "var" "void" "while" "with" "yield")
   "JavaScript keywords for tree-sitter font-locking.")
 
+(defvar js--treesit-operators
+  '("=" "+=" "-=" "*=" "/=" "%=" "**=" "<<=" ">>=" ">>>=" "&=" "^="
+    "|=" "&&=" "||=" "??=" "==" "!=" "===" "!==" ">" ">=" "<" "<=" "+"
+    "-" "*" "/" "%" "++" "--" "**" "&" "|" "^" "~" "<<" ">>" ">>>"
+    "&&" "||" "!")
+  "JavaScript operators for tree-sitter font-locking.")
+
 (defvar js--treesit-font-lock-settings
   (treesit-font-lock-rules
 
@@ -3466,8 +3473,7 @@ js--treesit-font-lock-settings
    `(((identifier) @font-lock-constant-face
       (:match "^[A-Z_][A-Z_\\d]*$" @font-lock-constant-face))
 
-     [(true) (false) (null)] @font-lock-constant-face
-     (number) @font-lock-constant-face)
+     [(true) (false) (null)] @font-lock-constant-face)
 
    :language 'javascript
    :override t
@@ -3544,21 +3550,6 @@ js--treesit-font-lock-settings
              (member_expression
               property: (property_identifier) @font-lock-variable-name-face)]))
 
-   :language 'javascript
-   :override t
-   :feature 'property
-   `((pair key: (property_identifier) @font-lock-variable-name-face)
-
-     (pair value: (identifier) @font-lock-variable-name-face)
-
-     (pair
-      key: (property_identifier) @font-lock-function-name-face
-      value: [(function) (arrow_function)])
-
-     ((shorthand_property_identifier) @font-lock-variable-name-face)
-
-     ((shorthand_property_identifier_pattern) @font-lock-variable-name-face))
-
    :language 'javascript
    :override t
    :feature 'pattern
@@ -3583,7 +3574,42 @@ js--treesit-font-lock-settings
 
      (jsx_attribute
       (property_identifier)
-      @font-lock-constant-face)))
+      @font-lock-property-face))
+
+   :language 'javascript
+   :feature 'number
+   `((number) @font-lock-number-face
+     ((identifier) @font-lock-number-face
+      (:match "^\\(:?NaN\\|Infinity\\)$" @font-lock-number-face)))
+
+   :language 'javascript
+   :feature 'operator
+   `([,@js--treesit-operators] @font-lock-operator-face
+     (ternary_expression ["?" ":"] @font-lock-operator-face))
+
+   :language 'javascript
+   :feature 'bracket
+   '(["(" ")" "[" "]" "{" "}"] @font-lock-bracket-face)
+
+   :language 'javascript
+   :feature 'delimiter
+   '(["," "." ";" ":"] @font-lock-delimiter-face)
+
+   :language 'javascript
+   :feature 'escape-sequence
+   :override t
+   '((escape_sequence) @font-lock-escape-face)
+
+   :language 'javascript
+   :override t
+   :feature 'property
+   `((property_identifier) @font-lock-property-face
+
+     (pair value: (identifier) @font-lock-property-face)
+
+     ((shorthand_property_identifier) @font-lock-property-face)
+
+     ((shorthand_property_identifier_pattern) @font-lock-property-face)))
   "Tree-sitter font-lock settings.")
 
 (defun js--fontify-template-string (node override start end &rest _)
@@ -3831,9 +3857,10 @@ js-ts-mode
     ;; Fontification.
     (setq-local treesit-font-lock-settings js--treesit-font-lock-settings)
     (setq-local treesit-font-lock-feature-list
-                '((comment declaration)
-                  (string keyword identifier expression constant)
-                  (property pattern jsx )))
+                '(( comment declaration)
+                  ( constant expression identifier keyword string)
+                  ( bracket delimiter escape-sequence jsx number operator
+                    pattern property)))
     ;; Imenu
     (setq-local imenu-create-index-function
                 #'js--treesit-imenu)
diff --git a/lisp/progmodes/json-ts-mode.el b/lisp/progmodes/json-ts-mode.el
index 7e0dd17911..3edc0a6888 100644
--- a/lisp/progmodes/json-ts-mode.el
+++ b/lisp/progmodes/json-ts-mode.el
@@ -68,26 +68,28 @@ json-ts--indent-rules
 (defvar json-ts-mode--font-lock-settings
   (treesit-font-lock-rules
    :language 'json
-   :feature 'comment
-   :override t
-   '((comment) @font-lock-comment-face)
+   :feature 'bracket
+   '(["[" "]" "{" "}"] @font-lock-bracket-face)
    :language 'json
-   :feature 'string
-   :override t
-   '((escape_sequence) @font-lock-constant-face
-     (string) @font-lock-string-face)
+   :feature 'constant
+   '([(null) (true) (false)] @font-lock-constant-face)
+   :language 'json
+   :feature 'delimiter
+   '(["," ":"] @font-lock-delimiter-face)
    :language 'json
    :feature 'number
-   :override t
-   '((number) @font-lock-constant-face)
+   '((number) @font-lock-number-face)
    :language 'json
-   :feature 'constant
+   :feature 'string
+   '((string) @font-lock-string-face)
+   :language 'json
+   :feature 'escape-sequence
    :override t
-   '([(null) (true) (false)] @font-lock-constant-face)
+   '((escape_sequence) @font-lock-escape-face)
    :language 'json
-   :feature 'pair
+   :feature 'error
    :override t
-   `((pair key: (_) @font-lock-variable-name-face)))
+   '((ERROR) @font-lock-warning-face))
   "Font-lock settings for JSON.")
 
 (defun json-ts-mode--imenu-1 (node)
@@ -148,7 +150,9 @@ json-ts-mode
   ;; Font-lock.
   (setq-local treesit-font-lock-settings json-ts-mode--font-lock-settings)
   (setq-local treesit-font-lock-feature-list
-              '((comment string number) (constant pair) ()))
+              '((constant number string)
+                (escape-sequence)
+                (bracket delimiter error)))
 
   ;; Imenu.
   (setq-local imenu-create-index-function #'json-ts-mode--imenu)
diff --git a/lisp/progmodes/sh-script.el b/lisp/progmodes/sh-script.el
index ed06f2263e..d40ce20e49 100644
--- a/lisp/progmodes/sh-script.el
+++ b/lisp/progmodes/sh-script.el
@@ -1589,9 +1589,9 @@ sh-mode
    ;; Tree-sitter.  If the shell is bash, we can enable tree-sitter.
    ((treesit-ready-p sh-shell)
     (setq-local treesit-font-lock-feature-list
-                '((comment function string heredoc)
-                  (variable keyword command declaration-command)
-                  (constant operator builtin-variable)))
+                '((comment function heredoc string)
+                  (command declaration-command keyword variable)
+                  (builtin-variable constant number operator)))
     (setq-local treesit-font-lock-settings
                 sh-mode--treesit-settings)
     (treesit-major-mode-setup))
@@ -3306,7 +3306,7 @@ sh-mode--treesit-settings
 
    :feature 'operator
    :language 'bash
-   `([ ,@sh-mode--treesit-operators ] @font-lock-builtin-face)
+   `([,@sh-mode--treesit-operators] @font-lock-operator-face)
 
    :feature 'builtin-variable
    :language 'bash
@@ -3316,7 +3316,12 @@ sh-mode--treesit-settings
                   `(seq bol
                         (or ,@builtin-vars)
                         eol)))
-              @font-lock-builtin-face))))
+              @font-lock-builtin-face)))
+
+   :feature 'number
+   :language 'bash
+   `(((word) @font-lock-number-face
+      (:match "^[0-9]+$" @font-lock-number-face))))
   "Tree-sitter font-lock settings for `sh-mode'.")
 
 (provide 'sh-script)
diff --git a/lisp/progmodes/ts-mode.el b/lisp/progmodes/ts-mode.el
index 01719a89ee..35275d501d 100644
--- a/lisp/progmodes/ts-mode.el
+++ b/lisp/progmodes/ts-mode.el
@@ -101,6 +101,13 @@ ts-mode--keywords
     "while" "with" "yield")
   "TypeScript keywords for tree-sitter font-locking.")
 
+(defvar ts-mode--operators
+  '("=" "+=" "-=" "*=" "/=" "%=" "**=" "<<=" ">>=" ">>>=" "&=" "^="
+    "|=" "&&=" "||=" "??=" "==" "!=" "===" "!==" ">" ">=" "<" "<=" "+"
+    "-" "*" "/" "%" "++" "--" "**" "&" "|" "^" "~" "<<" ">>" ">>>"
+    "&&" "||" "!" "?.")
+  "TypeScript operators for tree-sitter font-locking.")
+
 (defvar ts-mode--font-lock-settings
   (treesit-font-lock-rules
    :language 'tsx
@@ -114,8 +121,7 @@ ts-mode--font-lock-settings
    `(((identifier) @font-lock-constant-face
       (:match "^[A-Z_][A-Z_\\d]*$" @font-lock-constant-face))
 
-     [(true) (false) (null)] @font-lock-constant-face
-     (number) @font-lock-constant-face)
+     [(true) (false) (null)] @font-lock-constant-face)
 
    :language 'tsx
    :override t
@@ -207,25 +213,6 @@ ts-mode--font-lock-settings
        (member_expression
         property: (property_identifier) @font-lock-function-name-face)]))
 
-   :language 'tsx
-   :override t
-   :feature 'property
-   `((pair key: (property_identifier) @font-lock-variable-name-face)
-
-     (pair value: (identifier) @font-lock-variable-name-face)
-
-     (pair
-      key: (property_identifier) @font-lock-function-name-face
-      value: [(function) (arrow_function)])
-
-     (property_signature
-      name: (property_identifier) @font-lock-variable-name-face)
-
-     ((shorthand_property_identifier) @font-lock-variable-name-face)
-
-     ((shorthand_property_identifier_pattern)
-      @font-lock-variable-name-face))
-
    :language 'tsx
    :override t
    :feature 'pattern
@@ -249,7 +236,43 @@ ts-mode--font-lock-settings
       [(nested_identifier (identifier)) (identifier)]
       @font-lock-function-name-face)
 
-     (jsx_attribute (property_identifier) @font-lock-constant-face)))
+     (jsx_attribute (property_identifier) @font-lock-property-face))
+
+   :language 'tsx
+   :feature 'number
+   `((number) @font-lock-number-face
+     ((identifier) @font-lock-number-face
+      (:match "^\\(:?NaN\\|Infinity\\)$" @font-lock-number-face)))
+
+   :language 'tsx
+   :feature 'operator
+   `([,@ts-mode--operators] @font-lock-operator-face
+     (ternary_expression ["?" ":"] @font-lock-operator-face))
+
+   :language 'tsx
+   :feature 'bracket
+   '(["(" ")" "[" "]" "{" "}"] @font-lock-bracket-face)
+
+   :language 'tsx
+   :feature 'delimiter
+   '(["," "." ";" ":"] @font-lock-delimiter-face)
+
+   :language 'tsx
+   :feature 'escape-sequence
+   :override t
+   '((escape_sequence) @font-lock-escape-face)
+
+   :language 'tsx
+   :override t
+   :feature 'property
+   `(((property_identifier) @font-lock-property-face)
+
+     (pair value: (identifier) @font-lock-property-face)
+
+     ((shorthand_property_identifier) @font-lock-property-face)
+
+     ((shorthand_property_identifier_pattern)
+      @font-lock-property-face)))
   "Tree-sitter font-lock settings.")
 
 ;;;###autoload
@@ -296,8 +319,8 @@ ts-mode
     (setq-local treesit-font-lock-settings ts-mode--font-lock-settings)
     (setq-local treesit-font-lock-feature-list
                 '((comment declaration)
-                  (string keyword identifier expression constant)
-                  (property pattern jsx)))
+                  (constant expression identifier keyword number string)
+                  (bracket delimiter jsx property pattern)))
     ;; Imenu.
     (setq-local imenu-create-index-function #'js--treesit-imenu)
 
-- 
2.38.1