joaotavora / eglot

A client for Language Server Protocol servers
GNU General Public License v3.0
2.21k stars 203 forks source link

Error fontifying hover info from Pyright when using `python-ts-mode` #1355

Closed d125q closed 5 months ago

d125q commented 5 months ago
  1. Ensure that python-ts-mode is configured
  2. Ensure that pyright is installed and eglot configured to use it for python-ts-mode
  3. Ensure that eglot-prefer-plaintext is nil
  4. Open a Python buffer, start Eglot, and type a simple assignment such as foo = 1
  5. Hover over foo
  6. Observe an error
Debugger entered--Lisp error: (treesit-query-error "Node type error at" 1978 "((identifier) @font-lock-type-face (#match \"\\\\(?:^\\\\(?:A\\\\(?:\\\\(?:rithmetic\\\\|ssertion\\\\|ttribute\\\\)Error\\\\)\\\\|B\\\\(?:aseException\\\\|lockingIOError\\\\|rokenPipeError\\\\|ufferError\\\\|ytesWarning\\\\)\\\\|C\\\\(?:\\\\(?:hildProcess\\\\|onnection\\\\(?:Aborted\\\\|Re\\\\(?:fused\\\\|set\\\\)\\\\)?\\\\)Error\\\\)\\\\|DeprecationWarning\\\\|E\\\\(?:OFError\\\\|nvironmentError\\\\|xception\\\\)\\\\|F\\\\(?:ile\\\\(?:\\\\(?:Exists\\\\|NotFound\\\\)Error\\\\)\\\\|loatingPointError\\\\|utureWarning\\\\)\\\\|GeneratorExit\\\\|I\\\\(?:OError\\\\|mport\\\\(?:Error\\\\|Warning\\\\)\\\\|\\\\(?:n\\\\(?:de\\\\(?:ntation\\\\|x\\\\)\\\\|terrupted\\\\)\\\\|sADirectory\\\\)Error\\\\)\\\\|Key\\\\(?:Error\\\\|boardInterrupt\\\\)\\\\|LookupError\\\\|MemoryError\\\\|N\\\\(?:\\\\(?:ame\\\\|ot\\\\(?:ADirectory\\\\|Implemented\\\\)\\\\)Error\\\\)\\\\|O\\\\(?:\\\\(?:S\\\\|verflow\\\\)Error\\\\)\\\\|P\\\\(?:e\\\\(?:ndingDeprecationWarning\\\\|rmissionError\\\\)\\\\|rocessLookupError\\\\)\\\\|R\\\\(?:e\\\\(?:cursionError\\\\|ferenceError\\\\|sourceWarning\\\\)\\\\|untime\\\\(?:Error\\\\|Warning\\\\)\\\\)\\\\|S\\\\(?:t\\\\(?:andardError\\\\|op\\\\(?:\\\\(?:Async\\\\)?Iteration\\\\)\\\\)\\\\|y\\\\(?:ntax\\\\(?:Error\\\\|Warning\\\\)\\\\|stemE\\\\(?:rror\\\\|xit\\\\)\\\\)\\\\)\\\\|T\\\\(?:\\\\(?:ab\\\\|imeout\\\\|ype\\\\)Error\\\\)\\\\|U\\\\(?:n\\\\(?:boundLocalError\\\\|icode\\\\(?:DecodeError\\\\|E\\\\(?:\\\\(?:ncodeE\\\\)?rror\\\\)\\\\|TranslateError\\\\|Warning\\\\)\\\\)\\\\|serWarning\\\\)\\\\|V\\\\(?:\\\\(?:MS\\\\|alue\\\\)Error\\\\)\\\\|W\\\\(?:arning\\\\|indowsError\\\\)\\\\|ZeroDivisionError\\\\)$\\\\)\" @font-lock-type-face)) (type [(identifier) (none)] @font-lock-type-face) (type (attribute attribute: (identifier) @font-lock-type-face)) (type (_ !attribute [[(identifier) (none)] @font-lock-type-face (attribute attribute: (identifier) @font-lock-type-face)])) (type (subscript (attribute attribute: (identifier) @font-lock-type-face))) (type (binary_operator) @python--treesit-fontify-union-types) (class_definition superclasses: (argument_list [(identifier) @font-lock-type-face (attribute attribute: (identifier) @font-lock-type-face) (subscript (identifier) @font-lock-type-face) (subscript (attribute attribute: (identifier) @font-lock-type-face))])) (class_pattern (dotted_name (identifier) @font-lock-type-face .)) ((call function: (identifier) @func-name (argument_list . (_) [(identifier) @font-lock-type-face (attribute attribute: (identifier) @font-lock-type-face) (tuple (identifier) @font-lock-type-face) (tuple (attribute attribute: (identifier) @font-lock-type-face))] (#match \"\\\\(?:^\\\\(?:int\\\\|float\\\\|complex\\\\|bool\\\\|list\\\\|tuple\\\\|range\\\\|str\\\\|bytes\\\\|bytearray\\\\|memoryview\\\\|set\\\\|frozenset\\\\|dict\\\\|_?[A-Z][0-9A-Z_a-z]+\\\\)$\\\\)\" @font-lock-type-face))) (#match \"^is\\\\(?:instance\\\\|subclass\\\\)$\" @func-name)) ((call function: (identifier) @func-name (argument_list . (_) (binary_operator) @python--treesit-fontify-union-types-strict)) (#match \"^is\\\\(?:instance\\\\|subclass\\\\)$\" @func-name))" "Debug the query with `treesit-query-validate'")
  treesit--font-lock-fontify-region-1(#<treesit-node module in 1-29> #<treesit-compiled-query> 1 29 t nil)
  treesit-font-lock-fontify-region(1 29 nil)
  font-lock-fontify-syntactically-region(1 29 nil)
  font-lock-default-fontify-region(1 29 nil)
  font-lock-fontify-region(1 29)
  #f(compiled-function (beg end) #<bytecode 0x74f363be2918d7c>)(1 29)
  font-lock-ensure()
  markdown-fontify-code-block-natively("python" 11 38)
  markdown-fontify-code-blocks-generic(markdown-match-gfm-code-blocks 41)
  markdown-fontify-gfm-code-blocks(41)
  font-lock-fontify-keywords-region(1 41 nil)
  font-lock-default-fontify-region(1 41 nil)
  font-lock-fontify-region(1 41)
  #f(compiled-function (beg end) #<bytecode 0x74f363be2918d7c>)(1 41)
  font-lock-ensure()
  eglot--format-markup((:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```"))
  eglot--hover-info((:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") (:start (:line 0 :character 0) :end (:line 0 :character 3)))
  #f(compiled-function (jsonrpc-lambda-elem13) #<bytecode 0xaff343647a291b7>)((:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3))))
  jsonrpc--continue(#<eglot-lsp-server eglot-lsp-server-1802eee63f61> 2 (2 :textDocument/hover #f(compiled-function (jsonrpc-lambda-elem13) #<bytecode 0xaff343647a291b7>) #f(compiled-function (jsonrpc-lambda-elem3) #<bytecode -0x16a9060a7b992f8f>) [nil 26035 44589 20890 nil #f(compiled-function () #<bytecode 0x1e305b5262c789c8>) nil nil 0 nil]) (:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3))) nil)
  jsonrpc-connection-receive(#<eglot-lsp-server eglot-lsp-server-1802eee63f61> (:jsonrpc "2.0" :id 2 :result (:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3)))))
  #f(compiled-function (m) #<bytecode 0x2c24de43e7ef0cf>)((:jsonrpc "2.0" :id 2 :result (:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3)))))
  apply(#f(compiled-function (m) #<bytecode 0x2c24de43e7ef0cf>) (:jsonrpc "2.0" :id 2 :result (:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3)))))
  timer-event-handler([t 26035 44579 48874 nil #f(compiled-function (m) #<bytecode 0x2c24de43e7ef0cf>) ((:jsonrpc "2.0" :id 2 :result (:contents (:kind "markdown" :value "```python\n(variable) foo: Literal[1]\n```") :range (:start (:line 0 :character 0) :end (:line 0 :character 3))))) nil 0 nil])

As you can see from the backtrace, Pyright replied with

```python
(variable) foo: Literal[1]
which then resulted in an attempt to fontify

(variable) foo: Literal[1]


as Python code.  Since this is invalid Python code due to the `(variable) ` prefix, `python-ts-mode` errored out.

Pyright seems to add these prefixes everywhere; e.g., when one hovers over `print`, Pyright replies with `(function) def print(...)`.

Should Eglot try to strip these prefixes?  Should it ignore fontification errors in [`eglot--format-markup`](https://github.com/joaotavora/eglot/blob/db91d58374627a195b731a61bead9b4f84a7e4bc/eglot.el#L1800)?

In the meantime, a workaround is to set `eglot-prefer-plaintext` to `t`.
joaotavora commented 5 months ago

Should pyright be forked by someone who actually cares about editors other than VS code?

joaotavora commented 5 months ago

Should it ignore fontification errors in eglot--format-markup?

Yes, I'll do that later. There's already an Emacs bugs for it