added mode to connect vscode extension to running language server
This commit is contained in:
@@ -2,36 +2,60 @@
|
||||
// The module 'vscode' contains the VS Code extensibility API
|
||||
// Import the module and reference it with the alias vscode in your code below
|
||||
|
||||
import * as net from 'net';
|
||||
|
||||
import * as VSCode from 'vscode';
|
||||
import * as Path from 'path';
|
||||
import * as FS from 'fs';
|
||||
import * as Net from 'net';
|
||||
import * as ChildProcess from 'child_process';
|
||||
import {LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo} from 'vscode-languageclient';
|
||||
import {TextDocument} from 'vscode';
|
||||
import { LanguageClient, LanguageClientOptions, SettingMonitor, ServerOptions, StreamInfo } from 'vscode-languageclient';
|
||||
import { TextDocument } from 'vscode';
|
||||
import { Trace } from 'vscode-jsonrpc';
|
||||
|
||||
import * as commons from 'commons-vscode';
|
||||
|
||||
/** Called when extension is activated */
|
||||
export function activate(context: VSCode.ExtensionContext) {
|
||||
let options : commons.ActivatorOptions = {
|
||||
DEBUG: true,
|
||||
extensionId: 'vscode-boot-java',
|
||||
fatJarFile: 'target/vscode-boot-java-0.0.1-SNAPSHOT.jar',
|
||||
clientOptions: {
|
||||
// HACK!!! documentSelector only takes string|string[] where string is language id, but DocumentFilter object is passed instead
|
||||
// Reasons:
|
||||
// 1. documentSelector is just passed over to functions like #registerHoverProvider(documentSelector, ...) that take documentSelector
|
||||
// parameter in string | DocumentFilter | string[] | DocumentFilter[] format
|
||||
// 2. Combination of non string|string[] documentSelector parameter and synchronize.textDocumentFilter function makes doc synchronization
|
||||
// events pass on to Language Server only for documents for which function passed via textDocumentFilter property return true
|
||||
|
||||
// TODO: Remove <any> cast ones https://github.com/Microsoft/vscode-languageserver-node/issues/9 is resolved
|
||||
let CONNECT_TO_LS = false;
|
||||
|
||||
if (CONNECT_TO_LS) {
|
||||
let connectionInfo = {
|
||||
port: 5007
|
||||
};
|
||||
let serverOptions = () => {
|
||||
let socket = net.connect(connectionInfo);
|
||||
let result: StreamInfo = {
|
||||
writer: socket,
|
||||
reader: socket
|
||||
};
|
||||
return Promise.resolve(result);
|
||||
};
|
||||
|
||||
let clientOptions: LanguageClientOptions = {
|
||||
documentSelector: ['java'],
|
||||
synchronize: {
|
||||
configurationSection: 'vscode-boot-java'
|
||||
}
|
||||
}
|
||||
};
|
||||
commons.activate(options, context);
|
||||
};
|
||||
|
||||
let lc = new LanguageClient('vscode-boot-java', serverOptions, clientOptions);
|
||||
lc.trace = Trace.Verbose;
|
||||
let disposable = lc.start();
|
||||
context.subscriptions.push(disposable);
|
||||
}
|
||||
else {
|
||||
let options: commons.ActivatorOptions = {
|
||||
DEBUG: false,
|
||||
extensionId: 'vscode-boot-java',
|
||||
fatJarFile: 'target/vscode-boot-java-0.0.1-SNAPSHOT.jar',
|
||||
clientOptions: {
|
||||
documentSelector: ['java'],
|
||||
synchronize: {
|
||||
configurationSection: 'vscode-boot-java'
|
||||
}
|
||||
}
|
||||
};
|
||||
commons.activate(options, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* 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
|
||||
*
|
||||
* Contributors:
|
||||
* Pivotal, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.net.SocketAddress;
|
||||
import java.nio.channels.AsynchronousServerSocketChannel;
|
||||
import java.nio.channels.AsynchronousSocketChannel;
|
||||
import java.nio.channels.Channels;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.eclipse.lsp4j.jsonrpc.Launcher;
|
||||
import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.STS4LanguageClient;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class StartupServer {
|
||||
|
||||
public static void main(String[] args) throws InterruptedException, IOException {
|
||||
|
||||
JavaProjectFinder javaProjectFinder = BootJavaLanguageServer.DEFAULT_PROJECT_FINDER;
|
||||
SimpleLanguageServer languageServer = new BootJavaLanguageServer(javaProjectFinder);
|
||||
|
||||
Function<MessageConsumer, MessageConsumer> wrapper = consumer -> {
|
||||
MessageConsumer result = consumer;
|
||||
return result;
|
||||
};
|
||||
|
||||
Launcher<STS4LanguageClient> launcher = createSocketLauncher(languageServer, STS4LanguageClient.class, new InetSocketAddress("localhost", 5007), Executors.newCachedThreadPool(), wrapper);
|
||||
|
||||
languageServer.connect(launcher.getRemoteProxy());
|
||||
Future<?> future = launcher.startListening();
|
||||
while (!future.isDone()) {
|
||||
Thread.sleep(10_000l);
|
||||
}
|
||||
}
|
||||
|
||||
private static <T> Launcher<T> createSocketLauncher(Object localService, Class<T> remoteInterface, SocketAddress socketAddress, ExecutorService executorService, Function<MessageConsumer, MessageConsumer> wrapper) throws IOException {
|
||||
AsynchronousServerSocketChannel serverSocket = AsynchronousServerSocketChannel.open().bind(socketAddress);
|
||||
AsynchronousSocketChannel socketChannel;
|
||||
try {
|
||||
socketChannel = serverSocket.accept().get();
|
||||
return Launcher.createIoLauncher(localService, remoteInterface, Channels.newInputStream(socketChannel), Channels.newOutputStream(socketChannel), executorService, wrapper);
|
||||
} catch (InterruptedException | ExecutionException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user