Merge branch 'master' of github.com:spring-projects/sts4

Conflicts:
	headless-services/commons/commons-util/src/main/java/org/springframework/ide/vscode/commons/util/StringUtil.java
This commit is contained in:
Kris De Volder
2017-11-16 15:03:53 -08:00
42 changed files with 1097 additions and 259 deletions

View File

@@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java;
import java.nio.file.Paths;
import java.time.Duration;
import java.util.Arrays;
@@ -21,6 +22,7 @@ import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectCache;
import org.springframework.ide.vscode.commons.gradle.GradleProjectFinder;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeProjectOvserver;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
@@ -60,10 +62,10 @@ public class BootJavaLanguageServerParams {
// Initialize project finders, project caches and project observers
FileObserver fileObserver = server.getWorkspaceService().getFileObserver();
CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder();
MavenProjectCache mavenProjectCache = new MavenProjectCache(fileObserver, MavenCore.getDefault());
MavenProjectCache mavenProjectCache = new MavenProjectCache(fileObserver, MavenCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER));
javaProjectFinder.addJavaProjectFinder(new MavenProjectFinder(mavenProjectCache));
GradleProjectCache gradleProjectCache = new GradleProjectCache(fileObserver, GradleCore.getDefault());
GradleProjectCache gradleProjectCache = new GradleProjectCache(fileObserver, GradleCore.getDefault(), true, Paths.get(IJavaProject.PROJECT_CACHE_FOLDER));
javaProjectFinder.addJavaProjectFinder(new GradleProjectFinder(gradleProjectCache));
CompositeProjectOvserver projectObserver = new CompositeProjectOvserver(Arrays.asList(mavenProjectCache, gradleProjectCache));
@@ -78,5 +80,29 @@ public class BootJavaLanguageServerParams {
};
}
public static LSFactory<BootJavaLanguageServerParams> createTestDefault() {
return (SimpleLanguageServer server) -> {
// Initialize project finders, project caches and project observers
FileObserver fileObserver = server.getWorkspaceService().getFileObserver();
CompositeJavaProjectFinder javaProjectFinder = new CompositeJavaProjectFinder();
MavenProjectCache mavenProjectCache = new MavenProjectCache(fileObserver, MavenCore.getDefault(), false, null);
mavenProjectCache.setAlwaysFireEventOnFileChanged(true);
javaProjectFinder.addJavaProjectFinder(new MavenProjectFinder(mavenProjectCache));
GradleProjectCache gradleProjectCache = new GradleProjectCache(fileObserver, GradleCore.getDefault(), false, null);
gradleProjectCache.setAlwaysFireEventOnFileChanged(true);
javaProjectFinder.addJavaProjectFinder(new GradleProjectFinder(gradleProjectCache));
CompositeProjectOvserver projectObserver = new CompositeProjectOvserver(Arrays.asList(mavenProjectCache, gradleProjectCache));
return new BootJavaLanguageServerParams(
javaProjectFinder.filter(BootProjectUtil::isBootProject),
projectObserver,
new DefaultSpringPropertyIndexProvider(javaProjectFinder, projectObserver),
RunningAppProvider.DEFAULT,
SpringLiveHoverWatchdog.DEFAULT_INTERVAL
);
};
}
}

View File

@@ -140,18 +140,18 @@ public class ConditionalsLiveHoverProvider implements HoverProvider {
// Check that Java type in annotation in editor matches Java information in the live Conditional
ASTNode parent = annotation.getParent();
String rawJsonKey = liveConditional.getPositiveMatchKey();
String typeInfo = liveConditional.getTypeInfo();
if (parent instanceof MethodDeclaration) {
MethodDeclaration methodDec = (MethodDeclaration) parent;
IMethodBinding binding = methodDec.resolveBinding();
String annotationDeclaringClassName = binding.getDeclaringClass().getName();
String annotationMethodName = binding.getName();
return rawJsonKey.contains(annotationDeclaringClassName) && rawJsonKey.contains(annotationMethodName);
return typeInfo.contains(annotationDeclaringClassName) && typeInfo.contains(annotationMethodName);
} else if (parent instanceof TypeDeclaration) {
TypeDeclaration typeDec = (TypeDeclaration) parent;
String annotationDeclaringClassName = typeDec.resolveBinding().getName();
return rawJsonKey.contains(annotationDeclaringClassName);
return typeInfo.contains(annotationDeclaringClassName);
}
return false;
}

View File

@@ -110,7 +110,7 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(doc.getUri())).get();
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
Stream<Path> classpathEntries = classpath.getClasspathEntries().stream();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);

View File

@@ -213,7 +213,7 @@ public class BootJavaHoverProvider implements HoverHandler {
try {
IClasspath classpath = project.getClasspath();
if (classpath!=null) {
return classpath.getClasspathEntries().anyMatch(cpe -> {
return classpath.getClasspathEntries().stream().anyMatch(cpe -> {
String name = cpe.getFileName().toString();
return name.startsWith("spring-boot-actuator-");
});

View File

@@ -126,7 +126,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler {
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(new TextDocumentIdentifier(doc.getUri())).get();
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
Stream<Path> classpathEntries = classpath.getClasspathEntries().stream();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);

View File

@@ -22,7 +22,7 @@ public class BootProjectUtil {
try {
IClasspath cp = jp.getClasspath();
if (cp!=null) {
return cp.getClasspathEntries().anyMatch(cpe -> isBootEntry(cpe));
return cp.getClasspathEntries().stream().anyMatch(cpe -> isBootEntry(cpe));
}
} catch (Exception e) {
Log.log(e);

View File

@@ -133,7 +133,7 @@ public final class CompilationUnitCache {
return new String[0];
} else {
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
Stream<Path> classpathEntries = classpath.getClasspathEntries().stream();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);

View File

@@ -55,6 +55,7 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -242,7 +243,7 @@ public class SpringIndexer {
try {
initializeTask.get();
return allsymbols.stream()
.filter(symbol -> containsCharacters(symbol.getName().toCharArray(), query.toCharArray()))
.filter(symbol -> StringUtil.containsCharactersCaseInsensitive(symbol.getName(), query))
.collect(Collectors.toList());
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
@@ -251,20 +252,6 @@ public class SpringIndexer {
return null;
}
private boolean containsCharacters(char[] symbolChars, char[] queryChars) {
int symbolindex = 0;
int queryindex = 0;
while (queryindex < queryChars.length && symbolindex < symbolChars.length) {
if (symbolChars[symbolindex] == queryChars[queryindex]) {
queryindex++;
}
symbolindex++;
}
return queryindex == queryChars.length;
}
private void scanFiles(File directory) {
try {
Map<Optional<IJavaProject>, List<String>> projects = Files.walk(directory.toPath())
@@ -456,7 +443,7 @@ public class SpringIndexer {
private String[] getClasspathEntries(IJavaProject project) throws Exception {
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
Stream<Path> classpathEntries = classpath.getClasspathEntries().stream();
return classpathEntries
.filter(path -> path.toFile().exists())
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);

View File

@@ -69,7 +69,7 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("22022").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"ConditionalOnBeanConfig#hi\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found bean 'missing'\"}]}}")
.build();
@@ -93,7 +93,7 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("22022").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
.build();
@@ -116,7 +116,7 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("22022").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"HelloConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}],\"HelloConfig2#hi\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found bean 'missing'\"}],\"MultipleConditionals#hi\":[{\"condition\":\"OnClassCondition\",\"message\":\"@ConditionalOnClass found required class; @ConditionalOnMissingClass did not find unwanted class\"},{\"condition\":\"OnWebApplicationCondition\",\"message\":\"@ConditionalOnWebApplication (required) found StandardServletEnvironment\"},{\"condition\":\"OnJavaCondition\",\"message\":\"@ConditionalOnJava (1.8 or newer) found 1.8\"},{\"condition\":\"OnExpressionCondition\",\"message\":\"@ConditionalOnExpression (#{true}) resulted in true\"},{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found beans 'hi', 'missing'\"}]}}")
.build();
@@ -158,19 +158,19 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1000").processId("70000").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
.build();
mockAppProvider.builder().isSpringBootApp(true).port("1001").processId("80000").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
.build();
mockAppProvider.builder().isSpringBootApp(true).port("1002").processId("90000").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"ConditionalOnMissingBeanConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}]}}")
.build();
@@ -218,7 +218,7 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1000").processId("70000").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"HelloConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}],\"HelloConfig2#hi\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found bean 'missing'\"}],\"MultipleConditionals#hi\":[{\"condition\":\"OnClassCondition\",\"message\":\"@ConditionalOnClass found required class; @ConditionalOnMissingClass did not find unwanted class\"},{\"condition\":\"OnWebApplicationCondition\",\"message\":\"@ConditionalOnWebApplication (required) found StandardServletEnvironment\"},{\"condition\":\"OnJavaCondition\",\"message\":\"@ConditionalOnJava (1.8 or newer) found 1.8\"},{\"condition\":\"OnExpressionCondition\",\"message\":\"@ConditionalOnExpression (#{true}) resulted in true\"},{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found beans 'hi', 'missing'\"}]}}")
.build();
@@ -264,7 +264,7 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1000").processId("70000").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"MultipleConditionalsPT152535713#hi\":[{\"condition\":\"OnWebApplicationCondition\",\"message\":\"@ConditionalOnWebApplication (required) found StandardServletEnvironment\"},{\"condition\":\"OnJavaCondition\",\"message\":\"@ConditionalOnJava (1.8 or newer) found 1.8\"}]}}")
.build();
@@ -290,7 +290,7 @@ public class ConditionalsLiveHoverTest {
}
@Test
public void testHighlights() throws Exception {
public void testHighlightsMethodConditionals() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-conditionals-live-hover/").toURI());
@@ -299,18 +299,131 @@ public class ConditionalsLiveHoverTest {
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("22022").host("cfapps.io")
.processName("test-conditionals-live-hover")
.positiveMatchesJsonForLiveConditionals(
.liveConditionalsJson(
"{\"positiveMatches\":{\"HelloConfig#missing\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnMissingBean (types: example.Hello; SearchStrategy: all) did not find any beans\"}],\"HelloConfig2#hi\":[{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found bean 'missing'\"}],\"MultipleConditionals#hi\":[{\"condition\":\"OnClassCondition\",\"message\":\"@ConditionalOnClass found required class; @ConditionalOnMissingClass did not find unwanted class\"},{\"condition\":\"OnWebApplicationCondition\",\"message\":\"@ConditionalOnWebApplication (required) found StandardServletEnvironment\"},{\"condition\":\"OnJavaCondition\",\"message\":\"@ConditionalOnJava (1.8 or newer) found 1.8\"},{\"condition\":\"OnExpressionCondition\",\"message\":\"@ConditionalOnExpression (#{true}) resulted in true\"},{\"condition\":\"OnBeanCondition\",\"message\":\"@ConditionalOnBean (types: example.Hello; SearchStrategy: all) found beans 'hi', 'missing'\"}]}}")
.build();
harness.intialize(directory);
String content = "package example;\n" +
"\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnJava;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingClass;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnNotWebApplication;\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;\n" +
"import org.springframework.context.annotation.Bean;\n" +
"import org.springframework.context.annotation.Configuration;\n" +
"\n" +
"@Configuration\n" +
"public class MultipleConditionals {\n" +
"\n" +
" @Bean\n" +
" @ConditionalOnBean\n" +
" @ConditionalOnWebApplication\n" +
" @ConditionalOnJava(value=ConditionalOnJava.JavaVersion.EIGHT)\n" +
" @ConditionalOnMissingClass\n" +
" @ConditionalOnExpression\n" +
" public Hello hi() {\n" +
" return null;\n" +
" }\n" +
"}";
Editor editor = harness.newEditorFromFileUri(docUri, LanguageId.JAVA);
Editor editor = harness.newEditor( LanguageId.JAVA, content, docUri);
editor.assertHighlights("@ConditionalOnBean", "@ConditionalOnWebApplication",
"@ConditionalOnJava(value=ConditionalOnJava.JavaVersion.EIGHT)", "@ConditionalOnMissingClass",
"@ConditionalOnExpression");
}
@Test
public void testHighlightsTypeConditionals() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-conditionals-live-hover/").toURI());
String docUri = "file://" + directory.getAbsolutePath() + "/src/main/java/example/MultipleConditionals.java";
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("22022").host("cfapps.io")
.processName("test-conditionals-live-hover")
.liveConditionalsJson(
"{\"negativeMatches\": {\n" +
" \"MyConditionalComponent\": {\n" +
" \"notMatched\": [\n" +
" {\n" +
" \"condition\": \"OnClassCondition\",\n" +
" \"message\": \"@ConditionalOnClass did not find required class 'java.lang.String2'\"\n" +
" }\n" +
" ],\n" +
" \"matched\": []\n" +
" }\n"
+ "}\n"
+ "}")
.build();
harness.intialize(directory);
String content = "package com.example;\n" +
"\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\n" +
"import org.springframework.stereotype.Component;\n" +
"\n" +
"@Component\n" +
"@ConditionalOnClass(name=\"java.lang.String2\")\n" +
"public class MyConditionalComponent {\n" +
"}";
Editor editor = harness.newEditor( LanguageId.JAVA, content, docUri);
editor.assertHighlights("@ConditionalOnClass(name=\"java.lang.String2\")");
}
@Test
public void testNegativeMatches() throws Exception {
File directory = new File(
ProjectsHarness.class.getResource("/test-projects/test-conditionals-live-hover/").toURI());
String docUri = "file://" + directory.getAbsolutePath() + "/src/main/java/example/MultipleConditionals.java";
// Build a mock running boot app
mockAppProvider.builder().isSpringBootApp(true).port("1111").processId("67950").host("cfapps.io")
.processName("test-conditionals-live-hover")
.liveConditionalsJson(
"{\"negativeMatches\": {\n" +
" \"MyConditionalComponent\": {\n" +
" \"notMatched\": [\n" +
" {\n" +
" \"condition\": \"OnClassCondition\",\n" +
" \"message\": \"@ConditionalOnClass did not find required class 'java.lang.String2'\"\n" +
" }\n" +
" ],\n" +
" \"matched\": []\n" +
" }\n"
+ "}\n"
+ "}")
.build();
harness.intialize(directory);
String content = "package com.example;\n" +
"\n" +
"import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;\n" +
"import org.springframework.stereotype.Component;\n" +
"\n" +
"@Component\n" +
"@ConditionalOnClass(name=\"java.lang.String2\")\n" +
"public class MyConditionalComponent {\n" +
"}";
Editor editor = harness.newEditor( LanguageId.JAVA, content, docUri);
editor.assertHoverContains("@ConditionalOnClass(name=\"java.lang.String2\")", "@ConditionalOnClass did not find required class 'java.lang.String2'\n" +
"\n" +
"Process [PID=67950, name=`test-conditionals-live-hover`]");
}
}

View File

@@ -43,7 +43,7 @@ public class BootLanguageServerHarness extends LanguageServerHarness<BootJavaLan
public static class Builder {
LSFactory<BootJavaLanguageServerParams> defaultsFactory = BootJavaLanguageServerParams.createDefault();
LSFactory<BootJavaLanguageServerParams> defaultsFactory = BootJavaLanguageServerParams.createTestDefault();
private JavaProjectFinder projectFinder = null;
private ProjectObserver projectObserver = null;
private SpringPropertyIndexProvider indexProvider = null;
@@ -92,7 +92,7 @@ public class BootLanguageServerHarness extends LanguageServerHarness<BootJavaLan
private BootLanguageServerHarness(Builder builder) throws Exception {
super(() -> {
LSFactory<BootJavaLanguageServerParams> params = (server) -> {
BootJavaLanguageServerParams defaults = BootJavaLanguageServerParams.createDefault().create(server);
BootJavaLanguageServerParams defaults = BootJavaLanguageServerParams.createTestDefault().create(server);
return new BootJavaLanguageServerParams(
builder.projectFinder==null?defaults.projectFinder:builder.projectFinder,
builder.projectObserver==null?defaults.projectObserver:builder.projectObserver,

View File

@@ -111,12 +111,7 @@ public class MockRunningAppProvider {
return this;
}
public MockAppBuilder autoConfigReport(String autoConfigReport) throws Exception {
when(app.getAutoConfigReport()).thenReturn(autoConfigReport);
return this;
}
public MockAppBuilder positiveMatchesJsonForLiveConditionals(String rawJson) throws Exception{
public MockAppBuilder liveConditionalsJson(String rawJson) throws Exception{
when(app.getLiveConditionals()).thenReturn(SpringBootApp.getLiveConditionals(rawJson, processId, processName));
return this;
}

View File

@@ -22,11 +22,4 @@ public class MultipleConditionals {
public Hello hi() {
return null;
}
@Bean
@ConditionalOnMissingBean
@ConditionalOnNotWebApplication
public Hello missing() {
return null;
}
}