Skip to content

Commit

Permalink
Declaration providers and resolve session are protected by a storage …
Browse files Browse the repository at this point in the history
…manager
  • Loading branch information
abreslav committed Jan 30, 2013
1 parent 222c237 commit c2822fd
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 108 deletions.
Expand Up @@ -37,6 +37,7 @@
import org.jetbrains.jet.lang.psi.JetPsiFactory;
import org.jetbrains.jet.lang.resolve.*;
import org.jetbrains.jet.lang.resolve.lazy.FileBasedDeclarationProviderFactory;
import org.jetbrains.jet.lang.resolve.lazy.LockBasedStorageManager;
import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
Expand Down Expand Up @@ -90,7 +91,8 @@ public ResolveSession getLazyResolveSession(@NotNull final Project fileProject,
final PsiClassFinder psiClassFinder = injector.getPsiClassFinder();

// TODO: Replace with stub declaration provider
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(files, new Predicate<FqName>() {
LockBasedStorageManager storageManager = new LockBasedStorageManager();
final FileBasedDeclarationProviderFactory declarationProviderFactory = new FileBasedDeclarationProviderFactory(storageManager, files, new Predicate<FqName>() {
@Override
public boolean apply(FqName fqName) {
return psiClassFinder.findPsiPackage(fqName) != null || new FqName("jet").equals(fqName);
Expand Down Expand Up @@ -136,7 +138,7 @@ public PlatformToKotlinClassMap getPlatformToKotlinClassMap() {

ModuleDescriptor lazyModule = new ModuleDescriptor(Name.special("<lazy module>"));

return new ResolveSession(fileProject, lazyModule, moduleConfiguration, declarationProviderFactory, javaResolverTrace);
return new ResolveSession(fileProject, storageManager, lazyModule, moduleConfiguration, declarationProviderFactory, javaResolverTrace);
}

public static AnalyzeExhaust analyzeOneFileWithJavaIntegrationAndCheckForErrors(
Expand Down
Expand Up @@ -20,6 +20,7 @@
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.Name;
Expand All @@ -30,71 +31,76 @@
import static org.jetbrains.jet.lang.resolve.lazy.ResolveSessionUtils.safeNameForLazyResolve;

public abstract class AbstractPsiBasedDeclarationProvider implements DeclarationProvider {
private final List<JetDeclaration> allDeclarations = Lists.newArrayList();
private final Multimap<Name, JetNamedFunction> functions = HashMultimap.create();
private final Multimap<Name, JetProperty> properties = HashMultimap.create();
private final Multimap<Name, JetClassOrObject> classesAndObjects = ArrayListMultimap.create(); // order matters here

private boolean indexCreated = false;
protected static class Index {
// This mutable state is only modified under inside the computable
private final List<JetDeclaration> allDeclarations = Lists.newArrayList();
private final Multimap<Name, JetNamedFunction> functions = HashMultimap.create();
private final Multimap<Name, JetProperty> properties = HashMultimap.create();
private final Multimap<Name, JetClassOrObject> classesAndObjects = ArrayListMultimap.create(); // order matters here

protected final void createIndex() {
if (indexCreated) return;
indexCreated = true;
public void putToIndex(@NotNull JetDeclaration declaration) {
if (declaration instanceof JetClassInitializer) {
return;
}
allDeclarations.add(declaration);
if (declaration instanceof JetNamedFunction) {
JetNamedFunction namedFunction = (JetNamedFunction) declaration;
functions.put(safeNameForLazyResolve(namedFunction), namedFunction);
}
else if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
properties.put(safeNameForLazyResolve(property), property);
}
else if (declaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
classesAndObjects.put(safeNameForLazyResolve(classOrObject.getNameAsName()), classOrObject);
}
else if (declaration instanceof JetParameter || declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) {
// Do nothing, just put it into allDeclarations is enough
}
else {
throw new IllegalArgumentException("Unknown declaration: " + declaration);
}
}

doCreateIndex();
}

protected abstract void doCreateIndex();
private final LazyValue<Index> index;

protected void putToIndex(JetDeclaration declaration) {
if (declaration instanceof JetClassInitializer) {
return;
}
allDeclarations.add(declaration);
if (declaration instanceof JetNamedFunction) {
JetNamedFunction namedFunction = (JetNamedFunction) declaration;
functions.put(safeNameForLazyResolve(namedFunction), namedFunction);
}
else if (declaration instanceof JetProperty) {
JetProperty property = (JetProperty) declaration;
properties.put(safeNameForLazyResolve(property), property);
}
else if (declaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) declaration;
classesAndObjects.put(safeNameForLazyResolve(classOrObject.getNameAsName()), classOrObject);
}
else if (declaration instanceof JetParameter || declaration instanceof JetTypedef || declaration instanceof JetMultiDeclaration) {
// Do nothing, just put it into allDeclarations is enough
}
else {
throw new IllegalArgumentException("Unknown declaration: " + declaration);
}
public AbstractPsiBasedDeclarationProvider(@NotNull StorageManager storageManager) {
index = storageManager.createLazyValue(new Computable<Index>() {
@Override
public Index compute() {
Index index = new Index();
doCreateIndex(index);
return index;
}
});
}

protected abstract void doCreateIndex(@NotNull Index index);

@Override
public List<JetDeclaration> getAllDeclarations() {
createIndex();
return allDeclarations;
return index.get().allDeclarations;
}

@NotNull
@Override
public List<JetNamedFunction> getFunctionDeclarations(@NotNull Name name) {
createIndex();
return Lists.newArrayList(functions.get(name));
return Lists.newArrayList(index.get().functions.get(name));
}

@NotNull
@Override
public List<JetProperty> getPropertyDeclarations(@NotNull Name name) {
createIndex();
return Lists.newArrayList(properties.get(name));
return Lists.newArrayList(index.get().properties.get(name));
}

@NotNull
@Override
public Collection<JetClassOrObject> getClassOrObjectDeclarations(@NotNull Name name) {
createIndex();
return classesAndObjects.get(name);
return index.get().classesAndObjects.get(name);
}
}
Expand Up @@ -18,72 +18,88 @@

import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.*;
import com.google.common.collect.Collections2;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.psi.JetNamespaceHeader;
import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
import org.jetbrains.jet.lang.resolve.name.FqName;

import java.util.Collection;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ConcurrentMap;

public class FileBasedDeclarationProviderFactory implements DeclarationProviderFactory {

private final Collection<JetFile> allFiles;

private final Multimap<FqName, JetFile> filesByPackage = HashMultimap.create();
private final Set<FqName> declaredPackages = Sets.newHashSet();
private final Map<FqName, PackageMemberDeclarationProvider> packageDeclarationProviders = Maps.newHashMap();
private static class Index {
private final Multimap<FqName, JetFile> filesByPackage = HashMultimap.create();
private final Set<FqName> declaredPackages = Sets.newHashSet();
}

private final Predicate<FqName> isPackageDeclaredExternally;

private boolean indexed = false;
private final StorageManager storageManager;
private final LazyValue<Index> index;

private final ConcurrentMap<FqName, PackageMemberDeclarationProvider> packageDeclarationProviders;

public FileBasedDeclarationProviderFactory(@NotNull Collection<JetFile> files) {
this(files, Predicates.<FqName>alwaysFalse());
public FileBasedDeclarationProviderFactory(@NotNull StorageManager storageManager, @NotNull Collection<JetFile> files) {
this(storageManager, files, Predicates.<FqName>alwaysFalse());
}

public FileBasedDeclarationProviderFactory(@NotNull Collection<JetFile> files, Predicate<FqName> isPackageDeclaredExternally) {
this.allFiles = files;
public FileBasedDeclarationProviderFactory(
@NotNull StorageManager storageManager,
@NotNull final Collection<JetFile> files,
@NotNull Predicate<FqName> isPackageDeclaredExternally
) {
this.storageManager = storageManager;
this.isPackageDeclaredExternally = isPackageDeclaredExternally;
this.index = storageManager.createLazyValue(new Computable<Index>() {
@Override
public Index compute() {
return computeFilesByPackage(files);
}
});
this.packageDeclarationProviders = storageManager.createConcurrentMap();
}

private void createIndex() {
if (indexed) return;
indexed = true;

for (JetFile file : allFiles) {
@NotNull
private static Index computeFilesByPackage(@NotNull Collection<JetFile> files) {
Index index = new Index();
for (JetFile file : files) {
JetNamespaceHeader header = file.getNamespaceHeader();
if (header == null) {
throw new IllegalArgumentException("Scripts are not supported");
}

FqName packageFqName = new FqName(header.getQualifiedName());
addMeAndParentPackages(packageFqName);
filesByPackage.put(packageFqName, file);
addMeAndParentPackages(index, packageFqName);
index.filesByPackage.put(packageFqName, file);
}
return index;
}

private void addMeAndParentPackages(@NotNull FqName name) {
declaredPackages.add(name);
private static void addMeAndParentPackages(@NotNull Index index, @NotNull FqName name) {
index.declaredPackages.add(name);
if (!name.isRoot()) {
addMeAndParentPackages(name.parent());
addMeAndParentPackages(index, name.parent());
}
}

/*package*/ boolean isPackageDeclaredExplicitly(@NotNull FqName packageFqName) {
createIndex();
return declaredPackages.contains(packageFqName);
return index.get().declaredPackages.contains(packageFqName);
}

/*package*/ boolean isPackageDeclared(@NotNull FqName packageFqName) {
return isPackageDeclaredExplicitly(packageFqName) || isPackageDeclaredExternally.apply(packageFqName);
}

/*package*/ Collection<FqName> getAllDeclaredSubPackagesOf(@NotNull final FqName parent) {
return Collections2.filter(declaredPackages, new Predicate<FqName>() {
return Collections2.filter(index.get().declaredPackages, new Predicate<FqName>() {
@Override
public boolean apply(FqName fqName) {
return !fqName.isRoot() && fqName.parent().equals(parent);
Expand All @@ -93,8 +109,6 @@ public boolean apply(FqName fqName) {

@Override
public PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@NotNull FqName packageFqName) {
createIndex();

PackageMemberDeclarationProvider declarationProvider = packageDeclarationProviders.get(packageFqName);
if (declarationProvider != null) {
return declarationProvider;
Expand All @@ -108,21 +122,18 @@ public PackageMemberDeclarationProvider getPackageMemberDeclarationProvider(@Not
}

FileBasedPackageMemberDeclarationProvider provider =
new FileBasedPackageMemberDeclarationProvider(packageFqName, this, filesByPackage.get(packageFqName));
packageDeclarationProviders.put(packageFqName, provider);
new FileBasedPackageMemberDeclarationProvider(storageManager, packageFqName, this, index.get().filesByPackage.get(packageFqName));

return provider;
return packageDeclarationProviders.putIfAbsent(packageFqName, provider);
}

@NotNull
@Override
public ClassMemberDeclarationProvider getClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classLikeInfo) {
createIndex();

if (!filesByPackage.containsKey(classLikeInfo.getContainingPackageFqName())) {
if (!index.get().filesByPackage.containsKey(classLikeInfo.getContainingPackageFqName())) {
throw new IllegalStateException("This factory doesn't know about this class: " + classLikeInfo);
}

return new PsiBasedClassMemberDeclarationProvider(classLikeInfo);
return new PsiBasedClassMemberDeclarationProvider(storageManager, classLikeInfo);
}
}
Expand Up @@ -16,6 +16,7 @@

package org.jetbrains.jet.lang.resolve.lazy;

import com.intellij.openapi.util.Computable;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.psi.*;
import org.jetbrains.jet.lang.resolve.name.FqName;
Expand All @@ -28,24 +29,32 @@ public class FileBasedPackageMemberDeclarationProvider extends AbstractPsiBasedD
private final FqName fqName;
private final FileBasedDeclarationProviderFactory factory;
private final Collection<JetFile> allFiles;
private Collection<FqName> allDeclaredPackages;
private final LazyValue<Collection<FqName>> allDeclaredPackages;


/*package*/ FileBasedPackageMemberDeclarationProvider(
@NotNull FqName fqName,
@NotNull FileBasedDeclarationProviderFactory factory,
@NotNull StorageManager storageManager,
@NotNull FqName _fqName,
@NotNull FileBasedDeclarationProviderFactory _factory,
@NotNull Collection<JetFile> allFiles
) {
this.fqName = fqName;
this.factory = factory;
super(storageManager);
this.fqName = _fqName;
this.factory = _factory;
this.allFiles = allFiles;
this.allDeclaredPackages = storageManager.createLazyValue(new Computable<Collection<FqName>>() {
@Override
public Collection<FqName> compute() {
return factory.getAllDeclaredSubPackagesOf(fqName);
}
});
}

@Override
protected void doCreateIndex() {
protected void doCreateIndex(@NotNull Index index) {
for (JetFile file : allFiles) {
for (JetDeclaration declaration : file.getDeclarations()) {
putToIndex(declaration);
index.putToIndex(declaration);
}
}
}
Expand All @@ -57,10 +66,7 @@ public boolean isPackageDeclared(@NotNull Name name) {

@Override
public Collection<FqName> getAllDeclaredPackages() {
if (allDeclaredPackages == null) {
allDeclaredPackages = factory.getAllDeclaredSubPackagesOf(fqName);
}
return allDeclaredPackages;
return allDeclaredPackages.get();
}

@Override
Expand Down
Expand Up @@ -24,7 +24,8 @@ public class PsiBasedClassMemberDeclarationProvider extends AbstractPsiBasedDecl

private final JetClassLikeInfo classInfo;

public PsiBasedClassMemberDeclarationProvider(@NotNull JetClassLikeInfo classInfo) {
public PsiBasedClassMemberDeclarationProvider(@NotNull StorageManager storageManager, @NotNull JetClassLikeInfo classInfo) {
super(storageManager);
this.classInfo = classInfo;
}

Expand All @@ -35,19 +36,19 @@ public JetClassLikeInfo getOwnerInfo() {
}

@Override
protected void doCreateIndex() {
protected void doCreateIndex(@NotNull Index index) {
for (JetDeclaration declaration : classInfo.getDeclarations()) {
if (declaration instanceof JetClassObject) {
// Do nothing, class object will be taken directly from the classInfo
}
else {
putToIndex(declaration);
index.putToIndex(declaration);
}
}

for (JetParameter parameter : classInfo.getPrimaryConstructorParameters()) {
if (parameter.getValOrVarNode() != null) {
putToIndex(parameter);
index.putToIndex(parameter);
}
}
}
Expand Down

0 comments on commit c2822fd

Please sign in to comment.