emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] master 5ccaee4: Implement C++ Mode attributes. This fixes


From: Alan Mackenzie
Subject: [Emacs-diffs] master 5ccaee4: Implement C++ Mode attributes. This fixes bug #36650.
Date: Sun, 21 Jul 2019 17:10:39 -0400 (EDT)

branch: master
commit 5ccaee4bbc184c53b262021361bd216af17e80f5
Author: Alan Mackenzie <address@hidden>
Commit: Alan Mackenzie <address@hidden>

    Implement C++ Mode attributes.  This fixes bug #36650.
    
    * lisp/progmodes/cc-engine.el (c-looking-at-c++-attribute)
    (c-enclosing-c++-attribute, c-slow-enclosing-c++-attribute): New macro and
    functions.
    (c-crosses-statement-barrier-p): Add [ into skip-chars for C++ Mode, and use
    it to detect and skip over an attribute whilst scanning forward.
    (c-sws-lit-type): Use the new value 'attribute.
    (c-invalidate-sws-region-before): Put a save-match-data around this 
function.
    Detect and handle an enclosing attribute at either END or BEG.
    (c-invalidate-sws-region-after): Handle C++ attributes.
    (c-forward-sws, c-backward-sws): Handle C++ attributes.
    
    * lisp/progmodes/cc-mode.el (c-fl-decl-end): Detect and handle point being
    inside a C++ attribute.
---
 lisp/progmodes/cc-engine.el | 178 ++++++++++++++++++++++++++++++++++++--------
 lisp/progmodes/cc-mode.el   |   4 +-
 2 files changed, 148 insertions(+), 34 deletions(-)

diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el
index cb88fc3..e7bae0e 100644
--- a/lisp/progmodes/cc-engine.el
+++ b/lisp/progmodes/cc-engine.el
@@ -690,6 +690,21 @@ comment at the start of cc-engine.el for more info."
       (overlay-put (make-overlay end ol-end) 'face face))))
 
 
+(defmacro c-looking-at-c++-attribute ()
+  ;; If we're in C++ Mode, and point is at the [[ introducing an attribute,
+  ;; return the position of the end of the attribute, otherwise return nil.
+  ;; The match data are NOT preserved over this macro.
+  `(and
+    (c-major-mode-is 'c++-mode)
+    (looking-at "\\[\\[")
+    (save-excursion
+      (and
+       (c-go-list-forward)
+       (eq (char-before) ?\])
+       (eq (char-before (1- (point))) ?\])
+       (point)))))
+
+
 ;; `c-beginning-of-statement-1' and accompanying stuff.
 
 ;; KLUDGE ALERT: c-maybe-labelp is used to pass information between
@@ -1414,9 +1429,15 @@ comment at the start of cc-engine.el for more info."
                      c-opt-cpp-symbol                   ; usually "#"
                      (substring c-stmt-delim-chars 1))  ; e.g. ";{}?:"
            c-stmt-delim-chars))
+        (skip-chars
+         (if (c-major-mode-is 'c++-mode)
+             (concat (substring skip-chars 0 1) ; "^"
+                     "["                        ; to catch C++ attributes
+                     (substring skip-chars 1)) ; e.g. "#;{}?:"
+           skip-chars))
         (non-skip-list
          (append (substring skip-chars 1) nil)) ; e.g. (?# ?\; ?{ ?} ?? ?:)
-        lit-range lit-start vsemi-pos)
+        lit-range lit-start vsemi-pos attr-end)
     (save-restriction
       (widen)
       (save-excursion
@@ -1440,6 +1461,11 @@ comment at the start of cc-engine.el for more info."
             ;; In a string/comment?
             ((setq lit-range (c-literal-limits from))
              (goto-char (cdr lit-range)))
+            ;; Skip over a C++ attribute?
+            ((eq (char-after) ?\[)
+             (if (setq attr-end (c-looking-at-c++-attribute))
+                 (goto-char attr-end)
+               (forward-char)))
             ((eq (char-after) ?:)
              (forward-char)
              (if (and (eq (char-after) ?:)
@@ -1827,12 +1853,63 @@ comment at the start of cc-engine.el for more info."
 (def-edebug-spec c-remove-is-and-in-sws t)
 
 ;; The type of literal position `end' is in a `before-change-functions'
-;; function - one of `c', `c++', `pound', or nil (but NOT `string').
+;; function - one of `c', `c++', `pound', `noise', `attribute' or nil (but NOT
+;; `string').
 (defvar c-sws-lit-type nil)
-;; A cons (START . STOP) of the bounds of the comment or CPP construct
+;; A cons (START . STOP) of the bounds of the comment or CPP construct, etc.,
 ;; enclosing END, if any, else nil.
 (defvar c-sws-lit-limits nil)
 
+(defun c-enclosing-c++-attribute ()
+  ;; If we're in C++ Mode, and point is within a correctly balanced [[ ... ]]
+  ;; attribute structure, return a cons of its starting and ending positions.
+  ;; Otherwise, return nil.  We use the c-{in,is}-sws-face text properties for
+  ;; this determination, this macro being intended only for use in the *-sws-*
+  ;; functions and macros.  The match data are NOT preserved over this macro.
+  (let (attr-end pos-is-sws)
+     (and
+      (c-major-mode-is 'c++-mode)
+      (> (point) (point-min))
+      (setq pos-is-sws
+           (if (get-text-property (1- (point)) 'c-is-sws)
+               (1- (point))
+             (1- (previous-single-property-change
+                  (point) 'c-is-sws nil (point-min)))))
+      (save-excursion
+       (goto-char pos-is-sws)
+       (setq attr-end (c-looking-at-c++-attribute)))
+      (> attr-end (point))
+      (cons pos-is-sws attr-end))))
+
+(defun c-slow-enclosing-c++-attribute ()
+  ;; Like `c-enclosing-c++-attribute', but does not depend on the c-i[ns]-sws
+  ;; properties being set.
+  (and
+   (c-major-mode-is 'c++-mode)
+   (save-excursion
+     (let ((paren-state (c-parse-state))
+          cand)
+       (while
+          (progn
+            (setq cand
+                  (catch 'found-cand
+                    (while (cdr paren-state)
+                      (when (and (numberp (car paren-state))
+                                 (numberp (cadr paren-state))
+                                 (eq (car paren-state)
+                                     (1+ (cadr paren-state)))
+                                 (eq (char-after (car paren-state)) ?\[)
+                                 (eq (char-after (cadr paren-state)) ?\[))
+                        (throw 'found-cand (cadr paren-state)))
+                      (setq paren-state (cdr paren-state)))))
+            (and cand
+                 (not
+                  (and (c-go-list-forward cand)
+                       (eq (char-before) ?\])
+                       (eq (char-before (1- (point))) ?\])))))
+        (setq paren-state (cdr paren-state)))
+       (and cand (cons cand (point)))))))
+
 (defun c-invalidate-sws-region-before (beg end)
   ;; Called from c-before-change.  BEG and END are the bounds of the change
   ;; region, the standard parameters given to all before-change-functions.
@@ -1841,31 +1918,41 @@ comment at the start of cc-engine.el for more info."
   ;; if so note its bounds in `c-sws-lit-limits' and type in `c-sws-lit-type'.
   (setq c-sws-lit-type nil
        c-sws-lit-limits nil)
-  (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)))))
-       ((progn (skip-syntax-backward "w_")
-              (looking-at c-noise-macro-name-re))
-       (setq c-sws-lit-type 'noise
-             c-sws-lit-limits (cons (match-beginning 1) (match-end 1))))
-       (t))))
-  (save-excursion
-    (goto-char beg)
-    (skip-syntax-backward "w_")
-    (when (looking-at c-noise-macro-name-re)
-      (setq c-sws-lit-type 'noise)
-      (if (consp c-sws-lit-limits)
-         (setcar c-sws-lit-limits (match-beginning 1))
-       (setq c-sws-lit-limits (cons (match-beginning 1) (match-end 1)))))))
+  (save-match-data
+    (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)))))
+        ((eq lit-type 'string))
+        ((setq c-sws-lit-limits (c-enclosing-c++-attribute))
+         (setq c-sws-lit-type 'attribute))
+        ((progn (skip-syntax-backward "w_")
+                (looking-at c-noise-macro-name-re))
+         (setq c-sws-lit-type 'noise
+               c-sws-lit-limits (cons (match-beginning 1) (match-end 1))))
+        (t))))
+    (save-excursion
+      (goto-char beg)
+      (let ((attr-limits (c-enclosing-c++-attribute)))
+       (if attr-limits
+           (if (consp c-sws-lit-limits)
+               (setcar c-sws-lit-limits (car attr-limits))
+             (setq c-sws-lit-limits attr-limits))
+         (skip-syntax-backward "w_")
+         (when (looking-at c-noise-macro-name-re)
+           (setq c-sws-lit-type 'noise)
+           (if (consp c-sws-lit-limits)
+               (setcar c-sws-lit-limits (match-beginning 1))
+             (setq c-sws-lit-limits (cons (match-beginning 1)
+                                          (match-end 1))))))))))
 
 (defun c-invalidate-sws-region-after-del (beg end _old-len)
   ;; Text has been deleted, OLD-LEN characters of it starting from position
@@ -1940,7 +2027,7 @@ comment at the start of cc-engine.el for more info."
       (when (and (eolp) (not (eobp)))
        (setq end (1+ (point)))))
 
-    (when (eq c-sws-lit-type 'noise)
+    (when (memq c-sws-lit-type '(noise attribute))
       (setq beg (car c-sws-lit-limits)
            end (cdr c-sws-lit-limits))) ; This last setting may be redundant.
 
@@ -1990,6 +2077,8 @@ comment at the start of cc-engine.el for more info."
     (when (or (looking-at c-syntactic-ws-start)
              (and c-opt-cpp-prefix
                   (looking-at c-noise-macro-name-re))
+             (and (c-major-mode-is 'c++-mode)
+                  (looking-at "\\[\\["))
              (looking-at c-doc-line-join-re))
 
       (setq rung-end-pos (min (1+ (point)) (point-max)))
@@ -2126,6 +2215,10 @@ comment at the start of cc-engine.el for more info."
              (goto-char (match-end 1))
              (not (eobp)))
 
+            ((setq next-rung-pos (c-looking-at-c++-attribute))
+             (goto-char next-rung-pos)
+             (not (eobp)))
+
             ((looking-at c-doc-line-join-re)
              ;; Skip over a line join in (e.g.) Pike autodoc.
              (goto-char (match-end 0))
@@ -2214,8 +2307,7 @@ comment at the start of cc-engine.el for more info."
                "c-forward-sws clearing thoroughly at %s for cache separation"
                (1- last-put-in-sws-pos))
               (c-remove-is-and-in-sws (1- last-put-in-sws-pos)
-                                      last-put-in-sws-pos))))
-      ))))
+                                      last-put-in-sws-pos))))))))
 
 (defun c-backward-sws ()
   ;; Used by `c-backward-syntactic-ws' to implement the unbounded search.
@@ -2226,7 +2318,8 @@ comment at the start of cc-engine.el for more info."
        ;; part of the simple ws region.
        (rung-pos (point)) next-rung-pos last-put-in-sws-pos
        rung-is-marked simple-ws-beg cmt-skip-pos
-       (doc-line-join-here (concat c-doc-line-join-re "\\=")))
+       (doc-line-join-here (concat c-doc-line-join-re "\\="))
+       attr-end)
 
     ;; Skip simple horizontal ws and do a quick check on the preceding
     ;; character to see if it's anything that can't end syntactic ws, so we can
@@ -2240,6 +2333,14 @@ comment at the start of cc-engine.el for more info."
                      (memq (char-before) c-doc-line-join-end-ch) ; For speed.
                      (re-search-backward doc-line-join-here
                                          (c-point 'bopl) t))
+                    (and
+                     (c-major-mode-is 'c++-mode)
+                     (eq (char-before) ?\])
+                     (eq (char-before (1- (point))) ?\])
+                     (save-excursion
+                       (and (c-go-list-backward)
+                            (looking-at "\\[\\[")))
+                     (setq attr-end (point)))
                     (progn
                       (backward-char)
                       (or (looking-at c-syntactic-ws-end)
@@ -2250,7 +2351,8 @@ comment at the start of cc-engine.el for more info."
       ;; Try to find a rung position in the simple ws preceding point, so that
       ;; we can get a cache hit even if the last bit of the simple ws has
       ;; changed recently.
-      (setq simple-ws-beg (or (match-end 1) ; Noise macro
+      (setq simple-ws-beg (or attr-end       ; After attribute.
+                             (match-end 1) ; Noise macro, etc.
                              (match-end 0))) ; c-syntactic-ws-end
       (skip-chars-backward " \t\n\r\f\v")
       (if (setq rung-is-marked (text-property-any
@@ -2388,6 +2490,16 @@ comment at the start of cc-engine.el for more info."
              (goto-char next-rung-pos)
              t)
 
+            ((and (c-major-mode-is 'c++-mode)
+                  (eq (char-before) ?\])
+                  (eq (char-before (1- (point))) ?\])
+                  (save-excursion
+                    (and (c-go-list-backward)
+                         (setq next-rung-pos (point))
+                         (looking-at "\\[\\["))))
+             (goto-char next-rung-pos)
+             t)
+
             ((and
               (memq (char-before) c-doc-line-join-end-ch) ; For speed.
               (re-search-backward doc-line-join-here (c-point 'bopl) t)))))
diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el
index 5ae7e0f..a5e1589 100644
--- a/lisp/progmodes/cc-mode.el
+++ b/lisp/progmodes/cc-mode.el
@@ -2158,9 +2158,11 @@ Note that this is a strict tail, so won't match, e.g. 
\"0x....\".")
   ;; count as being in a declarator (on pragmatic grounds).
   (goto-char pos)
   (let ((lit-start (c-literal-start))
-       pos1)
+       enclosing-attribute pos1)
     (unless lit-start
       (c-backward-syntactic-ws)
+      (when (setq enclosing-attribute (c-slow-enclosing-c++-attribute))
+       (goto-char (car enclosing-attribute))) ; Only happens in C++ Mode.
       (when (setq pos1 (c-on-identifier))
        (goto-char pos1)
        (let ((lim (save-excursion



reply via email to

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