Support top-down analysis starting from anonymous initializers

This commit is contained in:
Andrey Breslav
2014-04-23 20:09:54 +04:00
parent bac82935c3
commit a1b0b07824
6 changed files with 59 additions and 27 deletions
@@ -49,6 +49,8 @@ public interface BodiesResolveContext extends GlobalContext {
@Mutable
Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses();
@Mutable
Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers();
@Mutable
Map<JetScript, ScriptDescriptor> getScripts();
@Mutable
@@ -334,35 +334,43 @@ public class BodyResolver {
}
private void resolveAnonymousInitializers(@NotNull BodiesResolveContext c) {
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
JetClassOrObject classOrObject = entry.getKey();
ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
resolveAnonymousInitializers(c, classOrObject, descriptor.getUnsubstitutedPrimaryConstructor(),
descriptor.getScopeForInitializerResolution());
}
}
public void resolveAnonymousInitializers(
@NotNull BodiesResolveContext c,
@NotNull JetClassOrObject jetClassOrObject,
@Nullable ConstructorDescriptor primaryConstructor,
@NotNull JetScope scopeForInitializers) {
if (!c.completeAnalysisNeeded(jetClassOrObject)) {
return;
}
List<JetClassInitializer> anonymousInitializers = jetClassOrObject.getAnonymousInitializers();
if (primaryConstructor != null) {
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
expressionTypingServices.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), trace);
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
if (c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
for (Map.Entry<JetClassInitializer, ClassDescriptorWithResolutionScopes> entry : c.getAnonymousInitializers().entrySet()) {
JetClassInitializer initializer = entry.getKey();
ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
resolveAnonymousInitializer(c, initializer, descriptor);
}
}
else {
for (JetClassInitializer anonymousInitializer : anonymousInitializers) {
trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer));
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
JetClassOrObject classOrObject = entry.getKey();
ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
if (!c.completeAnalysisNeeded(classOrObject)) return;
for (JetClassInitializer initializer : classOrObject.getAnonymousInitializers()) {
resolveAnonymousInitializer(c, initializer, descriptor);
}
}
}
}
public void resolveAnonymousInitializer(
@NotNull BodiesResolveContext c,
@NotNull JetClassInitializer anonymousInitializer,
@NotNull ClassDescriptorWithResolutionScopes classDescriptor
) {
if (!c.completeAnalysisNeeded(anonymousInitializer)) return;
JetScope scopeForInitializers = classDescriptor.getScopeForInitializerResolution();
if (classDescriptor.getUnsubstitutedPrimaryConstructor() != null) {
expressionTypingServices.getType(scopeForInitializers, anonymousInitializer.getBody(), NO_EXPECTED_TYPE, c.getOuterDataFlowInfo(), trace);
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
}
else {
trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer));
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers);
}
}
private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) {
@@ -41,6 +41,7 @@ import java.util.Map;
public class CachedBodiesResolveContext implements BodiesResolveContext {
private final Collection<JetFile> files;
private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes;
private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers;
private final Map<JetProperty, PropertyDescriptor> properties;
private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions;
private final Function<JetDeclaration, JetScope> declaringScopes;
@@ -52,6 +53,7 @@ public class CachedBodiesResolveContext implements BodiesResolveContext {
public CachedBodiesResolveContext(TopDownAnalysisContext context) {
files = Collections.unmodifiableCollection(context.getFiles());
classes = Collections.unmodifiableMap(context.getDeclaredClasses());
anonymousInitializers = Collections.unmodifiableMap(context.getAnonymousInitializers());
properties = Collections.unmodifiableMap(context.getProperties());
functions = Collections.unmodifiableMap(context.getFunctions());
declaringScopes = context.getDeclaringScopes();
@@ -83,6 +85,11 @@ public class CachedBodiesResolveContext implements BodiesResolveContext {
return classes;
}
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return anonymousInitializers;
}
@Override
public Map<JetProperty, PropertyDescriptor> getProperties() {
return properties;
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap;
import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*;
@@ -206,6 +207,11 @@ public class LazyTopDownAnalyzer {
@Override
public void visitAnonymousInitializer(@NotNull JetClassInitializer initializer) {
registerScope(c, resolveSession, initializer);
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(initializer, JetClassOrObject.class);
c.getAnonymousInitializers().put(
initializer,
(ClassDescriptorWithResolutionScopes) resolveSession.resolveToDescriptor(classOrObject)
);
}
@Override
@@ -42,6 +42,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private DataFlowInfo outerDataFlowInfo = DataFlowInfo.EMPTY;
private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap();
private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers = Maps.newLinkedHashMap();
protected final Map<JetFile, MutablePackageFragmentDescriptor> packageFragments = Maps.newHashMap();
protected final Set<JetFile> files = new LinkedHashSet<JetFile>();
private List<MutableClassDescriptor> classesTopologicalOrder = null;
@@ -114,6 +115,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return classes;
}
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return anonymousInitializers;
}
public Map<JetFile, WritableScope> getFileScopes() {
return fileScopes;
}
@@ -348,9 +348,7 @@ public class ResolveElementCache {
LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
bodyResolver.resolveAnonymousInitializers(createEmptyContext(resolveSession), classOrObject,
classOrObjectDescriptor.getUnsubstitutedPrimaryConstructor(),
classOrObjectDescriptor.getScopeForInitializerResolution());
bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor);
return true;
}
@@ -493,6 +491,11 @@ public class ResolveElementCache {
return Collections.emptyMap();
}
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return Collections.emptyMap();
}
@Override
public Map<JetProperty, PropertyDescriptor> getProperties() {
return Collections.emptyMap();