Fix flycheck + eglot integration.

This commit is contained in:
kj 2022-11-19 14:53:04 -04:00
parent 017566a9dd
commit d683d3cbf7
1 changed files with 99 additions and 9 deletions

View File

@ -15,27 +15,117 @@
:config
(add-to-list 'eglot-server-programs '(php-mode . ("intelephense" "--stdio")))
;; Integrate flycheck and eglot (code from doomemacs)
(cl-defstruct (flycheck-error
(:constructor flycheck-error-new)
(:constructor flycheck-error-new-at
(line column
&optional level message
&key checker id group beg-pos end-pos end-line end-column
(filename (buffer-file-name))
(buffer (current-buffer)))))
"Structure representing an error reported by a syntax checker.
Slots:
`buffer'
The buffer that the error was reported for, as buffer object.
`checker'
The syntax checker which reported this error, as symbol.
`filename'
The file name the error refers to, as string.
`line'
The line number the error refers to, as number.
`column' (optional)
The column number the error refers to, as number.
For compatibility with external tools and unlike Emacs
itself (e.g. in Compile Mode) Flycheck uses _1-based_
columns: The first character on a line is column 1.
Occasionally some tools try to proactively adapt to Emacs
and emit 0-based columns automatically. In these cases, the
columns must be adjusted for Flycheck, see
`flycheck-increment-error-columns'.
`beg-pos' (optional)
The begining position of the error, if provided by the checker.
`end-pos' (optional)
The end position of the error, if provided by the checker.
`end-line' (optional)
The end line of the error, if provided by the checker.
`end-column' (optional)
The end column of the error, if provided by the checker.
`message' (optional)
The error message as a string, if any.
`level'
The error level, as either `info', `warning' or `error'.
`id' (optional)
An ID identifying the kind of error.
`group` (optional)
A symbol identifying the group the error belongs to.
Some tools will emit multiple errors that relate to the same
issue (e.g., lifetime errors in Rust). All related errors
collected by a checker should have the same `group` value,
in order to be able to present them to the user.
See `flycheck-related-errors`."
buffer checker filename line column message level id group beg-pos end-pos end-line end-column)
(defun flycheck-error-thing-region (thing err)
"Get the region of THING at the column of ERR.
ERR is a Flycheck error whose region to get. THING is a
understood by `thing-at-point'.
If the error has beg-pos and end-pos in it, use them. Otherwise,
return a cons cell `(BEG . END)' where BEG is the beginning of
the THING at the error column, and END the end of the symbol. If
ERR has no error column, or if there is no THING at this column,
return nil."
(-when-let (column (car (flycheck-error-column-region err)))
(flycheck-error-with-buffer err
(save-excursion
(save-restriction
(widen)
(goto-char column)
(or
(and (flycheck-error-end-pos err)
(flycheck-error-beg-pos err)
(cons (flycheck-error-beg-pos err)
(flycheck-error-end-pos err)))
(bounds-of-thing-at-point thing)))))))
(defvar-local flycheck-eglot-current-errors nil)
;; Use flycheck (https://gist.github.com/purcell/ca33abbea9a98bb0f8a04d790a0cadcd)
(defun flycheck-position-to-line-column (point)
"Return a (LINE . COLUMN) cons corresponding to POINT."
(let ((inhibit-field-text-motion t))
(save-excursion
(goto-char point)
(cons (line-number-at-pos) (1+ (- (point) (line-beginning-position)))))))
(defun flycheck-eglot-report-fn (diags &rest _)
"Convert flymake eglot errors to flycheck errors.
DIAGS are the diags that flymake provided."
(setq flycheck-eglot-current-errors
(mapcar (lambda (diag)
(save-excursion
(goto-char (flymake--diag-beg diag))
(flycheck-error-new-at (line-number-at-pos)
(1+ (- (point) (line-beginning-position)))
(flycheck-error-new-at (line-number-at-pos) ;; will be ignored
(1+ (current-column)) ;; will be ignored
(pcase (flymake--diag-type diag)
('eglot-error 'error)
('eglot-warning 'warning)
('eglot-note 'info)
(_ (error "Unknown diag type, %S" diag)))
(flymake--diag-text diag)
:checker 'eglot)))
:checker 'eglot
:end-line (car (flycheck-position-to-line-column (flymake--diag-end diag)))
:end-column (cdr (flycheck-position-to-line-column (flymake--diag-end diag)))
:beg-pos (copy-marker (flymake--diag-beg diag) t)
:end-pos (copy-marker (flymake--diag-end diag)))))
diags))
(flycheck-buffer))
(defun flycheck-eglot--start (checker callback)
"Clean up errors when done.
CHECKER is the checker, which is unused because we know that it
is eglot. CALLBACK is the function that we need to call when we
are done, on all the errors."
(funcall callback 'finished flycheck-eglot-current-errors))
(defun flycheck-eglot--available-p ()
@ -49,16 +139,16 @@
(push 'eglot flycheck-checkers)
(defun sanityinc/eglot-prefer-flycheck ()
(defun +doom/eglot-prefer-flycheck-h ()
(when eglot--managed-mode
(when-let ((current-checker (flycheck-get-checker-for-buffer)))
(flycheck-add-next-checker 'eglot current-checker))
(flycheck-add-mode 'eglot major-mode)
(flycheck-select-checker 'eglot)
(flycheck-mode)
(flycheck-mode 1)
(flymake-mode -1)
(setq eglot--current-flymake-report-fn 'flycheck-eglot-report-fn)))
(add-hook 'eglot--managed-mode-hook 'sanityinc/eglot-prefer-flycheck)
)
(add-hook 'eglot--managed-mode-hook #'+doom/eglot-prefer-flycheck-h))
;; Emmet (mientras veo como hacer funcionar emmet-ls)
(use-package emmet-mode