PT #164216122: JDT LS search performance improvement 1

This commit is contained in:
BoykoAlex
2019-03-05 20:31:03 -05:00
parent b865a0d0a5
commit d994d2abcd
19 changed files with 447 additions and 107586 deletions

View File

@@ -87,32 +87,32 @@ public class JavaLangugeClientTest {
@Test @Test
public void fuzzyFindTypesIncludingSysLibs() throws Exception { public void fuzzyFindTypesIncludingSysLibs() throws Exception {
List<TypeData> data = client List<String> data = client
.javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, true)) .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, true))
.get(100, TimeUnit.SECONDS); .get(100, TimeUnit.SECONDS);
assertNotNull(data); assertNotNull(data);
assertTrue(data.size() > 500); assertTrue(data.size() > 500);
List<TypeData> closeMatches = data.stream().filter(t -> t.getFqName().contains("util.Map")).collect(Collectors.toList()); List<String> closeMatches = data.stream().filter(t -> t.contains("util.Map")).collect(Collectors.toList());
assertEquals(2, closeMatches.size()); assertEquals(2, closeMatches.size());
assertNotNull(closeMatches.stream().filter(t -> "java.util.Map".equals(t.getFqName())).findFirst().orElse(null)); assertNotNull(closeMatches.stream().filter(t -> "java.util.Map".equals(t)).findFirst().orElse(null));
} }
@Test @Test
public void fuzzyFindTypesExcludingSysLibs() throws Exception { public void fuzzyFindTypesExcludingSysLibs() throws Exception {
List<TypeData> data = client List<String> data = client
.javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, false)) .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, false))
.get(10, TimeUnit.SECONDS); .get(10, TimeUnit.SECONDS);
assertNotNull(data); assertNotNull(data);
assertEquals(186, data.size()); assertEquals(186, data.size());
TestUtils.saveJsonData("search-util-map.json", data); // TestUtils.saveJsonData("search-util-map.json", data);
List<TypeData> closeMatches = data.stream().filter(t -> t.getFqName().contains("util.Map")).collect(Collectors.toList()); List<String> closeMatches = data.stream().filter(t -> t.contains("util.Map")).collect(Collectors.toList());
assertEquals(1, closeMatches.size()); assertEquals(1, closeMatches.size());
assertEquals("io.netty.util.Mapping", closeMatches.get(0).getFqName()); assertEquals("io.netty.util.Mapping", closeMatches.get(0));
} }
@Test @Test
public void fuzzyFindAllTypesExcludingSysLibs() throws Exception { public void fuzzyFindAllTypesExcludingSysLibs() throws Exception {
List<TypeData> data = client List<String> data = client
.javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "", true, false)) .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "", true, false))
.get(1000, TimeUnit.SECONDS); .get(1000, TimeUnit.SECONDS);
assertNotNull(data); assertNotNull(data);

View File

@@ -126,7 +126,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
final private JavaData javaData = new JavaData(STS4LanguageClientImpl::label , Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance)); final private JavaData javaData = new JavaData(STS4LanguageClientImpl::label , Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance));
final private JavaSearch javaSearch = new JavaSearch(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance), javaData); final private JavaSearch javaSearch = new JavaSearch(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance));
final private TypeHierarchy typeHierarchy = new TypeHierarchy(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance), javaData); final private TypeHierarchy typeHierarchy = new TypeHierarchy(Logger.forEclipsePlugin(LanguageServerCommonsActivator::getInstance), javaData);
@@ -440,7 +440,7 @@ public class STS4LanguageClientImpl extends LanguageClientImpl implements STS4La
} }
@Override @Override
public CompletableFuture<List<TypeData>> javaSearchTypes(JavaSearchParams params) { public CompletableFuture<List<String>> javaSearchTypes(JavaSearchParams params) {
return CompletableFuture.supplyAsync(() -> { return CompletableFuture.supplyAsync(() -> {
try { try {
return javaSearch.fuzzySearchTypes(URI.create(params.getProjectUri()), params.getTerm(), return javaSearch.fuzzySearchTypes(URI.create(params.getProjectUri()), params.getTerm(),

View File

@@ -17,7 +17,6 @@ import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Queue; import java.util.Queue;
import java.util.Set; import java.util.Set;
import java.util.function.Predicate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@@ -37,6 +36,7 @@ import reactor.core.Disposable;
import reactor.core.Disposables; import reactor.core.Disposables;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.util.function.Tuple2; import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
/** /**
* Classpath with Jandex Java index for searching types * Classpath with Jandex Java index for searching types
@@ -101,8 +101,8 @@ public final class JandexClasspath implements ClasspathIndex {
} }
@Override @Override
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs, Predicate<IType> typeFilter) { public Flux<Tuple2<String, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs) {
return javaIndex.get().fuzzySearchTypes(searchTerm, typeFilter); return javaIndex.get().fuzzySearchTypes(searchTerm).map(m -> Tuples.of(m.getT2().name().toString(), m.getT3()));
} }
@Override @Override

View File

@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2016, 2018 Pivotal, Inc. * Copyright (c) 2016, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@@ -13,7 +13,6 @@ package org.springframework.ide.vscode.commons.jandex;
import java.io.File; import java.io.File;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.function.Predicate;
import org.jboss.jandex.ClassInfo; import org.jboss.jandex.ClassInfo;
import org.jboss.jandex.DotName; import org.jboss.jandex.DotName;
@@ -29,7 +28,6 @@ import com.google.common.cache.CacheBuilder;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.util.function.Tuple2; import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;
public class JandexIndex extends BasicJandexIndex { public class JandexIndex extends BasicJandexIndex {
@@ -83,12 +81,6 @@ public class JandexIndex extends BasicJandexIndex {
return Wrappers.wrap(this, match.getT1(), match.getT2(), javadocProvider); return Wrappers.wrap(this, match.getT1(), match.getT2(), javadocProvider);
} }
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, Predicate<IType> typeFilter) {
return fuzzySearchTypes(searchTerm)
.map(match -> Tuples.of(createType(Tuples.of(match.getT1(), match.getT2())), match.getT3()))
.filter(t -> typeFilter == null || typeFilter.test(t.getT1()));
}
public Flux<IType> allSubtypesOf(IType type) { public Flux<IType> allSubtypesOf(IType type) {
DotName name = DotName.createSimple(type.getFullyQualifiedName()); DotName name = DotName.createSimple(type.getFullyQualifiedName());
return allSubtypesOf(name, type.isInterface()).map(match -> createType(match)); return allSubtypesOf(name, type.isInterface()).map(match -> createType(match));

View File

@@ -10,8 +10,6 @@
*******************************************************************************/ *******************************************************************************/
package org.springframework.ide.vscode.commons.java; package org.springframework.ide.vscode.commons.java;
import java.util.function.Predicate;
import reactor.core.Disposable; import reactor.core.Disposable;
import reactor.core.publisher.Flux; import reactor.core.publisher.Flux;
import reactor.util.function.Tuple2; import reactor.util.function.Tuple2;
@@ -19,7 +17,7 @@ import reactor.util.function.Tuple2;
public interface ClasspathIndex extends Disposable { public interface ClasspathIndex extends Disposable {
IType findType(String fqName); IType findType(String fqName);
Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs, Predicate<IType> typeFilter); Flux<Tuple2<String, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs);
Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm, boolean includeBinaries, boolean includeSystemLibs); Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm, boolean includeBinaries, boolean includeSystemLibs);
Flux<IType> allSubtypesOf(IType type); Flux<IType> allSubtypesOf(IType type);
Flux<IType> allSuperTypesOf(IType type); Flux<IType> allSuperTypesOf(IType type);

View File

@@ -123,4 +123,8 @@ public class JavaUtils {
return null; return null;
} }
public static String typeBindingKeyToFqName(String bindingKey) {
return bindingKey == null ? null : bindingKey.substring(1, bindingKey.length() - 1).replace('/', '.');
}
} }

View File

@@ -16,13 +16,13 @@ import java.util.Optional;
import java.util.concurrent.ExecutionException; import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException; import java.util.concurrent.TimeoutException;
import java.util.function.Predicate;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.commons.java.ClasspathIndex; import org.springframework.ide.vscode.commons.java.ClasspathIndex;
import org.springframework.ide.vscode.commons.java.IJavaModuleData; import org.springframework.ide.vscode.commons.java.IJavaModuleData;
import org.springframework.ide.vscode.commons.java.IType; import org.springframework.ide.vscode.commons.java.IType;
import org.springframework.ide.vscode.commons.java.JavaUtils;
import org.springframework.ide.vscode.commons.javadoc.JdtLsJavadocProvider; import org.springframework.ide.vscode.commons.javadoc.JdtLsJavadocProvider;
import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient; import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient;
import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams; import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams;
@@ -63,7 +63,7 @@ public class JdtLsIndex implements ClasspathIndex {
private IType toType(TypeData data) { private IType toType(TypeData data) {
String declaringTypeBindingKey = data.getDeclaringType(); String declaringTypeBindingKey = data.getDeclaringType();
String declaringTypeFqName = declaringTypeBindingKey == null ? null : declaringTypeBindingKey.substring(1, declaringTypeBindingKey.length() - 1).replace('/', '.'); String declaringTypeFqName = JavaUtils.typeBindingKeyToFqName(declaringTypeBindingKey);
return Wrappers.wrap(data, Suppliers.memoize(() -> declaringTypeFqName == null ? null : findType(declaringTypeFqName)), javadocProvider); return Wrappers.wrap(data, Suppliers.memoize(() -> declaringTypeFqName == null ? null : findType(declaringTypeFqName)), javadocProvider);
} }
@@ -89,14 +89,12 @@ public class JdtLsIndex implements ClasspathIndex {
} }
@Override @Override
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs, Predicate<IType> typeFilter) { public Flux<Tuple2<String, Double>> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs) {
JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, includeBinaries, includeSystemLibs); JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, includeBinaries, includeSystemLibs);
return Mono.fromFuture(client.javaSearchTypes(searchParams)) return Mono.fromFuture(client.javaSearchTypes(searchParams))
.flatMapMany(results -> Flux.fromIterable(results).publishOn(Schedulers.parallel())) .flatMapMany(results -> Flux.fromIterable(results).publishOn(Schedulers.parallel()))
.filter(Objects::nonNull) .filter(Objects::nonNull)
.map(this::toType) .map(type -> Tuples.of(type, FuzzyMatcher.matchScore(searchTerm, type)))
.filter(t -> typeFilter == null || typeFilter.test(t))
.map(type -> Tuples.of(type, FuzzyMatcher.matchScore(searchTerm, type.getFullyQualifiedName())))
.filter(tuple -> tuple.getT2() != 0.0); .filter(tuple -> tuple.getT2() != 0.0);
} }

View File

@@ -51,9 +51,9 @@ public class JdtLsIndexTest {
return gson.fromJson(new FileReader(jsonFile), TypeData.class); return gson.fromJson(new FileReader(jsonFile), TypeData.class);
} }
private List<TypeData> loadJsonSearchTypeResults(String fileName) throws Exception { private List<String> loadJsonSearchTypeResults(String fileName) throws Exception {
File jsonFile = new File(JdtLsIndexTest.class.getResource("/java-data-json/" + fileName).toURI()); File jsonFile = new File(JdtLsIndexTest.class.getResource("/java-data-json/" + fileName).toURI());
Type listType = new TypeToken<List<TypeData>>(){}.getType(); Type listType = new TypeToken<List<String>>(){}.getType();
return gson.fromJson(new FileReader(jsonFile), listType); return gson.fromJson(new FileReader(jsonFile), listType);
} }
@@ -138,9 +138,9 @@ public class JdtLsIndexTest {
})); }));
// Some valid URI necessary for URI#toString() to succeed // Some valid URI necessary for URI#toString() to succeed
JdtLsIndex index = new JdtLsIndex(client, URI.create(System.getProperty("java.io.tmpdir"))); JdtLsIndex index = new JdtLsIndex(client, URI.create(System.getProperty("java.io.tmpdir")));
List<Tuple2<IType, Double>> results = index.fuzzySearchTypes("util.Map", true, false, null).collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())).block(); List<Tuple2<String, Double>> results = index.fuzzySearchTypes("util.Map", true, false).collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())).block();
IType type = results.get(0).getT1(); String type = results.get(0).getT1();
assertEquals("io.netty.util.Mapping", type.getFullyQualifiedName()); assertEquals("io.netty.util.Mapping", type);
} }
@Test @Test

View File

@@ -59,7 +59,7 @@ public interface STS4LanguageClient extends LanguageClient {
CompletableFuture<Location> javaLocation(JavaDataParams params); CompletableFuture<Location> javaLocation(JavaDataParams params);
@JsonRequest("sts/javaSearchTypes") @JsonRequest("sts/javaSearchTypes")
CompletableFuture<List<TypeData>> javaSearchTypes(JavaSearchParams params); CompletableFuture<List<String>> javaSearchTypes(JavaSearchParams params);
@JsonRequest("sts/javaSearchPackages") @JsonRequest("sts/javaSearchPackages")
CompletableFuture<List<String>> javaSearchPackages(JavaSearchParams params); CompletableFuture<List<String>> javaSearchPackages(JavaSearchParams params);

View File

@@ -28,7 +28,6 @@ import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import org.junit.Test; import org.junit.Test;
import org.springframework.ide.vscode.commons.java.Flags;
import org.springframework.ide.vscode.commons.java.IJavaModuleData; import org.springframework.ide.vscode.commons.java.IJavaModuleData;
import org.springframework.ide.vscode.commons.java.IMethod; import org.springframework.ide.vscode.commons.java.IMethod;
import org.springframework.ide.vscode.commons.java.IPrimitiveType; import org.springframework.ide.vscode.commons.java.IPrimitiveType;
@@ -62,26 +61,12 @@ public class JavaIndexTest {
@Test @Test
public void fuzzySearchNoFilter() throws Exception { public void fuzzySearchNoFilter() throws Exception {
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file"); MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
List<Tuple2<IType, Double>> results = project.getIndex().fuzzySearchTypes("util.Map", true, true, null) List<Tuple2<String, Double>> results = project.getIndex().fuzzySearchTypes("util.Map", true, true)
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())) .collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.block(); .block();
assertTrue(results.size() > 10); assertTrue(results.size() > 10);
IType type = results.get(0).getT1(); String type = results.get(0).getT1();
System.out.println(type.getFullyQualifiedName() + ": " + type.getBindingKey()); assertEquals("java.util.Map", type);
assertEquals("java.util.Map", type.getFullyQualifiedName());
}
@Test
public void fuzzySearchWithFilter() throws Exception {
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");
List<Tuple2<IType, Double>> results = project.getIndex()
.fuzzySearchTypes("util.Map", true, true, (type) -> Flags.isPrivate(type.getFlags()))
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.block();
assertTrue(results.size() > 10);
IType type = results.get(0).getT1();
System.out.println(type.getFullyQualifiedName() + ": " + type.getBindingKey());
assertEquals("java.util.EnumMap$KeySet", type.getFullyQualifiedName());
} }
@Test @Test

View File

@@ -85,7 +85,6 @@ import org.eclipse.lsp4j.ResourceOperation;
import org.eclipse.lsp4j.ResourceOperationKind; import org.eclipse.lsp4j.ResourceOperationKind;
import org.eclipse.lsp4j.ShowMessageRequestParams; import org.eclipse.lsp4j.ShowMessageRequestParams;
import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.SymbolKindCapabilities;
import org.eclipse.lsp4j.TextDocumentClientCapabilities; import org.eclipse.lsp4j.TextDocumentClientCapabilities;
import org.eclipse.lsp4j.TextDocumentContentChangeEvent; import org.eclipse.lsp4j.TextDocumentContentChangeEvent;
import org.eclipse.lsp4j.TextDocumentEdit; import org.eclipse.lsp4j.TextDocumentEdit;
@@ -363,7 +362,7 @@ public class LanguageServerHarness {
} }
@Override @Override
public CompletableFuture<List<TypeData>> javaSearchTypes(JavaSearchParams params) { public CompletableFuture<List<String>> javaSearchTypes(JavaSearchParams params) {
return CompletableFuture.completedFuture(Collections.emptyList()); return CompletableFuture.completedFuture(Collections.emptyList());
} }

View File

@@ -16,7 +16,6 @@ import java.util.stream.Stream;
import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IType; import org.eclipse.jdt.core.IType;
import org.springframework.ide.vscode.commons.protocol.java.TypeData;
import org.springframework.tooling.jdt.ls.commons.Logger; import org.springframework.tooling.jdt.ls.commons.Logger;
import org.springframework.tooling.jdt.ls.commons.resources.ResourceUtils; import org.springframework.tooling.jdt.ls.commons.resources.ResourceUtils;
@@ -24,12 +23,9 @@ public class JavaSearch {
private Logger logger; private Logger logger;
private JavaData javaData; public JavaSearch(Logger logger) {
public JavaSearch(Logger logger, JavaData javaData) {
super(); super();
this.logger = logger; this.logger = logger;
this.javaData = javaData;
} }
public Stream<String> fuzzySearchPackages(URI projectUri, String searchTerm, boolean includeBinaries, boolean includeSystemLibs) throws Exception { public Stream<String> fuzzySearchPackages(URI projectUri, String searchTerm, boolean includeBinaries, boolean includeSystemLibs) throws Exception {
@@ -44,16 +40,16 @@ public class JavaSearch {
.map(p -> ((IPackageFragment)p).getElementName()); .map(p -> ((IPackageFragment)p).getElementName());
} }
public Stream<TypeData> fuzzySearchTypes(URI projectUri, String searchTerm, boolean includeBinaries, boolean includeSystemLibs) throws Exception { public Stream<String> fuzzySearchTypes(URI projectUri, String searchTerm, boolean includeBinaries, boolean includeSystemLibs) throws Exception {
IJavaProject javaProject = projectUri == null ? null : ResourceUtils.getJavaProject(projectUri); IJavaProject javaProject = projectUri == null ? null : ResourceUtils.getJavaProject(projectUri);
return new StreamJdtSearch(logger) return new StreamJdtSearch(logger)
.scope(StreamJdtSearch.searchScope(javaProject, includeBinaries, includeSystemLibs)) .scope(StreamJdtSearch.searchScope(javaProject, includeBinaries, includeSystemLibs))
.pattern(StreamJdtSearch.toTypePattern(StreamJdtSearch.toWildCardPattern(searchTerm))) .pattern(StreamJdtSearch.toTypePattern(StreamJdtSearch.toWildCardPattern(StreamJdtSearch.toProperTypeQuery(searchTerm))))
.search() .search()
.parallel() .parallel()
.map(match -> match.getElement()) .map(match -> match.getElement())
.filter(o -> o instanceof IType) .filter(o -> o instanceof IType)
.map(e -> javaData.createTypeData((IType) e)); .map(e -> ((IType) e).getFullyQualifiedName());
} }
} }

View File

@@ -215,6 +215,15 @@ public class StreamJdtSearch {
int matchRule = SearchPattern.R_PATTERN_MATCH; int matchRule = SearchPattern.R_PATTERN_MATCH;
return SearchPattern.createPattern(wildCardedQuery, searchFor, limitTo, matchRule); return SearchPattern.createPattern(wildCardedQuery, searchFor, limitTo, matchRule);
} }
public static String toProperTypeQuery(String query) {
int idx = query.lastIndexOf('.');
if (idx > 0 && idx < query.length() - 1 && Character.isLowerCase(query.charAt(idx + 1))) {
return query + '.';
} else {
return query;
}
}
} }

View File

@@ -26,7 +26,7 @@ public class JavaHelpers {
final public static Supplier<JavaData> DATA = Suppliers.memoize(() -> new JavaData(element -> HoverInfoProvider.computeSignature(element).getValue(), logger)); final public static Supplier<JavaData> DATA = Suppliers.memoize(() -> new JavaData(element -> HoverInfoProvider.computeSignature(element).getValue(), logger));
final public static Supplier<JavaSearch> SEARCH = Suppliers.memoize(() -> new JavaSearch(logger, DATA.get())); final public static Supplier<JavaSearch> SEARCH = Suppliers.memoize(() -> new JavaSearch(logger));
final public static Supplier<TypeHierarchy> HIERARCHY = Suppliers.memoize(() -> new TypeHierarchy(logger, DATA.get())); final public static Supplier<TypeHierarchy> HIERARCHY = Suppliers.memoize(() -> new TypeHierarchy(logger, DATA.get()));

View File

@@ -22,6 +22,7 @@ import org.springframework.ide.vscode.boot.metadata.hints.StsValueHint;
import org.springframework.ide.vscode.commons.java.IJavaProject; import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FuzzyMatcher; import org.springframework.ide.vscode.commons.util.FuzzyMatcher;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder; import com.google.common.collect.ImmutableSet.Builder;
@@ -84,8 +85,8 @@ public class LoggerNameProvider extends CachingValueProvider {
.fuzzySearchPackages(query, true, false) .fuzzySearchPackages(query, true, false)
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())), .map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())),
javaProject.getIndex() javaProject.getIndex()
.fuzzySearchTypes(query, true, false, null) .fuzzySearchTypes(query, true, false)
.map(t -> Tuples.of(StsValueHint.create(sourceLinks, javaProject, t.getT1()), t.getT2())) .map(t -> Tuples.of(StsValueHint.create(sourceLinks, t.getT1(), javaProject, Suppliers.memoize(() -> javaProject.getIndex().findType(t.getT1()))), t.getT2()))
) )
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2())) .collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.flatMapIterable(l -> l) .flatMapIterable(l -> l)

View File

@@ -27,6 +27,9 @@ import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.Renderables; import org.springframework.ide.vscode.commons.util.Renderables;
import org.springframework.ide.vscode.commons.util.StringUtil; import org.springframework.ide.vscode.commons.util.StringUtil;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
/** /**
* Sts version of {@link ValueHint} contains similar data, but accomoates * Sts version of {@link ValueHint} contains similar data, but accomoates
* a html snippet to be computed lazyly for the description. * a html snippet to be computed lazyly for the description.
@@ -43,7 +46,7 @@ public class StsValueHint {
private final String value; private final String value;
private final Renderable description; private final Renderable description;
private final Deprecation deprecation; private final Supplier<Deprecation> deprecation;
/** /**
* Create a hint with a textual description. * Create a hint with a textual description.
@@ -51,7 +54,7 @@ public class StsValueHint {
* This constructor is private. Use one of the provided * This constructor is private. Use one of the provided
* static 'create' methods instead. * static 'create' methods instead.
*/ */
private StsValueHint(String value, Renderable description, Deprecation deprecation) { private StsValueHint(String value, Renderable description, Supplier<Deprecation> deprecation) {
this.value = value==null?"null":value.toString(); this.value = value==null?"null":value.toString();
Assert.isLegal(!this.value.startsWith("StsValueHint")); Assert.isLegal(!this.value.startsWith("StsValueHint"));
this.description = description; this.description = description;
@@ -62,7 +65,7 @@ public class StsValueHint {
* Creates a hint out of an IJavaElement. * Creates a hint out of an IJavaElement.
*/ */
public static StsValueHint create(SourceLinks sourceLinks, String value, IJavaProject project, IJavaElement javaElement) { public static StsValueHint create(SourceLinks sourceLinks, String value, IJavaProject project, IJavaElement javaElement) {
return new StsValueHint(value, javaDocSnippet(sourceLinks, project, javaElement), DeprecationUtil.extract(javaElement)) { return new StsValueHint(value, javaDocSnippet(sourceLinks, project, () -> javaElement), () -> DeprecationUtil.extract(javaElement)) {
@Override @Override
public IJavaElement getJavaElement() { public IJavaElement getJavaElement() {
return javaElement; return javaElement;
@@ -70,6 +73,18 @@ public class StsValueHint {
}; };
} }
/**
* Creates a hint out of an Supplier<IJavaElement>.
*/
public static StsValueHint create(SourceLinks sourceLinks, String value, IJavaProject project, Supplier<IJavaElement> elementSupplier) {
return new StsValueHint(value, javaDocSnippet(sourceLinks, project, elementSupplier), Suppliers.memoize(() -> DeprecationUtil.extract(elementSupplier.get()))) {
@Override
public IJavaElement getJavaElement() {
return elementSupplier.get();
}
};
}
public static StsValueHint create(String value) { public static StsValueHint create(String value) {
return new StsValueHint(value, Renderables.NO_DESCRIPTION, null); return new StsValueHint(value, Renderables.NO_DESCRIPTION, null);
} }
@@ -94,7 +109,7 @@ public class StsValueHint {
} }
public static StsValueHint create(SourceLinks sourceLinks, IJavaProject project, IType klass) { public static StsValueHint create(SourceLinks sourceLinks, IJavaProject project, IType klass) {
return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(sourceLinks, project, klass), DeprecationUtil.extract(klass)) { return new StsValueHint(klass.getFullyQualifiedName(), javaDocSnippet(sourceLinks, project, () -> klass), Suppliers.memoize(() -> DeprecationUtil.extract(klass))) {
@Override @Override
public IJavaElement getJavaElement() { public IJavaElement getJavaElement() {
return klass; return klass;
@@ -120,9 +135,9 @@ public class StsValueHint {
return description; return description;
} }
private static Renderable javaDocSnippet(SourceLinks sourceLinks, IJavaProject project, IJavaElement je) { private static Renderable javaDocSnippet(SourceLinks sourceLinks, IJavaProject project, Supplier<IJavaElement> je) {
return Renderables.lazy(() -> { return Renderables.lazy(() -> {
return PropertyDocUtils.documentJavaElement(sourceLinks, project, je); return PropertyDocUtils.documentJavaElement(sourceLinks, project, je.get());
}); });
} }
@@ -132,7 +147,7 @@ public class StsValueHint {
} }
public Deprecation getDeprecation() { public Deprecation getDeprecation() {
return deprecation; return deprecation.get();
} }
public IJavaElement getJavaElement() { public IJavaElement getJavaElement() {

View File

@@ -1,5 +1,5 @@
/******************************************************************************* /*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc. * Copyright (c) 2016, 2019 Pivotal, Inc.
* All rights reserved. This program and the accompanying materials * All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0 * are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at * which accompanies this distribution, and is available at
@@ -147,7 +147,7 @@ public class PropertiesCompletionProposalsCalculator {
PropertyInfo prop = findLongestValidProperty(index, navPrefix); PropertyInfo prop = findLongestValidProperty(index, navPrefix);
if (prop!=null) { if (prop!=null) {
int regionStart = navOffset-navPrefix.length(); int regionStart = navOffset-navPrefix.length();
Collection<ICompletionProposal> hintProposals = getKeyHintProposals(prop, navOffset); Collection<ICompletionProposal> hintProposals = getKeyHintProposals(prop, regionStart + prop.getId().length());
if (CollectionUtil.hasElements(hintProposals)) { if (CollectionUtil.hasElements(hintProposals)) {
return hintProposals; return hintProposals;
} }