-
Notifications
You must be signed in to change notification settings - Fork 200
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
WIP: pcase macro #156
WIP: pcase macro #156
Conversation
@joaotavora So is this the right approach? Do we want to always allow other keys? I believe that we should - accept all but use the minimum required. You mentioned here that we could add |
We want to allow-other-keys sometimes right? We want to decide that at runtime, if possible (or, if it's very slow, at compile-time). Hiding it in a macro such as the one you wrote it's trivial to implement. Regarding the But in a very first version, it's OK for users of the |
A new variable, eglot-strict-mode controls whether Eglot is strict or lax with regard to incoming LSP messages. 1. Bug reports should be tested with eglot-strict-mode set to '(disallow-non-standard-keys enforce-required-keys) 2. Users struggling to get non-standard servers working set this variable to '(), nil. For now, by popular demand, this is the default value. Note that this commit in particular introduces a new infrastructure, but does not yet alter any code in Eglot to use it. Neither is the variable eglot--lsp-interface-alist populated. * eglot-tests.el (eglot-strict-interfaces): New test. * eglot.el (eglot--lsp-interface-alist): New variable. (eglot-strict-mode): New variable. (eglot--call-with-interface): New helper. (eglot--dbind): New macro. (eglot--lambda): New macro.
@mkcms I've pushed a commit that doesn't yet solve the problem but implements some of my ideas. You can try out the new macros for yourself and start using them instead of In the future, we might want to add more macros on top of those, a "destructuring case" comes to mind. This should hopefully make it easier to track back to the spec from the lisp code in eglot. |
@joaotavora I also wrote some of those macros for fun. I didn't really pay attention to performance or readability though, they're just a proof-of-concept. Also, options to control strict checking aren't implemented yet. With (pcase-defmacro lsp--Object (fields)
`(and (pred listp) it
,@(mapcar (lambda (field) `(guard (plist-member it ,field)))
(butlast fields))
,@(mapcar (lambda (field)
`(let ,field
(plist-get it ,(intern (format ":%s" field)))))
(car (last fields)))))
(pcase-defmacro lsp-TextEdit (symbols)
`(lsp--Object (:range :newText ,symbols)))
(pcase-defmacro lsp-WorkspaceEdit (symbols)
`(lsp--Object (:changes :documentChanges ,symbols)))
;; Example
(let ((response '(:range (:start (:character 1 :line 1)
:end (:character 2 :line 1))
:newText "x")))
(pcase response
((lsp-WorkspaceEdit (changes documentChanges))
(format "WorkspaceEdit with changes %S" changes))
((lsp-TextEdit (newText range))
(format "TextEdit with text %S" newText)))) And a custom macro: (defmacro eglot--dbind (exp &rest clauses)
(declare (indent 1) (debug (form &rest (sexp sexp body))))
(let ((expval (make-symbol "eglot--dbind-expval")))
`(let ((,expval ,exp))
(cond ,@(mapcar (pcase-lambda (`(,type ,args . ,body))
(cond ((eq type 'string)
`((stringp ,expval) (let ((,args ,expval)) ,@body)))
(t
`((cl-every (apply-partially #'plist-member ,expval)
(get ',type 'eglot--destructuring))
(cl-destructuring-bind (&key ,@args) ,expval
,@body)))))
clauses)
(t (error "No match"))))))
(put 'TextEdit 'eglot--destructuring '(:range :newText))
(put 'WorkspaceEdit 'eglot--destructuring '(:changes :documentChanges))
(eglot--dbind (list :range '(:start (:line 1 :character 1)
(:end (:line 1 :character 5)))
:newText "asdf")
(string x (message "got a string %s" x))
(WorkspaceEdit (changes documentChanges)
(message "got WorkspaceEdit with changes %s" changes))
(TextEdit (range newText)
(message "got TextEdit with newText %s" newText))) |
This is precisely what the
These look very good. Perhaps they can substitute my versions, since their API seems to be similar. But I don't have time now to review them now. Anyway, to fix #144 in the short-term, I think it won't be wasted effort to replace most |
The |
I will try to implement that. |
@joaotavora |
For now, I brought back the old |
~This is better some in a separate branch, by the way...~ nevermind this is a separate branch
…On Sun, Nov 25, 2018, 00:33 mkcms ***@***.*** wrote:
For now, I brought back the old eglot--dbind and
eglot--call-with-interface, because I realised I broke the old behavior.
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#156 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/AAXnw4TTMBBAXePBshX98cby6haG31g1ks5uyeU8gaJpZM4YoDC_>
.
|
@joaotavora @mkcms Is there still interest in this? I wrote something similar in |
@leungbk Given the lack of reply in 6 months, I think it's fair to say that any work you would want to do here is very welcome. Just open a new PR with your changes. Thanks in advance! |
…wards incoming LSP messages A new variable, eglot-strict-mode controls whether Eglot is strict or lax with regard to incoming LSP messages. 1. Bug reports should be tested with eglot-strict-mode set to '(disallow-non-standard-keys enforce-required-keys) 2. Users struggling to get non-standard servers working set this variable to '(), nil. For now, by popular demand, this is the default value. Note that this commit in particular introduces a new infrastructure, but does not yet alter any code in Eglot to use it. Neither is the variable eglot--lsp-interface-alist populated. * eglot-tests.el (eglot-strict-interfaces): New test. * eglot.el (eglot--lsp-interface-alist): New variable. (eglot-strict-mode): New variable. (eglot--call-with-interface): New helper. (eglot--dbind): New macro. (eglot--lambda): New macro.
…wards incoming LSP messages A new variable, eglot-strict-mode controls whether Eglot is strict or lax with regard to incoming LSP messages. 1. Bug reports should be tested with eglot-strict-mode set to '(disallow-non-standard-keys enforce-required-keys) 2. Users struggling to get non-standard servers working set this variable to '(), nil. For now, by popular demand, this is the default value. Note that this commit in particular introduces a new infrastructure, but does not yet alter any code in Eglot to use it. Neither is the variable eglot--lsp-interface-alist populated. * eglot-tests.el (eglot-strict-interfaces): New test. * eglot.el (eglot--lsp-interface-alist): New variable. (eglot-strict-mode): New variable. (eglot--call-with-interface): New helper. (eglot--dbind): New macro. (eglot--lambda): New macro.
A new variable, eglot-strict-mode controls whether Eglot is strict or lax with regard to incoming LSP messages. 1. Bug reports should be tested with eglot-strict-mode set to '(disallow-non-standard-keys enforce-required-keys) 2. Users struggling to get non-standard servers working set this variable to '(), nil. For now, by popular demand, this is the default value. Note that this commit in particular introduces a new infrastructure, but does not yet alter any code in Eglot to use it. Neither is the variable eglot--lsp-interface-alist populated. * eglot-tests.el (eglot-strict-interfaces): New test. * eglot.el (eglot--lsp-interface-alist): New variable. (eglot-strict-mode): New variable. (eglot--call-with-interface): New helper. (eglot--dbind): New macro. (eglot--lambda): New macro. #144: joaotavora/eglot#144 #156: joaotavora/eglot#156
* eglot.el (eglot--dcase): New macro. * eglot-tests.el (eglot-dcase-with-interface) (eglot-dcase-no-interface): New tests. #171: joaotavora/eglot#171 ,#156: joaotavora/eglot#156
A new variable, eglot-strict-mode controls whether Eglot is strict or lax with regard to incoming LSP messages. 1. Bug reports should be tested with eglot-strict-mode set to '(disallow-non-standard-keys enforce-required-keys) 2. Users struggling to get non-standard servers working set this variable to '(), nil. For now, by popular demand, this is the default value. Note that this commit in particular introduces a new infrastructure, but does not yet alter any code in Eglot to use it. Neither is the variable eglot--lsp-interface-alist populated. * eglot-tests.el (eglot-strict-interfaces): New test. * eglot.el (eglot--lsp-interface-alist): New variable. (eglot-strict-mode): New variable. (eglot--call-with-interface): New helper. (eglot--dbind): New macro. (eglot--lambda): New macro. GitHub-reference: per joaotavora/eglot#144 GitHub-reference: per joaotavora/eglot#156
* eglot.el (eglot--dcase): New macro. * eglot-tests.el (eglot-dcase-with-interface) (eglot-dcase-no-interface): New tests. GitHub-reference: per joaotavora/eglot#171 GitHub-reference: per joaotavora/eglot#156
Previously we were strict about the structure and contents of LSP
objects. This led to errors when certain servers sent messages with
fields not defined in the specification (because those fields are
used by other clients, or the protocol evolved and added some fields
and we never upgraded).
This commit makes eglot tolerate unknown keys in all incoming
messages.
(eglot-handle-notification):
(eglot--register-unregister):
(eglot--xref-make):
(xref-backend-apropos):
(eglot-completion-at-point):
(eglot--sig-info):
(eglot-help-at-point):
(eglot--apply-workspace-edit):
(eglot-code-actions):
(eglot--register-workspace/didChangeWatchedFiles): Use it instead of
cl-destructuring-bind
.