Improve treesit settings for typescript/tsx-ts-mode (bug#73404)

* lisp/progmodes/typescript-ts-mode.el
(typescript-ts-mode--font-lock-settings): Add @font-lock-type-face
for 'internal_module' with 'identifier'.
(typescript-ts-mode--defun-type-regexp): New variable with
"internal_module" and "interface_declaration".
(typescript-ts-mode--defun-name): New function that uses
'js--treesit-defun-name' and adds "internal_module" and
"interface_declaration".
(typescript-ts-mode--simple-imenu-settings): New variable
like in 'js-ts-mode' with "Namespace" and "Interface" sections.
(typescript-ts-mode--outline-predicate): New variable.
(typescript-ts-base-mode): Set treesit-defun-type-regexp to
typescript-ts-mode--defun-type-regexp, treesit-defun-name-function
to typescript-ts-mode--defun-name, treesit-simple-imenu-settings
to typescript-ts-mode--simple-imenu-settings,
treesit-outline-predicate to typescript-ts-mode--outline-predicate.
Use js--regexp-opt-symbol for treesit-thing-settings.
(tsx-ts-mode): For 'sentence' thing use the same nodes as
js--treesit-sentence-nodes.  Use js--regexp-opt-symbol for
treesit-thing-settings.

* lisp/progmodes/js.el (js--treesit-sentence-nodes): Add
"jsx_opening_element" and "jsx_closing_element" like in html.

* lisp/progmodes/c-ts-mode.el (c-ts-mode--outline-predicate): Add
outline headings for C++ "namespace_definition" and "class_specifier".
This commit is contained in:
Juri Linkov 2025-03-05 19:44:44 +02:00
parent 98ca8b46e6
commit 68def672e6
3 changed files with 77 additions and 45 deletions

View file

@ -1048,7 +1048,9 @@ Return nil if NODE is not a defun node or doesn't have a name."
(treesit-parent-until node "function_definition"))
;; DEFUNs in Emacs sources.
(and c-ts-mode-emacs-sources-support
(c-ts-mode--emacs-defun-p node))))
(c-ts-mode--emacs-defun-p node))
(member (treesit-node-type node) '("namespace_definition"
"class_specifier"))))
;;; Defun navigation

View file

@ -3866,7 +3866,9 @@ Currently there are `js-mode' and `js-ts-mode'."
"labeled_statement"
"variable_declaration"
"lexical_declaration"
"jsx_attribute")
"jsx_opening_element"
"jsx_attribute"
"jsx_closing_element")
"Nodes that designate sentences in JavaScript.
See `treesit-thing-settings' for more information.")
@ -3958,10 +3960,10 @@ See `treesit-thing-settings' for more information.")
(defvar js-ts-mode--outline-predicate
`(or (and "\\`class\\'" named)
,(rx bos (or"class_declaration"
"method_definition"
"function_declaration"
"function_expression")
,(rx bos (or "class_declaration"
"method_definition"
"function_declaration"
"function_expression")
eos)))
(defvar js--treesit-defun-type-regexp
@ -4009,9 +4011,7 @@ See `treesit-thing-settings' for more information.")
(setq-local treesit-simple-indent-rules js--treesit-indent-rules)
;; Navigation.
(setq-local treesit-defun-type-regexp js--treesit-defun-type-regexp)
(setq-local treesit-defun-name-function #'js--treesit-defun-name)
(setq-local treesit-thing-settings js--treesit-thing-settings)
;; Fontification.

View file

@ -317,6 +317,8 @@ Argument LANGUAGE is either `typescript' or `tsx'."
object: (identifier) @font-lock-type-face
property: (property_identifier) @font-lock-type-face))
(internal_module (identifier) @font-lock-type-face)
(arrow_function
parameter: (identifier) @font-lock-variable-name-face)
@ -509,6 +511,49 @@ See `treesit-thing-settings' for more information.")
"Nodes that designate lists in TypeScript.
See `treesit-thing-settings' for more information.")
(defvar typescript-ts-mode--defun-type-regexp
(rx bos (or "internal_module"
"interface_declaration"
"class_declaration"
"method_definition"
"function_declaration"
"lexical_declaration")
eos)
"Settings for `treesit-defun-type-regexp'.")
(defun typescript-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."
(or (js--treesit-defun-name node)
(treesit-node-text
(pcase (treesit-node-type node)
("internal_module"
(treesit-node-child node 1))
("interface_declaration"
(treesit-node-child-by-field-name node "name")))
t)))
(defvar typescript-ts-mode--simple-imenu-settings
`(("Namespace" "\\`internal_module\\'" nil nil)
("Interface" "\\`interface_declaration\\'" nil nil)
("Class" "\\`class_declaration\\'" nil nil)
("Method" "\\`method_definition\\'" nil nil)
("Function" "\\`function_declaration\\'" nil nil)
("Variable" ,(rx bos (or "lexical_declaration"
"variable_declaration")
eos)
,#'js--treesit-valid-imenu-entry nil))
"Settings for `treesit-simple-imenu'.")
(defvar typescript-ts-mode--outline-predicate
(rx bos (or "internal_module"
"interface_declaration"
"class_declaration"
"method_definition"
"function_declaration"
"function_expression")
eos))
;;;###autoload
(define-derived-mode typescript-ts-base-mode prog-mode "TypeScript"
"Generic major mode for editing TypeScript.
@ -526,33 +571,21 @@ This mode is intended to be inherited by concrete major modes."
(setq-local electric-layout-rules
'((?\; . after) (?\{ . after) (?\} . before)))
;; Navigation.
(setq-local treesit-defun-type-regexp
(regexp-opt '("class_declaration"
"method_definition"
"function_declaration"
"lexical_declaration")))
(setq-local treesit-defun-name-function #'js--treesit-defun-name)
(setq-local treesit-defun-type-regexp typescript-ts-mode--defun-type-regexp)
(setq-local treesit-defun-name-function #'typescript-ts-mode--defun-name)
(setq-local treesit-thing-settings
`((typescript
(sexp ,(regexp-opt typescript-ts-mode--sexp-nodes 'symbols))
(list ,(regexp-opt typescript-ts-mode--list-nodes
'symbols))
(sentence ,(regexp-opt
typescript-ts-mode--sentence-nodes 'symbols))
(text ,(regexp-opt '("comment"
"template_string")
'symbols)))))
(sexp ,(js--regexp-opt-symbol typescript-ts-mode--sexp-nodes))
(list ,(js--regexp-opt-symbol typescript-ts-mode--list-nodes))
(sentence ,(js--regexp-opt-symbol typescript-ts-mode--sentence-nodes))
(text ,(js--regexp-opt-symbol '("comment" "template_string"))))))
;; Imenu (same as in `js-ts-mode').
;; Imenu (same as in `js-ts-mode') + namespace/interface.
(setq-local treesit-simple-imenu-settings
`(("Function" "\\`function_declaration\\'" nil nil)
("Variable" "\\`lexical_declaration\\'"
js--treesit-valid-imenu-entry nil)
("Class" ,(rx bos (or "class_declaration"
"method_definition")
eos)
nil nil))))
typescript-ts-mode--simple-imenu-settings)
;; Outline minor mode
(setq-local treesit-outline-predicate typescript-ts-mode--outline-predicate))
;;;###autoload
(define-derived-mode typescript-ts-mode typescript-ts-base-mode "TypeScript"
@ -618,24 +651,21 @@ at least 3 (which is the default value)."
(setq-local treesit-thing-settings
`((tsx
(sexp ,(regexp-opt
(sexp ,(js--regexp-opt-symbol
(append typescript-ts-mode--sexp-nodes
'("jsx"))))
(list ,(concat "^"
(regexp-opt
(append typescript-ts-mode--list-nodes
'(
"jsx_element"
"jsx_self_closing_element"
"jsx_expression")))
"$"))
(sentence ,(regexp-opt
(list ,(js--regexp-opt-symbol
(append typescript-ts-mode--list-nodes
'("jsx_element"
"jsx_self_closing_element"
"jsx_expression"))))
(sentence ,(js--regexp-opt-symbol
(append typescript-ts-mode--sentence-nodes
'("jsx_element"
"jsx_self_closing_element"))))
(text ,(regexp-opt '("comment"
"template_string"))
'symbols))))
'("jsx_opening_element"
"jsx_attribute"
"jsx_closing_element"))))
(text ,(js--regexp-opt-symbol '("comment"
"template_string"))))))
;; Font-lock.
(setq-local treesit-font-lock-settings