Subject: Re: bug#61302: 29.0.60; rust-ts-mode does not show function-invocation on field-properties

From: Randy Taylor <[email-masked]>
Date: Tue, 14 Feb 2023 03:25:48 +0000

On Sunday, February 12th, 2023 at 22:37, Dmitry Gutov <[email-masked]> wrote:
> On 12/02/2023 04:48, Randy Taylor wrote:
> 
> > > I'm not quite sure what's the best choice here (keeping in mind the
> > > problem with overreaching variable highlights on level 4), but
> > > logically, I think 'module' belongs with 'function' and 'property'
> > > because all three denote some basic syntactic elements which are easy to
> > > understand even without colors, and are harder to make a mistake in.
> > 
> > I am proposing to get rid of the module feature entirely and bring those queries into the type feature because:
> > - Of how much overlap there is between them
> > - It will make maintaining the queries much easier
> > - It's already a headache dealing with them separately, and I'm not sure the best way to deal with the issues of them being separate (and the different levels of highlighting to worry about). It will probably be quite the hack to deal with it, and no matter what I tried stuff was always sneaking through.
> > - It also won't introduce that much more highlighting
> 
> 
> Okay, let's try that.
> 
> > > > > Also here's a pre-existing problem mentioned above:
> > > > > 
> > > > > use std::{fmt, fs, usize};
> > > > > 
> > > > > 'fmt' and 'fs' are not types. But they are highlighted with
> > > > > font-lock-type-face.
> > > > 
> > > > This is really weird, I can reproduce it with emacs -Q but not with my normal config...
> > > > Also with emacs -Q this:
> > > > let date = DateTime::chrono::hey::there::Utc::from_utc(date, chrono::cool::this::Utc);
> > > > 
> > > > highlights incorrectly, where "there" is font-lock-variable-name-face. But with my normal config everything is fine.
> > > > 
> > > > I'll look into it tomorrow. Not really sure what in my config could cause this...
> > > 
> > > Thank you.
> > 
> > I did a clean build and wasn't able to reproduce it anymore. Guess it was stale bytecode or something?
> > At level 4 everything highlights correctly I believe, and with level 3 the only issues are the module highlighting ones, and to deal with that I think the module feature should be merged into the type one as I mentioned above. Then we can call it a day :). I'll post a new patch with those changes if you agree.
> 
> 
> Please go ahead, and thanks. :-)

Hi Dmitry and Jostein,

Here is the promised patch in all its glory.
I have also attached a screenshot of how things look now.

Changes:
- Attributes are now highlighted with font-lock-preprocessor-face.
- Added import-specific queries to cover all (hopefully...) import highlights, and simplified the existing scoped identifier types.
  - Note: I decided that anything at the end of a scoped identifier for imports or within a use list that's lowercased should be the default face because we don't know if it's a module, function, type, or whatever else. rust-mode also does this, and now we match their highlighting almost one for one. neovim and the rest do it this way too, and it makes the most sense.

From 4a933e123daa6a05164c806493b10c3e7a8a0af8 Mon Sep 17 00:00:00 2001
From: Randy Taylor <[email-masked]>
Date: Wed, 8 Feb 2023 21:43:04 -0500
Subject: [PATCH] Fix rust-ts-mode type and module highlighting (Bug#61302)

* lisp/progmodes/rust-ts-mode.el (rust-ts-mode--font-lock-settings):
Specify import queries to avoid clashing with scoped identifiers in
the code.  Highlight attributes with font-lock-preprocessor-face.
---
 lisp/progmodes/rust-ts-mode.el | 93 ++++++++++++++++++++++++++--------
 1 file changed, 72 insertions(+), 21 deletions(-)

diff --git a/lisp/progmodes/rust-ts-mode.el b/lisp/progmodes/rust-ts-mode.el
index 5c71a8ad461..d0ff49e2f26 100644
--- a/lisp/progmodes/rust-ts-mode.el
+++ b/lisp/progmodes/rust-ts-mode.el
@@ -124,8 +124,8 @@ rust-ts-mode--font-lock-settings
   (treesit-font-lock-rules
    :language 'rust
    :feature 'attribute
-   '((attribute_item) @font-lock-constant-face
-     (inner_attribute_item) @font-lock-constant-face)
+   '((attribute_item) @font-lock-preprocessor-face
+     (inner_attribute_item) @font-lock-preprocessor-face)
 
    :language 'rust
    :feature 'bracket
@@ -147,12 +147,6 @@ rust-ts-mode--font-lock-settings
    :feature 'comment
    '(([(block_comment) (line_comment)]) @font-lock-comment-face)
 
-   :language 'rust
-   :feature 'constant
-   `((boolean_literal) @font-lock-constant-face
-     ((identifier) @font-lock-constant-face
-      (:match "^[A-Z][A-Z\\d_]*$" @font-lock-constant-face)))
-
    :language 'rust
    :feature 'delimiter
    '((["," "." ";" ":" "::"]) @font-lock-delimiter-face)
@@ -206,7 +200,54 @@ rust-ts-mode--font-lock-settings
 
    :language 'rust
    :feature 'type
-   `((enum_variant name: (identifier) @font-lock-type-face)
+   `((scoped_use_list path: (identifier) @font-lock-constant-face)
+     (scoped_use_list path: (scoped_identifier
+                             name: (identifier) @font-lock-constant-face))
+
+     ((use_as_clause alias: (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     ((use_as_clause path: (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     ((use_as_clause path:
+                     (scoped_identifier path: (_)
+                                        name: (identifier) @font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_as_clause path: (scoped_identifier name: (identifier) @default))
+
+     ((use_declaration
+       argument: (scoped_identifier
+                  path: (_) @font-lock-constant-face
+                  name: (identifier) @font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_declaration
+      argument: (scoped_identifier
+                 name: (identifier) @default))
+
+     (use_declaration
+      argument: (scoped_identifier
+                 path: (scoped_identifier
+                        path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-constant-face)
+                 name: (identifier) @default))
+
+     (use_declaration
+      argument: (scoped_use_list
+                 path: (scoped_identifier
+                        path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-constant-face)))
+
+     ((use_list (identifier) @font-lock-type-face)
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_list (identifier) @default)
+     ((use_list (scoped_identifier path: (_)
+                                   name: (identifier) @font-lock-type-face))
+      (:match "^[A-Z]" @font-lock-type-face))
+     (use_list (scoped_identifier path: (_)
+                                  name: (identifier) @default))
+     (use_wildcard (scoped_identifier
+                    name: (identifier) @font-lock-constant-face))
+
+     (enum_variant name: (identifier) @font-lock-type-face)
      (match_arm
       pattern: (match_pattern (_ type: (identifier) @font-lock-type-face)))
      (match_arm
@@ -220,25 +261,35 @@ rust-ts-mode--font-lock-settings
       (:match "^[A-Z]" @font-lock-type-face))
      ((scoped_identifier path: (identifier) @font-lock-type-face)
       (:match "^[A-Z]" @font-lock-type-face))
-     ((scoped_identifier
-        (scoped_identifier
-         path: (identifier) @font-lock-type-face))
-      (:match "^[A-Z]" @font-lock-type-face))
-     ((scoped_identifier
-       path: [(identifier) @font-lock-type-face
-              (scoped_identifier
-               name: (identifier) @font-lock-type-face)])
-      (:match "^[A-Z]" @font-lock-type-face))
-     (scoped_type_identifier path: (identifier) @font-lock-type-face)
+     ((scoped_identifier path: (identifier) @font-lock-type-face)
+      (:match
+       "^\\(u8\\|u16\\|u32\\|u64\\|u128\\|usize\\|i8\\|i16\\|i32\\|i64\\|i128\\|isize\\|char\\|str\\)$"
+       @font-lock-type-face))
+     (scoped_identifier path: (_) @font-lock-constant-face
+                        name: (identifier) @font-lock-type-face)
+     (scoped_identifier path: (scoped_identifier
+                               name: (identifier) @font-lock-constant-face))
+     (scoped_type_identifier path: (_) @font-lock-constant-face)
+     (scoped_type_identifier
+      path: (scoped_identifier
+             path: (_) @font-lock-constant-face
+             name: (identifier) @font-lock-constant-face))
      (type_identifier) @font-lock-type-face
-     (use_as_clause alias: (identifier) @font-lock-type-face)
-     (use_list (identifier) @font-lock-type-face))
+     ;; Ensure function calls aren't highlighted as types.
+     (call_expression function: (scoped_identifier name: (identifier) @default)))
 
    :language 'rust
    :feature 'property
    '((field_identifier) @font-lock-property-face
      (shorthand_field_initializer (identifier) @font-lock-property-face))
 
+   ;; Must be under type, otherwise some imports can be highlighted as consants.
+   :language 'rust
+   :feature 'constant
+   `((boolean_literal) @font-lock-constant-face
+     ((identifier) @font-lock-constant-face
+      (:match "^[A-Z][A-Z\\d_]*$" @font-lock-constant-face)))
+
    :language 'rust
    :feature 'variable
    '((identifier) @font-lock-variable-name-face
-- 
2.39.1