[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Emacs-diffs] master 6463b85: Handle syntactic WS cache properties more
From: |
Alan Mackenzie |
Subject: |
[Emacs-diffs] master 6463b85: Handle syntactic WS cache properties more accurately at buffer changes. |
Date: |
Wed, 11 Jan 2017 18:29:41 +0000 (UTC) |
branch: master
commit 6463b85aeb67326acda340fbaad3e481e62120c0
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>
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.
---
lisp/progmodes/cc-engine.el | 153 +++++++++++++++++++++++++++++++++----------
lisp/progmodes/cc-langs.el | 9 +++
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 a5d2588..3077e00 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."
`((c-debug-remove-face beg end 'c-debug-is-sws-face)
(c-debug-remove-face beg end 'c-debug-in-sws-face)))))
-(defsubst c-invalidate-sws-region-after (beg end)
- ;; Called from `after-change-functions'. Note that if
- ;; `c-forward-sws' or `c-backward-sws' are used outside
+;; The type of literal position `end' is in in a `before-change-functions'
+;; function - one of `c', `c++', `pound', or nil (but NOT `string').
+(defvar c-sws-lit-type nil)
+;; A cons (START . STOP) of the bounds of the comment or CPP construct
+;; enclosing END, if any, else nil.
+(defvar c-sws-lit-limits nil)
+
+(defun c-invalidate-sws-region-before (end)
+ ;; Called from c-before-change. END is the end of the change region, the
+ ;; standard parameter given to all before-change-functions.
+ ;;
+ ;; Note whether END is inside a comment or CPP construct, and if so note its
+ ;; bounds in `c-sws-lit-limits' and type in `c-sws-lit-type'.
+ (save-excursion
+ (goto-char end)
+ (let* ((limits (c-literal-limits))
+ (lit-type (c-literal-type limits)))
+ (cond
+ ((memq lit-type '(c c++))
+ (setq c-sws-lit-type lit-type
+ c-sws-lit-limits limits))
+ ((c-beginning-of-macro)
+ (setq c-sws-lit-type 'pound
+ c-sws-lit-limits (cons (point)
+ (progn (c-end-of-macro) (point)))))
+ (t (setq c-sws-lit-type nil
+ c-sws-lit-limits nil))))))
+
+(defun c-invalidate-sws-region-after-del (beg end old-len)
+ ;; Text has been deleted, OLD-LEN characters of it starting from position
+ ;; BEG. END is typically eq to BEG. Should there have been a comment or
+ ;; CPP construct open at END before the deletion, check whether this
+ ;; deletion deleted or "damaged" its opening delimiter. If so, return the
+ ;; current position of where the construct ended, otherwise return nil.
+ (when c-sws-lit-limits
+ (setcdr c-sws-lit-limits (- (cdr c-sws-lit-limits) old-len))
+ (if (and (< beg (+ (car c-sws-lit-limits) 2)) ; A lazy assumption that
+ ; comment delimiters are 2
+ ; chars long.
+ (or (get-text-property end 'c-in-sws)
+ (next-single-property-change end 'c-in-sws nil
+ (cdr c-sws-lit-limits))
+ (get-text-property end 'c-is-sws)
+ (next-single-property-change end 'c-is-sws nil
+ (cdr c-sws-lit-limits))))
+ (cdr c-sws-lit-limits))))
+
+(defun c-invalidate-sws-region-after-ins (end)
+ ;; Text has been inserted, ending at buffer position END. Should there be a
+ ;; literal or CPP construct open at END, check whether there are `c-in-sws'
+ ;; or `c-is-sws' text properties inside this literal. If there are, return
+ ;; the buffer position of the end of the literal, else return nil.
+ (save-excursion
+ (let* ((limits (c-literal-limits))
+ (lit-type (c-literal-type limits)))
+ (goto-char end)
+ (when (and (not (memq lit-type '(c c++)))
+ (c-beginning-of-macro))
+ (setq lit-type 'pound
+ limits (cons (point)
+ (progn (c-end-of-macro) (point)))))
+ (when (memq lit-type '(c c++ pound))
+ (let ((next-in (next-single-property-change (car limits) 'c-in-sws
+ nil (cdr limits)))
+ (next-is (next-single-property-change (car limits) 'c-is-sws
+ nil (cdr limits))))
+ (and (or next-in next-is)
+ (cdr limits)))))))
+
+(defun c-invalidate-sws-region-after (beg end old-len)
+ ;; Called from `after-change-functions'. Remove any stale `c-in-sws' or
+ ;; `c-is-sws' text properties from the vicinity of the change. BEG, END,
+ ;; and OLD-LEN are the standard arguments given to after-change functions.
+ ;;
+ ;; Note that if `c-forward-sws' or `c-backward-sws' are used outside
;; `c-save-buffer-state' or similar then this will remove the cache
;; properties right after they're added.
;;
;; This function does hidden buffer changes.
-
- (save-excursion
- ;; Adjust the end to remove the properties in any following simple
- ;; ws up to and including the next line break, if there is any
- ;; after the changed region. This is necessary e.g. when a rung
- ;; marked empty line is converted to a line comment by inserting
- ;; "//" before the line break. In that case the line break would
- ;; keep the rung mark which could make a later `c-backward-sws'
- ;; move into the line comment instead of over it.
- (goto-char end)
- (skip-chars-forward " \t\f\v")
- (when (and (eolp) (not (eobp)))
- (setq end (1+ (point)))))
-
- (when (and (= beg end)
- (get-text-property beg 'c-in-sws)
- (> beg (point-min))
- (get-text-property (1- beg) 'c-in-sws))
- ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't
- ;; safe to keep a range that was continuous before the change. E.g:
- ;;
- ;; #define foo
- ;; \
- ;; bar
- ;;
- ;; There can be a "ladder" between "#" and "b". Now, if the newline
- ;; after "foo" is removed then "bar" will become part of the cpp
- ;; directive instead of a syntactically relevant token. In that
- ;; case there's no longer syntactic ws from "#" to "b".
- (setq beg (1- beg)))
-
- (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end)
- (c-remove-is-and-in-sws beg end))
+ (let ((del-end
+ (and (> old-len 0)
+ (c-invalidate-sws-region-after-del beg end old-len)))
+ (ins-end
+ (and (> end beg)
+ (c-invalidate-sws-region-after-ins end))))
+ (save-excursion
+ ;; Adjust the end to remove the properties in any following simple
+ ;; ws up to and including the next line break, if there is any
+ ;; after the changed region. This is necessary e.g. when a rung
+ ;; marked empty line is converted to a line comment by inserting
+ ;; "//" before the line break. In that case the line break would
+ ;; keep the rung mark which could make a later `c-backward-sws'
+ ;; move into the line comment instead of over it.
+ (goto-char end)
+ (skip-chars-forward " \t\f\v")
+ (when (and (eolp) (not (eobp)))
+ (setq end (1+ (point)))))
+
+ (when (and (= beg end)
+ (get-text-property beg 'c-in-sws)
+ (> beg (point-min))
+ (get-text-property (1- beg) 'c-in-sws))
+ ;; Ensure that an `c-in-sws' range gets broken. Note that it isn't
+ ;; safe to keep a range that was continuous before the change. E.g:
+ ;;
+ ;; #define foo
+ ;; \
+ ;; bar
+ ;;
+ ;; There can be a "ladder" between "#" and "b". Now, if the newline
+ ;; after "foo" is removed then "bar" will become part of the cpp
+ ;; directive instead of a syntactically relevant token. In that
+ ;; case there's no longer syntactic ws from "#" to "b".
+ (setq beg (1- beg)))
+
+ (setq end (max (or del-end end)
+ (or ins-end end)
+ end))
+
+ (c-debug-sws-msg "c-invalidate-sws-region-after [%s..%s]" beg end)
+ (c-remove-is-and-in-sws beg end)))
(defun c-forward-sws ()
;; 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 87aeaa4..0374046 100644
--- a/lisp/progmodes/cc-langs.el
+++ b/lisp/progmodes/cc-langs.el
@@ -1445,6 +1445,15 @@ properly."
t "*/"
awk nil)
+(c-lang-defconst c-block-comment-ender-regexp
+ ;; Regexp which matches the end of a block comment (if such exists in the
+ ;; language)
+ t (if (c-lang-const c-block-comment-ender)
+ (regexp-quote (c-lang-const c-block-comment-ender))
+ "\\<\\>"))
+(c-lang-defvar c-block-comment-ender-regexp
+ (c-lang-const c-block-comment-ender-regexp))
+
(c-lang-defconst c-comment-start-regexp
;; Regexp to match the start of any type of comment.
t (let ((re (c-make-keywords-re nil
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index ac4ba05..7e3c6ba 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."
;; Are we coalescing two tokens together, e.g. "fo o" -> "foo"?
(when (< beg end)
(c-unfind-coalesced-tokens beg end))
+ (c-invalidate-sws-region-before end)
;; Are we (potentially) disrupting the syntactic context which
;; makes a type a type? E.g. by inserting stuff after "foo" in
;; "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."
(c-clear-char-property-with-value beg end 'syntax-table nil)))
(c-trim-found-types beg end old-len) ; maybe we don't need all of
these.
- (c-invalidate-sws-region-after beg end)
+ (c-invalidate-sws-region-after beg end old-len)
;; (c-invalidate-state-cache beg) ; moved to `c-before-change'.
(c-invalidate-find-decl-cache beg)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Emacs-diffs] master 6463b85: Handle syntactic WS cache properties more accurately at buffer changes.,
Alan Mackenzie <=