Outer DataFlowInfo delivered to local class members

This commit is contained in:
Andrey Breslav
2015-01-23 18:22:00 +03:00
parent 7323ef7002
commit ed4da90dcd
12 changed files with 54 additions and 27 deletions
@@ -58,6 +58,7 @@ import org.jetbrains.kotlin.parsing.JetParserDefinition;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.psi.JetScript; import org.jetbrains.kotlin.psi.JetScript;
import org.jetbrains.kotlin.resolve.*; import org.jetbrains.kotlin.resolve.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.jvm.JvmClassName; import org.jetbrains.kotlin.resolve.jvm.JvmClassName;
import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM; import org.jetbrains.kotlin.resolve.jvm.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.kotlin.resolve.lazy.ResolveSession; import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
@@ -141,7 +142,7 @@ public class ReplInterpreter {
scopeProvider scopeProvider
); );
this.topDownAnalysisContext = new TopDownAnalysisContext(topDownAnalysisParameters); this.topDownAnalysisContext = new TopDownAnalysisContext(topDownAnalysisParameters, DataFlowInfo.EMPTY);
this.topDownAnalyzer = injector.getLazyTopDownAnalyzer(); this.topDownAnalyzer = injector.getLazyTopDownAnalyzer();
this.resolveSession = injector.getResolveSession(); this.resolveSession = injector.getResolveSession();
@@ -361,7 +362,9 @@ public class ReplInterpreter {
TopDownAnalysisContext context = topDownAnalyzer.analyzeDeclarations( TopDownAnalysisContext context = topDownAnalyzer.analyzeDeclarations(
topDownAnalysisContext.getTopDownAnalysisParameters(), topDownAnalysisContext.getTopDownAnalysisParameters(),
Collections.singletonList(psiFile)); Collections.singletonList(psiFile),
DataFlowInfo.EMPTY
);
if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) { if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) {
trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, resolveSession.getPackageFragment(FqName.ROOT)); trace.record(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile, resolveSession.getPackageFragment(FqName.ROOT));
@@ -30,7 +30,6 @@ import org.jetbrains.kotlin.resolve.lazy.LazyDeclarationResolver
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.descriptors.ClassDescriptor import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.jet.lang.resolve.lazy.descriptors.LazyClassContext
import org.jetbrains.kotlin.resolve.lazy.data.JetClassInfoUtil import org.jetbrains.kotlin.resolve.lazy.data.JetClassInfoUtil
import org.jetbrains.kotlin.psi.debugText.getDebugText import org.jetbrains.kotlin.psi.debugText.getDebugText
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor
@@ -45,6 +44,9 @@ import org.jetbrains.kotlin.descriptors.ModuleDescriptor
import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider import org.jetbrains.kotlin.resolve.lazy.DeclarationScopeProvider
import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral import org.jetbrains.kotlin.psi.psiUtil.isObjectLiteral
import org.jetbrains.kotlin.name.SpecialNames import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.resolve.lazy.LazyClassContext
public class LazyLocalClassifierAnalyzer( public class LazyLocalClassifierAnalyzer(
val descriptorResolver: DescriptorResolver, val descriptorResolver: DescriptorResolver,
@@ -65,9 +67,6 @@ public class LazyLocalClassifierAnalyzer(
globalContext.exceptionTracker, globalContext.exceptionTracker,
Predicates.equalTo(classOrObject.getContainingFile()), false, true) Predicates.equalTo(classOrObject.getContainingFile()), false, true)
val c = TopDownAnalysisContext(topDownAnalysisParameters)
c.setOuterDataFlowInfo(context.dataFlowInfo)
val moduleDescriptor = DescriptorUtils.getContainingModule(containingDeclaration) val moduleDescriptor = DescriptorUtils.getContainingModule(containingDeclaration)
val injector = InjectorForLazyLocalClassifierAnalyzer( val injector = InjectorForLazyLocalClassifierAnalyzer(
classOrObject.getProject(), classOrObject.getProject(),
@@ -91,7 +90,8 @@ public class LazyLocalClassifierAnalyzer(
injector.getLazyTopDownAnalyzer().analyzeDeclarations( injector.getLazyTopDownAnalyzer().analyzeDeclarations(
topDownAnalysisParameters, topDownAnalysisParameters,
listOf(classOrObject) listOf(classOrObject),
context.dataFlowInfo
) )
} }
} }
@@ -110,7 +110,8 @@ class LocalClassDescriptorManager(
// We do not need to synchronize here, because this code is used strictly from one thread // We do not need to synchronize here, because this code is used strictly from one thread
private var classDescriptor: ClassDescriptor? = null private var classDescriptor: ClassDescriptor? = null
fun isMyClass(c: PsiElement): Boolean = c == myClass fun isMyClass(element: PsiElement): Boolean = element == myClass
fun insideMyClass(element: PsiElement): Boolean = PsiTreeUtil.isAncestor(myClass, element, false)
fun createClassDescriptor(classOrObject: JetClassOrObject, declarationScopeProvider: DeclarationScopeProvider): ClassDescriptor { fun createClassDescriptor(classOrObject: JetClassOrObject, declarationScopeProvider: DeclarationScopeProvider): ClassDescriptor {
assert(isMyClass(classOrObject)) {"Called on a wrong class: ${classOrObject.getDebugText()}"} assert(isMyClass(classOrObject)) {"Called on a wrong class: ${classOrObject.getDebugText()}"}
@@ -177,4 +178,12 @@ class DeclarationScopeProviderForLocalClassifierAnalyzer(
} }
return super.getResolutionScopeForDeclaration(elementOfDeclaration) return super.getResolutionScopeForDeclaration(elementOfDeclaration)
} }
override fun getOuterDataFlowInfoForDeclaration(elementOfDeclaration: PsiElement): DataFlowInfo {
// nested (non-inner) classes and class objects are forbidden in local classes, so it's enough to be simply inside the class
if (localClassDescriptorManager.insideMyClass(elementOfDeclaration)) {
return localClassDescriptorManager.expressionTypingContext.dataFlowInfo
}
return super.getOuterDataFlowInfoForDeclaration(elementOfDeclaration)
}
} }
@@ -25,6 +25,7 @@ import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.descriptors.*; import org.jetbrains.kotlin.descriptors.*;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.*; import org.jetbrains.kotlin.resolve.lazy.*;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.resolveUtil.ResolveUtilPackage; import org.jetbrains.kotlin.resolve.resolveUtil.ResolveUtilPackage;
@@ -119,11 +120,13 @@ public class LazyTopDownAnalyzer {
@NotNull @NotNull
public TopDownAnalysisContext analyzeDeclarations( public TopDownAnalysisContext analyzeDeclarations(
@NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull TopDownAnalysisParameters topDownAnalysisParameters,
@NotNull Collection<? extends PsiElement> declarations @NotNull Collection<? extends PsiElement> declarations,
@NotNull DataFlowInfo outerDataFlowInfo
) { ) {
assert topDownAnalysisParameters.isLazy() : "Lazy analyzer is run in non-lazy mode"; assert topDownAnalysisParameters.isLazy() : "Lazy analyzer is run in non-lazy mode";
final TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters); final TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters, outerDataFlowInfo);
final Multimap<FqName, JetElement> topLevelFqNames = HashMultimap.create(); final Multimap<FqName, JetElement> topLevelFqNames = HashMultimap.create();
final List<JetProperty> properties = new ArrayList<JetProperty>(); final List<JetProperty> properties = new ArrayList<JetProperty>();
@@ -23,6 +23,7 @@ import org.jetbrains.kotlin.descriptors.impl.CompositePackageFragmentProvider;
import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl; import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.psi.JetScript; import org.jetbrains.kotlin.psi.JetScript;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer; import org.jetbrains.kotlin.resolve.lazy.KotlinCodeAnalyzer;
import org.jetbrains.kotlin.resolve.lazy.LazyFileScope; import org.jetbrains.kotlin.resolve.lazy.LazyFileScope;
@@ -66,7 +67,7 @@ public class LazyTopDownAnalyzerForTopLevel {
((ModuleDescriptorImpl) resolveSession.getModuleDescriptor()).initialize(provider); ((ModuleDescriptorImpl) resolveSession.getModuleDescriptor()).initialize(provider);
TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisParameters, files); TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisParameters, files, DataFlowInfo.EMPTY);
resolveImportsInAllFiles(c, resolveSession); resolveImportsInAllFiles(c, resolveSession);
@@ -39,7 +39,7 @@ import java.util.*;
public class TopDownAnalysisContext implements BodiesResolveContext { public class TopDownAnalysisContext implements BodiesResolveContext {
private DataFlowInfo outerDataFlowInfo = DataFlowInfo.EMPTY; private final DataFlowInfo outerDataFlowInfo;
private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap(); private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap();
private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap(); private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
@@ -66,8 +66,9 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private StringBuilder debugOutput; private StringBuilder debugOutput;
public TopDownAnalysisContext(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) { public TopDownAnalysisContext(@NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull DataFlowInfo outerDataFlowInfo) {
this.topDownAnalysisParameters = topDownAnalysisParameters; this.topDownAnalysisParameters = topDownAnalysisParameters;
this.outerDataFlowInfo = outerDataFlowInfo;
} }
@Override @Override
@@ -199,10 +200,6 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return outerDataFlowInfo; return outerDataFlowInfo;
} }
public void setOuterDataFlowInfo(@NotNull DataFlowInfo outerDataFlowInfo) {
this.outerDataFlowInfo = outerDataFlowInfo;
}
@NotNull @NotNull
public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() { public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
// SCRIPT: all classes are declared classes + script classes // SCRIPT: all classes are declared classes + script classes
@@ -26,6 +26,7 @@ import org.jetbrains.kotlin.descriptors.PackageFragmentProvider;
import org.jetbrains.kotlin.descriptors.impl.*; import org.jetbrains.kotlin.descriptors.impl.*;
import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.name.FqName;
import org.jetbrains.kotlin.psi.JetFile; import org.jetbrains.kotlin.psi.JetFile;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.resolve.scopes.WritableScope; import org.jetbrains.kotlin.resolve.scopes.WritableScope;
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker; import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker;
@@ -155,7 +156,7 @@ public class TopDownAnalyzer {
//noinspection deprecation //noinspection deprecation
assert !topDownAnalysisParameters.isLazy() : "Lazy resolve must be disabled for this method"; assert !topDownAnalysisParameters.isLazy() : "Lazy resolve must be disabled for this method";
TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters); TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters, DataFlowInfo.EMPTY);
CompositePackageFragmentProvider provider = CompositePackageFragmentProvider provider =
new CompositePackageFragmentProvider(KotlinPackage.plus(Arrays.asList(packageFragmentProvider), additionalProviders)); new CompositePackageFragmentProvider(KotlinPackage.plus(Arrays.asList(packageFragmentProvider), additionalProviders));
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.resolve.lazy
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.resolve.scopes.JetScope import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
public trait DeclarationScopeProvider { public trait DeclarationScopeProvider {
fun getResolutionScopeForDeclaration(elementOfDeclaration: PsiElement): JetScope fun getResolutionScopeForDeclaration(elementOfDeclaration: PsiElement): JetScope
fun getOuterDataFlowInfoForDeclaration(elementOfDeclaration: PsiElement): DataFlowInfo
} }
@@ -19,6 +19,7 @@ package org.jetbrains.kotlin.resolve.lazy;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.psi.*;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor; import org.jetbrains.kotlin.resolve.lazy.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.JetScope;
@@ -80,4 +81,10 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + "\n" + throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + "\n" +
JetPsiUtil.getElementTextWithContext(jetDeclaration)); JetPsiUtil.getElementTextWithContext(jetDeclaration));
} }
@NotNull
@Override
public DataFlowInfo getOuterDataFlowInfoForDeclaration(@NotNull PsiElement elementOfDeclaration) {
return DataFlowInfo.EMPTY;
}
} }
@@ -27,6 +27,7 @@ import org.jetbrains.kotlin.psi.JetImportDirective;
import org.jetbrains.kotlin.psi.JetImportsFactory; import org.jetbrains.kotlin.psi.JetImportsFactory;
import org.jetbrains.kotlin.resolve.ImportPath; import org.jetbrains.kotlin.resolve.ImportPath;
import org.jetbrains.kotlin.resolve.TemporaryBindingTrace; import org.jetbrains.kotlin.resolve.TemporaryBindingTrace;
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo;
import org.jetbrains.kotlin.resolve.scopes.JetScope; import org.jetbrains.kotlin.resolve.scopes.JetScope;
import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull; import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
import org.jetbrains.kotlin.storage.NotNullLazyValue; import org.jetbrains.kotlin.storage.NotNullLazyValue;
@@ -37,6 +38,7 @@ import java.util.Collections;
import java.util.List; import java.util.List;
public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvider { public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvider {
public static class AdditionalFileScopeProvider { public static class AdditionalFileScopeProvider {
@NotNull @NotNull
public List<JetScope> scopes(@NotNull JetFile file) { public List<JetScope> scopes(@NotNull JetFile file) {
@@ -113,4 +115,10 @@ public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvide
public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) { public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement elementOfDeclaration) {
return declarationScopeProvider.getResolutionScopeForDeclaration(elementOfDeclaration); return declarationScopeProvider.getResolutionScopeForDeclaration(elementOfDeclaration);
} }
@NotNull
@Override
public DataFlowInfo getOuterDataFlowInfoForDeclaration(@NotNull PsiElement elementOfDeclaration) {
return declarationScopeProvider.getOuterDataFlowInfoForDeclaration(elementOfDeclaration);
}
} }
@@ -74,9 +74,7 @@ public abstract class AbstractLazyMemberScope<D : DeclarationDescriptor, DP : De
resolutionScope, resolutionScope,
functionDeclaration, functionDeclaration,
trace, trace,
// this relies on the assumption that a lazily resolved declaration is not a local one, c.scopeProvider.getOuterDataFlowInfoForDeclaration(functionDeclaration)))
// thus doesn't have a surrounding data flow
DataFlowInfo.EMPTY))
} }
getNonDeclaredFunctions(name, result) getNonDeclaredFunctions(name, result)
@@ -101,9 +99,7 @@ public abstract class AbstractLazyMemberScope<D : DeclarationDescriptor, DP : De
resolutionScope, resolutionScope,
propertyDeclaration, propertyDeclaration,
trace, trace,
// this relies on the assumption that a lazily resolved declaration is not a local one, c.scopeProvider.getOuterDataFlowInfoForDeclaration(propertyDeclaration))
// thus doesn't have a surrounding data flow
DataFlowInfo.EMPTY)
result.add(propertyDescriptor) result.add(propertyDescriptor)
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations(), trace) AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations(), trace)
} }
@@ -63,8 +63,7 @@ public class LocalClassifierAnalyzer {
dynamicTypesSettings dynamicTypesSettings
); );
TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters); TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters, context.dataFlowInfo);
c.setOuterDataFlowInfo(context.dataFlowInfo);
injector.getTopDownAnalyzer().doProcess( injector.getTopDownAnalyzer().doProcess(
c, c,
@@ -263,7 +263,8 @@ private object KotlinResolveDataProvider {
/* analyzingBootstrapLibrary = */ false, /* analyzingBootstrapLibrary = */ false,
/* declaredLocally = */ false /* declaredLocally = */ false
), ),
listOf(analyzableElement) listOf(analyzableElement),
DataFlowInfo.EMPTY
) )
return AnalysisResult.success( return AnalysisResult.success(
trace.getBindingContext(), trace.getBindingContext(),