From 457ece728fb9ec8b3a7964af8c219f6846b196a9 Mon Sep 17 00:00:00 2001 From: "Matthew \"strager\" Glazar" Date: Tue, 24 Oct 2023 20:01:28 -0400 Subject: [PATCH] fix(emacs): clear diagnostics properly in Flymake When our Flymake code set diagnostics, it set them for the whole buffer with :range. However, the :range was incorrect; the begin/end points given were for the *stdout* temporary buffer, not for the user's code buffer. This meant that Flymake diagnostics markers were often not removed because they were not inside the range. (stdout is often much smaller than the JavaScript source being linted.) Fix this by using :range with points derived from the correct buffer. --- docs/CHANGELOG.md | 2 ++ plugin/emacs/flymake-quicklintjs.el | 13 +++++++------ plugin/emacs/test/quicklintjs-test.el | 24 ++++++++++++++++++++++++ 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md index d4e10ea55e..8575115fbd 100644 --- a/docs/CHANGELOG.md +++ b/docs/CHANGELOG.md @@ -50,6 +50,8 @@ Semantic Versioning. in the head of a `for` loop. For example, quick-lint-js no longer warns about `let x; for (let x = 0;;);`. * Emacs: .el files are now installed in the correct place on Arch Linux, btw. +* Emacs: The Flymake plugin now reliably clears out diagnostics after issues are + fixed. Sticky diagnostics are no more. * TypeScript support (still experimental): * A newline after `public`, `protected`, `private`, or `readonly` inside a class is now interpreted correctly. diff --git a/plugin/emacs/flymake-quicklintjs.el b/plugin/emacs/flymake-quicklintjs.el index d29d46a624..a007925f9b 100644 --- a/plugin/emacs/flymake-quicklintjs.el +++ b/plugin/emacs/flymake-quicklintjs.el @@ -96,12 +96,13 @@ REPORT-FN is Flymake's callback." (point-min) (point-max)))) (if (not (string-empty-p stderr-data)) (flymake-log :warning "%S" stderr-data)))) - (with-current-buffer stdout-buf - (let ((diags (flymake-quicklintjs--make-diagnostics - src-buf - (car (read-from-string - (buffer-substring-no-properties - (point-min) (point-max))))))) + (let ((diags (flymake-quicklintjs--make-diagnostics + src-buf + (car (read-from-string + (with-current-buffer stdout-buf + (buffer-substring-no-properties + (point-min) (point-max)))))))) + (with-current-buffer src-buf (if (or diags (zerop (process-exit-status p))) (funcall report-fn diags :region (cons (point-min) (point-max))) diff --git a/plugin/emacs/test/quicklintjs-test.el b/plugin/emacs/test/quicklintjs-test.el index 5bd1cfaf83..cbdc597432 100644 --- a/plugin/emacs/test/quicklintjs-test.el +++ b/plugin/emacs/test/quicklintjs-test.el @@ -110,6 +110,30 @@ foobar\")((16 . 22) 2 \"E0057\" \"use of undeclared variable: foobar\")(\ (ert-fail "Test timed out waiting for diagnostics.")) ;; TODO(strager): Assert specific diagnostics (while (not (flymake-diagnostics)) + (accept-process-output nil 0.01))))) + + ;; This is a regression test. Buffers were mixed up causing + ;; diagnostics after a certain point (usually a few bytes in) to not + ;; be cleared. + (ert-deftest quicklintjs-flymake-fixing-error-clears-diagnostics () + (with-temp-buffer + (javascript-mode) + (insert "/*xxx*/ consol") + (flymake-mode 1) + (add-hook 'flymake-diagnostic-functions #'flymake-quicklintjs nil t) + (flymake-start) + + (with-timeout (5 + (ert-fail "Test timed out waiting for diagnostics.")) + (while (not (flymake-diagnostics)) + (accept-process-output nil 0.01))) + + (insert "e") ;; Buffer content: /*xxx*/ console + (flymake-start) + + (with-timeout (5 + (ert-fail "Test timed out waiting for diagnostics to be removed.")) + (while (flymake-diagnostics) (accept-process-output nil 0.01)))))) (defun def-eglot-tests ()