improve file observer mechanism to work with multiple files
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2018 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2020 Pivotal, 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
|
||||
@@ -54,8 +54,8 @@ public abstract class AbstractFileToProjectCache<P extends IJavaProject> extends
|
||||
protected void attachListeners(File file, P project) {
|
||||
super.attachListeners(file, project);
|
||||
List<String> globPattern = Arrays.asList(file.toString().replace(File.separator, "/"));
|
||||
subscriptions.add(getFileObserver().onFileChanged(globPattern, (uri) -> performUpdate(project, asyncUpdate, true)));
|
||||
subscriptions.add(getFileObserver().onFileDeleted(globPattern, (uri) -> {
|
||||
subscriptions.add(getFileObserver().onFilesChanged(globPattern, (uris) -> performUpdate(project, asyncUpdate, true)));
|
||||
subscriptions.add(getFileObserver().onFilesDeleted(globPattern, (uris) -> {
|
||||
cache.invalidate(file);
|
||||
notifyProjectDeleted(project);
|
||||
dispose();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2020 Pivotal, 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
|
||||
@@ -41,22 +41,22 @@ public class SimpleServerFileObserver extends BasicFileObserver {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileCreated(List<String> globPattern, Consumer<String> handler) {
|
||||
String subscriptionId = super.onFileCreated(globPattern, handler);
|
||||
public String onFilesCreated(List<String> globPattern, Consumer<String[]> handler) {
|
||||
String subscriptionId = super.onFilesCreated(globPattern, handler);
|
||||
subscribe(subscriptionId, globPattern, FileSystemWatcher.CREATE);
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileChanged(List<String> globPattern, Consumer<String> handler) {
|
||||
String subscriptionId = super.onFileChanged(globPattern, handler);
|
||||
public String onFilesChanged(List<String> globPattern, Consumer<String[]> handler) {
|
||||
String subscriptionId = super.onFilesChanged(globPattern, handler);
|
||||
subscribe(subscriptionId, globPattern, FileSystemWatcher.CHANGE);
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileDeleted(List<String> globPattern, Consumer<String> handler) {
|
||||
String subscriptionId = super.onFileDeleted(globPattern, handler);
|
||||
public String onFilesDeleted(List<String> globPattern, Consumer<String[]> handler) {
|
||||
String subscriptionId = super.onFilesDeleted(globPattern, handler);
|
||||
subscribe(subscriptionId, globPattern, FileSystemWatcher.DELETE);
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
@@ -13,14 +13,18 @@ package org.springframework.ide.vscode.commons.languageserver.util;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.eclipse.lsp4j.DidChangeConfigurationParams;
|
||||
import org.eclipse.lsp4j.DidChangeWatchedFilesParams;
|
||||
import org.eclipse.lsp4j.DidChangeWorkspaceFoldersParams;
|
||||
import org.eclipse.lsp4j.ExecuteCommandParams;
|
||||
import org.eclipse.lsp4j.FileChangeType;
|
||||
import org.eclipse.lsp4j.FileEvent;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.eclipse.lsp4j.WorkspaceFoldersChangeEvent;
|
||||
@@ -31,7 +35,6 @@ import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.commons.util.AsyncRunner;
|
||||
import org.springframework.ide.vscode.commons.util.FileObserver;
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.gson.JsonElement;
|
||||
@@ -78,29 +81,31 @@ public class SimpleWorkspaceService implements WorkspaceService {
|
||||
|
||||
@Override
|
||||
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
|
||||
params.getChanges().forEach(event -> {
|
||||
try {
|
||||
String uri = event.getUri();
|
||||
if (uri != null) {
|
||||
switch (event.getType()) {
|
||||
case Created:
|
||||
fileObserver.notifyFileCreated(uri);
|
||||
break;
|
||||
case Changed:
|
||||
fileObserver.notifyFileChanged(uri);
|
||||
break;
|
||||
case Deleted:
|
||||
fileObserver.notifyFileDeleted(uri);
|
||||
break;
|
||||
default:
|
||||
Log.log("Uknown file change type '" + event.getType() + "' for file: " + uri);
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Map<FileChangeType, List<FileEvent>> collect =
|
||||
params.getChanges().stream().filter(event -> event.getUri() != null).collect(Collectors.groupingBy(FileEvent::getType));
|
||||
|
||||
for (FileChangeType type : collect.keySet()) {
|
||||
String[] docURIs = collect.get(type).stream().map(event -> event.getUri()).toArray(String[]::new);
|
||||
|
||||
switch (type) {
|
||||
case Created:
|
||||
fileObserver.notifyFilesCreated(docURIs);
|
||||
break;
|
||||
case Changed:
|
||||
fileObserver.notifyFilesChanged(docURIs);
|
||||
break;
|
||||
case Deleted:
|
||||
fileObserver.notifyFilesDeleted(docURIs);
|
||||
break;
|
||||
default:
|
||||
log.warn("Uknown file change type '" + type + "' for files: " + docURIs);
|
||||
break;
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
Log.log(t);
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
log.warn("problem occurred while dispatching file event", t);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2020 Pivotal, 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
|
||||
@@ -12,9 +12,9 @@ package org.springframework.ide.vscode.commons.util;
|
||||
|
||||
import java.net.URI;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.PathMatcher;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
@@ -24,8 +24,6 @@ import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.lang3.tuple.ImmutablePair;
|
||||
|
||||
import reactor.core.Disposable;
|
||||
|
||||
/**
|
||||
* Basic implementation of File Observer interface
|
||||
*
|
||||
@@ -34,22 +32,22 @@ import reactor.core.Disposable;
|
||||
*/
|
||||
public class BasicFileObserver implements FileObserver {
|
||||
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String>>> createRegistry = new ConcurrentHashMap<>();
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String>>> deleteRegistry = new ConcurrentHashMap<>();
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String>>> changeRegistry = new ConcurrentHashMap<>();
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String[]>>> createRegistry = new ConcurrentHashMap<>();
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String[]>>> deleteRegistry = new ConcurrentHashMap<>();
|
||||
protected ConcurrentHashMap<String, ImmutablePair<List<PathMatcher>, Consumer<String[]>>> changeRegistry = new ConcurrentHashMap<>();
|
||||
|
||||
@Override
|
||||
public String onFileCreated(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesCreated(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return registerFileListener(createRegistry, globPattern, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileChanged(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesChanged(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return registerFileListener(changeRegistry, globPattern, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileDeleted(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesDeleted(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return registerFileListener(deleteRegistry, globPattern, handler);
|
||||
}
|
||||
|
||||
@@ -67,34 +65,66 @@ public class BasicFileObserver implements FileObserver {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String registerFileListener(Map<String, ImmutablePair<List<PathMatcher>, Consumer<String>>> registry, List<String> globPattern, Consumer<String> handler) {
|
||||
private static String registerFileListener(Map<String, ImmutablePair<List<PathMatcher>, Consumer<String[]>>> registry, List<String> globPattern, Consumer<String[]> handler) {
|
||||
String subscriptionId = UUID.randomUUID().toString();
|
||||
registry.put(subscriptionId, ImmutablePair.of(globPattern.stream().map(g -> FileSystems.getDefault().getPathMatcher("glob:" + g)).collect(Collectors.toList()), handler));
|
||||
return subscriptionId;
|
||||
}
|
||||
|
||||
final public void notifyFileCreated(String uri) {
|
||||
notify(createRegistry, uri);
|
||||
notify(createRegistry, new String[] {uri});
|
||||
}
|
||||
|
||||
final public void notifyFilesCreated(String[] uris) {
|
||||
notify(createRegistry, uris);
|
||||
}
|
||||
|
||||
final public void notifyFileChanged(String uri) {
|
||||
notify(changeRegistry, uri);
|
||||
notify(changeRegistry, new String[] {uri});
|
||||
}
|
||||
|
||||
final public void notifyFilesChanged(String[] uris) {
|
||||
notify(changeRegistry, uris);
|
||||
}
|
||||
|
||||
final public void notifyFileDeleted(String uri) {
|
||||
notify(deleteRegistry, uri);
|
||||
notify(deleteRegistry, new String[] {uri});
|
||||
}
|
||||
|
||||
private static void notify(Map<String, ImmutablePair<List<PathMatcher>, Consumer<String>>> registry, String uri) {
|
||||
Path path = Paths.get(URI.create(uri));
|
||||
final public void notifyFilesDeleted(String[] uris) {
|
||||
notify(deleteRegistry, uris);
|
||||
}
|
||||
|
||||
private static void notify(Map<String, ImmutablePair<List<PathMatcher>, Consumer<String[]>>> registry, String[] uris) {
|
||||
// Path path = Paths.get(URI.create(uris));
|
||||
// registry.values().stream()
|
||||
// .filter(pair -> pair.left.stream()
|
||||
// .filter(matcher ->
|
||||
// matcher.matches(path)
|
||||
// )
|
||||
// .findFirst()
|
||||
// .isPresent())
|
||||
// .forEach(pair -> pair.right.accept(uris));
|
||||
//
|
||||
registry.values().stream()
|
||||
.filter(pair -> pair.left.stream()
|
||||
.filter(matcher ->
|
||||
matcher.matches(path)
|
||||
)
|
||||
.findFirst()
|
||||
.isPresent())
|
||||
.forEach(pair -> pair.right.accept(uri));
|
||||
|
||||
// create for each consumer with multiple pattern patchers a pair that contains the pair + an array of matching doc URIs
|
||||
.map(pair -> ImmutablePair.of(
|
||||
pair,
|
||||
|
||||
// this creates an array of those doc URIs that match at least to one of those pattern matchers
|
||||
Arrays.stream(uris)
|
||||
.filter(uri ->
|
||||
|
||||
// keep only URIs for which a matcher succeeds
|
||||
pair.left.stream()
|
||||
.filter(matcher -> matcher.matches(Paths.get(URI.create(uri))))
|
||||
.findFirst()
|
||||
.isPresent())
|
||||
.toArray(String[]::new)))
|
||||
|
||||
// then call the accept method of each consumer with the generated array of doc URIs
|
||||
.forEach(superPair -> superPair.left.right.accept(superPair.right));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2020 Pivotal, 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
|
||||
@@ -23,19 +23,19 @@ import reactor.core.Disposable;
|
||||
*/
|
||||
public interface FileObserver {
|
||||
|
||||
String onFileCreated(List<String> globPattern, Consumer<String> handler);
|
||||
String onFilesCreated(List<String> globPattern, Consumer<String[]> handler);
|
||||
|
||||
String onFileChanged(List<String> globPattern, Consumer<String> handler);
|
||||
String onFilesChanged(List<String> globPattern, Consumer<String[]> handler);
|
||||
|
||||
String onFileDeleted(List<String> globPattern, Consumer<String> handler);
|
||||
String onFilesDeleted(List<String> globPattern, Consumer<String[]> handler);
|
||||
|
||||
boolean unsubscribe(String subscriptionId);
|
||||
|
||||
default Disposable onAnyChange(List<String> globPattern, Consumer<String> handler) {
|
||||
default Disposable onAnyChange(List<String> globPattern, Consumer<String[]> handler) {
|
||||
String[] ids = {
|
||||
onFileChanged(globPattern, handler),
|
||||
onFileCreated(globPattern, handler),
|
||||
onFileDeleted(globPattern, handler)
|
||||
onFilesChanged(globPattern, handler),
|
||||
onFilesCreated(globPattern, handler),
|
||||
onFilesDeleted(globPattern, handler)
|
||||
};
|
||||
return () -> {
|
||||
for (String id : ids) {
|
||||
|
||||
@@ -194,14 +194,14 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
public void serverInitialized() {
|
||||
List<String> globPattern = Arrays.asList(springIndexerJava.getFileWatchPatterns());
|
||||
|
||||
getWorkspaceService().getFileObserver().onFileDeleted(globPattern, (file) -> {
|
||||
deleteDocument(new TextDocumentIdentifier(file).getUri());
|
||||
getWorkspaceService().getFileObserver().onFilesDeleted(globPattern, (files) -> {
|
||||
deleteDocuments(files);
|
||||
});
|
||||
getWorkspaceService().getFileObserver().onFileCreated(globPattern, (file) -> {
|
||||
createDocument(new TextDocumentIdentifier(file).getUri());
|
||||
getWorkspaceService().getFileObserver().onFilesCreated(globPattern, (files) -> {
|
||||
createDocuments(files);
|
||||
});
|
||||
getWorkspaceService().getFileObserver().onFileChanged(globPattern, (file) -> {
|
||||
updateDocument(new TextDocumentIdentifier(file).getUri(), null, "file changed");
|
||||
getWorkspaceService().getFileObserver().onFilesChanged(globPattern, (files) -> {
|
||||
updateDocuments(files, "file changed");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -227,17 +227,17 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
|
||||
private void addXmlFileListeners(List<String> globPattern) {
|
||||
removeXmlFileListeners();
|
||||
watchXMLDeleteRegistration = getWorkspaceService().getFileObserver().onFileDeleted(globPattern,
|
||||
(file) -> {
|
||||
deleteDocument(new TextDocumentIdentifier(file).getUri());
|
||||
watchXMLDeleteRegistration = getWorkspaceService().getFileObserver().onFilesDeleted(globPattern,
|
||||
(files) -> {
|
||||
deleteDocuments(files);
|
||||
});
|
||||
watchXMLCreatedRegistration = getWorkspaceService().getFileObserver().onFileCreated(globPattern,
|
||||
(file) -> {
|
||||
createDocument(new TextDocumentIdentifier(file).getUri());
|
||||
watchXMLCreatedRegistration = getWorkspaceService().getFileObserver().onFilesCreated(globPattern,
|
||||
(files) -> {
|
||||
createDocuments(files);
|
||||
});
|
||||
watchXMLChangedRegistration = getWorkspaceService().getFileObserver().onFileChanged(globPattern,
|
||||
(file) -> {
|
||||
updateDocument(new TextDocumentIdentifier(file).getUri(), null, "xml changed");
|
||||
watchXMLChangedRegistration = getWorkspaceService().getFileObserver().onFilesChanged(globPattern,
|
||||
(files) -> {
|
||||
updateDocuments(files, "xml changed");
|
||||
});
|
||||
}
|
||||
|
||||
@@ -346,6 +346,32 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> createDocuments(String[] docURIs) {
|
||||
synchronized(this) {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
|
||||
for (SpringIndexer indexer : this.indexers) {
|
||||
String[] interestingDocs = getDocumentsInterestingForIndexer(indexer, docURIs);
|
||||
Map<String, IJavaProject> projectsForDocs = getProjectsForDocs(interestingDocs);
|
||||
Map<IJavaProject, List<String>> projectMapping = getProjectMapping(projectsForDocs);
|
||||
|
||||
for (IJavaProject project : projectMapping.keySet()) {
|
||||
List<String> docs = projectMapping.get(project);
|
||||
|
||||
try {
|
||||
UpdatedDoc[] updatedDocs = docs.stream().map(doc -> createUpdatedDoc(doc, null)).toArray(UpdatedDoc[]::new);
|
||||
futures.add(updateItems(project, updatedDocs, indexer));
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf((CompletableFuture[]) futures.toArray(new CompletableFuture[futures.size()]));
|
||||
}
|
||||
}
|
||||
|
||||
private JavaProjectFinder projectFinder() {
|
||||
return params.projectFinder;
|
||||
}
|
||||
@@ -454,7 +480,7 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
try {
|
||||
Optional<IJavaProject> maybeProject = projectFinder().find(new TextDocumentIdentifier(deletedDocURI));
|
||||
if (maybeProject.isPresent()) {
|
||||
DeleteItem deleteItem = new DeleteItem(maybeProject.get(), deletedDocURI, this.indexers);
|
||||
DeleteItems deleteItem = new DeleteItems(maybeProject.get(), new String[] {deletedDocURI}, this.indexers);
|
||||
return CompletableFuture.runAsync(deleteItem, this.updateQueue);
|
||||
}
|
||||
}
|
||||
@@ -467,6 +493,30 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
return null;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> deleteDocuments(String[] deletedDocURIs) {
|
||||
synchronized(this) {
|
||||
try {
|
||||
List<CompletableFuture<Void>> futures = new ArrayList<>();
|
||||
|
||||
Map<String, IJavaProject> projectsForDocs = getProjectsForDocs(deletedDocURIs);
|
||||
Map<IJavaProject, List<String>> projectMapping = getProjectMapping(projectsForDocs);
|
||||
|
||||
for (IJavaProject project : projectMapping.keySet()) {
|
||||
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));
|
||||
}
|
||||
|
||||
return CompletableFuture.allOf((CompletableFuture[]) futures.toArray(new CompletableFuture[futures.size()]));
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("", e);
|
||||
return Futures.error(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public List<SymbolInformation> getAllSymbols(String query) {
|
||||
if (query != null && query.length() > 0) {
|
||||
synchronized(this.symbols) {
|
||||
@@ -651,24 +701,27 @@ public class SpringSymbolIndex implements InitializingBean {
|
||||
}, this.updateQueue);
|
||||
}
|
||||
|
||||
private class DeleteItem implements Runnable {
|
||||
private class DeleteItems implements Runnable {
|
||||
|
||||
private final String docURI;
|
||||
private final String[] docURIs;
|
||||
private final IJavaProject project;
|
||||
private final SpringIndexer[] indexer;
|
||||
|
||||
public DeleteItem(IJavaProject project, String docURI, SpringIndexer[] indexer) {
|
||||
public DeleteItems(IJavaProject project, String[] docURIs, SpringIndexer[] indexer) {
|
||||
this.project = project;
|
||||
this.docURI = docURI;
|
||||
this.docURIs = docURIs;
|
||||
this.indexer = indexer;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
removeSymbolsByDoc(project, docURI);
|
||||
for (String doc : this.docURIs) {
|
||||
removeSymbolsByDoc(project, doc);
|
||||
}
|
||||
|
||||
for (SpringIndexer index : this.indexer) {
|
||||
index.removeFiles(project, new String[] {docURI});
|
||||
index.removeFiles(project, docURIs);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2017, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2017, 2020 Pivotal, 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
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2020 Pivotal, 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
|
||||
@@ -15,7 +15,9 @@ import java.io.FileInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.Reader;
|
||||
import java.util.HashSet;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
@@ -63,11 +65,20 @@ public class AdHocSpringPropertyIndexProvider implements ProjectBasedPropertyInd
|
||||
"**/application.properties",
|
||||
"**/application.yml"
|
||||
), changed -> {
|
||||
log.debug("File changed: {}", changed);
|
||||
projectFinder.find(new TextDocumentIdentifier(changed)).ifPresent(project -> {
|
||||
log.debug("Files changed: {}", (Object[])changed);
|
||||
|
||||
Set<IJavaProject> affectedProjects = new HashSet<>();
|
||||
for (String docURI : changed) {
|
||||
projectFinder.find(new TextDocumentIdentifier(docURI)).ifPresent(project -> {
|
||||
affectedProjects.add(project);
|
||||
});
|
||||
}
|
||||
|
||||
for (IJavaProject project : affectedProjects) {
|
||||
log.debug("=> Project changed: {}", project.getElementName());
|
||||
indexes.invalidate(project);
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
if (documents!=null) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2018, 2019 Pivotal, Inc.
|
||||
* Copyright (c) 2018, 2020 Pivotal, 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
|
||||
@@ -204,13 +204,16 @@ public class MockProjects {
|
||||
}
|
||||
|
||||
private static class FileListener {
|
||||
|
||||
final PathMatcher matcher;
|
||||
final Consumer<String> handler;
|
||||
FileListener(List<String> globPatterns, Consumer<String> listener) {
|
||||
final Consumer<String[]> handler;
|
||||
|
||||
FileListener(List<String> globPatterns, Consumer<String[]> listener) {
|
||||
super();
|
||||
this.matcher = buildPathMatcher(globPatterns);
|
||||
this.handler = listener;
|
||||
}
|
||||
|
||||
private PathMatcher buildPathMatcher(List<String> globPatterns) {
|
||||
if (globPatterns.size()==0) {
|
||||
return path -> true;
|
||||
@@ -241,7 +244,7 @@ public class MockProjects {
|
||||
final Map<String,FileListener> change_listeners = new HashMap<>();
|
||||
final Map<String,FileListener> delete_listeners = new HashMap<>();
|
||||
|
||||
private String add(Map<String, FileListener> listeners, List<String> globPatterns, Consumer<String> handler) {
|
||||
private String add(Map<String, FileListener> listeners, List<String> globPatterns, Consumer<String[]> handler) {
|
||||
String id = ""+idGen.incrementAndGet();
|
||||
synchronized (listeners) {
|
||||
listeners.put(id, new FileListener(globPatterns, handler));
|
||||
@@ -262,25 +265,25 @@ public class MockProjects {
|
||||
synchronized (listeners) {
|
||||
for (FileListener l : listeners.values()) {
|
||||
if (l.matcher.matches(path)) {
|
||||
l.handler.accept(target.toURI().toString());
|
||||
l.handler.accept(new String[] {target.toURI().toString()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileCreated(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesCreated(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return add(create_listeners, globPattern, handler);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String onFileChanged(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesChanged(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return add(change_listeners, globPattern, handler);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String onFileDeleted(List<String> globPattern, Consumer<String> handler) {
|
||||
public String onFilesDeleted(List<String> globPattern, Consumer<String[]> handler) {
|
||||
return add(delete_listeners, globPattern, handler);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user