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 @Mutable
Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses(); Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> getDeclaredClasses();
@Mutable @Mutable
Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers();
@Mutable
Map<JetScript, ScriptDescriptor> getScripts(); Map<JetScript, ScriptDescriptor> getScripts();
@Mutable @Mutable
@@ -334,35 +334,43 @@ public class BodyResolver {
} }
private void resolveAnonymousInitializers(@NotNull BodiesResolveContext c) { private void resolveAnonymousInitializers(@NotNull BodiesResolveContext c) {
for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) { if (c.getTopDownAnalysisParameters().isLazyTopDownAnalysis()) {
JetClassOrObject classOrObject = entry.getKey(); for (Map.Entry<JetClassInitializer, ClassDescriptorWithResolutionScopes> entry : c.getAnonymousInitializers().entrySet()) {
ClassDescriptorWithResolutionScopes descriptor = entry.getValue(); JetClassInitializer initializer = entry.getKey();
resolveAnonymousInitializers(c, classOrObject, descriptor.getUnsubstitutedPrimaryConstructor(), ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
descriptor.getScopeForInitializerResolution()); resolveAnonymousInitializer(c, initializer, descriptor);
}
}
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);
} }
} }
else { else {
for (JetClassInitializer anonymousInitializer : anonymousInitializers) { for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry : c.getDeclaredClasses().entrySet()) {
trace.report(ANONYMOUS_INITIALIZER_IN_TRAIT.on(anonymousInitializer)); JetClassOrObject classOrObject = entry.getKey();
processModifiersOnInitializer(anonymousInitializer, scopeForInitializers); 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) { private void processModifiersOnInitializer(@NotNull JetModifierListOwner owner, @NotNull JetScope scope) {
@@ -41,6 +41,7 @@ import java.util.Map;
public class CachedBodiesResolveContext implements BodiesResolveContext { public class CachedBodiesResolveContext implements BodiesResolveContext {
private final Collection<JetFile> files; private final Collection<JetFile> files;
private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes; private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes;
private final Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> anonymousInitializers;
private final Map<JetProperty, PropertyDescriptor> properties; private final Map<JetProperty, PropertyDescriptor> properties;
private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions; private final Map<JetNamedFunction, SimpleFunctionDescriptor> functions;
private final Function<JetDeclaration, JetScope> declaringScopes; private final Function<JetDeclaration, JetScope> declaringScopes;
@@ -52,6 +53,7 @@ public class CachedBodiesResolveContext implements BodiesResolveContext {
public CachedBodiesResolveContext(TopDownAnalysisContext context) { public CachedBodiesResolveContext(TopDownAnalysisContext context) {
files = Collections.unmodifiableCollection(context.getFiles()); files = Collections.unmodifiableCollection(context.getFiles());
classes = Collections.unmodifiableMap(context.getDeclaredClasses()); classes = Collections.unmodifiableMap(context.getDeclaredClasses());
anonymousInitializers = Collections.unmodifiableMap(context.getAnonymousInitializers());
properties = Collections.unmodifiableMap(context.getProperties()); properties = Collections.unmodifiableMap(context.getProperties());
functions = Collections.unmodifiableMap(context.getFunctions()); functions = Collections.unmodifiableMap(context.getFunctions());
declaringScopes = context.getDeclaringScopes(); declaringScopes = context.getDeclaringScopes();
@@ -83,6 +85,11 @@ public class CachedBodiesResolveContext implements BodiesResolveContext {
return classes; return classes;
} }
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return anonymousInitializers;
}
@Override @Override
public Map<JetProperty, PropertyDescriptor> getProperties() { public Map<JetProperty, PropertyDescriptor> getProperties() {
return properties; return properties;
@@ -19,6 +19,7 @@ package org.jetbrains.jet.lang.resolve;
import com.google.common.collect.HashMultimap; import com.google.common.collect.HashMultimap;
import com.google.common.collect.Multimap; import com.google.common.collect.Multimap;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.util.PsiTreeUtil;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.descriptors.*;
@@ -206,6 +207,11 @@ public class LazyTopDownAnalyzer {
@Override @Override
public void visitAnonymousInitializer(@NotNull JetClassInitializer initializer) { public void visitAnonymousInitializer(@NotNull JetClassInitializer initializer) {
registerScope(c, resolveSession, initializer); registerScope(c, resolveSession, initializer);
JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(initializer, JetClassOrObject.class);
c.getAnonymousInitializers().put(
initializer,
(ClassDescriptorWithResolutionScopes) resolveSession.resolveToDescriptor(classOrObject)
);
} }
@Override @Override
@@ -42,6 +42,7 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
private DataFlowInfo outerDataFlowInfo = DataFlowInfo.EMPTY; private DataFlowInfo outerDataFlowInfo = DataFlowInfo.EMPTY;
private final Map<JetClassOrObject, ClassDescriptorWithResolutionScopes> classes = Maps.newLinkedHashMap(); 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 Map<JetFile, MutablePackageFragmentDescriptor> packageFragments = Maps.newHashMap();
protected final Set<JetFile> files = new LinkedHashSet<JetFile>(); protected final Set<JetFile> files = new LinkedHashSet<JetFile>();
private List<MutableClassDescriptor> classesTopologicalOrder = null; private List<MutableClassDescriptor> classesTopologicalOrder = null;
@@ -114,6 +115,11 @@ public class TopDownAnalysisContext implements BodiesResolveContext {
return classes; return classes;
} }
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return anonymousInitializers;
}
public Map<JetFile, WritableScope> getFileScopes() { public Map<JetFile, WritableScope> getFileScopes() {
return fileScopes; return fileScopes;
} }
@@ -348,9 +348,7 @@ public class ResolveElementCache {
LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject); LazyClassDescriptor classOrObjectDescriptor = (LazyClassDescriptor) resolveSession.resolveToDescriptor(classOrObject);
BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file); BodyResolver bodyResolver = createBodyResolver(resolveSession, trace, file);
bodyResolver.resolveAnonymousInitializers(createEmptyContext(resolveSession), classOrObject, bodyResolver.resolveAnonymousInitializer(createEmptyContext(resolveSession), classInitializer, classOrObjectDescriptor);
classOrObjectDescriptor.getUnsubstitutedPrimaryConstructor(),
classOrObjectDescriptor.getScopeForInitializerResolution());
return true; return true;
} }
@@ -493,6 +491,11 @@ public class ResolveElementCache {
return Collections.emptyMap(); return Collections.emptyMap();
} }
@Override
public Map<JetClassInitializer, ClassDescriptorWithResolutionScopes> getAnonymousInitializers() {
return Collections.emptyMap();
}
@Override @Override
public Map<JetProperty, PropertyDescriptor> getProperties() { public Map<JetProperty, PropertyDescriptor> getProperties() {
return Collections.emptyMap(); return Collections.emptyMap();