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.JetScript;
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.TopDownAnalyzerFacadeForJVM;
import org.jetbrains.kotlin.resolve.lazy.ResolveSession;
@@ -141,7 +142,7 @@ public class ReplInterpreter {
scopeProvider
);
this.topDownAnalysisContext = new TopDownAnalysisContext(topDownAnalysisParameters);
this.topDownAnalysisContext = new TopDownAnalysisContext(topDownAnalysisParameters, DataFlowInfo.EMPTY);
this.topDownAnalyzer = injector.getLazyTopDownAnalyzer();
this.resolveSession = injector.getResolveSession();
@@ -361,7 +362,9 @@ public class ReplInterpreter {
TopDownAnalysisContext context = topDownAnalyzer.analyzeDeclarations(
topDownAnalysisContext.getTopDownAnalysisParameters(),
Collections.singletonList(psiFile));
Collections.singletonList(psiFile),
DataFlowInfo.EMPTY
);
if (trace.get(BindingContext.FILE_TO_PACKAGE_FRAGMENT, psiFile) == null) {
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 org.jetbrains.kotlin.resolve.scopes.JetScope
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.psi.debugText.getDebugText
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.psi.psiUtil.isObjectLiteral
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(
val descriptorResolver: DescriptorResolver,
@@ -65,9 +67,6 @@ public class LazyLocalClassifierAnalyzer(
globalContext.exceptionTracker,
Predicates.equalTo(classOrObject.getContainingFile()), false, true)
val c = TopDownAnalysisContext(topDownAnalysisParameters)
c.setOuterDataFlowInfo(context.dataFlowInfo)
val moduleDescriptor = DescriptorUtils.getContainingModule(containingDeclaration)
val injector = InjectorForLazyLocalClassifierAnalyzer(
classOrObject.getProject(),
@@ -91,7 +90,8 @@ public class LazyLocalClassifierAnalyzer(
injector.getLazyTopDownAnalyzer().analyzeDeclarations(
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
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 {
assert(isMyClass(classOrObject)) {"Called on a wrong class: ${classOrObject.getDebugText()}"}
@@ -177,4 +178,12 @@ class DeclarationScopeProviderForLocalClassifierAnalyzer(
}
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.name.FqName;
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.descriptors.LazyClassDescriptor;
import org.jetbrains.kotlin.resolve.resolveUtil.ResolveUtilPackage;
@@ -119,11 +120,13 @@ public class LazyTopDownAnalyzer {
@NotNull
public TopDownAnalysisContext analyzeDeclarations(
@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";
final TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
final TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters, outerDataFlowInfo);
final Multimap<FqName, JetElement> topLevelFqNames = HashMultimap.create();
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.psi.JetFile;
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.LazyFileScope;
@@ -66,7 +67,7 @@ public class LazyTopDownAnalyzerForTopLevel {
((ModuleDescriptorImpl) resolveSession.getModuleDescriptor()).initialize(provider);
TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisParameters, files);
TopDownAnalysisContext c = lazyTopDownAnalyzer.analyzeDeclarations(topDownAnalysisParameters, files, DataFlowInfo.EMPTY);
resolveImportsInAllFiles(c, resolveSession);
@@ -39,7 +39,7 @@ import java.util.*;
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<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
@@ -66,8 +66,9 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private StringBuilder debugOutput;
public TopDownAnalysisContext(@NotNull TopDownAnalysisParameters topDownAnalysisParameters) {
public TopDownAnalysisContext(@NotNull TopDownAnalysisParameters topDownAnalysisParameters, @NotNull DataFlowInfo outerDataFlowInfo) {
this.topDownAnalysisParameters = topDownAnalysisParameters;
this.outerDataFlowInfo = outerDataFlowInfo;
}
@Override
@@ -199,10 +200,6 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return outerDataFlowInfo;
}
public void setOuterDataFlowInfo(@NotNull DataFlowInfo outerDataFlowInfo) {
this.outerDataFlowInfo = outerDataFlowInfo;
}
@NotNull
public Collection<ClassDescriptorWithResolutionScopes> getAllClasses() {
// 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.name.FqName;
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.WritableScope;
import org.jetbrains.kotlin.resolve.varianceChecker.VarianceChecker;
@@ -155,7 +156,7 @@ public class TopDownAnalyzer {
//noinspection deprecation
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 =
new CompositePackageFragmentProvider(KotlinPackage.plus(Arrays.asList(packageFragmentProvider), additionalProviders));
@@ -18,7 +18,9 @@ package org.jetbrains.kotlin.resolve.lazy
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.kotlin.resolve.calls.smartcasts.DataFlowInfo
public trait DeclarationScopeProvider {
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 org.jetbrains.annotations.NotNull;
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.scopes.JetScope;
@@ -80,4 +81,10 @@ public class DeclarationScopeProviderImpl implements DeclarationScopeProvider {
throw new IllegalStateException("Don't call this method for local declarations: " + jetDeclaration + "\n" +
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.resolve.ImportPath;
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.storage.MemoizedFunctionToNotNull;
import org.jetbrains.kotlin.storage.NotNullLazyValue;
@@ -37,6 +38,7 @@ import java.util.Collections;
import java.util.List;
public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvider {
public static class AdditionalFileScopeProvider {
@NotNull
public List<JetScope> scopes(@NotNull JetFile file) {
@@ -113,4 +115,10 @@ public class ScopeProvider implements DeclarationScopeProvider, FileScopeProvide
public JetScope getResolutionScopeForDeclaration(@NotNull PsiElement 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,
functionDeclaration,
trace,
// this relies on the assumption that a lazily resolved declaration is not a local one,
// thus doesn't have a surrounding data flow
DataFlowInfo.EMPTY))
c.scopeProvider.getOuterDataFlowInfoForDeclaration(functionDeclaration)))
}
getNonDeclaredFunctions(name, result)
@@ -101,9 +99,7 @@ public abstract class AbstractLazyMemberScope<D : DeclarationDescriptor, DP : De
resolutionScope,
propertyDeclaration,
trace,
// this relies on the assumption that a lazily resolved declaration is not a local one,
// thus doesn't have a surrounding data flow
DataFlowInfo.EMPTY)
c.scopeProvider.getOuterDataFlowInfoForDeclaration(propertyDeclaration))
result.add(propertyDescriptor)
AnnotationResolver.resolveAnnotationsArguments(propertyDescriptor.getAnnotations(), trace)
}
@@ -63,8 +63,7 @@ public class LocalClassifierAnalyzer {
dynamicTypesSettings
);
TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters);
c.setOuterDataFlowInfo(context.dataFlowInfo);
TopDownAnalysisContext c = new TopDownAnalysisContext(topDownAnalysisParameters, context.dataFlowInfo);
injector.getTopDownAnalyzer().doProcess(
c,
@@ -263,7 +263,8 @@ private object KotlinResolveDataProvider {
/* analyzingBootstrapLibrary = */ false,
/* declaredLocally = */ false
),
listOf(analyzableElement)
listOf(analyzableElement),
DataFlowInfo.EMPTY
)
return AnalysisResult.success(
trace.getBindingContext(),