mirror of
git://git.sv.gnu.org/emacs.git
synced 2026-01-06 03:40:56 -08:00
Handle C++11 lambda functions.
* lisp/progmodes/cc-engine.el (c-looking-at-inexpr-block): Enhance also to handle C++ lambda functions. (c-looking-at-c++-lambda-capture-list): New function. * lisp/progmodes/cc-fonts.el (c-font-lock-declarations): Recognize the parameter list of a lambda function and set `context' and `c-restricted-<>-arglists' suitably for it. (c-font-lock-c++-lambda-captures): New function. (c-complex-decl-matchers): Insert c-font-lock-c++-lambda-captures into it. * lisp/progmodes/cc-langs.el (c-pre-lambda-tokens, c-pre-lambda-tokens-re): New language constants/variables. (c-paren-nontype-kwds): Include "noexcept" in the C++ value. * lisp/progmodes/cc-mode.el (c-fl-decl-start): Handle being in a C++ lambda function capture list.
This commit is contained in:
parent
9c2ce57719
commit
ce1ed9c811
4 changed files with 243 additions and 13 deletions
|
|
@ -10005,12 +10005,27 @@ comment at the start of cc-engine.el for more info."
|
|||
;; This function might do hidden buffer changes.
|
||||
|
||||
(save-excursion
|
||||
(let ((res 'maybe) passed-paren
|
||||
(let ((res 'maybe) (passed-bracket-pairs 0) bracket-pos passed-paren
|
||||
haskell-op-pos
|
||||
(closest-lim (or containing-sexp lim (point-min)))
|
||||
;; Look at the character after point only as a last resort
|
||||
;; when we can't disambiguate.
|
||||
(block-follows (and (eq (char-after) ?{) (point))))
|
||||
|
||||
;; Search for a C++11 "->" which suggests a lambda declaration.
|
||||
(when (and (c-major-mode-is 'c++-mode)
|
||||
(setq haskell-op-pos
|
||||
(save-excursion
|
||||
(while
|
||||
(progn
|
||||
(c-syntactic-skip-backward "^;=}>" closest-lim t)
|
||||
(and (eq (char-before) ?>)
|
||||
(c-backward-token-2)
|
||||
(not (looking-at c-haskell-op-re)))))
|
||||
(and (looking-at c-haskell-op-re)
|
||||
(point)))))
|
||||
(goto-char haskell-op-pos))
|
||||
|
||||
(while (and (eq res 'maybe)
|
||||
(progn (c-backward-syntactic-ws)
|
||||
(> (point) closest-lim))
|
||||
|
|
@ -10048,6 +10063,11 @@ comment at the start of cc-engine.el for more info."
|
|||
(zerop (c-forward-token-2 1 t)))
|
||||
(eq (char-after) ?\())))
|
||||
(cons 'inexpr-class (point))))
|
||||
((c-keyword-member kw-sym 'c-paren-any-kwds) ; e.g. C++11 "throw" or "noexcept"
|
||||
(setq passed-paren nil)
|
||||
(setq passed-bracket-pairs 0)
|
||||
(setq bracket-pos nil)
|
||||
'maybe)
|
||||
((c-keyword-member kw-sym 'c-inexpr-block-kwds)
|
||||
(when (not passed-paren)
|
||||
(cons 'inexpr-statement (point))))
|
||||
|
|
@ -10062,20 +10082,49 @@ comment at the start of cc-engine.el for more info."
|
|||
|
||||
(if (looking-at "\\s(")
|
||||
(if passed-paren
|
||||
(if (and (eq passed-paren ?\[)
|
||||
(eq (char-after) ?\[))
|
||||
;; Accept several square bracket sexps for
|
||||
;; Java array initializations.
|
||||
'maybe)
|
||||
(setq passed-paren (char-after))
|
||||
(cond
|
||||
((and (eq passed-paren ?\[)
|
||||
(eq (char-after) ?\[)
|
||||
(not (eq (char-after (1+ (point))) ?\[))) ; C++ attribute.
|
||||
;; Accept several square bracket sexps for
|
||||
;; Java array initializations.
|
||||
(setq passed-bracket-pairs (1+ passed-bracket-pairs))
|
||||
'maybe)
|
||||
((and (eq passed-paren ?\()
|
||||
(eq (char-after) ?\[)
|
||||
(not (eq (char-after (1+ (point))) ?\[))
|
||||
(eq passed-bracket-pairs 0))
|
||||
;; C++11 lambda function declaration
|
||||
(setq passed-bracket-pairs 1)
|
||||
(setq bracket-pos (point))
|
||||
'maybe)
|
||||
(t nil))
|
||||
(when (not (looking-at "\\[\\["))
|
||||
(setq passed-paren (char-after))
|
||||
(when (eq passed-paren ?\[)
|
||||
(setq passed-bracket-pairs 1)
|
||||
(setq bracket-pos (point))))
|
||||
'maybe)
|
||||
'maybe))))
|
||||
|
||||
(if (eq res 'maybe)
|
||||
(when (and c-recognize-paren-inexpr-blocks
|
||||
block-follows
|
||||
containing-sexp
|
||||
(eq (char-after containing-sexp) ?\())
|
||||
(cond
|
||||
((and (c-major-mode-is 'c++-mode)
|
||||
block-follows
|
||||
(eq passed-bracket-pairs 1)
|
||||
(save-excursion
|
||||
(goto-char bracket-pos)
|
||||
(or (<= (point) (or lim (point-min)))
|
||||
(progn
|
||||
(c-backward-token-2 1 nil lim)
|
||||
(and
|
||||
(not (c-on-identifier))
|
||||
(not (looking-at c-opt-op-identifier-prefix)))))))
|
||||
(cons 'inlambda bracket-pos))
|
||||
((and c-recognize-paren-inexpr-blocks
|
||||
block-follows
|
||||
containing-sexp
|
||||
(eq (char-after containing-sexp) ?\())
|
||||
(goto-char containing-sexp)
|
||||
(if (or (save-excursion
|
||||
(c-backward-syntactic-ws lim)
|
||||
|
|
@ -10089,7 +10138,7 @@ comment at the start of cc-engine.el for more info."
|
|||
(and c-special-brace-lists
|
||||
(c-looking-at-special-brace-list)))
|
||||
nil
|
||||
(cons 'inexpr-statement (point))))
|
||||
(cons 'inexpr-statement (point)))))
|
||||
|
||||
res))))
|
||||
|
||||
|
|
@ -10115,6 +10164,18 @@ comment at the start of cc-engine.el for more info."
|
|||
paren-state)
|
||||
containing-sexp)))))
|
||||
|
||||
(defun c-looking-at-c++-lambda-capture-list ()
|
||||
;; Return non-nil if we're at the opening "[" of the capture list of a C++
|
||||
;; lambda function, nil otherwise.
|
||||
(and
|
||||
(eq (char-after) ?\[)
|
||||
(not (eq (char-before) ?\[))
|
||||
(not (eq (char-after (1+ (point))) ?\[))
|
||||
(save-excursion
|
||||
(or (eq (c-backward-token-2 1) 1)
|
||||
(looking-at c-pre-lambda-tokens-re)))
|
||||
(not (c-in-literal))))
|
||||
|
||||
(defun c-at-macro-vsemi-p (&optional pos)
|
||||
;; Is there a "virtual semicolon" at POS or point?
|
||||
;; (See cc-defs.el for full details of "virtual semicolons".)
|
||||
|
|
|
|||
|
|
@ -1242,6 +1242,20 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
((eq type 'c-decl-arg-start)
|
||||
(setq context 'decl
|
||||
c-restricted-<>-arglists nil))
|
||||
;; Inside a C++11 lambda function arglist.
|
||||
((and (c-major-mode-is 'c++-mode)
|
||||
(eq (char-before match-pos) ?\()
|
||||
(save-excursion
|
||||
(goto-char match-pos)
|
||||
(c-backward-token-2)
|
||||
(and
|
||||
(c-safe (goto-char (scan-sexps (point) -1)))
|
||||
(c-looking-at-c++-lambda-capture-list))))
|
||||
(setq context 'decl
|
||||
c-restricted-<>-arglists nil)
|
||||
(c-put-char-property (1- match-pos) 'c-type
|
||||
'c-decl-arg-start))
|
||||
|
||||
;; Inside an angle bracket arglist.
|
||||
((or (eq type 'c-<>-arg-sep)
|
||||
(eq (char-before match-pos) ?<))
|
||||
|
|
@ -1583,6 +1597,90 @@ casts and declarations are fontified. Used on level 2 and higher."
|
|||
(setq raw-id (match-string-no-properties 2)))))))))
|
||||
nil)
|
||||
|
||||
(defun c-font-lock-c++-lambda-captures (limit)
|
||||
;; Fontify the lambda capture component of C++ lambda declarations.
|
||||
;;
|
||||
;; This function will be called from font-lock for a region bounded by POINT
|
||||
;; and LIMIT, as though it were to identify a keyword for
|
||||
;; font-lock-keyword-face. It always returns NIL to inhibit this and
|
||||
;; prevent a repeat invocation. See elisp/lispref page "Search-based
|
||||
;; Fontification".
|
||||
(let (mode capture-default id-start id-end declaration sub-begin sub-end)
|
||||
(while (and (< (point) limit)
|
||||
(search-forward "[" limit t))
|
||||
(when (progn (backward-char)
|
||||
(prog1
|
||||
(c-looking-at-c++-lambda-capture-list)
|
||||
(forward-char)))
|
||||
(c-forward-syntactic-ws)
|
||||
(setq mode (and (memq (char-after) '(?= ?&))
|
||||
(char-after)))
|
||||
;; Is the first element of the list a bare "=" or "&"?
|
||||
(when mode
|
||||
(forward-char)
|
||||
(c-forward-syntactic-ws)
|
||||
(if (memq (char-after) '(?, ?\]))
|
||||
(progn
|
||||
(setq capture-default mode)
|
||||
(when (eq (char-after) ?,)
|
||||
(forward-char)
|
||||
(c-forward-syntactic-ws)))
|
||||
(c-backward-token-2)))
|
||||
|
||||
;; Go round the following loop once per captured item.
|
||||
(while (and (not (eq (char-after) ?\]))
|
||||
(< (point) limit))
|
||||
(if (eq (char-after) ?&)
|
||||
(progn (setq mode ?&)
|
||||
(forward-char)
|
||||
(c-forward-syntactic-ws))
|
||||
(setq mode ?=))
|
||||
(if (c-on-identifier)
|
||||
(progn
|
||||
(setq id-start (point))
|
||||
(forward-char)
|
||||
(c-end-of-current-token)
|
||||
(setq id-end (point))
|
||||
(c-forward-syntactic-ws)
|
||||
|
||||
(setq declaration (eq (char-after) ?=))
|
||||
(when declaration
|
||||
(forward-char) ; over "="
|
||||
(c-forward-syntactic-ws)
|
||||
(setq sub-begin (point)))
|
||||
(if (or (and (< (point) limit)
|
||||
(c-syntactic-re-search-forward "," limit t t))
|
||||
(and (c-go-up-list-forward nil limit)
|
||||
(eq (char-before) ?\])))
|
||||
(backward-char)
|
||||
(goto-char limit))
|
||||
(when declaration
|
||||
(save-excursion
|
||||
(setq sub-end (point))
|
||||
(goto-char sub-begin)
|
||||
(c-font-lock-c++-lambda-captures sub-end)))
|
||||
|
||||
(c-put-font-lock-face id-start id-end
|
||||
(cond
|
||||
(declaration
|
||||
'font-lock-variable-name-face)
|
||||
((and capture-default
|
||||
(eq mode capture-default))
|
||||
'font-lock-warning-face)
|
||||
((eq mode ?=) font-lock-constant-face)
|
||||
(t 'font-lock-variable-name-face))))
|
||||
(c-syntactic-re-search-forward "," limit 'bound t))
|
||||
|
||||
(c-forward-syntactic-ws)
|
||||
(when (eq (char-after) ?,)
|
||||
(forward-char)
|
||||
(c-forward-syntactic-ws)))
|
||||
|
||||
(setq capture-default nil)
|
||||
(forward-char)))) ; over the terminating "]".
|
||||
nil)
|
||||
|
||||
|
||||
(c-lang-defconst c-simple-decl-matchers
|
||||
"Simple font lock matchers for types and declarations. These are used
|
||||
on level 2 only and so aren't combined with `c-complex-decl-matchers'."
|
||||
|
|
@ -1700,6 +1798,9 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
|
|||
,@(when (c-lang-const c-recognize-<>-arglists)
|
||||
`(c-font-lock-<>-arglists))
|
||||
|
||||
,@(when (c-major-mode-is 'c++-mode)
|
||||
`(c-font-lock-c++-lambda-captures))
|
||||
|
||||
;; The first two rules here mostly find occurrences that
|
||||
;; `c-font-lock-declarations' has found already, but not
|
||||
;; declarations containing blocks in the type (see note below).
|
||||
|
|
|
|||
|
|
@ -474,6 +474,7 @@ so that all identifiers are recognized as words.")
|
|||
;; The value here may be a list of functions or a single function.
|
||||
t nil
|
||||
c++ '(c-extend-region-for-CPP
|
||||
; c-before-after-change-extend-region-for-lambda-capture ; doesn't seem needed.
|
||||
c-before-change-check-raw-strings
|
||||
c-before-change-check-<>-operators
|
||||
c-depropertize-CPP
|
||||
|
|
@ -517,6 +518,7 @@ parameters \(point-min) and \(point-max).")
|
|||
c-change-expand-fl-region)
|
||||
c++ '(c-depropertize-new-text
|
||||
c-extend-font-lock-region-for-macros
|
||||
; c-before-after-change-extend-region-for-lambda-capture ; doens't seem needed.
|
||||
c-before-after-change-digit-quote
|
||||
c-after-change-re-mark-raw-strings
|
||||
c-neutralize-syntax-in-and-mark-CPP
|
||||
|
|
@ -1360,6 +1362,25 @@ operators."
|
|||
t '(";" "{" "}"))
|
||||
(c-lang-defvar c-pre-start-tokens (c-lang-const c-pre-start-tokens))
|
||||
|
||||
(c-lang-defconst c-pre-lambda-tokens
|
||||
"List of tokens which may precede a lambda declaration.
|
||||
In C++ this is something like \"[a,b] (foo, bar) -> int { ... };\".
|
||||
Currently (2016-08) only used in C++ mode."
|
||||
t (c--set-difference
|
||||
(c--delete-duplicates
|
||||
(append (c-lang-const c-operator-list)
|
||||
(c-lang-const c-other-op-syntax-tokens)))
|
||||
(append
|
||||
'("#" "%:" "??=" "##" "%:%:" "??=??=" "::" "." "->"
|
||||
"]" "<:" ":>" "??(" "??)" "??-" "new" "delete"
|
||||
")" ".*" "->*" "??'" "??!" "??!??!" "??!=" "??'=")
|
||||
'("<%" "%>" "<:" ":>" "%:" "%:%:" "#" "##" "::" "..."))
|
||||
:test #'string-equal))
|
||||
|
||||
(c-lang-defconst c-pre-lambda-tokens-re
|
||||
;; Regexp matching any token in the list `c-pre-lambda-tokens'.
|
||||
t (regexp-opt (c-lang-const c-pre-lambda-tokens)))
|
||||
(c-lang-defvar c-pre-lambda-tokens-re (c-lang-const c-pre-lambda-tokens-re))
|
||||
|
||||
;;; Syntactic whitespace.
|
||||
|
||||
|
|
@ -2284,7 +2305,8 @@ contain type identifiers."
|
|||
(c c++) '(;; GCC extension.
|
||||
"__attribute__"
|
||||
;; MSVC extension.
|
||||
"__declspec"))
|
||||
"__declspec")
|
||||
c++ (append (c-lang-const c-paren-nontype-kwds) '("noexcept")))
|
||||
|
||||
(c-lang-defconst c-paren-nontype-key
|
||||
t (c-make-keywords-re t (c-lang-const c-paren-nontype-kwds)))
|
||||
|
|
|
|||
|
|
@ -1142,6 +1142,38 @@ Note that the style variables are always made local to the buffer."
|
|||
(goto-char try-end)
|
||||
(setq num-begin (point)))))
|
||||
|
||||
;; The following doesn't seem needed at the moment (2016-08-15).
|
||||
;; (defun c-before-after-change-extend-region-for-lambda-capture
|
||||
;; (_beg _end &optional _old-len)
|
||||
;; ;; In C++ Mode, extend the region (c-new-BEG c-new-END) to cover any lambda
|
||||
;; ;; function capture lists we happen to be inside. This function is expected
|
||||
;; ;; to be called both as a before-change and after change function.
|
||||
;; ;;
|
||||
;; ;; Note that these things _might_ be nested, with a capture list looking
|
||||
;; ;; like:
|
||||
;; ;;
|
||||
;; ;; [ ...., &foo = [..](){...}(..), ... ]
|
||||
;; ;;
|
||||
;; ;; . What a wonderful language is C++. ;-)
|
||||
;; (c-save-buffer-state (paren-state pos)
|
||||
;; (goto-char c-new-BEG)
|
||||
;; (setq paren-state (c-parse-state))
|
||||
;; (while (setq pos (c-pull-open-brace paren-state))
|
||||
;; (goto-char pos)
|
||||
;; (when (c-looking-at-c++-lambda-capture-list)
|
||||
;; (setq c-new-BEG (min c-new-BEG pos))
|
||||
;; (if (c-go-list-forward)
|
||||
;; (setq c-new-END (max c-new-END (point))))))
|
||||
|
||||
;; (goto-char c-new-END)
|
||||
;; (setq paren-state (c-parse-state))
|
||||
;; (while (setq pos (c-pull-open-brace paren-state))
|
||||
;; (goto-char pos)
|
||||
;; (when (c-looking-at-c++-lambda-capture-list)
|
||||
;; (setq c-new-BEG (min c-new-BEG pos))
|
||||
;; (if (c-go-list-forward)
|
||||
;; (setq c-new-END (max c-new-END (point))))))))
|
||||
|
||||
(defun c-before-change (beg end)
|
||||
;; Function to be put on `before-change-functions'. Primarily, this calls
|
||||
;; the language dependent `c-get-state-before-change-functions'. It is
|
||||
|
|
@ -1329,12 +1361,24 @@ Note that the style variables are always made local to the buffer."
|
|||
;; lock context (etc.) fontification.
|
||||
(let ((lit-start (c-literal-start))
|
||||
(new-pos pos)
|
||||
capture-opener
|
||||
bod-lim bo-decl)
|
||||
(goto-char (c-point 'bol new-pos))
|
||||
(when lit-start ; Comment or string.
|
||||
(goto-char lit-start))
|
||||
(setq bod-lim (c-determine-limit 500))
|
||||
|
||||
;; In C++ Mode, first check if we are within a (possibly nested) lambda
|
||||
;; form capture list.
|
||||
(when (c-major-mode-is 'c++-mode)
|
||||
(let ((paren-state (c-parse-state))
|
||||
opener)
|
||||
(save-excursion
|
||||
(while (setq opener (c-pull-open-brace paren-state))
|
||||
(goto-char opener)
|
||||
(if (c-looking-at-c++-lambda-capture-list)
|
||||
(setq capture-opener (point)))))))
|
||||
|
||||
(while
|
||||
;; Go to a less nested declaration each time round this loop.
|
||||
(and
|
||||
|
|
@ -1361,6 +1405,8 @@ Note that the style variables are always made local to the buffer."
|
|||
c-<-as-paren-syntax)))))
|
||||
(not (bobp)))
|
||||
(backward-char)) ; back over (, [, <.
|
||||
(when (and capture-opener (< capture-opener new-pos))
|
||||
(setq new-pos capture-opener))
|
||||
(and (/= new-pos pos) new-pos)))
|
||||
|
||||
(defun c-change-expand-fl-region (_beg _end _old-len)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue