From 565992c3f14817263779f7adc2124fd3419d174f Mon Sep 17 00:00:00 2001 From: =?utf8?q?Jo=C3=A3o=20T=C3=A1vora?= Date: Thu, 17 Apr 2025 22:00:39 +0100 Subject: [PATCH] Flymake: more powerful flymake-make-diagnostic and rework manual Flymake backends may now explicitly specify an origin and a code for a diagnostic in addition to the textual description. This change lays groundwork for richer diagnostic listings and user options for summarizing diagnostics, addressing bug#77439 and bug#77480. * doc/misc/flymake.texi (Flymake API): Rename from "Extending Flymake". Rework. (Inspecting diagnostics): New section. * lisp/progmodes/flymake.el (flymake--diag): Add origin, code and message. Remove text. (flymake-make-diagnostic): Support new origin, code and message. (flymake-diagnostic-text): Rework. (cherry picked from commit 0fe05a920adc457d6f4adca71979059b8e2d0253) --- doc/misc/flymake.texi | 89 ++++++++++++++++++++++----------------- lisp/progmodes/flymake.el | 60 +++++++++++++++++--------- 2 files changed, 92 insertions(+), 57 deletions(-) diff --git a/doc/misc/flymake.texi b/doc/misc/flymake.texi index 668a72b4cd1..0e43df17aa2 100644 --- a/doc/misc/flymake.texi +++ b/doc/misc/flymake.texi @@ -62,7 +62,7 @@ To learn about using Flymake, @pxref{Using Flymake}. When the Emacs LSP support mode Eglot is enabled, Flymake will use that as an additional back-end. @xref{Eglot Features,,, eglot, Eglot: The Emacs LSP Client}. Flymake is also designed to be easily extended to -support new backends via an Elisp interface. @xref{Extending Flymake}. +support new backends via an Elisp interface. @xref{Flymake API}. @ifnottex @insertcopying @@ -70,7 +70,7 @@ support new backends via an Elisp interface. @xref{Extending Flymake}. @menu * Using Flymake:: -* Extending Flymake:: +* Flymake API:: * The legacy Proc backend:: * GNU Free Documentation License:: * Index:: @@ -210,7 +210,7 @@ investigate and remedy the situation (@pxref{Troubleshooting}). @item @code{?} @tab There are no applicable Flymake backends for this buffer, thus Flymake cannot annotate it. To fix this, a user may look to extending Flymake -and add a new backend (@pxref{Extending Flymake}). +and add a new backend (@pxref{Flymake API}). @end multitable @@ -361,19 +361,23 @@ A custom face for summarizing diagnostic warning messages. A custom face for summarizing diagnostic notes. @end vtable -@node Extending Flymake -@chapter Extending Flymake +@node Flymake API, The legacy Proc backend, Using Flymake, Top +@chapter Flymake API @cindex extending flymake -Flymake can primarily be extended in one of two ways: +Flymake's API supports the following use cases: @enumerate @item -By changing the look and feel of the annotations produced by the +Changing the look and feel of the annotations produced by the different backends. @xref{Flymake error types}. @item -By adding a new buffer-checking backend. @xref{Backend functions}. +Adding a new buffer-checking backend. @xref{Backend functions}. + +@item +Writing extension to and process Flymake's output. @xref{Inspecting +diagnostics}. @end enumerate The following sections discuss each approach in detail. @@ -381,6 +385,7 @@ The following sections discuss each approach in detail. @menu * Flymake error types:: * Backend functions:: +* Inspecting diagnostics:: @end menu @node Flymake error types @@ -673,37 +678,19 @@ reports targeting other parts of the buffer remain valid. Before delivering them to Flymake, backends create diagnostic objects by calling the function @code{flymake-make-diagnostic}. -@deffn Function flymake-make-diagnostic locus beg end type text &optional data +@deffn Function flymake-make-diagnostic locus beg end type info &optional data Make a Flymake diagnostic for the region of text in @var{locus}'s -delimited by @var{beg} and @var{end}. @var{type} is a diagnostic -symbol (@pxref{Flymake error types}), and @var{text} is a description -of the problem detected in this region. Most commonly @var{locus} is -the buffer object designating for the current buffer being -syntax-checked. However, it may be a string naming a file relative -to the current working directory. @xref{Foreign and list-only -diagnostics}, for when this may be useful. Depending on the type of -@var{locus}, @var{beg} and @var{end} are both either buffer positions -or conses (@var{line} . @var{col}) which specify the line and column -of the diagnostic's start and end positions, respectively. -@end deffn - -@cindex access diagnostic object -These objects' properties can be accessed with the functions -@code{flymake-diagnostic-backend}, @code{flymake-diagnostic-buffer}, -@code{flymake-diagnostic-text}, @code{flymake-diagnostic-beg}, -@code{flymake-diagnostic-end}, @code{flymake-diagnostic-type} and -@code{flymake-diagnostic-data}. - -Additionally, the function @code{flymake-diagnostics} will collect -such objects in the region you specify. - -@cindex collect diagnostic objects -@deffn Function flymake-diagnostics beg end -Get a list of Flymake diagnostics in the region determined by -@var{beg} and @var{end}. If neither @var{beg} or @var{end} is -supplied, use the whole buffer, otherwise if @var{beg} is -non-@code{nil} and @var{end} is @code{nil}, consider only diagnostics -at @var{beg}. +delimited by @var{beg} and @var{end}. @var{type} is a diagnostic symbol +(@pxref{Flymake error types}). @var{text} can be a string or a list +(@var{origin} @var{code} @var{message}) appropriately categorizing and +describing the diagnostic. Most commonly, @var{locus} is the buffer +object designating for the current buffer being syntax-checked. +However, it may be a string naming a file relative to the current +working directory. @xref{Foreign and list-only diagnostics}, for when +this may be useful. Depending on the type of @var{locus}, @var{beg} and +@var{end} are both either buffer positions or conses (@var{line} +. @var{col}) which specify the line and column of the diagnostic's start +and end positions, respectively. @end deffn @cindex buffer position from line and column number @@ -900,6 +887,32 @@ Binding,,, elisp, The Emacs Lisp Reference Manual}) to be active. @end group @end example +@node Inspecting diagnostics +@section Inspecting diagnostics + +When Flymake has called on the backend and collected its diagnostics, it +will annotate the buffer with it. After this happens, Elisp programs +may call @code{flymake-diagnostics} to collect such objects in a +specified region. + +@cindex collect diagnostic objects +@deffn Function flymake-diagnostics beg end +Get a list of Flymake diagnostics in the region determined by +@var{beg} and @var{end}. If neither @var{beg} or @var{end} is +supplied, use the whole buffer, otherwise if @var{beg} is +non-@code{nil} and @var{end} is @code{nil}, consider only diagnostics +at @var{beg}. +@end deffn + +@cindex access diagnostic object +A diagnostic object's properties can be accessed with the functions +@code{flymake-diagnostic-backend}, @code{flymake-diagnostic-buffer}, +@code{flymake-diagnostic-origin}, @code{flymake-diagnostic-code} +@code{flymake-diagnostic-message}, @code{flymake-diagnostic-beg}, +@code{flymake-diagnostic-end}, @code{flymake-diagnostic-type} and +@code{flymake-diagnostic-data}. @code{flymake-diagnostic-text} will +compose the diagnostic's origin, code and message in a single string. + @node The legacy Proc backend @chapter The legacy ``Proc'' backend @cindex legacy proc backend diff --git a/lisp/progmodes/flymake.el b/lisp/progmodes/flymake.el index 0359b88218f..2a6205b28f1 100644 --- a/lisp/progmodes/flymake.el +++ b/lisp/progmodes/flymake.el @@ -292,7 +292,7 @@ when flymake is turned off.") (cl-defstruct (flymake--diag (:constructor flymake--diag-make)) - locus beg end type text backend data overlay-properties overlay + locus beg end type origin code message backend data overlay-properties overlay ;; FIXME: See usage of these two in `flymake--highlight-line'. ;; Ideally they wouldn't be needed. orig-beg orig-end fix-function) @@ -302,29 +302,33 @@ when flymake is turned off.") beg end type - text + info &optional data overlay-properties fix-function) "Make a Flymake diagnostic for LOCUS's region from BEG to END. LOCUS is a buffer object or a string designating a file name. -TYPE is a diagnostic symbol and TEXT is string describing the -problem detected in this region. DATA is any object that the -caller wishes to attach to the created diagnostic for later -retrieval with `flymake-diagnostic-data'. +TYPE is a diagnostic symbol (see Info Node `(Flymake)Flymake error +types') -If LOCUS is a buffer BEG and END should be buffer positions -inside it. If LOCUS designates a file, BEG and END should be a -cons (LINE . COL) indicating a file position. In this second -case, END may be omitted in which case the region is computed -using `flymake-diag-region' if the diagnostic is appended to an -actual buffer. +INFO is a description of the problem detected. It may be a string, or +list of three strings (ORIGIN CODE MESSAGE) appropriately categorizing +and describing the diagnostic. -OVERLAY-PROPERTIES is an alist of properties attached to the -created diagnostic, overriding the default properties and any -properties listed in the `flymake-overlay-control' property of -the diagnostic's type symbol. +DATA is any object that the caller wishes to attach to the created +diagnostic for later retrieval with `flymake-diagnostic-data'. + +If LOCUS is a buffer, BEG and END should be buffer positions inside it. +If LOCUS designates a file, BEG and END should be a cons (LINE . COL) +indicating a file position. In this second case, END may be omitted in +which case the region is computed using `flymake-diag-region' if the +diagnostic is appended to an actual buffer. + +OVERLAY-PROPERTIES is an alist of properties attached to the created +diagnostic, overriding the default properties and any properties listed +in the `flymake-overlay-control' property of the diagnostic's type +symbol. FIX-FUNCTION, if non-nil, is a function that takes DATA and returns a list of fix suggestions for this diagnostic. Each fix suggestion is a @@ -334,8 +338,11 @@ Alternatively, EDITS can also be a function of no arguments that performs the fix." (when (stringp locus) (setq locus (expand-file-name locus))) + (when (stringp info) + (setq info (list nil nil info))) (flymake--diag-make :locus locus :beg beg :end end - :type type :text text :data data + :type type :origin (car info) :code (cadr info) + :message (caddr info) :data data :overlay-properties overlay-properties :orig-beg beg :orig-end end @@ -362,14 +369,27 @@ diagnostics at BEG." ,(format "Get Flymake diagnostic DIAG's %s." (symbol-name thing)) (,internal diag))) -(flymake--diag-accessor flymake-diagnostic-text flymake--diag-text text) (flymake--diag-accessor flymake-diagnostic-type flymake--diag-type type) (flymake--diag-accessor flymake-diagnostic-backend flymake--diag-backend backend) +(flymake--diag-accessor flymake-diagnostic-origin flymake--diag-origin backend) +(flymake--diag-accessor flymake-diagnostic-code flymake--diag-code backend) +(flymake--diag-accessor flymake-diagnostic-message flymake--diag-message backend) (flymake--diag-accessor flymake-diagnostic-data flymake--diag-data data) (flymake--diag-accessor flymake-diagnostic-beg flymake--diag-beg beg) (flymake--diag-accessor flymake-diagnostic-end flymake--diag-end end) (flymake--diag-accessor flymake-diagnostic-buffer flymake--diag-locus locus) +(defun flymake-diagnostic-text (diag) + "Get Flymake diagnostic DIAG's text." + (let ((a (flymake--diag-origin diag)) + (b (flymake--diag-code diag)) + (c (flymake--diag-message diag))) + (concat a + (when (and a b) " ") + (when b (concat "[" b "]")) + (when (and c (or a b)) ": ") + c))) + (defun flymake-diagnostic-oneliner (diag &optional nopaintp) "Get truncated one-line text string for diagnostic DIAG. This is useful for displaying the DIAG's text to the user in @@ -708,7 +728,9 @@ Return to original margin width if ORIG-WIDTH is non-nil." flymake--diag-beg flymake-diagnostic-type flymake-diagnostic-backend - flymake-diagnostic-text) + flymake-diagnostic-origin + flymake-diagnostic-code + flymake-diagnostic-message) always (equal (funcall comp a) (funcall comp b))))) (defun flymake--delete-overlay (ov) -- 2.39.5