1
Fork 0
mirror of git://git.sv.gnu.org/emacs.git synced 2025-12-09 07:40:39 -08:00

Enhance fontification of declarators to take account of the

presence/absence of "typedef".

cc-engine.el (c-forward-type): New &optional param "brace-block-too".
(c-forward-decl-or-cast-1): cdr of return value now indicates the
presence of either or both of a "struct"-like keyword and "typedef".

cc-fonts.el (c-complex-decl-matchers): Remove the heuristic fontification
of declarators which follow a "}".
(c-font-lock-declarations): Fontify declarators according to the
presence/absence of "typedef".

cc-langs.el (c-typedef-kwds c-typedef-key): New lang variable for
"typedef".
(c-typedef-decl-key): New lang variable built from c-typedef-decl-kwds.
This commit is contained in:
Alan Mackenzie 2010-10-09 19:58:28 +00:00
parent eef3ab9443
commit e15f8aaa0e
4 changed files with 311 additions and 148 deletions

View file

@ -1,3 +1,24 @@
2010-10-09 Alan Mackenzie <acm@muc.de>
Enhance fontification of declarators to take account of the
presence/absence of "typedef".
* cc-engine.el (c-forward-type): New &optional param
"brace-block-too".
(c-forward-decl-or-cast-1): cdr of return value now indicates the
presence of either or both of a "struct"-like keyword and
"typedef".
* cc-fonts.el (c-complex-decl-matchers): Remove the heuristic
fontification of declarators which follow a "}".
(c-font-lock-declarations): Fontify declarators according to the
presence/absence of "typedef".
* cc-langs.el (c-typedef-kwds c-typedef-key): New lang variable
for "typedef".
(c-typedef-decl-key): New lang variable built from
c-typedef-decl-kwds.
2010-10-09 Lars Magne Ingebrigtsen <larsi@gnus.org> 2010-10-09 Lars Magne Ingebrigtsen <larsi@gnus.org>
* ibuffer.el (ibuffer-mode-map): Don't redefine the cursor keys, * ibuffer.el (ibuffer-mode-map): Don't redefine the cursor keys,

View file

@ -5646,17 +5646,23 @@ comment at the start of cc-engine.el for more info."
(defun c-forward-name () (defun c-forward-name ()
;; Move forward over a complete name if at the beginning of one, ;; Move forward over a complete name if at the beginning of one,
;; stopping at the next following token. If the point is not at ;; stopping at the next following token. A keyword, as such,
;; something that are recognized as name then it stays put. A name ;; doesn't count as a name. If the point is not at something that
;; could be something as simple as "foo" in C or something as ;; is recognized as a name then it stays put.
;;
;; A name could be something as simple as "foo" in C or something as
;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> :: ;; complex as "X<Y<class A<int>::B, BIT_MAX >> b>, ::operator<> ::
;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short ;; Z<(a>b)> :: operator const X<&foo>::T Q::G<unsigned short
;; int>::*volatile const" in C++ (this function is actually little ;; int>::*volatile const" in C++ (this function is actually little
;; more than a `looking-at' call in all modes except those that, ;; more than a `looking-at' call in all modes except those that,
;; like C++, have `c-recognize-<>-arglists' set). Return nil if no ;; like C++, have `c-recognize-<>-arglists' set).
;; name is found, 'template if it's an identifier ending with an ;;
;; angle bracket arglist, 'operator of it's an operator identifier, ;; Return
;; or t if it's some other kind of name. ;; o - nil if no name is found;
;; o - 'template if it's an identifier ending with an angle bracket
;; arglist;
;; o - 'operator of it's an operator identifier;
;; o - t if it's some other kind of name.
;; ;;
;; This function records identifier ranges on ;; This function records identifier ranges on
;; `c-record-type-identifiers' and `c-record-ref-identifiers' if ;; `c-record-type-identifiers' and `c-record-ref-identifiers' if
@ -5808,16 +5814,28 @@ comment at the start of cc-engine.el for more info."
(goto-char pos) (goto-char pos)
res)) res))
(defun c-forward-type () (defun c-forward-type (&optional brace-block-too)
;; Move forward over a type spec if at the beginning of one, ;; Move forward over a type spec if at the beginning of one,
;; stopping at the next following token. Return t if it's a known ;; stopping at the next following token. The keyword "typedef"
;; type that can't be a name or other expression, 'known if it's an ;; isn't part of a type spec here.
;; otherwise known type (according to `*-font-lock-extra-types'), ;;
;; 'prefix if it's a known prefix of a type, 'found if it's a type ;; BRACE-BLOCK-TOO, when non-nil, means move over the brace block in
;; that matches one in `c-found-types', 'maybe if it's an identfier ;; constructs like "struct foo {...} bar ;" or "struct {...} bar;".
;; that might be a type, or nil if it can't be a type (the point ;; The current (2009-03-10) intention is to convert all uses of
;; isn't moved then). The point is assumed to be at the beginning ;; `c-forward-type' to call with this parameter set, then to
;; of a token. ;; eliminate it.
;;
;; Return
;; o - t if it's a known type that can't be a name or other
;; expression;
;; o - 'known if it's an otherwise known type (according to
;; `*-font-lock-extra-types');
;; o - 'prefix if it's a known prefix of a type;
;; o - 'found if it's a type that matches one in `c-found-types';
;; o - 'maybe if it's an identfier that might be a type; or
;; o - nil if it can't be a type (the point isn't moved then).
;;
;; The point is assumed to be at the beginning of a token.
;; ;;
;; Note that this function doesn't skip past the brace definition ;; Note that this function doesn't skip past the brace definition
;; that might be considered part of the type, e.g. ;; that might be considered part of the type, e.g.
@ -5836,32 +5854,39 @@ comment at the start of cc-engine.el for more info."
;; Skip leading type modifiers. If any are found we know it's a ;; Skip leading type modifiers. If any are found we know it's a
;; prefix of a type. ;; prefix of a type.
(when c-opt-type-modifier-key (when c-opt-type-modifier-key ; e.g. "const" "volatile", but NOT "typedef"
(while (looking-at c-opt-type-modifier-key) (while (looking-at c-opt-type-modifier-key)
(goto-char (match-end 1)) (goto-char (match-end 1))
(c-forward-syntactic-ws) (c-forward-syntactic-ws)
(setq res 'prefix))) (setq res 'prefix)))
(cond (cond
((looking-at c-type-prefix-key) ((looking-at c-type-prefix-key) ; e.g. "struct", "class", but NOT
;; Looking at a keyword that prefixes a type identifier, ; "typedef".
;; e.g. "class".
(goto-char (match-end 1)) (goto-char (match-end 1))
(c-forward-syntactic-ws) (c-forward-syntactic-ws)
(setq pos (point)) (setq pos (point))
(if (memq (setq name-res (c-forward-name)) '(t template))
(progn (setq name-res (c-forward-name))
(when (eq name-res t) (setq res (not (null name-res)))
;; In many languages the name can be used without the (when (eq name-res t)
;; prefix, so we add it to `c-found-types'. ;; In many languages the name can be used without the
(c-add-type pos (point)) ;; prefix, so we add it to `c-found-types'.
(when (and c-record-type-identifiers (c-add-type pos (point))
c-last-identifier-range) (when (and c-record-type-identifiers
(c-record-type-id c-last-identifier-range))) c-last-identifier-range)
(setq res t)) (c-record-type-id c-last-identifier-range)))
;; Invalid syntax. (when (and brace-block-too
(goto-char start) (memq res '(t nil))
(setq res nil))) (eq (char-after) ?\{)
(save-excursion
(c-safe
(progn (c-forward-sexp)
(c-forward-syntactic-ws)
(setq pos (point))))))
(goto-char pos)
(setq res t))
(unless res (goto-char start))) ; invalid syntax
((progn ((progn
(setq pos nil) (setq pos nil)
@ -5951,14 +5976,13 @@ comment at the start of cc-engine.el for more info."
(setq res nil))))) (setq res nil)))))
(when res (when res
;; Skip trailing type modifiers. If any are found we know it's ;; Skip trailing type modifiers. If any are found we know it's
;; a type. ;; a type.
(when c-opt-type-modifier-key (when c-opt-type-modifier-key
(while (looking-at c-opt-type-modifier-key) (while (looking-at c-opt-type-modifier-key) ; e.g. "const", "volatile"
(goto-char (match-end 1)) (goto-char (match-end 1))
(c-forward-syntactic-ws) (c-forward-syntactic-ws)
(setq res t))) (setq res t)))
;; Step over any type suffix operator. Do not let the existence ;; Step over any type suffix operator. Do not let the existence
;; of these alter the classification of the found type, since ;; of these alter the classification of the found type, since
;; these operators typically are allowed in normal expressions ;; these operators typically are allowed in normal expressions
@ -5968,7 +5992,7 @@ comment at the start of cc-engine.el for more info."
(goto-char (match-end 1)) (goto-char (match-end 1))
(c-forward-syntactic-ws))) (c-forward-syntactic-ws)))
(when c-opt-type-concat-key (when c-opt-type-concat-key ; Only/mainly for pike.
;; Look for a trailing operator that concatenates the type ;; Look for a trailing operator that concatenates the type
;; with a following one, and if so step past that one through ;; with a following one, and if so step past that one through
;; a recursive call. Note that we don't record concatenated ;; a recursive call. Note that we don't record concatenated
@ -6119,11 +6143,15 @@ comment at the start of cc-engine.el for more info."
;; car ^ ^ point ;; car ^ ^ point
;; Foo::Foo (int b) : Base (b) {} ;; Foo::Foo (int b) : Base (b) {}
;; car ^ ^ point ;; car ^ ^ point
;; ;;
;; The cdr of the return value is non-nil iff a `c-typedef-decl-kwds' ;; The cdr of the return value is non-nil when a
;; specifier (e.g. class, struct, enum, typedef) is found in the ;; `c-typedef-decl-kwds' specifier is found in the declaration.
;; declaration, i.e. the declared identifier(s) are types. ;; Specifically it is a dotted pair (A . B) where B is t when a
;; ;; `c-typedef-kwds' ("typedef") is present, and A is t when some
;; other `c-typedef-decl-kwds' (e.g. class, struct, enum)
;; specifier is present. I.e., (some of) the declared
;; identifier(s) are types.
;;
;; If a cast is parsed: ;; If a cast is parsed:
;; ;;
;; The point is left at the first token after the closing paren of ;; The point is left at the first token after the closing paren of
@ -6181,9 +6209,11 @@ comment at the start of cc-engine.el for more info."
;; If `backup-at-type' is nil then the other variables have ;; If `backup-at-type' is nil then the other variables have
;; undefined values. ;; undefined values.
backup-at-type backup-type-start backup-id-start backup-at-type backup-type-start backup-id-start
;; Set if we've found a specifier that makes the defined ;; Set if we've found a specifier (apart from "typedef") that makes
;; identifier(s) types. ;; the defined identifier(s) types.
at-type-decl at-type-decl
;; Set if we've a "typedef" keyword.
at-typedef
;; Set if we've found a specifier that can start a declaration ;; Set if we've found a specifier that can start a declaration
;; where there's no type. ;; where there's no type.
maybe-typeless maybe-typeless
@ -6223,12 +6253,14 @@ comment at the start of cc-engine.el for more info."
;; Look for a specifier keyword clause. ;; Look for a specifier keyword clause.
(when (looking-at c-prefix-spec-kwds-re) (when (looking-at c-prefix-spec-kwds-re)
(if (looking-at c-typedef-key)
(setq at-typedef t))
(setq kwd-sym (c-keyword-sym (match-string 1))) (setq kwd-sym (c-keyword-sym (match-string 1)))
(save-excursion (save-excursion
(c-forward-keyword-clause 1) (c-forward-keyword-clause 1)
(setq kwd-clause-end (point)))) (setq kwd-clause-end (point))))
(when (setq found-type (c-forward-type)) (when (setq found-type (c-forward-type t)) ; brace-block-too
;; Found a known or possible type or a prefix of a known type. ;; Found a known or possible type or a prefix of a known type.
(when at-type (when at-type
@ -6293,6 +6325,8 @@ comment at the start of cc-engine.el for more info."
(setq backup-maybe-typeless t))) (setq backup-maybe-typeless t)))
(when (c-keyword-member kwd-sym 'c-typedef-decl-kwds) (when (c-keyword-member kwd-sym 'c-typedef-decl-kwds)
;; This test only happens after we've scanned a type.
;; So, with valid syntax, kwd-sym can't be 'typedef.
(setq at-type-decl t)) (setq at-type-decl t))
(when (c-keyword-member kwd-sym 'c-typeless-decl-kwds) (when (c-keyword-member kwd-sym 'c-typeless-decl-kwds)
(setq maybe-typeless t)) (setq maybe-typeless t))
@ -6892,7 +6926,9 @@ comment at the start of cc-engine.el for more info."
(goto-char type-start) (goto-char type-start)
(c-forward-type)))) (c-forward-type))))
(cons id-start at-type-decl)) (cons id-start
(and (or at-type-decl at-typedef)
(cons at-type-decl at-typedef))))
(t (t
;; False alarm. Restore the recorded ranges. ;; False alarm. Restore the recorded ranges.

View file

@ -289,7 +289,7 @@
;; bit of the overhead compared to a real matcher. The main reason ;; bit of the overhead compared to a real matcher. The main reason
;; is however to pass the real search limit to the anchored ;; is however to pass the real search limit to the anchored
;; matcher(s), since most (if not all) font-lock implementations ;; matcher(s), since most (if not all) font-lock implementations
;; arbitrarily limits anchored matchers to the same line, and also ;; arbitrarily limit anchored matchers to the same line, and also
;; to insulate against various other irritating differences between ;; to insulate against various other irritating differences between
;; the different (X)Emacs font-lock packages. ;; the different (X)Emacs font-lock packages.
;; ;;
@ -310,7 +310,7 @@
;; covered by the font-lock context.) ;; covered by the font-lock context.)
;; Note: Replace `byte-compile' with `eval' to debug the generated ;; Note: Replace `byte-compile' with `eval' to debug the generated
;; lambda easier. ;; lambda more easily.
(byte-compile (byte-compile
`(lambda (limit) `(lambda (limit)
(let (;; The font-lock package in Emacs is known to clobber (let (;; The font-lock package in Emacs is known to clobber
@ -721,16 +721,26 @@ casts and declarations are fontified. Used on level 2 and higher."
;; Clear the list of found types if we start from the start of the ;; Clear the list of found types if we start from the start of the
;; buffer, to make it easier to get rid of misspelled types and ;; buffer, to make it easier to get rid of misspelled types and
;; variables that has gotten recognized as types in malformed code. ;; variables that have gotten recognized as types in malformed code.
(when (bobp) (when (bobp)
(c-clear-found-types)) (c-clear-found-types))
;; Clear the c-type char properties in the region to recalculate ;; Clear the c-type char properties which mark the region, to recalculate
;; them properly. This is necessary e.g. to handle constructs that ;; them properly. The most interesting properties are those put on the
;; might been required as declarations temporarily during editing. ;; closest token before the region.
;; The interesting properties are anyway those put on the closest (save-excursion
;; token before the region. (let ((pos (point)))
(c-clear-char-properties (point) limit 'c-type) (c-backward-syntactic-ws)
(c-clear-char-properties
(if (and (not (bobp))
(memq (c-get-char-property (1- (point)) 'c-type)
'(c-decl-arg-start
c-decl-end
c-decl-id-start
c-decl-type-start)))
(1- (point))
pos)
limit 'c-type)))
;; Update `c-state-cache' to the beginning of the region. This will ;; Update `c-state-cache' to the beginning of the region. This will
;; make `c-beginning-of-syntax' go faster when it's used later on, ;; make `c-beginning-of-syntax' go faster when it's used later on,
@ -739,6 +749,8 @@ casts and declarations are fontified. Used on level 2 and higher."
;; Check if the fontified region starts inside a declarator list so ;; Check if the fontified region starts inside a declarator list so
;; that `c-font-lock-declarators' should be called at the start. ;; that `c-font-lock-declarators' should be called at the start.
;; The declared identifiers are font-locked correctly as types, if
;; that is what they are.
(let ((prop (save-excursion (let ((prop (save-excursion
(c-backward-syntactic-ws) (c-backward-syntactic-ws)
(unless (bobp) (unless (bobp)
@ -831,12 +843,19 @@ casts and declarations are fontified. Used on level 2 and higher."
nil) nil)
(defun c-font-lock-declarators (limit list types) (defun c-font-lock-declarators (limit list types)
;; Assuming the point is at the start of a declarator in a ;; Assuming the point is at the start of a declarator in a declaration,
;; declaration, fontify it. If LIST is non-nil, fontify also all ;; fontify the identifier it declares. (If TYPES is set, it does this via
;; following declarators in a comma separated list (e.g. "foo" and ;; the macro `c-fontify-types-and-refs'.)
;; "bar" in "int foo = 17, bar;"). Stop at LIMIT. If TYPES is ;;
;; non-nil, fontify all identifiers as types. Nil is always ;; If LIST is non-nil, also fontify the ids in any following declarators in
;; returned. ;; a comma separated list (e.g. "foo" and "*bar" in "int foo = 17, *bar;");
;; additionally, mark the commas with c-type property 'c-decl-id-start or
;; 'c-decl-type-start (according to TYPES). Stop at LIMIT.
;;
;; If TYPES is non-nil, fontify all identifiers as types.
;;
;; Nil is always returned. The function leaves point at the delimiter after
;; the last declarator it processes.
;; ;;
;; This function might do hidden buffer changes. ;; This function might do hidden buffer changes.
@ -848,18 +867,31 @@ casts and declarations are fontified. Used on level 2 and higher."
c-last-identifier-range c-last-identifier-range
(separator-prop (if types 'c-decl-type-start 'c-decl-id-start))) (separator-prop (if types 'c-decl-type-start 'c-decl-id-start)))
(while (and ;; The following `while' fontifies a single declarator id each time round.
;; It loops only when LIST is non-nil.
(while
;; Inside the following "condition form", we move forward over the
;; declarator's identifier up as far as any opening bracket (for array
;; size) or paren (for parameters of function-type) or brace (for
;; array/struct initialisation) or "=" or terminating delimiter
;; (e.g. "," or ";" or "}").
(and
pos pos
(< (point) limit) (< (point) limit)
;; The following form moves forward over the declarator's
;; identifier (and what precedes it), returning t. If there
;; wasn't one, it returns nil, terminating the `while'.
(let (got-identifier) (let (got-identifier)
(setq paren-depth 0) (setq paren-depth 0)
;; Skip over type decl prefix operators. (Note similar ;; Skip over type decl prefix operators, one for each iteration
;; code in `c-forward-decl-or-cast-1'.) ;; of the while. These are, e.g. "*" in "int *foo" or "(" and
;; "*" in "int (*foo) (void)" (Note similar code in
;; `c-forward-decl-or-cast-1'.)
(while (and (looking-at c-type-decl-prefix-key) (while (and (looking-at c-type-decl-prefix-key)
(if (and (c-major-mode-is 'c++-mode) (if (and (c-major-mode-is 'c++-mode)
(match-beginning 2)) (match-beginning 3))
;; If the second submatch matches in C++ then ;; If the third submatch matches in C++ then
;; we're looking at an identifier that's a ;; we're looking at an identifier that's a
;; prefix only if it specifies a member pointer. ;; prefix only if it specifies a member pointer.
(progn (progn
@ -882,7 +914,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(goto-char (match-end 1))) (goto-char (match-end 1)))
(c-forward-syntactic-ws)) (c-forward-syntactic-ws))
;; If we didn't pass the identifier above already, do it now. ;; If we haven't passed the identifier already, do it now.
(unless got-identifier (unless got-identifier
(setq id-start (point)) (setq id-start (point))
(c-forward-name)) (c-forward-name))
@ -890,12 +922,14 @@ casts and declarations are fontified. Used on level 2 and higher."
(/= id-end pos)) (/= id-end pos))
;; Skip out of the parens surrounding the identifier. ;; Skip out of the parens surrounding the identifier. If closing
;; parens are missing, this form returns nil.
(or (= paren-depth 0) (or (= paren-depth 0)
(c-safe (goto-char (scan-lists (point) 1 paren-depth)))) (c-safe (goto-char (scan-lists (point) 1 paren-depth))))
(<= (point) limit) (<= (point) limit)
;; Skip over any trailing bit, such as "__attribute__".
(progn (progn
(when (looking-at c-decl-hangon-key) (when (looking-at c-decl-hangon-key)
(c-forward-keyword-clause 1)) (c-forward-keyword-clause 1))
@ -936,7 +970,7 @@ casts and declarations are fontified. Used on level 2 and higher."
id-face))) id-face)))
(goto-char next-pos) (goto-char next-pos)
(setq pos nil) (setq pos nil) ; So as to terminate the enclosing `while' form.
(when list (when list
;; Jump past any initializer or function prototype to see if ;; Jump past any initializer or function prototype to see if
;; there's a ',' to continue at. ;; there's a ',' to continue at.
@ -944,11 +978,11 @@ casts and declarations are fontified. Used on level 2 and higher."
(cond ((eq id-face 'font-lock-function-name-face) (cond ((eq id-face 'font-lock-function-name-face)
;; Skip a parenthesized initializer (C++) or a function ;; Skip a parenthesized initializer (C++) or a function
;; prototype. ;; prototype.
(if (c-safe (c-forward-sexp 1) t) (if (c-safe (c-forward-sexp 1) t) ; over the parameter list.
(c-forward-syntactic-ws limit) (c-forward-syntactic-ws limit)
(goto-char limit))) (goto-char limit))) ; unbalanced parens
(got-init (got-init ; "=" sign OR opening "(", "[", or "{"
;; Skip an initializer expression. If we're at a '=' ;; Skip an initializer expression. If we're at a '='
;; then accept a brace list directly after it to cope ;; then accept a brace list directly after it to cope
;; with array initializers. Otherwise stop at braces ;; with array initializers. Otherwise stop at braces
@ -956,7 +990,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(and (if (and (eq got-init ?=) (and (if (and (eq got-init ?=)
(= (c-forward-token-2 1 nil limit) 0) (= (c-forward-token-2 1 nil limit) 0)
(looking-at "{")) (looking-at "{"))
(c-safe (c-forward-sexp) t) (c-safe (c-forward-sexp) t) ; over { .... }
t) t)
;; FIXME: Should look for c-decl-end markers here; ;; FIXME: Should look for c-decl-end markers here;
;; we might go far into the following declarations ;; we might go far into the following declarations
@ -971,7 +1005,7 @@ casts and declarations are fontified. Used on level 2 and higher."
(c-put-char-property (point) 'c-type separator-prop) (c-put-char-property (point) 'c-type separator-prop)
(forward-char) (forward-char)
(c-forward-syntactic-ws limit) (c-forward-syntactic-ws limit)
(setq pos (point)))))) (setq pos (point)))))) ; acts to make the `while' form continue.
nil) nil)
(defconst c-font-lock-maybe-decl-faces (defconst c-font-lock-maybe-decl-faces
@ -984,27 +1018,29 @@ casts and declarations are fontified. Used on level 2 and higher."
font-lock-keyword-face)) font-lock-keyword-face))
(defun c-font-lock-declarations (limit) (defun c-font-lock-declarations (limit)
;; Fontify all the declarations, casts and labels from the point to LIMIT.
;; Assumes that strings and comments have been fontified already.
;;
;; This function will be called from font-lock for a region bounded by POINT ;; 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 ;; and LIMIT, as though it were to identify a keyword for
;; font-lock-keyword-face. It always returns NIL to inhibit this and ;; font-lock-keyword-face. It always returns NIL to inhibit this and
;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; prevent a repeat invocation. See elisp/lispref page "Search-based
;; Fontification". ;; Fontification".
;; ;;
;; Fontify all the declarations, casts and labels from the point to LIMIT.
;; Assumes that strings and comments have been fontified already.
;;
;; This function might do hidden buffer changes. ;; This function might do hidden buffer changes.
;;(message "c-font-lock-declarations search from %s to %s" (point) limit) ;;(message "c-font-lock-declarations search from %s to %s" (point) limit)
(save-restriction (save-restriction
(let (;; The position where `c-find-decl-spots' stopped. (let (;; The position where `c-find-decl-spots' last stopped.
start-pos start-pos
;; 'decl if we're in an arglist containing declarations (but ;; o - 'decl if we're in an arglist containing declarations
;; if `c-recognize-paren-inits' is set it might also be an ;; (but if `c-recognize-paren-inits' is set it might also be
;; initializer arglist), '<> if the arglist is of angle ;; an initializer arglist);
;; bracket type, 'arglist if it's some other arglist, or nil ;; o - '<> if the arglist is of angle bracket type;
;; if not in an arglist at all. ;; o - 'arglist if it's some other arglist;
;; o - nil, if not in an arglist at all. This includes the
;; parenthesised condition which follows "if", "while", etc.
context context
;; The position of the next token after the closing paren of ;; The position of the next token after the closing paren of
;; the last detected cast. ;; the last detected cast.
@ -1082,57 +1118,106 @@ casts and declarations are fontified. Used on level 2 and higher."
;; can't start a declaration. ;; can't start a declaration.
t t
;; Set `context'. Look for "<" for the sake of C++-style template ;; Set `context' and `c-restricted-<>-arglists'. Look for
;; arglists. ;; "<" for the sake of C++-style template arglists.
(if (memq (char-before match-pos) '(?\( ?, ?\[ ?<)) ;; Ignore "(" when it's part of a control flow construct
;; (e.g. "for (").
(let ((type (and (> match-pos (point-min))
(c-get-char-property (1- match-pos) 'c-type))))
(cond ((not (memq (char-before match-pos) '(?\( ?, ?\[ ?<)))
(setq context nil
c-restricted-<>-arglists nil))
;; A control flow expression
((and (eq (char-before match-pos) ?\()
(save-excursion
(goto-char match-pos)
(backward-char)
(c-backward-token-2)
(looking-at c-block-stmt-2-key)))
(setq context nil
c-restricted-<>-arglists t))
;; Near BOB.
((<= match-pos (point-min))
(setq context 'arglist
c-restricted-<>-arglists t))
;; Got a cached hit in a declaration arglist.
((eq type 'c-decl-arg-start)
(setq context 'decl
c-restricted-<>-arglists nil))
;; Inside an angle bracket arglist.
((or (eq type 'c-<>-arg-sep)
(eq (char-before match-pos) ?<))
(setq context '<>
c-restricted-<>-arglists nil))
;; Got a cached hit in some other type of arglist.
(type
(setq context 'arglist
c-restricted-<>-arglists t))
((if inside-macro
(< match-pos max-type-decl-end-before-token)
(< match-pos max-type-decl-end))
;; The point is within the range of a previously
;; encountered type decl expression, so the arglist
;; is probably one that contains declarations.
;; However, if `c-recognize-paren-inits' is set it
;; might also be an initializer arglist.
(setq context 'decl
c-restricted-<>-arglists nil)
;; The result of this check is cached with a char
;; property on the match token, so that we can look
;; it up again when refontifying single lines in a
;; multiline declaration.
(c-put-char-property (1- match-pos)
'c-type 'c-decl-arg-start))
(t (setq context 'arglist
c-restricted-<>-arglists t))))
;; Find out the type of the arglist. ;; Check we haven't missed a preceding "typedef".
(if (<= match-pos (point-min)) (when (not (looking-at c-typedef-key))
(setq context 'arglist) (c-backward-syntactic-ws)
(let ((type (c-get-char-property (1- match-pos) 'c-type))) (c-backward-token-2)
(cond ((eq type 'c-decl-arg-start) (or (looking-at c-typedef-key)
;; Got a cached hit in a declaration arglist. (goto-char start-pos)))
(setq context 'decl))
((or (eq type 'c-<>-arg-sep)
(eq (char-before match-pos) ?<))
;; Inside an angle bracket arglist.
(setq context '<>))
(type
;; Got a cached hit in some other type of arglist.
(setq context 'arglist))
((if inside-macro
(< match-pos max-type-decl-end-before-token)
(< match-pos max-type-decl-end))
;; The point is within the range of a previously
;; encountered type decl expression, so the arglist
;; is probably one that contains declarations.
;; However, if `c-recognize-paren-inits' is set it
;; might also be an initializer arglist.
(setq context 'decl)
;; The result of this check is cached with a char
;; property on the match token, so that we can look
;; it up again when refontifying single lines in a
;; multiline declaration.
(c-put-char-property (1- match-pos)
'c-type 'c-decl-arg-start))
(t
(setq context 'arglist)))))
(setq context nil)) ;; Now analyze the construct.
(setq decl-or-cast (c-forward-decl-or-cast-1
;; If we're in a normal arglist context we don't want to
;; recognize commas in nested angle bracket arglists since
;; those commas could be part of our own arglist.
(setq c-restricted-<>-arglists (and c-recognize-<>-arglists
(eq context 'arglist))
;; Now analyze the construct.
decl-or-cast (c-forward-decl-or-cast-1
match-pos context last-cast-end)) match-pos context last-cast-end))
(if (not decl-or-cast) (if (not decl-or-cast)
;; False alarm. Return t to go on to the next check. ;; Are we at a declarator?
t ;; Try to go back to the declaration to check this.
(let (paren-state bod-res lim encl-pos is-typedef)
(goto-char start-pos)
(save-excursion
(setq lim (and (c-syntactic-skip-backward "^;" nil t)
(point))))
(save-excursion
(setq bod-res (car (c-beginning-of-decl-1 lim)))
(if (and (eq bod-res 'same)
(progn
(c-backward-syntactic-ws)
(eq (char-before) ?\})))
(c-beginning-of-decl-1 lim))
;; We're now putatively at the declaration.
(setq paren-state (c-parse-state))
;; At top level or inside a "{"?
(if (or (not (setq encl-pos
(c-most-enclosing-brace paren-state)))
(eq (char-after encl-pos) ?\{))
(progn
(when (looking-at c-typedef-key) ; "typedef"
(setq is-typedef t)
(goto-char (match-end 0))
(c-forward-syntactic-ws))
;; At a real declaration?
(if (memq (c-forward-type t) '(t known found))
(progn
(c-font-lock-declarators limit t is-typedef)
nil)
;; False alarm. Return t to go on to the next check.
(goto-char start-pos)
t))
t)))
(if (eq decl-or-cast 'cast) (if (eq decl-or-cast 'cast)
;; Save the position after the previous cast so we can feed ;; Save the position after the previous cast so we can feed
@ -1296,7 +1381,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
"Complex font lock matchers for types and declarations. Used on level "Complex font lock matchers for types and declarations. Used on level
3 and higher." 3 and higher."
;; Note: This code in this form dumps a number of funtions into the ;; Note: This code in this form dumps a number of functions into the
;; resulting constant, `c-matchers-3'. At run time, font lock will call ;; resulting constant, `c-matchers-3'. At run time, font lock will call
;; each of them as a "FUNCTION" (see Elisp page "Search-based ;; each of them as a "FUNCTION" (see Elisp page "Search-based
;; Fontification"). The font lock region is delimited by POINT and the ;; Fontification"). The font lock region is delimited by POINT and the
@ -1348,7 +1433,7 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
`(,(concat "\\<\\(" re "\\)\\>") `(,(concat "\\<\\(" re "\\)\\>")
1 'font-lock-type-face))) 1 'font-lock-type-face)))
;; Fontify types preceded by `c-type-prefix-kwds'. ;; Fontify types preceded by `c-type-prefix-kwds' (e.g. "struct").
,@(when (c-lang-const c-type-prefix-kwds) ,@(when (c-lang-const c-type-prefix-kwds)
`((,(byte-compile `((,(byte-compile
`(lambda (limit) `(lambda (limit)
@ -1396,23 +1481,25 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'."
;; override it if it turns out to be an new declaration, but ;; override it if it turns out to be an new declaration, but
;; it will be wrong if it's an expression (see the test ;; it will be wrong if it's an expression (see the test
;; decls-8.cc). ;; decls-8.cc).
,@(when (c-lang-const c-opt-block-decls-with-vars-key) ;; ,@(when (c-lang-const c-opt-block-decls-with-vars-key)
`((,(c-make-font-lock-search-function ;; `((,(c-make-font-lock-search-function
(concat "}" ;; (concat "}"
(c-lang-const c-single-line-syntactic-ws) ;; (c-lang-const c-single-line-syntactic-ws)
"\\(" ; 1 + c-single-line-syntactic-ws-depth ;; "\\(" ; 1 + c-single-line-syntactic-ws-depth
(c-lang-const c-type-decl-prefix-key) ;; (c-lang-const c-type-decl-prefix-key)
"\\|" ;; "\\|"
(c-lang-const c-symbol-key) ;; (c-lang-const c-symbol-key)
"\\)") ;; "\\)")
`((c-font-lock-declarators limit t nil) ;; `((c-font-lock-declarators limit t nil) ; That `nil' says use `font-lock-variable-name-face';
(progn ;; ; `t' would mean `font-lock-function-name-face'.
(c-put-char-property (match-beginning 0) 'c-type ;; (progn
'c-decl-id-start) ;; (c-put-char-property (match-beginning 0) 'c-type
(goto-char (match-beginning ;; 'c-decl-id-start)
,(1+ (c-lang-const ;; ; 'c-decl-type-start)
c-single-line-syntactic-ws-depth))))) ;; (goto-char (match-beginning
(goto-char (match-end 0))))))) ;; ,(1+ (c-lang-const
;; c-single-line-syntactic-ws-depth)))))
;; (goto-char (match-end 0)))))))
;; Fontify the type in C++ "new" expressions. ;; Fontify the type in C++ "new" expressions.
,@(when (c-major-mode-is 'c++-mode) ,@(when (c-major-mode-is 'c++-mode)
@ -1660,6 +1747,10 @@ need for `c-font-lock-extra-types'.")
;;; C++. ;;; C++.
(defun c-font-lock-c++-new (limit) (defun c-font-lock-c++-new (limit)
;; FIXME!!! Put in a comment about the context of this function's
;; invocation. I think it's called as an ANCHORED-MATCHER within an
;; ANCHORED-HIGHLIGHTER. (2007/2/10).
;;
;; Assuming point is after a "new" word, check that it isn't inside ;; Assuming point is after a "new" word, check that it isn't inside
;; a string or comment, and if so try to fontify the type in the ;; a string or comment, and if so try to fontify the type in the
;; allocation expression. Nil is always returned. ;; allocation expression. Nil is always returned.

View file

@ -1565,6 +1565,17 @@ be a subset of `c-primitive-type-kwds'."
;; In CORBA PSDL: ;; In CORBA PSDL:
"strong")) "strong"))
(c-lang-defconst c-typedef-kwds
"Prefix keyword\(s\) like \"typedef\" which make a type declaration out
of a variable declaration."
t '("typedef")
(awk idl java) nil)
(c-lang-defconst c-typedef-key
;; Adorned regexp matching `c-typedef-kwds'.
t (c-make-keywords-re t (c-lang-const c-typedef-kwds)))
(c-lang-defvar c-typedef-key (c-lang-const c-typedef-key))
(c-lang-defconst c-type-prefix-kwds (c-lang-defconst c-type-prefix-kwds
"Keywords where the following name - if any - is a type name, and "Keywords where the following name - if any - is a type name, and
where the keyword together with the symbol works as a type in where the keyword together with the symbol works as a type in
@ -1731,6 +1742,10 @@ will be handled."
;; types in IDL since they only can occur in "raises" specs. ;; types in IDL since they only can occur in "raises" specs.
idl (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil))) idl (delete "exception" (append (c-lang-const c-typedef-decl-kwds) nil)))
(c-lang-defconst c-typedef-decl-key
t (c-make-keywords-re t (c-lang-const c-typedef-decl-kwds)))
(c-lang-defvar c-typedef-decl-key (c-lang-const c-typedef-decl-key))
(c-lang-defconst c-typeless-decl-kwds (c-lang-defconst c-typeless-decl-kwds
"Keywords introducing declarations where the \(first) identifier "Keywords introducing declarations where the \(first) identifier
\(declarator) follows directly after the keyword, without any type. \(declarator) follows directly after the keyword, without any type.