With the resolution of #187 and the related issues with JEDI we are left with no reliable way to get syntax errors published. I suggest the replacement of that functionality with the use of the compile function.
def _publish_diagnostics(server: JediLanguageServer, uri: str) -> None:
"""Helper function to publish diagnostics for a file."""
# since this function is executed with a delay we need to check
# whether the document still exists
if not (uri in server.workspace.documents):
return
doc = server.workspace.get_document(uri)
diagnostic = jedi_utils.lsp_python_diagnostic(uri, doc.source)
diagnostics = [diagnostic] if diagnostic else []
server.publish_diagnostics(uri, diagnostics)
This is all that it takes. It is reliable and probably faster than using jedi. The only downside is that it provides just the first error even when there are many. Still quite useful.
Further refinement
The idea and the following quite remarkable decorator function are borrowed from python_lsp_server.
Add to jedi_utils:
import functools
import threading
import inspect
def debounce(interval_s, keyed_by=None):
"""Debounce calls to this function until interval_s seconds have passed."""
def wrapper(func):
timers = {}
lock = threading.Lock()
@functools.wraps(func)
def debounced(*args, **kwargs):
sig = inspect.signature(func)
call_args = sig.bind(*args, **kwargs)
key = call_args.arguments[keyed_by] if keyed_by else None
def run():
with lock:
del timers[key]
return func(*args, **kwargs)
with lock:
old_timer = timers.get(key)
if old_timer:
old_timer.cancel()
timer = threading.Timer(interval_s, run)
timers[key] = timer
timer.start()
return debounced
return wrapper
In server.py decorate _publish_diagnostics
@jedi_utils.debounce(1, keyed_by='uri')
def _publish_diagnostics(server: JediLanguageServer, uri: str) -> None:
"""Helper function to publish diagnostics for a file."""
# the debounce decorator delays the execution by 1 second
# canceling notifications that happen in that interval
# since this function is executed with a delay we need to check
# whether the document still exists
if not (uri in server.workspace.documents):
return
doc = server.workspace.get_document(uri)
diagnostic = jedi_utils.lsp_python_diagnostic(uri, doc.source)
diagnostics = [diagnostic] if diagnostic else []
server.publish_diagnostics(uri, diagnostics)
So, for example, if the user types fast, instead of sending multiple publishDiagnostics notifications only one will be send with a bit of delay. Each new one will cancel the previous one if it has not already been executed.
Proposal
With the resolution of #187 and the related issues with JEDI we are left with no reliable way to get syntax errors published. I suggest the replacement of that functionality with the use of the compile function.
Suggested changes:
Add to jedi_utils:
Change _publish_diagnostics in server.py to:
This is all that it takes. It is reliable and probably faster than using jedi. The only downside is that it provides just the first error even when there are many. Still quite useful.
Further refinement
The idea and the following quite remarkable decorator function are borrowed from python_lsp_server.
Add to jedi_utils:
In server.py decorate _publish_diagnostics
So, for example, if the user types fast, instead of sending multiple publishDiagnostics notifications only one will be send with a bit of delay. Each new one will cancel the previous one if it has not already been executed.
I can submit a PR if you approve the above.