refactored symbol cache to enable reuse for various types of cache items and separated symbol cache from beans index cache

This commit is contained in:
Martin Lippert
2023-07-12 14:13:21 +02:00
parent 0be66eb6ae
commit 97cf3b32f4
23 changed files with 477 additions and 255 deletions

View File

@@ -170,37 +170,44 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
public void addSymbols(IJavaProject project, EnhancedSymbolInformation[] enhancedSymbols,
Bean[] beanDefinitions) {
// organize symbols by doc URI
Map<String, List<EnhancedSymbolInformation>> symbolsPerDoc = new HashMap<>();
for (EnhancedSymbolInformation symbol : enhancedSymbols) {
Either<Location, WorkspaceSymbolLocation> location = symbol.getSymbol().getLocation();
String docURI = location.isLeft() ? location.getLeft().getUri() : location.getRight().getUri();
symbolsPerDoc.computeIfAbsent(docURI, k -> new ArrayList<>()).add(symbol);
}
if (enhancedSymbols != null) {
// add symbols per doc
for (Map.Entry<String, List<EnhancedSymbolInformation>> entry : symbolsPerDoc.entrySet()) {
String docURI = entry.getKey();
List<EnhancedSymbolInformation> symbols = entry.getValue();
SpringSymbolIndex.this.addSymbolsByDoc(project, docURI, (EnhancedSymbolInformation[]) symbols.toArray(new EnhancedSymbolInformation[symbols.size()]));
// organize symbols by doc URI
Map<String, List<EnhancedSymbolInformation>> symbolsPerDoc = new HashMap<>();
for (EnhancedSymbolInformation symbol : enhancedSymbols) {
Either<Location, WorkspaceSymbolLocation> location = symbol.getSymbol().getLocation();
String docURI = location.isLeft() ? location.getLeft().getUri() : location.getRight().getUri();
symbolsPerDoc.computeIfAbsent(docURI, k -> new ArrayList<>()).add(symbol);
}
// add symbols per doc
for (Map.Entry<String, List<EnhancedSymbolInformation>> entry : symbolsPerDoc.entrySet()) {
String docURI = entry.getKey();
List<EnhancedSymbolInformation> symbols = entry.getValue();
SpringSymbolIndex.this.addSymbolsByDoc(project, docURI, (EnhancedSymbolInformation[]) symbols.toArray(new EnhancedSymbolInformation[symbols.size()]));
}
}
// organize beans per doc URI
Map<String, List<Bean>> beansPerDoc = new HashMap<>();
for (Bean bean : beanDefinitions) {
String docURI = bean.getLocation().getUri();
beansPerDoc.computeIfAbsent(docURI, k -> new ArrayList<>()).add(bean);
if (beanDefinitions != null) {
// organize beans per doc URI
Map<String, List<Bean>> beansPerDoc = new HashMap<>();
for (Bean bean : beanDefinitions) {
String docURI = bean.getLocation().getUri();
beansPerDoc.computeIfAbsent(docURI, k -> new ArrayList<>()).add(bean);
}
// add beans per doc URI
for (Map.Entry<String, List<Bean>> entry : beansPerDoc.entrySet()) {
String docURI = entry.getKey();
List<Bean> beans = entry.getValue();
springIndex.updateBeans(project.getElementName(), docURI, (Bean[]) beans.toArray(new Bean[beans.size()]));
}
}
// add beans per doc URI
for (Map.Entry<String, List<Bean>> entry : beansPerDoc.entrySet()) {
String docURI = entry.getKey();
List<Bean> beans = entry.getValue();
springIndex.updateBeans(project.getElementName(), docURI, (Bean[]) beans.toArray(new Bean[beans.size()]));
}
}
@Override

View File

@@ -0,0 +1,27 @@
/*******************************************************************************
* 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.index.cache;
public abstract class AbstractIndexCacheable implements IndexCacheable {
private final String docURI;
public AbstractIndexCacheable(String docURI) {
this.docURI = docURI;
}
@Override
public String getDocURI() {
return this.docURI;
}
}

View File

@@ -14,7 +14,6 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import com.google.common.collect.Multimap;
@@ -23,17 +22,17 @@ import com.google.common.collect.Multimap;
*/
public interface IndexCache {
void store(IndexCacheKey cacheKey, String[] files, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies);
Pair<CachedSymbol[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files);
<T extends IndexCacheable> void store(IndexCacheKey cacheKey, String[] files, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type);
<T extends IndexCacheable> Pair<T[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files, Class<T> type);
void update(IndexCacheKey cacheKey, String file, long lastModified, List<CachedSymbol> generatedSymbols, Set<String> dependencies);
void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies);
<T extends IndexCacheable> void update(IndexCacheKey cacheKey, String file, long lastModified, List<T> generatedSymbols, Set<String> dependencies, Class<T> type);
<T extends IndexCacheable> void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type);
void remove(IndexCacheKey cacheKey);
void removeFile(IndexCacheKey symbolCacheKey, String file);
<T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type);
default CachedSymbol[] retrieveSymbols(IndexCacheKey cacheKey, String[] files) {
Pair<CachedSymbol[], Multimap<String, String>> r = retrieve(cacheKey, files);
default <T extends IndexCacheable> T[] retrieveSymbols(IndexCacheKey cacheKey, String[] files, Class<T> type) {
Pair<T[], Multimap<String, String>> r = retrieve(cacheKey, files, type);
return r!=null ? r.getLeft() : null;
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019 2021 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
@@ -14,6 +14,7 @@ import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Array;
import java.lang.reflect.Type;
import java.nio.file.Files;
import java.util.Arrays;
@@ -34,7 +35,6 @@ import org.eclipse.lsp4j.Location;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
import org.springframework.ide.vscode.commons.util.UriUtil;
@@ -53,6 +53,7 @@ import com.google.gson.JsonParseException;
import com.google.gson.JsonPrimitive;
import com.google.gson.JsonSerializationContext;
import com.google.gson.JsonSerializer;
import com.google.gson.reflect.TypeToken;
import com.google.gson.stream.JsonReader;
/**
@@ -61,7 +62,7 @@ import com.google.gson.stream.JsonReader;
public class IndexCacheOnDisc implements IndexCache {
private final File cacheDirectory;
private final Map<IndexCacheKey, CacheStore> stores;
private final Map<IndexCacheKey, IndexCacheStore<? extends IndexCacheable>> stores;
private static final Logger log = LoggerFactory.getLogger(IndexCacheOnDisc.class);
@@ -79,10 +80,11 @@ public class IndexCacheOnDisc implements IndexCache {
}
@Override
public void store(IndexCacheKey cacheKey, String[] files, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies) {
if (dependencies==null) {
public <T extends IndexCacheable> void store(IndexCacheKey cacheKey, String[] files, List<T> elements, Multimap<String, String> dependencies, Class<T> type) {
if (dependencies == null) {
dependencies = ImmutableMultimap.of();
}
SortedMap<String, Long> timestampedFiles = new TreeMap<>();
timestampedFiles = Arrays.stream(files)
@@ -95,18 +97,19 @@ public class IndexCacheOnDisc implements IndexCache {
}
}, (v1,v2) -> { throw new RuntimeException(String.format("Duplicate key for values %s and %s", v1, v2));}, TreeMap::new));
save(cacheKey, generatedSymbols, timestampedFiles, dependencies.asMap());
save(cacheKey, elements, timestampedFiles, dependencies.asMap(), type);
}
@SuppressWarnings("unchecked")
@Override
public Pair<CachedSymbol[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files) {
public <T extends IndexCacheable> Pair<T[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files, Class<T> type) {
File cacheStore = new File(cacheDirectory, cacheKey.toString() + ".json");
if (cacheStore.exists()) {
Gson gson = createGson();
try (JsonReader reader = new JsonReader(new FileReader(cacheStore))) {
CacheStore store = gson.fromJson(reader, CacheStore.class);
IndexCacheStore<T> store = gson.fromJson(reader, IndexCacheStore.class);
SortedMap<String, Long> timestampedFiles = Arrays.stream(files)
.filter(file -> new File(file).exists())
@@ -121,16 +124,19 @@ public class IndexCacheOnDisc implements IndexCache {
if (isFileMatch(timestampedFiles, store.getTimestampedFiles())) {
this.stores.put(cacheKey, store);
List<CachedSymbol> symbols = store.getSymbols();
List<T> symbols = store.getSymbols();
Map<String, Collection<String>> storedDependencies = store.getDependencies();
Multimap<String, String> dependencies = MultimapBuilder.hashKeys().hashSetValues().build();
if (storedDependencies!=null && !storedDependencies.isEmpty()) {
for (Entry<String, Collection<String>> entry : storedDependencies.entrySet()) {
dependencies.replaceValues(entry.getKey(), entry.getValue());
}
}
return Pair.of(
(CachedSymbol[]) symbols.toArray(new CachedSymbol[symbols.size()]),
(T[]) symbols.toArray((T[]) Array.newInstance(type, symbols.size())),
MultimapBuilder.hashKeys().hashSetValues().build(dependencies)
);
}
@@ -143,20 +149,22 @@ public class IndexCacheOnDisc implements IndexCache {
}
@Override
public void removeFile(IndexCacheKey cacheKey, String file) {
CacheStore cacheStore = this.stores.get(cacheKey);
public <T extends IndexCacheable> void removeFile(IndexCacheKey cacheKey, String file, Class<T> type) {
@SuppressWarnings("unchecked")
IndexCacheStore<T> cacheStore = (IndexCacheStore<T>) this.stores.get(cacheKey);
if (cacheStore != null) {
String docURI = UriUtil.toUri(new File(file)).toASCIIString();
SortedMap<String, Long> timestampedFiles = new TreeMap<>(cacheStore.getTimestampedFiles());
timestampedFiles.remove(file);
List<CachedSymbol> cachedSymbols = cacheStore.getSymbols().stream()
List<T> cachedSymbols = cacheStore.getSymbols().stream()
.filter(cachedSymbol -> !cachedSymbol.getDocURI().equals(docURI))
.collect(Collectors.toList());
Map<String, Collection<String>> changedDeps = new HashMap<>(cacheStore.getDependencies());
changedDeps.remove(file);
save(cacheKey, cachedSymbols, timestampedFiles, changedDeps);
save(cacheKey, cachedSymbols, timestampedFiles, changedDeps, type);
}
}
@@ -170,12 +178,14 @@ public class IndexCacheOnDisc implements IndexCache {
}
@Override
public void update(IndexCacheKey cacheKey, String file, long lastModified, List<CachedSymbol> generatedSymbols, Set<String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String file, long lastModified,
List<T> generatedSymbols, Set<String> dependencies, Class<T> type) {
if (dependencies == null) {
dependencies = ImmutableSet.of();
}
CacheStore cacheStore = this.stores.get(cacheKey);
@SuppressWarnings("unchecked")
IndexCacheStore<T> cacheStore = (IndexCacheStore<T>) this.stores.get(cacheKey);
if (cacheStore != null) {
String docURI = UriUtil.toUri(new File(file)).toASCIIString();
@@ -183,7 +193,7 @@ public class IndexCacheOnDisc implements IndexCache {
SortedMap<String, Long> timestampedFiles = new TreeMap<>(cacheStore.getTimestampedFiles());
timestampedFiles.put(file, lastModified);
List<CachedSymbol> cachedSymbols = cacheStore.getSymbols().stream()
List<T> cachedSymbols = cacheStore.getSymbols().stream()
.filter(cachedSymbol -> !cachedSymbol.getDocURI().equals(docURI))
.collect(Collectors.toList());
@@ -195,17 +205,20 @@ public class IndexCacheOnDisc implements IndexCache {
} else {
changedDependencies.put(file, ImmutableSet.copyOf(dependencies));
}
save(cacheKey, cachedSymbols, timestampedFiles, changedDependencies);
save(cacheKey, cachedSymbols, timestampedFiles, changedDependencies, type);
}
}
@Override
public void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String[] files, long[] lastModified,
List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type) {
if (dependencies == null) {
dependencies = ImmutableMultimap.of();
}
CacheStore cacheStore = this.stores.get(cacheKey);
@SuppressWarnings("unchecked")
IndexCacheStore<T> cacheStore = (IndexCacheStore<T>) this.stores.get(cacheKey);
if (cacheStore != null) {
SortedMap<String, Long> timestampedFiles = new TreeMap<>(cacheStore.getTimestampedFiles());
@@ -231,19 +244,19 @@ public class IndexCacheOnDisc implements IndexCache {
}
// update cache internal list of cached symbols (by removing old ones and adding all new ones)
List<CachedSymbol> cachedSymbols = cacheStore.getSymbols().stream()
List<T> cachedSymbols = cacheStore.getSymbols().stream()
.filter(cachedSymbol -> !allDocURIs.contains(cachedSymbol.getDocURI()))
.collect(Collectors.toList());
cachedSymbols.addAll(generatedSymbols);
// store the complete cache content of this project to disc
save(cacheKey, cachedSymbols, timestampedFiles, changedDependencies);
save(cacheKey, cachedSymbols, timestampedFiles, changedDependencies, type);
}
}
@Override
public long getModificationTimestamp(IndexCacheKey cacheKey, String file) {
CacheStore cacheStore = this.stores.get(cacheKey);
IndexCacheStore<? extends IndexCacheable> cacheStore = this.stores.get(cacheKey);
if (cacheStore != null) {
Long result = cacheStore.getTimestampedFiles().get(file);
@@ -255,9 +268,9 @@ public class IndexCacheOnDisc implements IndexCache {
return 0;
}
private void save(IndexCacheKey cacheKey, List<CachedSymbol> generatedSymbols,
SortedMap<String, Long> timestampedFiles, Map<String, Collection<String>> dependencies) {
CacheStore store = new CacheStore(timestampedFiles, generatedSymbols, dependencies);
private <T extends IndexCacheable> void save(IndexCacheKey cacheKey, List<T> elements, SortedMap<String, Long> timestampedFiles,
Map<String, Collection<String>> dependencies, Class<T> type) {
IndexCacheStore<T> store = new IndexCacheStore<T>(timestampedFiles, elements, dependencies, type);
this.stores.put(cacheKey, store);
try (FileWriter writer = new FileWriter(new File(cacheDirectory, cacheKey.toString() + ".json")))
@@ -301,6 +314,7 @@ public class IndexCacheOnDisc implements IndexCache {
return new GsonBuilder()
.registerTypeAdapter(SymbolAddOnInformation.class, new SymbolAddOnInformationAdapter())
.registerTypeAdapter(Bean.class, new BeanJsonAdapter())
.registerTypeAdapter(IndexCacheStore.class, new IndexCacheStoreAdapter())
.create();
}
@@ -308,31 +322,68 @@ public class IndexCacheOnDisc implements IndexCache {
/**
* internal storage structure
*/
private static class CacheStore {
private static class IndexCacheStore<T extends IndexCacheable> {
@SuppressWarnings("unused")
private final String elementType;
private final SortedMap<String, Long> timestampedFiles;
private final List<CachedSymbol> symbols;
private final List<T> elements;
private final Map<String, Collection<String>> dependencies;
public CacheStore(SortedMap<String, Long> timestampedFiles, List<CachedSymbol> symbols, Map<String, Collection<String>> dependencies) {
super();
public IndexCacheStore(SortedMap<String, Long> timestampedFiles, List<T> elements, Map<String, Collection<String>> dependencies, Class<T> elementType) {
this.timestampedFiles = timestampedFiles;
this.symbols = symbols;
this.elements = elements;
this.dependencies = dependencies;
this.elementType = elementType.getName();
}
public Map<String, Collection<String>> getDependencies() {
return dependencies;
}
public List<CachedSymbol> getSymbols() {
return symbols;
public List<T> getSymbols() {
return elements;
}
public SortedMap<String, Long> getTimestampedFiles() {
return timestampedFiles;
}
}
private static class IndexCacheStoreAdapter implements JsonDeserializer<IndexCacheStore<?>> {
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public IndexCacheStore<?> deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
throws JsonParseException {
JsonObject parsedObject = json.getAsJsonObject();
String className = parsedObject.get("elementType").getAsString();
try {
Class<?> elementType = Class.forName(className);
JsonElement elementsObject = parsedObject.get("elements");
Type elementListType = TypeToken.getParameterized(List.class, elementType).getType();
List elements = context.deserialize(elementsObject, elementListType);
JsonElement timestampedFilesObject = parsedObject.get("timestampedFiles");
Type timestampsMapType = TypeToken.getParameterized(SortedMap.class, String.class, Long.class).getType();
SortedMap timestampedFiles = context.deserialize(timestampedFilesObject, timestampsMapType);
JsonElement dependenciesObject = parsedObject.get("dependencies");
Map dependencies = context.deserialize(dependenciesObject, HashMap.class);
return new IndexCacheStore(timestampedFiles, elements, dependencies, elementType);
} catch (ClassNotFoundException e) {
throw new JsonParseException("cannot parse data from index cache with element type: " + className, e);
}
}
}
/**

View File

@@ -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
@@ -14,7 +14,6 @@ import java.util.List;
import java.util.Set;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import com.google.common.collect.Multimap;
@@ -24,20 +23,20 @@ import com.google.common.collect.Multimap;
public class IndexCacheVoid implements IndexCache {
@Override
public void store(IndexCacheKey cacheKey, String[] files, List<CachedSymbol> generatedSymbols, Multimap<String,String> dependencies) {
public <T extends IndexCacheable> void store(IndexCacheKey cacheKey, String[] files, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type) {
}
@Override
public Pair<CachedSymbol[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files) {
public <T extends IndexCacheable> Pair<T[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files, Class<T> type) {
return null;
}
@Override
public void update(IndexCacheKey cacheKey, String file, long lastModified, List<CachedSymbol> generatedSymbols, Set<String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String file, long lastModified, List<T> generatedSymbols, Set<String> dependencies, Class<T> type) {
}
@Override
public void update(IndexCacheKey cacheKey, String[] file, long[] lastModified, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type) {
}
@Override
@@ -45,7 +44,7 @@ public class IndexCacheVoid implements IndexCache {
}
@Override
public void removeFile(IndexCacheKey symbolCacheKey, String file) {
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
}
@Override

View File

@@ -0,0 +1,16 @@
/*******************************************************************************
* 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.index.cache;
public interface IndexCacheable {
String getDocURI();
}

View File

@@ -101,7 +101,8 @@ public class BeansSymbolProvider extends AbstractSymbolProvider {
Bean beanDefinition = new Bean(nameAndRegion.getT1(), beanType.getQualifiedName(), location, injectionPoints, (String[]) supertypes.toArray(new String[supertypes.size()]), annotations);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, beanDefinition));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));
} catch (BadLocationException e) {
log.error("", e);
@@ -121,7 +122,7 @@ public class BeansSymbolProvider extends AbstractSymbolProvider {
Either.forLeft(new Location(doc.getUri(), doc.toRange(functionBean.getT3()))));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(),
new EnhancedSymbolInformation(symbol, new SymbolAddOnInformation[] {new BeansSymbolAddOnInformation(functionBean.getT1(), functionBean.getT2().getQualifiedName())}), null));
new EnhancedSymbolInformation(symbol, new SymbolAddOnInformation[] {new BeansSymbolAddOnInformation(functionBean.getT1(), functionBean.getT2().getQualifiedName())})));
} catch (BadLocationException e) {
log.error("", e);

View File

@@ -0,0 +1,29 @@
/*******************************************************************************
* 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.java.beans;
import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
public class CachedBean extends AbstractIndexCacheable {
private final Bean bean;
public CachedBean(String docURI, Bean bean) {
super(docURI);
this.bean = bean;
}
public Bean getBean() {
return this.bean;
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2022 Pivotal, Inc.
* Copyright (c) 2017, 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
@@ -28,7 +28,6 @@ import org.eclipse.lsp4j.jsonrpc.messages.Tuple.Two;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
@@ -56,7 +55,8 @@ public class ComponentSymbolProvider extends AbstractSymbolProvider {
EnhancedSymbolInformation enhancedSymbol = result.getFirst();
Bean beanDefinition = result.getSecond();
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, beanDefinition));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));
}
}
catch (Exception e) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018, 2019 Pivotal, Inc.
* Copyright (c) 2018, 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
@@ -23,6 +23,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.java.beans.BeanUtils;
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
@@ -74,7 +75,8 @@ public class DataRepositorySymbolProvider extends AbstractSymbolProvider {
String concreteRepoType = concreteBeanTypeBindung.getQualifiedName();
Bean beanDefinition = new Bean(beanName, concreteRepoType, location, injectionPoints, (String[]) supertypes.toArray(new String[supertypes.size()]), new String[0]);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, beanDefinition));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
context.getBeans().add(new CachedBean(context.getDocURI(), beanDefinition));
} catch (BadLocationException e) {
log.error("error creating data repository symbol for a specific range", e);

View File

@@ -0,0 +1,21 @@
/*******************************************************************************
* 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.java.reconcilers;
import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
public class CachedDiagnostics extends AbstractIndexCacheable {
public CachedDiagnostics(String docURI) {
super(docURI);
}
}

View File

@@ -63,7 +63,7 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider {
return resultPath.startsWith("/") ? resultPath : "/" + resultPath;
}))
.map(p -> RouteUtils.createRouteSymbol(location, p, methods, contentTypes, acceptTypes, null))
.forEach((enhancedSymbol) -> context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, null)));
.forEach((enhancedSymbol) -> context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol)));
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -112,7 +112,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider {
EnhancedSymbolInformation enhancedSymbol = RouteUtils.createRouteSymbol(location, path, getElementStrings(httpMethods),
getElementStrings(contentTypes), getElementStrings(acceptTypes), addon);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, null));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
} catch (BadLocationException e) {
e.printStackTrace();

View File

@@ -10,43 +10,31 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.utils;
import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
public class CachedSymbol {
public class CachedSymbol extends AbstractIndexCacheable {
private final String docURI;
private final long lastModified;
private final EnhancedSymbolInformation enhancedSymbol;
private final Bean bean;
public CachedSymbol(String docURI, long lastModified, EnhancedSymbolInformation enhancedSymbol, Bean bean) {
this.docURI = docURI;
public CachedSymbol(String docURI, long lastModified, EnhancedSymbolInformation enhancedSymbol) {
super(docURI);
this.lastModified = lastModified;
this.enhancedSymbol = enhancedSymbol;
this.bean = bean;
}
public EnhancedSymbolInformation getEnhancedSymbol() {
return enhancedSymbol;
}
public Bean getBean() {
return bean;
}
public String getDocURI() {
return docURI;
}
public long getLastModified() {
return lastModified;
}
@Override
public String toString() {
return "CachedSymbol [docURI=" + docURI + ", enhancedSymbol=" + enhancedSymbol + "]";
return "CachedSymbol [docURI=" + getDocURI() + ", enhancedSymbol=" + enhancedSymbol + "]";
}
}

View File

@@ -40,7 +40,7 @@ public class RestrictedDefaultSymbolProvider extends AbstractSymbolProvider {
if (!isCombinedWithAnnotation(node, Annotations.BEAN)) {
try {
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(DefaultSymbolProvider.provideDefaultSymbol(node, doc), null);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, null));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
} catch (Exception e) {
log.warn(e.getMessage());
}

View File

@@ -170,7 +170,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
IndexCacheKey cacheKey = getCacheKey(project);
CachedSymbol[] symbols = this.cache.retrieveSymbols(cacheKey, filesStr);
CachedSymbol[] symbols = this.cache.retrieveSymbols(cacheKey, filesStr, CachedSymbol.class);
if (symbols == null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
@@ -178,7 +178,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
generatedSymbols.addAll(scanFile(file));
}
this.cache.store(cacheKey, filesStr, generatedSymbols, null);
this.cache.store(cacheKey, filesStr, generatedSymbols, null, CachedSymbol.class);
symbols = (CachedSymbol[]) generatedSymbols.toArray(new CachedSymbol[generatedSymbols.size()]);
}
@@ -188,8 +188,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
if (symbols != null) {
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = Arrays.stream(symbols).filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, enhancedSymbols, beans);
symbolHandler.addSymbols(project, enhancedSymbols, null);
}
long endTime = System.currentTimeMillis();
@@ -205,7 +204,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
long lastModified = Files.getLastModifiedTime(file).toMillis();
String docUri = file.toUri().toASCIIString();
for (EnhancedSymbolInformation s : computeSymbols(docUri, content)) {
builder.add(new CachedSymbol(docUri, lastModified, s, null));
builder.add(new CachedSymbol(docUri, lastModified, s));
}
return builder.build();
} catch (IOException e) {
@@ -256,11 +255,10 @@ public class SpringFactoriesIndexer implements SpringIndexer {
IndexCacheKey cacheKey = getCacheKey(project);
String file = new File(new URI(docURI)).getAbsolutePath();
this.cache.update(cacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null);
this.cache.update(cacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null, CachedSymbol.class);
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = generatedSymbols.stream().filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, docURI, symbols, beans);
symbolHandler.addSymbols(project, docURI, symbols, null);
}
}
@@ -275,7 +273,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
updateFile(project, d, Files.readString(path));
} else {
String file = new File(new URI(d.getDocURI())).getAbsolutePath();
cache.removeFile(key, file);
cache.removeFile(key, file, CachedSymbol.class);
}
}
}
@@ -286,7 +284,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
IndexCacheKey key = getCacheKey(project);
for (String docUri : docURIs) {
String file = new File(new URI(docUri)).getAbsolutePath();
cache.removeFile(key, file);
cache.removeFile(key, file, CachedSymbol.class);
}
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2022 Pivotal, Inc.
* Copyright (c) 2017, 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
@@ -52,6 +52,7 @@ import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchies;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.java.IClasspath;
@@ -80,6 +81,9 @@ public class SpringIndexerJava implements SpringIndexer {
// we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found
private static final String GENERATION = "GEN-3";
private static final String SYMBOL_KEY = "symbols";
private static final String BEANS_KEY = "beans";
private final SymbolHandler symbolHandler;
private final AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
private final IndexCache cache;
@@ -126,17 +130,24 @@ public class SpringIndexerJava implements SpringIndexer {
@Override
public void removeProject(IJavaProject project) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
this.cache.remove(cacheKey);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
this.cache.remove(symbolsCacheKey);
this.cache.remove(beansCacheKey);
}
@Override
public void updateFile(IJavaProject project, DocumentDescriptor updatedDoc, String content) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
if (updatedDoc != null && shouldProcessDocument(project, updatedDoc.getDocURI())
&& isCacheOutdated(cacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())) {
this.symbolHandler.removeSymbols(project, updatedDoc.getDocURI());
scanFile(project, updatedDoc, content);
IndexCacheKey symbolCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
if (updatedDoc != null && shouldProcessDocument(project, updatedDoc.getDocURI())) {
if (isCacheOutdated(symbolCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())
|| isCacheOutdated(beansCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())) {
this.symbolHandler.removeSymbols(project, updatedDoc.getDocURI());
scanFile(project, updatedDoc, content);
}
}
}
@@ -155,18 +166,23 @@ public class SpringIndexerJava implements SpringIndexer {
@Override
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
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(cacheKey, file);
this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedSymbol.class);
}
}
private DocumentDescriptor[] filterDocuments(IJavaProject project, DocumentDescriptor[] updatedDocs) {
IndexCacheKey cacheKey = getCacheKey(project);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
return Arrays.stream(updatedDocs).filter(doc -> shouldProcessDocument(project, doc.getDocURI()))
.filter(doc -> isCacheOutdated(cacheKey, doc.getDocURI(), doc.getLastModified())).toArray(DocumentDescriptor[]::new);
.filter(doc -> isCacheOutdated(symbolsCacheKey, doc.getDocURI(), doc.getLastModified())
|| isCacheOutdated(beansCacheKey, doc.getDocURI(), doc.getLastModified())).toArray(DocumentDescriptor[]::new);
}
private boolean shouldProcessDocument(IJavaProject project, String docURI) {
@@ -218,19 +234,25 @@ public class SpringIndexerJava implements SpringIndexer {
if (cu != null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
AtomicReference<TextDocument> docRef = new AtomicReference<>();
String file = UriUtil.toFileString(docURI);
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
lastModified, docRef, content, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>());
lastModified, docRef, content, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
IndexCacheKey cacheKey = getCacheKey(project);
this.cache.update(cacheKey, file, lastModified, generatedSymbols, context.getDependencies());
IndexCacheKey symbolCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
this.cache.update(symbolCacheKey, file, lastModified, generatedSymbols, context.getDependencies(), CachedSymbol.class);
this.cache.update(beansCacheKey, file, lastModified, generatedBeans, context.getDependencies(), CachedBean.class);
// dependencyTracker.dump();
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = generatedSymbols.stream().filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, docURI, symbols, beans);
Set<String> scannedFiles = new HashSet<>();
@@ -253,10 +275,12 @@ public class SpringIndexerJava implements SpringIndexer {
if (cu != null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
AtomicReference<TextDocument> docRef = new AtomicReference<>();
String file = UriUtil.toFileString(docURI);
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
0, docRef, content, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>());
0, docRef, content, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
@@ -289,6 +313,8 @@ public class SpringIndexerJava implements SpringIndexer {
}
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
Multimap<String, String> dependencies = MultimapBuilder.hashKeys().hashSetValues().build();
FileASTRequestor requestor = new FileASTRequestor() {
@@ -303,7 +329,7 @@ public class SpringIndexerJava implements SpringIndexer {
AtomicReference<TextDocument> docRef = new AtomicReference<>();
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
lastModified, docRef, null, generatedSymbols, SCAN_PASS.ONE, new ArrayList<>());
lastModified, docRef, null, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
@@ -317,11 +343,14 @@ public class SpringIndexerJava implements SpringIndexer {
parser.createASTs(javaFiles, null, new String[0], requestor, null);
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = generatedSymbols.stream().filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, symbols, beans);
IndexCacheKey cacheKey = getCacheKey(project);
this.cache.update(cacheKey, javaFiles, lastModified, generatedSymbols, dependencies);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
this.cache.update(symbolsCacheKey, javaFiles, lastModified, generatedSymbols, dependencies, CachedSymbol.class);
this.cache.update(beansCacheKey, javaFiles, lastModified, generatedBeans, dependencies, CachedBean.class);
return scannedTypes;
}
@@ -358,45 +387,55 @@ public class SpringIndexerJava implements SpringIndexer {
}
private void scanFiles(IJavaProject project, String[] javaFiles) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
Pair<CachedSymbol[], Multimap<String, String>> cached = this.cache.retrieve(cacheKey, javaFiles);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
Pair<CachedSymbol[], Multimap<String, String>> cachedSymbols = this.cache.retrieve(symbolsCacheKey, javaFiles, CachedSymbol.class);
Pair<CachedBean[], Multimap<String, String>> cachedBeans = this.cache.retrieve(beansCacheKey, javaFiles, CachedBean.class);
CachedSymbol[] symbols;
if (cached == null) {
CachedBean[] beans;
if (cachedSymbols == null || cachedBeans == null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
log.info("scan java files, AST parse, pass 1 for files: {}", javaFiles.length);
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, SCAN_PASS.ONE);
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, generatedBeans, SCAN_PASS.ONE);
if (pass2Files.length > 0) {
log.info("scan java files, AST parse, pass 2 for files: {}", javaFiles.length);
scanFiles(project, pass2Files, generatedSymbols, SCAN_PASS.TWO);
scanFiles(project, pass2Files, generatedSymbols, generatedBeans, SCAN_PASS.TWO);
}
log.info("scan java files done, number of symbols created: " + generatedSymbols.size());
this.cache.store(cacheKey, javaFiles, generatedSymbols, dependencyTracker.getAllDependencies());
this.cache.store(symbolsCacheKey, javaFiles, generatedSymbols, dependencyTracker.getAllDependencies(), CachedSymbol.class);
this.cache.store(beansCacheKey, javaFiles, generatedBeans, dependencyTracker.getAllDependencies(), CachedBean.class);
// dependencyTracker.dump();
symbols = (CachedSymbol[]) generatedSymbols.toArray(new CachedSymbol[generatedSymbols.size()]);
beans = (CachedBean[]) generatedBeans.toArray(new CachedBean[generatedBeans.size()]);
}
else {
symbols = cached.getLeft();
symbols = cachedSymbols.getLeft();
beans = cachedBeans.getLeft();
log.info("scan java files used cached data: {} - no. of cached symbols retrieved: {}", project.getElementName(), symbols.length);
this.dependencyTracker.restore(cached.getRight());
log.info("scan java files restored cached dependency data: {} - no. of cached dependencies: {}", cached.getRight().size());
this.dependencyTracker.restore(cachedSymbols.getRight());
log.info("scan java files restored cached dependency data: {} - no. of cached dependencies: {}", cachedSymbols.getRight().size());
}
if (symbols != null) {
if (symbols != null && beans != null) {
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = Arrays.stream(symbols).filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, enhancedSymbols, beans);
Bean[] allBeans = Arrays.stream(beans).filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, enhancedSymbols, allBeans);
}
}
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, SCAN_PASS pass)
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans, SCAN_PASS pass)
throws Exception {
ASTParser parser = createParser(project, SCAN_PASS.ONE.equals(pass));
List<String> nextPassFiles = new ArrayList<>();
@@ -410,7 +449,7 @@ public class SpringIndexerJava implements SpringIndexer {
AtomicReference<TextDocument> docRef = new AtomicReference<>();
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
lastModified, docRef, null, generatedSymbols, pass, nextPassFiles);
lastModified, docRef, null, generatedSymbols, generatedBeans, pass, nextPassFiles);
scanAST(context);
}
@@ -523,7 +562,7 @@ public class SpringIndexerJava implements SpringIndexer {
WorkspaceSymbol symbol = provideDefaultSymbol(node, context);
if (symbol != null) {
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, null);
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol, null));
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
}
}
}
@@ -608,7 +647,7 @@ public class SpringIndexerJava implements SpringIndexer {
.toArray(String[]::new);
}
private IndexCacheKey getCacheKey(IJavaProject project) {
private IndexCacheKey getCacheKey(IJavaProject project, String elementType) {
IClasspath classpath = project.getClasspath();
Stream<File> classpathEntries = IClasspathUtil.getAllBinaryRoots(classpath).stream();
@@ -617,7 +656,7 @@ public class SpringIndexerJava implements SpringIndexer {
.map(file -> file.getAbsolutePath() + "#" + file.lastModified())
.collect(Collectors.joining(","));
return new IndexCacheKey(project.getElementName() + "-java-", DigestUtils.md5Hex(GENERATION + "-" + classpathIdentifier).toUpperCase());
return new IndexCacheKey(project.getElementName() + "-java-" + elementType + "-", DigestUtils.md5Hex(GENERATION + "-" + classpathIdentifier).toUpperCase());
}
public void setScanTestJavaSources(boolean scanTestJavaSources) {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2017, 2020 Pivotal, Inc.
* Copyright (c) 2017, 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
@@ -17,8 +17,10 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJava.SCAN_PASS;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
/**
@@ -34,6 +36,7 @@ public class SpringIndexerJavaContext {
private final AtomicReference<TextDocument> docRef;
private final String content;
private final List<CachedSymbol> generatedSymbols;
private final List<CachedBean> beans;
private final SCAN_PASS pass;
private final List<String> nextPassFiles;
@@ -48,7 +51,8 @@ public class SpringIndexerJavaContext {
long lastModified,
AtomicReference<TextDocument> docRef,
String content,
List<CachedSymbol> generatedSymbols,
List<CachedSymbol> generatedSymbols,
List<CachedBean> beans,
SCAN_PASS pass,
List<String> nextPassFiles
) {
@@ -61,6 +65,7 @@ public class SpringIndexerJavaContext {
this.docRef = docRef;
this.content = content;
this.generatedSymbols = generatedSymbols;
this.beans = beans;
this.pass = pass;
this.nextPassFiles = nextPassFiles;
}
@@ -96,6 +101,10 @@ public class SpringIndexerJavaContext {
public List<CachedSymbol> getGeneratedSymbols() {
return generatedSymbols;
}
public List<CachedBean> getBeans() {
return beans;
}
public SCAN_PASS getPass() {
return pass;

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2019, 2022 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
@@ -33,6 +33,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
@@ -48,6 +49,9 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class SpringIndexerXML implements SpringIndexer {
private static final Logger log = LoggerFactory.getLogger(SpringIndexerJava.class);
private static final String SYMBOL_KEY = "symbols";
private static final String BEANS_KEY = "beans";
private final SymbolHandler symbolHandler;
private final Map<String, SpringIndexerXMLNamespaceHandler> namespaceHandler;
@@ -106,28 +110,34 @@ public class SpringIndexerXML implements SpringIndexer {
log.info("scan xml files for symbols for project: " + project.getElementName() + " - no. of files: " + files.length);
IndexCacheKey cacheKey = getCacheKey(project);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
CachedSymbol[] symbols = this.cache.retrieveSymbols(cacheKey, files);
if (symbols == null) {
CachedSymbol[] symbols = this.cache.retrieveSymbols(symbolsCacheKey, files, CachedSymbol.class);
CachedBean[] beans = this.cache.retrieveSymbols(beansCacheKey, files, CachedBean.class);
if (symbols == null || beans == null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
for (String file : files) {
scanFile(project, file, generatedSymbols);
scanFile(project, file, generatedSymbols, generatedBeans);
}
this.cache.store(cacheKey, files, generatedSymbols, null);
this.cache.store(symbolsCacheKey, files, generatedSymbols, null, CachedSymbol.class);
this.cache.store(beansCacheKey, files, generatedBeans, null, CachedBean.class);
symbols = (CachedSymbol[]) generatedSymbols.toArray(new CachedSymbol[generatedSymbols.size()]);
beans = (CachedBean[]) generatedBeans.toArray(new CachedBean[generatedBeans.size()]);
}
else {
log.info("scan xml files used cached data: " + project.getElementName() + " - no. of cached symbols retrieved: " + symbols.length);
}
if (symbols != null) {
if (symbols != null && beans != null) {
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = Arrays.stream(symbols).filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, enhancedSymbols, beans);
Bean[] allBeans = Arrays.stream(beans).filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, enhancedSymbols, allBeans);
}
long endTime = System.currentTimeMillis();
@@ -137,8 +147,11 @@ public class SpringIndexerXML implements SpringIndexer {
@Override
public void removeProject(IJavaProject project) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
this.cache.remove(cacheKey);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
this.cache.remove(symbolsCacheKey);
this.cache.remove(beansCacheKey);
}
@Override
@@ -147,16 +160,21 @@ public class SpringIndexerXML implements SpringIndexer {
this.symbolHandler.removeSymbols(project, updatedDoc.getDocURI());
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
String docURI = updatedDoc.getDocURI();
scanFile(project, content, docURI, updatedDoc.getLastModified(), generatedSymbols);
scanFile(project, content, docURI, updatedDoc.getLastModified(), generatedSymbols, generatedBeans);
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey cacheKey = getCacheKey(project);
String file = new File(new URI(docURI)).getAbsolutePath();
this.cache.update(cacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null);
this.cache.update(symbolsCacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null, CachedSymbol.class);
this.cache.update(beansCacheKey, file, updatedDoc.getLastModified(), generatedBeans, null, CachedBean.class);
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = generatedSymbols.stream().filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, docURI, symbols, beans);
}
@@ -172,29 +190,36 @@ public class SpringIndexerXML implements SpringIndexer {
String content = new String(Files.readAllBytes(path));
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
scanFile(project, content, docURI, updatedDoc.getLastModified(), generatedSymbols);
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
scanFile(project, content, docURI, updatedDoc.getLastModified(), generatedSymbols, generatedBeans);
IndexCacheKey cacheKey = getCacheKey(project);
IndexCacheKey symbolCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
String file = new File(new URI(docURI)).getAbsolutePath();
this.cache.update(cacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null);
this.cache.update(symbolCacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null, CachedSymbol.class);
this.cache.update(beansCacheKey, file, updatedDoc.getLastModified(), generatedBeans, null, CachedBean.class);
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
Bean[] beans = generatedSymbols.stream().filter(cachedSymbol -> cachedSymbol.getBean() != null).map(cachedSymbol -> cachedSymbol.getBean()).toArray(Bean[]::new);
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
symbolHandler.addSymbols(project, docURI, symbols, beans);
}
}
@Override
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
IndexCacheKey cacheKey = getCacheKey(project);
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(cacheKey, file);
this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
}
}
private void scanFile(IJavaProject project, String fileName, List<CachedSymbol> generatedSymbols) {
private void scanFile(IJavaProject project, String fileName, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) {
log.debug("starting to parse XML file for Spring symbol indexing: {}", fileName);
try {
@@ -204,29 +229,32 @@ public class SpringIndexerXML implements SpringIndexer {
String docURI = UriUtil.toUri(file).toASCIIString();
String fileContent = FileUtils.readFileToString(file);
scanFile(project, fileContent, docURI, lastModified, generatedSymbols);
scanFile(project, fileContent, docURI, lastModified, generatedSymbols, generatedBeans);
}
catch (Exception e) {
log.error("error parsing XML file: ", e);
}
}
private void scanFile(IJavaProject project, String fileContent, String docURI, long lastModified, List<CachedSymbol> generatedSymbols) throws Exception {
private void scanFile(IJavaProject project, String fileContent, String docURI, long lastModified, List<CachedSymbol> generatedSymbols,
List<CachedBean> generatedBeans) throws Exception {
DOMParser parser = DOMParser.getInstance();
DOMDocument document = parser.parse(fileContent, "", null);
AtomicReference<TextDocument> docRef = new AtomicReference<>();
scanNode(document, project, docURI, lastModified, docRef, fileContent, generatedSymbols);
scanNode(document, project, docURI, lastModified, docRef, fileContent, generatedSymbols, generatedBeans);
}
private void scanNode(DOMNode node, IJavaProject project, String docURI, long lastModified, AtomicReference<TextDocument> docRef, String content, List<CachedSymbol> generatedSymbols) throws Exception {
private void scanNode(DOMNode node, IJavaProject project, String docURI, long lastModified, AtomicReference<TextDocument> docRef, String content,
List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) throws Exception {
String namespaceURI = node.getNamespaceURI();
if (namespaceURI != null && this.namespaceHandler.containsKey(namespaceURI)) {
SpringIndexerXMLNamespaceHandler namespaceHandler = this.namespaceHandler.get(namespaceURI);
TextDocument document = DocumentUtils.getTempTextDocument(docURI, docRef, content);
namespaceHandler.processNode(node, project, docURI, lastModified, document, generatedSymbols);
namespaceHandler.processNode(node, project, docURI, lastModified, document, generatedSymbols, generatedBeans);
}
@@ -240,7 +268,7 @@ public class SpringIndexerXML implements SpringIndexer {
List<DOMNode> children = node.getChildren();
for (DOMNode child : children) {
scanNode(child, project, docURI, lastModified, docRef, content, generatedSymbols);
scanNode(child, project, docURI, lastModified, docRef, content, generatedSymbols, generatedBeans);
}
@@ -269,7 +297,7 @@ public class SpringIndexerXML implements SpringIndexer {
return xmlFiles;
}
private IndexCacheKey getCacheKey(IJavaProject project) {
private IndexCacheKey getCacheKey(IJavaProject project, String elementType) {
IClasspath classpath = project.getClasspath();
Stream<File> classpathEntries = IClasspathUtil.getAllBinaryRoots(classpath).stream();
@@ -278,7 +306,7 @@ public class SpringIndexerXML implements SpringIndexer {
.map(file -> file.getAbsolutePath() + "#" + file.lastModified())
.collect(Collectors.joining(","));
return new IndexCacheKey(project.getElementName() + "-xml-", DigestUtils.md5Hex(classpathIdentifier).toUpperCase());
return new IndexCacheKey(project.getElementName() + "-xml-" + elementType + "-", DigestUtils.md5Hex(classpathIdentifier).toUpperCase());
}
private void clearIndex() {
@@ -318,7 +346,9 @@ public class SpringIndexerXML implements SpringIndexer {
throws Exception {
if (content != null) {
List<CachedSymbol> generatedSymbols = new ArrayList<>();
scanFile(project, content, docURI, 0, generatedSymbols);
List<CachedBean> generatedBeans = new ArrayList<>();
scanFile(project, content, docURI, 0, generatedSymbols, generatedBeans);
return generatedSymbols.stream().map(s -> s.getEnhancedSymbol()).collect(Collectors.toList());
}
return Collections.emptyList();

View File

@@ -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
@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.boot.java.utils;
import java.util.List;
import org.eclipse.lemminx.dom.DOMNode;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -21,6 +22,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
*/
public interface SpringIndexerXMLNamespaceHandler {
void processNode(DOMNode node, IJavaProject project, String docURI, long lastModifiued, TextDocument document, List<CachedSymbol> generatedSymbols) throws Exception;
void processNode(DOMNode node, IJavaProject project, String docURI, long lastModifiued, TextDocument document,
List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) throws Exception;
}

View File

@@ -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
@@ -22,6 +22,7 @@ import org.eclipse.lsp4j.WorkspaceSymbol;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.ide.vscode.boot.java.beans.BeanUtils;
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.commons.java.IJavaProject;
@@ -34,14 +35,16 @@ import org.springframework.lang.NonNull;
public class SpringIndexerXMLNamespaceHandlerBeans implements SpringIndexerXMLNamespaceHandler {
@Override
public void processNode(DOMNode node, IJavaProject project, String docURI, long lastModified, TextDocument document, List<CachedSymbol> generatedSymbols) throws Exception {
public void processNode(DOMNode node, IJavaProject project, String docURI, long lastModified, TextDocument document,
List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) throws Exception {
String localName = node.getLocalName();
if (localName != null && "bean".equals(localName)) {
createBeanSymbol(node, project, docURI, lastModified, document, generatedSymbols);
createBeanSymbol(node, project, docURI, lastModified, document, generatedSymbols, generatedBeans);
}
}
private void createBeanSymbol(DOMNode node, IJavaProject project, String docURI, long lastModified, TextDocument document, List<CachedSymbol> generatedSymbols) throws Exception {
private void createBeanSymbol(DOMNode node, IJavaProject project, String docURI, long lastModified, TextDocument document,
List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans) throws Exception {
String beanID = null;
int symbolStart = 0;
int symbolEnd = 0;
@@ -94,8 +97,10 @@ public class SpringIndexerXMLNamespaceHandlerBeans implements SpringIndexerXMLNa
EnhancedSymbolInformation fullSymbol = new EnhancedSymbolInformation(symbol, addon);
CachedSymbol cachedSymbol = new CachedSymbol(docURI, lastModified, fullSymbol, null);
CachedSymbol cachedSymbol = new CachedSymbol(docURI, lastModified, fullSymbol);
generatedSymbols.add(cachedSymbol);
// TODO: bean index
}
}

View File

@@ -36,6 +36,7 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheOnDisc;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
@@ -67,7 +68,7 @@ public class IndexCacheOnDiscTest {
@Test
void testEmptyCache() throws Exception {
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("something", "0"), new String[0]);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("something", "0"), new String[0], CachedSymbol.class);
assertNull(result);
}
@@ -87,15 +88,15 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols = new ArrayList<>();
WorkspaceSymbol symbol = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location("docURI", new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, null);
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol, null));
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, ImmutableMultimap.of(
file1.toString(), "file1dep1",
file2.toString(), "file2dep1",
file2.toString(), "file2dep2"
));
), CachedSymbol.class);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
CachedSymbol[] cachedSymbols = result.getLeft();
assertNotNull(cachedSymbols);
@@ -113,8 +114,6 @@ public class IndexCacheOnDiscTest {
assertEquals(timeFile1.toMillis(), cache.getModificationTimestamp(new IndexCacheKey("somekey", "1"), file1.toString()));
assertEquals(0, cache.getModificationTimestamp(new IndexCacheKey("somekey", "1"), "random-non-existing-file"));
assertNull(cachedSymbols[0].getBean());
}
@Test
@@ -133,11 +132,11 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols = new ArrayList<>();
WorkspaceSymbol symbol = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location("docURI", new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, null);
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol, null));
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null, CachedSymbol.class);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("otherkey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("otherkey", "1"), files, CachedSymbol.class);
assertNull(result);
}
@@ -157,16 +156,16 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols = new ArrayList<>();
WorkspaceSymbol symbol = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location("docURI", new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, null);
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol, null));
generatedSymbols.add(new CachedSymbol("", timeFile1.toMillis(), enhancedSymbol));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, ImmutableMultimap.of(
file1.toString(), "file1dep",
file2.toString(), "file2dep"
));
), CachedSymbol.class);
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 1000));
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNull(result);
}
@@ -181,10 +180,10 @@ public class IndexCacheOnDiscTest {
Files.createFile(file3);
String[] files = {file1.toString(), file2.toString()};
cache.store(new IndexCacheKey("somekey", "1"), files, new ArrayList<>(), null);
cache.store(new IndexCacheKey("somekey", "1"), files, new ArrayList<>(), null, CachedSymbol.class);
String[] moreFiles = {file1.toString(), file2.toString(), file3.toString()};
assertNull(cache.retrieve(new IndexCacheKey("somekey", "1"), moreFiles));
assertNull(cache.retrieve(new IndexCacheKey("somekey", "1"), moreFiles, CachedSymbol.class));
}
@Test
@@ -198,20 +197,20 @@ public class IndexCacheOnDiscTest {
Files.createFile(file3);
String[] files = {file1.toString(), file2.toString(), file3.toString()};
cache.store(new IndexCacheKey("somekey", "1"), files, new ArrayList<>(), null);
cache.store(new IndexCacheKey("somekey", "1"), files, new ArrayList<>(), null, CachedSymbol.class);
String[] fewerFiles = {file1.toString(), file2.toString()};
assertNull(cache.retrieve(new IndexCacheKey("somekey", "1"), fewerFiles));
assertNull(cache.retrieve(new IndexCacheKey("somekey", "1"), fewerFiles, CachedSymbol.class));
}
@Test
void testDeleteOldCacheFileIfNewOneIsStored() throws Exception {
IndexCacheKey key1 = new IndexCacheKey("somekey", "1");
cache.store(key1, new String[0], new ArrayList<>(), null);
cache.store(key1, new String[0], new ArrayList<>(), null, CachedSymbol.class);
assertTrue(Files.exists(tempDir.resolve(Paths.get(key1.toString() + ".json"))));
IndexCacheKey key2 = new IndexCacheKey("somekey", "2");
cache.store(key2, new String[0], new ArrayList<>(), null);
cache.store(key2, new String[0], new ArrayList<>(), null, CachedSymbol.class);
assertTrue(Files.exists(tempDir.resolve(Paths.get(key2.toString() + ".json"))));
assertFalse(Files.exists(tempDir.resolve(Paths.get(key1.toString() + ".json"))));
}
@@ -231,11 +230,11 @@ public class IndexCacheOnDiscTest {
WebfluxElementsInformation addon = new WebfluxElementsInformation(new Range(new Position(4, 4), new Position(5, 5)), new Range(new Position(6, 6), new Position(7, 7)));
EnhancedSymbolInformation enhancedSymbol = new EnhancedSymbolInformation(symbol, new SymbolAddOnInformation[]{addon});
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol, null));
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(1, cachedSymbols.length);
@@ -268,9 +267,9 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols1 = new ArrayList<>();
WorkspaceSymbol symbol1 = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location("docURI", new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol1 = new EnhancedSymbolInformation(symbol1, null);
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1, null));
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null, CachedSymbol.class);
List<CachedSymbol> generatedSymbols2 = new ArrayList<>();
symbol1 = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location(doc1URI, new Range(new Position(3, 10), new Position(3, 20)))));
@@ -279,13 +278,13 @@ public class IndexCacheOnDiscTest {
WorkspaceSymbol symbol2 = new WorkspaceSymbol("symbol2", SymbolKind.Interface, Either.forLeft(new Location(doc1URI, new Range(new Position(5, 5), new Position(5, 10)))));
EnhancedSymbolInformation enhancedSymbol2 = new EnhancedSymbolInformation(symbol2, null);
generatedSymbols2.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, enhancedSymbol1, null));
generatedSymbols2.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, enhancedSymbol2, null));
generatedSymbols2.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, enhancedSymbol1));
generatedSymbols2.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, enhancedSymbol2));
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 2000));
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, null);
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files);
AbstractIndexCacheable[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(2, cachedSymbols.length);
@@ -317,18 +316,18 @@ public class IndexCacheOnDiscTest {
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);
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1, null));
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
WorkspaceSymbol symbol2 = new WorkspaceSymbol("symbol2", SymbolKind.Field, Either.forLeft(new Location(doc2URI, new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol2 = new EnhancedSymbolInformation(symbol2, null);
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2, null));
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2));
WorkspaceSymbol symbol3 = new WorkspaceSymbol("symbol3", SymbolKind.Field, Either.forLeft(new Location(doc3URI, new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol3 = new EnhancedSymbolInformation(symbol3, null);
generatedSymbols.add(new CachedSymbol(doc3URI, timeFile3.toMillis(), enhancedSymbol3, null));
generatedSymbols.add(new CachedSymbol(doc3URI, timeFile3.toMillis(), enhancedSymbol3));
// store original version of the symbols to the cache
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, null, CachedSymbol.class);
// create updated and new symbols
@@ -340,23 +339,23 @@ public class IndexCacheOnDiscTest {
WorkspaceSymbol newSymbol1 = new WorkspaceSymbol("symbol1-new", SymbolKind.Interface, Either.forLeft(new Location(doc1URI, new Range(new Position(5, 5), new Position(5, 10)))));
EnhancedSymbolInformation newEnhancedSymbol1 = new EnhancedSymbolInformation(newSymbol1, null);
updatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, updatedEnhancedSymbol1, null));
updatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, newEnhancedSymbol1, null));
updatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, updatedEnhancedSymbol1));
updatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis() + 2000, newEnhancedSymbol1));
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 2000));
WorkspaceSymbol updatedSymbol2 = new WorkspaceSymbol("symbol2-updated", SymbolKind.Field, Either.forLeft(new Location(doc2URI, new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation updatedEnhancedSymbol2 = new EnhancedSymbolInformation(updatedSymbol2, null);
updatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis() + 3000, updatedEnhancedSymbol2, null));
updatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis() + 3000, updatedEnhancedSymbol2));
assertTrue(file2.toFile().setLastModified(timeFile2.toMillis() + 3000));
String[] updatedFiles = new String[]{file1.toAbsolutePath().toString(), file2.toAbsolutePath().toString()};
long[] updatedModificationTimestamps = new long[]{timeFile1.toMillis() + 2000, timeFile2.toMillis() + 3000};
// update multiple files in the cache
cache.update(new IndexCacheKey("somekey", "1"), updatedFiles, updatedModificationTimestamps, updatedSymbols, null);
cache.update(new IndexCacheKey("somekey", "1"), updatedFiles, updatedModificationTimestamps, updatedSymbols, null, CachedSymbol.class);
// double check whether all changes got stored and retrieved correctly
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(4, cachedSymbols.length);
@@ -395,13 +394,13 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols = ImmutableList.of();
Multimap<String, String> dependencies = ImmutableMultimap.of(file1.toString(), "dep1");
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, dependencies);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, dependencies, CachedSymbol.class);
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 2000));
Set<String> dependencies2 = ImmutableSet.of("dep1", "dep2");
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols, dependencies2);
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols, dependencies2, CachedSymbol.class);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(result);
assertEquals(ImmutableSet.of("dep1", "dep2"), result.getRight().get(file1.toString()));
}
@@ -420,16 +419,16 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols1 = new ArrayList<>();
WorkspaceSymbol symbol1 = new WorkspaceSymbol("symbol1", SymbolKind.Field, Either.forLeft(new Location("docURI", new Range(new Position(3, 10), new Position(3, 20)))));
EnhancedSymbolInformation enhancedSymbol1 = new EnhancedSymbolInformation(symbol1, null);
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1, null));
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null, CachedSymbol.class);
List<CachedSymbol> generatedSymbols2 = new ArrayList<>();
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 2000));
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, null);
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files);
AbstractIndexCacheable[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(0, cachedSymbols.length);
}
@@ -450,15 +449,15 @@ public class IndexCacheOnDiscTest {
file1.toString(), "dep2"
);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, dependencies1);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, dependencies1, CachedSymbol.class);
List<CachedSymbol> generatedSymbols2 = new ArrayList<>();
assertTrue(file1.toFile().setLastModified(timeFile1.toMillis() + 2000));
Set<String> dependencies2 = ImmutableSet.of("dep2");
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, dependencies2);
cache.update(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), timeFile1.toMillis() + 2000, generatedSymbols2, dependencies2, CachedSymbol.class);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
assertNotNull(result);
assertEquals(ImmutableSet.of("dep2"), result.getRight().get(file1.toString()));
}
@@ -481,19 +480,19 @@ public class IndexCacheOnDiscTest {
List<CachedSymbol> generatedSymbols1 = 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);
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1, null));
generatedSymbols1.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, null, CachedSymbol.class);
List<CachedSymbol> generatedSymbols2 = new ArrayList<>();
WorkspaceSymbol symbol2 = new WorkspaceSymbol("symbol2", SymbolKind.Interface, Either.forLeft(new Location(doc2URI, new Range(new Position(5, 5), new Position(5, 10)))));
EnhancedSymbolInformation enhancedSymbol2 = new EnhancedSymbolInformation(symbol2, null);
generatedSymbols2.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2, null));
generatedSymbols2.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2));
cache.update(new IndexCacheKey("somekey", "1"), file2.toString(), timeFile2.toMillis(), generatedSymbols2, null);
cache.update(new IndexCacheKey("somekey", "1"), file2.toString(), timeFile2.toMillis(), generatedSymbols2, null, CachedSymbol.class);
CachedSymbol[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), new String[]{file1.toString(), file2.toString()});
AbstractIndexCacheable[] cachedSymbols = cache.retrieveSymbols(new IndexCacheKey("somekey", "1"), new String[]{file1.toString(), file2.toString()}, CachedSymbol.class);
assertNotNull(cachedSymbols);
assertEquals(2, cachedSymbols.length);
}
@@ -513,12 +512,12 @@ public class IndexCacheOnDiscTest {
Multimap<String, String> dependencies1 = ImmutableMultimap.of(
file1.toString(), "dep1"
);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, dependencies1);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols1, dependencies1, CachedSymbol.class);
Set<String> dependencies2 = ImmutableSet.of("dep2");
cache.update(new IndexCacheKey("somekey", "1"), file2.toString(), timeFile2.toMillis(), generatedSymbols1, dependencies2);
cache.update(new IndexCacheKey("somekey", "1"), file2.toString(), timeFile2.toMillis(), generatedSymbols1, dependencies2, CachedSymbol.class);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), new String[]{file1.toString(), file2.toString()});
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), new String[]{file1.toString(), file2.toString()}, CachedSymbol.class);
assertNotNull(result);
assertEquals(ImmutableSet.of("dep2"), result.getRight().get(file2.toString()));
assertEquals(ImmutableSet.of("dep1"), result.getRight().get(file1.toString()));
@@ -527,7 +526,7 @@ public class IndexCacheOnDiscTest {
@Test
void testProjectDeleted() throws Exception {
IndexCacheKey key1 = new IndexCacheKey("somekey", "1");
cache.store(key1, new String[0], new ArrayList<>(), null);
cache.store(key1, new String[0], new ArrayList<>(), null, CachedSymbol.class);
assertTrue(Files.exists(tempDir.resolve(Paths.get(key1.toString() + ".json"))));
cache.remove(key1);
@@ -557,18 +556,18 @@ public class IndexCacheOnDiscTest {
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);
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1, null));
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2, null));
generatedSymbols.add(new CachedSymbol(doc1URI, timeFile1.toMillis(), enhancedSymbol1));
generatedSymbols.add(new CachedSymbol(doc2URI, timeFile2.toMillis(), enhancedSymbol2));
Multimap<String, String> dependencies = ImmutableMultimap.of(
file1.toString(), "dep1",
file2.toString(), "dep2"
);
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, dependencies);
cache.removeFile(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString());
cache.store(new IndexCacheKey("somekey", "1"), files, generatedSymbols, dependencies, CachedSymbol.class);
cache.removeFile(new IndexCacheKey("somekey", "1"), file1.toAbsolutePath().toString(), CachedSymbol.class);
files = new String[]{file2.toAbsolutePath().toString()};
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files);
Pair<CachedSymbol[], Multimap<String, String>> result = cache.retrieve(new IndexCacheKey("somekey", "1"), files, CachedSymbol.class);
CachedSymbol[] cachedSymbols = result.getLeft();
assertNotNull(result);
assertEquals(1, cachedSymbols.length);

View File

@@ -25,7 +25,7 @@ import java.util.stream.Collectors;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.ide.vscode.boot.index.cache.IndexCache;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheKey;
import org.springframework.ide.vscode.boot.java.utils.CachedSymbol;
import org.springframework.ide.vscode.boot.index.cache.IndexCacheable;
import com.google.common.collect.Multimap;
@@ -41,7 +41,7 @@ public class IndexCacheTimestampsOnly implements IndexCache {
}
@Override
public void store(IndexCacheKey cacheKey, String[] files, List<CachedSymbol> generatedSymbols, Multimap<String,String> dependencies) {
public <T extends IndexCacheable> void store(IndexCacheKey cacheKey, String[] files, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type) {
SortedMap<String, Long> timestampedFiles = new TreeMap<>();
timestampedFiles = Arrays.stream(files)
@@ -58,18 +58,18 @@ public class IndexCacheTimestampsOnly implements IndexCache {
}
@Override
public Pair<CachedSymbol[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files) {
public <T extends IndexCacheable> Pair<T[], Multimap<String, String>> retrieve(IndexCacheKey cacheKey, String[] files, Class<T> type) {
return null;
}
@Override
public void update(IndexCacheKey cacheKey, String file, long lastModified, List<CachedSymbol> generatedSymbols, Set<String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String file, long lastModified, List<T> generatedSymbols, Set<String> dependencies, Class<T> type) {
Map<String, Long> timestampMap = timestampCache.get(cacheKey);
timestampMap.put(file, lastModified);
}
@Override
public void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<CachedSymbol> generatedSymbols, Multimap<String, String> dependencies) {
public <T extends IndexCacheable> void update(IndexCacheKey cacheKey, String[] files, long[] lastModified, List<T> generatedSymbols, Multimap<String, String> dependencies, Class<T> type) {
Map<String, Long> timestampMap = timestampCache.get(cacheKey);
for (int i = 0; i < files.length; i++) {
@@ -82,7 +82,7 @@ public class IndexCacheTimestampsOnly implements IndexCache {
}
@Override
public void removeFile(IndexCacheKey symbolCacheKey, String file) {
public <T extends IndexCacheable> void removeFile(IndexCacheKey symbolCacheKey, String file, Class<T> type) {
}
@Override