]> git.eshelyaron.com Git - emacs.git/commitdiff
Defend against broken move-to-column in recent emacs
authorJoão Távora <joaotavora@gmail.com>
Fri, 18 Mar 2022 10:54:21 +0000 (10:54 +0000)
committerJoão Távora <joaotavora@gmail.com>
Fri, 18 Mar 2022 10:54:48 +0000 (10:54 +0000)
* eglot.el (eglot-lsp-abiding-column): Use (min (point) (point-max))

This is a defensive fix for an Emacs/company-mode problem described
below.

The problem can be reproduced in Eglot before this commit with:

~/Source/Emacs/emacs/src/emacs -Q -f package-initialize -L       \
~/Source/Emacs/company-mode -l company -f global-company-mode -l \
 eglot.el ~/tmp/issue-860/args_out_of_range.c -f eglot -f        \
 display-line-numbers-mode -f toggle-debug-on-error

  1 // args_out_of_range.c
  2 struct Book {
  3   int id;
  4   char title[50]
  5 } book = { 1024, "C" };
  6
  7 int main(int argc, char *argv[])
  8 {
  9
 10   // Error when typing the dot to make "book."
 11   book
 12   return 0;
 13 }

When one types the dot after the "book" on line 11, company-mode
displays a two-line overlay that visually encompasses line 12 after
"book", which has the "return 0;" statement.  That line happens to
also hold a warning about incorrect syntax, one that starts at column
2.

Eglot uses 'move-to-column' to go that precise place.

In Emacs 27.2, move-to-column is unaffected by previous company-mode
overlays, even if the current line is being co-used visually by the
overlay.  It moves to the right buffer position.

In Emacs master, this isn't true.  It seems to be confounded by the
company-mode overlay and moves to eob, which eventually breaks Eglot
with a backtrace such as this one:

Debugger entered--Lisp error: (args-out-of-range #<buffer args_out_of_range.c> 110 124)
  encode-coding-region(110 124 utf-16 t)
  (length (encode-coding-region (or lbp (line-beginning-position)) (point) 'utf-16 t))
  (- (length (encode-coding-region (or lbp (line-beginning-position)) (point) 'utf-16 t)) 2)
  (/ (- (length (encode-coding-region (or lbp (line-beginning-position)) (point) 'utf-16 t)) 2) 2)
  eglot-lsp-abiding-column(110)
  (- column (eglot-lsp-abiding-column lbp))
  (setq diff (- column (eglot-lsp-abiding-column lbp)))
  (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff)))
  (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff))) (condition-case eob-err (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq --cl-var-- nil))
  (let* ((lbp (line-beginning-position)) (diff nil) (--cl-var-- t)) (narrow-to-region lbp (line-end-position)) (move-to-column column) (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff))) (condition-case eob-err (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq --cl-var-- nil)) nil)
  (catch '--cl-block-nil-- (let* ((lbp (line-beginning-position)) (diff nil) (--cl-var-- t)) (narrow-to-region lbp (line-end-position)) (move-to-column column) (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff))) (condition-case eob-err (forward-char (/ (if (> diff 0) (1+ diff) (1- diff)) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq --cl-var-- nil)) nil))
  (save-restriction (catch '--cl-block-nil-- (let* ((lbp (line-beginning-position)) (diff nil) (--cl-var-- t)) (narrow-to-region lbp (line-end-position)) (move-to-column column) (while (progn (setq diff (- column (eglot-lsp-abiding-column lbp))) (not (= 0 diff))) (condition-case eob-err (forward-char (/ (if ... ... ...) 2)) (end-of-buffer (throw '--cl-block-nil-- eob-err))) (setq --cl-var-- nil)) nil)))
  eglot-move-to-lsp-abiding-column(2)

GitHub-reference: fix https://github.com/joaotavora/eglot/issues/860

lisp/progmodes/eglot.el

index ea9299ab59e22062bbfbd0d3e97a40a41b49e6f0..3bd2d844c8a3cd784bcd0bd7e89be37b05c32676 100644 (file)
@@ -1312,7 +1312,8 @@ fully LSP-compliant servers, this should be set to
   "Calculate current COLUMN as defined by the LSP spec.
 LBP defaults to `line-beginning-position'."
   (/ (- (length (encode-coding-region (or lbp (line-beginning-position))
-                                      (point) 'utf-16 t))
+                                      ;; Fix github#860
+                                      (min (point) (point-max)) 'utf-16 t))
         2)
      2))