diff --git a/README.md b/README.md index 9d828da0b..ba02b901c 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,29 @@ Get started * Run `./mvnw clean verify` (OSX, Linux) or `mvnw.cmd clean verify` (Windows) * After successful compilation you can find the resulting `org.eclipse.lsp4xml-all.jar` in the folder `org.eclipse.lsp4xml/target` +Developer +-------------- + +To debug the XML LS you can use XMLServerSocketLauncher: + +1. Run the XMLServerSocketLauncher in debug mode (e.g. in eclipse) +2. Connect your client via socket port. Default port is 5008, but you can change it with start argument `--port` in step 1 + +Client connection example using Theia and TypeScript: + +``` + let socketPort = '5008' + console.log(`Connecting via port ${socketPort}`) + const socket = new net.Socket() + const serverConnection = createSocketConnection(socket, + socket, () => { + socket.destroy() + }); + this.forward(clientConnection, serverConnection) + socket.connect(socketPort) +``` + + Clients ------- diff --git a/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLServerSocketLauncher.java b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLServerSocketLauncher.java new file mode 100644 index 000000000..c64253c2d --- /dev/null +++ b/org.eclipse.lsp4xml/src/main/java/org/eclipse/lsp4xml/XMLServerSocketLauncher.java @@ -0,0 +1,73 @@ +/** + * Copyright (c) 2018 TypeFox GmbH (http://www.typefox.io) and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Eclipse Public License v1.0 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/epl-v10.html + * + * @author Dennis Huebner - Initial contribution and API + */ +package org.eclipse.lsp4xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.net.InetSocketAddress; +import java.nio.channels.AsynchronousServerSocketChannel; +import java.nio.channels.AsynchronousSocketChannel; +import java.nio.channels.Channels; +import java.util.Objects; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.eclipse.lsp4j.jsonrpc.Launcher; +import org.eclipse.lsp4j.jsonrpc.MessageConsumer; +import org.eclipse.lsp4j.services.LanguageClient; + +public class XMLServerSocketLauncher { + + private static final int DEFAULT_PORT = 5_008; + + /** + * Calls {@link #launch(String[])} + */ + public static void main(String[] args) throws Exception { + new XMLServerSocketLauncher().launch(args); + } + + /** + * Launches {@link XMLLanguageServer} using asynchronous server-socket channel and makes it accessible through the JSON + * RPC protocol defined by the LSP. + * + * @param args standard launch arguments. may contain --port argument to change the default port 5008 + */ + public void launch(String[] args) throws Exception { + AsynchronousServerSocketChannel _open = AsynchronousServerSocketChannel.open(); + int _port = getPort(args); + InetSocketAddress _inetSocketAddress = new InetSocketAddress("0.0.0.0", _port); + final AsynchronousServerSocketChannel serverSocket = _open.bind(_inetSocketAddress); + while (true) { + final AsynchronousSocketChannel socketChannel = serverSocket.accept().get(); + final InputStream in = Channels.newInputStream(socketChannel); + final OutputStream out = Channels.newOutputStream(socketChannel); + final ExecutorService executorService = Executors.newCachedThreadPool(); + XMLLanguageServer languageServer = new XMLLanguageServer(); + final Launcher launcher = Launcher.createIoLauncher(languageServer, LanguageClient.class, + in, out, executorService, (MessageConsumer it) -> { + return it; + }); + languageServer.setClient(launcher.getRemoteProxy()); + launcher.startListening(); + } + } + + protected int getPort(final String... args) { + for (int i = 0; (i < (args.length - 1)); i++) { + String _get = args[i]; + boolean _equals = Objects.equals(_get, "--port"); + if (_equals) { + return Integer.parseInt(args[(i + 1)]); + } + } + return DEFAULT_PORT; + } +}