;;; flymake.el --- a universal on-the-fly syntax checker -*- lexical-binding: t; -*-
-;; Copyright (C) 2003-2013 Free Software Foundation, Inc.
+;; Copyright (C) 2003-2016 Free Software Foundation, Inc.
;; Author: Pavel Kobyakov <pk_at_work@yahoo.com>
;; Maintainer: Leo Liu <sdl.web@gmail.com>
(defgroup flymake nil
"Universal on-the-fly syntax checker."
:version "23.1"
+ :link '(custom-manual "(flymake) Top")
:group 'tools)
(defcustom flymake-error-bitmap '(exclamation-mark error)
(defvar-local flymake-new-err-info nil
"Same as `flymake-err-info', effective when a syntax check is in progress.")
-(defun flymake-posn-at-point-as-event (&optional position window dx dy)
- "Return pixel position of top left corner of glyph at POSITION.
-
-The position is relative to top left corner of WINDOW, as a
-mouse-1 click event (identical to the event that would be
-triggered by clicking mouse button 1 at the top left corner of
-the glyph).
-
-POSITION and WINDOW default to the position of point in the
-selected window.
-
-DX and DY specify optional offsets from the top left of the glyph."
- (let* ((window (or window (selected-window)))
- (position (or position (window-point window)))
- (dx (or dx 0))
- (dy (or dy 0))
- (pos (posn-at-point position window))
- (x-y (posn-x-y pos))
- (edges (window-inside-pixel-edges window))
- (win-x-y (window-pixel-edges window)))
- ;; adjust for window edges
- (setcar (nthcdr 2 pos)
- (cons (+ (car x-y) (car edges) (- (car win-x-y)) dx)
- (+ (cdr x-y) (cadr edges) (- (cadr win-x-y)) dy)))
- (list 'mouse-1 pos)))
-
-;;; XXX: get rid of the following two functions
-
-(defun flymake-popup-menu (menu-data)
- "Pop up the flymake menu at point, using the data MENU-DATA.
-POS is a list of the form ((X Y) WINDOW), where X and Y are
-pixels positions from the top left corner of WINDOW's frame.
-MENU-DATA is a list of error and warning messages returned by
-`flymake-make-err-menu-data'."
- (x-popup-menu (flymake-posn-at-point-as-event)
- (flymake-make-emacs-menu menu-data)))
-
-(defun flymake-make-emacs-menu (menu-data)
- "Return a menu specifier using MENU-DATA.
-MENU-DATA is a list of error and warning messages returned by
-`flymake-make-err-menu-data'.
-See `x-popup-menu' for the menu specifier format."
- (let* ((menu-title (nth 0 menu-data))
- (menu-items (nth 1 menu-data))
- (menu-commands (mapcar (lambda (foo)
- (cons (nth 0 foo) (nth 1 foo)))
- menu-items)))
- (list menu-title (cons "" menu-commands))))
-
(defun flymake-log (level text &rest args)
"Log a message at level LEVEL.
If LEVEL is higher than `flymake-log-level', the message is
TEXT is a format control string, and the remaining arguments ARGS
are the string substitutions (see the function `format')."
(if (<= level flymake-log-level)
- (let* ((msg (apply 'format text args)))
+ (let* ((msg (apply #'format-message text args)))
(message "%s" msg))))
(defun flymake-ins-after (list pos val)
nil)))))
(defun flymake-fix-file-name (name)
- "Replace all occurrences of '\' with '/'."
+ "Replace all occurrences of `\\' with `/'."
(when name
(setq name (expand-file-name name))
(setq name (abbreviate-file-name name))
(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)
- "Save string DATA to file FILE-NAME."
- (write-region data nil file-name nil 566))
-
-(defun flymake-read-file-to-string (file-name)
- "Read contents of file FILE-NAME and return as a string."
- (with-temp-buffer
- (insert-file-contents file-name)
- (buffer-substring (point-min) (point-max))))
-
(defun flymake-process-filter (process output)
"Parse OUTPUT and highlight error lines.
It's flymake process filter."
(setq flymake-is-running nil))))))))
(defun flymake-post-syntax-check (exit-status command)
- (setq flymake-err-info flymake-new-err-info)
- (setq flymake-new-err-info nil)
- (setq flymake-err-info
- (flymake-fix-line-numbers
- flymake-err-info 1 (count-lines (point-min) (point-max))))
- (flymake-delete-own-overlays)
- (flymake-highlight-err-lines flymake-err-info)
- (let (err-count warn-count)
- (setq err-count (flymake-get-err-count flymake-err-info "e"))
- (setq warn-count (flymake-get-err-count flymake-err-info "w"))
- (flymake-log 2 "%s: %d error(s), %d warning(s) in %.2f second(s)"
- (buffer-name) err-count warn-count
- (- (float-time) flymake-check-start-time))
- (setq flymake-check-start-time nil)
-
- (if (and (equal 0 err-count) (equal 0 warn-count))
- (if (equal 0 exit-status)
- (flymake-report-status "" "") ; PASSED
- (if (not flymake-check-was-interrupted)
- (flymake-report-fatal-status "CFGERR"
- (format "Configuration error has occurred while running %s" command))
- (flymake-report-status nil ""))) ; "STOPPED"
- (flymake-report-status (format "%d/%d" err-count warn-count) ""))))
+ (save-restriction
+ (widen)
+ (setq flymake-err-info flymake-new-err-info)
+ (setq flymake-new-err-info nil)
+ (setq flymake-err-info
+ (flymake-fix-line-numbers
+ flymake-err-info 1 (count-lines (point-min) (point-max))))
+ (flymake-delete-own-overlays)
+ (flymake-highlight-err-lines flymake-err-info)
+ (let (err-count warn-count)
+ (setq err-count (flymake-get-err-count flymake-err-info "e"))
+ (setq warn-count (flymake-get-err-count flymake-err-info "w"))
+ (flymake-log 2 "%s: %d error(s), %d warning(s) in %.2f second(s)"
+ (buffer-name) err-count warn-count
+ (- (float-time) flymake-check-start-time))
+ (setq flymake-check-start-time nil)
+
+ (if (and (equal 0 err-count) (equal 0 warn-count))
+ (if (equal 0 exit-status)
+ (flymake-report-status "" "") ; PASSED
+ (if (not flymake-check-was-interrupted)
+ (flymake-report-fatal-status "CFGERR"
+ (format "Configuration error has occurred while running %s" command))
+ (flymake-report-status nil ""))) ; "STOPPED"
+ (flymake-report-status (format "%d/%d" err-count warn-count) "")))))
(defun flymake-parse-output-and-residual (output)
"Split OUTPUT into lines, merge in residual if necessary."
"Determine whether overlay OV was created by flymake."
(and (overlayp ov) (overlay-get ov 'flymake-overlay)))
-(defun flymake-make-overlay (beg end tooltip-text face bitmap mouse-face)
+(defun flymake-make-overlay (beg end tooltip-text face bitmap)
"Allocate a flymake overlay in range BEG and END."
(when (not (flymake-region-has-flymake-overlays beg end))
- (let ((ov (make-overlay beg end nil t t))
+ (let ((ov (make-overlay beg end nil t))
(fringe (and flymake-fringe-indicator-position
(propertize "!" 'display
(cons flymake-fringe-indicator-position
bitmap
(list bitmap)))))))
(overlay-put ov 'face face)
- (overlay-put ov 'mouse-face mouse-face)
(overlay-put ov 'help-echo tooltip-text)
(overlay-put ov 'flymake-overlay t)
(overlay-put ov 'priority 100)
Perhaps use text from LINE-ERR-INFO-LIST to enhance highlighting."
(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)))
- (face nil)
- (bitmap nil))
-
- (goto-char line-beg)
- (while (looking-at "[ \t]")
- (forward-char))
-
- (setq beg (point))
-
- (goto-char line-end)
- (while (and (looking-at "[ \t\r\n]") (> (point) 1))
- (backward-char))
-
- (setq end (1+ (point)))
-
- (when (<= end beg)
- (setq beg line-beg)
- (setq end line-end))
-
- (when (= end beg)
- (goto-char end)
- (forward-line)
- (setq end (point)))
-
- (if (> (flymake-get-line-err-count line-err-info-list "e") 0)
- (setq face 'flymake-errline
- bitmap flymake-error-bitmap)
- (setq face 'flymake-warnline
- bitmap flymake-warning-bitmap))
-
- (flymake-make-overlay beg end tooltip-text face bitmap nil)))
+ (pcase-let* ((beg (progn (back-to-indentation) (point)))
+ (end (progn
+ (end-of-line)
+ (skip-chars-backward " \t\f\t\n" beg)
+ (if (eq (point) beg)
+ (line-beginning-position 2)
+ (point))))
+ (tooltip-text (mapconcat #'flymake-ler-text line-err-info-list "\n"))
+ (`(,face ,bitmap)
+ (if (> (flymake-get-line-err-count line-err-info-list "e") 0)
+ (list 'flymake-errline flymake-error-bitmap)
+ (list 'flymake-warnline flymake-warning-bitmap))))
+ (flymake-make-overlay beg end tooltip-text face bitmap)))
(defun flymake-parse-err-lines (err-info-list lines)
"Parse err LINES, store info in ERR-INFO-LIST."
(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"))
+ (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))
(append
'(
;; MS Visual C++ 6.0
- ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
+ ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) : \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
1 3 nil 4)
;; jikes
- ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
+ ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\):[0-9]+:[0-9]+:[0-9]+: \\(\\(Error\\|Warning\\|Caution\\|Semantic Error\\):[ \t\n]*\\(.+\\)\\)"
1 3 nil 4)
;; MS midl
("midl[ ]*:[ ]*\\(command line error .*\\)"
nil nil nil 1)
;; MS C#
- ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+)\: \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
+ ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\),[0-9]+): \\(\\(error\\|warning\\|fatal error\\) \\(CS[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
1 3 nil 4)
;; perl
("\\(.*\\) at \\([^ \n]+\\) line \\([0-9]+\\)[,.\n]" 2 3 nil 1)
("\\(?:Parse\\|Fatal\\) error: \\(.*\\) in \\(.*\\) on line \\([0-9]+\\)" 2 3 nil 1)
;; LaTeX warnings (fileless) ("\\(LaTeX \\(Warning\\|Error\\): .*\\) on input line \\([0-9]+\\)" 20 3 nil 1)
;; ant/javac. Note this also matches gcc warnings!
- (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\\(?:\:[0-9]+\\)?\:[ \t\n]*\\(.+\\)"
+ (" *\\(\\[javac\\] *\\)?\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\):\\([0-9]+\\)\\(?::[0-9]+\\)?:[ \t\n]*\\(.+\\)"
2 4 nil 5))
;; compilation-error-regexp-alist)
(flymake-reformat-err-line-patterns-from-compile-el compilation-error-regexp-alist-alist))
Use `flymake-reformat-err-line-patterns-from-compile-el' to add patterns
from compile.el")
-;;(defcustom flymake-err-line-patterns
-;; '(
-;; ; MS Visual C++ 6.0
-;; ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)(\\([0-9]+\\)) \: \\(\\(error\\|warning\\|fatal error\\) \\(C[0-9]+\\):[ \t\n]*\\(.+\\)\\)"
-;; 1 3 4)
-;; ; jikes
-;; ("\\(\\([a-zA-Z]:\\)?[^:(\t\n]+\\)\:\\([0-9]+\\)\:[0-9]+\:[0-9]+\:[0-9]+\: \\(\\(Error\\|Warning\\|Caution\\):[ \t\n]*\\(.+\\)\\)"
-;; 1 3 4))
-;; "patterns for matching error/warning lines, (regexp file-idx line-idx err-text-idx)"
-;; :group 'flymake
-;; :type '(repeat (string number number number))
-;;)
-
(define-obsolete-variable-alias 'flymake-warning-re 'flymake-warning-predicate "24.4")
(defvar flymake-warning-predicate "^[wW]arning"
"Predicate matching against error text to detect a warning.
(funcall flymake-get-project-include-dirs-function basedir))
(defun flymake-get-system-include-dirs ()
- "System include dirs - from the 'INCLUDE' env setting."
+ "System include dirs - from the `INCLUDE' env setting."
(let* ((includes (getenv "INCLUDE")))
(if includes (split-string includes path-separator t) nil)))
default-directory)
process)
(error
- (let* ((err-str (format "Failed to launch syntax check process '%s' with args %s: %s"
- cmd args (error-message-string err)))
+ (let* ((err-str
+ (format-message
+ "Failed to launch syntax check process `%s' with args %s: %s"
+ cmd args (error-message-string err)))
(source-file-name buffer-file-name)
(cleanup-f (flymake-get-cleanup-function source-file-name)))
(flymake-log 0 err-str)
(flymake-log 3 "starting syntax check as more than 1 second passed since last change")
(flymake-start-syntax-check)))))
-(defun flymake-display-err-menu-for-current-line ()
- "Display a menu with errors/warnings for current line if it has errors and/or warnings."
- (interactive)
- (let* ((line-no (line-number-at-pos))
- (line-err-info-list (nth 0 (flymake-find-err-info flymake-err-info line-no)))
- (menu-data (flymake-make-err-menu-data line-no line-err-info-list))
- (choice nil))
- (if menu-data
- (progn
- (setq choice (flymake-popup-menu menu-data))
- (flymake-log 3 "choice=%s" choice)
- (when choice
- (eval choice)))
- (flymake-log 1 "no errors for line %d" line-no))))
-
-(defun flymake-make-err-menu-data (line-no line-err-info-list)
- "Make a (menu-title (item-title item-action)*) list with errors/warnings from LINE-ERR-INFO-LIST."
- (let* ((menu-items nil))
- (when line-err-info-list
- (let* ((count (length line-err-info-list))
- (menu-item-text nil))
- (while (> count 0)
- (setq menu-item-text (flymake-ler-text (nth (1- count) line-err-info-list)))
- (let* ((file (flymake-ler-file (nth (1- count) line-err-info-list)))
- (full-file (flymake-ler-full-file (nth (1- count) line-err-info-list)))
- (line (flymake-ler-line (nth (1- count) line-err-info-list))))
- (if file
- (setq menu-item-text (concat menu-item-text " - " file "(" (format "%d" line) ")")))
- (setq menu-items (cons (list menu-item-text
- (if file (list 'flymake-goto-file-and-line full-file line) nil))
- menu-items)))
- (setq count (1- count)))
- (flymake-log 3 "created menu-items with %d item(s)" (length menu-items))))
- (if menu-items
- (let* ((menu-title (format "Line %d: %d error(s), %d warning(s)" line-no
- (flymake-get-line-err-count line-err-info-list "e")
- (flymake-get-line-err-count line-err-info-list "w"))))
- (list menu-title menu-items))
- nil)))
+(define-obsolete-function-alias 'flymake-display-err-menu-for-current-line
+ 'flymake-popup-current-error-menu "24.4")
+
+(defun flymake-popup-current-error-menu (&optional event)
+ "Pop up a menu with errors/warnings for current line."
+ (interactive (list last-nonmenu-event))
+ (let* ((line-no (line-number-at-pos))
+ (errors (or (car (flymake-find-err-info flymake-err-info line-no))
+ (user-error "No errors for current line")))
+ (menu (mapcar (lambda (x)
+ (if (flymake-ler-file x)
+ (cons (format "%s - %s(%d)"
+ (flymake-ler-text x)
+ (flymake-ler-file x)
+ (flymake-ler-line x))
+ x)
+ (list (flymake-ler-text x))))
+ errors))
+ (event (if (mouse-event-p event)
+ event
+ (list 'mouse-1 (posn-at-point))))
+ (title (format "Line %d: %d error(s), %d warning(s)"
+ line-no
+ (flymake-get-line-err-count errors "e")
+ (flymake-get-line-err-count errors "w")))
+ (choice (x-popup-menu event (list title (cons "" menu)))))
+ (flymake-log 3 "choice=%s" choice)
+ (when choice
+ (flymake-goto-file-and-line (flymake-ler-full-file choice)
+ (flymake-ler-line choice)))))
(defun flymake-goto-file-and-line (file line)
"Try to get buffer for FILE and goto line LINE in it."