Skip to content

Commit

Permalink
GH-1049: spring index protocol now has new request for find matching …
Browse files Browse the repository at this point in the history
…beans
  • Loading branch information
martinlippert committed May 24, 2023
1 parent c9b526f commit 709e215
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 8 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@
import org.springframework.ide.vscode.commons.protocol.STS4LanguageClient;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.BeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.MatchingBeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndex;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndexLanguageServer;
import org.springframework.ide.vscode.commons.util.Assert;
Expand Down Expand Up @@ -927,13 +928,14 @@ final public Integer getParentProcessId() {

@Override
public CompletableFuture<List<Bean>> beans(BeansParams params) {
Map<String, SpringIndex> allSpringIndex = appContext.getBeansOfType(SpringIndex.class, false, false);
Assert.isLegal(allSpringIndex.size() <= 1, "One at most SpringModel bean is expected");
if (!allSpringIndex.isEmpty()) {
SpringIndex springIndex = allSpringIndex.values().iterator().next();
return springIndex.beans(params);
}
return CompletableFuture.completedFuture(Collections.emptyList());
SpringIndex springIndex = appContext.getBean(SpringIndex.class);
return springIndex.beans(params);
}

@Override
public CompletableFuture<List<Bean>> matchingBeans(MatchingBeansParams params) {
SpringIndex springIndex = appContext.getBean(SpringIndex.class);
return springIndex.matchingBeans(params);
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*******************************************************************************
* Copyright (c) 2023 VMware, 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
* https://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* VMware, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.protocol.spring;

public class MatchingBeansParams extends BeansParams {

private String beanType;

public String getBeanTypeToMatch() {
return beanType;
}

public void setBeanTypeToMatch(String beanType) {
this.beanType = beanType;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@
public interface SpringIndex {

CompletableFuture<List<Bean>> beans(BeansParams params);
CompletableFuture<List<Bean>> matchingBeans(MatchingBeansParams params);

}
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,10 @@ public interface SpringIndexLanguageServer extends LanguageServer {
default CompletableFuture<List<Bean>> beans(BeansParams params) {
throw new UnsupportedOperationException();
}

@JsonRequest("spring/index/beans/matches")
default CompletableFuture<List<Bean>> matchingBeans(MatchingBeansParams params) {
throw new UnsupportedOperationException();
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.BeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.MatchingBeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.SpringIndex;
import org.springframework.ide.vscode.commons.util.Futures;
import org.springframework.ide.vscode.commons.util.StringUtil;
Expand Down Expand Up @@ -720,7 +721,21 @@ public CompletableFuture<List<Bean>> beans(BeansParams params) {
else {
return CompletableFuture.completedFuture(null);
}

}

@Override
public CompletableFuture<List<Bean>> matchingBeans(MatchingBeansParams params) {
String projectName = params.getProjectName();
String matchType = params.getBeanTypeToMatch();

CompletableFuture<Void> latestTask = this.latestScheduledTaskByProject.get(projectName);

if (latestTask != null) {
return latestTask.thenApply((e) -> Arrays.asList(springIndex.getMatchingBeans(projectName, matchType)));
}
else {
return CompletableFuture.completedFuture(null);
}
}

/**
Expand Down Expand Up @@ -989,4 +1004,5 @@ private void removeSymbolsByProject(IJavaProject project) {
public void onUpdate(Consumer<Void> listener) {
listeners.add(listener);
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -97,4 +97,15 @@ public Bean[] getBeansWithName(String project, String name) {
}
}

public Bean[] getMatchingBeans(String projectName, String matchType) {
Bean[] allBeans = this.beansPerProject.get(projectName);

if (allBeans != null) {
return Arrays.stream(allBeans).filter(bean -> bean.isTypeCompatibleWith(matchType)).collect(Collectors.toList()).toArray(new Bean[0]);
}
else {
return null;
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.BeansParams;
import org.springframework.ide.vscode.commons.protocol.spring.MatchingBeansParams;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.context.junit.jupiter.SpringExtension;
Expand Down Expand Up @@ -86,4 +87,35 @@ void testBeansNameAndTypeFromBeanAnnotatedMethod() throws Exception {
assertEquals(11, beans.size());
}

@Test
void testMatchingBeansForObject() throws Exception {
MatchingBeansParams params = new MatchingBeansParams();
params.setProjectName("test-spring-indexing");
params.setBeanTypeToMatch("java.lang.Object");

CompletableFuture<List<Bean>> result = indexer.matchingBeans(params);

List<Bean> beans = result.get(5, TimeUnit.SECONDS);

assertNotNull(beans);
assertEquals(10, beans.size());
}

@Test
void testMatchingBeansForSpecificSupertype() throws Exception {
MatchingBeansParams params = new MatchingBeansParams();
params.setProjectName("test-spring-indexing");
params.setBeanTypeToMatch("org.test.springdata.CustomerRepository");

CompletableFuture<List<Bean>> result = indexer.matchingBeans(params);

List<Bean> beans = result.get(5, TimeUnit.SECONDS);

assertNotNull(beans);
assertEquals(1, beans.size());

assertEquals("customerRepository", beans.get(0).getName());
assertEquals("org.test.springdata.CustomerRepository", beans.get(0).getType());
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -266,5 +266,78 @@ void testEmptyInjectionPointsOptimization() {
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes);
assertSame(DefaultValues.EMPTY_INJECTION_POINTS, bean1.getInjectionPoints());
}

@Test
void testFindNoMatchingBeansWithEmptySupertypes() {
SpringMetamodelIndex index = new SpringMetamodelIndex();
Bean bean1 = new Bean("beanName1", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes);
Bean bean2 = new Bean("beanName2", "beanType", locationForDoc1, emptyInjectionPoints, emptySupertypes);

index.updateBeans("someProject", new Bean[] {bean1, bean2});

Bean[] matchingBeans = index.getMatchingBeans("someProject", "");
assertEquals(0, matchingBeans.length);

matchingBeans = index.getMatchingBeans("someProject", "sometype");
assertEquals(0, matchingBeans.length);
}

@Test
void testFindMatchingBeansWithOneProject() {
SpringMetamodelIndex index = new SpringMetamodelIndex();
Bean bean1 = new Bean("beanName1", "beanType1", locationForDoc1, emptyInjectionPoints, new String[] {"supertype1", "supertype2"});
Bean bean2 = new Bean("beanName2", "beanType2", locationForDoc1, emptyInjectionPoints, new String[] {"supertype3", "supertype4", "supertype5"});

index.updateBeans("someProject", new Bean[] {bean1, bean2});

Bean[] matchingBeans = index.getMatchingBeans("someProject", "supertype2");
assertEquals(1, matchingBeans.length);
assertSame(bean1, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("someProject", "beanType1");
assertEquals(1, matchingBeans.length);
assertSame(bean1, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("someProject", "supertype5");
assertEquals(1, matchingBeans.length);
assertSame(bean2, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("someProject", "sometype");
assertEquals(0, matchingBeans.length);

matchingBeans = index.getMatchingBeans("otherProject", "supertype1");
assertNull(matchingBeans);
}

@Test
void testFindMatchingBeansWithMultipleProjects() {
SpringMetamodelIndex index = new SpringMetamodelIndex();
Bean bean1 = new Bean("beanName1", "beanType1", locationForDoc1, emptyInjectionPoints, new String[] {"supertype1", "supertype2"});
Bean bean2 = new Bean("beanName2", "beanType2", locationForDoc1, emptyInjectionPoints, new String[] {"supertype3", "supertype4, supertype5"});

Bean bean3 = new Bean("beanName3", "beanType1", locationForDoc1, emptyInjectionPoints, new String[] {"supertype1", "supertype2"});
Bean bean4 = new Bean("beanName4", "beanType2", locationForDoc1, emptyInjectionPoints, new String[] {"supertype3", "supertype4, supertype5"});

index.updateBeans("projectA", new Bean[] {bean1, bean2});
index.updateBeans("projectB", new Bean[] {bean3, bean4});

Bean[] matchingBeans = index.getMatchingBeans("projectA", "supertype2");
assertEquals(1, matchingBeans.length);
assertSame(bean1, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("projectA", "beanType2");
assertEquals(1, matchingBeans.length);
assertSame(bean2, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("projectB", "supertype2");
assertEquals(1, matchingBeans.length);
assertSame(bean3, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("projectB", "beanType2");
assertEquals(1, matchingBeans.length);
assertSame(bean4, matchingBeans[0]);

matchingBeans = index.getMatchingBeans("otherProject", "supertype1");
}

}

0 comments on commit 709e215

Please sign in to comment.