emacs-diffs
[Top][All Lists]
Advanced

[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)
 



reply via email to

[Prev in Thread] Current Thread [Next in Thread]