下面列出了org.eclipse.lsp4j.services.LanguageClient#org.eclipse.lsp4j.services.LanguageServer 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。
/**
* Gets list of LS initialized for given project
*
* @param onlyActiveLS true if this method should return only the already running
* language servers, otherwise previously started language servers
* will be re-activated
* @return list of Language Servers
*/
@Nonnull
public List<LanguageServer> getLanguageServers(@Nullable Module project,
Predicate<ServerCapabilities> request, boolean onlyActiveLS) {
List<LanguageServer> serverInfos = new ArrayList<>();
for (LanguageServerWrapper wrapper : startedServers) {
if ((!onlyActiveLS || wrapper.isActive()) && (project == null || wrapper.canOperate(project))) {
@Nullable
LanguageServer server = wrapper.getServer();
if (server == null) {
continue;
}
if (request == null
|| wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
|| request.test(wrapper.getServerCapabilities())) {
serverInfos.add(server);
}
}
}
return serverInfos;
}
@Override
public void handleMessage(Message message, LanguageServer languageServer, URI rootUri) {
IPreferenceStore preferenceStore = Activator.getDefault().getPreferenceStore();
String schemaStr = preferenceStore.getString(YAMLPreferenceInitializer.YAML_SCHEMA_PREFERENCE);
if (cachedSchema == null || !schemaStr.equals(cachedSchema)) {
cachedSchema = schemaStr;
Map<String, Object> schemas = new Gson().fromJson(schemaStr, new TypeToken<HashMap<String, Object>>() {}.getType());
Map<String, Object> yaml = new HashMap<>();
yaml.put("schemas", schemas);
yaml.put("validate", true);
yaml.put("completion", true);
yaml.put("hover", true);
Map<String, Object> settings = new HashMap<>();
settings.put("yaml", yaml);
DidChangeConfigurationParams params = new DidChangeConfigurationParams(settings);
languageServer.getWorkspaceService().didChangeConfiguration(params);
}
}
@Override
public void handleMessage(Message message, LanguageServer languageServer, URI rootUri) {
if (message instanceof ResponseMessage) {
ResponseMessage responseMessage = (ResponseMessage) message;
if (responseMessage.getResult() instanceof InitializeResult) {
Map<String, Object> htmlOptions = new HashMap<>();
Map<String, Object> validateOptions = new HashMap<>();
validateOptions.put("scripts", true);
validateOptions.put("styles", true);
htmlOptions.put("validate", validateOptions);
htmlOptions.put("format", Collections.singletonMap("enable", Boolean.TRUE));
Map<String, Object> html = new HashMap<>();
html.put("html", htmlOptions);
DidChangeConfigurationParams params = new DidChangeConfigurationParams(html);
languageServer.getWorkspaceService().didChangeConfiguration(params);
}
}
}
@Before
public void setUp() throws IOException {
this.client = mock(ExecuteCommandProposedClient.class);
PipedOutputStream clientWritesTo = new PipedOutputStream();
PipedInputStream clientReadsFrom = new PipedInputStream();
PipedInputStream serverReadsFrom = new PipedInputStream();
PipedOutputStream serverWritesTo = new PipedOutputStream();
serverWritesTo.connect(clientReadsFrom);
clientWritesTo.connect(serverReadsFrom);
this.closeables = new Closeable[] { clientWritesTo, clientReadsFrom, serverReadsFrom, serverWritesTo };
Launcher<JavaLanguageClient> serverLauncher = Launcher.createLauncher(new Object(), JavaLanguageClient.class, serverReadsFrom, serverWritesTo);
serverLauncher.startListening();
Launcher<LanguageServer> clientLauncher = Launcher.createLauncher(client, LanguageServer.class, clientReadsFrom, clientWritesTo);
clientLauncher.startListening();
this.clientConnection = serverLauncher.getRemoteProxy();
}
@Before public void setup() throws IOException {
PipedInputStream inClient = new PipedInputStream();
PipedOutputStream outClient = new PipedOutputStream();
PipedInputStream inServer = new PipedInputStream();
PipedOutputStream outServer = new PipedOutputStream();
inClient.connect(outServer);
outClient.connect(inServer);
server = new AssertingEndpoint();
serverLauncher = LSPLauncher.createServerLauncher(ServiceEndpoints.toServiceObject(server, LanguageServer.class), inServer, outServer);
serverListening = serverLauncher.startListening();
client = new AssertingEndpoint();
clientLauncher = LSPLauncher.createClientLauncher(ServiceEndpoints.toServiceObject(client, LanguageClient.class), inClient, outClient);
clientListening = clientLauncher.startListening();
Logger logger = Logger.getLogger(StreamMessageProducer.class.getName());
logLevel = logger.getLevel();
logger.setLevel(Level.SEVERE);
}
@Test public void testDocumentResolve() throws Exception, ExecutionException {
LanguageServer languageServer = wrap(LanguageServer.class, new MockLanguageServer() {
@Override
public CompletableFuture<DocumentLink> documentLinkResolve(DocumentLink params) {
return CompletableFutures.computeAsync(canceler -> {
params.setTarget("resolved");
return params;
});
}
});
CompletableFuture<DocumentLink> future = languageServer.getTextDocumentService().documentLinkResolve(
new DocumentLink(new Range(new Position(0, 0), new Position(0, 0)), "unresolved")
);
DocumentLink resolved = future.get(TIMEOUT, TimeUnit.MILLISECONDS);
Assert.assertEquals("resolved", resolved.getTarget());
}
public DefaultRequestManager(LanguageServerWrapper wrapper, LanguageServer server, LanguageClient client,
ServerCapabilities serverCapabilities) {
this.wrapper = wrapper;
this.server = server;
this.client = client;
this.serverCapabilities = serverCapabilities;
textDocumentOptions = serverCapabilities.getTextDocumentSync().isRight() ?
serverCapabilities.getTextDocumentSync().getRight() : null;
workspaceService = server.getWorkspaceService();
textDocumentService = server.getTextDocumentService();
}
/**
* @return the LanguageServer
*/
@Nullable
public LanguageServer getServer() {
start();
if (initializeFuture != null && !initializeFuture.isDone()) {
initializeFuture.join();
}
return languageServer;
}
public LSIncompleteCompletionProposal(Editor editor, int offset, CompletionItem item, LanguageServer languageServer) {
this.item = item;
this.editor = editor;
this.languageServer = languageServer;
this.initialOffset = offset;
this.currentOffset = offset;
this.bestOffset = getPrefixCompletionStart(editor.getDocument(), offset);
putUserData(CodeCompletionHandlerBase.DIRECT_INSERTION, true);
}
@SuppressWarnings("unchecked")
@Override
public Class<? extends LanguageServer> getServerInterface() {
String serverInterface = extension.serverInterface;
if (serverInterface != null && !serverInterface.isEmpty()) {
try {
return (Class<? extends LanguageServer>) (Class<?>)extension.findClass(serverInterface);
} catch (ClassNotFoundException exception) {
LOGGER.warn(exception.getLocalizedMessage(), exception);
}
}
return super.getServerInterface();
}
public @Nonnull
List<CompletableFuture<LanguageServer>> getInitializedLanguageServers(@Nonnull VirtualFile file,
@Nullable Predicate<ServerCapabilities> request) throws IOException {
synchronized (startedServers) {
Collection<LanguageServerWrapper> wrappers = getLSWrappers(file, request);
return wrappers.stream().map(wrapper -> wrapper.getInitializedServer().thenApplyAsync(server -> {
try {
wrapper.connect(file, null);
} catch (IOException e) {
LOGGER.warn(e.getLocalizedMessage(), e);
}
return server;
})).collect(Collectors.toList());
}
}
/**
* Get the requested language server instance for the given file. Starts the language server if not already started.
*
* @param file
* @param lsDefinition
* @param capabilitiesPredicate a predicate to check capabilities
* @return a LanguageServer for the given file, which is defined with provided server ID and conforms to specified request
* @deprecated use {@link #getInitializedLanguageServer(IFile, LanguageServerDefinition, Predicate)} instead.
*/
@Deprecated
public LanguageServer getLanguageServer(@Nonnull VirtualFile file, @Nonnull LanguageServersRegistry.LanguageServerDefinition lsDefinition,
Predicate<ServerCapabilities> capabilitiesPredicate)
throws IOException {
LanguageServerWrapper wrapper = getLSWrapperForConnection(LSPIJUtils.getProject(file), lsDefinition, LSPIJUtils.toUri(file));
if (capabilitiesPredicate == null
|| wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
|| capabilitiesPredicate.test(wrapper.getServerCapabilities())) {
wrapper.connect(file, null);
return wrapper.getServer();
}
return null;
}
/**
* Get the requested language server instance for the given file. Starts the language server if not already started.
*
* @param file
* @param lsDefinition
* @param capabilitiesPredicate a predicate to check capabilities
* @return a LanguageServer for the given file, which is defined with provided server ID and conforms to specified request
*/
public CompletableFuture<LanguageServer> getInitializedLanguageServer(@Nonnull VirtualFile file,
@Nonnull LanguageServersRegistry.LanguageServerDefinition lsDefinition,
Predicate<ServerCapabilities> capabilitiesPredicate)
throws IOException {
LanguageServerWrapper wrapper = getLSWrapperForConnection(LSPIJUtils.getProject(file), lsDefinition, LSPIJUtils.toUri(file));
if (capabilitiesPredicate == null
|| wrapper.getServerCapabilities() == null /* null check is workaround for https://github.com/TypeFox/ls-api/issues/47 */
|| capabilitiesPredicate.test(wrapper.getServerCapabilities())) {
wrapper.connect(file, null);
return wrapper.getInitializedServer();
}
return null;
}
/**
* @param document
* @param filter
* @return
* @since 0.9
*/
@Nonnull
public CompletableFuture<List<LanguageServer>> getLanguageServers(@Nonnull Document document,
Predicate<ServerCapabilities> filter) {
URI uri = LSPIJUtils.toUri(document);
if (uri == null) {
return CompletableFuture.completedFuture(Collections.emptyList());
}
final List<LanguageServer> res = Collections.synchronizedList(new ArrayList<>());
try {
return CompletableFuture.allOf(getLSWrappers(document).stream().map(wrapper ->
wrapper.getInitializedServer().thenComposeAsync(server -> {
if (server != null && (filter == null || filter.test(wrapper.getServerCapabilities()))) {
try {
return wrapper.connect(document);
} catch (IOException ex) {
LOGGER.warn(ex.getLocalizedMessage(), ex);
}
}
return CompletableFuture.completedFuture(null);
}).thenAccept(server -> {
if (server != null) {
res.add(server);
}
})).toArray(CompletableFuture[]::new)).thenApply(theVoid -> res);
} catch (final Exception e) {
LOGGER.warn(e.getLocalizedMessage(), e);
}
return CompletableFuture.completedFuture(Collections.emptyList());
}
/**
*
* @param document
* @return null if not connection has happened, a future tracking the connection state otherwise
* @throws IOException
*/
public @Nullable CompletableFuture<LanguageServer> connect(Document document) throws IOException {
VirtualFile file = LSPIJUtils.getFile(document);
if (file != null && file.exists()) {
return connect(file, document);
} else {
URI uri = LSPIJUtils.toUri(document);
if (uri != null) {
return connect(uri, document);
}
}
return null;
}
/**
* Starts and returns the language server, regardless of if it is initialized.
* If not in the UI Thread, will wait to return the initialized server.
*
* @deprecated use {@link #getInitializedServer()} instead.
*/
@Deprecated
@Nullable
public LanguageServer getServer() {
CompletableFuture<LanguageServer> languagServerFuture = getInitializedServer();
if (ApplicationManager.getApplication().isDispatchThread()) { // UI Thread
return this.languageServer;
} else {
return languagServerFuture.join();
}
}
/**
* Starts the language server and returns a CompletableFuture waiting for the
* server to be initialized. If done in the UI stream, a job will be created
* displaying that the server is being initialized
*/
@Nonnull
public CompletableFuture<LanguageServer> getInitializedServer() {
try {
start();
} catch (IOException ex) {
LOGGER.warn(ex.getLocalizedMessage(), ex);
}
if (initializeFuture != null && !this.initializeFuture.isDone()) {
/*if (ApplicationManager.getApplication().isDispatchThread()) { // UI Thread
try {
ProgressManager.getInstance().run(new Task.WithResult<Void, Exception>(null, Messages.initializeLanguageServer_job, false) {
@Override
protected Void compute(@NotNull ProgressIndicator indicator) throws Exception {
indicator.setText("Waiting for server " + LanguageServerWrapper.this.serverDefinition.id + " to be started");
initializeFuture.join();
return null;
}
});
} catch (Exception e) {
LOGGER.error(e.getLocalizedMessage(), e);
}
}*/
return initializeFuture.thenApply(r -> this.languageServer);
}
return CompletableFuture.completedFuture(this.languageServer);
}
private static boolean executeCommandServerSide(Project project, Command command, String languageServerId,
Document document) {
if (languageServerId == null) {
return false;
}
LanguageServersRegistry.LanguageServerDefinition languageServerDefinition = LanguageServersRegistry.getInstance()
.getDefinition(languageServerId);
if (languageServerDefinition == null) {
return false;
}
try {
CompletableFuture<LanguageServer> languageServerFuture = getLanguageServerForCommand(project, command, document,
languageServerDefinition);
if (languageServerFuture == null) {
return false;
}
// Server can handle command
languageServerFuture.thenAcceptAsync(server -> {
ExecuteCommandParams params = new ExecuteCommandParams();
params.setCommand(command.getCommand());
params.setArguments(command.getArguments());
server.getWorkspaceService().executeCommand(params);
});
return true;
} catch (IOException e) {
// log and let the code fall through for LSPEclipseUtils to handle
LOGGER.warn(e.getLocalizedMessage(), e);
return false;
}
}
private static CompletableFuture<LanguageServer> getLanguageServerForCommand(Project project,
Command command,
Document document, LanguageServersRegistry.LanguageServerDefinition languageServerDefinition) throws IOException {
CompletableFuture<LanguageServer> languageServerFuture = LanguageServiceAccessor.getInstance(project)
.getInitializedLanguageServer(document, languageServerDefinition, serverCapabilities -> {
ExecuteCommandOptions provider = serverCapabilities.getExecuteCommandProvider();
return provider != null && provider.getCommands().contains(command.getCommand());
});
return languageServerFuture;
}
@Override
public void handleMessage(Message message, LanguageServer languageServer, URI rootUri) {
if (message instanceof ResponseMessage) {
ResponseMessage responseMessage = (ResponseMessage)message;
if (responseMessage.getResult() instanceof InitializeResult) {
// enable validation: so far, no better way found than changing conf after init.
DidChangeConfigurationParams params = new DidChangeConfigurationParams(getInitializationOptions(rootUri));
languageServer.getWorkspaceService().didChangeConfiguration(params);
}
}
}
@Override
public void handleMessage(Message message, LanguageServer languageServer, URI rootUri) {
if (message instanceof ResponseMessage) {
ResponseMessage responseMessage = (ResponseMessage) message;
if (responseMessage.getResult() instanceof InitializeResult) {
// Send json/schemaAssociations notification to register JSON Schema on JSON
// Language server side.
JSonLanguageServerInterface server = (JSonLanguageServerInterface) languageServer;
Map<String, List<String>> schemaAssociations = getSchemaAssociations();
server.sendJSonchemaAssociations(schemaAssociations);
}
}
}
@Messages("LBL_Connecting=Connecting to language server")
public static void addBindings(FileObject root, int port, String... extensions) {
BaseProgressUtils.showProgressDialogAndRun(() -> {
try {
Socket s = new Socket(InetAddress.getLocalHost(), port);
LanguageClientImpl lc = new LanguageClientImpl();
InputStream in = s.getInputStream();
OutputStream out = s.getOutputStream();
Launcher<LanguageServer> launcher = LSPLauncher.createClientLauncher(lc, in, new OutputStream() {
@Override
public void write(int w) throws IOException {
out.write(w);
if (w == '\n')
out.flush();
}
});
launcher.startListening();
LanguageServer server = launcher.getRemoteProxy();
InitializeResult result = initServer(null, server, root);
LSPBindings bindings = new LSPBindings(server, result, null);
lc.setBindings(bindings);
workspace2Extension2Server.put(root, Arrays.stream(extensions).collect(Collectors.toMap(k -> k, v -> bindings)));
} catch (InterruptedException | ExecutionException | IOException ex) {
Exceptions.printStackTrace(ex);
}
}, Bundle.LBL_Connecting());
}
private static InitializeResult initServer(Process p, LanguageServer server, FileObject root) throws InterruptedException, ExecutionException {
InitializeParams initParams = new InitializeParams();
initParams.setRootUri(Utils.toURI(root));
initParams.setRootPath(FileUtil.toFile(root).getAbsolutePath()); //some servers still expect root path
initParams.setProcessId(0);
TextDocumentClientCapabilities tdcc = new TextDocumentClientCapabilities();
DocumentSymbolCapabilities dsc = new DocumentSymbolCapabilities();
dsc.setHierarchicalDocumentSymbolSupport(true);
dsc.setSymbolKind(new SymbolKindCapabilities(Arrays.asList(SymbolKind.values())));
tdcc.setDocumentSymbol(dsc);
WorkspaceClientCapabilities wcc = new WorkspaceClientCapabilities();
wcc.setWorkspaceEdit(new WorkspaceEditCapabilities());
wcc.getWorkspaceEdit().setDocumentChanges(true);
wcc.getWorkspaceEdit().setResourceOperations(Arrays.asList(ResourceOperationKind.Create, ResourceOperationKind.Delete, ResourceOperationKind.Rename));
initParams.setCapabilities(new ClientCapabilities(wcc, tdcc, null));
CompletableFuture<InitializeResult> initResult = server.initialize(initParams);
while (true) {
try {
return initResult.get(100, TimeUnit.MILLISECONDS);
} catch (TimeoutException ex) {
if (p != null && !p.isAlive()) {
InitializeResult emptyResult = new InitializeResult();
emptyResult.setCapabilities(new ServerCapabilities());
return emptyResult;
}
}
}
}
@Override
public CompletableFuture<Void> start(File rootPath) {
setStatus(STARTING);
this.client = new LSPClient(this.startupLogic);
this.rootPath = rootPath;
try {
var processedArgs = this.argumentPreprocessor.apply(this, new ArrayList<>(this.lspArgs));
var streamConnectionProvider = new LSPProvider(
() -> requestManager,
processedArgs,
serverPath.get());
streamConnectionProvider.start();
Launcher<LanguageServer> launcher =
Launcher.createLauncher(client, LanguageServer.class, streamConnectionProvider.getInputStream(), streamConnectionProvider.getOutputStream());
languageServer = launcher.getRemoteProxy();
client.connect(languageServer);
launcherFuture = launcher.startListening();
return (startingFuture = languageServer.initialize(getInitParams()).thenApply(res -> {
LOGGER.info("Started LSP");
requestManager = new DefaultRequestManager(this, languageServer, client, res.getCapabilities());
setStatus(STARTED);
requestManager.initialized(new InitializedParams());
setStatus(INITIALIZED);
return res;
}).thenRun(() -> LOGGER.info("Done starting LSP!")));
} catch (Exception e) {
LOGGER.error("Can't launch language server for project", e);
}
return CompletableFuture.runAsync(() -> {});
}
public DefaultRequestManager(LanguageServerWrapper wrapper, LanguageServer server, LanguageClient client,
ServerCapabilities serverCapabilities) {
this.wrapper = wrapper;
this.server = server;
this.client = client;
this.serverCapabilities = serverCapabilities;
textDocumentOptions = serverCapabilities.getTextDocumentSync().isRight() ?
serverCapabilities.getTextDocumentSync().getRight() :
null;
workspaceService = server.getWorkspaceService();
textDocumentService = server.getTextDocumentService();
}
@Test
public void testLSFound()
throws IOException, CoreException, InterruptedException, ExecutionException, TimeoutException {
IProject project = getProject(BASIC_PROJECT_NAME);
IFile rustFile = project.getFolder("src").getFile("main.rs");
CompletableFuture<LanguageServer> languageServer = LanguageServiceAccessor
.getInitializedLanguageServers(rustFile, capabilities -> capabilities.getHoverProvider() != null)
.iterator().next();
String uri = rustFile.getLocationURI().toString();
Either<List<CompletionItem>, CompletionList> completionItems = languageServer.get(1, TimeUnit.MINUTES)
.getTextDocumentService()
.completion(new CompletionParams(new TextDocumentIdentifier(uri), new Position(1, 4)))
.get(1, TimeUnit.MINUTES);
Assert.assertNotNull(completionItems);
}
private static LanguageServer getLanguageClient(LSPDocumentInfo info) {
try {
return info.getInitializedLanguageClient().get();
} catch (InterruptedException | ExecutionException e) {
CorrosionPlugin.logError(e);
return null;
}
}
public static void main(String[] args) throws Exception {
Injector injector = Guice.createInjector(new ServerModule());
LanguageServer languageServer = injector.getInstance(LanguageServer.class);
ServerSocketChannel serverSocket = ServerSocketChannel.open();
serverSocket.bind(new InetSocketAddress("localhost", 5007));
SocketChannel socketChannel = serverSocket.accept();
Launcher<LanguageClient> launcher = LSPLauncher.createServerLauncher(languageServer, Channels.newInputStream(socketChannel), Channels.newOutputStream(socketChannel), true, new PrintWriter(System.out));
launcher.startListening().get();
}
@Override
protected void configure() {
binder().bind(ExecutorService.class).toProvider(ExecutorServiceProvider.class);
bind(LanguageServer.class).to(LanguageServerImpl.class);
bind(IResourceServiceProvider.Registry.class).toProvider(ResourceServiceProviderServiceLoader.class);
bind(IMultiRootWorkspaceConfigFactory.class).to(MultiRootWorkspaceConfigFactory.class);
bind(IProjectDescriptionFactory.class).to(DefaultProjectDescriptionFactory.class);
bind(IContainer.Manager.class).to(ProjectDescriptionBasedContainerManager.class);
}
/**
* Create a new Launcher for a language server and an input and output stream.
*
* @param server - the server that receives method calls from the remote client
* @param in - input stream to listen for incoming messages
* @param out - output stream to send outgoing messages
*/
public static Launcher<LanguageClient> createServerLauncher(LanguageServer server, InputStream in, OutputStream out) {
return new Builder<LanguageClient>()
.setLocalService(server)
.setRemoteInterface(LanguageClient.class)
.setInput(in)
.setOutput(out)
.create();
}