service method to return beans as future waits for project-related indexing tasks to complete
This commit is contained in:
@@ -98,10 +98,11 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
private final List<EnhancedSymbolInformation> symbols = new ArrayList<>();
|
||||
|
||||
private final ConcurrentMap<String, List<EnhancedSymbolInformation>> symbolsByDoc = new ConcurrentHashMap<>();
|
||||
|
||||
private final ConcurrentMap<String, List<EnhancedSymbolInformation>> symbolsByProject = new ConcurrentHashMap<>();
|
||||
|
||||
private final ExecutorService updateQueue = Executors.newSingleThreadExecutor();
|
||||
private final Map<String, CompletableFuture<Void>> latestScheduledTaskByProject = new ConcurrentHashMap<String, CompletableFuture<Void>>();
|
||||
|
||||
private SpringIndexer[] indexers;
|
||||
private ListenerList<Void> listeners = new ListenerList<Void>();
|
||||
|
||||
@@ -343,6 +344,7 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
cf.thenAccept( f -> {
|
||||
projectInitializedFuture(project).complete(null);
|
||||
});
|
||||
|
||||
return cf;
|
||||
}
|
||||
|
||||
@@ -365,7 +367,10 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
}
|
||||
|
||||
CompletableFuture<Void> future = CompletableFuture.allOf(futures);
|
||||
|
||||
future.thenAccept(v -> listeners.fire(v));
|
||||
|
||||
this.latestScheduledTaskByProject.put(project.getElementName(), future);
|
||||
return future;
|
||||
}
|
||||
} else {
|
||||
@@ -389,7 +394,10 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
} else {
|
||||
DeleteProject initializeItem = new DeleteProject(project, this.indexers);
|
||||
return CompletableFuture.runAsync(initializeItem, this.updateQueue);
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(initializeItem, this.updateQueue);
|
||||
this.latestScheduledTaskByProject.put(project.getElementName(), future);
|
||||
|
||||
return future;
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error("", e);
|
||||
@@ -545,7 +553,10 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
Optional<IJavaProject> maybeProject = projectFinder().find(new TextDocumentIdentifier(deletedDocURI));
|
||||
if (maybeProject.isPresent()) {
|
||||
DeleteItems deleteItem = new DeleteItems(maybeProject.get(), new String[] {deletedDocURI}, this.indexers);
|
||||
return CompletableFuture.runAsync(deleteItem, this.updateQueue);
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(deleteItem, this.updateQueue);
|
||||
|
||||
this.latestScheduledTaskByProject.put(maybeProject.get().getElementName(), future);
|
||||
return future;
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -569,7 +580,10 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
List<String> docURIs = projectMapping.get(project);
|
||||
|
||||
DeleteItems deleteItems = new DeleteItems(project, (String[]) docURIs.toArray(new String[docURIs.size()]), this.indexers);
|
||||
futures.add(CompletableFuture.runAsync(deleteItems, this.updateQueue));
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(deleteItems, this.updateQueue);
|
||||
|
||||
this.latestScheduledTaskByProject.put(project.getElementName(), future);
|
||||
futures.add(future);
|
||||
}
|
||||
|
||||
CompletableFuture<Void> future = CompletableFuture.allOf((CompletableFuture[]) futures.toArray(new CompletableFuture[futures.size()]));
|
||||
@@ -691,8 +705,16 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<List<Bean>> beans(String project) {
|
||||
return CompletableFuture.completedFuture(Arrays.asList(springIndex.getBeansOfProject(project)));
|
||||
public CompletableFuture<List<Bean>> beans(String projectName) {
|
||||
CompletableFuture<Void> latestTask = this.latestScheduledTaskByProject.get(projectName);
|
||||
|
||||
if (latestTask != null) {
|
||||
return latestTask.thenApply((e) -> Arrays.asList(springIndex.getBeansOfProject(projectName)));
|
||||
}
|
||||
else {
|
||||
return CompletableFuture.completedFuture(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -782,8 +804,7 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
CompletableFuture<Void> updateItem(IJavaProject project, DocumentDescriptor updatedDoc, String content, SpringIndexer indexer) {
|
||||
log.debug("scheduling updateItem {}. {}, {}, {}", project.getElementName(), updatedDoc.getDocURI(), updatedDoc.getLastModified(), indexer);
|
||||
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
try {
|
||||
log.debug("updateItem {}. {}, {}, {}", project.getElementName(), updatedDoc.getDocURI(), updatedDoc.getLastModified(), indexer);
|
||||
indexer.updateFile(project, updatedDoc, content);
|
||||
@@ -791,6 +812,9 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
log.error("{}", e);
|
||||
}
|
||||
}, this.updateQueue);
|
||||
|
||||
this.latestScheduledTaskByProject.put(project.getElementName(), future);
|
||||
return future;
|
||||
}
|
||||
|
||||
CompletableFuture<Void> updateItems(IJavaProject project, DocumentDescriptor[] updatedDoc, SpringIndexer indexer) {
|
||||
@@ -798,7 +822,7 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
log.debug("scheduling updateItem {}. {}, {}, {}", project.getElementName(), doc.getDocURI(), doc.getLastModified(), indexer);
|
||||
}
|
||||
|
||||
return CompletableFuture.runAsync(() -> {
|
||||
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
|
||||
|
||||
try {
|
||||
for (DocumentDescriptor doc : updatedDoc) {
|
||||
@@ -810,6 +834,9 @@ public class SpringSymbolIndex implements InitializingBean, SpringModelService {
|
||||
log.error("{}", e);
|
||||
}
|
||||
}, this.updateQueue);
|
||||
|
||||
this.latestScheduledTaskByProject.put(project.getElementName(), future);
|
||||
return future;
|
||||
}
|
||||
|
||||
private class DeleteItems implements Runnable {
|
||||
|
||||
@@ -0,0 +1,91 @@
|
||||
/*******************************************************************************
|
||||
* 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.boot.metamodel.test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.Position;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.junit.jupiter.api.extension.ExtendWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
|
||||
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
|
||||
import org.springframework.ide.vscode.boot.bootiful.SymbolProviderTestConf;
|
||||
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
|
||||
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.InjectionPoint;
|
||||
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
import org.springframework.test.context.junit.jupiter.SpringExtension;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
@ExtendWith(SpringExtension.class)
|
||||
@BootLanguageServerTest
|
||||
@Import(SymbolProviderTestConf.class)
|
||||
public class SpringModelServiceTest {
|
||||
|
||||
@Autowired private BootLanguageServerHarness harness;
|
||||
@Autowired private JavaProjectFinder projectFinder;
|
||||
@Autowired private SpringSymbolIndex indexer;
|
||||
|
||||
private File directory;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() throws Exception {
|
||||
harness.intialize(null);
|
||||
|
||||
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-spring-indexing/").toURI());
|
||||
|
||||
String projectDir = directory.toURI().toString();
|
||||
|
||||
// trigger project creation
|
||||
projectFinder.find(new TextDocumentIdentifier(projectDir)).get();
|
||||
|
||||
// CompletableFuture<Void> initProject = indexer.waitOperation();
|
||||
// initProject.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testSpringModelServiceBeansForNonExistingProject() throws Exception {
|
||||
CompletableFuture<List<Bean>> result = indexer.beans("random-project");
|
||||
|
||||
List<Bean> list = result.get();
|
||||
assertNull(list);
|
||||
}
|
||||
|
||||
@Test
|
||||
void testBeansNameAndTypeFromBeanAnnotatedMethod() throws Exception {
|
||||
CompletableFuture<List<Bean>> result = indexer.beans("test-spring-indexing");
|
||||
|
||||
List<Bean> beans = result.get(5, TimeUnit.SECONDS);
|
||||
|
||||
assertNotNull(beans);
|
||||
assertEquals(11, beans.size());
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user