Skip to content

Commit

Permalink
Initial changes to support semantic highlighting
Browse files Browse the repository at this point in the history
Closes eclipse-jdtls#715.

Signed-off-by: Akos Kitta <kittaakos@typefox.io>
  • Loading branch information
Akos Kitta committed Jul 18, 2018
1 parent b695ed2 commit 957340b
Show file tree
Hide file tree
Showing 21 changed files with 3,665 additions and 71 deletions.
45 changes: 45 additions & 0 deletions jdt.ls.socket-stream.launch
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.pde.ui.RuntimeWorkbench">
<setAttribute key="additional_plugins"/>
<booleanAttribute key="append.args" value="true"/>
<stringAttribute key="application" value="org.eclipse.jdt.ls.core.id1"/>
<booleanAttribute key="askclear" value="false"/>
<booleanAttribute key="automaticAdd" value="true"/>
<booleanAttribute key="automaticValidate" value="false"/>
<stringAttribute key="bootstrap" value=""/>
<stringAttribute key="checked" value="[NONE]"/>
<booleanAttribute key="clearConfig" value="false"/>
<booleanAttribute key="clearws" value="true"/>
<booleanAttribute key="clearwslog" value="false"/>
<stringAttribute key="configLocation" value="${workspace_loc}/.metadata/.plugins/org.eclipse.pde.core/jdt.ls.socket-stream"/>
<booleanAttribute key="default" value="false"/>
<stringAttribute key="deselected_workspace_plugins" value="org.eclipse.jdt.ls.tests,org.eclipse.jdt.ui"/>
<stringAttribute key="featureDefaultLocation" value="workspace"/>
<stringAttribute key="featurePluginResolution" value="workspace"/>
<booleanAttribute key="includeOptional" value="false"/>
<stringAttribute key="location" value="${workspace_loc}/../runtime-JDT-LS"/>
<mapAttribute key="org.eclipse.debug.core.environmentVariables">
<mapEntry key="CLIENT_HOST" value="127.0.0.1"/>
<mapEntry key="CLIENT_PORT" value="5036"/>
<mapEntry key="socket.stream.debug" value="true"/>
</mapAttribute>
<listAttribute key="org.eclipse.debug.ui.favoriteGroups">
<listEntry value="org.eclipse.debug.ui.launchGroup.debug"/>
</listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.ATTR_USE_START_ON_FIRST_THREAD" value="true"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
<stringAttribute key="org.eclipse.jdt.launching.PROGRAM_ARGUMENTS" value="-os ${target.os} -ws ${target.ws} -arch ${target.arch} -nl ${target.nl} -consoleLog"/>
<stringAttribute key="org.eclipse.jdt.launching.SOURCE_PATH_PROVIDER" value="org.eclipse.pde.ui.workbenchClasspathProvider"/>
<stringAttribute key="pde.version" value="3.3"/>
<stringAttribute key="product" value="org.eclipse.sdk.ide"/>
<setAttribute key="selected_features"/>
<stringAttribute key="selected_target_plugins" value="com.google.gson@default:default,com.google.guava*15.0.0.v201403281430@default:default,com.google.guava*21.0.0.v20170206-1425@default:default,com.gradleware.tooling.client@default:default,com.gradleware.tooling.model@default:default,com.gradleware.tooling.utils@default:default,com.ibm.icu.base@default:default,javax.inject@default:default,javax.xml@default:default,org.apache.ant@default:default,org.apache.commons.io@default:default,org.apache.commons.lang3@default:default,org.apache.log4j@default:default,org.eclipse.buildship.core@default:default,org.eclipse.compare.core@default:default,org.eclipse.core.commands@default:default,org.eclipse.core.contenttype@default:default,org.eclipse.core.expressions@default:default,org.eclipse.core.filebuffers@default:default,org.eclipse.core.filesystem.macosx@default:false,org.eclipse.core.filesystem@default:default,org.eclipse.core.jobs@default:default,org.eclipse.core.net@default:default,org.eclipse.core.resources@default:default,org.eclipse.core.runtime@default:true,org.eclipse.core.variables@default:default,org.eclipse.debug.core@default:default,org.eclipse.equinox.app@default:default,org.eclipse.equinox.common@2:true,org.eclipse.equinox.frameworkadmin.equinox@default:default,org.eclipse.equinox.frameworkadmin@default:default,org.eclipse.equinox.preferences@default:default,org.eclipse.equinox.region@default:false,org.eclipse.equinox.registry@default:default,org.eclipse.equinox.security.macosx@default:false,org.eclipse.equinox.security@default:default,org.eclipse.equinox.simpleconfigurator.manipulator@default:default,org.eclipse.equinox.simpleconfigurator@1:true,org.eclipse.equinox.transforms.hook@default:false,org.eclipse.equinox.weaving.hook@default:false,org.eclipse.jdt.apt.core@default:default,org.eclipse.jdt.apt.pluggable.core@default:default,org.eclipse.jdt.compiler.apt@default:false,org.eclipse.jdt.compiler.tool@default:false,org.eclipse.jdt.core.manipulation@default:default,org.eclipse.jdt.core@default:default,org.eclipse.jdt.debug@default:default,org.eclipse.jdt.junit.core@default:default,org.eclipse.jdt.junit.runtime@default:default,org.eclipse.jdt.launching@default:default,org.eclipse.jface.text@default:default,org.eclipse.jface@default:default,org.eclipse.lsp4j.jsonrpc@default:default,org.eclipse.lsp4j@default:default,org.eclipse.ltk.core.refactoring@default:default,org.eclipse.m2e.archetype.common@default:default,org.eclipse.m2e.core@default:default,org.eclipse.m2e.jdt@default:default,org.eclipse.m2e.lifecyclemapping.defaults@default:default,org.eclipse.m2e.maven.indexer@default:default,org.eclipse.m2e.maven.runtime.slf4j.simple@default:default,org.eclipse.m2e.maven.runtime@default:default,org.eclipse.m2e.workspace.cli@default:default,org.eclipse.osgi.compatibility.state@default:false,org.eclipse.osgi.services@default:default,org.eclipse.osgi.util@default:default,org.eclipse.osgi@-1:true,org.eclipse.swt.cocoa.macosx.x86_64@default:false,org.eclipse.swt@default:default,org.eclipse.text@default:default,org.eclipse.xtend.lib.macro@default:default,org.eclipse.xtend.lib@default:default,org.eclipse.xtext.logging@default:false,org.eclipse.xtext.xbase.lib@default:default,org.gradle.toolingapi@default:default,org.hamcrest.core@default:default,org.jboss.tools.maven.apt.core@default:default,org.junit@default:default,org.slf4j.api@default:default"/>
<stringAttribute key="selected_workspace_plugins" value="org.eclipse.jdt.ls.core@default:default"/>
<booleanAttribute key="show_selected_only" value="false"/>
<stringAttribute key="templateConfig" value="${target_home}/configuration/config.ini"/>
<booleanAttribute key="tracing" value="false"/>
<booleanAttribute key="useCustomFeatures" value="false"/>
<booleanAttribute key="useDefaultConfig" value="true"/>
<booleanAttribute key="useDefaultConfigArea" value="true"/>
<booleanAttribute key="useProduct" value="false"/>
</launchConfiguration>
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,6 @@ public OutputStream getOutputStream() throws IOException {
}

private StreamProvider provider;

/**
*
* @return
Expand All @@ -99,10 +98,9 @@ public StreamProvider getSelectedStream() {
}

private StreamProvider createProvider() {
final String host = Environment.get("CLIENT_HOST", "localhost");
final String port = Environment.get("CLIENT_PORT");
Integer port = JDTEnvironmentUtils.getClientPort();
if (port != null) {
return new SocketStreamProvider(host, Integer.parseInt(port));
return new SocketStreamProvider(JDTEnvironmentUtils.getClientHost(), port);
}
return new StdIOStreamProvider();
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
/*******************************************************************************
* Copyright (c) 2018 TypeFox 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
*
* Contributors:
* TypeFox - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.ls.core.internal;

import org.eclipse.core.runtime.Platform;

import com.google.common.base.Preconditions;

public class JDTEnvironmentUtils {

public static final String CLIENT_PORT = "CLIENT_PORT";
public static final String CLIENT_HOST = "CLIENT_HOST";
public static final String DEFAULT_CLIENT_HOST = "localhost";

/**
* Environment variable indicating that the JDT LS has to be started with a
* socket stream. In this case, it is the JDT LS that starts and waits until the
* client connects to it.
*/
public static final String SOCKET_STREAM_DEBUG = "socket.stream.debug";

/**
* Returns with the client port if set. Otherwise, returns with {@code null}.
* Throw an {@link IllegalStateException} if the port is set but it has an
* invalid port number.
*
* When the client port environment variable is set to a valid port number, then
* plain socket communication will be used between the language client and the
* server instead of the standard IO stream one.
*/
public static Integer getClientPort() {
final String port = Environment.get(CLIENT_PORT);
if (port != null) {
int clientPort = Integer.parseInt(port);
Preconditions.checkState(clientPort > 1 && clientPort < 65535, "The port must be an integer between 1 and 65535. It was: '" + port + "'.");
return clientPort;
}
return null;
}

/**
* Returns with the client host. Defaults to {@code localhost} if not set. Has
* absolutely no effect, if this is set but the {@code CLIENT_PORT} is not.
*/
public static String getClientHost() {
return Environment.get(CLIENT_HOST);
}

/**
* Has no effect, and always returns with {@code false} if the JDT LS has been
* started from the source either in debug or development mode. If the
* {@code CLIENT_HOST} and {@code CLIENT_PORT} environment variables are set and
* the {@link JDTEnvironmentUtils#SOCKET_STREAM_DEBUG socket.stream.debug} is
* set to {@code true}, the the server will start with plain socket connection
* and will wait until the client connects.
*
* @return
*/
public static boolean inSocketStreamDebugMode() {
return Boolean.parseBoolean(Environment.get(SOCKET_STREAM_DEBUG, "false")) && (Platform.inDebugMode() || Platform.inDevelopmentMode()) && getClientHost() != null && getClientPort() != null;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
import org.eclipse.lsp4j.MessageType;
import org.eclipse.lsp4j.PublishDiagnosticsParams;
import org.eclipse.lsp4j.RegistrationParams;
import org.eclipse.lsp4j.SemanticHighlightingParams;
import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.lsp4j.UnregistrationParams;
import org.eclipse.lsp4j.WorkspaceEdit;
Expand Down Expand Up @@ -191,6 +192,13 @@ public void registerCapability(RegistrationParams params) {
client.registerCapability(params);
}

/**
* @see {@link LanguageClient#semanticHighlighting(SemanticHighlightingParams)}
*/
public void semanticHighlighting(SemanticHighlightingParams params) {
client.semanticHighlighting(params);
}

public void disconnect() {
if (logHandler != null) {
logHandler.uninstall();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,21 @@
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.PasswordAuthentication;
import java.nio.channels.AsynchronousServerSocketChannel;
import java.nio.channels.AsynchronousSocketChannel;
import java.nio.channels.Channels;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Hashtable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.function.Function;

import org.apache.commons.lang3.StringUtils;
import org.eclipse.core.internal.net.ProxySelector;
Expand All @@ -46,6 +54,7 @@
import org.eclipse.jdt.ls.core.internal.managers.ProjectsManager;
import org.eclipse.jdt.ls.core.internal.preferences.PreferenceManager;
import org.eclipse.lsp4j.jsonrpc.Launcher;
import org.eclipse.lsp4j.jsonrpc.MessageConsumer;
import org.osgi.framework.Bundle;
import org.osgi.framework.BundleContext;
import org.osgi.framework.BundleException;
Expand Down Expand Up @@ -237,13 +246,30 @@ public IProxyService getProxyService() {
}

private void startConnection() throws IOException {
Launcher<JavaLanguageClient> launcher;
ExecutorService executorService = Executors.newCachedThreadPool();
protocol = new JDTLanguageServer(projectsManager, preferenceManager);
ConnectionStreamFactory connectionFactory = new ConnectionStreamFactory();
Launcher<JavaLanguageClient> launcher = Launcher.createLauncher(protocol,
JavaLanguageClient.class,
connectionFactory.getInputStream(),
connectionFactory.getOutputStream(),
Executors.newCachedThreadPool(), new ParentProcessWatcher(this.languageServer));
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();
}
Expand Down
Loading

0 comments on commit 957340b

Please sign in to comment.