def client_server(): """ A fixture to setup a LSP client/server """ from cp2k_input_tools.ls import setup_ls from pygls.server import LanguageServer from pygls import features from pygls.types import LogMessageParams, PublishDiagnosticsParams # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() server = LanguageServer() setup_ls(server) server_thread = Thread(target=server.start_io, args=(os.fdopen(csr, "rb"), os.fdopen(scw, "wb"))) server_thread.daemon = True server_thread.start() # Add thread id to the server (just for testing) server.thread_id = server_thread.ident # Setup client client = LanguageServer(asyncio.new_event_loop()) # make sure our minimal client can store log messages and diagnostics @client.feature(features.WINDOW_LOG_MESSAGE) async def client_log_message(ls, params: LogMessageParams): ls.msg_type = params.type ls.msg = params.message @client.feature(features.TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS) async def client_handle_diagnostics(ls, params: PublishDiagnosticsParams): ls.diagnostics = params.diagnostics client_thread = Thread(target=client.start_io, args=(os.fdopen(scr, "rb"), os.fdopen(csw, "wb"))) client_thread.daemon = True client_thread.start() yield client, server shutdown_response = client.lsp.send_request( features.SHUTDOWN).result(timeout=CALL_TIMEOUT) assert shutdown_response is None client.lsp.notify(features.EXIT)
def test_allow_custom_protocol_derived_from_lsp(): class CustomProtocol(LanguageServerProtocol): pass server = LanguageServer(protocol_cls=CustomProtocol) assert isinstance(server.lsp, CustomProtocol)
async def test_tcp_connection_lost(): loop = asyncio.new_event_loop() server = LanguageServer(loop=loop) server.lsp.connection_made = Mock() server.lsp.connection_lost = Mock() # Run the server over TCP in a separate thread server_thread = Thread(target=server.start_tcp, args=('127.0.0.1', 0, )) server_thread.daemon = True server_thread.start() # Wait for server to be ready while server._server is None: await asyncio.sleep(.5) # Simulate client's connection port = server._server.sockets[0].getsockname()[1] reader, writer = await asyncio.open_connection('127.0.0.1', port) await asyncio.sleep(1) assert server.lsp.connection_made.called # Socket is closed (client's process is terminated) writer.close() await asyncio.sleep(1) assert server.lsp.connection_lost.called
def client_server(): c2s_r, c2s_w = os.pipe() s2c_r, s2c_w = os.pipe() def start(ls: LanguageServer, fdr, fdw): # TODO: better patch is needed # disable `close()` to avoid error messages close = ls.loop.close ls.loop.close = lambda: None ls.start_io(os.fdopen(fdr, "rb"), os.fdopen(fdw, "wb")) ls.loop.close = close server = CMakeLanguageServer(asyncio.new_event_loop()) server_thread = Thread(target=start, args=(server, c2s_r, s2c_w)) server_thread.start() client = LanguageServer(asyncio.new_event_loop()) client_thread = Thread(target=start, args=(client, s2c_r, c2s_w)) client_thread.start() yield client, server client.send_notification(features.EXIT) server.send_notification(features.EXIT) server_thread.join() client_thread.join()
def setUp(self): self.folder = Path(__file__).parent / 'verilog' # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() # Server self.server = server # Client self.client = LanguageServer(asyncio.new_event_loop()) server_thread = Thread(target=self.server.start_io, args=(os.fdopen(csr, 'rb'), os.fdopen(scw, 'wb'))) server_thread.daemon = True server_thread.start() client_thread = Thread(target=self.client.start_io, args=(os.fdopen(scr, 'rb'), os.fdopen(csw, 'wb'))) client_thread.daemon = True client_thread.start() # Initialize server self.server.lsp.bf_initialize( InitializeParams(process_id=1234, root_uri=self.folder.as_uri(), capabilities=None)) print("Setup done!")
def __init__(self): from pygls.lsp.methods import ( TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS, WINDOW_LOG_MESSAGE, ) from pygls.lsp.types import LogMessageParams, PublishDiagnosticsParams from pygls.server import LanguageServer from cp2k_input_tools.ls import setup_cp2k_ls_server # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() # Setup Server self.server = LanguageServer() setup_cp2k_ls_server(self.server) self.server_thread = Thread(target=self.server.start_io, args=(os.fdopen(csr, "rb"), os.fdopen(scw, "wb"))) self.server_thread.daemon = True # Setup client self.client = LanguageServer(asyncio.new_event_loop()) # make sure our minimal client can store log messages and diagnostics self.client.msgs = [] self.client.diagnostics = None @self.client.feature(WINDOW_LOG_MESSAGE) async def client_log_message(ls, params: LogMessageParams): ls.msgs.append(params) @self.client.feature(TEXT_DOCUMENT_PUBLISH_DIAGNOSTICS) async def client_handle_diagnostics(ls, params: PublishDiagnosticsParams): ls.diagnostics = params.diagnostics self.client_thread = Thread(target=self.client.start_io, args=(os.fdopen(scr, "rb"), os.fdopen(csw, "wb"))) self.client_thread.daemon = True
def __init__(self): # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() # Setup Server self.server = LanguageServer() self.server_thread = Thread(target=self.server.start_io, args=(os.fdopen(csr, 'rb'), os.fdopen(scw, 'wb'))) self.server_thread.daemon = True # Setup client self.client = LanguageServer(asyncio.new_event_loop()) self.client_thread = Thread(target=self.client.start_io, args=(os.fdopen(scr, 'rb'), os.fdopen(csw, 'wb'))) self.client_thread.daemon = True
def client_server(): """ A fixture to setup a client/server """ # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() # Setup server server = LanguageServer() setup_ls_features(server) server_thread = Thread(target=server.start_io, args=( os.fdopen(csr, 'rb'), os.fdopen(scw, 'wb') )) server_thread.daemon = True server_thread.start() # Add thread id to the server (just for testing) server.thread_id = server_thread.ident # Setup client client = LanguageServer(asyncio.new_event_loop()) client_thread = Thread(target=client.start_io, args=( os.fdopen(scr, 'rb'), os.fdopen(csw, 'wb'))) client_thread.daemon = True client_thread.start() yield client, server shutdown_response = client.lsp.send_request( features.SHUTDOWN).result(timeout=CALL_TIMEOUT) assert shutdown_response is None client.lsp.notify(features.EXIT)
async def test_io_connection_lost(): # Client to Server pipe. csr, csw = os.pipe() # Server to client pipe. scr, scw = os.pipe() server = LanguageServer(loop=asyncio.new_event_loop()) server.lsp.connection_made = Mock() server_thread = Thread(target=server.start_io, args=(os.fdopen(csr, 'rb'), os.fdopen(scw, 'wb'))) server_thread.daemon = True server_thread.start() # Wait for server to be ready while not server.lsp.connection_made.called: await asyncio.sleep(.5) # Pipe is closed (client's process is terminated) os.close(csw) server_thread.join()
def client_server(): """A fixture that sets up an LSP server + client. Originally based on https://github.com/openlawlibrary/pygls/blob/59f3056baa4de4c4fb374d3657194f2669c174bc/tests/conftest.py # noqa: E501 """ # Pipes so that client + server can communicate csr, csw = os.pipe() scr, scw = os.pipe() # Server setup server = create_language_server(BUILTIN_MODULES) server_thread = threading.Thread( name="ServThread", target=server.start_io, args=(os.fdopen(csr, "rb"), os.fdopen(scw, "wb")), ) server_thread.daemon = True server_thread.start() # Not entirely sure what this step does... server.thread_id = server_thread.ident # Client setup - we can get away with a vanilla 'LanguageServer' for this client = LanguageServer(asyncio.new_event_loop()) client_thread = threading.Thread( name="ClntThread", target=client.start_io, args=(os.fdopen(scr, "rb"), os.fdopen(csw, "wb")), ) client_thread.daemon = True client_thread.start() yield client, server response = client.lsp.send_request(SHUTDOWN).result(timeout=2) assert response is None client.lsp.notify(EXIT)
def client_server(): """ A fixture to setup a client/server """ # Client to Server pipe csr, csw = os.pipe() # Server to client pipe scr, scw = os.pipe() # Run server server_thread = Thread(target=textx_server.start_io, args=( os.fdopen(csr, 'rb'), os.fdopen(scw, 'wb') )) server_thread.daemon = True server_thread.start() # Setup client client = LanguageServer(asyncio.new_event_loop()) client_thread = Thread(target=client.start_io, args=( os.fdopen(scr, 'rb'), os.fdopen(csw, 'wb') )) client_thread.daemon = True client_thread.start() # Register client features to catch responses register_client_features(client) # Initialize server initialize_server(textx_server) yield client, textx_server shutdown_response = client.lsp.send_request( SHUTDOWN).result(timeout=CALL_TIMEOUT) assert shutdown_response is None client.send_notification(EXIT)
def __init__( self, method: ConnectionMethod, host: Optional[str], port: Optional[int] ) -> None: self._method = method self._host = host self._port = port if self._method == ConnectionMethod.TCP: if host is None or port is None: raise ValueError("host and port is required when method is TCP") self._server = LanguageServer() self._config = LanguageServerConfiguration.default() self._workspace = Workspace(self._server) self._register_command( Commands.ReloadServerConfiguration, self._on_reload_server_config, ) self._register_command( Commands.LintDocument, self._on_lint_document, ) self._register_command( Commands.FormatDocument, self._on_format_document, ) self._register_command( Commands.LintWorkspace, self._on_lint_workspace, ) self._register_command( Commands.FormatWorkspace, self._on_format_workspace, ) self._register_feature("$/setTrace", None, lambda *args, **kwargs: None) self._register_feature( lsp.methods.INITIALIZE, None, self._on_initialize, ) self._register_feature( lsp.methods.WORKSPACE_DID_CHANGE_CONFIGURATION, None, self._on_workspace_did_change_configuration, ) self._register_feature( lsp.methods.FORMATTING, lsp.types.DocumentFormattingOptions(), self._on_formatting, ) self._register_feature( lsp.methods.TEXT_DOCUMENT_DID_SAVE, None, self._on_text_document_did_save, ) self._register_feature( lsp.methods.TEXT_DOCUMENT_DID_OPEN, None, self._on_text_document_did_open, ) self._register_feature( lsp.methods.TEXT_DOCUMENT_DID_CLOSE, None, self._on_text_document_did_close, ) self._register_feature( lsp.methods.TEXT_DOCUMENT_DID_CHANGE, None, self._on_text_document_did_change, ) self._register_feature( lsp.methods.CODE_ACTION, lsp.types.CodeActionOptions( code_action_kinds=[lsp.types.CodeActionKind.QuickFix] ), self._provide_code_action, )
CompletionItemKind, CompletionOptions, CompletionParams, DidChangeTextDocumentParams, DidChangeWatchedFilesParams, DidOpenTextDocumentParams, MarkupContent, MarkupKind, Position, Range, TextEdit, ) from . import buildout, diagnostic server = LanguageServer() logger = logging.getLogger(__name__) DEBOUNCE_DELAY = 0.3 async def parseAndSendDiagnostics( ls: LanguageServer, uri: str, ) -> None: await asyncio.sleep(DEBOUNCE_DELAY) diagnostics = [] async for diag in diagnostic.getDiagnostics(ls, uri): diagnostics.append(diag) ls.publish_diagnostics(uri, diagnostics)
if hover: hoverMarkup = hover[0] if hoverMarkup == types.MarkupKind.Markdown: hoverFunction = _docstring_markdown else: hoverFunction = _docstring # pygls does not currently support serverInfo of LSP v3.15 result.server_info = types.ServerInfo( name='anakinls', version=get_version(), ) return result server = LanguageServer(protocol_cls=AnakinLanguageServerProtocol) scripts: Dict[str, Script] = {} pycodestyleOptions: Dict[str, Any] = {} mypyConfigs: Dict[str, str] = {} jediEnvironment = None jediProject = None completionPrefixPlain = 'a' completionPrefixSnippet = 'z' jediHoverFunction = Script.help config = { 'pyflakes_errors': ['UndefinedName'],
def test_forbid_custom_protocol_not_derived_from_lsp(): class CustomProtocol: pass with pytest.raises(TypeError): LanguageServer(protocol_cls=CustomProtocol)
): server.feature(DOCUMENT_SYMBOL)(document_symbol) else: server.feature(DOCUMENT_SYMBOL)(document_symbol_legacy) init = rgetattr(params, "initializationOptions") if rgetattr(init, "diagnostics.enable", True): if rgetattr(init, "diagnostics.didOpen", True): SERVER.feature(TEXT_DOCUMENT_DID_OPEN)(did_open) if rgetattr(init, "diagnostics.didChange", True): SERVER.feature(TEXT_DOCUMENT_DID_CHANGE)(did_change) if rgetattr(init, "diagnostics.didSave", True): SERVER.feature(TEXT_DOCUMENT_DID_SAVE)(did_save) return super().bf_initialize(params) SERVER = LanguageServer(protocol_cls=JediLanguageServerProtocol) # Static capabilities, no configuration @SERVER.feature(COMPLETION, trigger_characters=[".", "'", '"']) def completion(server: LanguageServer, params: CompletionParams) -> CompletionList: """Returns completion items""" jedi_script = jedi_utils.script(server.workspace, params.textDocument.uri) jedi_lines = jedi_utils.line_column(params.position) completions = jedi_script.complete(**jedi_lines) char = pygls_utils.char_before_cursor( document=server.workspace.get_document(params.textDocument.uri), position=params.position, )
diagnostics += [ Diagnostic(erange, msg, source=type(cp2k_inp_server).__name__, related_information=[]) ] ls.publish_diagnostics(text_doc.uri, diagnostics) def setup_ls(server): @server.feature(TEXT_DOCUMENT_DID_CHANGE) def did_change(ls, params: DidChangeTextDocumentParams): """Text document did change notification.""" _validate(ls, params) @server.feature(TEXT_DOCUMENT_DID_CLOSE) def did_close(server: LanguageServer, params: DidCloseTextDocumentParams): """Text document did close notification.""" server.show_message("Text Document Did Close") @server.feature(TEXT_DOCUMENT_DID_OPEN) async def did_open(ls, params: DidOpenTextDocumentParams): """Text document did open notification.""" ls.show_message("Text Document Did Open") _validate(ls, params) cp2k_inp_server = LanguageServer() setup_ls(cp2k_inp_server)
else: erange = Range(start=Position(line=linenr, character=1), end=Position(line=linenr, character=len(line))) diagnostics += [ Diagnostic(range=erange, message=msg, source=type(ls).__name__) ] ls.publish_diagnostics(text_doc.uri, diagnostics) def setup_cp2k_ls_server(server): @server.feature(TEXT_DOCUMENT_DID_CHANGE) def did_change(ls, params: DidChangeTextDocumentParams): """Text document did change notification.""" _validate(ls, params) @server.feature(TEXT_DOCUMENT_DID_CLOSE) def did_close(ls: LanguageServer, params: DidCloseTextDocumentParams): """Text document did close notification.""" pass @server.feature(TEXT_DOCUMENT_DID_OPEN) async def did_open(ls, params: DidOpenTextDocumentParams): """Text document did open notification.""" _validate(ls, params) cp2k_server = LanguageServer() setup_cp2k_ls_server(cp2k_server)