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?

1 Answer 1

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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.