Add a first test for jdt.ls.extension
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -24,6 +24,9 @@ eclipse-language-servers/**/*.jar
|
||||
|
||||
# Exceptions
|
||||
!**/.mvn/wrapper/maven-wrapper.jar
|
||||
!**/jdt-ls-extension/**/test-projects/**/.classpath
|
||||
!**/jdt-ls-extension/**/test-projects/**/.project
|
||||
!**/jdt-ls-extension/**/test-projects/**/.settings
|
||||
|
||||
# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
|
||||
hs_err_pid*
|
||||
|
||||
@@ -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.test</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,16 @@
|
||||
Manifest-Version: 1.0
|
||||
Bundle-ManifestVersion: 2
|
||||
Bundle-Name: Commons
|
||||
Bundle-SymbolicName: org.springframework.tooling.jdt.ls.commons.test
|
||||
Bundle-Version: 1.0.0.qualifier
|
||||
Automatic-Module-Name: org.springframework.tooling.jdt.ls.commons.test
|
||||
Bundle-RequiredExecutionEnvironment: JavaSE-1.8
|
||||
Require-Bundle: org.springframework.tooling.jdt.ls.commons,
|
||||
org.eclipse.core.runtime,
|
||||
org.eclipse.jdt.core,
|
||||
org.eclipse.core.resources,
|
||||
org.apache.commons.lang3,
|
||||
org.junit,
|
||||
org.apache.commons.io,
|
||||
org.eclipse.swt
|
||||
|
||||
@@ -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-test-plugin</packaging>
|
||||
<groupId>org.springframework.ide.vscode</groupId>
|
||||
<artifactId>org.springframework.tooling.jdt.ls.commons.test</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,120 @@
|
||||
/*******************************************************************************
|
||||
* 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 static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.time.Duration;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.lang3.RandomStringUtils;
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.IProjectDescription;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
import org.eclipse.core.runtime.FileLocator;
|
||||
import org.eclipse.core.runtime.Path;
|
||||
import org.eclipse.core.runtime.Platform;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.junit.After;
|
||||
import org.junit.Test;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.Classpath;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.ClientCommandExecutor;
|
||||
import org.springframework.tooling.jdt.ls.commons.classpath.ReusableClasspathListenerHandler;
|
||||
import org.springsource.ide.eclipse.commons.frameworks.test.util.ACondition;
|
||||
|
||||
public class ClasspathListenerHandlerTest {
|
||||
|
||||
static class Info {
|
||||
public final String name;
|
||||
public final Classpath classpath;
|
||||
|
||||
private Info(String name, Classpath cp) {
|
||||
super();
|
||||
this.name = name;
|
||||
this.classpath = cp;
|
||||
}
|
||||
}
|
||||
|
||||
public class MockClasspathCache implements ClientCommandExecutor {
|
||||
|
||||
|
||||
String commandId = RandomStringUtils.randomAlphabetic(8);
|
||||
|
||||
Map<File, Info> classpaths = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public synchronized Object executeClientCommand(String id, Object... params) throws Exception {
|
||||
if (id.equals(commandId)) {
|
||||
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];
|
||||
if (deleted) {
|
||||
classpaths.remove(projectLoc);
|
||||
} else {
|
||||
Classpath cp = (Classpath) params[3];
|
||||
classpaths.put(projectLoc, new Info(name, cp));
|
||||
}
|
||||
}
|
||||
return "whatever";
|
||||
}
|
||||
|
||||
public synchronized Info getFor(IProject project) {
|
||||
File location = project.getLocation().toFile();
|
||||
return classpaths.get(location);
|
||||
}
|
||||
|
||||
public void dispose() {
|
||||
service.removeClasspathListener(commandId);
|
||||
}
|
||||
|
||||
}
|
||||
private MockClasspathCache classpaths = new MockClasspathCache();
|
||||
private ReusableClasspathListenerHandler service = new ReusableClasspathListenerHandler(classpaths);
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
classpaths.dispose();
|
||||
assertTrue(service.hasNoActiveSubscriptions());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void classpathIsSentForExistingProject() throws Exception {
|
||||
String projectName = "classpath-test-simple-java-project";
|
||||
IProject project = createTestProject(projectName);
|
||||
|
||||
service.addClasspathListener(classpaths.commandId);
|
||||
ACondition.waitFor("Project with classpath to appear", Duration.ofSeconds(5), () -> {
|
||||
Classpath cp = classpaths.getFor(project).classpath;
|
||||
assertTrue(cp.getEntries().stream().filter(cpe -> Classpath.isSource(cpe)).count()==1); //has 1 source entry
|
||||
assertTrue(cp.getEntries().stream().filter(cpe -> Classpath.isBinary(cpe) && cpe.isSystem()).count()>=1); //has some system libraries
|
||||
});
|
||||
}
|
||||
|
||||
private IProject createTestProject(String name) throws Exception {
|
||||
File testProjectLocation = new File(FileLocator.toFileURL(Platform.getBundle("org.springframework.tooling.jdt.ls.commons.test").getEntry("test-projects/"+name)).toURI());
|
||||
IProject project = ResourcesPlugin.getWorkspace().getRoot().getProject(name);
|
||||
IProjectDescription desc = ResourcesPlugin.getWorkspace().newProjectDescription(null);
|
||||
desc.setName(name);
|
||||
desc.setLocation(Path.fromOSString(testProjectLocation.toString()));
|
||||
project.create(desc, null);
|
||||
project.open(null);
|
||||
|
||||
assertTrue(project.hasNature(JavaCore.NATURE_ID));
|
||||
return project;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,264 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2012, 2018 Pivotal Software, 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 Software, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springsource.ide.eclipse.commons.frameworks.test.util;
|
||||
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.core.runtime.jobs.IJobManager;
|
||||
import org.eclipse.core.runtime.jobs.Job;
|
||||
import org.eclipse.swt.widgets.Display;
|
||||
|
||||
import junit.framework.AssertionFailedError;
|
||||
|
||||
/**
|
||||
* Abstract class to create a "waitable" condition. This is to be used in implementing
|
||||
* tests where we want some condition to be true eventually, but cannot be sure it will be
|
||||
* true immediately.
|
||||
* <p>
|
||||
* Typical use would like so:
|
||||
* <code>
|
||||
* new ACondition() {
|
||||
* public boolean test() throws Exception {
|
||||
* ... some asserts ...
|
||||
* return ...something to test...;
|
||||
* }
|
||||
* }.waitFor(4000); // wait for 4 seconds or until test passes.
|
||||
* </code>
|
||||
* An exception will be thrown if the test method does not return true before the
|
||||
* timeout limit.
|
||||
* <p>
|
||||
* If the test method throws an exception this is treated the same as returning false.
|
||||
* If condition fails, we will try to rethrow a pertinent exception (typically the
|
||||
* exception thrown by the test method, the last time we tried to run it.
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
public abstract class ACondition {
|
||||
|
||||
private String description = null;
|
||||
|
||||
/**
|
||||
* This method is deprecated because it is a common problem that client calls it
|
||||
* and then forgets to call the waitFor method on the created instance. This results
|
||||
* in test code that looks like it is testing something but doesn't because the
|
||||
* asserts inside the ACondition are never actually executed.
|
||||
* <p>
|
||||
* Clients should instead call one of the constructor that takes a timeout
|
||||
* as a parameter (which does the to waitFor automatically).
|
||||
*/
|
||||
@Deprecated
|
||||
public ACondition() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is deprecated because it is a common problem that client calls it
|
||||
* and then forgets to call the waitFor method on the created instance. This results
|
||||
* in test code that looks like it is testing something but doesn't because the
|
||||
* asserts inside the ACondition are never actually executed.
|
||||
* <p>
|
||||
* Clients should instead call one of the constructor that takes a timeout
|
||||
* as a parameter (which does the to waitFor automatically).
|
||||
*/
|
||||
@Deprecated
|
||||
public ACondition(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
public ACondition(long timeout) throws Exception {
|
||||
this();
|
||||
waitFor(timeout);
|
||||
}
|
||||
|
||||
public ACondition(String description, long timeout) throws Exception {
|
||||
this(description);
|
||||
waitFor(timeout);
|
||||
}
|
||||
|
||||
Throwable e = null;
|
||||
|
||||
/**
|
||||
* Deprecated. Use one of the constructors that accepts a timeout value and automatically
|
||||
* calls waitFor.
|
||||
*/
|
||||
@Deprecated
|
||||
public void waitFor(long timeout) throws Exception {
|
||||
long SLEEP_FOR = Math.min(2000, timeout/5);
|
||||
long startTime = System.currentTimeMillis();
|
||||
long endTime = startTime + timeout;
|
||||
boolean result = false;
|
||||
waitForDisplay(); //Make sure this gets called at least once to avoid 'UI thread starvation'.
|
||||
while (!(result = doTest()) && System.currentTimeMillis() < endTime) {
|
||||
waitForDisplay(); // Avoids UI deadlock by allowing UI to process events.
|
||||
try {
|
||||
Thread.sleep(SLEEP_FOR);
|
||||
} catch (InterruptedException e) {
|
||||
}
|
||||
}
|
||||
if (!result) {
|
||||
//Try our best to create a 'nice' exception reflecting the reason for the test failure
|
||||
System.err.println("ACondition "+describe()+" timed out. Dumping current Thread stacks...\n" +
|
||||
getStackDumps()
|
||||
);
|
||||
if (e!=null) {
|
||||
if (e instanceof Exception) {
|
||||
throw (Exception)e;
|
||||
} else if (e instanceof Error) {
|
||||
throw (Error)e;
|
||||
} else {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
throw new RuntimeException(getMessage());
|
||||
}
|
||||
}
|
||||
if (description!=null) {
|
||||
System.out.println(description + " succeeded after: " + (System.currentTimeMillis() - startTime));
|
||||
}
|
||||
}
|
||||
|
||||
private String describe() {
|
||||
if (description!=null) {
|
||||
return "["+description+"]";
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private boolean doTest() {
|
||||
boolean result = false;
|
||||
try {
|
||||
e = null;
|
||||
result = test();
|
||||
} catch (Throwable e) {
|
||||
this.e = e;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test something. If the method returns true, the test passes.
|
||||
* If it returns false or throws an exception the test fails (and will be
|
||||
* retried until it passes or timeout is reached).
|
||||
*/
|
||||
public abstract boolean test() throws Exception;
|
||||
|
||||
/**
|
||||
* Message used when time out reached without an exception
|
||||
*/
|
||||
public String getMessage() {
|
||||
return "timed out";
|
||||
}
|
||||
|
||||
public static void assertJobManagerIdle() {
|
||||
final IJobManager jm = Job.getJobManager();
|
||||
if (jm.isIdle()) {
|
||||
return; //OK!
|
||||
}
|
||||
//Make a nice message listing all the jobs and their present state.
|
||||
Job[] allJobs = jm.find(null);
|
||||
StringBuffer msg = new StringBuffer("JobManager not idle: \n");
|
||||
for (Job job : allJobs) {
|
||||
msg.append(" Job: "+job.getName() + " State: " + stateString(job) +"\n");
|
||||
}
|
||||
throw new AssertionFailedError(msg.toString());
|
||||
}
|
||||
|
||||
public static String stateString(Job job) {
|
||||
int state = job.getState();
|
||||
switch (state) {
|
||||
case Job.RUNNING:
|
||||
return "RUNNING";
|
||||
case Job.SLEEPING:
|
||||
return "SLEEPING";
|
||||
case Job.WAITING:
|
||||
return "WAITING";
|
||||
case Job.NONE:
|
||||
return "NONE";
|
||||
default:
|
||||
return ""+state;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A Java 8 friendlier way of using this class with a lambda.
|
||||
* <p>
|
||||
* Waits for some asserts to pass by periodically checking them until either:
|
||||
* a) the asserts all pass (i.e. asserter returns without throwing); or b)
|
||||
* the timeout is exceeded.
|
||||
*/
|
||||
public static void waitFor(String name, Duration timeout, final Asserter asserter) throws Exception {
|
||||
waitFor(name, timeout.toMillis(), asserter);
|
||||
}
|
||||
|
||||
/**
|
||||
* A Java 8 friendlier way of using this class with a lambda.
|
||||
* <p>
|
||||
* Waits for some asserts to pass by periodically checking them until either:
|
||||
* a) the asserts all pass (i.e. asserter returns without throwing); or b)
|
||||
* the timeout is exceeded.
|
||||
*/
|
||||
public static void waitFor(String name, long timeout, final Asserter asserter) throws Exception {
|
||||
new ACondition("Wait for "+name, timeout) {
|
||||
@Override
|
||||
public boolean test() throws Exception {
|
||||
asserter.execute();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows Display to process events, so UI can make progress. Tests running
|
||||
* in the UI thread may need to call this to avoid UI deadlocks.
|
||||
* <p>
|
||||
* For convenience, it is allowed to call this method from a non UI thread,
|
||||
* but such calls have no effect.
|
||||
*/
|
||||
public static void waitForDisplay() {
|
||||
if (inUIThread()) {
|
||||
try {
|
||||
while (Display.getDefault().readAndDispatch()) {
|
||||
// do nothing
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
// in e 44 this is throwing exceptions... a lot. Log them in case they contain
|
||||
// some valuable hints... but move along. These errors happen because some component
|
||||
// probably unrelated to our tests misbehaved. I suspect GTK3 may be causing
|
||||
// NPEs and other errors in the Eclipse UI code, for example. These errors seem
|
||||
// to propagate out of the 'readAndDispatch' call on e44.
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean inUIThread() {
|
||||
return Display.getDefault().getThread() == Thread.currentThread();
|
||||
}
|
||||
|
||||
public static StringBuffer getStackDumps() {
|
||||
StringBuffer sb = new StringBuffer();
|
||||
Map<Thread, StackTraceElement[]> traces = Thread.getAllStackTraces();
|
||||
for (Map.Entry<Thread, StackTraceElement[]> entry : traces.entrySet()) {
|
||||
sb.append(entry.getKey().toString());
|
||||
sb.append("\n");
|
||||
for (StackTraceElement element : entry.getValue()) {
|
||||
sb.append(" ");
|
||||
sb.append(element.toString());
|
||||
sb.append("\n");
|
||||
}
|
||||
sb.append("\n");
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2016 Pivotal Software, 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 Software, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springsource.ide.eclipse.commons.frameworks.test.util;
|
||||
|
||||
/**
|
||||
* An {@link Asserter} provides a single method which is expected
|
||||
* to check some stuff during a test (i.e. typically execute a bunch
|
||||
* of asserts).
|
||||
*
|
||||
* @author Kris De Volder
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface Asserter {
|
||||
/**
|
||||
* Called on to check some conditions during a test. Should return
|
||||
* normally to indicate 'success' and throw an exception of any type
|
||||
* to indicate 'failure'.
|
||||
*/
|
||||
void execute() throws Exception;
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<?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="src" path="src"/>
|
||||
<classpathentry kind="output" path="bin"/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,17 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>classpath-test-simple-java-project</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,11 @@
|
||||
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.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.8
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
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,5 @@
|
||||
package com.demo;
|
||||
|
||||
public class Something {
|
||||
|
||||
}
|
||||
@@ -125,10 +125,19 @@ public class Classpath {
|
||||
public void setSystem(boolean isSystem) {
|
||||
this.isSystem = isSystem;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "CPE [kind=" + kind + ", path=" + path + "]";
|
||||
}
|
||||
}
|
||||
|
||||
public static boolean isSource(CPE e) {
|
||||
return e!=null && Classpath.ENTRY_KIND_SOURCE.equals(e.getKind());
|
||||
}
|
||||
|
||||
public static boolean isBinary(CPE e) {
|
||||
return e!=null && Classpath.ENTRY_KIND_BINARY.equals(e.getKind());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,11 +10,15 @@
|
||||
*******************************************************************************/
|
||||
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;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.eclipse.core.resources.IProject;
|
||||
import org.eclipse.core.resources.ResourcesPlugin;
|
||||
@@ -22,17 +26,48 @@ import org.eclipse.core.runtime.IPath;
|
||||
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.classpath.Classpath.CPE;
|
||||
|
||||
import static org.springframework.tooling.jdt.ls.commons.Logger.*;
|
||||
|
||||
public class ClasspathUtil {
|
||||
|
||||
private static final Object JRE_CONTAINER_ID = "org.eclipse.jdt.launching.JRE_CONTAINER";
|
||||
|
||||
private static Set<String> getSystemLibraryPaths(IJavaProject javaProject) {
|
||||
try {
|
||||
IClasspathEntry jreContainer = getJreContainer(javaProject.getRawClasspath());
|
||||
IClasspathEntry[] resolvedJreEntries = ((JavaProject)javaProject).resolveClasspath(new IClasspathEntry[] {jreContainer});
|
||||
Set<String> paths = new HashSet<>();
|
||||
for (IClasspathEntry systemEntry : resolvedJreEntries) {
|
||||
paths.add(systemEntry.getPath().toString());
|
||||
}
|
||||
return paths;
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
private static IClasspathEntry getJreContainer(IClasspathEntry[] rawClasspath) {
|
||||
for (IClasspathEntry cpe : rawClasspath) {
|
||||
if (cpe.getEntryKind()==IClasspathEntry.CPE_CONTAINER) {
|
||||
if (cpe.getPath().segment(0).equals(JRE_CONTAINER_ID)) {
|
||||
return cpe;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public static Classpath resolve(IJavaProject javaProject) throws Exception {
|
||||
//log("resolving classpath " + javaProject.getElementName() +" ...");
|
||||
|
||||
List<CPE> cpEntries = new ArrayList<>();
|
||||
|
||||
|
||||
|
||||
IClasspathEntry[] entries = javaProject.getResolvedClasspath(true);
|
||||
Set<String> systemLibs = getSystemLibraryPaths(javaProject);
|
||||
|
||||
if (entries != null) {
|
||||
for (IClasspathEntry entry : entries) {
|
||||
@@ -41,6 +76,9 @@ public class ClasspathUtil {
|
||||
case Classpath.ENTRY_KIND_BINARY: {
|
||||
String path = entry.getPath().toString();
|
||||
CPE cpe = CPE.binary(path);
|
||||
if (systemLibs.contains(path)) {
|
||||
cpe.setSystem(true);
|
||||
}
|
||||
cpEntries.add(cpe);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,13 @@
|
||||
/*******************************************************************************
|
||||
* 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;
|
||||
|
||||
public interface ClientCommandExecutor {
|
||||
|
||||
@@ -98,7 +98,11 @@ public class ReusableClasspathListenerHandler {
|
||||
subscribers = null;
|
||||
}
|
||||
}
|
||||
Logger.log("subsribers = " + subscribers.keySet());
|
||||
Logger.log("subsribers = " + (subscribers == null ? "null" : subscribers.keySet()));
|
||||
}
|
||||
|
||||
public boolean isEmpty() {
|
||||
return subscribers == null || subscribers.isEmpty();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,4 +122,8 @@ public class ReusableClasspathListenerHandler {
|
||||
return "ok";
|
||||
}
|
||||
|
||||
public boolean hasNoActiveSubscriptions() {
|
||||
return subscribptions.isEmpty();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
<modules>
|
||||
<module>org.springframework.tooling.jdt.ls.extension</module>
|
||||
<module>org.springframework.tooling.jdt.ls.commons</module>
|
||||
<module>org.springframework.tooling.jdt.ls.commons.test</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
|
||||
Reference in New Issue
Block a user