From d6bcb39ba9d46f7dc29e01551a1d35fe250695a9 Mon Sep 17 00:00:00 2001 From: Alan Mackenzie Date: Wed, 28 Jun 2023 18:29:39 +0000 Subject: [PATCH] Fontify C, C++, Objective C identifiers containing $ Optionally, fontify them with font-lock-warning-face. This fixes bug#64204. * lisp/progmodes/cc-fonts.el (c-font-lock-ids-with-dollar): New function. (c-simple-decl-matchers, c-complex-decl-matchers): invoke c-font-lock-ids-with-dollar for pertinent languages. * lisp/progmodes/cc-langs.el (c-symbol-start): Add `$' to the character list. (c-dollar-in-ids): New lang const. (c-symbol-key): For the Pike value, use the AWK value rather than the C value as the basis, as the latter is no longer suitable. * lisp/progmodes/cc-vars.el (c-warn-ids-with-dollar): New customizable option. * doc/misc/cc-mode.texi ("Miscellaneous Font Locking"): Add a section on the new optional fontification of identifiers with 'font-lock-warning-face'. --- doc/misc/cc-mode.texi | 17 ++++++++++++++ lisp/progmodes/cc-fonts.el | 45 ++++++++++++++++++++++++++++++++++++-- lisp/progmodes/cc-langs.el | 11 +++++++--- lisp/progmodes/cc-vars.el | 8 +++++++ 4 files changed, 76 insertions(+), 5 deletions(-) diff --git a/doc/misc/cc-mode.texi b/doc/misc/cc-mode.texi index 5f905be09d5..4ab95798468 100644 --- a/doc/misc/cc-mode.texi +++ b/doc/misc/cc-mode.texi @@ -2169,6 +2169,23 @@ which aren't of the default style will be fontified with @section Miscellaneous Font Locking @comment !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +Some compilers, notably GCC, allow the character @samp{$} to be a +constituent of identifiers in the languages C, C++, and Objective C. +CC Mode defaults to accepting these @samp{$} characters and fontifying +the identifiers in which they appear like any others. + +However, the compiler you're using, or your project coding standards +may disallow such use. In such cases, you can set +@code{c-warn-ids-with-dollar} to non-@code{nil}. This causes these +invalid identifiers to be fontified distinctively. + +@defvar c-warn-ids-with-dollar +@vindex warn-ids-with-dollar (c-) +When this customization option is non-@code{nil}, identifiers +containing the @samp{$} character are fontified with +@code{font-lock-warning-face}. +@end defvar + In some languages, particularly in C++, there are constructs which are syntactically ambiguous---they could be either declarations or expressions, and @ccmode{} cannot tell for sure which. Often such a diff --git a/lisp/progmodes/cc-fonts.el b/lisp/progmodes/cc-fonts.el index baf57d6839a..afbf841bcb1 100644 --- a/lisp/progmodes/cc-fonts.el +++ b/lisp/progmodes/cc-fonts.el @@ -1890,6 +1890,38 @@ casts and declarations are fontified. Used on level 2 and higher." (c-font-lock-declarators limit t in-typedef (not (c-bs-at-toplevel-p (point))))))))))) +(defun c-font-lock-ids-with-dollar (limit) + ;; Maybe fontify identifiers with a dollar using `font-lock-warning-face'. + ;; This is done only for languages which tolerate a $ in ids, and only when + ;; the flag variable `c-warn-ids-with-dollar' is set to non-nil. This + ;; function only works after functions such as `c-font-lock-declarations' + ;; have already been run. + ;; + ;; 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". + (when c-warn-ids-with-dollar + (let (id-start) + (while (and (< (point) limit) + (skip-chars-forward "^$" limit) + (< (point) limit) + (eq (char-after) ?$)) + (if (and (memq (c-get-char-property (point) 'face) + '(font-lock-variable-name-face + font-lock-function-name-face + font-lock-type-face)) + (setq id-start (c-on-identifier))) + (progn + (goto-char id-start) + (looking-at c-identifier-key) + (c-put-font-lock-face (match-beginning 0) (match-end 0) + 'font-lock-warning-face) + (goto-char (match-end 0))) + (forward-char))) + nil))) + (defun c-font-lock-ml-strings (limit) ;; Fontify multi-line strings. ;; @@ -2290,7 +2322,12 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." ;; Fontify generic colon labels in languages that support them. ,@(when (c-lang-const c-recognize-colon-labels) - '(c-font-lock-labels)))) + '(c-font-lock-labels)) + + ;; Maybe fontify identifiers containing a dollar sign with + ;; `font-lock-warning-face'. + ,@(when (c-lang-const c-dollar-in-ids) + `(c-font-lock-ids-with-dollar)))) (c-lang-defconst c-complex-decl-matchers "Complex font lock matchers for types and declarations. Used on level @@ -2366,7 +2403,11 @@ on level 2 only and so aren't combined with `c-complex-decl-matchers'." ;; (see Elisp page "Search-based Fontification"). '(("\\" (c-font-lock-c++-new)))) - )) + + ;; Maybe fontify identifiers containing a dollar sign with + ;; `font-lock-warning-face'. + ,@(when (c-lang-const c-dollar-in-ids) + `(c-font-lock-ids-with-dollar)))) (defun c-font-lock-labels (limit) ;; Fontify all statement labels from the point to LIMIT. Assumes diff --git a/lisp/progmodes/cc-langs.el b/lisp/progmodes/cc-langs.el index d56366e1755..2422cf3deb0 100644 --- a/lisp/progmodes/cc-langs.el +++ b/lisp/progmodes/cc-langs.el @@ -834,8 +834,9 @@ which `c-backward-sexp' needs to be called twice to move backwards over." keyword. It's unspecified how far it matches. Does not contain a \\| operator at the top level." t (concat "[" c-alpha "_]") + (c c++) (concat "[" c-alpha "_$]") java (concat "[" c-alpha "_@]") - objc (concat "[" c-alpha "_@]") + objc (concat "[" c-alpha "_@$]") pike (concat "[" c-alpha "_`]")) (c-lang-defvar c-symbol-start (c-lang-const c-symbol-start)) @@ -848,6 +849,10 @@ This is of the form that fits inside [ ] in a regexp." objc (concat c-alnum "_$@")) (c-lang-defvar c-symbol-chars (c-lang-const c-symbol-chars)) +(c-lang-defconst c-dollar-in-ids + "Non-nil when a dollar (can be) a non-standard constituent of an identifier." + t (string-match (c-lang-const c-symbol-start) "$")) + (c-lang-defconst c-symbol-char-key "Regexp matching a sequence of at least one identifier character." t (concat "[" (c-lang-const c-symbol-chars) "]+")) @@ -859,9 +864,9 @@ to match if `c-symbol-start' matches on the same position." t (concat (c-lang-const c-symbol-start) "[" (c-lang-const c-symbol-chars) "]\\{,1000\\}") pike (concat - ;; Use the value from C here since the operator backquote is + ;; Use the value from AWK here since the operator backquote is ;; covered by the other alternative. - (c-lang-const c-symbol-key c) + (c-lang-const c-symbol-key awk) "\\|" (c-make-keywords-re nil (c-lang-const c-overloadable-operators)))) diff --git a/lisp/progmodes/cc-vars.el b/lisp/progmodes/cc-vars.el index 286d569aaca..c7b66f040cd 100644 --- a/lisp/progmodes/cc-vars.el +++ b/lisp/progmodes/cc-vars.el @@ -280,6 +280,14 @@ anchoring position to indent the line in that case." :type 'boolean :group 'c) +(defcustom c-warn-ids-with-dollar nil + "Fontify identifiers with a dollar character in font-lock-warn-face. +This has effect only for languages in which `c-dollar-in-ids' is +non-nil, e.g. C, C++, Objective C. It covers languages where +\"$\" is permitted in ids \"informally\", but only by some compilers." + :type 'boolean + :group 'c) + (defcustom-c-stylevar c-basic-offset 4 "Amount of basic offset used by + and - symbols in `c-offsets-alist'. Also used as the indentation step when `c-syntactic-indentation' is -- 2.39.2