On Jun 22, 2023, at 10:58 AM, Daniel Martín <mardani29@yahoo.es> wrote:

Dave Abrahams <dave@boostpro.com> writes:

Swift is a programming language.  When its assertions (like C's
assert() macro) fail, a diagnostic is output with a file ID and
line. The file ID looks like a path, but it's really not. If it's a
path in the filesystem, that's coincidental but it's likely to point
to the right file.  I don't want to manually hunt down the file every
time an assertion fails; I'd rather emacs made an educated guess based
on the current project.  It's obviously not the right answer for
everyone, but I'd like to have the hooks needed to implement that
without too much hackery.

This is the Elisp code you posted on GitHub, based on customizing
compilation-parse-errors-filename-function:

(defun dwa/path-tails-matching (path paths)
 "Returns the elements of PATHS with PATH as their suffix, matching by path component."
 (let ((tail (file-name-concat "/" path)))
   (seq-filter (lambda (full-path) (string-suffix-p tail full-path)) paths)))

(defun dwa/compilation-parse-errors-filename-in-project (path-in-error)
 "If PATH-IN-ERROR is found in the filesystem, returns it
unchanged; otherwise tries to return a unique file in the current
project likely to be identified by PATH-IN-ERROR.  Returns
PATH-IN-ERROR unchanged if no such file can be found."
 (if (file-exists-p path-in-error) path-in-error
   ;; First look for relative path suffixes.
   (let* ((candidates (project-files (project-current t)))
   (full-matches (dwa/path-tails-matching path-in-error candidates)))

     ;; If not found, try just the filename component of
     ;; path-in-error; Swift assertions are weird and include a
     ;; module name that doesn't necessarily correspond to anything in the
     ;; filesystem.
     (cond ((null full-matches)
     (let ((filename-matches
   (dwa/path-tails-matching (file-name-nondirectory path-in-error) candidates)))
       (cond ((null filename-matches) path-in-error)
     ;; unique match; return it
     ((null (cadr filename-matches)) (car filename-matches))
     ;; multiple matches; consider prompting for the user to select one.
     (t path-in-error))))
    ;; unique match; return it
    ((null (cadr matches)) (car matches))
     ; multiple matches; consider prompting for the user to select one.
    (t path-in-error)))))

(setq compilation-parse-errors-filename-function 'dwa/compilation-parse-errors-filename-in-project)

I've tried it and it seems to work well, although I agree that the code
is a bit hacky and prone to error.  How would the new hooks you propose
simplify this customization code?

It would not.  The problem with this code is that it runs too early.  That means two things:

1. if you get 1000 errors in different files, this code will try to resolve each one, accessing the filesystem during parsing, before the compilation buffer even font locks, which is really inefficient especially if you only care about the first of these errors.
2. There's no good way to prompt the user for a match when there are multiple matches.
 
I want a hook that will be run at the time compile.el currently prompts me to locate the file in the filesystem: the first time I visit an error at a given path and no file is found there by emacs.

Similar use cases have been discussed in the mailing list in the past.
Someone proposed to make compilation-find-file customizable, which may
not be a bad idea.  See
https://lists.gnu.org/archive/html/emacs-devel/2021-04/msg00910.html

Yes, I think I could probably get where I need to by advising compilation-find-file.