diff --git a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java index 1659cb57d..977fbf8eb 100644 --- a/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java +++ b/eclipse-language-servers/org.springframework.tooling.ls.eclipse.commons.test/src/org/springframework/tooling/ls/eclipse/commons/test/JavaLangugeClientTest.java @@ -30,6 +30,7 @@ import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams; import org.springframework.ide.vscode.commons.protocol.java.JavaTypeHierarchyParams; import org.springframework.ide.vscode.commons.protocol.java.TypeData; import org.springframework.ide.vscode.commons.protocol.java.TypeDescriptorData; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import org.springframework.tooling.ls.eclipse.commons.STS4LanguageClientImpl; public class JavaLangugeClientTest { @@ -89,7 +90,7 @@ public class JavaLangugeClientTest { @Test public void fuzzyFindTypesIncludingSysLibs() throws Exception { List data = client - .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, true)) + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", SearchType.FUZZY, true, true)) .get(100, TimeUnit.SECONDS); assertNotNull(data); assertEquals(500, data.size()); @@ -101,7 +102,7 @@ public class JavaLangugeClientTest { @Test public void fuzzyFindTypesExcludingSysLibs() throws Exception { List data = client - .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", true, false)) + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "util.Map", SearchType.FUZZY, true, false)) .get(10, TimeUnit.SECONDS); assertNotNull(data); assertEquals(186, data.size()); @@ -114,7 +115,7 @@ public class JavaLangugeClientTest { @Test public void fuzzyFindAllTypesExcludingSysLibs() throws Exception { List data = client - .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "", true, false)) + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "", SearchType.FUZZY, true, false)) .get(1000, TimeUnit.SECONDS); assertNotNull(data); assertEquals(500, data.size()); @@ -122,21 +123,21 @@ public class JavaLangugeClientTest { @Test public void searchPackagesIncludingSysLibs() throws Exception { - List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "java.lang", true, true)).get(30, TimeUnit.SECONDS); + List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "java.lang", SearchType.FUZZY, true, true)).get(30, TimeUnit.SECONDS); assertTrue(packages.size() > 15 && packages.size() < 25); } @Test public void searchPackagesExcludingSysLibs() throws Exception { - List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "java.lang", true, false)).get(30, TimeUnit.SECONDS); + List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "java.lang", SearchType.FUZZY, true, false)).get(30, TimeUnit.SECONDS); assertEquals(1, packages.size()); - packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "org.test", true, false)).get(30, TimeUnit.SECONDS); + packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "org.test", SearchType.FUZZY, true, false)).get(30, TimeUnit.SECONDS); assertTrue(packages.contains("org.test")); } @Test public void searchAllPackagesExcludingSysLibs() throws Exception { - List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "", true, false)).get(30, TimeUnit.SECONDS); + List packages = client.javaSearchPackages(new JavaSearchParams(project.getLocationURI().toString(), "", SearchType.FUZZY, true, false)).get(30, TimeUnit.SECONDS); assertEquals(500, packages.size()); } @@ -220,4 +221,41 @@ public class JavaLangugeClientTest { )); assertEquals(expected, actual); } + + @Test + public void camelcaseFindTypesExcludingSysLibs_1() throws Exception { + List data = client + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "springb", SearchType.CAMELCASE, true, false)) + .get(10, TimeUnit.SECONDS); + assertNotNull(data); + assertEquals(24, data.size()); + List closeMatches = data.stream().map(t -> t.getFqName()).filter(t -> t.endsWith("SpringBootApplication")).collect(Collectors.toList()); + assertEquals(1, closeMatches.size()); + assertEquals("org.springframework.boot.autoconfigure.SpringBootApplication", closeMatches.get(0)); + } + + @Test + public void camelcaseFindTypesExcludingSysLibs_2() throws Exception { + List data = client + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "SpBA", SearchType.CAMELCASE, true, false)) + .get(10, TimeUnit.SECONDS); + assertNotNull(data); + assertEquals(2, data.size()); + Set actual = data.stream().map(t -> t.getFqName()).collect(Collectors.toSet()); + Set expected = new HashSet<>(Arrays.asList( + "org.springframework.boot.autoconfigure.SpringBootApplication", + "org.springframework.web.context.support.SpringBeanAutowiringSupport" + )); + assertEquals(expected, actual); + } + + @Test + public void camelcaseFindAllTypesExcludingSysLibs() throws Exception { + List data = client + .javaSearchTypes(new JavaSearchParams(project.getLocationURI().toString(), "", SearchType.CAMELCASE, true, false)) + .get(1000, TimeUnit.SECONDS); + assertNotNull(data); + assertEquals(500, data.size()); + } + } diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java index d2f40d282..f5f9c24ef 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jandex/JandexClasspath.java @@ -105,6 +105,12 @@ public final class JandexClasspath implements ClasspathIndex { return javaIndex.get().fuzzySearchITypes(searchTerm); } + @Override + public Flux> camelcaseSearchTypes(String searchTerm, boolean includeBinaries, + boolean includeSystemLibs) { + throw new UnsupportedOperationException("Not implemented for Jandex index!"); + } + @Override public Flux> fuzzySearchPackages(String searchTerm, boolean includeBinaries, boolean includeSystemLibs) { return javaIndex.get().fuzzySearchPackages(searchTerm); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathIndex.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathIndex.java index 5a5e5b266..8ce62f621 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathIndex.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/java/ClasspathIndex.java @@ -18,6 +18,7 @@ public interface ClasspathIndex extends Disposable { IType findType(String fqName); Flux> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs); + Flux> camelcaseSearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs); Flux> fuzzySearchPackages(String searchTerm, boolean includeBinaries, boolean includeSystemLibs); Flux allSubtypesOf(String fqName, boolean includeFocusType); Flux allSuperTypesOf(String fqName, boolean includeFocusType); diff --git a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jdtls/JdtLsIndex.java b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jdtls/JdtLsIndex.java index 743661683..b0fb40ebd 100644 --- a/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jdtls/JdtLsIndex.java +++ b/headless-services/commons/commons-java/src/main/java/org/springframework/ide/vscode/commons/jdtls/JdtLsIndex.java @@ -33,6 +33,7 @@ import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient; import org.springframework.ide.vscode.commons.protocol.java.Classpath; import org.springframework.ide.vscode.commons.protocol.java.JavaDataParams; import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import org.springframework.ide.vscode.commons.protocol.java.JavaTypeHierarchyParams; import org.springframework.ide.vscode.commons.protocol.java.TypeData; import org.springframework.ide.vscode.commons.protocol.java.TypeDescriptorData; @@ -146,7 +147,7 @@ public class JdtLsIndex implements ClasspathIndex { @Override public Flux> fuzzySearchTypes(String searchTerm, boolean includeBinaries, boolean includeSystemLibs) { - JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, includeBinaries, includeSystemLibs, SEARCH_TIMEOUT); + JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, SearchType.FUZZY, includeBinaries, includeSystemLibs, SEARCH_TIMEOUT); return Mono.fromFuture(client.javaSearchTypes(searchParams)) .flatMapMany(results -> Flux.fromIterable(results).publishOn(Schedulers.parallel())) .filter(Objects::nonNull) @@ -156,13 +157,24 @@ public class JdtLsIndex implements ClasspathIndex { @Override public Flux> fuzzySearchPackages(String searchTerm, boolean includeBinaries, boolean includeSystemLibs) { - JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, includeBinaries, includeSystemLibs, SEARCH_TIMEOUT); + JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, SearchType.FUZZY, includeBinaries, includeSystemLibs, SEARCH_TIMEOUT); return Mono.fromFuture(client.javaSearchPackages(searchParams)) .flatMapMany(results -> Flux.fromIterable(results).publishOn(Schedulers.parallel())) .filter(Objects::nonNull) .map(p -> Tuples.of(p, FuzzyMatcher.matchScore(searchTerm, p))) .filter(tuple -> tuple.getT2() != 0.0); } + + @Override + public Flux> camelcaseSearchTypes(String searchTerm, boolean includeBinaries, + boolean includeSystemLibs) { + JavaSearchParams searchParams = new JavaSearchParams(projectUri.toString(), searchTerm, SearchType.CAMELCASE, includeBinaries, includeSystemLibs, SEARCH_TIMEOUT); + return Mono.fromFuture(client.javaSearchTypes(searchParams)) + .flatMapMany(results -> Flux.fromIterable(results).publishOn(Schedulers.parallel())) + .filter(Objects::nonNull) + .map(type -> Tuples.of(toTypeFromDescriptor(type), FuzzyMatcher.matchScore(searchTerm, type.getFqName()))) + .filter(tuple -> tuple.getT2() != 0.0); + } private List convertTypeDescriptors(List descriptors) { List types = new ArrayList<>(descriptors.size()); diff --git a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/JavaSearchParams.java b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/JavaSearchParams.java index c1ec71fc8..ef30ec3f9 100644 --- a/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/JavaSearchParams.java +++ b/headless-services/commons/commons-lsp-extensions/src/main/java/org/springframework/ide/vscode/commons/protocol/java/JavaSearchParams.java @@ -12,27 +12,34 @@ package org.springframework.ide.vscode.commons.protocol.java; public class JavaSearchParams { + public enum SearchType { + FUZZY, + CAMELCASE + } + private String projectUri; private String term; private boolean includeBinaries; private boolean includeSystemLibs; private long timeLimit = -1; + private SearchType searchType; - public JavaSearchParams(String projectUri, String term) { - this(projectUri, term, true, false); + public JavaSearchParams(String projectUri, String term, SearchType searchType) { + this(projectUri, term, searchType, true, false); } - public JavaSearchParams(String projectUri, String term, boolean includeBinaries, boolean includeSystemLibs, long timeLimit) { + public JavaSearchParams(String projectUri, String term, SearchType searchType, boolean includeBinaries, boolean includeSystemLibs, long timeLimit) { super(); this.projectUri = projectUri; this.term = term; + this.setSearchType(searchType); this.includeBinaries = includeBinaries; this.includeSystemLibs = includeSystemLibs; this.setTimeLimit(timeLimit); } - public JavaSearchParams(String projectUri, String term, boolean includeBinaries, boolean includeSystemLibs) { - this(projectUri, term, includeBinaries, includeSystemLibs, -1); + public JavaSearchParams(String projectUri, String term, SearchType searchType, boolean includeBinaries, boolean includeSystemLibs) { + this(projectUri, term, searchType, includeBinaries, includeSystemLibs, -1); } public String getProjectUri() { @@ -75,4 +82,12 @@ public class JavaSearchParams { this.timeLimit = timeLimit; } + public SearchType getSearchType() { + return searchType; + } + + public void setSearchType(SearchType searchType) { + this.searchType = searchType; + } + } diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/CachingFluxJavaSearch.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/CachingFluxJavaSearch.java index ce5c86967..7cc96d98a 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/CachingFluxJavaSearch.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/CachingFluxJavaSearch.java @@ -14,6 +14,7 @@ import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import org.eclipse.jdt.core.IJavaProject; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import org.springframework.tooling.jdt.ls.commons.Logger; import com.google.common.cache.Cache; @@ -22,6 +23,7 @@ import com.google.common.cache.CacheLoader.InvalidCacheLoadException; import reactor.core.publisher.Flux; import reactor.util.function.Tuple2; +import reactor.util.function.Tuple3; import reactor.util.function.Tuples; public abstract class CachingFluxJavaSearch implements FluxSearch { @@ -62,11 +64,11 @@ public abstract class CachingFluxJavaSearch implements FluxSearch { } @Override - public final Flux search(IJavaProject javaProject, String query) { - Tuple2 key = key(javaProject, query); + public final Flux search(IJavaProject javaProject, String query, SearchType searchType) { + Tuple2 key = key(javaProject, query, searchType); CacheEntry cached = null; try { - cached = cache.get(key, () -> new CacheEntry(query, getValuesIncremental(javaProject, query))); + cached = cache.get(key, () -> new CacheEntry(query, getValuesIncremental(javaProject, query, searchType))); } catch (ExecutionException e) { logger.log(e); } @@ -78,14 +80,14 @@ public abstract class CachingFluxJavaSearch implements FluxSearch { *

* Falls back on doing a full-blown search if there's no usable 'prefix-query' in the cache. */ - private Flux getValuesIncremental(IJavaProject javaProject, String query) { + private Flux getValuesIncremental(IJavaProject javaProject, String query, SearchType searchType) { // debug("trying to solve "+query+" incrementally"); String subquery = query; while (subquery.length()>=1) { subquery = subquery.substring(0, subquery.length()-1); CacheEntry cached = null; try { - cached = cache.get(key(javaProject, subquery), () -> null); + cached = cache.get(key(javaProject, subquery, searchType), () -> null); } catch (ExecutionException | InvalidCacheLoadException e) { // Log.log(e); } @@ -101,19 +103,19 @@ public abstract class CachingFluxJavaSearch implements FluxSearch { } } // debug("full search for: "+query); - return getValuesAsync(javaProject, query); + return getValuesAsync(javaProject, query, searchType); } - protected abstract Flux getValuesAsync(IJavaProject javaProject, String query); + protected abstract Flux getValuesAsync(IJavaProject javaProject, String query, SearchType searchType); protected abstract String stringValue(T t); - private Tuple2 key(IJavaProject javaProject, String query) { - return Tuples.of(javaProject==null?null:javaProject.getElementName(), query); + private Tuple3 key(IJavaProject javaProject, String query, SearchType searchType) { + return Tuples.of(javaProject==null?null:javaProject.getElementName(), query, searchType); } protected Cache createCache() { return CacheBuilder.newBuilder().expireAfterWrite(1, TimeUnit.MINUTES).expireAfterAccess(1, TimeUnit.MINUTES).build(); } - + } diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/FluxSearch.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/FluxSearch.java index ecf02a492..222714779 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/FluxSearch.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/FluxSearch.java @@ -14,15 +14,16 @@ import java.time.Duration; import java.util.List; import org.eclipse.jdt.core.IJavaProject; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import reactor.core.publisher.Flux; public interface FluxSearch { - Flux search(IJavaProject project, String searchTerm); + Flux search(IJavaProject project, String searchTerm, SearchType searchType); - default List searchWithLimits(IJavaProject javaProject, String searchTerm, long timeLimit) { - Flux flux = this.search(javaProject, searchTerm); + default List searchWithLimits(IJavaProject javaProject, String searchTerm, SearchType searchType, long timeLimit) { + Flux flux = this.search(javaProject, searchTerm, searchType); if (timeLimit > 0) { flux = flux.take(Duration.ofMillis(timeLimit)); } diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaFluxSearch.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaFluxSearch.java index e4f4439f4..954bdd27c 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaFluxSearch.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/JavaFluxSearch.java @@ -44,7 +44,7 @@ public class JavaFluxSearch { PackageFluxSearch fluxPackageSearch = packageSearchCache.get( Tuples.of(params.isIncludeBinaries(), params.isIncludeSystemLibs()), () -> new PackageFluxSearch(logger, params.isIncludeBinaries(), params.isIncludeSystemLibs()) ); - return fluxPackageSearch.searchWithLimits(javaProject, params.getTerm(), params.getTimeLimit()); + return fluxPackageSearch.searchWithLimits(javaProject, params.getTerm(), params.getSearchType(), params.getTimeLimit()); } public List fuzzySearchTypes(JavaSearchParams params) throws Exception { @@ -53,7 +53,7 @@ public class JavaFluxSearch { TypeFluxSearch fluxTypeSearch = typeSearchCache.get( Tuples.of(params.isIncludeBinaries(), params.isIncludeSystemLibs()), () -> new TypeFluxSearch(logger, javaData, params.isIncludeBinaries(), params.isIncludeSystemLibs()) ); - return fluxTypeSearch.searchWithLimits(javaProject, params.getTerm(), params.getTimeLimit()); + return fluxTypeSearch.searchWithLimits(javaProject, params.getTerm(), params.getSearchType(), params.getTimeLimit()); } } diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/PackageFluxSearch.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/PackageFluxSearch.java index cd5b393d4..2081488e6 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/PackageFluxSearch.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/PackageFluxSearch.java @@ -12,11 +12,11 @@ package org.springframework.tooling.jdt.ls.commons.java; import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.searchScope; import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.toPackagePattern; -import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.toWildCardPattern; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IPackageFragment; import org.eclipse.jdt.core.JavaModelException; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import org.springframework.tooling.jdt.ls.commons.Logger; import reactor.core.publisher.Flux; @@ -28,11 +28,11 @@ public class PackageFluxSearch extends CachingFluxJavaSearch { } @Override - protected Flux getValuesAsync(IJavaProject javaProject, String searchTerm) { + protected Flux getValuesAsync(IJavaProject javaProject, String searchTerm, SearchType searchType) { try { return new FluxJdtSearch(logger) .scope(searchScope(javaProject, includeBinaries, includeSystemLibs)) - .pattern(toPackagePattern(toWildCardPattern(searchTerm))) + .pattern(toPackagePattern(searchType, searchTerm)) .search() .map(match -> match.getElement()) .filter(o -> o instanceof IPackageFragment) diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/SearchUtils.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/SearchUtils.java index a5c5006fb..e5e08f245 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/SearchUtils.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/SearchUtils.java @@ -17,37 +17,100 @@ import org.eclipse.jdt.core.search.IJavaSearchConstants; import org.eclipse.jdt.core.search.IJavaSearchScope; import org.eclipse.jdt.core.search.SearchEngine; import org.eclipse.jdt.core.search.SearchPattern; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; public class SearchUtils { + private static final String WILDCARD = "*"; + public static String toWildCardPattern(String query) { - StringBuilder builder = new StringBuilder("*"); + StringBuilder builder = new StringBuilder(WILDCARD); for (char c : query.toCharArray()) { builder.append(c); builder.append('*'); } return builder.toString(); } + + public static String toCamelCasePattern(String query) { + StringBuilder builder = new StringBuilder(); + boolean insertStarBeforeCapitalLetter = false; + for (char c : query.toCharArray()) { + if (Character.isUpperCase(c)) { + if (insertStarBeforeCapitalLetter) { + builder.append('*'); + } + insertStarBeforeCapitalLetter = true; + } + builder.append(c); + } + builder.append('*'); + return builder.toString(); + } + + public static String toSearchPattern(SearchType searchType, String query) { + switch(searchType) { + case FUZZY: + return toWildCardPattern(query); + case CAMELCASE: + return toCamelCasePattern(query); + default: + return query; + } + } - public static SearchPattern toPackagePattern(String wildCardedQuery) { + public static SearchPattern toPackagePattern(SearchType searchType, String query) { int searchFor = IJavaSearchConstants.PACKAGE; int limitTo = IJavaSearchConstants.DECLARATIONS; - int matchRule = SearchPattern.R_PATTERN_MATCH; - return SearchPattern.createPattern(wildCardedQuery, searchFor, limitTo, matchRule); + int matchRule = SearchPattern.R_EXACT_MATCH; + String finalQuery = query; + switch (searchType) { + case FUZZY: + matchRule = SearchPattern.R_PATTERN_MATCH; + finalQuery = toWildCardPattern(query); + break; + case CAMELCASE: + matchRule = SearchPattern.R_CAMELCASE_MATCH; + finalQuery = query.isEmpty() ? WILDCARD : query; + break; + } + return SearchPattern.createPattern(finalQuery, searchFor, limitTo, matchRule); } - public static SearchPattern toClassPattern(String wildCardedQuery) { + public static SearchPattern toClassPattern(SearchType searchType, String query) { int searchFor = IJavaSearchConstants.CLASS; int limitTo = IJavaSearchConstants.DECLARATIONS; - int matchRule = SearchPattern.R_PATTERN_MATCH; - return SearchPattern.createPattern(wildCardedQuery, searchFor, limitTo, matchRule); + int matchRule = SearchPattern.R_EXACT_MATCH; + String finalQuery = query; + switch (searchType) { + case FUZZY: + matchRule = SearchPattern.R_PATTERN_MATCH; + finalQuery = toWildCardPattern(query); + break; + case CAMELCASE: + matchRule = SearchPattern.R_CAMELCASE_MATCH; + finalQuery = query.isEmpty() ? WILDCARD : query; + break; + } + return SearchPattern.createPattern(finalQuery, searchFor, limitTo, matchRule); } - public static SearchPattern toTypePattern(String wildCardedQuery) { + public static SearchPattern toTypePattern(SearchType searchType, String query) { int searchFor = IJavaSearchConstants.TYPE; int limitTo = IJavaSearchConstants.DECLARATIONS; - int matchRule = SearchPattern.R_PATTERN_MATCH; - return SearchPattern.createPattern(wildCardedQuery, searchFor, limitTo, matchRule); + int matchRule = SearchPattern.R_EXACT_MATCH; + String finalQuery = query; + switch (searchType) { + case FUZZY: + matchRule = SearchPattern.R_PATTERN_MATCH; + finalQuery = toWildCardPattern(query); + break; + case CAMELCASE: + matchRule = SearchPattern.R_CAMELCASE_MATCH; + finalQuery = query.isEmpty() ? WILDCARD : query; + break; + } + return SearchPattern.createPattern(finalQuery, searchFor, limitTo, matchRule); } public static String toProperTypeQuery(String query) { diff --git a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeFluxSearch.java b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeFluxSearch.java index cea43cbfc..36ce8ef3a 100644 --- a/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeFluxSearch.java +++ b/headless-services/jdt-ls-extension/org.springframework.tooling.jdt.ls.commons/src/org/springframework/tooling/jdt/ls/commons/java/TypeFluxSearch.java @@ -11,12 +11,11 @@ package org.springframework.tooling.jdt.ls.commons.java; import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.searchScope; -import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.toProperTypeQuery; import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.toTypePattern; -import static org.springframework.tooling.jdt.ls.commons.java.SearchUtils.toWildCardPattern; import org.eclipse.jdt.core.IJavaProject; import org.eclipse.jdt.core.IType; +import org.springframework.ide.vscode.commons.protocol.java.JavaSearchParams.SearchType; import org.springframework.ide.vscode.commons.protocol.java.TypeDescriptorData; import org.springframework.tooling.jdt.ls.commons.Logger; @@ -32,11 +31,11 @@ public class TypeFluxSearch extends CachingFluxJavaSearch { } @Override - protected Flux getValuesAsync(IJavaProject javaProject, String searchTerm) { + protected Flux getValuesAsync(IJavaProject javaProject, String searchTerm, SearchType searchType) { try { return new FluxJdtSearch(logger) .scope(searchScope(javaProject, includeBinaries, includeSystemLibs)) - .pattern(toTypePattern(toWildCardPattern(toProperTypeQuery(searchTerm)))) + .pattern(toTypePattern(searchType, searchTerm)) .search() .map(match -> match.getElement()) .filter(o -> o instanceof IType) @@ -46,7 +45,7 @@ public class TypeFluxSearch extends CachingFluxJavaSearch { return Flux.empty(); } } - + @Override protected String stringValue(TypeDescriptorData t) { return t.getFqName();