mirror of
git://git.sv.gnu.org/emacs.git
synced 2025-12-06 06:20:55 -08:00
* lisp/allout.el (allout-abbreviate-flattened-numbering) (allout-mode-deactivate-hook): * lisp/ansi-color.el (ansi-color-unfontify-region): * lisp/auth-source.el (auth-source-hide-passwords) (auth-source-user-or-password) (auth-source-forget-user-or-password): * lisp/cedet/data-debug.el (data-debug-map): * lisp/cedet/semantic/grammar.el (semantic-grammar-syntax-table) (semantic-grammar-map): * lisp/chistory.el (command-history-map): * lisp/comint.el (comint-dynamic-complete) (comint-dynamic-complete-as-filename) (comint-dynamic-simple-complete): * lisp/dired-x.el (read-filename-at-point) (dired-x-submit-report): * lisp/dos-fns.el (register-name-alist, make-register) (register-value, set-register-value, intdos, mode25, mode4350): * lisp/emacs-lisp/bytecomp.el (byte-compile-disable-print-circle): * lisp/emacs-lisp/chart.el (chart-map): * lisp/emacs-lisp/package.el (package-menu-view-commentary): * lisp/emacs-lock.el (toggle-emacs-lock, emacs-lock-from-exiting): * lisp/erc/erc.el (erc-complete-word): * lisp/eshell/em-cmpl.el (eshell-cmpl-suffix-list): * lisp/eshell/esh-util.el (eshell-for): * lisp/files.el (inhibit-first-line-modes-regexps) (inhibit-first-line-modes-suffixes): * lisp/gnus/gnus-msg.el (gnus-outgoing-message-group) (gnus-debug-files, gnus-debug-exclude-variables): * lisp/gnus/gnus-registry.el (gnus-registry-user-format-function-M): * lisp/gnus/gnus.el (gnus-local-domain, gnus-carpal): * lisp/gnus/nnimap.el (nnimap-split-rule): * lisp/iimage.el (turn-on-iimage-mode): * lisp/image.el (image-extension-data, image-library-alist): * lisp/mail/emacsbug.el (report-emacs-bug-pretest-address): * lisp/mail/mail-utils.el (rmail-dont-reply-to): * lisp/mail/mailalias.el (mail-complete-function) (mail-completion-at-point-function): * lisp/mail/rmail.el (rmail-dont-reply-to-names) (rmail-default-dont-reply-to-names): * lisp/mail/sendmail.el (mail-mailer-swallows-blank-line) (mail-sent-via): * lisp/menu-bar.el (menu-bar-kill-ring-save): * lisp/minibuffer.el (completion-annotate-function) (minibuffer-local-filename-must-match-map): * lisp/msb.el (msb-after-load-hooks): * lisp/obsolete/eieio-compat.el (eieio-defmethod) (eieio-defgeneric): * lisp/obsolete/info-edit.el (Info-edit-map): * lisp/obsolete/starttls.el (starttls-any-program-available): * lisp/progmodes/cfengine.el (cfengine-mode-abbrevs): * lisp/progmodes/cwarn.el (turn-on-cwarn-mode): * lisp/progmodes/make-mode.el (makefile-complete): * lisp/progmodes/meta-mode.el (meta-complete-symbol) (meta-mode-map): * lisp/progmodes/pascal.el (pascal-toggle-completions) (pascal-last-completions, pascal-show-completions): * lisp/progmodes/prolog.el (prolog-char-quote-workaround): * lisp/progmodes/which-func.el (which-func-mode): [FUNCTION] * lisp/simple.el (count-lines-region, minibuffer-completing-symbol): * lisp/speedbar.el (speedbar-syntax-table, speedbar-key-map): * lisp/strokes.el (strokes-report-bug): * lisp/subr.el (condition-case-no-debug): * lisp/term/ns-win.el (ns-alternatives-map) (ns-store-cut-buffer-internal): * lisp/term/w32-win.el (w32-default-color-map): * lisp/term/x-win.el (x-cut-buffer-or-selection-value): * lisp/textmodes/bibtex.el (bibtex-complete) (bibtex-entry-field-alist): * lisp/textmodes/reftex-index.el (reftex-index-map) (reftex-index-phrases-map): * lisp/textmodes/reftex-sel.el (reftex-select-label-map) (reftex-select-bib-map): * lisp/textmodes/reftex-toc.el (reftex-toc-map): * lisp/textmodes/rst.el (rst-block-face, rst-external-face) (rst-definition-face, rst-directive-face, rst-comment-face) (rst-emphasis1-face, rst-emphasis2-face, rst-literal-face) (rst-reference-face): * lisp/vc/vc-hooks.el (vc-toggle-read-only): * lisp/view.el (view-return-to-alist) (view-return-to-alist-update): Remove many functions and variables obsolete since 24.1. * lisp/textmodes/bibtex.el (bibtex-entry-alist): Don't use above removed variable 'bibtex-entry-field-alist'. * lisp/cedet/data-debug.el (data-debug-edebug-expr) (data-debug-eval-expression): * lisp/emacs-lisp/trace.el (trace--read-args): * lisp/files-x.el (read-file-local-variable-value): * lisp/simple.el (read--expression): Don't use above removed variable 'minibuffer-completing-symbol'. * lisp/textmodes/rst.el (rst-font-lock-keywords): Don't use above removed variables. * src/w32fns.c (Fw32_default_color_map): Delete obsolete function. (syms_of_w32fns): Delete defsubr for above defun. * src/keyboard.c (syms_of_keyboard) <Vdeferred_action_list> <Vdeferred_action_function>: Delete DEFVARs. <Qdeferred_action_function>: Delete DEFSYM. (syms_of_keyboard_for_pdumper): Adjust for above change. (command_loop_1): Don't run deferred-action-function hook. * lisp/subr.el (deferred-action-list, deferred-action-function): Delete obsoletion statements. * lisp/emacs-lisp/ert-x.el (ert-simulate-command): Don't run 'deferred-action-list' hook. * doc/lispref/hooks.texi (Standard Hooks): Delete 'deferred-action-function'. * lisp/emacs-lisp/lisp.el (field-complete): * lisp/eshell/em-cmpl.el (eshell-cmpl-initialize): * lisp/gnus/gnus-msg.el (gnus-inews-insert-gcc): * lisp/gnus/nnmail.el (nnmail-fancy-expiry-target): * lisp/mail/mail-utils.el (mail-dont-reply-to): * lisp/mail/sendmail.el (sendmail-send-it): * lisp/mail/smtpmail.el (smtpmail-send-it): * lisp/minibuffer.el (minibuffer-completion-help): * lisp/progmodes/python.el: Don't use above removed items. * lisp/emacs-lisp/eieio-core.el: * lisp/mail/mailalias.el (mail-complete-alist): Doc fixes; don't refer to above removed items. ; * etc/NEWS: List removed items.
335 lines
11 KiB
EmacsLisp
335 lines
11 KiB
EmacsLisp
;;; cwarn.el --- highlight suspicious C and C++ constructions -*- lexical-binding: t -*-
|
|
|
|
;; Copyright (C) 1999-2022 Free Software Foundation, Inc.
|
|
|
|
;; Author: Anders Lindgren
|
|
;; Keywords: c, languages, faces
|
|
;; Old-Version: 1.3.1
|
|
|
|
;; This file is part of GNU Emacs.
|
|
|
|
;; GNU Emacs is free software: you can redistribute it and/or modify
|
|
;; it under the terms of the GNU General Public License as published by
|
|
;; the Free Software Foundation, either version 3 of the License, or
|
|
;; (at your option) any later version.
|
|
|
|
;; GNU Emacs is distributed in the hope that it will be useful,
|
|
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
;; GNU General Public License for more details.
|
|
|
|
;; You should have received a copy of the GNU General Public License
|
|
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
|
|
|
|
;;; Commentary:
|
|
|
|
;;{{{ Documentation
|
|
|
|
;; Description:
|
|
;;
|
|
;; CWarn is a package that highlights suspicious C and C++ constructions.
|
|
;;
|
|
;; For example, take a look at the following piece of C code:
|
|
;;
|
|
;; if (x = 0);
|
|
;; foo();
|
|
;;
|
|
;; The code contains two, possibly fatal, bugs. The first is that the
|
|
;; assignment operator "=" is used as part of the test; the user
|
|
;; probably meant to use the comparison operator "==".
|
|
;;
|
|
;; The second problem is that an extra semicolon is placed after
|
|
;; closing parenthesis of the test expression. This makes the body of
|
|
;; the if statement to be an empty statement, not the call to the
|
|
;; function "foo", as the user probably intended.
|
|
;;
|
|
;; This package is capable of highlighting the following C and C++
|
|
;; constructions:
|
|
;;
|
|
;; * Assignments inside expressions, including variations like "+=".
|
|
;; * Semicolon following immediately after `if', `for', and `while'
|
|
;; (except, of course, after a `do .. while' statement).
|
|
;; * C++ functions with reference parameters.
|
|
;;
|
|
;; Note that none of the constructions highlighted (especially not C++
|
|
;; reference parameters) are considered errors by the language
|
|
;; definitions.
|
|
|
|
;; Usage:
|
|
;;
|
|
;; CWarn is implemented as two minor modes: `cwarn-mode' and
|
|
;; `global-cwarn-mode'. The former can be applied to individual buffers
|
|
;; and the latter to all buffers.
|
|
;;
|
|
;; Activate this package by Customize, or by placing the following line
|
|
;; into the appropriate init file:
|
|
;;
|
|
;; (global-cwarn-mode 1)
|
|
;;
|
|
;; Also, `font-lock-mode' or `global-font-lock-mode' must be enabled.
|
|
|
|
;; Afterthought:
|
|
;;
|
|
;; After using this package for several weeks it feels as though I
|
|
;; find stupid typo-style bugs while editing rather than at compile-
|
|
;; or run-time, if I ever find them.
|
|
;;
|
|
;; On the other hand, I find myself using assignments inside
|
|
;; expressions much more often than I used to do. The reason is that
|
|
;; there is no risk of interpreting an assignment operator as a
|
|
;; comparison ("hey, the assignment operator is red, duh!").
|
|
|
|
;; Reporting bugs:
|
|
;;
|
|
;; Out of the last ten bugs you found, how many did you report?
|
|
;;
|
|
;; When reporting a bug, please:
|
|
;;
|
|
;; * Send a mail the maintainer of the package, or to the author
|
|
;; if no maintainer exists.
|
|
;; * Include the name of the package in the title of the mail, to
|
|
;; simplify for the recipient.
|
|
;; * State exactly what you did, what happened, and what you expected
|
|
;; to see when you found the bug.
|
|
;; * If the bug cause an error, set the variable `debug-on-error' to t,
|
|
;; repeat the operations that triggered the error and include
|
|
;; the backtrace in the letter.
|
|
;; * If possible, include an example that activates the bug.
|
|
;; * Should you speculate about the cause of the problem, please
|
|
;; state explicitly that you are guessing.
|
|
|
|
;;}}}
|
|
|
|
;;; Code:
|
|
|
|
;;{{{ Dependencies
|
|
|
|
(require 'cc-mode)
|
|
|
|
;;}}}
|
|
;;{{{ Variables
|
|
|
|
(defgroup cwarn nil
|
|
"Highlight suspicious C and C++ constructions."
|
|
:version "21.1"
|
|
:group 'faces)
|
|
|
|
(defcustom cwarn-configuration
|
|
'((c-mode (not reference))
|
|
(c++-mode t))
|
|
"List of items each describing which features are enable for a mode.
|
|
Each item is on the form (mode featurelist), where featurelist can be
|
|
on one of three forms:
|
|
|
|
* A list of enabled features.
|
|
* A list starting with the atom `not' followed by the features
|
|
which are not enabled.
|
|
* The atom t, that represent that all features are enabled.
|
|
|
|
See variable `cwarn-font-lock-feature-keywords-alist' for available
|
|
features."
|
|
:type '(repeat sexp))
|
|
|
|
(defcustom cwarn-font-lock-feature-keywords-alist
|
|
'((assign . cwarn-font-lock-assignment-keywords)
|
|
(semicolon . cwarn-font-lock-semicolon-keywords)
|
|
(reference . cwarn-font-lock-reference-keywords))
|
|
"An alist mapping a CWarn feature to font-lock keywords.
|
|
The keywords could either a font-lock keyword list or a symbol.
|
|
If it is a symbol it is assumed to be a variable containing a font-lock
|
|
keyword list."
|
|
:type '(alist :key-type (choice (const assign)
|
|
(const semicolon)
|
|
(const reference))
|
|
:value-type (sexp :tag "Value")))
|
|
|
|
(defcustom cwarn-verbose t
|
|
"When nil, CWarn mode will not generate any messages.
|
|
|
|
Currently, messages are generated when the mode is activated and
|
|
deactivated."
|
|
:type 'boolean)
|
|
|
|
(defcustom cwarn-mode-text " CWarn"
|
|
"String to display in the mode line when CWarn mode is active.
|
|
|
|
\(When the string is not empty, make sure that it has a leading space.)"
|
|
:tag "CWarn mode text" ; To separate it from `global-...'
|
|
:type 'string)
|
|
|
|
(defcustom cwarn-load-hook nil
|
|
"Functions to run when CWarn mode is first loaded."
|
|
:tag "Load Hook"
|
|
:type 'hook)
|
|
(make-obsolete-variable 'cwarn-load-hook
|
|
"use `with-eval-after-load' instead." "28.1")
|
|
|
|
;;}}}
|
|
;;{{{ The modes
|
|
|
|
;;;###autoload
|
|
(define-minor-mode cwarn-mode
|
|
"Minor mode that highlights suspicious C and C++ constructions.
|
|
|
|
Suspicious constructs are highlighted using `font-lock-warning-face'.
|
|
|
|
Note, in addition to enabling this minor mode, the major mode must
|
|
be included in the variable `cwarn-configuration'. By default C and
|
|
C++ modes are included."
|
|
:group 'cwarn :lighter cwarn-mode-text
|
|
(cwarn-font-lock-keywords cwarn-mode)
|
|
(font-lock-flush))
|
|
|
|
;;}}}
|
|
;;{{{ Help functions
|
|
|
|
(defun cwarn-is-enabled (mode &optional feature)
|
|
"Non-nil if CWarn FEATURE is enabled for MODE.
|
|
FEATURE is an atom representing one construction to highlight.
|
|
|
|
Check if any feature is enabled for MODE if no feature is specified.
|
|
|
|
The valid features are described by the variable
|
|
`cwarn-font-lock-feature-keywords-alist'."
|
|
(let ((mode-configuration (assq mode cwarn-configuration)))
|
|
(and mode-configuration
|
|
(or (null feature)
|
|
(let ((list-or-t (nth 1 mode-configuration)))
|
|
(or (eq list-or-t t)
|
|
(if (eq (car-safe list-or-t) 'not)
|
|
(not (memq feature (cdr list-or-t)))
|
|
(memq feature list-or-t))))))))
|
|
|
|
(defun cwarn-inside-macro ()
|
|
"True if point is inside a C macro definition."
|
|
(save-excursion
|
|
(beginning-of-line)
|
|
(while (eq (char-before (1- (point))) ?\\)
|
|
(forward-line -1))
|
|
(back-to-indentation)
|
|
(eq (char-after) ?#)))
|
|
|
|
(defun cwarn-font-lock-keywords (addp)
|
|
"Install/remove keywords into current buffer.
|
|
If ADDP is non-nil, install else remove."
|
|
(dolist (pair cwarn-font-lock-feature-keywords-alist)
|
|
(let ((feature (car pair))
|
|
(keywords (cdr pair)))
|
|
(if (not (listp keywords))
|
|
(setq keywords (symbol-value keywords)))
|
|
(if (cwarn-is-enabled major-mode feature)
|
|
(funcall (if addp 'font-lock-add-keywords 'font-lock-remove-keywords)
|
|
nil keywords)))))
|
|
|
|
;;}}}
|
|
;;{{{ Font-lock keywords and match functions
|
|
|
|
;; This section contains font-lock keywords. A font lock keyword can
|
|
;; either contain a regular expression or a match function. All
|
|
;; keywords defined here use match functions since the C and C++
|
|
;; constructions highlighted by CWarn are too complex to be matched by
|
|
;; regular expressions.
|
|
;;
|
|
;; A match function should act like a normal forward search. They
|
|
;; should return non-nil if they found a candidate and the match data
|
|
;; should correspond to the highlight part of the font-lock keyword.
|
|
;; The functions should not generate errors, in that case font-lock
|
|
;; will fail to highlight the buffer. A match function takes one
|
|
;; argument, LIMIT, that represent the end of area to be searched.
|
|
;;
|
|
;; The variable `cwarn-font-lock-feature-keywords-alist' contains a
|
|
;; mapping from CWarn features to the font-lock keywords defined
|
|
;; below.
|
|
|
|
(defmacro cwarn-font-lock-match (re &rest body)
|
|
"Match RE but only if BODY holds."
|
|
`(let ((res nil))
|
|
(while
|
|
(progn
|
|
(setq res (re-search-forward ,re limit t))
|
|
(and res
|
|
(save-excursion
|
|
(when (match-beginning 1) (goto-char (match-beginning 1)))
|
|
(condition-case nil ; In case something barfs.
|
|
(not (save-match-data
|
|
,@body))
|
|
(error t))))))
|
|
res))
|
|
|
|
;;{{{ Assignment in expressions
|
|
|
|
(defconst cwarn-font-lock-assignment-keywords
|
|
'((cwarn-font-lock-match-assignment-in-expression
|
|
(1 font-lock-warning-face))))
|
|
|
|
(defun cwarn-font-lock-match-assignment-in-expression (limit)
|
|
"Match assignments inside expressions."
|
|
(cwarn-font-lock-match
|
|
"[^!<>=]\\(\\([-+*/%&^|]\\|<<\\|>>\\)?=\\)[^=]"
|
|
(backward-up-list 1)
|
|
(and (memq (following-char) '(?\( ?\[))
|
|
(not (progn
|
|
(skip-chars-backward " ")
|
|
(skip-chars-backward "a-zA-Z0-9_")
|
|
(or
|
|
;; Default parameter of function.
|
|
(c-at-toplevel-p)
|
|
(looking-at "for\\>")))))))
|
|
|
|
;;}}}
|
|
;;{{{ Semicolon
|
|
|
|
(defconst cwarn-font-lock-semicolon-keywords
|
|
'((cwarn-font-lock-match-dangerous-semicolon (0 font-lock-warning-face))))
|
|
|
|
(defun cwarn-font-lock-match-dangerous-semicolon (limit)
|
|
"Match semicolons directly after `for', `while', and `if'.
|
|
The semicolon after a `do { ... } while (x);' construction is not matched."
|
|
(cwarn-font-lock-match
|
|
";"
|
|
(backward-sexp 2) ; Expression and keyword.
|
|
(or (looking-at "\\(for\\|if\\)\\>")
|
|
(and (looking-at "while\\>")
|
|
(condition-case nil
|
|
(progn
|
|
(backward-sexp 2) ; Body and "do".
|
|
(not (looking-at "do\\>")))
|
|
(error t))))))
|
|
|
|
;;}}}
|
|
;;{{{ Reference
|
|
|
|
(defconst cwarn-font-lock-reference-keywords
|
|
'((cwarn-font-lock-match-reference (1 font-lock-warning-face))))
|
|
|
|
(defun cwarn-font-lock-match-reference (limit)
|
|
"Font-lock matcher for C++ reference parameters."
|
|
(cwarn-font-lock-match
|
|
"[^&]\\(&\\)[^&=]"
|
|
(backward-up-list 1)
|
|
(and (eq (following-char) ?\()
|
|
(not (cwarn-inside-macro))
|
|
(c-at-toplevel-p))))
|
|
|
|
;;}}}
|
|
|
|
;;}}}
|
|
;;{{{ The end
|
|
|
|
(defun turn-on-cwarn-mode-if-enabled ()
|
|
"Turn on CWarn mode in the current buffer if applicable.
|
|
The mode is turned if some feature is enabled for the current
|
|
`major-mode' in `cwarn-configuration'."
|
|
(when (cwarn-is-enabled major-mode) (cwarn-mode 1)))
|
|
|
|
;;;###autoload
|
|
(define-globalized-minor-mode global-cwarn-mode
|
|
cwarn-mode turn-on-cwarn-mode-if-enabled)
|
|
|
|
(provide 'cwarn)
|
|
|
|
(run-hooks 'cwarn-load-hook)
|
|
|
|
;;}}}
|
|
|
|
;;; cwarn.el ends here
|