unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* compile.el error properties: buffer as filename not working
@ 2022-02-01  4:07 JD Smith
  2022-02-12 22:42 ` Stefan Monnier
  0 siblings, 1 reply; 3+ messages in thread
From: JD Smith @ 2022-02-01  4:07 UTC (permalink / raw)
  To: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1348 bytes --]


`compilation-parse-errors’ uses a regex matcher which includes support for a file matching function returning a buffer (emphasis added):

Or FILE can also be a function that returns (FILENAME) or (RELATIVE-FILENAME . DIRNAME).
In the former case, FILENAME may be relative or absolute, or it may be a buffer.

But unfortunately compile.el (v27.2) doesn’t actually seem to fully support the (BUFFER) style of return, despite mentioning, in the docs of `compilation-internal-error-properties':

FILE should be (FILENAME) or (RELATIVE-FILENAME . DIRNAME) or (BUFFER) or
nil.

I have discovered two issues (there may be more):

1. In `compilation-error-properties’, `compilation-transform-file-match-alist’ is matched against a nil filename, since the definition of that filename looks like (note the bufferp):

(let ((file-name
             (and (consp file)
                  (not (bufferp (car file)))
                  (if (cdr file)
                      (expand-file-name (car file) (cdr file))
                    (car file)))))

This seems to have been fixed using a when-let in the Emacs 28 branch (unconfirmed).

2. `compilation-get-file-structure’ is called with the file list, but this function does not expect a (buffer), and calls (e.g.) file-name-absolute-p(#<buffer boo.py>), resulting in an error.


[-- Attachment #2: Type: text/html, Size: 4436 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: compile.el error properties: buffer as filename not working
  2022-02-01  4:07 compile.el error properties: buffer as filename not working JD Smith
@ 2022-02-12 22:42 ` Stefan Monnier
  2022-02-13 14:20   ` JD Smith
  0 siblings, 1 reply; 3+ messages in thread
From: Stefan Monnier @ 2022-02-12 22:42 UTC (permalink / raw)
  To: JD Smith; +Cc: emacs-devel

> 1. In `compilation-error-properties’,
>    `compilation-transform-file-match-alist’ is matched against a nil
>    filename, since the definition of that filename looks like (note
>    the bufferp):
>
> (let ((file-name
>              (and (consp file)
>                   (not (bufferp (car file)))
>                   (if (cdr file)
>                       (expand-file-name (car file) (cdr file))
>                     (car file)))))
>
> This seems to have been fixed using a when-let in the Emacs 28 branch (unconfirmed).

> 2. `compilation-get-file-structure’ is called with the file list, but
>    this function does not expect a (buffer), and calls (e.g.)
>    file-name-absolute-p(#<buffer boo.py>), resulting in an error.

Any chance you can provide a recipe or a backtrace?
Also it might be useful to provide some context, such as which package
uses this ability to return a buffer.


        Stefan




^ permalink raw reply	[flat|nested] 3+ messages in thread

* Re: compile.el error properties: buffer as filename not working
  2022-02-12 22:42 ` Stefan Monnier
@ 2022-02-13 14:20   ` JD Smith
  0 siblings, 0 replies; 3+ messages in thread
From: JD Smith @ 2022-02-13 14:20 UTC (permalink / raw)
  To: Stefan Monnier; +Cc: emacs-devel

[-- Attachment #1: Type: text/plain, Size: 5137 bytes --]



> On Feb 12, 2022, at 5:42 PM, Stefan Monnier <monnier@iro.umontreal.ca> wrote:
> 
>> 1. In `compilation-error-properties’,
>>   `compilation-transform-file-match-alist’ is matched against a nil
>>   filename, since the definition of that filename looks like (note
>>   the bufferp):
>> 
>> (let ((file-name
>>             (and (consp file)
>>                  (not (bufferp (car file)))
>>                  (if (cdr file)
>>                      (expand-file-name (car file) (cdr file))
>>                    (car file)))))
>> 
>> This seems to have been fixed using a when-let in the Emacs 28 branch (unconfirmed).
> 
>> 2. `compilation-get-file-structure’ is called with the file list, but
>>   this function does not expect a (buffer), and calls (e.g.)
>>   file-name-absolute-p(#<buffer boo.py>), resulting in an error.
> 
> Any chance you can provide a recipe or a backtrace?
> Also it might be useful to provide some context, such as which package
> uses this ability to return a buffer.

Thanks. This is for an as yet unreleased packaged, which uses compilation scanning for uniform traceback navigation for both code files on disk as well as regions of code sent from buffers (which may have no associated file).  Hence the interest in using a buffer as the compile error “file” target.

Reproducing is fairly straightforward.  First, evaluate this simple “error line” pattern:

(defun my/filename-function () (list (get-buffer (match-string 1))))
(defvar my/compilation-error-regexp
  `((,(rx line-start 
	  "Buffer \"" (group (+ (not "\""))) "\", " ; 1: buffer name
	  "line" (+ space) (group (+ digit))	    ; 2: line
	  (* nonl) ?\n)
     my/filename-function
     2
     nil nil 1)))

Then, in a buffer like *compile* put the following fake error for it to match:

Buffer "*scratch*", line 2

In that buffer, evaluate (e.g. via M-:):

(progn (compilation-setup)
       (setq compilation-error-regexp-alist my/compilation-error-regexp)
       (compilation-parse-errors (point-min) (point-max)))

You should see error 1.) pertaining to searching the (nil) filename for /bin/sh (which may have been fixed in Emacs 28 already). 

Now, let’s eliminate that error by evaluating (again in *compile*):

(setq compilation-transform-file-match-alist nil)

To stop the transform check.  Now evaluate again:

(compilation-parse-errors (point-min) (point-max))

and you will see a different error (2.) from `compilation-get-file-structure', which does not appreciate being handed a buffer instead of a file, despite the documented validity of this input:

Debugger entered--Lisp error: (wrong-type-argument stringp #<buffer *scratch*>)
  file-name-absolute-p(#<buffer *scratch*>)
  (if (file-name-absolute-p filename) (setq filename (concat comint-file-name-prefix filename)))
  (let ((filename (car file)) (spec-directory (if (cdr file) (file-truename (concat comint-file-name-prefix (cdr file)))))) (if (file-name-absolute-p filename) (setq filename (concat comint-file-name-prefix filename))) (unless (memq compilation-parse-errors-filename-function '(nil identity)) (save-match-data (setq filename (funcall compilation-parse-errors-filename-function filename)))) (if (stringp filename) (setq filename (command-line-normalize-file-name filename))) (puthash file (or (gethash (cons filename spec-directory) compilation-locs) (puthash (cons filename spec-directory) (compilation--make-file-struct (list filename spec-directory) fmt) compilation-locs)) compilation-locs))
  (or (gethash file compilation-locs) (let ((filename (car file)) (spec-directory (if (cdr file) (file-truename (concat comint-file-name-prefix (cdr file)))))) (if (file-name-absolute-p filename) (setq filename (concat comint-file-name-prefix filename))) (unless (memq compilation-parse-errors-filename-function '(nil identity)) (save-match-data (setq filename (funcall compilation-parse-errors-filename-function filename)))) (if (stringp filename) (setq filename (command-line-normalize-file-name filename))) (puthash file (or (gethash (cons filename spec-directory) compilation-locs) (puthash (cons filename spec-directory) (compilation--make-file-struct (list filename spec-directory) fmt) compilation-locs)) compilation-locs)))
  compilation-get-file-structure((#<buffer *scratch*>) nil)
  compilation-internal-error-properties((#<buffer *scratch*>) 2 nil nil nil 2 nil)
...

If you patch file-name-absolute-p to accept buffers as well, in fact the whole system works.  This indicates that compile.el does explicitly accept buffers for file, as the docs advertise, but has a couple of small bugs related to parsing such arrangements, since presumably this path is seldom exercised.

E.g.:

(defalias 'orig-file-name-absolute-p
  (symbol-function 'file-name-absolute-p))

(defun my/file-name-absolute-p (file-or-buffer)
  (and (not (bufferp file-or-buffer))
       (funcall #'orig-file-name-absolute-p file-or-buffer)))

(cl-letf (((symbol-function #'file-name-absolute-p)
		 #'my/file-name-absolute-p)) (compilation-parse-errors (point-min) (point-max)))



[-- Attachment #2: Type: text/html, Size: 15668 bytes --]

^ permalink raw reply	[flat|nested] 3+ messages in thread

end of thread, other threads:[~2022-02-13 14:20 UTC | newest]

Thread overview: 3+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2022-02-01  4:07 compile.el error properties: buffer as filename not working JD Smith
2022-02-12 22:42 ` Stefan Monnier
2022-02-13 14:20   ` JD Smith

Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).