0

I work on a typescript project that I compile with webpack serve, using projectile-run-project. My *compilation buffer shows the webpack output, which includes typescript errors. After some webpack hacking, I managed to get the errors into a compilation mode compatible format. When I select an error (which runs compilation-goto-error on this error), emacs opens the respective file in another buffer and jumps to the correct line. This works well so far.

When I change files, webpack serve immediately recompiles the project, and echos new error messages into *compilation*.

When I now edit a file, emacs seems to memorise error locations at the start of the compilation. Meaning:

  • I start compilation
  • I edit file index.ts to add a new line after line 4
  • webpack reports an error at index.ts:6
  • compile-goto-error goes to index.ts:7

I assume that this happens because compilation mode knows that line 6 in index.ts at the start of the compilation is now at line 7. However, I don't need that memoization, as the compilation reports current (correct) lines. How can I make compilation-goto-error use current lines, not cached onces?

fbuether
  • 1
  • 1

1 Answers1

0

So, as I was just finishing writing my answer I found what I think might be a solution.

I had a look at compile.el, and I found several messages relating to omake -P, which probably has a similar re-compilation behaviour. An entry into compilation-error-regexp-alist-alist omake calls compilation--flush-file-structure for the respective file, so that the memoisation is cleared prior to navigating there:

    (omake
     ;; "omake -P" reports "file foo changed"
     ;; (useful if you do "cvs up" and want to see what has changed)
     "^\\*\\*\\* omake: file \\(.*\\) changed" 1 nil nil nil nil
     ;; FIXME-omake: This tries to prevent reusing pre-existing markers
     ;; for subsequent messages, since those messages's line numbers
     ;; are about another version of the file.
     (0 (progn (compilation--flush-file-structure (match-string 1))
               nil)))

I adopted this for the compilation-error-regexp-alist-alist entries for typescript, using a bit from typescript-mode.el:

;; handle plain compiler-errors like the following when doing M-x compile<ret>tsc<ret>
;;
;; greeter.ts(24,9): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
;; greeter.ts(30,12): error TS2339: Property 'indexOf' does not exist on type 'number'.
(defconst typescript-tsc-error-regexp
  (concat
   "^[[:blank:]]*"
   "\\([^(\r\n)]+\\)(\\([0-9]+\\),\\([0-9]+\\)):[[:blank:]]+"
   "error [[:alnum:]]+: [^\r\n]+$")
  "Regexp to match errors generated by tsc.")

I add the result to compilation-error-regexp-alist-alist, overiding the regular typescript-mode entries:

(dolist
    (regexp
     `((typescript-tsc
        ,typescript-tsc-error-regexp
        1 2 3 2
        ;; for flushing the marker cache of this file
        nil (0 (progn (compilation--flush-file-structure (match-string 1))
                      nil)))
   (typescript-tsc-pretty
    ,typescript-tsc-pretty-error-regexp
    1 2 3 2
    ;; for flushing the marker cache of this file
    nil (0 (progn (compilation--flush-file-structure (match-string 1))
                  nil)))))

(add-to-list 'compilation-error-regexp-alist-alist regexp) (add-to-list 'compilation-error-regexp-alist (car regexp)))

That feels really hackish, but so far seems to work.

fbuether
  • 1
  • 1