diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 21fb0ca9e53..677273afaac 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -321,7 +321,8 @@ PARENT and BOL are like other anchor functions." (treesit-node-parent prev-sibling) t))) ;; If the start of the previous sibling isn't at the ;; beginning of a line, something's probably not quite - ;; right, go a step further. + ;; right, go a step further. (E.g., comment after a + ;; statement.) (_ (goto-char (treesit-node-start prev-sibling)) (if (looking-back (rx bol (* whitespace)) (line-beginning-position)) @@ -364,6 +365,19 @@ PARENT, BOL, ARGS are the same as other anchor functions." (back-to-indentation) (looking-at-p regexp)))) +(defun c-ts-mode--first-sibling (node parent &rest _) + "Matches when NODE is the \"first sibling\". +\"First sibling\" is defined as: the first child node of PARENT +such that it's on its own line. NODE is the node to match and +PARENT is its parent." + (let ((prev-sibling (treesit-node-prev-sibling node t))) + (or (null prev-sibling) + (save-excursion + (goto-char (treesit-node-start prev-sibling)) + (<= (line-beginning-position) + (treesit-node-start parent) + (line-end-position)))))) + (defun c-ts-mode--indent-styles (mode) "Indent rules supported by `c-ts-mode'. MODE is either `c' or `cpp'." @@ -457,7 +471,11 @@ MODE is either `c' or `cpp'." ((parent-is "field_declaration_list") c-ts-mode--anchor-prev-sibling 0) ;; Statement in {} blocks. - ((or (match nil "compound_statement" nil 1 1) + ((or (and (parent-is "compound_statement") + ;; If the previous sibling(s) are not on their + ;; own line, indent as if this node is the first + ;; sibling (Bug#67357) + c-ts-mode--first-sibling) (match null "compound_statement")) standalone-parent c-ts-mode-indent-offset) ((parent-is "compound_statement") c-ts-mode--anchor-prev-sibling 0) @@ -470,6 +488,7 @@ MODE is either `c' or `cpp'." ((parent-is "if_statement") standalone-parent c-ts-mode-indent-offset) ((parent-is "else_clause") standalone-parent c-ts-mode-indent-offset) ((parent-is "for_statement") standalone-parent c-ts-mode-indent-offset) + ((match "while" "do_statement") parent-bol 0) ; (do_statement "while") ((parent-is "while_statement") standalone-parent c-ts-mode-indent-offset) ((parent-is "do_statement") standalone-parent c-ts-mode-indent-offset) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index bac76fb7378..2fd26d75844 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -330,7 +330,7 @@ label: Name: Bracket-less Block-Statement (Linux Style) (bug#61026) -=-=-= +=-= int main() { while (true) if (true) { @@ -351,6 +351,8 @@ int main() { if (true) { puts ("Hello"); } + else + puts("Hello"); } =-=-= @@ -399,6 +401,34 @@ void foo( } =-=-= +Name: Block-Statement where first siblings are comments (Linux Style) + +=-= +int main() { + while (true) { /* foo */ + if (true) { // bar + puts ("Hello"); + } + } + for (;;) { // 1. fooo + /* 2. baaa */ + /* 3. rrr */ + if (true) + // 2. baaa + puts ("Hello"); + } + if (1) { // 1 + /* + * 2 + */ + if (1) /*3*/ { + /* 4 */ + puts("Hello"); + } + } +} +=-=-= + Name: Initializer List (Linux Style) (Bug#61398) =-= @@ -498,3 +528,19 @@ main (void) { | =-=-= + +Code: + (lambda () + (c-ts-mode) + (setq-local indent-tabs-mode nil) + (goto-line 3) + (indent-for-tab-command)) + +Name: Block-Statement where previous sibling is comment + +=-= +int main() { + puts ("Hello"); // unusual indent and has trailing comment. + return true; // Should align with previous non-comment sibling (rather than one level up against parent). +} +=-=-=