Guard construction of imports index under common lock
This commit is contained in:
@@ -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,49 +53,56 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
ImmutableListMultimap.Builder<Name, JetImportDirective> namesToRelativeImportsBuilder = ImmutableListMultimap.builder();
|
private List<JetImportDirective> getImports(@NotNull Name name) {
|
||||||
|
return nameToDirectives.containsKey(name) ? nameToDirectives.get(name) : allUnderImports;
|
||||||
|
}
|
||||||
|
|
||||||
Set<Name> processedAliases = Sets.newHashSet();
|
private static NameToImportsCache createIndex(List<JetImportDirective> importDirectives) {
|
||||||
List<JetImportDirective> processedAllUnderImports = Lists.newArrayList();
|
ImmutableListMultimap.Builder<Name, JetImportDirective> namesToRelativeImportsBuilder = ImmutableListMultimap.builder();
|
||||||
|
|
||||||
for (JetImportDirective anImport : importDirectives) {
|
Set<Name> processedAliases = Sets.newHashSet();
|
||||||
ImportPath path = JetPsiUtil.getImportPath(anImport);
|
List<JetImportDirective> processedAllUnderImports = Lists.newArrayList();
|
||||||
if (path == null) {
|
|
||||||
// Could be some parse errors
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path.isAllUnder()) {
|
for (JetImportDirective anImport : importDirectives) {
|
||||||
processedAllUnderImports.add(anImport);
|
ImportPath path = JetPsiUtil.getImportPath(anImport);
|
||||||
|
if (path == null) {
|
||||||
|
// Could be some parse errors
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path.isAllUnder()) {
|
||||||
|
processedAllUnderImports.add(anImport);
|
||||||
|
|
||||||
|
// All-Under import is relevant to all names found so far
|
||||||
|
for (Name aliasName : processedAliases) {
|
||||||
|
namesToRelativeImportsBuilder.put(aliasName, anImport);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Name aliasName = path.getImportedName();
|
||||||
|
assert aliasName != null;
|
||||||
|
|
||||||
|
if (!processedAliases.contains(aliasName)) {
|
||||||
|
processedAliases.add(aliasName);
|
||||||
|
|
||||||
|
// Add to relevant imports all all-under imports found by this moment
|
||||||
|
namesToRelativeImportsBuilder.putAll(aliasName, processedAllUnderImports);
|
||||||
|
}
|
||||||
|
|
||||||
// All-Under import is relevant to all names found so far
|
|
||||||
for (Name aliasName : processedAliases) {
|
|
||||||
namesToRelativeImportsBuilder.put(aliasName, anImport);
|
namesToRelativeImportsBuilder.put(aliasName, anImport);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
|
||||||
Name aliasName = path.getImportedName();
|
|
||||||
assert aliasName != null;
|
|
||||||
|
|
||||||
if (!processedAliases.contains(aliasName)) {
|
return new NameToImportsCache(namesToRelativeImportsBuilder.build(), ImmutableList.copyOf(processedAllUnderImports));
|
||||||
processedAliases.add(aliasName);
|
|
||||||
|
|
||||||
// Add to relevant imports all all-under imports found by this moment
|
|
||||||
namesToRelativeImportsBuilder.putAll(aliasName, processedAllUnderImports);
|
|
||||||
}
|
|
||||||
|
|
||||||
namesToRelativeImportsBuilder.put(aliasName, anImport);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
allUnderImports = 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;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user