Track the top level declarations, note not usages

It'll be useful for more accurate tracking dependencies inside package.
This commit is contained in:
Zalim Bashorov
2015-08-18 18:17:29 +03:00
parent 673df1f085
commit 0ba18ca8cd
12 changed files with 74 additions and 38 deletions
@@ -205,6 +205,15 @@ public class JetNamedFunction extends JetTypeParameterListOwnerStub<KotlinFuncti
return !(parent instanceof JetFile || parent instanceof JetClassBody);
}
public boolean isTopLevel() {
KotlinFunctionStub stub = getStub();
if (stub != null) {
return stub.isTopLevel();
}
return getParent() instanceof JetFile;
}
@Override
public boolean shouldChangeModificationCount(PsiElement place) {
// Suppress Java check for out-of-block
@@ -25,6 +25,7 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.diagnostics.Errors
import org.jetbrains.kotlin.diagnostics.Errors.REDECLARATION
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.name.Name
@@ -94,7 +95,7 @@ public class DeclarationResolver(
for ((fqName, declarationsOrPackageDirectives) in topLevelFqNames.asMap()) {
if (fqName.isRoot()) continue
val descriptors = getTopLevelDescriptorsByFqName(topLevelDescriptorProvider, fqName)
val descriptors = getTopLevelDescriptorsByFqName(topLevelDescriptorProvider, fqName, NoLookupLocation.WHEN_CHECK_REDECLARATIONS)
if (descriptors.size() > 1) {
for (declarationOrPackageDirective in declarationsOrPackageDirectives) {
@@ -107,7 +108,7 @@ public class DeclarationResolver(
}
}
private fun getTopLevelDescriptorsByFqName(topLevelDescriptorProvider: TopLevelDescriptorProvider, fqName: FqName): Set<DeclarationDescriptor> {
private fun getTopLevelDescriptorsByFqName(topLevelDescriptorProvider: TopLevelDescriptorProvider, fqName: FqName, location: LookupLocation): Set<DeclarationDescriptor> {
val parentFqName = fqName.parent()
val descriptors = HashSet<DeclarationDescriptor>()
@@ -115,13 +116,13 @@ public class DeclarationResolver(
val parentFragment = topLevelDescriptorProvider.getPackageFragment(parentFqName)
if (parentFragment != null) {
// Filter out extension properties
descriptors.addAll(parentFragment.getMemberScope().getProperties(fqName.shortName(), NoLookupLocation.WHEN_CHECK_REDECLARATIONS).filter {
descriptors.addAll(parentFragment.getMemberScope().getProperties(fqName.shortName(), location).filter {
it.getExtensionReceiverParameter() == null
})
}
descriptors.addIfNotNull(topLevelDescriptorProvider.getPackageFragment(fqName))
descriptors.addAll(topLevelDescriptorProvider.getTopLevelClassDescriptors(fqName))
descriptors.addAll(topLevelDescriptorProvider.getTopLevelClassDescriptors(fqName, location))
return descriptors
}
}
@@ -25,6 +25,8 @@ import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_OBJECT
import org.jetbrains.kotlin.diagnostics.Errors.CONSTRUCTOR_IN_TRAIT
import org.jetbrains.kotlin.diagnostics.Errors.MANY_COMPANION_OBJECTS
import org.jetbrains.kotlin.diagnostics.Errors.UNSUPPORTED
import org.jetbrains.kotlin.incremental.KotlinLookupLocation
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
@@ -99,7 +101,8 @@ public class LazyTopDownAnalyzer(
}
override fun visitClassOrObject(classOrObject: JetClassOrObject) {
val descriptor = lazyDeclarationResolver.getClassDescriptor(classOrObject) as ClassDescriptorWithResolutionScopes
val location = if (classOrObject.isTopLevel()) KotlinLookupLocation(classOrObject) else NoLookupLocation.WHEN_RESOLVE_DECLARATION
val descriptor = lazyDeclarationResolver.getClassDescriptor(classOrObject, location) as ClassDescriptorWithResolutionScopes
c.getDeclaredClasses().put(classOrObject, descriptor)
registerDeclarations(classOrObject.getDeclarations())
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.lazy;
import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
@@ -59,7 +60,7 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
if (parentDeclaration instanceof JetClassOrObject) {
JetClassOrObject classOrObject = (JetClassOrObject) parentDeclaration;
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject);
LazyClassDescriptor classDescriptor = (LazyClassDescriptor) lazyDeclarationResolver.getClassDescriptor(classOrObject, NoLookupLocation.WHEN_GET_DECLARATION_SCOPE);
if (jetDeclaration instanceof JetClassInitializer || jetDeclaration instanceof JetProperty) {
return classDescriptor.getScopeForInitializerResolution();
}
@@ -21,6 +21,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor;
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor;
import org.jetbrains.kotlin.descriptors.ModuleDescriptor;
import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
import org.jetbrains.kotlin.incremental.components.LookupLocation;
import org.jetbrains.kotlin.psi.JetClassOrObject;
import org.jetbrains.kotlin.psi.JetDeclaration;
import org.jetbrains.kotlin.resolve.BindingContext;
@@ -31,7 +32,7 @@ public interface KotlinCodeAnalyzer extends TopLevelDescriptorProvider {
ModuleDescriptor getModuleDescriptor();
@NotNull
ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject);
ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject, @NotNull LookupLocation location);
@NotNull
BindingContext getBindingContext();
@@ -21,6 +21,8 @@ import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.context.GlobalContext;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.incremental.KotlinLookupLocation;
import org.jetbrains.kotlin.incremental.components.LookupLocation;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.name.Name;
@@ -29,7 +31,6 @@ import org.jetbrains.kotlin.psi.psiUtil.PsiUtilPackage;
import org.jetbrains.kotlin.renderer.DescriptorRenderer;
import org.jetbrains.kotlin.resolve.BindingContext;
import org.jetbrains.kotlin.resolve.BindingTrace;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor;
import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.storage.LockBasedLazyResolveStorageManager;
@@ -64,14 +65,14 @@ public class LazyDeclarationResolver {
}
@NotNull
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
JetScope scope = getMemberScopeDeclaredIn(classOrObject);
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject, @NotNull LookupLocation location) {
JetScope scope = getMemberScopeDeclaredIn(classOrObject, location);
// Why not use the result here. Because it may be that there is a redeclaration:
// class A {} class A { fun foo(): A<completion here>}
// and if we find the class by name only, we may b-not get the right one.
// This call is only needed to make sure the classes are written to trace
ClassifierDescriptor scopeDescriptor = scope.getClassifier(classOrObject.getNameAsSafeName(), NoLookupLocation.UNSORTED);
ClassifierDescriptor scopeDescriptor = scope.getClassifier(classOrObject.getNameAsSafeName(), location);
DeclarationDescriptor descriptor = getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
if (descriptor == null) {
@@ -93,21 +94,32 @@ public class LazyDeclarationResolver {
@NotNull
public DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration) {
return resolveToDescriptor(declaration, /*track =*/true);
}
@NotNull
private DeclarationDescriptor resolveToDescriptor(@NotNull JetDeclaration declaration, final boolean track) {
DeclarationDescriptor result = declaration.accept(new JetVisitor<DeclarationDescriptor, Void>() {
@NotNull
private LookupLocation lookupLocationFor(@NotNull JetDeclaration declaration, boolean isTopLevel) {
return isTopLevel && track ? new KotlinLookupLocation(declaration) : NoLookupLocation.WHEN_RESOLVE_DECLARATION;
}
@Override
public DeclarationDescriptor visitClass(@NotNull JetClass klass, Void data) {
return getClassDescriptor(klass);
return getClassDescriptor(klass, lookupLocationFor(klass, klass.isTopLevel()));
}
@Override
public DeclarationDescriptor visitObjectDeclaration(@NotNull JetObjectDeclaration declaration, Void data) {
return getClassDescriptor(declaration);
return getClassDescriptor(declaration, lookupLocationFor(declaration, declaration.isTopLevel()));
}
@Override
public DeclarationDescriptor visitTypeParameter(@NotNull JetTypeParameter parameter, Void data) {
JetTypeParameterListOwner ownerElement = PsiTreeUtil.getParentOfType(parameter, JetTypeParameterListOwner.class);
DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement);
assert ownerElement != null : "Owner not found for type parameter: " + parameter.getText();
DeclarationDescriptor ownerDescriptor = resolveToDescriptor(ownerElement, /*track =*/false);
List<TypeParameterDescriptor> typeParameters;
if (ownerDescriptor instanceof CallableDescriptor) {
@@ -134,8 +146,9 @@ public class LazyDeclarationResolver {
@Override
public DeclarationDescriptor visitNamedFunction(@NotNull JetNamedFunction function, Void data) {
JetScope scopeForDeclaration = getMemberScopeDeclaredIn(function);
scopeForDeclaration.getFunctions(function.getNameAsSafeName(), NoLookupLocation.UNSORTED);
LookupLocation location = lookupLocationFor(function, function.isTopLevel());
JetScope scopeForDeclaration = getMemberScopeDeclaredIn(function, location);
scopeForDeclaration.getFunctions(function.getNameAsSafeName(), location);
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, function);
}
@@ -145,9 +158,9 @@ public class LazyDeclarationResolver {
if (grandFather instanceof JetPrimaryConstructor) {
JetClassOrObject jetClass = ((JetPrimaryConstructor) grandFather).getContainingClassOrObject();
// This is a primary constructor parameter
ClassDescriptor classDescriptor = getClassDescriptor(jetClass);
ClassDescriptor classDescriptor = getClassDescriptor(jetClass, lookupLocationFor(jetClass, false));
if (parameter.hasValOrVar()) {
classDescriptor.getDefaultType().getMemberScope().getProperties(parameter.getNameAsSafeName(), NoLookupLocation.UNSORTED);
classDescriptor.getDefaultType().getMemberScope().getProperties(parameter.getNameAsSafeName(), lookupLocationFor(parameter, false));
return getBindingContext().get(BindingContext.PRIMARY_CONSTRUCTOR_PARAMETER, parameter);
}
else {
@@ -177,20 +190,21 @@ public class LazyDeclarationResolver {
@Override
public DeclarationDescriptor visitSecondaryConstructor(@NotNull JetSecondaryConstructor constructor, Void data) {
getClassDescriptor((JetClassOrObject) constructor.getParent().getParent()).getConstructors();
getClassDescriptor((JetClassOrObject) constructor.getParent().getParent(), lookupLocationFor(constructor, false)).getConstructors();
return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
}
@Override
public DeclarationDescriptor visitPrimaryConstructor(@NotNull JetPrimaryConstructor constructor, Void data) {
getClassDescriptor(constructor.getContainingClassOrObject()).getConstructors();
getClassDescriptor(constructor.getContainingClassOrObject(), lookupLocationFor(constructor, false)).getConstructors();
return getBindingContext().get(BindingContext.CONSTRUCTOR, constructor);
}
@Override
public DeclarationDescriptor visitProperty(@NotNull JetProperty property, Void data) {
JetScope scopeForDeclaration = getMemberScopeDeclaredIn(property);
scopeForDeclaration.getProperties(property.getNameAsSafeName(), NoLookupLocation.UNSORTED);
LookupLocation location = lookupLocationFor(property, property.isTopLevel());
JetScope scopeForDeclaration = getMemberScopeDeclaredIn(property, location);
scopeForDeclaration.getProperties(property.getNameAsSafeName(), location);
return getBindingContext().get(BindingContext.DECLARATION_TO_DESCRIPTOR, property);
}
@@ -213,7 +227,7 @@ public class LazyDeclarationResolver {
}
@NotNull
/*package*/ JetScope getMemberScopeDeclaredIn(@NotNull JetDeclaration declaration) {
/*package*/ JetScope getMemberScopeDeclaredIn(@NotNull JetDeclaration declaration, @NotNull LookupLocation location) {
JetDeclaration parentDeclaration = JetStubbedPsiUtil.getContainingDeclaration(declaration);
boolean isTopLevel = parentDeclaration == null;
if (isTopLevel) { // for top level declarations we search directly in package because of possible conflicts with imports
@@ -224,7 +238,7 @@ public class LazyDeclarationResolver {
}
else {
if (parentDeclaration instanceof JetClassOrObject) {
return getClassDescriptor((JetClassOrObject) parentDeclaration).getUnsubstitutedMemberScope();
return getClassDescriptor((JetClassOrObject) parentDeclaration, location).getUnsubstitutedMemberScope();
} else {
throw new IllegalStateException("Don't call this method for local declarations: " + declaration + "\n" +
PsiUtilPackage.getElementTextWithContext(declaration));
@@ -27,6 +27,7 @@ import org.jetbrains.annotations.ReadOnly;
import org.jetbrains.kotlin.context.GlobalContext;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.annotations.Annotations;
import org.jetbrains.kotlin.incremental.components.LookupLocation;
import org.jetbrains.kotlin.incremental.components.LookupTracker;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.name.FqName;
@@ -258,7 +259,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
@Override
@NotNull
@ReadOnly
public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName) {
public Collection<ClassDescriptor> getTopLevelClassDescriptors(@NotNull FqName fqName, @NotNull final LookupLocation location) {
if (fqName.isRoot()) return Collections.emptyList();
PackageMemberDeclarationProvider provider = declarationProviderFactory.getPackageMemberDeclarationProvider(fqName.parent());
@@ -274,7 +275,7 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
}
JetClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
if (classOrObject == null) return null;
return getClassDescriptor(classOrObject);
return getClassDescriptor(classOrObject, location);
}
}
);
@@ -282,13 +283,13 @@ public class ResolveSession implements KotlinCodeAnalyzer, LazyClassContext {
@Override
@NotNull
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject) {
return lazyDeclarationResolver.getClassDescriptor(classOrObject);
public ClassDescriptor getClassDescriptor(@NotNull JetClassOrObject classOrObject, @NotNull LookupLocation location) {
return lazyDeclarationResolver.getClassDescriptor(classOrObject, location);
}
@NotNull
public ClassDescriptor getClassDescriptorForScript(@NotNull JetScript script) {
JetScope memberScope = lazyDeclarationResolver.getMemberScopeDeclaredIn(script);
JetScope memberScope = lazyDeclarationResolver.getMemberScopeDeclaredIn(script, NoLookupLocation.FOR_SCRIPT);
FqName fqName = ScriptNameUtil.classNameForScript(script);
ClassifierDescriptor classifier = memberScope.getClassifier(fqName.shortName(), NoLookupLocation.FOR_SCRIPT);
assert classifier != null : "No descriptor for " + fqName + " in file " + script.getContainingFile();
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.resolve.lazy
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.ScriptDescriptor
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetScript
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyPackageDescriptor
@@ -27,7 +28,7 @@ public interface TopLevelDescriptorProvider {
fun getScriptDescriptor(script: JetScript): ScriptDescriptor
fun getTopLevelClassDescriptors(fqName: FqName): Collection<ClassDescriptor>
fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor>
}
public object NoTopLevelDescriptorProvider : TopLevelDescriptorProvider {
@@ -41,7 +42,7 @@ public object NoTopLevelDescriptorProvider : TopLevelDescriptorProvider {
shouldNotBeCalled()
}
override fun getTopLevelClassDescriptors(fqName: FqName): Collection<ClassDescriptor> {
override fun getTopLevelClassDescriptors(fqName: FqName, location: LookupLocation): Collection<ClassDescriptor> {
shouldNotBeCalled()
}
}
}
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.frontend.di.createContainerForLazyLocalClassifierAnalyzer
import org.jetbrains.kotlin.incremental.components.LookupLocation
import org.jetbrains.kotlin.incremental.components.LookupTracker
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.psi.JetClassOrObject
@@ -156,11 +157,11 @@ class LocalLazyDeclarationResolver(
topLevelDescriptorProvider : TopLevelDescriptorProvider
) : LazyDeclarationResolver(globalContext, trace, topLevelDescriptorProvider) {
override fun getClassDescriptor(classOrObject: JetClassOrObject): ClassDescriptor {
override fun getClassDescriptor(classOrObject: JetClassOrObject, location: LookupLocation): ClassDescriptor {
if (localClassDescriptorManager.isMyClass(classOrObject)) {
return localClassDescriptorManager.getClassDescriptor(classOrObject, scopeProvider)
}
return super.getClassDescriptor(classOrObject)
return super.getClassDescriptor(classOrObject, location)
}
}
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.context.ContextPackage;
import org.jetbrains.kotlin.context.ModuleContext;
import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
@@ -108,7 +109,7 @@ public class JetDefaultModalityModifiersTest extends JetLiteFixture {
TargetPlatform.Default.INSTANCE$
);
return (ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(aClass);
return (ClassDescriptorWithResolutionScopes) resolveSession.getClassDescriptor(aClass, NoLookupLocation.FROM_TEST);
}
private void testClassModality(String classDeclaration, ClassKind kind, Modality expectedModality) {
@@ -28,5 +28,7 @@ public enum class NoLookupLocation : LookupLocation {
FROM_BUILTINS,
WHEN_CHECK_REDECLARATIONS,
FOR_SCRIPT,
FROM_REFLECTION
FROM_REFLECTION,
WHEN_RESOLVE_DECLARATION,
WHEN_GET_DECLARATION_SCOPE
}
@@ -18,6 +18,7 @@ package org.jetbrains.kotlin.idea.caches.resolve
import org.jetbrains.kotlin.descriptors.ClassDescriptorWithResolutionScopes
import org.jetbrains.kotlin.idea.project.ResolveElementCache
import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.psi.psiUtil.siblings
@@ -87,7 +88,7 @@ public class CodeFragmentAnalyzer(
when (context) {
is JetClassOrObject -> {
val descriptor = resolveSession.getClassDescriptor(context) as ClassDescriptorWithResolutionScopes
val descriptor = resolveSession.getClassDescriptor(context, NoLookupLocation.FROM_IDE) as ClassDescriptorWithResolutionScopes
scopeForContextElement = descriptor.getScopeForMemberDeclarationResolution()
dataFlowInfo = DataFlowInfo.EMPTY
@@ -117,4 +118,4 @@ public class CodeFragmentAnalyzer(
return chainedScope to dataFlowInfo
}
}
}