X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/a113b3ca322fd73d97d0d9d69c9f48dc13fb326a..73b0cd50031a714347109169ceb8bacae338612a:/lisp/progmodes/flymake.el diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 757afdd79e..a6059b1b69 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -1,6 +1,6 @@ ;;; flymake.el -- a universal on-the-fly syntax checker -;; Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008 +;; Copyright (C) 2003-2011 ;; Free Software Foundation, Inc. ;; Author: Pavel Kobyakov @@ -10,10 +10,10 @@ ;; This file is part of GNU Emacs. -;; GNU Emacs is free software; you can redistribute it and/or modify +;; 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, or (at your option) -;; any later version. +;; 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 @@ -21,9 +21,7 @@ ;; GNU General Public License for more details. ;; You should have received a copy of the GNU General Public License -;; along with GNU Emacs; see the file COPYING. If not, write to the -;; Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, -;; Boston, MA 02110-1301, USA. +;; along with GNU Emacs. If not, see . ;;; Commentary: ;; @@ -81,7 +79,7 @@ 'float-time (if (featurep 'xemacs) (lambda () - (multiple-value-bind (s0 s1 s2) (current-time) + (multiple-value-bind (s0 s1 s2) (values-list (current-time)) (+ (* (float (ash 1 16)) s0) (float s1) (* 0.0000001 s2))))))) (defalias 'flymake-replace-regexp-in-string @@ -108,16 +106,6 @@ Zero-length substrings at the beginning and end of the list are omitted." 'temp-directory (lambda () temporary-file-directory))) -(defalias 'flymake-line-beginning-position - (if (fboundp 'line-beginning-position) - 'line-beginning-position - (lambda (&optional arg) (save-excursion (beginning-of-line arg) (point))))) - -(defalias 'flymake-line-end-position - (if (fboundp 'line-end-position) - 'line-end-position - (lambda (&optional arg) (save-excursion (end-of-line arg) (point))))) - (defun flymake-posn-at-point-as-event (&optional position window dx dy) "Return pixel position of top left corner of glyph at POSITION, relative to top left corner of WINDOW, as a mouse-1 click @@ -265,9 +253,13 @@ are the string substitutions (see `format')." (make-variable-buffer-local 'flymake-output-residual) +(defgroup flymake nil + "A universal on-the-fly syntax checker." + :version "23.1" + :group 'tools) + (defcustom flymake-allowed-file-name-masks - '(("\\.c\\'" flymake-simple-make-init) - ("\\.cpp\\'" flymake-simple-make-init) + '(("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'" flymake-simple-make-init) ("\\.xml\\'" flymake-xml-init) ("\\.html?\\'" flymake-xml-init) ("\\.cs\\'" flymake-simple-make-init) @@ -288,7 +280,7 @@ are the string substitutions (see `format')." ;; ("[ \t]*\\input[ \t]*{\\(.*\\)\\(%s\\)}" 1 2 )) ;; ("\\.tex\\'" 1) ) - "*Files syntax checking is allowed for." + "Files syntax checking is allowed for." :group 'flymake :type '(repeat (string symbol symbol symbol))) @@ -342,13 +334,10 @@ Return nil if we cannot, non-nil if we can." Buildfile includes Makefile, build.xml etc. Return its file name if found, or nil if not found." (or (flymake-get-buildfile-from-cache source-dir-name) - (let* ((file (locate-dominating-file - source-dir-name - (concat "\\`" (regexp-quote buildfile-name) "\\'")))) + (let* ((file (locate-dominating-file source-dir-name buildfile-name))) (if file (progn (flymake-log 3 "found buildfile at %s" file) - (setq file (file-name-directory file)) (flymake-add-buildfile-to-cache source-dir-name file) file) (progn @@ -384,7 +373,7 @@ Return t if so, nil if not." (defun flymake-find-possible-master-files (file-name master-file-dirs masks) "Find (by name and location) all possible master files. -Master files are .cpp and .c for and .h. Files are searched for +Master files include .cpp and .c for .h. Files are searched for starting from the .h directory and max max-level parent dirs. File contents are not checked." (let* ((dirs master-file-dirs) @@ -424,9 +413,11 @@ to the beginning of the list (File.h -> File.cpp moved to top)." (not (equal file-one file-two)))) (defcustom flymake-check-file-limit 8192 - "Max number of chars to look at when checking possible master file." + "Maximum number of chars to look at when checking possible master file. +Nil means search the entire file." :group 'flymake - :type 'integer) + :type '(choice (const :tag "No limit" nil) + (integer :tag "Characters"))) (defun flymake-check-patch-master-file-buffer (master-file-temp-buffer @@ -434,22 +425,34 @@ to the beginning of the list (File.h -> File.cpp moved to top)." source-file-name patched-source-file-name include-dirs regexp) "Check if MASTER-FILE-NAME is a master file for SOURCE-FILE-NAME. -For .cpp master file this means it includes SOURCE-FILE-NAME (.h). If yes, patch a copy of MASTER-FILE-NAME to include PATCHED-SOURCE-FILE-NAME instead of SOURCE-FILE-NAME. + +For example, foo.cpp is a master file if it includes foo.h. + Whether a buffer for MATER-FILE-NAME exists, use it as a source instead of reading master file from disk." (let* ((source-file-nondir (file-name-nondirectory source-file-name)) + (source-file-extension (file-name-extension source-file-nondir)) + (source-file-nonext (file-name-sans-extension source-file-nondir)) (found nil) (inc-name nil) (search-limit flymake-check-file-limit)) (setq regexp (format regexp ; "[ \t]*#[ \t]*include[ \t]*\"\\(.*%s\\)\"" - (regexp-quote source-file-nondir))) + ;; Hack for tex files, where \include often excludes .tex. + ;; Maybe this is safe generally. + (if (and (> (length source-file-extension) 1) + (string-equal source-file-extension "tex")) + (format "%s\\(?:\\.%s\\)?" + (regexp-quote source-file-nonext) + (regexp-quote source-file-extension)) + (regexp-quote source-file-nondir)))) (unwind-protect (with-current-buffer master-file-temp-buffer - (when (> search-limit (point-max)) - (setq search-limit (point-max))) + (if (or (not search-limit) + (> search-limit (point-max))) + (setq search-limit (point-max))) (flymake-log 3 "checking %s against regexp %s" master-file-name regexp) (goto-char (point-min)) @@ -460,6 +463,11 @@ instead of reading master file from disk." (flymake-log 3 "found possible match for %s" source-file-nondir) (setq inc-name (match-string 1)) + (and (> (length source-file-extension) 1) + (string-equal source-file-extension "tex") + (not (string-match (format "\\.%s\\'" source-file-extension) + inc-name)) + (setq inc-name (concat inc-name "." source-file-extension))) (when (eq t (compare-strings source-file-nondir nil nil inc-name (- (length inc-name) @@ -564,10 +572,8 @@ Find master file, patch and save it." nil)))) (defun flymake-save-buffer-in-file (file-name) - (save-restriction - (widen) - (make-directory (file-name-directory file-name) 1) - (write-region (point-min) (point-max) file-name nil 566)) + (make-directory (file-name-directory file-name) 1) + (write-region nil nil file-name nil 566) (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name)) (defun flymake-save-string-to-file (file-name data) @@ -587,7 +593,7 @@ It's flymake process filter." (flymake-log 3 "received %d byte(s) of output from process %d" (length output) (process-id process)) - (when source-buffer + (when (buffer-live-p source-buffer) (with-current-buffer source-buffer (flymake-parse-output-and-residual output))))) @@ -645,7 +651,7 @@ It's flymake process filter." (flymake-report-status "" "") ; PASSED (if (not flymake-check-was-interrupted) (flymake-report-fatal-status "CFGERR" - (format "Configuration error has occured while running %s" command)) + (format "Configuration error has occurred while running %s" command)) (flymake-report-status nil ""))) ; "STOPPED" (flymake-report-status (format "%d/%d" err-count warn-count) "")))) @@ -791,15 +797,15 @@ Return t if it has at least one flymake overlay, nil if no overlay." has-flymake-overlays)) (defface flymake-errline - ;;+ '((((class color)) (:foreground "OrangeRed" :bold t :underline t)) - ;;+ '((((class color)) (:underline "OrangeRed")) - '((((class color)) (:background "LightPink")) + '((((class color) (background dark)) (:background "Firebrick4")) + (((class color) (background light)) (:background "LightPink")) (t (:bold t))) "Face used for marking error lines." :group 'flymake) (defface flymake-warnline - '((((class color)) (:background "LightBlue2")) + '((((class color) (background dark)) (:background "DarkBlue")) + (((class color) (background light)) (:background "LightBlue2")) (t (:bold t))) "Face used for marking warning lines." :group 'flymake) @@ -807,9 +813,10 @@ Return t if it has at least one flymake overlay, nil if no overlay." (defun flymake-highlight-line (line-no line-err-info-list) "Highlight line LINE-NO in current buffer. Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting." - (goto-line line-no) - (let* ((line-beg (flymake-line-beginning-position)) - (line-end (flymake-line-end-position)) + (goto-char (point-min)) + (forward-line (1- line-no)) + (let* ((line-beg (point-at-bol)) + (line-end (point-at-eol)) (beg line-beg) (end line-end) (tooltip-text (flymake-ler-text (nth 0 line-err-info-list))) @@ -858,11 +865,9 @@ Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting." (flymake-ler-file line-err-info))) (setq line-err-info (flymake-ler-set-full-file line-err-info real-file-name)) - (if (flymake-same-files real-file-name source-file-name) - (setq line-err-info (flymake-ler-set-file line-err-info nil)) - (setq line-err-info (flymake-ler-set-file line-err-info (file-name-nondirectory real-file-name)))) - - (setq err-info-list (flymake-add-err-info err-info-list line-err-info))) + (when (flymake-same-files real-file-name source-file-name) + (setq line-err-info (flymake-ler-set-file line-err-info nil)) + (setq err-info-list (flymake-add-err-info err-info-list line-err-info)))) (flymake-log 3 "parsed '%s', %s line-err-info" (nth idx lines) (if line-err-info "got" "no")) (setq idx (1+ idx))) err-info-list)) @@ -1154,7 +1159,8 @@ For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'." (when dir (let ((default-directory dir)) (flymake-log 3 "starting process on dir %s" default-directory))) - (setq process (apply 'start-process "flymake-proc" (current-buffer) cmd args)) + (setq process (apply 'start-file-process + "flymake-proc" (current-buffer) cmd args)) (set-process-sentinel process 'flymake-process-sentinel) (set-process-filter process 'flymake-process-filter) (push process flymake-processes) @@ -1273,7 +1279,8 @@ For the format of LINE-ERR-INFO, see `flymake-ler-make-ler'." (if (not (file-exists-p file)) (flymake-log 1 "File %s does not exist" file) (find-file file) - (goto-line line))) + (goto-char (point-min)) + (forward-line (1- line)))) ;; flymake minor mode declarations (defvar flymake-mode-line nil) @@ -1447,7 +1454,8 @@ With arg, turn Flymake mode on if and only if arg is positive." (defun flymake-goto-line (line-no) "Go to line LINE-NO, then skip whitespace." - (goto-line line-no) + (goto-char (point-min)) + (forward-line (1- line-no)) (flymake-skip-whitespace)) (defun flymake-goto-next-error () @@ -1701,9 +1709,10 @@ Use CREATE-TEMP-F for creating temp copy." ;;;; .h/make specific (defun flymake-master-make-header-init () - (flymake-master-make-init 'flymake-get-include-dirs - '("\\.cpp\\'" "\\.c\\'") - "[ \t]*#[ \t]*include[ \t]*\"\\([[:word:]0-9/\\_.]*%s\\)\"")) + (flymake-master-make-init + 'flymake-get-include-dirs + '("\\.\\(?:c\\(?:pp\\|xx\\|\\+\\+\\)?\\|CC\\)\\'") + "[ \t]*#[ \t]*include[ \t]*\"\\([[:word:]0-9/\\_.]*%s\\)\"")) ;;;; .java/make specific (defun flymake-simple-make-java-init () @@ -1745,11 +1754,14 @@ Use CREATE-TEMP-F for creating temp copy." (defun flymake-simple-tex-init () (flymake-get-tex-args (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace))) +;; Perhaps there should be a buffer-local variable flymake-master-file +;; that people can set to override this stuff. Could inherit from +;; the similar AUCTeX variable. (defun flymake-master-tex-init () (let* ((temp-master-file-name (flymake-init-create-temp-source-and-master-buffer-copy 'flymake-get-include-dirs-dot 'flymake-create-temp-inplace '("\\.tex\\'") - "[ \t]*\\input[ \t]*{\\(.*%s\\)}"))) + "[ \t]*\\in\\(?:put\\|clude\\)[ \t]*{\\(.*%s\\)}"))) (when temp-master-file-name (flymake-get-tex-args temp-master-file-name)))) @@ -1762,5 +1774,4 @@ Use CREATE-TEMP-F for creating temp copy." (provide 'flymake) -;; arch-tag: 8f0d6090-061d-4cac-8862-7c151c4a02dd ;;; flymake.el ends here