mirror of
https://github.com/masscollaborationlabs/emacs.git
synced 2025-07-11 06:30:51 +00:00
Support defun navigation for DEFUN in c-ts-mode (bug#64442)
Before this change, beginning/end-of-defun just ignores DEFUN in c-ts-mode. After this change, beginning/end-of-defun can recognize DEFUN, but a DEFUN definition is considered two defuns. Eg, beginning/end-of-defun will stop at (1) (2) and (3) in the following snippet: (1)DEFUN ("treesit-node-parser", Ftreesit_node_parser, Streesit_node_parser, 1, 1, 0, doc: /* Return the parser to which NODE belongs. */) (Lisp_Object node) (2){ CHECK_TS_NODE (node); return XTS_NODE (node)->parser; } (3) Ideally we want point to only stop at (1) and (3), but that'll be a lot harder to do. * lisp/progmodes/c-ts-mode.el: (c-ts-mode--defun-valid-p): Refactor to take in account of DEFUN body. (c-ts-mode--emacs-defun-body-p): New function. (c-ts-base-mode): Add DEFUN and DEFUN body to recognized types. (c-ts-mode--emacs-defun-at-point): Now that we recognize both parts of a DEFUN as defun, c-ts-mode--emacs-defun-at-point needs to be updated to adapt to it.
This commit is contained in:
parent
781ddd7e7d
commit
baeb2d71ae
1 changed files with 60 additions and 55 deletions
|
@ -880,29 +880,36 @@ Return nil if NODE is not a defun node or doesn't have a name."
|
||||||
(defun c-ts-mode--defun-valid-p (node)
|
(defun c-ts-mode--defun-valid-p (node)
|
||||||
"Return non-nil if NODE is a valid defun node.
|
"Return non-nil if NODE is a valid defun node.
|
||||||
Ie, NODE is not nested."
|
Ie, NODE is not nested."
|
||||||
(or (c-ts-mode--emacs-defun-p node)
|
(let ((top-level-p (lambda (node)
|
||||||
(not (or (and (member (treesit-node-type node)
|
(not (treesit-node-top-level
|
||||||
'("struct_specifier"
|
node (rx (or "function_definition"
|
||||||
"enum_specifier"
|
"type_definition"
|
||||||
"union_specifier"
|
"struct_specifier"
|
||||||
"declaration"))
|
"enum_specifier"
|
||||||
;; If NODE's type is one of the above, make sure it is
|
"union_specifier"
|
||||||
;; top-level.
|
"declaration")))))))
|
||||||
(treesit-node-top-level
|
(pcase (treesit-node-type node)
|
||||||
node (rx (or "function_definition"
|
;; The declaration part of a DEFUN.
|
||||||
"type_definition"
|
("expression_statement" (c-ts-mode--emacs-defun-p node))
|
||||||
"struct_specifier"
|
;; The body of a DEFUN.
|
||||||
"enum_specifier"
|
("compound_statement" (c-ts-mode--emacs-defun-body-p node))
|
||||||
"union_specifier"
|
;; If NODE's type is one of these three, make sure it is
|
||||||
"declaration"))))
|
;; top-level.
|
||||||
|
((or "struct_specifier"
|
||||||
(and (equal (treesit-node-type node) "declaration")
|
"enum_specifier"
|
||||||
;; If NODE is a declaration, make sure it is not a
|
"union_specifier")
|
||||||
;; function declaration.
|
(funcall top-level-p node))
|
||||||
(equal (treesit-node-type
|
;; If NODE is a declaration, make sure it's not a function
|
||||||
(treesit-node-child-by-field-name
|
;; declaration (we only want function_definition) and is a
|
||||||
node "declarator"))
|
;; top-level declaration.
|
||||||
"function_declarator"))))))
|
("declaration"
|
||||||
|
(and (not (equal (treesit-node-type
|
||||||
|
(treesit-node-child-by-field-name
|
||||||
|
node "declarator"))
|
||||||
|
"function_declarator"))
|
||||||
|
(funcall top-level-p node)))
|
||||||
|
;; Other types don't need further verification.
|
||||||
|
(_ t))))
|
||||||
|
|
||||||
(defun c-ts-mode--defun-for-class-in-imenu-p (node)
|
(defun c-ts-mode--defun-for-class-in-imenu-p (node)
|
||||||
"Check if NODE is a valid entry for the Class subindex.
|
"Check if NODE is a valid entry for the Class subindex.
|
||||||
|
@ -955,6 +962,11 @@ files using the DEFUN macro."
|
||||||
t)
|
t)
|
||||||
"DEFUN")))
|
"DEFUN")))
|
||||||
|
|
||||||
|
(defun c-ts-mode--emacs-defun-body-p (node)
|
||||||
|
"Return non-nil if NODE is the function body of a DEFUN."
|
||||||
|
(and (equal (treesit-node-type node) "compound_statement")
|
||||||
|
(c-ts-mode--emacs-defun-p (treesit-node-prev-sibling node))))
|
||||||
|
|
||||||
(defun c-ts-mode--emacs-defun-at-point (&optional range)
|
(defun c-ts-mode--emacs-defun-at-point (&optional range)
|
||||||
"Return the defun node at point.
|
"Return the defun node at point.
|
||||||
|
|
||||||
|
@ -969,31 +981,18 @@ function returns the declaration node.
|
||||||
If RANGE is non-nil, return (BEG . END) where BEG end END
|
If RANGE is non-nil, return (BEG . END) where BEG end END
|
||||||
encloses the whole defun. This is for when the entire defun
|
encloses the whole defun. This is for when the entire defun
|
||||||
is required, not just the declaration part for DEFUN."
|
is required, not just the declaration part for DEFUN."
|
||||||
(or (when-let ((node (treesit-defun-at-point)))
|
(when-let* ((node (treesit-defun-at-point))
|
||||||
(if range
|
(defun-range (cons (treesit-node-start node)
|
||||||
(cons (treesit-node-start node)
|
(treesit-node-end node))))
|
||||||
(treesit-node-end node))
|
;; Make some adjustment for DEFUN.
|
||||||
node))
|
(when c-ts-mode-emacs-sources-support
|
||||||
(and c-ts-mode-emacs-sources-support
|
(cond ((c-ts-mode--emacs-defun-body-p node)
|
||||||
(let ((candidate-1 ; For when point is in the DEFUN statement.
|
(setq node (treesit-node-prev-sibling node))
|
||||||
(treesit-node-prev-sibling
|
(setcar defun-range (treesit-node-start node)))
|
||||||
(treesit-node-top-level
|
((c-ts-mode--emacs-defun-p node)
|
||||||
(treesit-node-at (point))
|
(setcdr defun-range (treesit-node-end
|
||||||
"compound_statement")))
|
(treesit-node-next-sibling node))))))
|
||||||
(candidate-2 ; For when point is in the body.
|
(if range defun-range node)))
|
||||||
(treesit-node-top-level
|
|
||||||
(treesit-node-at (point))
|
|
||||||
"expression_statement")))
|
|
||||||
(when-let
|
|
||||||
((node (or (and (c-ts-mode--emacs-defun-p candidate-1)
|
|
||||||
candidate-1)
|
|
||||||
(and (c-ts-mode--emacs-defun-p candidate-2)
|
|
||||||
candidate-2))))
|
|
||||||
(if range
|
|
||||||
(cons (treesit-node-start node)
|
|
||||||
(treesit-node-end
|
|
||||||
(treesit-node-next-sibling node)))
|
|
||||||
node))))))
|
|
||||||
|
|
||||||
(defun c-ts-mode-indent-defun ()
|
(defun c-ts-mode-indent-defun ()
|
||||||
"Indent the current top-level declaration syntactically.
|
"Indent the current top-level declaration syntactically.
|
||||||
|
@ -1111,13 +1110,19 @@ BEG and END are described in `treesit-range-rules'."
|
||||||
|
|
||||||
;; Navigation.
|
;; Navigation.
|
||||||
(setq-local treesit-defun-type-regexp
|
(setq-local treesit-defun-type-regexp
|
||||||
(cons (regexp-opt '("function_definition"
|
(cons (regexp-opt (append
|
||||||
"type_definition"
|
'("function_definition"
|
||||||
"struct_specifier"
|
"type_definition"
|
||||||
"enum_specifier"
|
"struct_specifier"
|
||||||
"union_specifier"
|
"enum_specifier"
|
||||||
"class_specifier"
|
"union_specifier"
|
||||||
"namespace_definition"))
|
"class_specifier"
|
||||||
|
"namespace_definition")
|
||||||
|
(and c-ts-mode-emacs-sources-support
|
||||||
|
'(;; DEFUN.
|
||||||
|
"expression_statement"
|
||||||
|
;; DEFUN body.
|
||||||
|
"compound_statement"))))
|
||||||
#'c-ts-mode--defun-valid-p))
|
#'c-ts-mode--defun-valid-p))
|
||||||
(setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
|
(setq-local treesit-defun-skipper #'c-ts-mode--defun-skipper)
|
||||||
(setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
|
(setq-local treesit-defun-name-function #'c-ts-mode--defun-name)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue