Guard construction of imports index under common lock

This commit is contained in:
Nikolay Krasko
2013-07-27 01:30:29 +04:00
parent fbe1491ad4
commit 14247ea2ab
2 changed files with 55 additions and 42 deletions
@@ -17,29 +17,35 @@
package org.jetbrains.jet.lang.resolve.lazy; package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.collect.*; import com.google.common.collect.*;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetImportDirective; import org.jetbrains.jet.lang.psi.JetImportDirective;
import org.jetbrains.jet.lang.psi.JetPsiUtil; import org.jetbrains.jet.lang.psi.JetPsiUtil;
import org.jetbrains.jet.lang.resolve.ImportPath; import org.jetbrains.jet.lang.resolve.ImportPath;
import org.jetbrains.jet.lang.resolve.lazy.storage.NotNullLazyValue;
import org.jetbrains.jet.lang.resolve.lazy.storage.StorageManager;
import org.jetbrains.jet.lang.resolve.name.Name; import org.jetbrains.jet.lang.resolve.name.Name;
import java.util.*; import java.util.List;
import java.util.Set;
class ImportsProvider { class ImportsProvider {
private final List<JetImportDirective> importDirectives; private final List<JetImportDirective> importDirectives;
private final NotNullLazyValue<NameToImportsCache> importsCacheValue;
private ListMultimap<Name, JetImportDirective> nameToDirectives = null; public ImportsProvider(StorageManager storageManager, final List<JetImportDirective> importDirectives) {
private List<JetImportDirective> allUnderImports = null;
private boolean indexed;
public ImportsProvider(List<JetImportDirective> importDirectives) {
this.importDirectives = importDirectives; this.importDirectives = importDirectives;
this.importsCacheValue = storageManager.createLazyValue(new Computable<NameToImportsCache>() {
@Override
public NameToImportsCache compute() {
return NameToImportsCache.createIndex(importDirectives);
}
});
} }
@NotNull @NotNull
public List<JetImportDirective> getImports(@NotNull Name name) { public List<JetImportDirective> getImports(@NotNull Name name) {
createIndex(); return importsCacheValue.compute().getImports(name);
return nameToDirectives.containsKey(name) ? nameToDirectives.get(name) : allUnderImports;
} }
@NotNull @NotNull
@@ -47,11 +53,20 @@ class ImportsProvider {
return importDirectives; return importDirectives;
} }
private void createIndex() { private static class NameToImportsCache {
if (indexed) { private final ListMultimap<Name, JetImportDirective> nameToDirectives;
return; private final List<JetImportDirective> allUnderImports;
private NameToImportsCache(ListMultimap<Name, JetImportDirective> directives, List<JetImportDirective> imports) {
nameToDirectives = directives;
allUnderImports = imports;
} }
private List<JetImportDirective> getImports(@NotNull Name name) {
return nameToDirectives.containsKey(name) ? nameToDirectives.get(name) : allUnderImports;
}
private static NameToImportsCache createIndex(List<JetImportDirective> importDirectives) {
ImmutableListMultimap.Builder<Name, JetImportDirective> namesToRelativeImportsBuilder = ImmutableListMultimap.builder(); ImmutableListMultimap.Builder<Name, JetImportDirective> namesToRelativeImportsBuilder = ImmutableListMultimap.builder();
Set<Name> processedAliases = Sets.newHashSet(); Set<Name> processedAliases = Sets.newHashSet();
@@ -87,9 +102,7 @@ class ImportsProvider {
} }
} }
allUnderImports = ImmutableList.copyOf(processedAllUnderImports); return new NameToImportsCache(namesToRelativeImportsBuilder.build(), ImmutableList.copyOf(processedAllUnderImports));
nameToDirectives = namesToRelativeImportsBuilder.build(); }
indexed = true;
} }
} }
@@ -126,7 +126,7 @@ public class LazyImportScope implements JetScope {
) { ) {
this.resolveSession = resolveSession; this.resolveSession = resolveSession;
this.packageDescriptor = packageDescriptor; this.packageDescriptor = packageDescriptor;
this.importsProvider = new ImportsProvider(imports); this.importsProvider = new ImportsProvider(resolveSession.getStorageManager(), imports);
this.traceForImportResolve = traceForImportResolve; this.traceForImportResolve = traceForImportResolve;
this.debugName = debugName; this.debugName = debugName;