diff options
| author | Alan Mackenzie | 2016-09-01 18:06:22 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2016-09-01 18:12:43 +0000 |
| commit | dda2d6a311fd2a7096176e240e4e81b423eaa8e2 (patch) | |
| tree | 6c7f43e3058c8642f8c51a9ef1ad5d0f95207a75 | |
| parent | 0c94b847082bf915137c4270b8009ad599681ccf (diff) | |
| download | emacs-dda2d6a311fd2a7096176e240e4e81b423eaa8e2.tar.gz emacs-dda2d6a311fd2a7096176e240e4e81b423eaa8e2.zip | |
Fix c-declaration-limits to return correct limits in all cases.
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.
| -rw-r--r-- | lisp/progmodes/cc-cmds.el | 252 |
1 files changed, 140 insertions, 112 deletions
diff --git a/lisp/progmodes/cc-cmds.el b/lisp/progmodes/cc-cmds.el index f0ad2942457..cdca67c698d 100644 --- a/lisp/progmodes/cc-cmds.el +++ b/lisp/progmodes/cc-cmds.el | |||
| @@ -1501,15 +1501,24 @@ No indentation or other \"electric\" behavior is performed." | |||
| 1501 | (setq n (1- n)))) | 1501 | (setq n (1- n)))) |
| 1502 | n) | 1502 | n) |
| 1503 | 1503 | ||
| 1504 | (defun c-narrow-to-most-enclosing-decl-block (&optional inclusive) | 1504 | (defun c-narrow-to-most-enclosing-decl-block (&optional inclusive level) |
| 1505 | ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block), | 1505 | ;; If we are inside a decl-block (in the sense of c-looking-at-decl-block), |
| 1506 | ;; i.e. something like namespace{} or extern{}, narrow to the insides of | 1506 | ;; i.e. something like namespace{} or extern{}, narrow to the insides of |
| 1507 | ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil, | 1507 | ;; that block (NOT including the enclosing braces) if INCLUSIVE is nil, |
| 1508 | ;; otherwise include the braces. If the closing brace is missing, | 1508 | ;; otherwise include the braces and the declaration which introduces them. |
| 1509 | ;; (point-max) is used instead. | 1509 | ;; If the closing brace is missing, (point-max) is used instead. LEVEL, if |
| 1510 | ;; non-nil, says narrow to the LEVELth decl-block outward, default value | ||
| 1511 | ;; being 1. | ||
| 1510 | (let ((paren-state (c-parse-state)) | 1512 | (let ((paren-state (c-parse-state)) |
| 1511 | encl-decl) | 1513 | encl-decl) |
| 1512 | (setq encl-decl (and paren-state (c-most-enclosing-decl-block paren-state))) | 1514 | (setq level (or level 1)) |
| 1515 | (while (> level 0) | ||
| 1516 | (setq encl-decl (c-most-enclosing-decl-block paren-state)) | ||
| 1517 | (if encl-decl | ||
| 1518 | (progn | ||
| 1519 | (while (> (c-pull-open-brace paren-state) encl-decl)) | ||
| 1520 | (setq level (1- level))) | ||
| 1521 | (setq level 0))) | ||
| 1513 | (if encl-decl | 1522 | (if encl-decl |
| 1514 | (save-excursion | 1523 | (save-excursion |
| 1515 | (narrow-to-region | 1524 | (narrow-to-region |
| @@ -1875,114 +1884,133 @@ with a brace block." | |||
| 1875 | ;; This function might do hidden buffer changes. | 1884 | ;; This function might do hidden buffer changes. |
| 1876 | (save-excursion | 1885 | (save-excursion |
| 1877 | (save-restriction | 1886 | (save-restriction |
| 1878 | (when (eq c-defun-tactic 'go-outward) | 1887 | (let ((start (point)) |
| 1879 | (c-narrow-to-most-enclosing-decl-block t) ; e.g. class, namespace | 1888 | (paren-state (c-parse-state)) |
| 1880 | (or (save-restriction | 1889 | lim pos end-pos encl-decl-block where) |
| 1881 | (c-narrow-to-most-enclosing-decl-block nil) | 1890 | ;; Narrow enclosing brace blocks out, as required by the values of |
| 1882 | 1891 | ;; `c-defun-tactic', `near', and the position of point. | |
| 1883 | ;; Note: Some code duplication in `c-beginning-of-defun' and | 1892 | (when (eq c-defun-tactic 'go-outward) |
| 1884 | ;; `c-end-of-defun'. | 1893 | (let ((bounds |
| 1885 | (catch 'exit | 1894 | (save-restriction |
| 1886 | (let ((start (point)) | 1895 | (if (and (not (save-excursion (c-beginning-of-macro))) |
| 1887 | (paren-state (c-parse-state)) | 1896 | (save-restriction |
| 1888 | lim pos end-pos) | 1897 | (c-narrow-to-most-enclosing-decl-block) |
| 1889 | (unless (c-safe | 1898 | (memq (c-where-wrt-brace-construct) |
| 1890 | (goto-char (c-least-enclosing-brace paren-state)) | 1899 | '(at-function-end outwith-function))) |
| 1891 | ;; If we moved to the outermost enclosing paren | 1900 | (not near)) |
| 1892 | ;; then we can use c-safe-position to set the | 1901 | (c-narrow-to-most-enclosing-decl-block nil 2) |
| 1893 | ;; limit. Can't do that otherwise since the | 1902 | (c-narrow-to-most-enclosing-decl-block)) |
| 1894 | ;; earlier paren pair on paren-state might very | 1903 | (cons (point-min) (point-max))))) |
| 1895 | ;; well be part of the declaration we should go | 1904 | (narrow-to-region (car bounds) (cdr bounds)))) |
| 1896 | ;; to. | 1905 | (setq paren-state (c-parse-state)) |
| 1897 | (setq lim (c-safe-position (point) paren-state)) | 1906 | |
| 1898 | t) | 1907 | (or |
| 1899 | ;; At top level. Make sure we aren't inside a literal. | 1908 | ;; Note: Some code duplication in `c-beginning-of-defun' and |
| 1900 | (setq pos (c-literal-start | 1909 | ;; `c-end-of-defun'. |
| 1901 | (c-safe-position (point) paren-state))) | 1910 | (catch 'exit |
| 1902 | (if pos (goto-char pos))) | 1911 | (unless (c-safe |
| 1903 | 1912 | (goto-char (c-least-enclosing-brace paren-state)) | |
| 1904 | (when (c-beginning-of-macro) | 1913 | ;; If we moved to the outermost enclosing paren |
| 1905 | (throw 'exit | 1914 | ;; then we can use c-safe-position to set the |
| 1906 | (cons (point) | 1915 | ;; limit. Can't do that otherwise since the |
| 1907 | (save-excursion | 1916 | ;; earlier paren pair on paren-state might very |
| 1908 | (c-end-of-macro) | 1917 | ;; well be part of the declaration we should go |
| 1909 | (forward-line 1) | 1918 | ;; to. |
| 1910 | (point))))) | 1919 | (setq lim (c-safe-position (point) paren-state)) |
| 1911 | 1920 | t) | |
| 1912 | (setq pos (point)) | 1921 | ;; At top level. Make sure we aren't inside a literal. |
| 1913 | (when (or (eq (car (c-beginning-of-decl-1 lim)) 'previous) | 1922 | (setq pos (c-literal-start |
| 1914 | (= pos (point))) | 1923 | (c-safe-position (point) paren-state))) |
| 1915 | ;; We moved back over the previous defun. Skip to the next | 1924 | (if pos (goto-char pos))) |
| 1916 | ;; one. Not using c-forward-syntactic-ws here since we | 1925 | |
| 1917 | ;; should not skip a macro. We can also be directly after | 1926 | (when (c-beginning-of-macro) |
| 1918 | ;; the block in a `c-opt-block-decls-with-vars-key' | 1927 | (throw 'exit |
| 1919 | ;; declaration, but then we won't move significantly far | 1928 | (cons (point) |
| 1920 | ;; here. | 1929 | (save-excursion |
| 1921 | (goto-char pos) | 1930 | (c-end-of-macro) |
| 1922 | (c-forward-comments) | 1931 | (forward-line 1) |
| 1923 | 1932 | (point))))) | |
| 1924 | (when (and near (c-beginning-of-macro)) | 1933 | |
| 1925 | (throw 'exit | 1934 | (setq pos (point)) |
| 1926 | (cons (point) | 1935 | (setq where (and (not (save-excursion (c-beginning-of-macro))) |
| 1927 | (save-excursion | 1936 | (c-where-wrt-brace-construct))) |
| 1928 | (c-end-of-macro) | 1937 | (when (and (not (eq where 'at-header)) |
| 1929 | (forward-line 1) | 1938 | (or (and near |
| 1930 | (point)))))) | 1939 | (memq where |
| 1931 | 1940 | '(at-function-end outwith-function))) | |
| 1932 | (if (eobp) (throw 'exit nil)) | 1941 | (eq (car (c-beginning-of-decl-1 lim)) 'previous) |
| 1933 | 1942 | (= pos (point)))) | |
| 1934 | ;; Check if `c-beginning-of-decl-1' put us after the block in a | 1943 | ;; We moved back over the previous defun. Skip to the next |
| 1935 | ;; declaration that doesn't end there. We're searching back and | 1944 | ;; one. Not using c-forward-syntactic-ws here since we |
| 1936 | ;; forth over the block here, which can be expensive. | 1945 | ;; should not skip a macro. We can also be directly after |
| 1937 | (setq pos (point)) | 1946 | ;; the block in a `c-opt-block-decls-with-vars-key' |
| 1938 | (if (and c-opt-block-decls-with-vars-key | 1947 | ;; declaration, but then we won't move significantly far |
| 1939 | (progn | 1948 | ;; here. |
| 1940 | (c-backward-syntactic-ws) | 1949 | (goto-char pos) |
| 1941 | (eq (char-before) ?})) | 1950 | (c-forward-comments) |
| 1942 | (eq (car (c-beginning-of-decl-1)) | 1951 | |
| 1943 | 'previous) | 1952 | (when (and near (c-beginning-of-macro)) |
| 1944 | (save-excursion | 1953 | (throw 'exit |
| 1945 | (c-end-of-decl-1) | 1954 | (cons (point) |
| 1946 | (and (> (point) pos) | 1955 | (save-excursion |
| 1947 | (setq end-pos (point))))) | 1956 | (c-end-of-macro) |
| 1948 | nil | 1957 | (forward-line 1) |
| 1949 | (goto-char pos)) | 1958 | (point)))))) |
| 1950 | 1959 | ||
| 1951 | (if (and (not near) (> (point) start)) | 1960 | (if (eobp) (throw 'exit nil)) |
| 1952 | nil | 1961 | |
| 1953 | 1962 | ;; Check if `c-beginning-of-decl-1' put us after the block in a | |
| 1954 | ;; Try to be line oriented; position the limits at the | 1963 | ;; declaration that doesn't end there. We're searching back and |
| 1955 | ;; closest preceding boi, and after the next newline, that | 1964 | ;; forth over the block here, which can be expensive. |
| 1956 | ;; isn't inside a comment, but if we hit a neighboring | 1965 | (setq pos (point)) |
| 1957 | ;; declaration then we instead use the exact declaration | 1966 | (if (and c-opt-block-decls-with-vars-key |
| 1958 | ;; limit in that direction. | 1967 | (progn |
| 1959 | (cons (progn | 1968 | (c-backward-syntactic-ws) |
| 1960 | (setq pos (point)) | 1969 | (eq (char-before) ?})) |
| 1961 | (while (and (/= (point) (c-point 'boi)) | 1970 | (eq (car (c-beginning-of-decl-1)) |
| 1962 | (c-backward-single-comment))) | 1971 | 'previous) |
| 1963 | (if (/= (point) (c-point 'boi)) | 1972 | (save-excursion |
| 1964 | pos | 1973 | (c-end-of-decl-1) |
| 1965 | (point))) | 1974 | (and (> (point) pos) |
| 1966 | (progn | 1975 | (setq end-pos (point))))) |
| 1967 | (if end-pos | 1976 | nil |
| 1968 | (goto-char end-pos) | 1977 | (goto-char pos)) |
| 1969 | (c-end-of-decl-1)) | 1978 | |
| 1970 | (setq pos (point)) | 1979 | (if (and (not near) (> (point) start)) |
| 1971 | (while (and (not (bolp)) | 1980 | nil |
| 1972 | (not (looking-at "\\s *$")) | 1981 | |
| 1973 | (c-forward-single-comment))) | 1982 | ;; Try to be line oriented; position the limits at the |
| 1974 | (cond ((bolp) | 1983 | ;; closest preceding boi, and after the next newline, that |
| 1975 | (point)) | 1984 | ;; isn't inside a comment, but if we hit a neighboring |
| 1976 | ((looking-at "\\s *$") | 1985 | ;; declaration then we instead use the exact declaration |
| 1977 | (forward-line 1) | 1986 | ;; limit in that direction. |
| 1978 | (point)) | 1987 | (cons (progn |
| 1979 | (t | 1988 | (setq pos (point)) |
| 1980 | pos)))))))) | 1989 | (while (and (/= (point) (c-point 'boi)) |
| 1981 | (and (not near) | 1990 | (c-backward-single-comment))) |
| 1982 | (goto-char (point-min)) | 1991 | (if (/= (point) (c-point 'boi)) |
| 1983 | (c-forward-decl-or-cast-1 -1 nil nil) | 1992 | pos |
| 1984 | (eq (char-after) ?\{) | 1993 | (point))) |
| 1985 | (cons (point-min) (point-max)))))))) | 1994 | (progn |
| 1995 | (if end-pos | ||
| 1996 | (goto-char end-pos) | ||
| 1997 | (c-end-of-decl-1)) | ||
| 1998 | (setq pos (point)) | ||
| 1999 | (while (and (not (bolp)) | ||
| 2000 | (not (looking-at "\\s *$")) | ||
| 2001 | (c-forward-single-comment))) | ||
| 2002 | (cond ((bolp) | ||
| 2003 | (point)) | ||
| 2004 | ((looking-at "\\s *$") | ||
| 2005 | (forward-line 1) | ||
| 2006 | (point)) | ||
| 2007 | (t | ||
| 2008 | pos)))))) | ||
| 2009 | (and (not near) | ||
| 2010 | (goto-char (point-min)) | ||
| 2011 | (c-forward-decl-or-cast-1 -1 nil nil) | ||
| 2012 | (eq (char-after) ?\{) | ||
| 2013 | (cons (point-min) (point-max)))))))) | ||
| 1986 | 2014 | ||
| 1987 | (defun c-mark-function () | 2015 | (defun c-mark-function () |
| 1988 | "Put mark at end of the current top-level declaration or macro, point at beginning. | 2016 | "Put mark at end of the current top-level declaration or macro, point at beginning. |