Fix NPE in STS4LanguageClient related to classpath infra

Also improve test coverage around this breakage. And
improve the debugability of the tests by improving how
they log configure logger.
This commit is contained in:
Kris De Volder
2018-05-11 12:31:03 -07:00
parent 27551f6762
commit b3a61025a5
12 changed files with 258 additions and 120 deletions

View File

@@ -41,6 +41,7 @@ import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.progress.UIJob;
import org.eclipse.ui.texteditor.AbstractTextEditor;
import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathListenerHandler;
import com.google.common.collect.ImmutableList;
@@ -49,8 +50,10 @@ import com.google.common.collect.ImmutableMap;
@SuppressWarnings("restriction")
public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4LanguageClient {
private static ReusableClasspathListenerHandler classpathService = new ReusableClasspathListenerHandler(new LSP4ECommandExecutor());
private static ReusableClasspathListenerHandler classpathService = new ReusableClasspathListenerHandler(
Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance),
new LSP4ECommandExecutor()
);
public STS4LanguageClientImpl() {
System.out.println("Instantiatin STS4LanguageClientImpl");

View File

@@ -0,0 +1,59 @@
eclipse.preferences.version=1
editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true
sp_cleanup.add_default_serial_version_id=true
sp_cleanup.add_generated_serial_version_id=false
sp_cleanup.add_missing_annotations=true
sp_cleanup.add_missing_deprecated_annotations=true
sp_cleanup.add_missing_methods=false
sp_cleanup.add_missing_nls_tags=false
sp_cleanup.add_missing_override_annotations=true
sp_cleanup.add_missing_override_annotations_interface_methods=true
sp_cleanup.add_serial_version_id=false
sp_cleanup.always_use_blocks=true
sp_cleanup.always_use_parentheses_in_expressions=false
sp_cleanup.always_use_this_for_non_static_field_access=false
sp_cleanup.always_use_this_for_non_static_method_access=false
sp_cleanup.convert_functional_interfaces=false
sp_cleanup.convert_to_enhanced_for_loop=false
sp_cleanup.correct_indentation=false
sp_cleanup.format_source_code=false
sp_cleanup.format_source_code_changes_only=false
sp_cleanup.insert_inferred_type_arguments=false
sp_cleanup.make_local_variable_final=true
sp_cleanup.make_parameters_final=false
sp_cleanup.make_private_fields_final=true
sp_cleanup.make_type_abstract_if_missing_method=false
sp_cleanup.make_variable_declarations_final=false
sp_cleanup.never_use_blocks=false
sp_cleanup.never_use_parentheses_in_expressions=true
sp_cleanup.on_save_use_additional_actions=true
sp_cleanup.organize_imports=false
sp_cleanup.qualify_static_field_accesses_with_declaring_class=false
sp_cleanup.qualify_static_member_accesses_through_instances_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_through_subtypes_with_declaring_class=true
sp_cleanup.qualify_static_member_accesses_with_declaring_class=false
sp_cleanup.qualify_static_method_accesses_with_declaring_class=false
sp_cleanup.remove_private_constructors=true
sp_cleanup.remove_redundant_type_arguments=false
sp_cleanup.remove_trailing_whitespaces=true
sp_cleanup.remove_trailing_whitespaces_all=true
sp_cleanup.remove_trailing_whitespaces_ignore_empty=false
sp_cleanup.remove_unnecessary_casts=false
sp_cleanup.remove_unnecessary_nls_tags=false
sp_cleanup.remove_unused_imports=false
sp_cleanup.remove_unused_local_variables=false
sp_cleanup.remove_unused_private_fields=true
sp_cleanup.remove_unused_private_members=false
sp_cleanup.remove_unused_private_methods=true
sp_cleanup.remove_unused_private_types=true
sp_cleanup.sort_members=false
sp_cleanup.sort_members_all=false
sp_cleanup.use_anonymous_class_creation=false
sp_cleanup.use_blocks=false
sp_cleanup.use_blocks_only_for_return_and_throw=false
sp_cleanup.use_lambda=true
sp_cleanup.use_parentheses_in_expressions=false
sp_cleanup.use_this_for_non_static_field_access=false
sp_cleanup.use_this_for_non_static_field_access_only_if_necessary=true
sp_cleanup.use_this_for_non_static_method_access=false
sp_cleanup.use_this_for_non_static_method_access_only_if_necessary=true

View File

@@ -12,5 +12,6 @@ Require-Bundle: org.springframework.tooling.jdt.ls.commons,
org.apache.commons.lang3,
org.junit,
org.apache.commons.io,
org.eclipse.swt
org.eclipse.swt,
com.google.guava;bundle-version="21.0.0"

View File

@@ -43,6 +43,8 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.Logger.DefaultLogger;
import org.springframework.tooling.jdt.ls.commons.Logger.TestLogger;
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath;
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath.CPE;
import org.springframework.tooling.jdt.ls.commons.classpath.ClientCommandExecutor;
@@ -50,12 +52,15 @@ import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathLis
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
import org.springsource.ide.eclipse.commons.frameworks.test.util.Asserter;
import com.google.common.collect.ImmutableList;
import junit.framework.AssertionFailedError;
public class ClasspathListenerHandlerTest {
private TestLogger logger = new TestLogger();
private MockClasspathCache classpaths = new MockClasspathCache();
private ReusableClasspathListenerHandler service = new ReusableClasspathListenerHandler(classpaths);
private ReusableClasspathListenerHandler service = new ReusableClasspathListenerHandler(logger, classpaths);
@Test public void classpathIsSentForExistingProject() throws Exception {
String projectName = "classpath-test-simple-java-project";
@@ -82,7 +87,7 @@ public class ClasspathListenerHandlerTest {
assertTrue(cp.getEntries().stream().filter(cpe -> Classpath.isSource(cpe)).count()==1); //has 1 source entry
assertClasspath(cp, cp.getEntries().stream().filter(cpe -> Classpath.isBinary(cpe) && cpe.isSystem()).count()>=1); //has some system libraries
});
Logger.log("=== Deleteing project");
logger.log("=== Deleteing project");
project.delete(false, true, null);
ACondition.waitFor("Project classpath to disapear", Duration.ofSeconds(5), () -> {
Info cp = classpaths.getFor(loc);
@@ -96,7 +101,7 @@ public class ClasspathListenerHandlerTest {
File loc = project.getLocation().toFile();
service.addClasspathListener(classpaths.commandId);
ACondition.waitFor("Project with classpath to appear", Duration.ofSeconds(50), () -> {
ACondition.waitFor("Project with classpath to appear", Duration.ofSeconds(5), () -> {
Classpath cp = classpaths.getFor(loc).classpath;
assertTrue(cp.getEntries().stream().filter(cpe -> Classpath.isSource(cpe)).count()==1); //has 1 source entry
assertClasspath(cp, cp.getEntries().stream().filter(cpe -> Classpath.isBinary(cpe) && cpe.isSystem()).count()>=1); //has some system libraries
@@ -105,7 +110,7 @@ public class ClasspathListenerHandlerTest {
FileUtils.deleteQuietly(loc);
safe(() -> project.refreshLocal(IResource.DEPTH_INFINITE, null));
ACondition.waitFor("Project to disapear", Duration.ofSeconds(50), () -> {
ACondition.waitFor("Project to disapear", Duration.ofSeconds(5), () -> {
Info cp = classpaths.getFor(loc);
assertNull(cp);
});
@@ -133,17 +138,18 @@ public class ClasspathListenerHandlerTest {
Map<File, Info> classpaths = new HashMap<>();
@Override
public synchronized Object executeClientCommand(String id, Object... params) throws Exception {
public synchronized Object executeClientCommand(String id, Object... _params) throws Exception {
if (id.equals(commandId)) {
ImmutableList<Object> params = ImmutableList.copyOf(_params);
System.out.println("received: "+Arrays.asList(params));
File projectLoc = new File(new URI((String) params[0]));
String name = (String) params[1];
boolean deleted = (boolean) params[2];
File projectLoc = new File(new URI((String) params.get(0)));
String name = (String) params.get(1);
boolean deleted = (boolean) params.get(2);
if (deleted) {
System.out.println("DELETING "+name);
classpaths.remove(projectLoc);
} else {
Classpath cp = (Classpath) params[3];
Classpath cp = (Classpath) params.get(3);
System.out.println("PUT "+name+" "+cp.getEntries().size()+" entries");
classpaths.put(projectLoc, new Info(name, cp));
}
@@ -166,6 +172,7 @@ public class ClasspathListenerHandlerTest {
classpaths.dispose();
deleteAllProjects();
assertTrue(service.hasNoActiveSubscriptions());
logger.assertNoErrors();
}
private static void assertClasspath(Classpath cp, boolean b) {

View File

@@ -15,39 +15,102 @@ import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.util.Date;
import java.util.function.Supplier;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Plugin;
import org.eclipse.core.runtime.Status;
/**
* Poor man's logger which writes log output for jdt.ls extension into a predictable location.
* Poor man's logger with a defauly implementation writes log output for jdt.ls extension into a predictable location.
*/
public class Logger {
private static boolean USE_SYS_ERR = false;
public interface Logger {
private static PrintWriter printwriter;
public static Logger DEFAULT = new DefaultLogger(false);
static {
if (USE_SYS_ERR) {
printwriter = new PrintWriter(System.err);
} else {
File file = new File(System.getProperty("java.io.tmpdir"));
file = new File(file, "stsjdt.log");
try {
printwriter = new PrintWriter(new FileOutputStream(file), true);
log("======== "+new Date()+" =======");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
public static class DefaultLogger implements Logger {
private PrintWriter printwriter;
public DefaultLogger(boolean USE_SYS_ERR) {
if (USE_SYS_ERR) {
printwriter = new PrintWriter(System.err);
} else {
File file = new File(System.getProperty("java.io.tmpdir"));
file = new File(file, "stsjdt.log");
try {
printwriter = new PrintWriter(new FileOutputStream(file), true);
log("======== "+new Date()+" =======");
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
@Override
public void log(String message) {
printwriter.println(message);
printwriter.flush();
}
@Override
public void log(Exception e) {
e.printStackTrace(printwriter);
}
}
static Logger forEclipsePlugin(Supplier<Plugin> instance) {
return new Logger() {
@Override
public void log(String message) {
try {
Plugin plugin = instance.get();
plugin.getLog().log(new Status(IStatus.INFO, plugin.getBundle().getSymbolicName(), message));
} catch (Exception ignore) {
//Eclipse state is fubar... send log message someplace else.
DEFAULT.log(message);
}
}
@Override
public void log(Exception e) {
try {
Plugin plugin = instance.get();
plugin.getLog().log(new Status(IStatus.ERROR, plugin.getBundle().getSymbolicName(), "", e));
} catch (Exception ignore) {
//Eclipse state is fubar... send log message someplace else.
DEFAULT.log(e);
}
}
};
}
public static class TestLogger extends DefaultLogger {
private Exception firstError;
public TestLogger() {
super(true);
}
@Override
public void log(Exception e) {
super.log(e);
if (firstError!=null) {
firstError = e;
}
}
public void assertNoErrors() throws Exception {
if (firstError!=null) {
throw firstError;
}
}
}
public static void log(String message) {
printwriter.println(message);
printwriter.flush();
}
public static void log(Exception e) {
e.printStackTrace(printwriter);
}
void log(String message);
void log(Exception e);
}

View File

@@ -12,6 +12,7 @@ package org.springframework.tooling.jdt.ls.commons.classpath;
import java.io.File;
import java.net.URL;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.runtime.Assert;
@@ -20,6 +21,7 @@ public class Classpath {
public static final String ENTRY_KIND_SOURCE = "source";
public static final String ENTRY_KIND_BINARY = "binary";
public static final Classpath EMPTY = new Classpath(Collections.emptyList());
private List<CPE> entries;

View File

@@ -40,7 +40,7 @@ public class ClasspathListenerManager {
@Override
public void elementChanged(ElementChangedEvent event) {
Logger.log("changeEvent = "+event);
logger.log("changeEvent = "+event);
visit(event.getDelta());
}
@@ -83,6 +83,7 @@ public class ClasspathListenerManager {
private ClasspathListener listener;
private MyListener myListener;
private final Logger logger;
/**
* @param initialEvent If true, events are fired immediately on all existing java
@@ -90,31 +91,32 @@ public class ClasspathListenerManager {
* This allows clients to become aware of all classpaths from the start and
* continually monitor them for changes from that point onward.
*/
public ClasspathListenerManager(ClasspathListener listener, boolean initialEvent) {
log("Setting up ClasspathListenerManager");
public ClasspathListenerManager(Logger logger, ClasspathListener listener, boolean initialEvent) {
this.logger = logger;
logger.log("Setting up ClasspathListenerManager");
this.listener = listener;
JavaCore.addElementChangedListener(myListener=new MyListener(), ElementChangedEvent.POST_CHANGE);
if (initialEvent) {
log("Sending initial event for all projects ...");
logger.log("Sending initial event for all projects ...");
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
log("project "+p.getName() +" ..." );
logger.log("project "+p.getName() +" ..." );
try {
if (p.isAccessible() && p.hasNature(JavaCore.NATURE_ID)) {
IJavaProject jp = JavaCore.create(p);
listener.classpathChanged(jp);
} else {
log("project "+p.getName() +" SKIPPED" );
logger.log("project "+p.getName() +" SKIPPED" );
}
} catch (CoreException e) {
Logger.log(e);
logger.log(e);
}
}
log("Sending initial event for all projects DONE");
logger.log("Sending initial event for all projects DONE");
}
}
public ClasspathListenerManager(ClasspathListener listener) {
this(listener, false);
public ClasspathListenerManager(Logger logger, ClasspathListener listener) {
this(logger, listener, false);
}
public void dispose() {

View File

@@ -10,7 +10,6 @@
*******************************************************************************/
package org.springframework.tooling.jdt.ls.commons.classpath;
import static org.springframework.tooling.jdt.ls.commons.Logger.log;
import static org.springframework.tooling.jdt.ls.commons.classpath.Classpath.ENTRY_KIND_BINARY;
import static org.springframework.tooling.jdt.ls.commons.classpath.Classpath.ENTRY_KIND_SOURCE;
@@ -27,6 +26,7 @@ import org.eclipse.jdt.core.IClasspathEntry;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.internal.core.JavaProject;
import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath.CPE;
public class ClasspathUtil {
@@ -59,7 +59,7 @@ public class ClasspathUtil {
return null;
}
public static Classpath resolve(IJavaProject javaProject) throws Exception {
public static Classpath resolve(IJavaProject javaProject, Logger logger) throws Exception {
//log("resolving classpath " + javaProject.getElementName() +" ...");
List<CPE> cpEntries = new ArrayList<>();
@@ -106,7 +106,7 @@ public class ClasspathUtil {
}
}
Classpath classpath = new Classpath(cpEntries);
log("classpath=" + classpath.getEntries().size() + " entries");
logger.log("classpath=" + classpath.getEntries().size() + " entries");
return classpath;
}

View File

@@ -10,14 +10,11 @@
*******************************************************************************/
package org.springframework.tooling.jdt.ls.commons.classpath;
import static org.springframework.tooling.jdt.ls.commons.Logger.log;
import java.io.File;
import java.net.URI;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
@@ -31,11 +28,13 @@ import org.springframework.tooling.jdt.ls.commons.classpath.ClasspathListenerMan
*/
public class ReusableClasspathListenerHandler {
private ClientCommandExecutor conn;
private final ClientCommandExecutor conn;
private final Logger logger;
public ReusableClasspathListenerHandler(ClientCommandExecutor conn) {
public ReusableClasspathListenerHandler(Logger logger, ClientCommandExecutor conn) {
this.conn = conn;
log("Instantiating ReusableClasspathListenerHandler");
this.logger = logger;
logger.log("Instantiating ReusableClasspathListenerHandler");
}
/**
@@ -81,17 +80,17 @@ public class ReusableClasspathListenerHandler {
private Map<String, ClasspathListenerManager> subscribers = null;
public synchronized void subscribe(String callbackCommandId) {
Logger.log("subscribing to classpath changes: " + callbackCommandId);
logger.log("subscribing to classpath changes: " + callbackCommandId);
if (subscribers==null) {
subscribers = new HashMap<>(1);
}
subscribers.computeIfAbsent(callbackCommandId, (cid) -> new ClasspathListenerManager(new ClasspathListener() {
subscribers.computeIfAbsent(callbackCommandId, (cid) -> new ClasspathListenerManager(logger, new ClasspathListener() {
@Override
public void classpathChanged(IJavaProject jp) {
sendNotification(callbackCommandId, jp);
}
}, true));
Logger.log("subsribers = " + subscribers.keySet());
logger.log("subsribers = " + subscribers.keySet());
}
private void sendNotification(String callbackCommandId, IJavaProject jp) {
@@ -102,10 +101,10 @@ public class ReusableClasspathListenerHandler {
protected IStatus run(IProgressMonitor monitor) {
synchronized (projectLocations) { //Could use some Eclipse job rule. But its really a bit of a PITA to create the right one.
try {
log("Preparing classpath changed notification " + jp.getElementName());
logger.log("Preparing classpath changed notification " + jp.getElementName());
URI projectLoc = getProjectLocation(jp);
if (projectLoc==null) {
Logger.log("Could not send event for project because no project location: "+jp.getElementName());
logger.log("Could not send event for project because no project location: "+jp.getElementName());
} else {
boolean exsits = projectExists(jp);
boolean open = true; // WARNING: calling is jp.isOpen is unreliable and subject to race condition. After a POST_CHAGE project open event
@@ -115,31 +114,31 @@ public class ReusableClasspathListenerHandler {
// So we will just pretend / assume project is always open. If resolving classpath fails because it is not
// open... so be it (there will be no classpath... this is expected for closed project, so that is fine).
boolean deleted = !(exsits && open);
Logger.log("exists = "+exsits +" open = "+open +" => deleted = "+deleted);
logger.log("exists = "+exsits +" open = "+open +" => deleted = "+deleted);
String projectName = jp.getElementName();
Classpath classpath = null;
Classpath classpath = Classpath.EMPTY;
if (deleted) {
projectLocations.remove(projectName);
} else {
projectLocations.put(projectName, projectLoc);
try {
classpath = ClasspathUtil.resolve(jp);
classpath = ClasspathUtil.resolve(jp, logger);
} catch (Exception e) {
Logger.log(e);
logger.log(e);
}
}
try {
Logger.log("executing callback "+callbackCommandId+" "+projectName+" "+deleted+" "+(classpath==null ? "" : classpath.getEntries().size()));
logger.log("executing callback "+callbackCommandId+" "+projectName+" "+deleted+" "+ classpath.getEntries().size());
Object r = conn.executeClientCommand(callbackCommandId, projectLoc.toString(), projectName, deleted, classpath);
Logger.log("executing callback "+callbackCommandId+" SUCCESS ["+r+"]");
logger.log("executing callback "+callbackCommandId+" SUCCESS ["+r+"]");
} catch (Exception e) {
Logger.log("executing callback "+callbackCommandId+" FAILED");
Logger.log(e);
logger.log("executing callback "+callbackCommandId+" FAILED");
logger.log(e);
}
}
} catch (Exception e) {
Logger.log(e);
logger.log(e);
}
return Status.OK_STATUS;
}
@@ -149,7 +148,7 @@ public class ReusableClasspathListenerHandler {
}
public synchronized void unsubscribe(String callbackCommandId) {
Logger.log("unsubscribing from classpath changes: " + callbackCommandId);
logger.log("unsubscribing from classpath changes: " + callbackCommandId);
if (subscribers != null) {
ClasspathListenerManager mgr = subscribers.remove(callbackCommandId);
if (mgr!=null) {
@@ -159,7 +158,7 @@ public class ReusableClasspathListenerHandler {
subscribers = null;
}
}
Logger.log("subsribers = " + (subscribers == null ? "null" : subscribers.keySet()));
logger.log("subsribers = " + (subscribers == null ? "null" : subscribers.keySet()));
}
public boolean isEmpty() {
@@ -170,16 +169,16 @@ public class ReusableClasspathListenerHandler {
private Subscribptions subscribptions = new Subscribptions();
public Object removeClasspathListener(String callbackCommandId) {
log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId);
logger.log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId);
subscribptions.unsubscribe(callbackCommandId);
log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId + " => OK");
logger.log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId + " => OK");
return "ok";
}
public Object addClasspathListener(String callbackCommandId) {
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
logger.log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
subscribptions.subscribe(callbackCommandId);
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
logger.log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
return "ok";
}

View File

@@ -34,22 +34,22 @@ public final class ResourceUtils {
*/
public static IJavaProject getJavaProject(URI resourceUri) throws Exception {
IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(resourceUri);
log("containers=" + containers);
// log("containers=" + containers);
if (containers.length > 0) {
log("containers.length=" + containers.length);
// log("containers.length=" + containers.length);
Optional<IContainer> shortest = Arrays.stream(containers)
.min((f1, f2) -> f1.getFullPath().segmentCount() - f2.getFullPath().segmentCount());
log("shortest=" + shortest.isPresent());
// log("shortest=" + shortest.isPresent());
if (shortest.isPresent()) {
log("shortest.fullpath=" + shortest.get().getFullPath());
// log("shortest.fullpath=" + shortest.get().getFullPath());
IProject project = shortest.get().getProject();
log("project=" + project.getName());
// log("project=" + project.getName());
if (project.isAccessible() && project.hasNature(JavaCore.NATURE_ID)) {
IJavaProject javaProject = JavaCore.create(project);
log("javaProject=" + javaProject.getElementName());
// log("javaProject=" + javaProject.getElementName());
return javaProject;
}

View File

@@ -10,8 +10,6 @@
*******************************************************************************/
package org.springframework.tooling.jdt.ls.extension;
import static org.springframework.tooling.jdt.ls.commons.Logger.log;
import java.util.List;
import org.eclipse.core.runtime.IProgressMonitor;
@@ -25,18 +23,19 @@ import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathLis
@SuppressWarnings("restriction")
public class ClasspathListenerHandler implements IDelegateCommandHandler {
private static final Logger logger = Logger.DEFAULT;
private static ReusableClasspathListenerHandler handlerImpl = checkSupported();
private static ReusableClasspathListenerHandler checkSupported() {
try {
JavaClientConnection.class.getMethod("executeClientCommand", String.class, Object[].class);
return new ReusableClasspathListenerHandler(new ClientCommandExecutor() {
return new ReusableClasspathListenerHandler(logger, new ClientCommandExecutor() {
@Override
public Object executeClientCommand(String id, Object... params) {
return JavaLanguageServerPlugin.getInstance().getClientConnection().executeClientCommand(id, params);
}
});
} catch (Exception e) {
Logger.log(e);
logger.log(e);
}
return null;
}
@@ -46,7 +45,7 @@ public class ClasspathListenerHandler implements IDelegateCommandHandler {
if (handlerImpl==null) {
throw new UnsupportedOperationException("Command '"+commandId+"' not supported on older versions of JDT Language Server");
}
log("ClasspathListenerHandler executeCommand " + commandId + ", " + arguments);
logger.log("ClasspathListenerHandler executeCommand " + commandId + ", " + arguments);
switch (commandId) {
case "sts.java.addClasspathListener":
return addClasspathListener((String) arguments.get(0));
@@ -58,14 +57,14 @@ public class ClasspathListenerHandler implements IDelegateCommandHandler {
}
private Object removeClasspathListener(String callbackCommandId) {
log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId);
logger.log("ClasspathListenerHandler removeClasspathListener " + callbackCommandId);
return handlerImpl.removeClasspathListener(callbackCommandId);
}
private Object addClasspathListener(String callbackCommandId) {
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
logger.log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
handlerImpl.addClasspathListener(callbackCommandId);
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
logger.log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
return "ok";
}

View File

@@ -1,16 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<?pde version="3.8"?><target name="Java Language Server Target Definition" sequenceNumber="109">
<?pde version="3.8"?><target name="Java Language Server Target Definition" sequenceNumber="111">
<locations>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.mockito.mockito-all" version="1.9.5"/>
<repository location="http://download.eclipse.org/scout/releases/4.0/testing"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.xtend.sdk.feature.group" version="2.12.0.v20170519-1412"/>
<unit id="org.eclipse.xtext.sdk.feature.group" version="2.12.0.v20170519-1412"/>
<repository location="http://download.eclipse.org/releases/oxygen"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="com.google.gson" version="2.7.0.v20170129-0911"/>
<unit id="com.google.gson.source" version="2.7.0.v20170129-0911"/>
<unit id="com.ibm.icu.base" version="58.2.0.v20170418-1837"/>
@@ -19,32 +14,40 @@
<unit id="org.apache.log4j" version="1.2.15.v201012070815"/>
<repository location="http://download.eclipse.org/tools/orbit/R-builds/R20170516192513/repository"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.lsp4j.sdk.feature.group" version="0.3.0.v20170913-0640"/>
<repository location="http://download.eclipse.org/lsp4j/updates/releases/0.3.0/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.buildship.feature.group" version="2.2.0.v20171211-1404"/>
<repository location="http://download.eclipse.org/buildship/updates/e47/releases/2.x/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.m2e.feature.feature.group" version="1.9.0.20180214-1942"/>
<repository location="http://download.eclipse.org/technology/m2e/milestones/1.9/1.9.0.20180214-1942/"/>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.m2e.feature.feature.group" version="1.9.0.20180313-2237"/>
<repository location="http://download.eclipse.org/technology/m2e/milestones/1.9/1.9.0.20180313-2237/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.equinox.core.feature.feature.group" version="1.5.0.v20180123-1456"/>
<unit id="org.eclipse.equinox.core.sdk.feature.group" version="3.14.0.v20180119-2027"/>
<unit id="org.eclipse.equinox.executable.feature.group" version="3.8.0.v20180124-1426"/>
<unit id="org.eclipse.equinox.p2.core.feature.source.feature.group" version="1.5.0.v20180122-2220"/>
<unit id="org.eclipse.equinox.p2.discovery.feature.feature.group" version="1.2.0.v20180103-0918"/>
<unit id="org.eclipse.equinox.p2.rcp.feature.feature.group" version="1.4.0.v20180122-2220"/>
<unit id="org.eclipse.equinox.sdk.feature.group" version="3.14.0.v20180124-1426"/>
<unit id="org.eclipse.jdt.source.feature.group" version="3.14.0.v20180124-2000"/>
<unit id="org.eclipse.sdk.feature.group" version="4.8.0.v20180124-2000"/>
<repository location="http://download.eclipse.org/eclipse/updates/4.8milestones/"/>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.equinox.core.feature.feature.group" version="1.5.0.v20180419-0833"/>
<unit id="org.eclipse.equinox.core.sdk.feature.group" version="3.14.0.v20180412-1130"/>
<unit id="org.eclipse.equinox.executable.feature.group" version="3.8.0.v20180326-1331"/>
<unit id="org.eclipse.equinox.p2.core.feature.source.feature.group" version="1.5.0.v20180413-0846"/>
<unit id="org.eclipse.equinox.sdk.feature.group" version="3.14.0.v20180419-0833"/>
<unit id="org.eclipse.jdt.source.feature.group" version="3.14.0.v20180423-1043"/>
<unit id="org.eclipse.sdk.feature.group" version="4.8.0.v20180423-1043"/>
<repository location="http://download.eclipse.org/eclipse/updates/4.8-I-builds/I20180423-0655/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.jdt.ls.core" version="0.15.0.201803012111"/>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.lsp4j.sdk.feature.group" version="0.4.0.v20180301-0956"/>
<repository location="http://download.eclipse.org/lsp4j/updates/milestones/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.xtend.sdk.feature.group" version="2.13.0.v20171020-0920"/>
<unit id="org.eclipse.xtext.sdk.feature.group" version="2.13.0.v20171020-0920"/>
<repository location="http://download.eclipse.org/releases/photon/"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.jboss.tools.maven.apt.feature.feature.group" version="1.5.0.201804060341"/>
<repository location="http://download.jboss.org/jbosstools/updates/m2e-extensions/m2e-apt/1.5.0-2018-04-06_03-47-50-H10"/>
</location>
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="slicer" includeSource="true" type="InstallableUnit">
<unit id="org.eclipse.jdt.ls.core" version="0.19.0.201805111532"/>
<unit id="org.eclipse.jdt.ls.core.source" version="0.19.0.201805111532"/>
<repository location="http://download.eclipse.org/jdtls/snapshots/repository/latest/"/>
</location>
</locations>