Restructure caches in JavaNamespaceResolver

This commit is contained in:
Pavel V. Talanov
2012-11-02 19:49:31 +04:00
parent 2eb017fa1e
commit 86e93e3c22
@@ -17,6 +17,7 @@
package org.jetbrains.jet.lang.resolve.java.resolver; package org.jetbrains.jet.lang.resolve.java.resolver;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.intellij.psi.PsiClass; import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiPackage; import com.intellij.psi.PsiPackage;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
@@ -38,13 +39,17 @@ import org.jetbrains.jet.lang.resolve.name.Name;
import javax.inject.Inject; import javax.inject.Inject;
import java.util.Collections; import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set;
public final class JavaNamespaceResolver { public final class JavaNamespaceResolver {
@NotNull @NotNull
public static final ModuleDescriptor FAKE_ROOT_MODULE = new ModuleDescriptor(JavaDescriptorResolver.JAVA_ROOT); public static final ModuleDescriptor FAKE_ROOT_MODULE = new ModuleDescriptor(JavaDescriptorResolver.JAVA_ROOT);
@NotNull @NotNull
private final Map<FqName, ResolverNamespaceData> namespaceDescriptorCacheByFqn = Maps.newHashMap(); private final Map<FqName, JavaPackageScope> resolvedNamespaceCache = Maps.newHashMap();
@NotNull
private final Set<FqName> unresolvedCache = Sets.newHashSet();
private PsiClassFinder psiClassFinder; private PsiClassFinder psiClassFinder;
private BindingTrace trace; private BindingTrace trace;
private JavaSemanticServices javaSemanticServices; private JavaSemanticServices javaSemanticServices;
@@ -75,9 +80,12 @@ public final class JavaNamespaceResolver {
return searchRule.processFoundInKotlin(kotlinNamespaceDescriptor); return searchRule.processFoundInKotlin(kotlinNamespaceDescriptor);
} }
ResolverNamespaceData namespaceData = lookUpCache(qualifiedName); if (unresolvedCache.contains(qualifiedName)) {
if (namespaceData != null) { return null;
return namespaceData.getNamespaceDescriptor(); }
JavaPackageScope scope = resolvedNamespaceCache.get(qualifiedName);
if (scope != null) {
return (NamespaceDescriptor) scope.getContainingDeclaration();
} }
NamespaceDescriptorParent parentNs = resolveParentNamespace(qualifiedName); NamespaceDescriptorParent parentNs = resolveParentNamespace(qualifiedName);
@@ -103,10 +111,6 @@ public final class JavaNamespaceResolver {
return scopeData.getNamespaceDescriptor(); return scopeData.getNamespaceDescriptor();
} }
private ResolverNamespaceData lookUpCache(FqName qualifiedName) {
return namespaceDescriptorCacheByFqn.get(qualifiedName);
}
@Nullable @Nullable
public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) { public NamespaceDescriptor resolveNamespace(@NotNull FqName qualifiedName) {
return resolveNamespace(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN); return resolveNamespace(qualifiedName, DescriptorSearchRule.ERROR_IF_FOUND_IN_KOTLIN);
@@ -145,21 +149,26 @@ public final class JavaNamespaceResolver {
break lookingForPsi; break lookingForPsi;
} }
cache(fqName, ResolverNamespaceData.NEGATIVE); cache(fqName, null);
return null; return null;
} }
ResolverNamespaceData namespaceData = new ResolverNamespaceData(psiClass, psiPackage, fqName, ns); ResolverNamespaceData namespaceData = new ResolverNamespaceData(psiClass, psiPackage, fqName, ns);
namespaceData.setMemberScope(new JavaPackageScope(fqName, javaSemanticServices, namespaceData)); JavaPackageScope memberScope = new JavaPackageScope(fqName, javaSemanticServices, namespaceData);
namespaceData.setMemberScope(memberScope);
cache(fqName, namespaceData); cache(fqName, memberScope);
return namespaceData; return namespaceData;
} }
private void cache(@NotNull FqName fqName, @NotNull ResolverNamespaceData namespaceData) { private void cache(@NotNull FqName fqName, @Nullable JavaPackageScope packageScope) {
ResolverNamespaceData oldValue = namespaceDescriptorCacheByFqn.put(fqName, namespaceData); if (packageScope == null) {
unresolvedCache.add(fqName);
return;
}
JavaPackageScope oldValue = resolvedNamespaceCache.put(fqName, packageScope);
if (oldValue != null) { if (oldValue != null) {
throw new IllegalStateException("rewrite at " + fqName); throw new IllegalStateException("rewrite at " + fqName);
} }
@@ -168,19 +177,21 @@ public final class JavaNamespaceResolver {
@Nullable @Nullable
public JavaPackageScope getJavaPackageScopeForExistingNamespaceDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor) { public JavaPackageScope getJavaPackageScopeForExistingNamespaceDescriptor(@NotNull NamespaceDescriptor namespaceDescriptor) {
FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe(); FqName fqName = DescriptorUtils.getFQName(namespaceDescriptor).toSafe();
ResolverNamespaceData resolverNamespaceData = lookUpCache(fqName); if (unresolvedCache.contains(fqName)) {
if (resolverNamespaceData == null) {
resolverNamespaceData = createNamespaceResolverScopeData(fqName, namespaceDescriptor);
}
if (resolverNamespaceData == null) {
return null;
}
if (resolverNamespaceData == ResolverNamespaceData.NEGATIVE) {
throw new IllegalStateException( throw new IllegalStateException(
"This means that we are trying to create a Java package, but have a package with the same FQN defined in Kotlin: " + "This means that we are trying to create a Java package, but have a package with the same FQN defined in Kotlin: " +
fqName); fqName);
} }
JavaPackageScope scope = resolverNamespaceData.getMemberScope(); JavaPackageScope alreadyResolvedScope = resolvedNamespaceCache.get(fqName);
if (alreadyResolvedScope != null) {
return alreadyResolvedScope;
}
ResolverNamespaceData data;
data = createNamespaceResolverScopeData(fqName, namespaceDescriptor);
if (data == null) {
return null;
}
JavaPackageScope scope = data.getMemberScope();
if (scope == null) { if (scope == null) {
throw new IllegalStateException("fqn: " + fqName); throw new IllegalStateException("fqn: " + fqName);
} }