From: Alan Mackenzie Date: Tue, 23 Apr 2019 09:16:05 +0000 (+0000) Subject: Optimize for typing characters into long C++ raw strings. X-Git-Tag: emacs-27.0.90~3128 X-Git-Url: http://git.eshelyaron.com/gitweb/?a=commitdiff_plain;h=0d5caa9a0c668d06ab650392bd52ad03a4dfbd1a;p=emacs.git Optimize for typing characters into long C++ raw strings. * lisp/progmodes/cc-fonts.el (c-font-lock-complex-decl-prepare) (c-font-lock-objc-methods) (c-font-lock-declarations, c-font-lock-enum-tail) (c-font-lock-cut-off-declarators, c-font-lock-enclosing-decls): If the chunk been fontified consists entirely of comments and strings, don't attempt to perform the function's action. * lisp/progmodes/cc-mode.el (c-before-change-check-unbalanced-strings): Don't expand (c-new-BEG c-new-END) unnecessarily to the entire raw string being fontified. (c-fl-decl-start, c-fl-decl-end): When in a (raw or otherwise) string, don't return a position outside of the string (which used to cause unneeded fontification). --- diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index 5832f1f451c..4a5cf5719be 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -880,48 +880,51 @@ casts and declarations are fontified. Used on level 2 and higher." (when (bobp) (c-clear-found-types)) - ;; Clear the c-type char properties which mark the region, to recalculate - ;; them properly. The most interesting properties are those put on the - ;; closest token before the region. - (save-excursion - (let ((pos (point))) - (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 - ;; make `c-beginning-of-syntax' go faster when it's used later on, - ;; and it's near the point most of the time. - (c-parse-state) - - ;; Check if the fontified region starts inside a declarator list so - ;; 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 - (c-backward-syntactic-ws) - (unless (bobp) - (c-get-char-property (1- (point)) 'c-type))))) - (when (memq prop '(c-decl-id-start c-decl-type-start)) - (c-forward-syntactic-ws limit) - (c-font-lock-declarators limit t (eq prop 'c-decl-type-start) - (not (c-bs-at-toplevel-p (point)))))) - - (setq c-font-lock-context ;; (c-guess-font-lock-context) - (save-excursion - (if (and c-cpp-expr-intro-re - (c-beginning-of-macro) - (looking-at c-cpp-expr-intro-re)) - 'in-cpp-expr))) - nil) + (c-skip-comments-and-strings limit) + (when (< (point) limit) + + ;; Clear the c-type char properties which mark the region, to recalculate + ;; them properly. The most interesting properties are those put on the + ;; closest token before the region. + (save-excursion + (let ((pos (point))) + (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 + ;; make `c-beginning-of-syntax' go faster when it's used later on, + ;; and it's near the point most of the time. + (c-parse-state) + + ;; Check if the fontified region starts inside a declarator list so + ;; 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 + (c-backward-syntactic-ws) + (unless (bobp) + (c-get-char-property (1- (point)) 'c-type))))) + (when (memq prop '(c-decl-id-start c-decl-type-start)) + (c-forward-syntactic-ws limit) + (c-font-lock-declarators limit t (eq prop 'c-decl-type-start) + (not (c-bs-at-toplevel-p (point)))))) + + (setq c-font-lock-context ;; (c-guess-font-lock-context) + (save-excursion + (if (and c-cpp-expr-intro-re + (c-beginning-of-macro) + (looking-at c-cpp-expr-intro-re)) + 'in-cpp-expr))) + nil)) (defun c-font-lock-<>-arglists (limit) ;; This function will be called from font-lock for a region bounded by POINT @@ -936,73 +939,76 @@ casts and declarations are fontified. Used on level 2 and higher." ;; ;; This function might do hidden buffer changes. - (let (;; The font-lock package in Emacs is known to clobber - ;; `parse-sexp-lookup-properties' (when it exists). - (parse-sexp-lookup-properties - (cc-eval-when-compile - (boundp 'parse-sexp-lookup-properties))) - (c-parse-and-markup-<>-arglists t) - c-restricted-<>-arglists - id-start id-end id-face pos kwd-sym) + (c-skip-comments-and-strings limit) + (when (< (point) limit) - (while (and (< (point) limit) - (re-search-forward c-opt-<>-arglist-start limit t)) + (let (;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties))) + (c-parse-and-markup-<>-arglists t) + c-restricted-<>-arglists + id-start id-end id-face pos kwd-sym) - (setq id-start (match-beginning 1) - id-end (match-end 1) - pos (point)) + (while (and (< (point) limit) + (re-search-forward c-opt-<>-arglist-start limit t)) - (goto-char id-start) - (unless (c-skip-comments-and-strings limit) - (setq kwd-sym nil - c-restricted-<>-arglists nil - id-face (get-text-property id-start 'face)) - - (if (cond - ((eq id-face 'font-lock-type-face) - ;; The identifier got the type face so it has already been - ;; handled in `c-font-lock-declarations'. - nil) - - ((eq id-face 'font-lock-keyword-face) - (when (looking-at c-opt-<>-sexp-key) - ;; There's a special keyword before the "<" that tells - ;; that it's an angle bracket arglist. - (setq kwd-sym (c-keyword-sym (match-string 1))))) - - (t - ;; There's a normal identifier before the "<". If we're not in - ;; a declaration context then we set `c-restricted-<>-arglists' - ;; to avoid recognizing templates in function calls like "foo (a - ;; < b, c > d)". - (c-backward-syntactic-ws) - (when (and (memq (char-before) '(?\( ?,)) - (not (eq (get-text-property (1- (point)) 'c-type) - 'c-decl-arg-start))) - (setq c-restricted-<>-arglists t)) - t)) + (setq id-start (match-beginning 1) + id-end (match-end 1) + pos (point)) - (progn - (goto-char (1- pos)) - ;; Check for comment/string both at the identifier and - ;; at the "<". - (unless (c-skip-comments-and-strings limit) - - (c-fontify-types-and-refs () - (when (c-forward-<>-arglist (c-keyword-member - kwd-sym 'c-<>-type-kwds)) - (when (and c-opt-identifier-concat-key - (not (get-text-property id-start 'face))) - (c-forward-syntactic-ws) - (cond ((looking-at c-opt-identifier-concat-key) - (c-put-font-lock-face id-start id-end - c-reference-face-name)) - ((eq (char-after) ?\()) - (t (c-put-font-lock-face id-start id-end - 'font-lock-type-face)))))) - - (goto-char pos))) - (goto-char pos))))) + (goto-char id-start) + (unless (c-skip-comments-and-strings limit) + (setq kwd-sym nil + c-restricted-<>-arglists nil + id-face (get-text-property id-start 'face)) + + (if (cond + ((eq id-face 'font-lock-type-face) + ;; The identifier got the type face so it has already been + ;; handled in `c-font-lock-declarations'. + nil) + + ((eq id-face 'font-lock-keyword-face) + (when (looking-at c-opt-<>-sexp-key) + ;; There's a special keyword before the "<" that tells + ;; that it's an angle bracket arglist. + (setq kwd-sym (c-keyword-sym (match-string 1))))) + + (t + ;; There's a normal identifier before the "<". If we're not in + ;; a declaration context then we set `c-restricted-<>-arglists' + ;; to avoid recognizing templates in function calls like "foo (a + ;; < b, c > d)". + (c-backward-syntactic-ws) + (when (and (memq (char-before) '(?\( ?,)) + (not (eq (get-text-property (1- (point)) 'c-type) + 'c-decl-arg-start))) + (setq c-restricted-<>-arglists t)) + t)) + + (progn + (goto-char (1- pos)) + ;; Check for comment/string both at the identifier and + ;; at the "<". + (unless (c-skip-comments-and-strings limit) + + (c-fontify-types-and-refs () + (when (c-forward-<>-arglist (c-keyword-member + kwd-sym 'c-<>-type-kwds)) + (when (and c-opt-identifier-concat-key + (not (get-text-property id-start 'face))) + (c-forward-syntactic-ws) + (cond ((looking-at c-opt-identifier-concat-key) + (c-put-font-lock-face id-start id-end + c-reference-face-name)) + ((eq (char-after) ?\()) + (t (c-put-font-lock-face id-start id-end + 'font-lock-type-face)))))) + + (goto-char pos))) + (goto-char pos)))))) nil) (defun c-font-lock-declarators (limit list types not-top @@ -1311,227 +1317,229 @@ casts and declarations are fontified. Used on level 2 and higher." ;; This function might do hidden buffer changes. ;;(message "c-font-lock-declarations search from %s to %s" (point) limit) + (c-skip-comments-and-strings limit) + (when (< (point) limit) + + (save-restriction + (let (;; The position where `c-find-decl-spots' last stopped. + start-pos + ;; o - 'decl if we're in an arglist containing declarations + ;; (but if `c-recognize-paren-inits' is set it might also be + ;; an initializer arglist); + ;; o - '<> if the arglist is of angle bracket type; + ;; o - 'arglist if it's some other arglist; + ;; o - nil, if not in an arglist at all. This includes the + ;; parenthesized condition which follows "if", "while", etc. + context + ;; A list of starting positions of possible type declarations, or of + ;; the typedef preceding one, if any. + last-cast-end + ;; The result from `c-forward-decl-or-cast-1'. + decl-or-cast + ;; The maximum of the end positions of all the checked type + ;; decl expressions in the successfully identified + ;; declarations. The position might be either before or + ;; after the syntactic whitespace following the last token + ;; in the type decl expression. + (max-type-decl-end 0) + ;; Same as `max-type-decl-*', but used when we're before + ;; `token-pos'. + (max-type-decl-end-before-token 0) + ;; End of <..> construct which has had c-<>-arg-sep c-type + ;; properties set within it. + (max-<>-end 0) + ;; Set according to the context to direct the heuristics for + ;; recognizing C++ templates. + c-restricted-<>-arglists + ;; Turn on recording of identifier ranges in + ;; `c-forward-decl-or-cast-1' and `c-forward-label' for + ;; later fontification. + (c-record-type-identifiers t) + label-type + c-record-ref-identifiers + ;; Make `c-forward-type' calls mark up template arglists if + ;; it finds any. That's necessary so that we later will + ;; stop inside them to fontify types there. + (c-parse-and-markup-<>-arglists t) + ;; The font-lock package in Emacs is known to clobber + ;; `parse-sexp-lookup-properties' (when it exists). + (parse-sexp-lookup-properties + (cc-eval-when-compile + (boundp 'parse-sexp-lookup-properties)) + )) + + ;; Below we fontify a whole declaration even when it crosses the limit, + ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a + ;; time. That is however annoying during editing, e.g. the following is + ;; a common situation while the first line is being written: + ;; + ;; my_variable + ;; some_other_variable = 0; + ;; + ;; font-lock will put the limit at the beginning of the second line + ;; here, and if we go past it we'll fontify "my_variable" as a type and + ;; "some_other_variable" as an identifier, and the latter will not + ;; correct itself until the second line is changed. To avoid that we + ;; narrow to the limit if the region to fontify is a single line. + (if (<= limit (c-point 'bonl)) + (narrow-to-region + (point-min) + (save-excursion + ;; Narrow after any operator chars following the limit though, + ;; since those characters can be useful in recognizing a + ;; declaration (in particular the '{' that opens a function body + ;; after the header). + (goto-char limit) + (skip-chars-forward c-nonsymbol-chars) + (point)))) + + (c-find-decl-spots + limit + c-decl-start-re + (eval c-maybe-decl-faces) + + (lambda (match-pos inside-macro &optional toplev) + ;; Note to maintainers: don't use `limit' inside this lambda form; + ;; c-find-decl-spots sometimes narrows to less than `limit'. + (setq start-pos (point)) + (when + ;; The result of the form below is true when we don't recognize a + ;; declaration or cast, and we don't recognize a "non-decl", + ;; typically a brace list. + (if (or (and (eq (get-text-property (point) 'face) + 'font-lock-keyword-face) + (looking-at c-not-decl-init-keywords)) + (and c-macro-with-semi-re + (looking-at c-macro-with-semi-re))) ; 2008-11-04 + ;; Don't do anything more if we're looking at a keyword that + ;; can't start a declaration. + t + + ;; Set `context' and `c-restricted-<>-arglists'. Look for + ;; "<" for the sake of C++-style template arglists. + ;; Ignore "(" when it's part of a control flow construct + ;; (e.g. "for ("). + (let ((got-context + (c-get-fontification-context + match-pos + (< match-pos (if inside-macro + max-type-decl-end-before-token + max-type-decl-end)) + toplev))) + (setq context (car got-context) + c-restricted-<>-arglists (cdr got-context))) + + ;; Check we haven't missed a preceding "typedef". + (when (not (looking-at c-typedef-key)) + (c-backward-syntactic-ws) + (c-backward-token-2) + (or (looking-at c-typedef-key) + (goto-char start-pos))) + + ;; In QT, "more" is an irritating keyword that expands to nothing. + ;; We skip over it to prevent recognition of "more slots: " + ;; as a bitfield declaration. + (when (and (c-major-mode-is 'c++-mode) + (looking-at + (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)"))) + (goto-char (match-end 1)) + (c-forward-syntactic-ws)) - (save-restriction - (let (;; The position where `c-find-decl-spots' last stopped. - start-pos - ;; o - 'decl if we're in an arglist containing declarations - ;; (but if `c-recognize-paren-inits' is set it might also be - ;; an initializer arglist); - ;; o - '<> if the arglist is of angle bracket type; - ;; o - 'arglist if it's some other arglist; - ;; o - nil, if not in an arglist at all. This includes the - ;; parenthesized condition which follows "if", "while", etc. - context - ;; A list of starting positions of possible type declarations, or of - ;; the typedef preceding one, if any. - last-cast-end - ;; The result from `c-forward-decl-or-cast-1'. - decl-or-cast - ;; The maximum of the end positions of all the checked type - ;; decl expressions in the successfully identified - ;; declarations. The position might be either before or - ;; after the syntactic whitespace following the last token - ;; in the type decl expression. - (max-type-decl-end 0) - ;; Same as `max-type-decl-*', but used when we're before - ;; `token-pos'. - (max-type-decl-end-before-token 0) - ;; End of <..> construct which has had c-<>-arg-sep c-type - ;; properties set within it. - (max-<>-end 0) - ;; Set according to the context to direct the heuristics for - ;; recognizing C++ templates. - c-restricted-<>-arglists - ;; Turn on recording of identifier ranges in - ;; `c-forward-decl-or-cast-1' and `c-forward-label' for - ;; later fontification. - (c-record-type-identifiers t) - label-type - c-record-ref-identifiers - ;; Make `c-forward-type' calls mark up template arglists if - ;; it finds any. That's necessary so that we later will - ;; stop inside them to fontify types there. - (c-parse-and-markup-<>-arglists t) - ;; The font-lock package in Emacs is known to clobber - ;; `parse-sexp-lookup-properties' (when it exists). - (parse-sexp-lookup-properties - (cc-eval-when-compile - (boundp 'parse-sexp-lookup-properties)) - )) - - ;; Below we fontify a whole declaration even when it crosses the limit, - ;; to avoid gaps when jit/lazy-lock fontifies the file a block at a - ;; time. That is however annoying during editing, e.g. the following is - ;; a common situation while the first line is being written: - ;; - ;; my_variable - ;; some_other_variable = 0; - ;; - ;; font-lock will put the limit at the beginning of the second line - ;; here, and if we go past it we'll fontify "my_variable" as a type and - ;; "some_other_variable" as an identifier, and the latter will not - ;; correct itself until the second line is changed. To avoid that we - ;; narrow to the limit if the region to fontify is a single line. - (if (<= limit (c-point 'bonl)) - (narrow-to-region - (point-min) - (save-excursion - ;; Narrow after any operator chars following the limit though, - ;; since those characters can be useful in recognizing a - ;; declaration (in particular the '{' that opens a function body - ;; after the header). - (goto-char limit) - (skip-chars-forward c-nonsymbol-chars) - (point)))) - - (c-find-decl-spots - limit - c-decl-start-re - (eval c-maybe-decl-faces) - - (lambda (match-pos inside-macro &optional toplev) - ;; Note to maintainers: don't use `limit' inside this lambda form; - ;; c-find-decl-spots sometimes narrows to less than `limit'. - (setq start-pos (point)) - (when - ;; The result of the form below is true when we don't recognize a - ;; declaration or cast, and we don't recognize a "non-decl", - ;; typically a brace list. - (if (or (and (eq (get-text-property (point) 'face) - 'font-lock-keyword-face) - (looking-at c-not-decl-init-keywords)) - (and c-macro-with-semi-re - (looking-at c-macro-with-semi-re))) ; 2008-11-04 - ;; Don't do anything more if we're looking at a keyword that - ;; can't start a declaration. - t - - ;; Set `context' and `c-restricted-<>-arglists'. Look for - ;; "<" for the sake of C++-style template arglists. - ;; Ignore "(" when it's part of a control flow construct - ;; (e.g. "for ("). - (let ((got-context - (c-get-fontification-context - match-pos - (< match-pos (if inside-macro - max-type-decl-end-before-token - max-type-decl-end)) - toplev))) - (setq context (car got-context) - c-restricted-<>-arglists (cdr got-context))) - - ;; Check we haven't missed a preceding "typedef". - (when (not (looking-at c-typedef-key)) - (c-backward-syntactic-ws) - (c-backward-token-2) - (or (looking-at c-typedef-key) - (goto-char start-pos))) - - ;; In QT, "more" is an irritating keyword that expands to nothing. - ;; We skip over it to prevent recognition of "more slots: " - ;; as a bitfield declaration. - (when (and (c-major-mode-is 'c++-mode) - (looking-at - (concat "\\(more\\)\\([^" c-symbol-chars "]\\|$\\)"))) - (goto-char (match-end 1)) - (c-forward-syntactic-ws)) - - ;; Now analyze the construct. - (if (eq context 'not-decl) - (progn - (setq decl-or-cast nil) - (if (c-syntactic-re-search-forward - "," (min limit (point-max)) 'at-limit t) - (c-put-char-property (1- (point)) 'c-type 'c-not-decl)) - nil) - (setq decl-or-cast - (c-forward-decl-or-cast-1 - match-pos context last-cast-end)) - - ;; Ensure that c-<>-arg-sep c-type properties are in place on the - ;; commas separating the arguments inside template/generic <..>s. - (when (and (eq (char-before match-pos) ?<) - (> match-pos max-<>-end)) - (save-excursion - (goto-char match-pos) - (c-backward-token-2) - (if (and - (eq (char-after) ?<) - (let ((c-restricted-<>-arglists - (save-excursion - (c-backward-token-2) - (and - (not (looking-at c-opt-<>-sexp-key)) - (progn (c-backward-syntactic-ws) - (memq (char-before) '(?\( ?,))) - (not (eq (c-get-char-property (1- (point)) - 'c-type) - 'c-decl-arg-start)))))) - (c-forward-<>-arglist nil))) - (setq max-<>-end (point))))) - - (cond - ((eq decl-or-cast 'cast) - ;; Save the position after the previous cast so we can feed - ;; it to `c-forward-decl-or-cast-1' in the next round. That - ;; helps it discover cast chains like "(a) (b) c". - (setq last-cast-end (point)) - (c-fontify-recorded-types-and-refs) - nil) - - (decl-or-cast - ;; We've found a declaration. - - ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' - ;; under the assumption that we're after the first type decl - ;; expression in the declaration now. That's not really true; - ;; we could also be after a parenthesized initializer - ;; expression in C++, but this is only used as a last resort - ;; to slant ambiguous expression/declarations, and overall - ;; it's worth the risk to occasionally fontify an expression - ;; as a declaration in an initializer expression compared to - ;; getting ambiguous things in normal function prototypes - ;; fontified as expressions. - (if inside-macro - (when (> (point) max-type-decl-end-before-token) - (setq max-type-decl-end-before-token (point))) - (when (> (point) max-type-decl-end) - (setq max-type-decl-end (point)))) - (goto-char start-pos) - (c-font-lock-single-decl limit decl-or-cast match-pos - context - (or toplev (nth 4 decl-or-cast)))) - - (t t)))) - - ;; It was a false alarm. Check if we're in a label (or other - ;; construct with `:' except bitfield) instead. - (goto-char start-pos) - (when (setq label-type (c-forward-label t match-pos nil)) - ;; Can't use `c-fontify-types-and-refs' here since we - ;; use the label face at times. - (cond ((eq label-type 'goto-target) - (c-put-font-lock-face (caar c-record-ref-identifiers) - (cdar c-record-ref-identifiers) - c-label-face-name)) - ((eq label-type 'qt-1kwd-colon) - (c-put-font-lock-face (caar c-record-ref-identifiers) - (cdar c-record-ref-identifiers) - 'font-lock-keyword-face)) - ((eq label-type 'qt-2kwds-colon) - (mapc - (lambda (kwd) - (c-put-font-lock-face (car kwd) (cdr kwd) + ;; Now analyze the construct. + (if (eq context 'not-decl) + (progn + (setq decl-or-cast nil) + (if (c-syntactic-re-search-forward + "," (min limit (point-max)) 'at-limit t) + (c-put-char-property (1- (point)) 'c-type 'c-not-decl)) + nil) + (setq decl-or-cast + (c-forward-decl-or-cast-1 + match-pos context last-cast-end)) + + ;; Ensure that c-<>-arg-sep c-type properties are in place on the + ;; commas separating the arguments inside template/generic <..>s. + (when (and (eq (char-before match-pos) ?<) + (> match-pos max-<>-end)) + (save-excursion + (goto-char match-pos) + (c-backward-token-2) + (if (and + (eq (char-after) ?<) + (let ((c-restricted-<>-arglists + (save-excursion + (c-backward-token-2) + (and + (not (looking-at c-opt-<>-sexp-key)) + (progn (c-backward-syntactic-ws) + (memq (char-before) '(?\( ?,))) + (not (eq (c-get-char-property (1- (point)) + 'c-type) + 'c-decl-arg-start)))))) + (c-forward-<>-arglist nil))) + (setq max-<>-end (point))))) + + (cond + ((eq decl-or-cast 'cast) + ;; Save the position after the previous cast so we can feed + ;; it to `c-forward-decl-or-cast-1' in the next round. That + ;; helps it discover cast chains like "(a) (b) c". + (setq last-cast-end (point)) + (c-fontify-recorded-types-and-refs) + nil) + + (decl-or-cast + ;; We've found a declaration. + + ;; Set `max-type-decl-end' or `max-type-decl-end-before-token' + ;; under the assumption that we're after the first type decl + ;; expression in the declaration now. That's not really true; + ;; we could also be after a parenthesized initializer + ;; expression in C++, but this is only used as a last resort + ;; to slant ambiguous expression/declarations, and overall + ;; it's worth the risk to occasionally fontify an expression + ;; as a declaration in an initializer expression compared to + ;; getting ambiguous things in normal function prototypes + ;; fontified as expressions. + (if inside-macro + (when (> (point) max-type-decl-end-before-token) + (setq max-type-decl-end-before-token (point))) + (when (> (point) max-type-decl-end) + (setq max-type-decl-end (point)))) + (goto-char start-pos) + (c-font-lock-single-decl limit decl-or-cast match-pos + context + (or toplev (nth 4 decl-or-cast)))) + + (t t)))) + + ;; It was a false alarm. Check if we're in a label (or other + ;; construct with `:' except bitfield) instead. + (goto-char start-pos) + (when (setq label-type (c-forward-label t match-pos nil)) + ;; Can't use `c-fontify-types-and-refs' here since we + ;; use the label face at times. + (cond ((eq label-type 'goto-target) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) + c-label-face-name)) + ((eq label-type 'qt-1kwd-colon) + (c-put-font-lock-face (caar c-record-ref-identifiers) + (cdar c-record-ref-identifiers) 'font-lock-keyword-face)) - c-record-ref-identifiers))) - (setq c-record-ref-identifiers nil) - ;; `c-forward-label' has probably added a `c-decl-end' - ;; marker, so return t to `c-find-decl-spots' to signal - ;; that. - t)))) - - nil))) + ((eq label-type 'qt-2kwds-colon) + (mapc + (lambda (kwd) + (c-put-font-lock-face (car kwd) (cdr kwd) + 'font-lock-keyword-face)) + c-record-ref-identifiers))) + (setq c-record-ref-identifiers nil) + ;; `c-forward-label' has probably added a `c-decl-end' + ;; marker, so return t to `c-find-decl-spots' to signal + ;; that. + t)))) + + nil)))) (defun c-font-lock-enum-body (limit) ;; Fontify the identifiers of each enum we find by searching forward. @@ -1561,19 +1569,21 @@ casts and declarations are fontified. Used on level 2 and higher." ;; ;; Note that this function won't attempt to fontify beyond the end of the ;; current enum block, if any. - (let* ((paren-state (c-parse-state)) - (encl-pos (c-most-enclosing-brace paren-state))) - (when (and - encl-pos - (eq (char-after encl-pos) ?\{) - (save-excursion - (goto-char encl-pos) - (c-backward-over-enum-header))) - (c-syntactic-skip-backward "^{," nil t) - (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) + (c-skip-comments-and-strings limit) + (when (< (point) limit) + (let* ((paren-state (c-parse-state)) + (encl-pos (c-most-enclosing-brace paren-state))) + (when (and + encl-pos + (eq (char-after encl-pos) ?\{) + (save-excursion + (goto-char encl-pos) + (c-backward-over-enum-header))) + (c-syntactic-skip-backward "^{," nil t) + (c-put-char-property (1- (point)) 'c-type 'c-decl-id-start) - (c-forward-syntactic-ws) - (c-font-lock-declarators limit t nil t))) + (c-forward-syntactic-ws) + (c-font-lock-declarators limit t nil t)))) nil) (defun c-font-lock-cut-off-declarators (limit) @@ -1585,46 +1595,48 @@ casts and declarations are fontified. Used on level 2 and higher." ;; font-lock-keyword-face. It always returns NIL to inhibit this and ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; fontification". - (let ((here (point)) - (decl-search-lim (c-determine-limit 1000)) - paren-state encl-pos token-end context decl-or-cast - start-pos top-level c-restricted-<>-arglists - c-recognize-knr-p) ; Strictly speaking, bogus, but it + (c-skip-comments-and-strings limit) + (when (< (point) limit) + (let ((here (point)) + (decl-search-lim (c-determine-limit 1000)) + paren-state encl-pos token-end context decl-or-cast + start-pos top-level c-restricted-<>-arglists + c-recognize-knr-p) ; Strictly speaking, bogus, but it ; speeds up lisp.h tremendously. - (save-excursion - (when (not (c-back-over-member-initializers)) - (unless (or (eobp) - (looking-at "\\s(\\|\\s)")) - (forward-char)) - (c-syntactic-skip-backward "^;{}" decl-search-lim t) - (when (eq (char-before) ?}) - (c-go-list-backward) ; brace block of struct, etc.? - (c-syntactic-skip-backward "^;{}" decl-search-lim t)) - (when (or (bobp) - (memq (char-before) '(?\; ?{ ?}))) - (setq token-end (point)) - (c-forward-syntactic-ws here) - (when (< (point) here) - ;; We're now putatively at the declaration. - (setq start-pos (point)) - (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 - (setq top-level (c-at-toplevel-p)) - (let ((got-context (c-get-fontification-context - token-end nil top-level))) - (setq context (car got-context) - c-restricted-<>-arglists (cdr got-context))) - (setq decl-or-cast - (c-forward-decl-or-cast-1 token-end context nil)) - (when (consp decl-or-cast) - (goto-char start-pos) - (c-font-lock-single-decl limit decl-or-cast token-end - context top-level)))))))) - nil)) + (save-excursion + (when (not (c-back-over-member-initializers)) + (unless (or (eobp) + (looking-at "\\s(\\|\\s)")) + (forward-char)) + (c-syntactic-skip-backward "^;{}" decl-search-lim t) + (when (eq (char-before) ?}) + (c-go-list-backward) ; brace block of struct, etc.? + (c-syntactic-skip-backward "^;{}" decl-search-lim t)) + (when (or (bobp) + (memq (char-before) '(?\; ?{ ?}))) + (setq token-end (point)) + (c-forward-syntactic-ws here) + (when (< (point) here) + ;; We're now putatively at the declaration. + (setq start-pos (point)) + (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 + (setq top-level (c-at-toplevel-p)) + (let ((got-context (c-get-fontification-context + token-end nil top-level))) + (setq context (car got-context) + c-restricted-<>-arglists (cdr got-context))) + (setq decl-or-cast + (c-forward-decl-or-cast-1 token-end context nil)) + (when (consp decl-or-cast) + (goto-char start-pos) + (c-font-lock-single-decl limit decl-or-cast token-end + context top-level)))))))) + nil))) (defun c-font-lock-enclosing-decls (limit) ;; Fontify the declarators of (nested) declarations we're in the middle of. @@ -1636,27 +1648,29 @@ casts and declarations are fontified. Used on level 2 and higher." ;; font-lock-keyword-face. It always returns NIL to inhibit this and ;; prevent a repeat invocation. See elisp/lispref page "Search-based ;; Fontification". - (let* ((paren-state (c-parse-state)) - (decl-search-lim (c-determine-limit 1000)) - in-typedef ps-elt) - ;; Are we in any nested struct/union/class/etc. braces? - (while paren-state - (setq ps-elt (car paren-state) - paren-state (cdr paren-state)) - (when (and (atom ps-elt) - (eq (char-after ps-elt) ?\{)) - (goto-char ps-elt) - (c-syntactic-skip-backward "^;{}" decl-search-lim) - (c-forward-syntactic-ws) - (setq in-typedef (looking-at c-typedef-key)) - (if in-typedef (c-forward-over-token-and-ws)) - (when (and c-opt-block-decls-with-vars-key - (looking-at c-opt-block-decls-with-vars-key)) + (c-skip-comments-and-strings limit) + (when (< (point) limit) + (let* ((paren-state (c-parse-state)) + (decl-search-lim (c-determine-limit 1000)) + in-typedef ps-elt) + ;; Are we in any nested struct/union/class/etc. braces? + (while paren-state + (setq ps-elt (car paren-state) + paren-state (cdr paren-state)) + (when (and (atom ps-elt) + (eq (char-after ps-elt) ?\{)) (goto-char ps-elt) - (when (c-safe (c-forward-sexp)) - (c-forward-syntactic-ws) - (c-font-lock-declarators limit t in-typedef - (not (c-bs-at-toplevel-p (point)))))))))) + (c-syntactic-skip-backward "^;{}" decl-search-lim) + (c-forward-syntactic-ws) + (setq in-typedef (looking-at c-typedef-key)) + (if in-typedef (c-forward-over-token-and-ws)) + (when (and c-opt-block-decls-with-vars-key + (looking-at c-opt-block-decls-with-vars-key)) + (goto-char ps-elt) + (when (c-safe (c-forward-sexp)) + (c-forward-syntactic-ws) + (c-font-lock-declarators limit t in-typedef + (not (c-bs-at-toplevel-p (point))))))))))) (defun c-font-lock-raw-strings (limit) ;; Fontify C++ raw strings. diff --git a/lisp/progmodes/cc-mode.el b/lisp/progmodes/cc-mode.el index 35de7566c78..27ed04fea52 100644 --- a/lisp/progmodes/cc-mode.el +++ b/lisp/progmodes/cc-mode.el @@ -1192,8 +1192,6 @@ Note that the style variables are always made local to the buffer." (beg-literal-type (and beg-limits (c-literal-type beg-limits)))) - (when (eq end-literal-type 'string) - (setq c-new-END (max c-new-END (cdr end-limits)))) ;; It is possible the buffer change will include inserting a string quote. ;; This could have the effect of flipping the meaning of any following ;; quotes up until the next unescaped EOL. Also guard against the change @@ -1282,7 +1280,6 @@ Note that the style variables are always made local to the buffer." (when (and (eq beg-literal-type 'string) (memq (char-after (car beg-limits)) c-string-delims)) - (setq c-new-BEG (min c-new-BEG (car beg-limits))) (c-clear-char-property (car beg-limits) 'syntax-table) (c-truncate-semi-nonlit-pos-cache (car beg-limits)))))) @@ -1832,6 +1829,9 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") ;; declaration is one which does not start outside of struct braces (and ;; similar) enclosing POS. Brace list braces here are not "similar". ;; + ;; POS being in a literal does not count as being in a declaration (on + ;; pragmatic grounds). + ;; ;; This function is called indirectly from font locking stuff - either from ;; c-after-change (to prepare for after-change font-locking) or from font ;; lock context (etc.) fontification. @@ -1842,92 +1842,92 @@ Note that this is a strict tail, so won't match, e.g. \"0x....\".") 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 - (setq old-pos (point)) - (let (pseudo) - (while - (progn - (c-syntactic-skip-backward "^;{}" bod-lim t) - (and (eq (char-before) ?}) - (save-excursion - (backward-char) - (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state)))))) - (goto-char pseudo)) - t) - (> (point) bod-lim) - (progn (c-forward-syntactic-ws) - ;; Have we got stuck in a comment at EOB? - (not (and (eobp) - (c-literal-start)))) - (< (point) old-pos) - (progn (setq bo-decl (point)) - (or (not (looking-at c-protection-key)) - (c-forward-keyword-clause 1))) - (progn - ;; Are we looking at a keyword such as "template" or - ;; "typedef" which can decorate a type, or the type itself? - (when (or (looking-at c-prefix-spec-kwds-re) - (c-forward-type t)) - ;; We've found another candidate position. - (setq new-pos (min new-pos bo-decl)) - (goto-char bo-decl)) - t) - ;; Try and go out a level to search again. - (progn - (c-backward-syntactic-ws bod-lim) - (and (> (point) bod-lim) - (or (memq (char-before) '(?\( ?\[)) - (and (eq (char-before) ?\<) - (eq (c-get-char-property - (1- (point)) 'syntax-table) - c-<-as-paren-syntax)) - (and (eq (char-before) ?{) - (save-excursion - (backward-char) - (consp (c-looking-at-or-maybe-in-bracelist)))) - ))) - (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))) + (unless 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 + (setq old-pos (point)) + (let (pseudo) + (while + (progn + (c-syntactic-skip-backward "^;{}" bod-lim t) + (and (eq (char-before) ?}) + (save-excursion + (backward-char) + (setq pseudo (c-cheap-inside-bracelist-p (c-parse-state)))))) + (goto-char pseudo)) + t) + (> (point) bod-lim) + (progn (c-forward-syntactic-ws) + ;; Have we got stuck in a comment at EOB? + (not (and (eobp) + (c-literal-start)))) + (< (point) old-pos) + (progn (setq bo-decl (point)) + (or (not (looking-at c-protection-key)) + (c-forward-keyword-clause 1))) + (progn + ;; Are we looking at a keyword such as "template" or + ;; "typedef" which can decorate a type, or the type itself? + (when (or (looking-at c-prefix-spec-kwds-re) + (c-forward-type t)) + ;; We've found another candidate position. + (setq new-pos (min new-pos bo-decl)) + (goto-char bo-decl)) + t) + ;; Try and go out a level to search again. + (progn + (c-backward-syntactic-ws bod-lim) + (and (> (point) bod-lim) + (or (memq (char-before) '(?\( ?\[)) + (and (eq (char-before) ?\<) + (eq (c-get-char-property + (1- (point)) 'syntax-table) + c-<-as-paren-syntax)) + (and (eq (char-before) ?{) + (save-excursion + (backward-char) + (consp (c-looking-at-or-maybe-in-bracelist)))) + ))) + (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-fl-decl-end (pos) ;; If POS is inside a declarator, return the end of the token that follows - ;; the declarator, otherwise return nil. + ;; the declarator, otherwise return nil. POS being in a literal does not + ;; count as being in a declarator (on pragmatic grounds). (goto-char pos) (let ((lit-start (c-literal-start)) pos1) - (if lit-start (goto-char lit-start)) - (c-backward-syntactic-ws) - (when (setq pos1 (c-on-identifier)) - (goto-char pos1) - (let ((lim (save-excursion - (and (c-beginning-of-macro) - (progn (c-end-of-macro) (point)))))) - (when (and (c-forward-declarator lim) - (or (not (eq (char-after) ?\()) - (c-go-list-forward nil lim)) - (eq (c-forward-token-2 1 nil lim) 0)) - (c-backward-syntactic-ws) - (point)))))) + (unless lit-start + (c-backward-syntactic-ws) + (when (setq pos1 (c-on-identifier)) + (goto-char pos1) + (let ((lim (save-excursion + (and (c-beginning-of-macro) + (progn (c-end-of-macro) (point)))))) + (when (and (c-forward-declarator lim) + (or (not (eq (char-after) ?\()) + (c-go-list-forward nil lim)) + (eq (c-forward-token-2 1 nil lim) 0)) + (c-backward-syntactic-ws) + (point))))))) (defun c-change-expand-fl-region (_beg _end _old-len) ;; Expand the region (c-new-BEG c-new-END) to an after-change font-lock