From cdf74254ffa2c53612f6d985e3774b51233fbd49 Mon Sep 17 00:00:00 2001 From: Yuan Fu Date: Wed, 25 Jan 2023 23:47:27 -0800 Subject: [PATCH] Fix indentation for c-ts-mode (bug#61026) Fix indentation for things like while (true) if (true) { puts ("Hello"); } Note that the outer while loop omits brackets. * lisp/progmodes/c-ts-mode.el: (c-ts-mode--statement-offset-post-processr): New variable. (c-ts-mode--statement-offset): Use the new function. (c-ts-mode--fix-bracketless-indent): New function. (c-ts-base-mode): Use the new function. * test/lisp/progmodes/c-ts-mode-resources/indent.erts: New tests. --- lisp/progmodes/c-ts-mode.el | 32 +++++++++++- .../progmodes/c-ts-mode-resources/indent.erts | 52 +++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) diff --git a/lisp/progmodes/c-ts-mode.el b/lisp/progmodes/c-ts-mode.el index 95f9001e0d7..788c911f86b 100644 --- a/lisp/progmodes/c-ts-mode.el +++ b/lisp/progmodes/c-ts-mode.el @@ -279,6 +279,19 @@ NODE should be a labeled_statement." "enumerator_list")) "Regexp matching types of block nodes (i.e., {} blocks).") +(defvar c-ts-mode--statement-offset-post-processr nil + "A functions that makes adjustments to `c-ts-mode--statement-offset'. + +This is a function that takes two arguments, the current indent +level and the current node, and returns a new level. + +When `c-ts-mode--statement-offset' runs and go up the parse tree, +it increments the indent level when some condition are met in +each level. At each level, after (possibly) incrementing the +offset, it calls this function, passing it the current indent +level and the current node, and use the return value as the new +indent level.") + (defun c-ts-mode--statement-offset (node parent &rest _) "This anchor is used for children of a statement inside a block. @@ -319,9 +332,24 @@ PARENT is NODE's parent." ;; Add a level. ((looking-back (rx bol (* whitespace)) (line-beginning-position)) - (cl-incf level)))))) + (cl-incf level))))) + (when c-ts-mode--statement-offset-post-processr + (setq level (funcall c-ts-mode--statement-offset-post-processr + level node)))) (* level c-ts-mode-indent-offset))) +(defun c-ts-mode--fix-bracketless-indent (level node) + "Takes LEVEL and NODE and returns adjusted LEVEL. +This fixes indentation for cases shown in bug#61026. Basically +in C/C++, constructs like if, for, while sometimes don't have +bracket." + (if (and (not (equal (treesit-node-type node) "compound_statement")) + (member (treesit-node-type (treesit-node-parent node)) + '("if_statement" "while_statement" "do_statement" + "for_statement"))) + (1+ level) + level)) + (defun c-ts-mode--close-bracket-offset (node parent &rest _) "Offset for the closing bracket, NODE. It's basically one level less that the statements in the block. @@ -758,6 +786,8 @@ the semicolon. This function skips the semicolon." ;; Indent. (when (eq c-ts-mode-indent-style 'linux) (setq-local indent-tabs-mode t)) + (setq-local c-ts-mode--statement-offset-post-processr + #'c-ts-mode--fix-bracketless-indent) ;; Comment (c-ts-common-comment-setup) diff --git a/test/lisp/progmodes/c-ts-mode-resources/indent.erts b/test/lisp/progmodes/c-ts-mode-resources/indent.erts index b8524432d02..67654404a77 100644 --- a/test/lisp/progmodes/c-ts-mode-resources/indent.erts +++ b/test/lisp/progmodes/c-ts-mode-resources/indent.erts @@ -105,6 +105,58 @@ main (int argc, } =-=-= +Name: Bracket-less Block-Statement (GNU Style) (bug#61026) + +=-= +int main() { + while (true) + if (true) + { + puts ("Hello"); + } + for (int i=0; i<5; i++) + if (true) + { + puts ("Hello"); + } + do + if (true) + { + puts ("Hello"); + } + while (true); + if (true) + if (true) + { + puts ("Hello"); + } +} +=-=-= + +Name: Bracket-less Block-Statement (Linux Style) (bug#61026) + +=-=-= +int main() { + while (true) + if (true) { + puts ("Hello"); + } + for (int i=0; i<5; i++) + if (true) { + puts ("Hello"); + } + do + if (true) { + puts ("Hello"); + } + while (true); + if (true) + if (true) { + puts ("Hello"); + } +} +=-=-= + Name: Multiline Parameter List (bug#60398) =-= -- 2.39.2