Split jdt ls extension into two parts
One pugin to contain the bulk of the code, which is independent of jdt.ls, lsp4e and lsp4j. Second plugin to contain the jdt.ls specific DelegateCommandHandler implementation. This should allow us to somehow re-use the bulk of the code in STS4 eclipse, i.e. when we have access to JDT from eclipse directly, and there is no jdt.ls process around.
This commit is contained in:
11
headless-services/jdt-ls-extension/.project
Normal file
11
headless-services/jdt-ls-extension/.project
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>jdt-ls-extension-parent</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.springframework.tooling.jdt.ls.commons</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
@@ -0,0 +1,13 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Commons
|
||||
Bundle-SymbolicName: org.springframework.tooling.jdt.ls.commons
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Automatic-Module-Name: org.springframework.tooling.jdt.ls.commons
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: org.eclipse.jdt.ls.core,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.core.resources
|
||||
Export-Package: org.springframework.tooling.jdt.ls.commons,
|
||||
org.springframework.tooling.jdt.ls.commons.classpath
|
||||
@@ -0,0 +1,4 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.
|
||||
@@ -0,0 +1,18 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>org.springframework.tooling.jdt.ls.commons</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>org.springframework.tooling.jdt.ls.commons</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.tooling</groupId>
|
||||
<artifactId>jdt-ls-extension-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,47 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 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.tooling.jdt.ls.commons;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* Poor man's logger which writes log output for jdt.ls extension into a predictable location.
|
||||
*/
|
||||
public class Logger {
|
||||
|
||||
private static PrintWriter printwriter;
|
||||
|
||||
static {
|
||||
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 void log(String message) {
|
||||
printwriter.println(message);
|
||||
printwriter.flush();
|
||||
}
|
||||
|
||||
public static void log(Exception e) {
|
||||
e.printStackTrace(printwriter);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.springframework.tooling.jdt.ls.commons.classpath;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class Classpath {
|
||||
|
||||
public static final String ENTRY_KIND_SOURCE = "source";
|
||||
public static final String ENTRY_KIND_BINARY = "binary";
|
||||
public static final String OUTPUT_LOCATION = "output_location";
|
||||
|
||||
private List<CPE> entries;
|
||||
private String defaultOutputFolder;
|
||||
|
||||
public Classpath(List<CPE> entries, String defaultOutputFolder) {
|
||||
super();
|
||||
this.entries = entries;
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
public List<CPE> getEntries() {
|
||||
return entries;
|
||||
}
|
||||
|
||||
public void setEntries(List<CPE> entries) {
|
||||
this.entries = entries;
|
||||
}
|
||||
|
||||
public String getDefaultOutputFolder() {
|
||||
return defaultOutputFolder;
|
||||
}
|
||||
|
||||
public void setDefaultOutputFolder(String defaultOutputFolder) {
|
||||
this.defaultOutputFolder = defaultOutputFolder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Classpath [entries=" + entries + ", defaultOutputFolder=" + defaultOutputFolder + "]";
|
||||
}
|
||||
|
||||
public static class CPE {
|
||||
private String kind;
|
||||
private String path;
|
||||
|
||||
public CPE(String kind, String path) {
|
||||
super();
|
||||
this.kind = kind;
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
public String getKind() {
|
||||
return kind;
|
||||
}
|
||||
|
||||
public void setKind(String kind) {
|
||||
this.kind = kind;
|
||||
}
|
||||
|
||||
public String getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
public void setPath(String path) {
|
||||
this.path = path;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CPE [kind=" + kind + ", path=" + path + "]\n";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 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.tooling.jdt.ls.commons.classpath;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.CoreException;
|
||||
import org.eclipse.jdt.core.ElementChangedEvent;
|
||||
import org.eclipse.jdt.core.IElementChangedListener;
|
||||
import org.eclipse.jdt.core.IJavaElement;
|
||||
import org.eclipse.jdt.core.IJavaElementDelta;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.springframework.tooling.jdt.ls.commons.Logger;
|
||||
|
||||
import static org.springframework.tooling.jdt.ls.commons.Logger.*;
|
||||
|
||||
/**
|
||||
* An instance of this class provides a means to register
|
||||
* listeners that get notified when classpath for a IJavaProject
|
||||
* changes.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public class ClasspathListenerManager {
|
||||
|
||||
public interface ClasspathListener {
|
||||
public abstract void classpathChanged(IJavaProject jp);
|
||||
}
|
||||
|
||||
private class MyListener implements IElementChangedListener {
|
||||
|
||||
@Override
|
||||
public void elementChanged(ElementChangedEvent event) {
|
||||
visit(event.getDelta());
|
||||
}
|
||||
|
||||
private void visit(IJavaElementDelta delta) {
|
||||
IJavaElement el = delta.getElement();
|
||||
switch (el.getElementType()) {
|
||||
case IJavaElement.JAVA_MODEL:
|
||||
visitChildren(delta);
|
||||
break;
|
||||
case IJavaElement.JAVA_PROJECT:
|
||||
if (isClasspathChanged(delta.getFlags())) {
|
||||
listener.classpathChanged((IJavaProject)el);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isClasspathChanged(int flags) {
|
||||
return 0!= (flags & (
|
||||
IJavaElementDelta.F_CLASSPATH_CHANGED |
|
||||
IJavaElementDelta.F_RESOLVED_CLASSPATH_CHANGED
|
||||
));
|
||||
}
|
||||
|
||||
public void visitChildren(IJavaElementDelta delta) {
|
||||
for (IJavaElementDelta c : delta.getAffectedChildren()) {
|
||||
visit(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private ClasspathListener listener;
|
||||
private MyListener myListener;
|
||||
|
||||
/**
|
||||
* @param initialEvent If true, events are fired immediately on all existing java
|
||||
* projects, treating the connection of the listener itself as a change event.
|
||||
* 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");
|
||||
this.listener = listener;
|
||||
if (initialEvent) {
|
||||
log("Sending initial event for all projects ...");
|
||||
for (IProject p : ResourcesPlugin.getWorkspace().getRoot().getProjects()) {
|
||||
log("project = "+p);
|
||||
try {
|
||||
if (p.isAccessible() && p.hasNature(JavaCore.NATURE_ID)) {
|
||||
IJavaProject jp = JavaCore.create(p);
|
||||
listener.classpathChanged(jp);
|
||||
}
|
||||
} catch (CoreException e) {
|
||||
Logger.log(e);
|
||||
}
|
||||
}
|
||||
log("Sending initial event for all projects DONE");
|
||||
}
|
||||
JavaCore.addElementChangedListener(myListener=new MyListener(), ElementChangedEvent.POST_CHANGE);
|
||||
}
|
||||
|
||||
public ClasspathListenerManager(ClasspathListener listener) {
|
||||
this(listener, false);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
if (myListener!=null) {
|
||||
JavaCore.removeElementChangedListener(myListener);
|
||||
myListener = null;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 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.tooling.jdt.ls.commons.classpath;
|
||||
|
||||
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;
|
||||
import static org.springframework.tooling.jdt.ls.commons.Logger.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.IClasspathEntry;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.IPackageFragmentRoot;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath.CPE;
|
||||
|
||||
public class ClasspathUtil {
|
||||
|
||||
public static Classpath resolve(IJavaProject javaProject) throws Exception {
|
||||
|
||||
List<CPE> cpEntries = new ArrayList<>();
|
||||
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
|
||||
|
||||
if (entries != null) {
|
||||
for (IClasspathEntry entry : entries) {
|
||||
String kind = toContentKind(entry);
|
||||
String path = entry.getPath().toString();
|
||||
cpEntries.add(new CPE(kind, path));
|
||||
}
|
||||
}
|
||||
Classpath classpath = new Classpath(cpEntries, javaProject.getOutputLocation().toString());
|
||||
log("classpath=" + classpath.getEntries().size() + " entries");
|
||||
return classpath;
|
||||
}
|
||||
|
||||
private static String toContentKind(IClasspathEntry entry) {
|
||||
switch (entry.getContentKind()) {
|
||||
case IPackageFragmentRoot.K_BINARY:
|
||||
return ENTRY_KIND_BINARY;
|
||||
case IPackageFragmentRoot.K_SOURCE:
|
||||
return ENTRY_KIND_SOURCE;
|
||||
default:
|
||||
return "unknown: " + entry.getContentKind();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 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.tooling.jdt.ls.commons.resources;
|
||||
|
||||
import static org.springframework.tooling.jdt.ls.commons.Logger.*;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.core.resources.IContainer;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
|
||||
public final class ResourceUtils {
|
||||
|
||||
/**
|
||||
* Resolves a Java project given the resource URI. The resource URI could be any resource contained in the project.
|
||||
* @param resourceUri
|
||||
* @return Java project
|
||||
* @throws Exception if unable to resolve Java project from given resource URI
|
||||
*/
|
||||
public static IJavaProject getJavaProject(URI resourceUri) throws Exception {
|
||||
IContainer[] containers = ResourcesPlugin.getWorkspace().getRoot().findContainersForLocationURI(resourceUri);
|
||||
log("containers=" + containers);
|
||||
if (containers.length > 0) {
|
||||
log("containers.length=" + containers.length);
|
||||
Optional<IContainer> shortest = Arrays.stream(containers)
|
||||
.min((f1, f2) -> f1.getFullPath().segmentCount() - f2.getFullPath().segmentCount());
|
||||
log("shortest=" + shortest.isPresent());
|
||||
|
||||
if (shortest.isPresent()) {
|
||||
log("shortest.fullpath=" + shortest.get().getFullPath());
|
||||
|
||||
IProject project = shortest.get().getProject();
|
||||
log("project=" + project.getName());
|
||||
|
||||
if (project.isAccessible() && project.hasNature(JavaCore.NATURE_ID)) {
|
||||
IJavaProject javaProject = JavaCore.create(project);
|
||||
log("javaProject=" + javaProject.getElementName());
|
||||
|
||||
return javaProject;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
throw new Exception("Resolve classpath: unable to resolve a Java project from : " + resourceUri);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the resource URI, IFF it exists. Throws exception if it doesn't exist.
|
||||
* @param arguments
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static URI getResourceUri(List<Object> arguments) throws Exception {
|
||||
if (arguments == null || arguments.size() == 0) {
|
||||
throw new IllegalArgumentException(
|
||||
"Resolve classpath: Invalid number of arguments. A resource URI is required.");
|
||||
}
|
||||
URI uri = URI.create((String) arguments.get(0));
|
||||
File resource = new File(uri);
|
||||
if (!resource.exists()) {
|
||||
throw new IllegalArgumentException("Resolve classpath: Resource does not exist: " + resource);
|
||||
}
|
||||
|
||||
return uri;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
<classpathentry kind="con" path="org.eclipse.pde.core.requiredPlugins"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>org.springframework.tooling.jdt.ls.extension</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.ManifestBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.pde.SchemaBuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.pde.PluginNature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,7 @@
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.8
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.source=1.8
|
||||
@@ -0,0 +1,4 @@
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
resolveWorkspaceProjects=true
|
||||
version=1
|
||||
@@ -0,0 +1,12 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: org.springframework.tooling.jdt.ls.extension
|
||||
Bundle-SymbolicName: org.springframework.tooling.jdt.ls.extension;singleton:=true
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Bundle-Vendor: Pivotal Inc.
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: org.eclipse.jdt.ls.core,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.core.resources,
|
||||
org.springframework.tooling.jdt.ls.commons
|
||||
@@ -0,0 +1,5 @@
|
||||
source.. = src/
|
||||
output.. = bin/
|
||||
bin.includes = META-INF/,\
|
||||
.,\
|
||||
plugin.xml
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<?eclipse version="3.4"?>
|
||||
<plugin>
|
||||
<extension point="org.eclipse.jdt.ls.core.delegateCommandHandler">
|
||||
<delegateCommandHandler class="org.springframework.tooling.jdt.ls.extension.ClasspathListenerHandler">
|
||||
<command id="sts.java.addClasspathListener"/>
|
||||
<command id="sts.java.removeClasspathListener"/>
|
||||
</delegateCommandHandler>
|
||||
</extension>
|
||||
</plugin>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<packaging>eclipse-plugin</packaging>
|
||||
<groupId>org.springframework.tooling</groupId>
|
||||
<artifactId>org.springframework.tooling.jdt.ls.extension</artifactId>
|
||||
<version>1.0.0-SNAPSHOT</version>
|
||||
<name>org.springframework.tooling.jdt.ls.extension</name>
|
||||
|
||||
<parent>
|
||||
<groupId>org.springframework.tooling</groupId>
|
||||
<artifactId>jdt-ls-extension-parent</artifactId>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
</project>
|
||||
@@ -0,0 +1,150 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 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.tooling.jdt.ls.extension;
|
||||
|
||||
import static org.springframework.tooling.jdt.ls.commons.Logger.log;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.IProgressMonitor;
|
||||
import org.eclipse.core.runtime.IStatus;
|
||||
import org.eclipse.core.runtime.Status;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.jdt.core.IJavaProject;
|
||||
import org.eclipse.jdt.ls.core.internal.IDelegateCommandHandler;
|
||||
import org.eclipse.jdt.ls.core.internal.JavaClientConnection;
|
||||
import org.eclipse.jdt.ls.core.internal.JavaLanguageServerPlugin;
|
||||
import org.springframework.tooling.jdt.ls.commons.Logger;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.ClasspathListenerManager;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.ClasspathListenerManager.ClasspathListener;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.ClasspathUtil;
|
||||
|
||||
@SuppressWarnings("restriction")
|
||||
public class ClasspathListenerHandler implements IDelegateCommandHandler {
|
||||
|
||||
static {
|
||||
Logger.log("THIS IS NEW!");
|
||||
}
|
||||
|
||||
static final boolean isSupported = checkSupported();
|
||||
private static boolean checkSupported() {
|
||||
try {
|
||||
JavaClientConnection.class.getMethod("executeClientCommand", String.class, Object[].class);
|
||||
return true;
|
||||
} catch (Exception e) {
|
||||
Logger.log(e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static class Subscribptions {
|
||||
|
||||
private static Map<String, ClasspathListenerManager> subscribers = null;
|
||||
|
||||
public synchronized void subscribe(String callbackCommandId) {
|
||||
Logger.log("subscribing to classpath changes: " + callbackCommandId);
|
||||
if (subscribers==null) {
|
||||
subscribers = new HashMap<>(1);
|
||||
}
|
||||
subscribers.computeIfAbsent(callbackCommandId, (cid) -> new ClasspathListenerManager(new ClasspathListener() {
|
||||
@Override
|
||||
public void classpathChanged(IJavaProject jp) {
|
||||
sendNotification(callbackCommandId, jp);
|
||||
}
|
||||
}, true));
|
||||
Logger.log("subsribers = " + subscribers.keySet());
|
||||
}
|
||||
|
||||
private void sendNotification(String callbackCommandId, IJavaProject jp) {
|
||||
//TODO: make one Job to accumulate all requested notification and work more efficiently by batching
|
||||
// and avoiding multiple executions of duplicated requests.
|
||||
new Job("SendClasspath notification") {
|
||||
@Override
|
||||
protected IStatus run(IProgressMonitor monitor) {
|
||||
log("Classpath changed " + jp.getElementName());
|
||||
String project = jp.getProject().getLocationURI().toString();
|
||||
boolean deleted = !jp.exists();
|
||||
JavaClientConnection conn = JavaLanguageServerPlugin.getInstance().getClientConnection();
|
||||
String projectName = jp.getElementName();
|
||||
|
||||
Classpath classpath = null;
|
||||
if (!deleted) {
|
||||
try {
|
||||
classpath = ClasspathUtil.resolve(jp);
|
||||
} catch (Exception e) {
|
||||
Logger.log(e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
Logger.log("executing callback "+callbackCommandId+" "+projectName+" "+deleted+" "+(classpath==null ? "" : classpath.getEntries().size()));
|
||||
conn.executeClientCommand(callbackCommandId, project, projectName, deleted, classpath);
|
||||
Logger.log("executing callback "+callbackCommandId+" SUCCESS");
|
||||
} catch (Exception e) {
|
||||
Logger.log("executing callback "+callbackCommandId+" FAILED");
|
||||
Logger.log(e);
|
||||
}
|
||||
return Status.OK_STATUS;
|
||||
}
|
||||
}
|
||||
.schedule();
|
||||
}
|
||||
|
||||
public synchronized void unsubscribe(String callbackCommandId) {
|
||||
Logger.log("unsubscribing from classpath changes: " + callbackCommandId);
|
||||
if (subscribers != null) {
|
||||
ClasspathListenerManager mgr = subscribers.remove(callbackCommandId);
|
||||
if (mgr!=null) {
|
||||
mgr.dispose();
|
||||
}
|
||||
if (subscribers.isEmpty()) {
|
||||
subscribers = null;
|
||||
}
|
||||
}
|
||||
Logger.log("subsribers = " + subscribers.keySet());
|
||||
}
|
||||
}
|
||||
|
||||
private static Subscribptions subscribptions = new Subscribptions();
|
||||
|
||||
@Override
|
||||
public Object executeCommand(String commandId, List<Object> arguments, IProgressMonitor monitor) throws Exception {
|
||||
if (!isSupported) {
|
||||
throw new UnsupportedOperationException("Command '"+commandId+"' not supported on older versions of JDT Language Server");
|
||||
}
|
||||
log("ClasspathListenerHandler executeCommand " + commandId + ", " + arguments);
|
||||
switch (commandId) {
|
||||
case "sts.java.addClasspathListener":
|
||||
return addClasspathListener((String) arguments.get(0));
|
||||
case "sts.java.removeClasspathListener":
|
||||
return removeClasspathListener((String) arguments.get(0));
|
||||
default:
|
||||
throw new IllegalArgumentException("Unknown command id: " + commandId);
|
||||
}
|
||||
}
|
||||
|
||||
private Object removeClasspathListener(String callbackCommandId) {
|
||||
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
|
||||
subscribptions.unsubscribe(callbackCommandId);
|
||||
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
|
||||
return "ok";
|
||||
}
|
||||
|
||||
private Object addClasspathListener(String callbackCommandId) {
|
||||
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId);
|
||||
subscribptions.subscribe(callbackCommandId);
|
||||
log("ClasspathListenerHandler addClasspathListener " + callbackCommandId + " => OK");
|
||||
return "ok";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?pde version="3.8"?><target name="Java Language Server Target Definition" sequenceNumber="109">
|
||||
<locations>
|
||||
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" 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">
|
||||
<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"/>
|
||||
<unit id="org.apache.commons.io" version="2.2.0.v201405211200"/>
|
||||
<unit id="org.apache.commons.lang3" version="3.1.0.v201403281430"/>
|
||||
<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">
|
||||
<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>
|
||||
<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>
|
||||
<location includeAllPlatforms="false" includeConfigurePhase="false" includeMode="planner" includeSource="true" type="InstallableUnit">
|
||||
<unit id="org.eclipse.jdt.ls.core" version="0.15.0.201803012111"/>
|
||||
<repository location="http://download.eclipse.org/jdtls/snapshots/repository/latest/"/>
|
||||
</location>
|
||||
</locations>
|
||||
<targetJRE path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.8"/>
|
||||
</target>
|
||||
45
headless-services/jdt-ls-extension/pom.xml
Normal file
45
headless-services/jdt-ls-extension/pom.xml
Normal file
@@ -0,0 +1,45 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
|
||||
http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.tooling</groupId>
|
||||
<artifactId>jdt-ls-extension-parent</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<version>0.0.1-SNAPSHOT</version>
|
||||
<name>jdt-ls-extension-parent</name>
|
||||
|
||||
<modules>
|
||||
<module>org.springframework.tooling.jdt.ls.extension</module>
|
||||
<module>org.springframework.tooling.jdt.ls.commons</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<tycho-version>1.1.0</tycho-version>
|
||||
</properties>
|
||||
<repositories>
|
||||
<repository>
|
||||
<id>eclipse-oxygen</id>
|
||||
<layout>p2</layout>
|
||||
<url>http://download.eclipse.org/releases/oxygen</url>
|
||||
</repository>
|
||||
<repository>
|
||||
<id>JDT.LS</id>
|
||||
<layout>p2</layout>
|
||||
<!-- <url>${jdt.ls.updatesite}</url> -->
|
||||
<url>http://download.eclipse.org/jdtls/snapshots/repository/latest/</url>
|
||||
</repository>
|
||||
</repositories>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.eclipse.tycho</groupId>
|
||||
<artifactId>tycho-maven-plugin</artifactId>
|
||||
<version>${tycho-version}</version>
|
||||
<extensions>true</extensions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
|
||||
Reference in New Issue
Block a user