@Override public LanguageServer get(LanguageClient client, InputStream in, OutputStream out) { Launcher<LanguageServer> launcher = createLauncher(client, LanguageServer.class, in, out); LOG.debug("Created launcher for language server"); launcher.startListening(); LOG.debug("Started listening"); LanguageServer remoteProxy = launcher.getRemoteProxy(); LOG.debug("Got remote proxy"); return remoteProxy; }
private void handleConnection(final Socket client) { logger.debug("Client {} connected", client.getRemoteSocketAddress()); try { LanguageServerImpl languageServer = injector.getInstance(LanguageServerImpl.class); Launcher<LanguageClient> launcher = LSPLauncher.createServerLauncher(languageServer, client.getInputStream(), client.getOutputStream()); languageServer.connect(launcher.getRemoteProxy()); Future<?> future = launcher.startListening(); future.get(); } catch (IOException e) { logger.warn("Error communicating with LSP client {}", client.getRemoteSocketAddress()); } catch (InterruptedException e) { // go on, let the thread finish } catch (ExecutionException e) { logger.error("Error running the Language Server", e); } logger.debug("Client {} disconnected", client.getRemoteSocketAddress()); }
@SuppressFBWarnings("DM_DEFAULT_ENCODING") public void launch() { Function<MessageConsumer, MessageConsumer> loggingMessageConsumerAdapter = consumer -> { return message -> { log.debug("Message received to client: {}", message); consumer.consume(message); }; }; Launcher<LanguageClient> serverLauncher = LSPLauncher.createServerLauncher( languageServer, inputStream, outputStream, Executors.newCachedThreadPool(), loggingMessageConsumerAdapter); if (languageServer instanceof LanguageClientAware) { LanguageClient client = serverLauncher.getRemoteProxy(); ((LanguageClientAware) languageServer).connect(client); } serverLauncher.startListening(); } }
/** * starts up the language server and let it listen for connections from the outside * instead of connecting itself to an existing port or channel. * * This is meant for development only, to reduce turnaround times while working * on the language server from within an IDE, so that you can start the language * server right away in debug mode and let the vscode extension connect to that * instance instead of vice versa. * * Source of inspiration: * https://github.com/itemis/xtext-languageserver-example/blob/master/org.xtext.example.mydsl.ide/src/org/xtext/example/mydsl/ide/RunServer.java */ public void startAsServer() throws Exception { int serverPort = properties.getStandalonePort(); log.info("Starting LS as standlone server port = {}", serverPort); Function<MessageConsumer, MessageConsumer> wrapper = consumer -> { MessageConsumer result = consumer; return result; }; Launcher<STS4LanguageClient> launcher = createSocketLauncher(languageServer, STS4LanguageClient.class, new InetSocketAddress("localhost", serverPort), createServerThreads(), wrapper); languageServer.connect(launcher.getRemoteProxy()); launcher.startListening().get(); }
public void run() throws IOException, InterruptedException, ExecutionException { Injector injector = Guice.createInjector(module); GsonConfigurator gsonConf = injector.getInstance(GsonConfigurator.class); AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open() .bind(new InetSocketAddress(host, port)); ExecutorService threadPool = Executors.newCachedThreadPool(); log.info("The graphical server launcher is ready to accept new client requests"); while (true) { AsynchronousSocketChannel socketChannel = serverSocket.accept().get(); InputStream in = Channels.newInputStream(socketChannel); OutputStream out = Channels.newOutputStream(socketChannel); Consumer<GsonBuilder> configureGson = (GsonBuilder builder) -> gsonConf.configureGsonBuilder(builder); Function<MessageConsumer, MessageConsumer> wrapper = (MessageConsumer it) -> { return it; }; GLSPServer languageServer = injector.getInstance(GLSPServer.class); Launcher<GLSPClient> launcher = Launcher.createIoLauncher(languageServer, GLSPClient.class, in, out, threadPool, wrapper, configureGson); languageServer.connect(launcher.getRemoteProxy()); launcher.startListening(); log.info("Started language server for client " + socketChannel.getRemoteAddress()); } } }
private Future<Void> runAsync(Connection connection) throws Exception { LanguageServer server = this.languageServer; ExecutorService executor = createServerThreads(); Function<MessageConsumer, MessageConsumer> wrapper = (MessageConsumer consumer) -> { return (msg) -> { try { consumer.consume(msg); } catch (UnsupportedOperationException e) { //log a warning and ignore. We are getting some messages from vsCode the server doesn't know about log.warn("Unsupported message was ignored!", e); } }; }; Launcher<STS4LanguageClient> launcher = Launcher.createLauncher(server, STS4LanguageClient.class, connection.in, connection.out, executor, wrapper ); if (server instanceof LanguageClientAware) { LanguageClient client = launcher.getRemoteProxy(); ((LanguageClientAware) server).connect(client); } return launcher.startListening(); }
Executors.newCachedThreadPool(), c -> c, gsonBuilder -> {gsonBuilder.registerTypeAdapter(Param.class, typeAdapter);}); A remoteProxy = launcher.getRemoteProxy();
@SuppressFBWarnings("DM_DEFAULT_ENCODING") @Before public void before() throws IOException, InterruptedException { PipedOutputStream clientOutputStream = new PipedOutputStream(); PipedOutputStream serverOutputStream = new PipedOutputStream(); PipedInputStream clientInputStream = new PipedInputStream(serverOutputStream); PipedInputStream serverInputStream = new PipedInputStream(clientOutputStream); // Start Groovy language server createAndLaunchLanguageServer(serverInputStream, serverOutputStream); int counter = 0; while (server != null && counter++ < 20) { Thread.sleep(50); } LanguageClient client = getClient(); Launcher<LanguageServer> clientLauncher = LSPLauncher.createClientLauncher( client, clientInputStream, clientOutputStream, false, new PrintWriter(System.out)); clientLauncher.startListening(); server = clientLauncher.getRemoteProxy(); ((LanguageClientAware) actualServer).connect(client); }
@Test public void testCustomGson() throws Exception { A a = new A() { @Override public void say(Param p) { } }; ByteArrayOutputStream out = new ByteArrayOutputStream(); TypeAdapter<Param> typeAdapter = new TypeAdapter<Param>() { @Override public void write(JsonWriter out, Param value) throws IOException { out.beginObject(); out.name("message"); out.value("bar"); out.endObject(); } @Override public Param read(JsonReader in) throws IOException { return null; } }; Launcher<A> launcher = DebugLauncher.createIoLauncher(a, A.class, new ByteArrayInputStream("".getBytes()), out, Executors.newCachedThreadPool(), c -> c, gsonBuilder -> {gsonBuilder.registerTypeAdapter(Param.class, typeAdapter);}); A remoteProxy = launcher.getRemoteProxy(); remoteProxy.say(new Param("foo")); Assert.assertEquals("Content-Length: 63\r\n\r\n" + "{\"type\":\"event\",\"seq\":1,\"event\":\"say\",\"body\":{\"message\":\"bar\"}}", out.toString()); }
/** * creates a proxy, delegating to a remote endpoint, forwarding to another remote endpoint, that delegates to an actual implementation. * @param intf * @param impl * @return * @throws IOException */ public <T> T wrap(Class<T> intf, T impl) { PipedInputStream in1 = new PipedInputStream(); PipedOutputStream out1 = new PipedOutputStream(); Launcher<T> launcher1 = Launcher.createLauncher(impl, intf, in1, out1); PipedInputStream in2 = new PipedInputStream(); PipedOutputStream out2 = new PipedOutputStream(); Launcher<T> launcher2 = Launcher.createLauncher(new Object(), intf, in2, out2); try { in1.connect(out2); in2.connect(out1); } catch (IOException e) { throw new IllegalStateException(e); } launcher1.startListening(); launcher2.startListening(); return launcher2.getRemoteProxy(); } }
@Test public void testNotification() throws IOException { OutputEventArguments p = new OutputEventArguments(); p.setOutput("Hello World"); client.expectedNotifications.put("output", p); serverLauncher.getRemoteProxy().output(p); client.joinOnEmpty(); }
private void startConnection() throws IOException { Launcher<JavaLanguageClient> launcher; ExecutorService executorService = Executors.newCachedThreadPool(); protocol = new JDTLanguageServer(projectsManager, preferenceManager); if (JDTEnvironmentUtils.inSocketStreamDebugMode()) { String host = JDTEnvironmentUtils.getClientHost(); Integer port = JDTEnvironmentUtils.getClientPort(); InetSocketAddress inetSocketAddress = new InetSocketAddress(host, port); AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open().bind(inetSocketAddress); try { AsynchronousSocketChannel socketChannel = serverSocket.accept().get(); InputStream in = Channels.newInputStream(socketChannel); OutputStream out = Channels.newOutputStream(socketChannel); Function<MessageConsumer, MessageConsumer> messageConsumer = it -> it; launcher = Launcher.createIoLauncher(protocol, JavaLanguageClient.class, in, out, executorService, messageConsumer); } catch (InterruptedException | ExecutionException e) { throw new RuntimeException("Error when opening a socket channel at " + host + ":" + port + ".", e); } } else { ConnectionStreamFactory connectionFactory = new ConnectionStreamFactory(); InputStream in = connectionFactory.getInputStream(); OutputStream out = connectionFactory.getOutputStream(); Function<MessageConsumer, MessageConsumer> wrapper = new ParentProcessWatcher(this.languageServer); launcher = Launcher.createLauncher(protocol, JavaLanguageClient.class, in, out, executorService, wrapper); } protocol.connectClient(launcher.getRemoteProxy()); launcher.startListening(); }
@Test public void testNotification() throws IOException { MessageParams p = new MessageParams(); p.setMessage("Hello World"); p.setType(MessageType.Info); client.expectedNotifications.put("window/logMessage", p); serverLauncher.getRemoteProxy().logMessage(p); client.joinOnEmpty(); }
assertEquals("bar1", paramB[0]); Object remoteProxy = launcher.getRemoteProxy(); ((A) remoteProxy).say(new Param("foo2")); ((B) remoteProxy).ask(new Param("bar2"));
@Test public void testBothDirectionRequests() throws Exception { // create client side PipedInputStream in = new PipedInputStream(); PipedOutputStream out = new PipedOutputStream(); PipedInputStream in2 = new PipedInputStream(); PipedOutputStream out2 = new PipedOutputStream(); in.connect(out2); out.connect(in2); MyClient client = new MyClientImpl(); Launcher<MyServer> clientSideLauncher = Launcher.createLauncher(client, MyServer.class, in, out); // create server side MyServer server = new MyServerImpl(); Launcher<MyClient> serverSideLauncher = Launcher.createLauncher(server, MyClient.class, in2, out2); clientSideLauncher.startListening(); serverSideLauncher.startListening(); CompletableFuture<MyParam> fooFuture = clientSideLauncher.getRemoteProxy().askServer(new MyParam("FOO")); CompletableFuture<MyParam> barFuture = serverSideLauncher.getRemoteProxy().askClient(new MyParam("BAR")); Assert.assertEquals("FOO", fooFuture.get(TIMEOUT, TimeUnit.MILLISECONDS).value); Assert.assertEquals("BAR", barFuture.get(TIMEOUT, TimeUnit.MILLISECONDS).value); }
serverSideLauncher.startListening(); CompletableFuture<MyParam> fooFuture = clientSideLauncher.getRemoteProxy().askServer(new MyParam("FOO")); CompletableFuture<MyParam> barFuture = serverSideLauncher.getRemoteProxy().askClient(new MyParam("BAR"));
serverSideLauncher.startListening(); CompletableFuture<MyParam> fooFuture = clientSideLauncher.getRemoteProxy().askServer(new MyParam("FOO")); CompletableFuture<MyParam> barFuture = serverSideLauncher.getRemoteProxy().askClient(new MyParam("BAR"));
@Test public void testRequest() throws Exception { InitializeRequestArguments p = new InitializeRequestArguments(); p.setClientID("test"); Capabilities result = new Capabilities(); result.setSupportTerminateDebuggee(true); result.setSupportsCompletionsRequest(false); server.expectedRequests.put("initialize", new Pair<>(p, result)); CompletableFuture<Capabilities> future = clientLauncher.getRemoteProxy().initialize(p); Assert.assertEquals(result.toString(), future.get(TIMEOUT, TimeUnit.MILLISECONDS).toString()); client.joinOnEmpty(); }
serverSideLauncher.startListening(); CompletableFuture<MyParam> fooFuture = clientSideLauncher.getRemoteProxy().askServer(new MyParam("FOO")); CompletableFuture<MyParam> barFuture = serverSideLauncher.getRemoteProxy().askClient(new MyParam("BAR"));
@Test public void testRequest() throws Exception { CompletionParams p = new CompletionParams(); p.setPosition(new Position(1,1)); p.setTextDocument(new TextDocumentIdentifier("test/foo.txt")); CompletionList result = new CompletionList(); result.setIsIncomplete(true); result.setItems(new ArrayList<>()); CompletionItem item = new CompletionItem(); item.setDetail("test"); item.setDocumentation("doc"); item.setFilterText("filter"); item.setInsertText("insert"); item.setKind(CompletionItemKind.Field); result.getItems().add(item); server.expectedRequests.put("textDocument/completion", new Pair<>(p, result)); CompletableFuture<Either<List<CompletionItem>, CompletionList>> future = clientLauncher.getRemoteProxy().getTextDocumentService().completion(p); Assert.assertEquals(Either.forRight(result).toString(), future.get(TIMEOUT, TimeUnit.MILLISECONDS).toString()); client.joinOnEmpty(); }