]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix indentation for c-ts-mode (bug#61026)
authorYuan Fu <casouri@gmail.com>
Thu, 26 Jan 2023 07:47:27 +0000 (23:47 -0800)
committerYuan Fu <casouri@gmail.com>
Thu, 26 Jan 2023 07:47:27 +0000 (23:47 -0800)
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
test/lisp/progmodes/c-ts-mode-resources/indent.erts

index 95f9001e0d75c3824c591c11c601b03f6b678aa7..788c911f86b3d5c7329c4fd9b677893d108d055c 100644 (file)
@@ -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)
index b8524432d028d33f3006eead7ef555fa31f9aca5..67654404a7730a84f321223c11307f87f2fddc0f 100644 (file)
@@ -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)
 
 =-=