GH-1118: update cache once for multiple files being deleted
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2019, 2020 Pivotal, Inc.
|
||||
* Copyright (c) 2019, 2023 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
|
||||
@@ -30,6 +30,7 @@ public interface IndexCache {
|
||||
|
||||
void remove(IndexCacheKey cacheKey);
|
||||
<T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type);
|
||||
<T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type);
|
||||
|
||||
default <T extends IndexCacheable> T[] retrieveSymbols(IndexCacheKey cacheKey, String[] files, Class<T> type) {
|
||||
Pair<T[], Multimap<String, String>> r = retrieve(cacheKey, files, type);
|
||||
|
||||
@@ -168,6 +168,33 @@ public class IndexCacheOnDisc implements IndexCache {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IndexCacheable> void removeFiles(IndexCacheKey cacheKey, String[] files, Class<T> type) {
|
||||
@SuppressWarnings("unchecked")
|
||||
IndexCacheStore<T> cacheStore = (IndexCacheStore<T>) this.stores.get(cacheKey);
|
||||
|
||||
if (cacheStore != null) {
|
||||
|
||||
SortedMap<String, Long> timestampedFiles = new TreeMap<>(cacheStore.getTimestampedFiles());
|
||||
Map<String, Collection<String>> changedDeps = new HashMap<>(cacheStore.getDependencies());
|
||||
Set<String> docURIs = new HashSet<>();
|
||||
|
||||
for (String file : files) {
|
||||
String docURI = UriUtil.toUri(new File(file)).toASCIIString();
|
||||
docURIs.add(docURI);
|
||||
|
||||
timestampedFiles.remove(file);
|
||||
changedDeps.remove(file);
|
||||
}
|
||||
|
||||
List<T> cachedSymbols = cacheStore.getSymbols().stream()
|
||||
.filter(cachedSymbol -> !docURIs.contains(cachedSymbol.getDocURI()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
save(cacheKey, cachedSymbols, timestampedFiles, changedDeps, type);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void remove(IndexCacheKey cacheKey) {
|
||||
File cacheStore = new File(cacheDirectory, cacheKey.toString() + ".json");
|
||||
|
||||
@@ -47,6 +47,10 @@ public class IndexCacheVoid implements IndexCache {
|
||||
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getModificationTimestamp(IndexCacheKey cacheKey, String docURI) {
|
||||
return 0;
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.utils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.FileSystems;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
@@ -284,11 +285,16 @@ public class SpringFactoriesIndexer implements SpringIndexer {
|
||||
|
||||
@Override
|
||||
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
|
||||
String[] files = Arrays.stream(docURIs).map(docURI -> {
|
||||
try {
|
||||
return new File(new URI(docURI)).getAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).toArray(String[]::new);
|
||||
|
||||
IndexCacheKey key = getCacheKey(project);
|
||||
for (String docUri : docURIs) {
|
||||
String file = new File(new URI(docUri)).getAbsolutePath();
|
||||
cache.removeFile(key, file, CachedSymbol.class);
|
||||
}
|
||||
cache.removeFiles(key, files, CachedSymbol.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -199,17 +199,22 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
@Override
|
||||
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
|
||||
|
||||
String[] files = Arrays.stream(docURIs).map(docURI -> {
|
||||
try {
|
||||
return new File(new URI(docURI)).getAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).toArray(String[]::new);
|
||||
|
||||
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
|
||||
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
|
||||
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
|
||||
|
||||
for (String docURI : docURIs) {
|
||||
String file = new File(new URI(docURI)).getAbsolutePath();
|
||||
|
||||
this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
|
||||
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
|
||||
this.cache.removeFile(diagnosticsCacheKey, file, CachedDiagnostics.class);
|
||||
}
|
||||
this.cache.removeFiles(symbolsCacheKey, files, CachedSymbol.class);
|
||||
this.cache.removeFiles(beansCacheKey, files, CachedBean.class);
|
||||
this.cache.removeFiles(diagnosticsCacheKey, files, CachedDiagnostics.class);
|
||||
}
|
||||
|
||||
private DocumentDescriptor[] filterDocuments(IJavaProject project, DocumentDescriptor[] updatedDocs) {
|
||||
|
||||
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.utils;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
@@ -212,15 +213,19 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
|
||||
@Override
|
||||
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
|
||||
String[] files = Arrays.stream(docURIs).map(docURI -> {
|
||||
try {
|
||||
return new File(new URI(docURI)).getAbsolutePath();
|
||||
} catch (URISyntaxException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}).toArray(String[]::new);
|
||||
|
||||
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
|
||||
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
|
||||
|
||||
for (String docURI : docURIs) {
|
||||
String file = new File(new URI(docURI)).getAbsolutePath();
|
||||
|
||||
this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
|
||||
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
|
||||
}
|
||||
this.cache.removeFiles(symbolsCacheKey, files, CachedSymbol.class);
|
||||
this.cache.removeFiles(beansCacheKey, files, CachedBean.class);
|
||||
}
|
||||
|
||||
private void scanFile(IJavaProject project, String fileName, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) {
|
||||
|
||||
@@ -621,4 +621,82 @@ public class IndexCacheOnDiscTest {
|
||||
assertEquals(ImmutableSet.of(), cachedDependencies.get(file1.toString()));
|
||||
assertEquals(ImmutableSet.of("dep2"), cachedDependencies.get(file2.toString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
void testMultipleFilesDeleted() throws Exception {
|
||||
Path file1 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile1");
|
||||
Path file2 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile2");
|
||||
Path file3 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile3");
|
||||
Path file4 = Paths.get(tempDir.toAbsolutePath().toString(), "tempFile4");
|
||||
|
||||
Files.createFile(file1);
|
||||
Files.createFile(file2);
|
||||
Files.createFile(file3);
|
||||
Files.createFile(file4);
|
||||
|
||||
FileTime timeFile1 = Files.getLastModifiedTime(file1);
|
||||
FileTime timeFile2 = Files.getLastModifiedTime(file2);
|
||||
FileTime timeFile3 = Files.getLastModifiedTime(file3);
|
||||
FileTime timeFile4 = Files.getLastModifiedTime(file4);
|
||||
String[] files = {
|
||||
file1.toAbsolutePath().toString(),
|
||||
file2.toAbsolutePath().toString(),
|
||||
file3.toAbsolutePath().toString(),
|
||||
file4.toAbsolutePath().toString()
|
||||
};
|
||||
|
||||
String doc1URI = UriUtil.toUri(file1.toFile()).toASCIIString();
|
||||
String doc2URI = UriUtil.toUri(file2.toFile()).toASCIIString();
|
||||
String doc3URI = UriUtil.toUri(file3.toFile()).toASCIIString();
|
||||
String doc4URI = UriUtil.toUri(file4.toFile()).toASCIIString();
|
||||
|
||||
List<CachedSymbol> generatedSymbols = new ArrayList<>();
|
||||
|
||||
WorkspaceSymbol symbol1 = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20)))));
|
||||
EnhancedSymbolInformation enhancedSymbol1 = new EnhancedSymbolInformation(symbol1, null);
|
||||
|
||||
WorkspaceSymbol symbol2 = new WorkspaceSymbol("symbol2", SymbolKind.Field, Either.forLeft(new Location(doc2URI, new Range(new Position(5, 10), new Position(5, 20)))));
|
||||
EnhancedSymbolInformation enhancedSymbol2 = new EnhancedSymbolInformation(symbol2, null);
|
||||
|
||||
WorkspaceSymbol symbol3 = new WorkspaceSymbol("symbol3", SymbolKind.Field, Either.forLeft(new Location(doc3URI, new Range(new Position(20, 11), new Position(20, 30)))));
|
||||
EnhancedSymbolInformation enhancedSymbol3 = new EnhancedSymbolInformation(symbol3, null);
|
||||
|
||||
WorkspaceSymbol symbol4 = new WorkspaceSymbol("symbol4", SymbolKind.Field, Either.forLeft(new Location(doc4URI, new Range(new Position(4, 4), new Position(5, 5)))));
|
||||
EnhancedSymbolInformation enhancedSymbol4 = new EnhancedSymbolInformation(symbol4, null);
|
||||
|
||||
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
|
||||
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2));
|
||||
generatedSymbols.add(new CachedSymbol(doc3URI, timeFile3.toMillis(), enhancedSymbol3));
|
||||
generatedSymbols.add(new CachedSymbol(doc4URI, timeFile4.toMillis(), enhancedSymbol4));
|
||||
|
||||
Multimap<String, String> dependencies = ImmutableMultimap.of(
|
||||
file1.toString(), "dep1",
|
||||
file2.toString(), "dep2"
|
||||
);
|
||||
cache.store(CACHE_KEY_VERSION_1, files, generatedSymbols, dependencies, CachedSymbol.class);
|
||||
// cache.removeFile(CACHE_KEY_VERSION_1, file1.toAbsolutePath().toString(), CachedSymbol.class);
|
||||
// cache.removeFile(CACHE_KEY_VERSION_1, file3.toAbsolutePath().toString(), CachedSymbol.class);
|
||||
cache.removeFiles(CACHE_KEY_VERSION_1, new String[] {file1.toAbsolutePath().toString(), file3.toAbsolutePath().toString()}, CachedSymbol.class);
|
||||
|
||||
files = new String[]{file2.toAbsolutePath().toString(), file4.toAbsolutePath().toString()};
|
||||
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(CACHE_KEY_VERSION_1, files, CachedSymbol.class);
|
||||
CachedSymbol[] cachedSymbols = result.getLeft();
|
||||
assertNotNull(result);
|
||||
assertEquals(2, cachedSymbols.length);
|
||||
|
||||
assertEquals("symbol2", cachedSymbols[0].getEnhancedSymbol().getSymbol().getName());
|
||||
assertEquals(SymbolKind.Field, cachedSymbols[0].getEnhancedSymbol().getSymbol().getKind());
|
||||
assertEquals(new Location(doc2URI, new Range(new Position(5, 10), new Position(5, 20))), cachedSymbols[0].getEnhancedSymbol().getSymbol().getLocation().getLeft());
|
||||
assertNull(cachedSymbols[0].getEnhancedSymbol().getAdditionalInformation());
|
||||
|
||||
assertEquals("symbol4", cachedSymbols[1].getEnhancedSymbol().getSymbol().getName());
|
||||
assertEquals(SymbolKind.Field, cachedSymbols[1].getEnhancedSymbol().getSymbol().getKind());
|
||||
assertEquals(new Location(doc4URI, new Range(new Position(4, 4), new Position(5, 5))), cachedSymbols[1].getEnhancedSymbol().getSymbol().getLocation().getLeft());
|
||||
assertNull(cachedSymbols[1].getEnhancedSymbol().getAdditionalInformation());
|
||||
|
||||
Multimap<String, String> cachedDependencies = result.getRight();
|
||||
assertEquals(ImmutableSet.of(), cachedDependencies.get(file1.toString()));
|
||||
assertEquals(ImmutableSet.of("dep2"), cachedDependencies.get(file2.toString()));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,10 @@ public class IndexCacheTimestampsOnly implements IndexCache {
|
||||
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IndexCacheable> void removeFiles(IndexCacheKey symbolCacheKey, String[] files, Class<T> type) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getModificationTimestamp(IndexCacheKey cacheKey, String file) {
|
||||
Map<String, Long> timestampMap = timestampCache.get(cacheKey);
|
||||
|
||||
Reference in New Issue
Block a user