]> git.eshelyaron.com Git - emacs.git/commitdiff
Fix c-declaration-limits to return correct limits in all cases.
authorAlan Mackenzie <acm@muc.de>
Thu, 1 Sep 2016 18:06:22 +0000 (18:06 +0000)
committerAlan Mackenzie <acm@muc.de>
Thu, 1 Sep 2016 18:12:43 +0000 (18:12 +0000)
This function is the guts of c-indent-defun and c-mark-function.

In particular, when c-defun-tactic is nil, return a correct value rather than
always nil, and when it's 'go-outward, go through an intricate algorithm to
determine the requisite narrowing before the "top-level" defuns go to work.

* lisp/progmodes/cc-cmds.el (c-narrow-to-most-enclosing-decl-block): Enhance
to take additional optional parameter LEVEL, saying how many enclosing levels
of decl-block to narrow to.
(c-declaration-limits): Introduce algorithm to determine narrowing.  Use
c-where-wrt-to-brace-block to determine whether to go back to BOD to determine
lower bound.

lisp/progmodes/cc-cmds.el

index f0ad2942457623612071749b30732033596c0857..cdca67c698d7ddf84b3f1bfdba9d1d7a75bb36d9 100644 (file)
@@ -1501,15 +1501,24 @@ No indentation or other \"electric\" behavior is performed."
       (setq n (1- n))))
    n)
 
-(defun c-narrow-to-most-enclosing-decl-block (&optional inclusive)
+(defun c-narrow-to-most-enclosing-decl-block (&optional inclusive level)
   ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block),
   ;; i.e. something like namespace{} or extern{}, narrow to the insides of
   ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil,
-  ;; otherwise include the braces.  If the closing brace is missing,
-  ;; (point-max) is used instead.
+  ;; otherwise include the braces and the declaration which introduces them.
+  ;; If the closing brace is missing, (point-max) is used instead.  LEVEL, if
+  ;; non-nil, says narrow to the LEVELth decl-block outward, default value
+  ;; being 1.
   (let ((paren-state (c-parse-state))
        encl-decl)
-    (setq encl-decl (and paren-state (c-most-enclosing-decl-block paren-state)))
+    (setq level (or level 1))
+    (while (> level 0)
+      (setq encl-decl (c-most-enclosing-decl-block paren-state))
+      (if encl-decl
+         (progn
+           (while (> (c-pull-open-brace paren-state) encl-decl))
+           (setq level (1- level)))
+       (setq level 0)))
     (if encl-decl
        (save-excursion
          (narrow-to-region
@@ -1875,114 +1884,133 @@ with a brace block."
   ;; This function might do hidden buffer changes.
   (save-excursion
     (save-restriction
-      (when (eq c-defun-tactic 'go-outward)
-       (c-narrow-to-most-enclosing-decl-block t)  ; e.g. class, namespace
-       (or (save-restriction
-             (c-narrow-to-most-enclosing-decl-block nil)
-
-             ;; Note: Some code duplication in `c-beginning-of-defun' and
-             ;; `c-end-of-defun'.
-             (catch 'exit
-               (let ((start (point))
-                     (paren-state (c-parse-state))
-                     lim pos end-pos)
-                 (unless (c-safe
-                           (goto-char (c-least-enclosing-brace paren-state))
-                           ;; If we moved to the outermost enclosing paren
-                           ;; then we can use c-safe-position to set the
-                           ;; limit. Can't do that otherwise since the
-                           ;; earlier paren pair on paren-state might very
-                           ;; well be part of the declaration we should go
-                           ;; to.
-                           (setq lim (c-safe-position (point) paren-state))
-                           t)
-                   ;; At top level.  Make sure we aren't inside a literal.
-                   (setq pos (c-literal-start
-                              (c-safe-position (point) paren-state)))
-                   (if pos (goto-char pos)))
-
-                 (when (c-beginning-of-macro)
-                   (throw 'exit
-                          (cons (point)
-                                (save-excursion
-                                  (c-end-of-macro)
-                                  (forward-line 1)
-                                  (point)))))
-
-                 (setq pos (point))
-                 (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous)
-                           (= pos (point)))
-                   ;; We moved back over the previous defun.  Skip to the next
-                   ;; one.  Not using c-forward-syntactic-ws here since we
-                   ;; should not skip a macro.  We can also be directly after
-                   ;; the block in a `c-opt-block-decls-with-vars-key'
-                   ;; declaration, but then we won't move significantly far
-                   ;; here.
-                   (goto-char pos)
-                   (c-forward-comments)
-
-                   (when (and near (c-beginning-of-macro))
-                     (throw 'exit
-                            (cons (point)
-                                  (save-excursion
-                                    (c-end-of-macro)
-                                    (forward-line 1)
-                                    (point))))))
-
-                 (if (eobp) (throw 'exit nil))
-
-                 ;; Check if `c-beginning-of-decl-1' put us after the block in a
-                 ;; declaration that doesn't end there.  We're searching back and
-                 ;; forth over the block here, which can be expensive.
-                 (setq pos (point))
-                 (if (and c-opt-block-decls-with-vars-key
-                          (progn
-                            (c-backward-syntactic-ws)
-                            (eq (char-before) ?}))
-                          (eq (car (c-beginning-of-decl-1))
-                              'previous)
-                          (save-excursion
-                            (c-end-of-decl-1)
-                            (and (> (point) pos)
-                                 (setq end-pos (point)))))
-                     nil
-                   (goto-char pos))
-
-                 (if (and (not near) (> (point) start))
-                     nil
-
-                   ;; Try to be line oriented; position the limits at the
-                   ;; closest preceding boi, and after the next newline, that
-                   ;; isn't inside a comment, but if we hit a neighboring
-                   ;; declaration then we instead use the exact declaration
-                   ;; limit in that direction.
-                   (cons (progn
-                           (setq pos (point))
-                           (while (and (/= (point) (c-point 'boi))
-                                       (c-backward-single-comment)))
-                           (if (/= (point) (c-point 'boi))
-                               pos
-                             (point)))
-                         (progn
-                           (if end-pos
-                               (goto-char end-pos)
-                             (c-end-of-decl-1))
-                           (setq pos (point))
-                           (while (and (not (bolp))
-                                       (not (looking-at "\\s *$"))
-                                       (c-forward-single-comment)))
-                           (cond ((bolp)
-                                  (point))
-                                 ((looking-at "\\s *$")
-                                  (forward-line 1)
-                                  (point))
-                                 (t
-                                  pos))))))))
-           (and (not near)
-                (goto-char (point-min))
-                (c-forward-decl-or-cast-1 -1 nil nil)
-                (eq (char-after) ?\{)
-                (cons (point-min) (point-max))))))))
+      (let ((start (point))
+           (paren-state (c-parse-state))
+           lim pos end-pos encl-decl-block where)
+       ;; Narrow enclosing brace blocks out, as required by the values of
+       ;; `c-defun-tactic', `near', and the position of point.
+       (when (eq c-defun-tactic 'go-outward)
+         (let ((bounds
+                (save-restriction
+                  (if (and (not (save-excursion (c-beginning-of-macro)))
+                           (save-restriction
+                             (c-narrow-to-most-enclosing-decl-block)
+                             (memq (c-where-wrt-brace-construct)
+                                   '(at-function-end outwith-function)))
+                           (not near))
+                      (c-narrow-to-most-enclosing-decl-block nil 2)
+                    (c-narrow-to-most-enclosing-decl-block))
+                  (cons (point-min) (point-max)))))
+           (narrow-to-region (car bounds) (cdr bounds))))
+       (setq paren-state (c-parse-state))
+
+       (or
+        ;; Note: Some code duplication in `c-beginning-of-defun' and
+        ;; `c-end-of-defun'.
+        (catch 'exit
+          (unless (c-safe
+                    (goto-char (c-least-enclosing-brace paren-state))
+                    ;; If we moved to the outermost enclosing paren
+                    ;; then we can use c-safe-position to set the
+                    ;; limit. Can't do that otherwise since the
+                    ;; earlier paren pair on paren-state might very
+                    ;; well be part of the declaration we should go
+                    ;; to.
+                    (setq lim (c-safe-position (point) paren-state))
+                    t)
+            ;; At top level.  Make sure we aren't inside a literal.
+            (setq pos (c-literal-start
+                       (c-safe-position (point) paren-state)))
+            (if pos (goto-char pos)))
+
+          (when (c-beginning-of-macro)
+            (throw 'exit
+                   (cons (point)
+                         (save-excursion
+                           (c-end-of-macro)
+                           (forward-line 1)
+                           (point)))))
+
+          (setq pos (point))
+          (setq where (and (not (save-excursion (c-beginning-of-macro)))
+                           (c-where-wrt-brace-construct)))
+          (when (and (not (eq where 'at-header))
+                     (or (and near
+                              (memq where
+                                    '(at-function-end outwith-function)))
+                         (eq (car (c-beginning-of-decl-1 lim)) 'previous)
+                         (= pos (point))))
+            ;; We moved back over the previous defun.  Skip to the next
+            ;; one.  Not using c-forward-syntactic-ws here since we
+            ;; should not skip a macro.  We can also be directly after
+            ;; the block in a `c-opt-block-decls-with-vars-key'
+            ;; declaration, but then we won't move significantly far
+            ;; here.
+            (goto-char pos)
+            (c-forward-comments)
+
+            (when (and near (c-beginning-of-macro))
+              (throw 'exit
+                     (cons (point)
+                           (save-excursion
+                             (c-end-of-macro)
+                             (forward-line 1)
+                             (point))))))
+
+          (if (eobp) (throw 'exit nil))
+
+          ;; Check if `c-beginning-of-decl-1' put us after the block in a
+          ;; declaration that doesn't end there.  We're searching back and
+          ;; forth over the block here, which can be expensive.
+          (setq pos (point))
+          (if (and c-opt-block-decls-with-vars-key
+                   (progn
+                     (c-backward-syntactic-ws)
+                     (eq (char-before) ?}))
+                   (eq (car (c-beginning-of-decl-1))
+                       'previous)
+                   (save-excursion
+                     (c-end-of-decl-1)
+                     (and (> (point) pos)
+                          (setq end-pos (point)))))
+              nil
+            (goto-char pos))
+
+          (if (and (not near) (> (point) start))
+              nil
+
+            ;; Try to be line oriented; position the limits at the
+            ;; closest preceding boi, and after the next newline, that
+            ;; isn't inside a comment, but if we hit a neighboring
+            ;; declaration then we instead use the exact declaration
+            ;; limit in that direction.
+            (cons (progn
+                    (setq pos (point))
+                    (while (and (/= (point) (c-point 'boi))
+                                (c-backward-single-comment)))
+                    (if (/= (point) (c-point 'boi))
+                        pos
+                      (point)))
+                  (progn
+                    (if end-pos
+                        (goto-char end-pos)
+                      (c-end-of-decl-1))
+                    (setq pos (point))
+                    (while (and (not (bolp))
+                                (not (looking-at "\\s *$"))
+                                (c-forward-single-comment)))
+                    (cond ((bolp)
+                           (point))
+                          ((looking-at "\\s *$")
+                           (forward-line 1)
+                           (point))
+                          (t
+                           pos))))))
+        (and (not near)
+             (goto-char (point-min))
+             (c-forward-decl-or-cast-1 -1 nil nil)
+             (eq (char-after) ?\{)
+             (cons (point-min) (point-max))))))))
 
 (defun c-mark-function ()
   "Put mark at end of the current top-level declaration or macro, point at beginning.