Search classes by qualified name only in sources to prevent recursion

This commit is contained in:
Nikolay Krasko
2014-02-06 20:50:13 +04:00
parent 064612f0f3
commit 2ef879ea3e
3 changed files with 83 additions and 41 deletions
@@ -32,15 +32,19 @@ import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.diagnostic.Logger
import org.jetbrains.jet.lang.resolve.java.structure.impl.JavaClassImpl
import com.google.common.base.Predicates
import org.jetbrains.jet.lang.descriptors.impl.PackageViewDescriptorImpl
import org.jetbrains.jet.lang.resolve.name.tail
import org.jetbrains.jet.lang.resolve.name.each
public class LazyResolveBasedCache() : JavaResolverCache {
private var resolveSession by Delegates.notNull<ResolveSession>()
private var traceBasedCache = TraceBasedJavaResolverCache()
class object {
private val LOG = Logger.getInstance(javaClass<TraceBasedJavaResolverCache>())
}
private var resolveSession by Delegates.notNull<ResolveSession>()
private val traceBasedCache = TraceBasedJavaResolverCache()
Inject
public fun setSession(resolveSession: ResolveSession) {
this.resolveSession = resolveSession
@@ -51,8 +55,11 @@ public class LazyResolveBasedCache() : JavaResolverCache {
val descriptor = traceBasedCache.getClassResolvedFromSource(fqName)
if (descriptor != null) return descriptor
val classes = ResolveSessionUtils.getClassDescriptorsByFqName(resolveSession, fqName)
return if (classes.isNotEmpty()) classes.first() else null
return resolveSession.findInPackageFragments(fqName) { packageFragmentDescriptor ->
ResolveSessionUtils.findByQualifiedName(
packageFragmentDescriptor.getMemberScope(),
fqName.tail(packageFragmentDescriptor.getFqName()))
}
}
override fun getClass(javaClass: JavaClass): ClassDescriptor? {
@@ -73,4 +80,24 @@ public class LazyResolveBasedCache() : JavaResolverCache {
override fun recordClass(javaClass: JavaClass, descriptor: ClassDescriptor) {
traceBasedCache.recordClass(javaClass, descriptor)
}
private fun <T: Any> ResolveSession.findInPackageFragments(fqName: FqName, find: (PackageFragmentDescriptor) -> T?): T? {
var result: T? = null
(if (fqName.isRoot()) fqName else fqName.parent()).each { (parentFqName: FqName) : Boolean ->
val packageDescriptor = resolveSession.getPackageFragment(parentFqName)
if (packageDescriptor == null) {
return@each false // Stop iteration
}
val findResult = find(packageDescriptor)
if (findResult != null) {
result = findResult
return@each false // Stop iteration
}
true // Continue search
}
return result
}
}
@@ -16,13 +16,12 @@
package org.jetbrains.jet.lang.resolve.lazy;
import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.Lists;
import com.intellij.util.containers.Predicate;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassifierDescriptor;
import org.jetbrains.jet.lang.descriptors.PackageViewDescriptor;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.psi.JetNamed;
import org.jetbrains.jet.lang.resolve.name.FqName;
import org.jetbrains.jet.lang.resolve.name.Name;
@@ -44,14 +43,16 @@ public class ResolveSessionUtils {
public static final Predicate<ClassDescriptor> NON_SINGLETON_FILTER = new Predicate<ClassDescriptor>() {
@Override
public boolean apply(ClassDescriptor descriptor) {
public boolean apply(@Nullable ClassDescriptor descriptor) {
assert descriptor != null;
return !descriptor.getKind().isSingleton();
}
};
public static final Predicate<ClassDescriptor> SINGLETON_FILTER = new Predicate<ClassDescriptor>() {
@Override
public boolean apply(ClassDescriptor descriptor) {
public boolean apply(@Nullable ClassDescriptor descriptor) {
assert descriptor != null;
return descriptor.getKind().isSingleton();
}
};
@@ -70,9 +71,7 @@ public class ResolveSessionUtils {
@NotNull FqName fqName,
@NotNull Predicate<ClassDescriptor> filter
) {
if (fqName.isRoot()) {
return Collections.emptyList();
}
if (fqName.isRoot()) return Collections.emptyList();
Collection<ClassDescriptor> classDescriptors = Lists.newArrayList();
@@ -81,8 +80,10 @@ public class ResolveSessionUtils {
PackageViewDescriptor packageDescriptor = analyzer.getModuleDescriptor().getPackage(packageFqName);
if (packageDescriptor != null) {
FqName classInPackagePath = NamePackage.tail(fqName, packageFqName);
Collection<ClassDescriptor> descriptors = getClassOrObjectDescriptorsByFqName(packageDescriptor, classInPackagePath, filter);
classDescriptors.addAll(descriptors);
ClassDescriptor classDescriptor = findByQualifiedName(packageDescriptor.getMemberScope(), classInPackagePath, filter);
if (classDescriptor != null) {
classDescriptors.add(classDescriptor);
}
}
if (packageFqName.isRoot()) {
@@ -96,42 +97,47 @@ public class ResolveSessionUtils {
return classDescriptors;
}
@NotNull
private static Collection<ClassDescriptor> getClassOrObjectDescriptorsByFqName(
@NotNull PackageViewDescriptor packageDescriptor,
@Nullable
public static ClassDescriptor findByQualifiedName(@NotNull JetScope packageScope, @NotNull FqName path) {
return findByQualifiedName(packageScope, path, Predicates.<ClassDescriptor>alwaysTrue());
}
@Nullable
private static ClassDescriptor findByQualifiedName(
@NotNull JetScope jetScope,
@NotNull FqName path,
@NotNull Predicate<ClassDescriptor> filter
) {
if (path.isRoot()) {
return Collections.emptyList();
}
if (path.isRoot()) return null;
Collection<JetScope> scopes = Arrays.asList(packageDescriptor.getMemberScope());
if (NamePackage.isOneSegmentFQN(path)) {
Name shortName = path.shortName();
ClassifierDescriptor classifier = jetScope.getClassifier(shortName);
if (classifier instanceof ClassDescriptor) {
ClassDescriptor resultDescriptor = (ClassDescriptor) classifier;
List<Name> names = path.pathSegments();
if (names.size() > 1) {
for (Name subName : path.pathSegments().subList(0, names.size() - 1)) {
Collection<JetScope> tempScopes = Lists.newArrayList();
for (JetScope scope : scopes) {
ClassifierDescriptor classifier = scope.getClassifier(subName);
if (classifier instanceof ClassDescriptor) {
tempScopes.add(((ClassDescriptor) classifier).getUnsubstitutedInnerClassesScope());
}
if (filter.apply(resultDescriptor)) {
return resultDescriptor;
}
scopes = tempScopes;
}
return null;
}
Name shortName = path.shortName();
Collection<ClassDescriptor> resultClassifierDescriptors = Lists.newArrayList();
for (JetScope scope : scopes) {
ClassifierDescriptor classifier = scope.getClassifier(shortName);
if (classifier instanceof ClassDescriptor && filter.apply((ClassDescriptor) classifier)) {
resultClassifierDescriptors.add((ClassDescriptor) classifier);
}
Name firstName = NamePackage.getFirstSegment(path);
// Search in internal class
ClassifierDescriptor classifier = jetScope.getClassifier(firstName);
if (classifier instanceof ClassDescriptor) {
return findByQualifiedName(
((ClassDescriptor) classifier).getUnsubstitutedInnerClassesScope(),
NamePackage.withoutFirstSegment(path),
filter);
}
return resultClassifierDescriptors;
// TODO: search in class object
return null;
}
@NotNull
@@ -112,6 +112,15 @@ public fun isValidJavaFqName(qualifiedName: String?): Boolean {
return state != State.AFTER_DOT
}
public fun FqName.getFirstSegment(): Name = this.pathSegments().first()
tailRecursive
public fun FqName.each(operation: (FqName) -> Boolean) {
if (operation(this) && !isRoot()) {
parent().each(operation)
}
}
private fun isSubpackageOf(subpackageNameStr: String, packageNameStr: String): Boolean {
return subpackageNameStr == packageNameStr ||
(subpackageNameStr.startsWith(packageNameStr) && subpackageNameStr[packageNameStr.length()] == '.')