diff options
| author | Alan Mackenzie | 2017-01-11 18:25:39 +0000 |
|---|---|---|
| committer | Alan Mackenzie | 2017-01-11 18:25:39 +0000 |
| commit | 6463b85aeb67326acda340fbaad3e481e62120c0 (patch) | |
| tree | 888ef48e1defcf0c83acc651fc6db95bb3ea22f8 /lisp | |
| parent | 3a6df2d6043d32dd9a1864c87de8d99e9739a7e4 (diff) | |
| download | emacs-6463b85aeb67326acda340fbaad3e481e62120c0.tar.gz emacs-6463b85aeb67326acda340fbaad3e481e62120c0.zip | |
Handle syntactic WS cache properties more accurately at buffer changes.
This fixes bug #25362.
* lisp/progmodes/cc-engine.el (c-sws-lit-type, c-sws-lit-limits)
(c-invalidate-sws-region-before, c-invalidate-sws-region-after-del)
(c-invalidate-sws-region-after-ins): New variables and functions.
(c-invalidate-sws-region-after): Change from a defsubst to a defun.
Also pass
it the standard OLD-LEN argument. Call both
c-invalidate-sws-region-after-{ins,del} to check for "dangerous" WS
cache
properties.
* lisp/progmodes/cc-langs.el (c-block-comment-ender-regexp): New language
variable.
* lisp/progmodes/cc-mode.el (c-before-change): Call
c-invalidate-sws-region-before.
(c-after-change): Pass old-len to c-invalidate-sws-region-after.
Diffstat (limited to 'lisp')
| -rw-r--r-- | lisp/progmodes/cc-engine.el | 153 | ||||
| -rw-r--r-- | lisp/progmodes/cc-langs.el | 9 | ||||
| -rw-r--r-- | lisp/progmodes/cc-mode.el | 3 |
3 files changed, 128 insertions, 37 deletions
diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index a5d25880744..3077e0085d3 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el | |||
| @@ -1708,46 +1708,127 @@ comment at the start of cc-engine.el for more info." | |||
| 1708 | `((c-debug-remove-face beg end 'c-debug-is-sws-face) | 1708 | `((c-debug-remove-face beg end 'c-debug-is-sws-face) |
| 1709 | (c-debug-remove-face beg end 'c-debug-in-sws-face))))) | 1709 | (c-debug-remove-face beg end 'c-debug-in-sws-face))))) |
| 1710 | 1710 | ||
| 1711 | (defsubst c-invalidate-sws-region-after (beg end) | 1711 | ;; The type of literal position `end' is in in a `before-change-functions' |
| 1712 | ;; Called from `after-change-functions'. Note that if | 1712 | ;; function - one of `c', `c++', `pound', or nil (but NOT `string'). |
| 1713 | ;; `c-forward-sws' or `c-backward-sws' are used outside | 1713 | (defvar c-sws-lit-type nil) |
| 1714 | ;; A cons (START . STOP) of the bounds of the comment or CPP construct | ||
| 1715 | ;; enclosing END, if any, else nil. | ||
| 1716 | (defvar c-sws-lit-limits nil) | ||
| 1717 | |||
| 1718 | (defun c-invalidate-sws-region-before (end) | ||
| 1719 | ;; Called from c-before-change. END is the end of the change region, the | ||
| 1720 | ;; standard parameter given to all before-change-functions. | ||
| 1721 | ;; | ||
| 1722 | ;; Note whether END is inside a comment or CPP construct, and if so note its | ||
| 1723 | ;; bounds in `c-sws-lit-limits' and type in `c-sws-lit-type'. | ||
| 1724 | (save-excursion | ||
| 1725 | (goto-char end) | ||
| 1726 | (let* ((limits (c-literal-limits)) | ||
| 1727 | (lit-type (c-literal-type limits))) | ||
| 1728 | (cond | ||
| 1729 | ((memq lit-type '(c c++)) | ||
| 1730 | (setq c-sws-lit-type lit-type | ||
| 1731 | c-sws-lit-limits limits)) | ||
| 1732 | ((c-beginning-of-macro) | ||
| 1733 | (setq c-sws-lit-type 'pound | ||
| 1734 | c-sws-lit-limits (cons (point) | ||
| 1735 | (progn (c-end-of-macro) (point))))) | ||
| 1736 | (t (setq c-sws-lit-type nil | ||
| 1737 | c-sws-lit-limits nil)))))) | ||
| 1738 | |||
| 1739 | (defun c-invalidate-sws-region-after-del (beg end old-len) | ||
| 1740 | ;; Text has been deleted, OLD-LEN characters of it starting from position | ||
| 1741 | ;; BEG. END is typically eq to BEG. Should there have been a comment or | ||
| 1742 | ;; CPP construct open at END before the deletion, check whether this | ||
| 1743 | ;; deletion deleted or "damaged" its opening delimiter. If so, return the | ||
| 1744 | ;; current position of where the construct ended, otherwise return nil. | ||
| 1745 | (when c-sws-lit-limits | ||
| 1746 | (setcdr c-sws-lit-limits (- (cdr c-sws-lit-limits) old-len)) | ||
| 1747 | (if (and (< beg (+ (car c-sws-lit-limits) 2)) ; A lazy assumption that | ||
| 1748 | ; comment delimiters are 2 | ||
| 1749 | ; chars long. | ||
| 1750 | (or (get-text-property end 'c-in-sws) | ||
| 1751 | (next-single-property-change end 'c-in-sws nil | ||
| 1752 | (cdr c-sws-lit-limits)) | ||
| 1753 | (get-text-property end 'c-is-sws) | ||
| 1754 | (next-single-property-change end 'c-is-sws nil | ||
| 1755 | (cdr c-sws-lit-limits)))) | ||
| 1756 | (cdr c-sws-lit-limits)))) | ||
| 1757 | |||
| 1758 | (defun c-invalidate-sws-region-after-ins (end) | ||
| 1759 | ;; Text has been inserted, ending at buffer position END. Should there be a | ||
| 1760 | ;; literal or CPP construct open at END, check whether there are `c-in-sws' | ||
| 1761 | ;; or `c-is-sws' text properties inside this literal. If there are, return | ||
| 1762 | ;; the buffer position of the end of the literal, else return nil. | ||
| 1763 | (save-excursion | ||
| 1764 | (let* ((limits (c-literal-limits)) | ||
| 1765 | (lit-type (c-literal-type limits))) | ||
| 1766 | (goto-char end) | ||
| 1767 | (when (and (not (memq lit-type '(c c++))) | ||
| 1768 | (c-beginning-of-macro)) | ||
| 1769 | (setq lit-type 'pound | ||
| 1770 | limits (cons (point) | ||
| 1771 | (progn (c-end-of-macro) (point))))) | ||
| 1772 | (when (memq lit-type '(c c++ pound)) | ||
| 1773 | (let ((next-in (next-single-property-change (car limits) 'c-in-sws | ||
| 1774 | nil (cdr limits))) | ||
| 1775 | (next-is (next-single-property-change (car limits) 'c-is-sws | ||
| 1776 | nil (cdr limits)))) | ||
| 1777 | (and (or next-in next-is) | ||
| 1778 | (cdr limits))))))) | ||
| 1779 | |||
| 1780 | (defun c-invalidate-sws-region-after (beg end old-len) | ||
| 1781 | ;; Called from `after-change-functions'. Remove any stale `c-in-sws' or | ||
| 1782 | ;; `c-is-sws' text properties from the vicinity of the change. BEG, END, | ||
| 1783 | ;; and OLD-LEN are the standard arguments given to after-change functions. | ||
| 1784 | ;; | ||
| 1785 | ;; Note that if `c-forward-sws' or `c-backward-sws' are used outside | ||
| 1714 | ;; `c-save-buffer-state' or similar then this will remove the cache | 1786 | ;; `c-save-buffer-state' or similar then this will remove the cache |
| 1715 | ;; properties right after they're added. | 1787 | ;; properties right after they're added. |
| 1716 | ;; | 1788 | ;; |
| 1717 | ;; This function does hidden buffer changes. | 1789 | ;; This function does hidden buffer changes. |
| 1718 | 1790 | (let ((del-end | |
| 1719 | (save-excursion | 1791 | (and (> old-len 0) |
| 1720 | ;; Adjust the end to remove the properties in any following simple | 1792 | (c-invalidate-sws-region-after-del beg end old-len))) |
| 1721 | ;; ws up to and including the next line break, if there is any | 1793 | (ins-end |
| 1722 | ;; after the changed region. This is necessary e.g. when a rung | 1794 | (and (> end beg) |
| 1723 | ;; marked empty line is converted to a line comment by inserting | 1795 | (c-invalidate-sws-region-after-ins end)))) |
| 1724 | ;; "//" before the line break. In that case the line break would | 1796 | (save-excursion |
| 1725 | ;; keep the rung mark which could make a later `c-backward-sws' | 1797 | ;; Adjust the end to remove the properties in any following simple |
| 1726 | ;; move into the line comment instead of over it. | 1798 | ;; ws up to and including the next line break, if there is any |
| 1727 | (goto-char end) | 1799 | ;; after the changed region. This is necessary e.g. when a rung |
| 1728 | (skip-chars-forward " \t\f\v") | 1800 | ;; marked empty line is converted to a line comment by inserting |
| 1729 | (when (and (eolp) (not (eobp))) | 1801 | ;; "//" before the line break. In that case the line break would |
| 1730 | (setq end (1+ (point))))) | 1802 | ;; keep the rung mark which could make a later `c-backward-sws' |
| 1731 | 1803 | ;; move into the line comment instead of over it. | |
| 1732 | (when (and (= beg end) | 1804 | (goto-char end) |
| 1733 | (get-text-property beg 'c-in-sws) | 1805 | (skip-chars-forward " \t\f\v") |
| 1734 | (> beg (point-min)) | 1806 | (when (and (eolp) (not (eobp))) |
| 1735 | (get-text-property (1- beg) 'c-in-sws)) | 1807 | (setq end (1+ (point))))) |
| 1736 | ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't | 1808 | |
| 1737 | ;; safe to keep a range that was continuous before the change. E.g: | 1809 | (when (and (= beg end) |
| 1738 | ;; | 1810 | (get-text-property beg 'c-in-sws) |
| 1739 | ;; #define foo | 1811 | (> beg (point-min)) |
| 1740 | ;; \ | 1812 | (get-text-property (1- beg) 'c-in-sws)) |
| 1741 | ;; bar | 1813 | ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't |
| 1742 | ;; | 1814 | ;; safe to keep a range that was continuous before the change. E.g: |
| 1743 | ;; There can be a "ladder" between "#" and "b". Now, if the newline | 1815 | ;; |
| 1744 | ;; after "foo" is removed then "bar" will become part of the cpp | 1816 | ;; #define foo |
| 1745 | ;; directive instead of a syntactically relevant token. In that | 1817 | ;; \ |
| 1746 | ;; case there's no longer syntactic ws from "#" to "b". | 1818 | ;; bar |
| 1747 | (setq beg (1- beg))) | 1819 | ;; |
| 1748 | 1820 | ;; There can be a "ladder" between "#" and "b". Now, if the newline | |
| 1749 | (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end) | 1821 | ;; after "foo" is removed then "bar" will become part of the cpp |
| 1750 | (c-remove-is-and-in-sws beg end)) | 1822 | ;; directive instead of a syntactically relevant token. In that |
| 1823 | ;; case there's no longer syntactic ws from "#" to "b". | ||
| 1824 | (setq beg (1- beg))) | ||
| 1825 | |||
| 1826 | (setq end (max (or del-end end) | ||
| 1827 | (or ins-end end) | ||
| 1828 | end)) | ||
| 1829 | |||
| 1830 | (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end) | ||
| 1831 | (c-remove-is-and-in-sws beg end))) | ||
| 1751 | 1832 | ||
| 1752 | (defun c-forward-sws () | 1833 | (defun c-forward-sws () |
| 1753 | ;; Used by `c-forward-syntactic-ws' to implement the unbounded search. | 1834 | ;; Used by `c-forward-syntactic-ws' to implement the unbounded search. |
diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index 87aeaa4750f..037404696d6 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el | |||
| @@ -1445,6 +1445,15 @@ properly." | |||
| 1445 | t "*/" | 1445 | t "*/" |
| 1446 | awk nil) | 1446 | awk nil) |
| 1447 | 1447 | ||
| 1448 | (c-lang-defconst c-block-comment-ender-regexp | ||
| 1449 | ;; Regexp which matches the end of a block comment (if such exists in the | ||
| 1450 | ;; language) | ||
| 1451 | t (if (c-lang-const c-block-comment-ender) | ||
| 1452 | (regexp-quote (c-lang-const c-block-comment-ender)) | ||
| 1453 | "\\<\\>")) | ||
| 1454 | (c-lang-defvar c-block-comment-ender-regexp | ||
| 1455 | (c-lang-const c-block-comment-ender-regexp)) | ||
| 1456 | |||
| 1448 | (c-lang-defconst c-comment-start-regexp | 1457 | (c-lang-defconst c-comment-start-regexp |
| 1449 | ;; Regexp to match the start of any type of comment. | 1458 | ;; Regexp to match the start of any type of comment. |
| 1450 | t (let ((re (c-make-keywords-re nil | 1459 | t (let ((re (c-make-keywords-re nil |
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index ac4ba05bb56..7e3c6ba15a5 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el | |||
| @@ -1209,6 +1209,7 @@ Note that the style variables are always made local to the buffer." | |||
| 1209 | ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"? | 1209 | ;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"? |
| 1210 | (when (< beg end) | 1210 | (when (< beg end) |
| 1211 | (c-unfind-coalesced-tokens beg end)) | 1211 | (c-unfind-coalesced-tokens beg end)) |
| 1212 | (c-invalidate-sws-region-before end) | ||
| 1212 | ;; Are we (potentially) disrupting the syntactic context which | 1213 | ;; Are we (potentially) disrupting the syntactic context which |
| 1213 | ;; makes a type a type? E.g. by inserting stuff after "foo" in | 1214 | ;; makes a type a type? E.g. by inserting stuff after "foo" in |
| 1214 | ;; "foo bar;", or before "foo" in "typedef foo *bar;"? | 1215 | ;; "foo bar;", or before "foo" in "typedef foo *bar;"? |
| @@ -1338,7 +1339,7 @@ Note that the style variables are always made local to the buffer." | |||
| 1338 | (c-clear-char-property-with-value beg end 'syntax-table nil))) | 1339 | (c-clear-char-property-with-value beg end 'syntax-table nil))) |
| 1339 | 1340 | ||
| 1340 | (c-trim-found-types beg end old-len) ; maybe we don't need all of these. | 1341 | (c-trim-found-types beg end old-len) ; maybe we don't need all of these. |
| 1341 | (c-invalidate-sws-region-after beg end) | 1342 | (c-invalidate-sws-region-after beg end old-len) |
| 1342 | ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'. | 1343 | ;; (c-invalidate-state-cache beg) ; moved to `c-before-change'. |
| 1343 | (c-invalidate-find-decl-cache beg) | 1344 | (c-invalidate-find-decl-cache beg) |
| 1344 | 1345 | ||