Subject: bug#69024: closed (Re: bug#69024: [PATCH] Breaking change in tree-sitter-typescript/tsx starting version 0.20.4)

From: [email-masked] (GNU bug Tracking System)
Date: Sun, 11 Feb 2024 12:37:01 +0000

Your bug report

#69024: [PATCH] Breaking change in tree-sitter-typescript/tsx starting version 0.20.4

which was filed against the emacs package, has been closed.

The explanation is attached below, along with your original report.
If you require more details, please reply to [email-masked].

-- 
69024: https://debbugs.gnu.org/cgi/bugreport.cgi?bug=69024
GNU Bug Tracking System
Contact [email-masked] with problems

Subject: Re: bug#69024: [PATCH] Breaking change in tree-sitter-typescript/tsx starting version 0.20.4
From: Dmitry Gutov <[email-masked]>
To: Eli Zaretskii <[email-masked]>
Cc: [email-masked], [email-masked]
Date: Sun, 11 Feb 2024 14:27:46 +0200
List-Id: <debbugs-submit.debbugs.gnu.org>

On 11/02/2024 08:50, Eli Zaretskii wrote:
>> Date: Sun, 11 Feb 2024 05:02:17 +0200
>> From: Dmitry Gutov<[email-masked]>
>>
>> On 11/02/2024 01:38, Loïc Lemaître wrote:
>>> A similar patch is also needed for Typescript/TSX in relation to this
>>> closed bug in Javascript :
>>> https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68879
>>>
>>> The attached patch should do the job.
>> Thanks for the patch! Pushed to emacs-29.
> Should this bug be closed now?
> 
> And what about bug#68924 -- does this solve that one as well?

Yep, closing.

Subject: [PATCH] Breaking change in tree-sitter-typescript/tsx starting version 0.20.4
From: Loïc Lemaître <[email-masked]>
To: [email-masked]
Date: Sun, 11 Feb 2024 00:38:43 +0100
List-Id: <debbugs-submit.debbugs.gnu.org>

Hi,

A similar patch is also needed for Typescript/TSX in relation to this 
closed bug in Javascript :
https://debbugs.gnu.org/cgi/bugreport.cgi?bug=68879

The attached patch should do the job.

Thank you in advance.

Loïc Lemaître
From 4b7fb0045e67180a4cfe15a11b1a72772fcc7f04 Mon Sep 17 00:00:00 2001
From: Loic Lemaitre <[email-masked]>
Date: Sun, 11 Feb 2024 00:11:32 +0100
Subject: [PATCH] Handle tree-sitter grammar breaking change for "function"
 expression.

Starting from version 0.20.4 of the typescript/tsx grammar, "function"
becomes "function_expression". The right expression is used depending
on the grammar version.
---
 lisp/progmodes/typescript-ts-mode.el | 362 ++++++++++++++-------------
 1 file changed, 188 insertions(+), 174 deletions(-)

diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el
index 89ca47571eb..7021f012dcd 100644
--- a/lisp/progmodes/typescript-ts-mode.el
+++ b/lisp/progmodes/typescript-ts-mode.el
@@ -199,183 +199,197 @@ tsx-ts-mode--font-lock-compatibility-bb1f97b
 	      [(nested_identifier (identifier)) (identifier)]
 	      @typescript-ts-jsx-tag-face)))))
 
+(defun tsx-ts-mode--font-lock-compatibility-function-expression (language)
+  "Handle tree-sitter grammar breaking change for `function' expression.
+
+LANGUAGE can be `typescript' or `tsx'.  Starting from version 0.20.4 of the
+typescript/tsx grammar, `function' becomes `function_expression'."
+  (condition-case nil
+      (progn (treesit-query-capture language '((function_expression) @cap))
+             ;; New version of the grammar
+             'function_expression)
+    (treesit-query-error
+    ;; Old version of the grammar
+    'function)))
+
 (defun typescript-ts-mode--font-lock-settings (language)
   "Tree-sitter font-lock settings.
 Argument LANGUAGE is either `typescript' or `tsx'."
-  (treesit-font-lock-rules
-   :language language
-   :feature 'comment
-   `([(comment) (hash_bang_line)] @font-lock-comment-face)
-
-   :language language
-   :feature 'constant
-   `(((identifier) @font-lock-constant-face
-      (:match "\\`[A-Z_][0-9A-Z_]*\\'" @font-lock-constant-face))
-     [(true) (false) (null)] @font-lock-constant-face)
-
-   :language language
-   :feature 'keyword
-   `([,@typescript-ts-mode--keywords] @font-lock-keyword-face
-     [(this) (super)] @font-lock-keyword-face)
-
-   :language language
-   :feature 'string
-   `((regex pattern: (regex_pattern)) @font-lock-regexp-face
-     (string) @font-lock-string-face
-     (template_string) @js--fontify-template-string
-     (template_substitution ["${" "}"] @font-lock-misc-punctuation-face))
-
-   :language language
-   :override t ;; for functions assigned to variables
-   :feature 'declaration
-   `((function
-      name: (identifier) @font-lock-function-name-face)
-     (function_declaration
-      name: (identifier) @font-lock-function-name-face)
-     (function_signature
-      name: (identifier) @font-lock-function-name-face)
-
-     (method_definition
-      name: (property_identifier) @font-lock-function-name-face)
-     (method_signature
-      name: (property_identifier) @font-lock-function-name-face)
-     (required_parameter (identifier) @font-lock-variable-name-face)
-     (optional_parameter (identifier) @font-lock-variable-name-face)
-
-     (variable_declarator
-      name: (identifier) @font-lock-function-name-face
-      value: [(function) (arrow_function)])
-
-     (variable_declarator
-      name: (identifier) @font-lock-variable-name-face)
-
-     (enum_declaration (identifier) @font-lock-type-face)
-
-     (extends_clause value: (identifier) @font-lock-type-face)
-     ;; extends React.Component<T>
-     (extends_clause value: (member_expression
-                             object: (identifier) @font-lock-type-face
-                             property: (property_identifier) @font-lock-type-face))
-
-     (arrow_function
-      parameter: (identifier) @font-lock-variable-name-face)
-
-     (variable_declarator
-      name: (array_pattern
-             (identifier)
-             (identifier) @font-lock-function-name-face)
-      value: (array (number) (function)))
-
-     (catch_clause
-      parameter: (identifier) @font-lock-variable-name-face)
-
-     ;; full module imports
-     (import_clause (identifier) @font-lock-variable-name-face)
-     ;; named imports with aliasing
-     (import_clause (named_imports (import_specifier
-                                    alias: (identifier) @font-lock-variable-name-face)))
-     ;; named imports without aliasing
-     (import_clause (named_imports (import_specifier
-                                    !alias
-                                    name: (identifier) @font-lock-variable-name-face)))
-
-     ;; full namespace import (* as alias)
-     (import_clause (namespace_import (identifier) @font-lock-variable-name-face)))
-
-   :language language
-   :feature 'identifier
-   `((nested_type_identifier
-      module: (identifier) @font-lock-type-face)
-
-     (type_identifier) @font-lock-type-face
-
-     (predefined_type) @font-lock-type-face
-
-     (new_expression
-      constructor: (identifier) @font-lock-type-face)
-
-     (enum_body (property_identifier) @font-lock-type-face)
-
-     (enum_assignment name: (property_identifier) @font-lock-type-face)
-
-     (variable_declarator
-      name: (identifier) @font-lock-variable-name-face)
-
-     (for_in_statement
-      left: (identifier) @font-lock-variable-name-face)
-
-     (arrow_function
-      parameters:
-      [(_ (identifier) @font-lock-variable-name-face)
-       (_ (_ (identifier) @font-lock-variable-name-face))
-       (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
-
-   :language language
-   :feature 'property
-   `((property_signature
-      name: (property_identifier) @font-lock-property-name-face)
-     (public_field_definition
-      name: (property_identifier) @font-lock-property-name-face)
-
-     (pair key: (property_identifier) @font-lock-property-use-face)
-
-     ((shorthand_property_identifier) @font-lock-property-use-face))
-
-   :language language
-   :feature 'expression
-   '((assignment_expression
-      left: [(identifier) @font-lock-function-name-face
-             (member_expression
-              property: (property_identifier) @font-lock-function-name-face)]
-      right: [(function) (arrow_function)]))
-
-   :language language
-   :feature 'function
-   '((call_expression
-      function:
-      [(identifier) @font-lock-function-call-face
-       (member_expression
-        property: (property_identifier) @font-lock-function-call-face)]))
-
-   :language language
-   :feature 'pattern
-   `((pair_pattern
-      key: (property_identifier) @font-lock-property-use-face
-      value: [(identifier) @font-lock-variable-name-face
-              (assignment_pattern left: (identifier) @font-lock-variable-name-face)])
-
-     (array_pattern (identifier) @font-lock-variable-name-face)
-
-     ((shorthand_property_identifier_pattern) @font-lock-variable-name-face))
-
-   :language language
-   :feature 'jsx
-   (append (tsx-ts-mode--font-lock-compatibility-bb1f97b language)
-	   `((jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face)))
-
-   :language language
-   :feature 'number
-   `((number) @font-lock-number-face
-     ((identifier) @font-lock-number-face
-      (:match "\\`\\(?:NaN\\|Infinity\\)\\'" @font-lock-number-face)))
-
-   :language language
-   :feature 'operator
-   `([,@typescript-ts-mode--operators] @font-lock-operator-face
-     (ternary_expression ["?" ":"] @font-lock-operator-face))
-
-   :language language
-   :feature 'bracket
-   '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face)
-
-   :language language
-   :feature 'delimiter
-   '((["," "." ";" ":"]) @font-lock-delimiter-face)
-
-   :language language
-   :feature 'escape-sequence
-   :override t
-   '((escape_sequence) @font-lock-escape-face)))
+  (let ((func-exp (tsx-ts-mode--font-lock-compatibility-function-expression language)))
+    (treesit-font-lock-rules
+     :language language
+     :feature 'comment
+     `([(comment) (hash_bang_line)] @font-lock-comment-face)
+
+     :language language
+     :feature 'constant
+     `(((identifier) @font-lock-constant-face
+        (:match "\\`[A-Z_][0-9A-Z_]*\\'" @font-lock-constant-face))
+       [(true) (false) (null)] @font-lock-constant-face)
+
+     :language language
+     :feature 'keyword
+     `([,@typescript-ts-mode--keywords] @font-lock-keyword-face
+       [(this) (super)] @font-lock-keyword-face)
+
+     :language language
+     :feature 'string
+     `((regex pattern: (regex_pattern)) @font-lock-regexp-face
+       (string) @font-lock-string-face
+       (template_string) @js--fontify-template-string
+       (template_substitution ["${" "}"] @font-lock-misc-punctuation-face))
+
+     :language language
+     :override t ;; for functions assigned to variables
+     :feature 'declaration
+     `((,func-exp
+        name: (identifier) @font-lock-function-name-face)
+       (function_declaration
+        name: (identifier) @font-lock-function-name-face)
+       (function_signature
+        name: (identifier) @font-lock-function-name-face)
+
+       (method_definition
+        name: (property_identifier) @font-lock-function-name-face)
+       (method_signature
+        name: (property_identifier) @font-lock-function-name-face)
+       (required_parameter (identifier) @font-lock-variable-name-face)
+       (optional_parameter (identifier) @font-lock-variable-name-face)
+
+       (variable_declarator
+        name: (identifier) @font-lock-function-name-face
+        value: [(,func-exp) (arrow_function)])
+
+       (variable_declarator
+        name: (identifier) @font-lock-variable-name-face)
+
+       (enum_declaration (identifier) @font-lock-type-face)
+
+       (extends_clause value: (identifier) @font-lock-type-face)
+       ;; extends React.Component<T>
+       (extends_clause value: (member_expression
+                               object: (identifier) @font-lock-type-face
+                               property: (property_identifier) @font-lock-type-face))
+
+       (arrow_function
+        parameter: (identifier) @font-lock-variable-name-face)
+
+       (variable_declarator
+        name: (array_pattern
+               (identifier)
+               (identifier) @font-lock-function-name-face)
+        value: (array (number) (,func-exp)))
+
+       (catch_clause
+        parameter: (identifier) @font-lock-variable-name-face)
+
+       ;; full module imports
+       (import_clause (identifier) @font-lock-variable-name-face)
+       ;; named imports with aliasing
+       (import_clause (named_imports (import_specifier
+                                      alias: (identifier) @font-lock-variable-name-face)))
+       ;; named imports without aliasing
+       (import_clause (named_imports (import_specifier
+                                      !alias
+                                      name: (identifier) @font-lock-variable-name-face)))
+
+       ;; full namespace import (* as alias)
+       (import_clause (namespace_import (identifier) @font-lock-variable-name-face)))
+
+     :language language
+     :feature 'identifier
+     `((nested_type_identifier
+        module: (identifier) @font-lock-type-face)
+
+       (type_identifier) @font-lock-type-face
+
+       (predefined_type) @font-lock-type-face
+
+       (new_expression
+        constructor: (identifier) @font-lock-type-face)
+
+       (enum_body (property_identifier) @font-lock-type-face)
+
+       (enum_assignment name: (property_identifier) @font-lock-type-face)
+
+       (variable_declarator
+        name: (identifier) @font-lock-variable-name-face)
+
+       (for_in_statement
+        left: (identifier) @font-lock-variable-name-face)
+
+       (arrow_function
+        parameters:
+        [(_ (identifier) @font-lock-variable-name-face)
+         (_ (_ (identifier) @font-lock-variable-name-face))
+         (_ (_ (_ (identifier) @font-lock-variable-name-face)))]))
+
+     :language language
+     :feature 'property
+     `((property_signature
+        name: (property_identifier) @font-lock-property-name-face)
+       (public_field_definition
+        name: (property_identifier) @font-lock-property-name-face)
+
+       (pair key: (property_identifier) @font-lock-property-use-face)
+
+       ((shorthand_property_identifier) @font-lock-property-use-face))
+
+     :language language
+     :feature 'expression
+     `((assignment_expression
+        left: [(identifier) @font-lock-function-name-face
+               (member_expression
+                property: (property_identifier) @font-lock-function-name-face)]
+        right: [(,func-exp) (arrow_function)]))
+
+     :language language
+     :feature 'function
+     '((call_expression
+        function:
+        [(identifier) @font-lock-function-call-face
+         (member_expression
+          property: (property_identifier) @font-lock-function-call-face)]))
+
+     :language language
+     :feature 'pattern
+     `((pair_pattern
+        key: (property_identifier) @font-lock-property-use-face
+        value: [(identifier) @font-lock-variable-name-face
+                (assignment_pattern left: (identifier) @font-lock-variable-name-face)])
+
+       (array_pattern (identifier) @font-lock-variable-name-face)
+
+       ((shorthand_property_identifier_pattern) @font-lock-variable-name-face))
+
+     :language language
+     :feature 'jsx
+     (append (tsx-ts-mode--font-lock-compatibility-bb1f97b language)
+	     `((jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face)))
+
+     :language language
+     :feature 'number
+     `((number) @font-lock-number-face
+       ((identifier) @font-lock-number-face
+        (:match "\\`\\(?:NaN\\|Infinity\\)\\'" @font-lock-number-face)))
+
+     :language language
+     :feature 'operator
+     `([,@typescript-ts-mode--operators] @font-lock-operator-face
+       (ternary_expression ["?" ":"] @font-lock-operator-face))
+
+     :language language
+     :feature 'bracket
+     '((["(" ")" "[" "]" "{" "}"]) @font-lock-bracket-face)
+
+     :language language
+     :feature 'delimiter
+     '((["," "." ";" ":"]) @font-lock-delimiter-face)
+
+     :language language
+     :feature 'escape-sequence
+     :override t
+     '((escape_sequence) @font-lock-escape-face))))
 
 ;;;###autoload
 (define-derived-mode typescript-ts-base-mode prog-mode "TypeScript"
-- 
2.34.1