From 54beebb4e0d919c7ee6dcdd7d774d851c35f85b7 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 21 Sep 2017 14:44:13 +0100 Subject: [PATCH] Flymake highlights GCC info/notes as detected by flymake-proc.el * lisp/progmodes/flymake-proc.el (flymake-proc--diagnostics-for-pattern): Rewrite (using cl-loop) to honour more sophisticated flymake-proc-diagnostic-type-pred. (flymake-warning-re): Is now an obsolete alias for flymake-proc-diagnostic-type-pred. (flymake-proc-diagnostic-type-pred): Rename and augment from flymake-proc-warning-predicate. (flymake-proc-warning-predicate): Delete. * lisp/progmodes/flymake.el (flymake-note): New face. (flymake-diagnostic-types-alist): Simplify. (flymake-note): New overlay category. (flymake--lookup-type-property): Only lookup single keys, not lists. (flymake--diag-errorp): Rewrite. (flymake--highlight-line): Use flymake--lookup-type-property. * test/lisp/progmodes/flymake-tests.el (different-diagnostic-types): Rename from errors-and-warnings. Check notes. (flymake-tests--call-with-fixture): Use flymake-proc-diagnostic-type-pred. --- lisp/progmodes/flymake-proc.el | 121 +++++++++++++++------------ lisp/progmodes/flymake.el | 32 +++---- test/lisp/progmodes/flymake-tests.el | 8 +- 3 files changed, 90 insertions(+), 71 deletions(-) diff --git a/lisp/progmodes/flymake-proc.el b/lisp/progmodes/flymake-proc.el index dd6bf501733..2e593bd758d 100644 --- a/lisp/progmodes/flymake-proc.el +++ b/lisp/progmodes/flymake-proc.el @@ -394,47 +394,51 @@ Create parent directories as needed." (flymake-log 3 "saved buffer %s in file %s" (buffer-name) file-name)) (defun flymake-proc--diagnostics-for-pattern (proc pattern) - (condition-case err - (pcase-let ((`(,regexp ,file-idx ,line-idx ,col-idx ,message-idx) - pattern) - (retval)) - (while (search-forward-regexp regexp nil t) - (let* ((fname (and file-idx (match-string file-idx))) - (message (and message-idx (match-string message-idx))) - (line-string (and line-idx (match-string line-idx))) - (line-number (and line-string - (string-to-number line-string))) - (col-string (and col-idx (match-string col-idx))) - (col-number (and col-string - (string-to-number col-string)))) - (with-current-buffer (process-buffer proc) - (push - (flymake-make-diagnostic - :file fname - :line line-number - :col col-number - :type (if (and - message - (cond ((stringp flymake-proc-warning-predicate) - (string-match flymake-proc-warning-predicate - message)) - ((functionp flymake-proc-warning-predicate) - (funcall flymake-proc-warning-predicate - message)))) - "w" - "e") - :text message - :full-file (and fname - (funcall - (flymake-proc--get-real-file-name-function - fname) - fname))) - retval)))) - retval) - (error - (flymake-log 1 "Error parsing process output for pattern %s: %s" - pattern err) - nil))) + (cl-flet ((guess-type + (pred message) + (cond ((null message) + :error) + ((stringp pred) + (if (string-match pred message) + :warning + :error)) + ((functionp pred) + (let ((probe (funcall pred message))) + (cond ((assoc-default probe + flymake-diagnostic-types-alist) + probe) + (probe + :warning) + (t + :error))))))) + (condition-case err + (cl-loop + with (regexp file-idx line-idx col-idx message-idx) = pattern + while (search-forward-regexp regexp nil t) + for fname = (and file-idx (match-string file-idx)) + for message = (and message-idx (match-string message-idx)) + for line-string = (and line-idx (match-string line-idx)) + for line-number = (and line-string + (string-to-number line-string)) + for col-string = (and col-idx (match-string col-idx)) + for col-number = (and col-string + (string-to-number col-string)) + collect (with-current-buffer (process-buffer proc) + (flymake-make-diagnostic + :file fname + :line line-number + :col col-number + :type (guess-type flymake-proc-diagnostic-type-pred message) + :text message + :full-file (and fname + (funcall + (flymake-proc--get-real-file-name-function + fname) + fname))))) + (error + (flymake-log 1 "Error parsing process output for pattern %s: %s" + pattern err) + nil)))) (defun flymake-proc--process-filter (proc string) "Parse STRING and collect diagnostics info." @@ -567,12 +571,29 @@ Convert it to flymake internal format." Use `flymake-proc-reformat-err-line-patterns-from-compile-el' to add patterns from compile.el") -(define-obsolete-variable-alias 'flymake-warning-re 'flymake-proc-warning-predicate "24.4") -(defvar flymake-proc-warning-predicate "^[wW]arning" - "Predicate matching against error text to detect a warning. -Takes a single argument, the error's text and should return non-nil -if it's a warning. -Instead of a function, it can also be a regular expression.") +(define-obsolete-variable-alias 'flymake-warning-re 'flymake-proc-diagnostic-type-pred "26.1") +(defvar flymake-proc-diagnostic-type-pred + 'flymake-proc-default-guess + "Predicate matching against diagnostic text to detect its type. +Takes a single argument, the diagnostic's text and should return +a value suitable for indexing +`flymake-diagnostic-types-alist' (which see). If the returned +value is nil, a type of `error' is assumed. For some backward +compatibility, if a non-nil value is returned that that doesn't +index that alist, a type of `:warning' is assumed. + +Instead of a function, it can also be a string, a regular +expression. A match indicates `:warning' type, otherwise +`:error'") + +(defun flymake-proc-default-guess (text) + "Guess if TEXT means a warning, a note or an error." + (cond ((string-match "^[wW]arning" text) + :warning) + ((string-match "^[nN]ote" text) + :note) + (t + :error))) (defun flymake-proc-get-project-include-dirs-imp (basedir) "Include dirs for the project current file belongs to." @@ -1167,12 +1188,6 @@ Convert it to flymake internal format.") (REGEXP FILE-IDX LINE-IDX COL-IDX ERR-TEXT-IDX). Use `flymake-reformat-err-line-patterns-from-compile-el' to add patterns from compile.el") - (define-obsolete-variable-alias 'flymake-warning-predicate - 'flymake-proc-warning-predicate "26.1" - "Predicate matching against error text to detect a warning. -Takes a single argument, the error's text and should return non-nil -if it's a warning. -Instead of a function, it can also be a regular expression.") (define-obsolete-function-alias 'flymake-parse-line 'flymake-proc-parse-line "26.1" "Parse LINE to see if it is an error or warning. diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 827bce4b634..b32e799e672 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -189,6 +189,15 @@ verify FILTER, sort them by COMPARE (using KEY)." :version "24.4" :group 'flymake) +(defface flymake-note + '((((supports :underline (:style wave))) + :underline (:style wave :color "yellow green")) + (t + :inherit warning)) + "Face used for marking note regions." + :version "26.1" + :group 'flymake) + (define-obsolete-face-alias 'flymake-warnline 'flymake-warning "26.1") (define-obsolete-face-alias 'flymake-errline 'flymake-error "26.1") @@ -226,13 +235,14 @@ Or nil if the region is invalid." nil))) (defvar flymake-diagnostic-types-alist - `((("e" :error error) + `((:error . ((flymake-category . flymake-error))) - (("w" :warning warning) - . ((flymake-category . flymake-warning)))) + (:warning + . ((flymake-category . flymake-warning))) + (:note + . ((flymake-category . flymake-note)))) "Alist ((KEY . PROPS)*) of properties of flymake error types. -KEY can be anything passed as `:type' to `flymake-diag-make', or -a list of these objects. +KEY can be anything passed as `:type' to `flymake-diag-make'. PROPS is an alist of properties that are applied, in order, to the diagnostics of each type. The recognized properties are: @@ -259,27 +269,21 @@ the diagnostics of each type. The recognized properties are: (put 'flymake-error 'face 'flymake-error) (put 'flymake-error 'bitmap flymake-error-bitmap) (put 'flymake-error 'severity (warning-numeric-level :error)) -(put 'flymake-error 'mode-line-face 'compilation-error) (put 'flymake-warning 'face 'flymake-warning) (put 'flymake-warning 'bitmap flymake-warning-bitmap) (put 'flymake-warning 'severity (warning-numeric-level :warning)) -(put 'flymake-warning 'mode-line-face 'compilation-warning) (put 'flymake-note 'face 'flymake-note) (put 'flymake-note 'bitmap flymake-warning-bitmap) (put 'flymake-note 'severity (warning-numeric-level :debug)) -(put 'flymake-note 'mode-line-face 'compilation-info) (defun flymake--lookup-type-property (type prop &optional default) "Look up PROP for TYPE in `flymake-diagnostic-types-alist'. If TYPE doesn't declare PROP in either -`flymake-diagnostic-types-alist' or its associated category, -return DEFAULT." - (let ((alist-probe (assoc type flymake-diagnostic-types-alist - (lambda (entry key) - (or (equal key entry) - (member key entry)))))) +`flymake-diagnostic-types-alist' or its associated +`flymake-category', return DEFAULT." + (let ((alist-probe (assoc type flymake-diagnostic-types-alist))) (cond (alist-probe (let* ((alist (cdr alist-probe)) (prop-probe (assoc prop alist))) diff --git a/test/lisp/progmodes/flymake-tests.el b/test/lisp/progmodes/flymake-tests.el index 5e76f3136ea..5ecc87fc7e6 100644 --- a/test/lisp/progmodes/flymake-tests.el +++ b/test/lisp/progmodes/flymake-tests.el @@ -41,7 +41,7 @@ nil sev-pred-supplied-p)) "Call FN after flymake setup in FILE, using `flymake-proc`. SEVERITY-PREDICATE is used to setup -`flymake-proc-warning-predicate'." +`flymake-proc-diagnostic-type-pred'" (let* ((file (expand-file-name file flymake-tests-data-directory)) (visiting (find-buffer-visiting file)) (buffer (or visiting (find-file-noselect file))) @@ -51,7 +51,7 @@ SEVERITY-PREDICATE is used to setup (with-current-buffer buffer (save-excursion (when sev-pred-supplied-p - (setq-local flymake-proc-warning-predicate severity-predicate)) + (setq-local flymake-proc-diagnostic-type-pred severity-predicate)) (goto-char (point-min)) (flymake-mode 1) ;; Weirdness here... http://debbugs.gnu.org/17647#25 @@ -115,13 +115,13 @@ SEVERITY-PREDICATE is used to setup (should (eq 'flymake-warning (face-at-point))))) -(ert-deftest errors-and-warnings () +(ert-deftest different-diagnostic-types () "Test GCC warning via function predicate." (skip-unless (and (executable-find "gcc") (executable-find "make"))) (flymake-tests--with-flymake ("errors-and-warnings.c") (flymake-goto-next-error) - (should (eq 'flymake-error (face-at-point))) + (should (eq 'flymake-note (face-at-point))) (flymake-goto-next-error) (should (eq 'flymake-warning (face-at-point))) (flymake-goto-next-error) -- 2.39.5