@@ -40,47 +40,89 @@ Return a list of Flymake diagnostic objects in source buffer SRC-BUF."
4040 (if (= sev 0 ) :error :warning ) msg)))
4141 quicklintjs-output-alist))
4242
43+ (defun flymake-quicklintjs--report-with-crash (qljs-stdout-buf
44+ qljs-stderr-buf
45+ src-buf report-fn )
46+ " Similar to `flymake-quicklintjs--report' but tries to recover errors from
47+ quick-lint-js crashes and logs whatever is in QLJS-STDERR-BUF"
48+ (flymake-log :warning
49+ " quick-lint-js exited with a deadly signal.\n \
50+ Please consider filing a bug at\
51+ https://github.com/quick-lint/quick-lint-js/issues/new\n \
52+ qjls-stderr-buf:\n \
53+ %s\n "
54+ (with-current-buffer qljs-stderr-buf
55+ (buffer-substring-no-properties (point-min ) (point-max ))))
56+ (with-current-buffer qljs-stdout-buf
57+ (save-excursion
58+ ; ; a crash without any previous issue, try to fix an empty buffer
59+ (when (zerop (buffer-size ))
60+ (goto-char (point-min ))
61+ (insert-char ?\( ))
62+ ; ; the above left a '(' dangling or quick-lint-js crashed and
63+ ; ; emacs_lisp_error_reporter::finish() haven't been called yet
64+ (goto-char (point-min ))
65+ (when (eq (char-after 1 ) ?\( )
66+ (goto-char (point-max ))
67+ (insert-char ?\) ))))
68+ (condition-case nil
69+ (flymake-quicklintjs--report qljs-stdout-buf src-buf report-fn)
70+ (funcall report-fn '())))
71+
72+ (defun flymake-quicklintjs--report (qljs-stdout-buf src-buf report-fn )
73+ " Call REPORT-FN to highlight reports in SRC_BUF reported in QLJS-STDOUT-BUF.
74+ QLJS-STDOUT-BUF is entirely read and it's expected to be in
75+ QUICKLINTJS-OUTPUT-ALIST format."
76+ (with-current-buffer qljs-stdout-buf
77+ (funcall report-fn
78+ (flymake-quicklintjs--make-diagnostics
79+ src-buf
80+ (car (read-from-string
81+ (buffer-substring-no-properties (point-min )
82+ (point-max ))))))))
83+
4384;;;### autoload
4485(defun flymake-quicklintjs (report-fn &rest _args )
4586 " Flymake backend for quick-lint-js linter.
46- This backend uses `flymake- quicklintjs-program' (which see) to launch a
47- quick-lint-js process that is passed the current buffer's contents via stdin.
87+ This backend uses `quicklintjs-find- program' to find and launch a quick-lint-js
88+ process that is passed the current buffer's contents via stdin.
4889REPORT-FN is Flymake's callback."
4990 (when (process-live-p flymake-quicklintjs--proc)
5091 (kill-process flymake-quicklintjs--proc))
51- (let ((src-buf (current-buffer )))
52- (setq flymake-quicklintjs--proc
53- (make-process
54- :name " flymake-quicklintjs"
55- :connection-type 'pipe
56- :noquery t
57- :buffer (get-buffer-create " *flymake-quicklintjs*" )
58- :command (quicklintjs-find-program
59- (let ((file (buffer-file-name )))
60- (when file (concat " --path-for-config-search=" file)))
61- " --stdin" " --output-format=emacs-lisp" )
62- :sentinel
63- (lambda (p _ev )
64- (unwind-protect
65- (when (and (eq 'exit (process-status p))
66- (eq p flymake-quicklintjs--proc))
67- (with-current-buffer (process-buffer p)
68- (let ((diags (flymake-quicklintjs--make-diagnostics
69- src-buf
70- (car (read-from-string
71- (buffer-substring-no-properties
72- (point-min ) (point-max )))))))
73- (if (or diags (zerop (process-exit-status p)))
74- (funcall report-fn diags)
75- (funcall report-fn
76- :panic :explanation
77- (buffer-substring
78- (point-min ) (progn (goto-char (point-min ))
79- (line-end-position ))))))))
80- (unless (process-live-p p)
81- (kill-buffer (process-buffer p)))))))
82- (process-send-region flymake-quicklintjs--proc (point-min ) (point-max ))
83- (process-send-eof flymake-quicklintjs--proc)))
92+ (let ((src-buf (current-buffer ))
93+ (stdout-buf (generate-new-buffer " *flymake-quicklintjs-stdout*" ))
94+ (stderr-buf (generate-new-buffer " *flymake-quicklintjs-stderr*" )))
95+ (save-restriction
96+ (widen )
97+ (setq flymake-quicklintjs--proc
98+ (make-process
99+ :name " flymake-quicklintjs"
100+ :connection-type 'pipe
101+ :noquery t
102+ :buffer stdout-buf
103+ :stderr stderr-buf
104+ :command (quicklintjs-find-program
105+ (let ((file (buffer-file-name )))
106+ (when file (concat " --path-for-config-search=" file)))
107+ " --stdin" " --output-format=emacs-lisp" )
108+ :sentinel
109+ (lambda (p _ev )
110+ (let ((proc-status (process-status p)))
111+ (unwind-protect
112+ (when (and (or (eq proc-status 'exit )
113+ (eq proc-status 'signal ))
114+ (with-current-buffer src-buf
115+ (eq p flymake-quicklintjs--proc)))
116+ (if (zerop (process-exit-status p))
117+ (flymake-quicklintjs--report stdout-buf
118+ src-buf
119+ report-fn)
120+ (flymake-quicklintjs--report-with-crash
121+ stdout-buf stderr-buf src-buf report-fn)))
122+ (progn (kill-buffer stdout-buf)
123+ (kill-buffer stderr-buf)))))))
124+ (process-send-region flymake-quicklintjs--proc (point-min ) (point-max ))
125+ (process-send-eof flymake-quicklintjs--proc))))
84126
85127(provide 'flymake-quicklintjs )
86128
0 commit comments