Logger name content asisst

This commit is contained in:
BoykoAlex
2016-11-30 16:47:17 -05:00
parent 2959440a00
commit 47461c772c
10 changed files with 110 additions and 3 deletions

View File

@@ -20,6 +20,14 @@ import com.google.common.cache.CacheBuilder;
import reactor.core.publisher.Flux;
/**
* Provides the algorithm for 'class-reference' valueProvider.
* <p>
* See: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-docs/src/main/asciidoc/appendix-configuration-metadata.adoc
*
* @author Kris De Volder
* @author Alex Boyko
*/
public class ClassReferenceProvider extends CachingValueProvider {
/**
@@ -44,7 +52,7 @@ public class ClassReferenceProvider extends CachingValueProvider {
}
);
public static <K,V> Function<K,V> applyOn(long duration, TimeUnit unit, Function<K,V> func) {
private static <K,V> Function<K,V> applyOn(long duration, TimeUnit unit, Function<K,V> func) {
Cache<K,V> cache = CacheBuilder.newBuilder().expireAfterAccess(duration, unit).expireAfterWrite(duration, unit).build();
return (k) -> {
try {

View File

@@ -0,0 +1,41 @@
package org.springframework.ide.vscode.application.properties.metadata;
import java.util.Map;
import java.util.function.Function;
import org.springframework.ide.vscode.application.properties.metadata.ValueProviderRegistry.ValueProviderStrategy;
import org.springframework.ide.vscode.application.properties.metadata.hints.StsValueHint;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import reactor.core.publisher.Flux;
import reactor.util.function.Tuples;
/**
* Provides the algorithm for 'logger-name' valueProvider.
* <p>
* See: https://github.com/spring-projects/spring-boot/blob/master/spring-boot-docs/src/main/asciidoc/appendix-configuration-metadata.adoc
*
* @author Kris De Volder
* @author Alex Boyko
*/
public class LoggerNameProvider extends CachingValueProvider {
private static final ValueProviderStrategy INSTANCE = new LoggerNameProvider();
public static final Function<Map<String, Object>, ValueProviderStrategy> FACTORY = (params) -> INSTANCE;
@Override
protected Flux<StsValueHint> getValuesAsync(IJavaProject javaProject, String query) {
return Flux.concat(
javaProject
.fuzzySearchPackages(query)
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2())),
javaProject
.fuzzySearchTypes(query, null)
.map(t -> Tuples.of(StsValueHint.create(t.getT1()), t.getT2()))
)
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.flatMap(l -> Flux.fromIterable(l))
.map(t -> t.getT1());
}
}

View File

@@ -48,7 +48,7 @@ public class ValueProviderRegistry {
}
protected void initializeDefaults(ValueProviderRegistry r) {
// def("logger-name", LoggerNameProvider.FACTORY);
def("logger-name", LoggerNameProvider.FACTORY);
def("class-reference", ClassReferenceProvider.FACTORY);
}

View File

@@ -84,6 +84,8 @@ public class JandexIndex {
private Map<File, Supplier<List<Tuple2<String, IType>>>> knownTypes;
private Map<File, Supplier<List<String>>> knownPackages;
private Cache<File, IJavadocProvider> javadocProvidersCache = CacheBuilder.newBuilder().build();
private JandexIndex[] baseIndex;
@@ -100,10 +102,12 @@ public class JandexIndex {
this.baseIndex = baseIndex;
this.index = new ConcurrentHashMap<>();
this.knownTypes = new HashMap<>();
this.knownPackages = new HashMap<>();
this.javadocProviderFactory = javadocProviderFactory;
classpathEntries.forEach(file -> {
index.put(file, Suppliers.memoize(() -> createIndex(file, indexFileFinder)));
knownTypes.put(file, Suppliers.memoize(() -> getKnownTypesStream(file).collect(Collectors.toList())));
knownPackages.put(file, Suppliers.memoize(() -> getKnownPackages(file).collect(Collectors.toList())));
});
}
@@ -225,6 +229,21 @@ public class JandexIndex {
return Stream.empty();
}
private Stream<String> getKnownPackages(File file) {
Optional<IndexView> indexView = index.get(file).get();
if (indexView.isPresent()) {
return indexView.get()
.getKnownClasses()
.parallelStream()
.map(info -> {
String name = info.name().toString();
return name.substring(0, name.lastIndexOf('.'));
})
.distinct();
}
return Stream.empty();
}
public Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, TypeFilter typeFilter) {
Flux<Tuple2<IType, Double>> flux = Flux.fromIterable(knownTypes.values())
.publishOn(Schedulers.parallel())
@@ -239,6 +258,19 @@ public class JandexIndex {
}
}
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
Flux<Tuple2<String, Double>> flux = Flux.fromIterable(knownPackages.values())
.publishOn(Schedulers.parallel())
.flatMap(s -> Flux.fromIterable(s.get()))
.map(pkg -> Tuples.of(pkg, FuzzyMatcher.matchScore(searchTerm, pkg)))
.filter(t -> t.getT2() != 0.0);
if (baseIndex == null) {
return flux;
} else {
return Flux.merge(flux, Flux.fromArray(baseIndex).flatMap(index -> index.fuzzySearchPackages(searchTerm)));
}
}
public Flux<IType> allSubtypesOf(IType type) {
DotName name = DotName.createSimple(type.getFullyQualifiedName());
Flux<IType> flux = Flux.fromIterable(index.keySet())

View File

@@ -14,6 +14,8 @@ public interface IJavaProject extends IJavaElement {
Flux<Tuple2<IType, Double>> fuzzySearchTypes(String searchTerm, TypeFilter typeFilter);
Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm);
Flux<IType> allSubtypesOf(IType type);
IClasspath getClasspath();

View File

@@ -66,6 +66,11 @@ public class MavenJavaProject implements IJavaProject {
return classpath.fuzzySearchType(searchTerm, typeFilter);
}
@Override
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
return classpath.fuzzySearchPackages(searchTerm);
}
@Override
public Flux<IType> allSubtypesOf(IType type) {
return classpath.allSubtypesOf(type);

View File

@@ -104,6 +104,10 @@ public class MavenProjectClasspath implements IClasspath {
return javaIndex.get().fuzzySearchTypes(searchTerm, typeFilter);
}
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
return javaIndex.get().fuzzySearchPackages(searchTerm);
}
public Flux<IType> allSubtypesOf(IType type) {
return javaIndex.get().allSubtypesOf(type);
}

View File

@@ -63,6 +63,11 @@ public class JavaProjectWithClasspathFile implements IJavaProject {
return Flux.empty();
}
@Override
public Flux<Tuple2<String, Double>> fuzzySearchPackages(String searchTerm) {
return Flux.empty();
}
@Override
public Flux<IType> allSubtypesOf(IType type) {
return Flux.empty();

View File

@@ -87,6 +87,16 @@ public class JavaIndexTest {
assertEquals("java.util.EnumMap$KeySet", results.get(0).getT1().getFullyQualifiedName());
}
@Test
public void fuzzySearchPackage() throws Exception {
List<Tuple2<String, Double>> results = MavenCore.getInstance().getJavaIndexForJreLibs()
.fuzzySearchPackages("util")
.collectSortedList((o1, o2) -> o2.getT2().compareTo(o1.getT2()))
.block();
assertTrue(results.size() > 10);
assertEquals("java.util", results.get(0).getT1());
}
@Test
public void findClassInJar() throws Exception {
MavenJavaProject project = mavenProjectsCache.get("gs-rest-service-cors-boot-1.4.1-with-classpath-file");

View File

@@ -3056,7 +3056,7 @@ public class ApplicationYamlEditorTest extends AbstractPropsEditorTest {
);
}
@Ignore @Test public void testLoggerNameCompletion() throws Exception {
@Test public void testLoggerNameCompletion() throws Exception {
CachingValueProvider.TIMEOUT = Duration.ofSeconds(20); // the provider can't be reliably tested if its not allowed to
// fetch all its values (even though in 'production' you
// wouldn't want it to block the UI thread for this long.