Skip to content

Commit

Permalink
Fix initial reporting of diagnostics (#75)
Browse files Browse the repository at this point in the history
The issue was that the diagnostics were being reported before the
server had responded to the `initialize` request - which is against
the protocol.

Instead the server now listens for the `initialized` notification from
the client and exposes a hook to features where on first startup code
can be run once initialzation has finished
  • Loading branch information
alcarney authored Jan 28, 2021
1 parent e490e6b commit 068f082
Show file tree
Hide file tree
Showing 5 changed files with 32 additions and 11 deletions.
2 changes: 1 addition & 1 deletion lib/esbonio/CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ Fixes

- Errors encountered when initialising Sphinx are now caught and the language
client is notified of an issue. (`#33 <https://github.com/swyddfa/esbonio/issues/33>`_)
- **Language Server** Fix issue where some malformed ``CompletionItem``s were
- **Language Server** Fix issue where some malformed ``CompletionItem`` objects were
preventing completion suggestions from being shown. (`#54 <https://github.com/swyddfa/esbonio/issues/54>`_)
- **Language Server** Windows paths are now handled correctly (`#60 <https://github.com/swyddfa/esbonio/issues/60>`_)
- **Language Server** Server no longer chooses ``conf.py`` files that
Expand Down
1 change: 1 addition & 0 deletions lib/esbonio/changes/68.fix.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
**Language Server** Diagnostics are now reported on first startup
15 changes: 14 additions & 1 deletion lib/esbonio/esbonio/lsp/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@

from typing import List

from pygls.features import COMPLETION, INITIALIZE, TEXT_DOCUMENT_DID_SAVE
from pygls.features import COMPLETION, INITIALIZE, INITIALIZED, TEXT_DOCUMENT_DID_SAVE
from pygls.server import LanguageServer
from pygls.types import (
CompletionList,
Expand Down Expand Up @@ -35,6 +35,10 @@ def __init__(self, *args, **kwargs):
self.on_init_hooks = []
"""A list of functions to run on initialization"""

self.on_initialized_hooks = []
"""A list of functions to run after receiving the initialized notification from the
client"""

self.on_save_hooks = []
"""A list of hooks to run on document save."""

Expand All @@ -47,6 +51,9 @@ def add_feature(self, feature):
if hasattr(feature, "initialize"):
self.on_init_hooks.append(feature.initialize)

if hasattr(feature, "initialized"):
self.on_initialized_hooks.append(feature.initialized)

if hasattr(feature, "save"):
self.on_save_hooks.append(feature.save)

Expand Down Expand Up @@ -101,6 +108,12 @@ def on_initialize(rst: RstLanguageServer, params: InitializeParams):

rst.logger.info("LSP Server Initialized")

@server.feature(INITIALIZED)
def on_initialized(rst: RstLanguageServer, params):

for initialized_hook in rst.on_initialized_hooks:
initialized_hook()

@server.feature(COMPLETION, trigger_characters=[".", ":", "`", "<"])
def on_completion(rst: RstLanguageServer, params: CompletionParams):
"""Suggest completions based on the current context."""
Expand Down
23 changes: 15 additions & 8 deletions lib/esbonio/esbonio/lsp/sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,10 +74,21 @@ def __init__(self, rst: RstLanguageServer):

def initialize(self):
self.create_app()
self.refresh_app()

if self.rst.app is not None:
self.rst.app.builder.read()

def initialized(self):
self.report_diagnostics()

def save(self, params: DidSaveTextDocumentParams):
self.refresh_app()

if self.rst.app is None:
return

self.reset_diagnostics()
self.rst.app.builder.read()
self.report_diagnostics()

def create_app(self):
"""Initialize a Sphinx application instance for the current workspace."""
Expand Down Expand Up @@ -122,12 +133,8 @@ def create_app(self):
msg_type=MessageType.Error,
)

def refresh_app(self):
if self.rst.app is None:
return

self.reset_diagnostics()
self.rst.app.builder.read()
def report_diagnostics(self):
"""Publish the current set of diagnostics to the client."""

for doc, diagnostics in self.diagnostics.items():

Expand Down
2 changes: 1 addition & 1 deletion lib/esbonio/tests/lsp/test_sphinx.py
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ def test_report_diagnostics():
}

manager.reset_diagnostics = mock.Mock()
manager.refresh_app()
manager.save(None)

expected = [
mock.call("file:///c:\\Users\\username\\Project\\file.rst", (1, 2, 3)),
Expand Down

0 comments on commit 068f082

Please sign in to comment.