From 235561a2ccc03f50652cd942ab7906fe6178ef83 Mon Sep 17 00:00:00 2001 From: Vincenzo Pupillo Date: Sat, 22 Jul 2023 13:37:54 +0200 Subject: [PATCH] Update TSX support due to upstream changes (bug#64647) A recent change in tree-sitter-typescript grammar support for TSX (commit b893426), changed two things: 1. renamed nested_identifier to member_expression 2. removed jsx_fragment, jsx_text is used instead * lisp/progmodes/typescript-ts-mode.el (tsx-ts-mode--indent-compatibility-b893426): Indent helper function to handle different tree-sitter-typescript version. * lisp/progmodes/typescript-ts-mode.el (typescript-ts-mode--indent-rules): use the new function to handle both jsx_fragment and jsx_text. * lisp/progmodes/typescript-ts-mode.el (tsx-ts-mode--font-lock-compatibility-bb1f97b): Font lock helper function for handle different tree-sitter-typescript version. * lisp/progmodes/typescript-ts-mode.el (typescript-ts-mode--font-lock-settings): Use the new function to handle both nested_identifier and member_expression. --- lisp/progmodes/typescript-ts-mode.el | 78 ++++++++++++++++++++-------- 1 file changed, 55 insertions(+), 23 deletions(-) diff --git a/lisp/progmodes/typescript-ts-mode.el b/lisp/progmodes/typescript-ts-mode.el index 5df34de0472..173ec52f209 100644 --- a/lisp/progmodes/typescript-ts-mode.el +++ b/lisp/progmodes/typescript-ts-mode.el @@ -75,6 +75,18 @@ table) "Syntax table for `typescript-ts-mode'.") +(defun tsx-ts-mode--indent-compatibility-b893426 () + "Indent rules helper, to handle different releases of tree-sitter-tsx. +Check if a node type is available, then return the right indent rules." + ;; handle commit b893426 + (condition-case nil + (progn (treesit-query-capture 'tsx '((jsx_fragment) @capture)) + `(((match "<" "jsx_fragment") parent 0) + ((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset))) + (error + `(((match "<" "jsx_text") parent 0) + ((parent-is "jsx_text") parent typescript-ts-mode-indent-offset))))) + (defun typescript-ts-mode--indent-rules (language) "Rules used for indentation. Argument LANGUAGE is either `typescript' or `tsx'." @@ -110,16 +122,15 @@ Argument LANGUAGE is either `typescript' or `tsx'." ((parent-is "binary_expression") parent-bol typescript-ts-mode-indent-offset) ,@(when (eq language 'tsx) - `(((match "<" "jsx_fragment") parent 0) - ((parent-is "jsx_fragment") parent typescript-ts-mode-indent-offset) - ((node-is "jsx_closing_element") parent 0) - ((match "jsx_element" "statement") parent typescript-ts-mode-indent-offset) - ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset) - ((parent-is "jsx_text") parent-bol typescript-ts-mode-indent-offset) - ((parent-is "jsx_opening_element") parent typescript-ts-mode-indent-offset) - ((parent-is "jsx_expression") parent-bol typescript-ts-mode-indent-offset) - ((match "/" "jsx_self_closing_element") parent 0) - ((parent-is "jsx_self_closing_element") parent typescript-ts-mode-indent-offset))) + (append (tsx-ts-mode--indent-compatibility-b893426) + `(((node-is "jsx_closing_element") parent 0) + ((match "jsx_element" "statement") parent typescript-ts-mode-indent-offset) + ((parent-is "jsx_element") parent typescript-ts-mode-indent-offset) + ((parent-is "jsx_text") parent-bol typescript-ts-mode-indent-offset) + ((parent-is "jsx_opening_element") parent typescript-ts-mode-indent-offset) + ((parent-is "jsx_expression") parent-bol typescript-ts-mode-indent-offset) + ((match "/" "jsx_self_closing_element") parent 0) + ((parent-is "jsx_self_closing_element") parent typescript-ts-mode-indent-offset)))) ;; FIXME(Theo): This no-node catch-all should be removed. When is it needed? (no-node parent-bol 0)))) @@ -142,6 +153,38 @@ Argument LANGUAGE is either `typescript' or `tsx'." "&&" "||" "!" "?.") "TypeScript operators for tree-sitter font-locking.") +(defun tsx-ts-mode--font-lock-compatibility-bb1f97b () + "Font lock rules helper, to handle different releases of tree-sitter-tsx. +Check if a node type is available, then return the right font lock rules." + ;; handle commit bb1f97b + ;; Warning: treesitter-query-capture says both node types are valid, + ;; but then raises an error if the wrong node type is used. So it is + ;; important to check with the new node type (member_expression) + (condition-case nil + (progn (treesit-query-capture 'tsx '((member_expression) @capture)) + '((jsx_opening_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_closing_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_self_closing_element + [(member_expression (identifier)) (identifier)] + @typescript-ts-jsx-tag-face))) + (error '((jsx_opening_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_closing_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face) + + (jsx_self_closing_element + [(nested_identifier (identifier)) (identifier)] + @typescript-ts-jsx-tag-face))))) + (defun typescript-ts-mode--font-lock-settings (language) "Tree-sitter font-lock settings. Argument LANGUAGE is either `typescript' or `tsx'." @@ -293,19 +336,8 @@ Argument LANGUAGE is either `typescript' or `tsx'." :language language :feature 'jsx - `((jsx_opening_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_closing_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_self_closing_element - [(nested_identifier (identifier)) (identifier)] - @typescript-ts-jsx-tag-face) - - (jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face)) + (append (tsx-ts-mode--font-lock-compatibility-bb1f97b) + `((jsx_attribute (property_identifier) @typescript-ts-jsx-attribute-face))) :language language :feature 'number -- 2.39.2