From ff73c2c3e2b99c1a759fd876464d36f6dd57a4b0 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Thu, 30 Oct 2014 16:07:19 +0000 Subject: [PATCH] Add "enum classs" support to C++ mode. progmodes/cc-langs.el (c-after-brace-list-decl-kwds) (c-after-brace-list-key): New language consts/variables. progmodes/cc-engine.el (c-looking-at-decl-block): Exclude spurious match of "enum struct" from decl-block recognition. (c-backward-colon-prefixed-type): New function. (c-backward-over-enum-header): Call above function to extend recognition of enum structure. --- lisp/ChangeLog | 11 ++++++ lisp/progmodes/cc-engine.el | 95 +++++++++++++++++++++++++++++++++------------ lisp/progmodes/cc-langs.el | 20 ++++++++++ 3 files changed, 102 insertions(+), 24 deletions(-) diff --git a/lisp/ChangeLog b/lisp/ChangeLog index 56da0d6e154..91f61aa448b 100644 --- a/lisp/ChangeLog +++ b/lisp/ChangeLog @@ -1,3 +1,14 @@ +2014-10-30 Alan Mackenzie + + Add "enum classs" support to C++ mode. + * progmodes/cc-langs.el (c-after-brace-list-decl-kwds) + (c-after-brace-list-key): New language consts/variables. + * progmodes/cc-engine.el (c-looking-at-decl-block): Exclude + spurious match of "enum struct" from decl-block recognition. + (c-backward-colon-prefixed-type): New function. + (c-backward-over-enum-header): Call above function to extend + recognition of enum structure. + 2014-10-30 Stefan Monnier * progmodes/cc-defs.el (c--macroexpand-all): New function (bug#18845). diff --git a/lisp/progmodes/cc-engine.el b/lisp/progmodes/cc-engine.el index ccc3f067571..0e8539b795b 100644 --- a/lisp/progmodes/cc-engine.el +++ b/lisp/progmodes/cc-engine.el @@ -8460,31 +8460,44 @@ comment at the start of cc-engine.el for more info." (cond ((c-syntactic-re-search-forward c-decl-block-key open-brace t t t) (goto-char (setq kwd-start (match-beginning 0))) - (or - - ;; Found a keyword that can't be a type? - (match-beginning 1) - - ;; Can be a type too, in which case it's the return type of a - ;; function (under the assumption that no declaration level - ;; block construct starts with a type). - (not (c-forward-type)) - - ;; Jumped over a type, but it could be a declaration keyword - ;; followed by the declared identifier that we've jumped over - ;; instead (e.g. in "class Foo {"). If it indeed is a type - ;; then we should be at the declarator now, so check for a - ;; valid declarator start. - ;; - ;; Note: This doesn't cope with the case when a declared - ;; identifier is followed by e.g. '(' in a language where '(' - ;; also might be part of a declarator expression. Currently - ;; there's no such language. - (not (or (looking-at c-symbol-start) - (looking-at c-type-decl-prefix-key))))) + (and + ;; Exclude cases where we matched what would ordinarily + ;; be a block declaration keyword, except where it's not + ;; legal because it's part of a "compound keyword" like + ;; "enum class". Of course, if c-after-brace-list-key + ;; is nil, we can skip the test. + (or (equal c-after-brace-list-key "\\<\\>") + (save-match-data + (save-excursion + (not + (and + (looking-at c-after-brace-list-key) + (= (c-backward-token-2 1 t) 0) + (looking-at c-brace-list-key)))))) + (or + ;; Found a keyword that can't be a type? + (match-beginning 1) + + ;; Can be a type too, in which case it's the return type of a + ;; function (under the assumption that no declaration level + ;; block construct starts with a type). + (not (c-forward-type)) + + ;; Jumped over a type, but it could be a declaration keyword + ;; followed by the declared identifier that we've jumped over + ;; instead (e.g. in "class Foo {"). If it indeed is a type + ;; then we should be at the declarator now, so check for a + ;; valid declarator start. + ;; + ;; Note: This doesn't cope with the case when a declared + ;; identifier is followed by e.g. '(' in a language where '(' + ;; also might be part of a declarator expression. Currently + ;; there's no such language. + (not (or (looking-at c-symbol-start) + (looking-at c-type-decl-prefix-key)))))) ;; In Pike a list of modifiers may be followed by a brace - ;; to make them apply to many identifiers. Note that the + ;; to make them apply to many identifiers. Note that the ;; match data will be empty on return in this case. ((and (c-major-mode-is 'pike-mode) (progn @@ -8586,11 +8599,44 @@ comment at the start of cc-engine.el for more info." (not (looking-at "="))))) b-pos))) +(defun c-backward-colon-prefixed-type () + ;; We're at the token after what might be a type prefixed with a colon. Try + ;; moving backward over this type and the colon. On success, return t and + ;; leave point before colon, on falure, leave point unchanged. Will clobber + ;; match data. + (let ((here (point)) + (colon-pos nil)) + (save-excursion + (while + (and (eql (c-backward-token-2) 0) + (or (not (looking-at "\\s)")) + (c-go-up-list-backward)) + (cond + ((eql (char-after) ?:) + (setq colon-pos (point)) + (forward-char) + (c-forward-syntactic-ws) + (or (and (c-forward-type) + (progn (c-forward-syntactic-ws) + (eq (point) here))) + (setq colon-pos nil)) + nil) + ((eql (char-after) ?\() + t) + ((looking-at c-symbol-key) + t) + (t nil))))) + (when colon-pos + (goto-char colon-pos) + t))) + (defun c-backward-over-enum-header () ;; We're at a "{". Move back to the enum-like keyword that starts this ;; declaration and return t, otherwise don't move and return nil. (let ((here (point)) up-sexp-pos before-identifier) + (when c-recognize-post-brace-list-type-p + (c-backward-colon-prefixed-type)) (while (and (eq (c-backward-token-2) 0) @@ -8601,10 +8647,11 @@ comment at the start of cc-engine.el for more info." (not before-identifier)) (setq before-identifier t)) ((and before-identifier - (or (eq (char-after) ?,) + (or (eql (char-after) ?,) (looking-at c-postfix-decl-spec-key))) (setq before-identifier nil) t) + ((looking-at c-after-brace-list-key) t) ((looking-at c-brace-list-key) nil) ((and c-recognize-<>-arglists (eq (char-after) ?<) diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index a8dc3b8968c..2a5db6d3c86 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -1807,6 +1807,26 @@ will be handled." t (c-make-keywords-re t (c-lang-const c-brace-list-decl-kwds))) (c-lang-defvar c-brace-list-key (c-lang-const c-brace-list-key)) +(c-lang-defconst c-after-brace-list-decl-kwds + "Keywords that might follow keywords in `c-brace-list-decl-kwds' +and precede the opening brace." + t nil + c++ '("class" "struct")) + +(c-lang-defconst c-after-brace-list-key + ;; Regexp matching keywords that can fall between a brace-list + ;; keyword and the associated brace list. + t (c-make-keywords-re t (c-lang-const c-after-brace-list-decl-kwds))) +(c-lang-defvar c-after-brace-list-key (c-lang-const c-after-brace-list-key)) + +(c-lang-defconst c-recognize-post-brace-list-type-p + "Set to t when we recognize a colon and then a type after an enum, +e.g., enum foo : int { A, B, C };" + t nil + c++ t) +(c-lang-defvar c-recognize-post-brace-list-type-p + (c-lang-const c-recognize-post-brace-list-type-p)) + (c-lang-defconst c-other-block-decl-kwds "Keywords where the following block (if any) contains another declaration level that should not be considered a class. For every -- 2.11.4.GIT