Override/Implement methods: Use lazy analysis

This commit is contained in:
Alexey Sedunov
2014-01-30 18:13:40 +04:00
parent bfbcaba0b0
commit 7c1e28a748
5 changed files with 40 additions and 20 deletions
@@ -21,10 +21,12 @@ import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.intellij.lang.ASTNode;
import com.intellij.openapi.util.Condition;
import com.intellij.psi.PsiElement;
import com.intellij.util.containers.ContainerUtil;
import com.intellij.util.containers.LinkedMultiMap;
import com.intellij.util.containers.MultiMap;
import kotlin.KotlinPackage;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.*;
import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
@@ -265,12 +267,25 @@ public class OverrideResolver {
}
}
public static void collectMissingImplementations(MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl) {
public static void collectMissingImplementations(
MutableClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
) {
for (CallableMemberDescriptor descriptor : classDescriptor.getAllCallableMembers()) {
collectMissingImplementations(descriptor, abstractNoImpl, manyImpl);
}
}
public static void collectMissingImplementations(
ClassDescriptor classDescriptor, Set<CallableMemberDescriptor> abstractNoImpl, Set<CallableMemberDescriptor> manyImpl
) {
Iterator<CallableMemberDescriptor> callableMembers = KotlinPackage.filterIsInstance(
classDescriptor.getDefaultType().getMemberScope().getAllDescriptors().iterator(), CallableMemberDescriptor.class
);
while (callableMembers.hasNext()) {
collectMissingImplementations(callableMembers.next(), abstractNoImpl, manyImpl);
}
}
private static void collectMissingImplementations(
@NotNull CallableMemberDescriptor descriptor,
@NotNull Set<CallableMemberDescriptor> abstractNoImpl,
@@ -408,9 +423,9 @@ public class OverrideResolver {
return overriddenDeclarationsByDirectParent;
}
public static Multimap<CallableMemberDescriptor, CallableMemberDescriptor> collectSuperMethods(MutableClassDescriptor classDescriptor) {
public static Multimap<CallableMemberDescriptor, CallableMemberDescriptor> collectSuperMethods(ClassDescriptor classDescriptor) {
Set<CallableMemberDescriptor> inheritedFunctions = Sets.newLinkedHashSet();
for (JetType supertype : classDescriptor.getSupertypes()) {
for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) {
for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) {
if (descriptor instanceof CallableMemberDescriptor) {
CallableMemberDescriptor memberDescriptor = (CallableMemberDescriptor) descriptor;
@@ -23,7 +23,7 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.plugin.JetBundle;
@@ -32,7 +32,7 @@ import java.util.Set;
public class ImplementMethodsHandler extends OverrideImplementMethodsHandler implements IntentionAction {
@Override
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor) {
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(ClassDescriptor descriptor) {
Set<CallableMemberDescriptor> missingImplementations = Sets.newLinkedHashSet();
OverrideResolver.collectMissingImplementations(descriptor, missingImplementations, missingImplementations);
return missingImplementations;
@@ -206,13 +206,13 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
@NotNull
public Set<CallableMemberDescriptor> collectMethodsToGenerate(@NotNull JetClassOrObject classOrObject, BindingContext bindingContext) {
DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject);
if (descriptor instanceof MutableClassDescriptor) {
return collectMethodsToGenerate((MutableClassDescriptor) descriptor);
if (descriptor instanceof ClassDescriptor) {
return collectMethodsToGenerate((ClassDescriptor) descriptor);
}
return Collections.emptySet();
}
protected abstract Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor);
protected abstract Set<CallableMemberDescriptor> collectMethodsToGenerate(ClassDescriptor descriptor);
private MemberChooser<DescriptorClassMember> showOverrideImplementChooser(
Project project,
@@ -245,9 +245,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
assert classOrObject != null : "ClassObject should be checked in isValidFor method";
BindingContext bindingContext =
AnalyzerFacadeWithCache.analyzeFileWithCache((JetFile) classOrObject.getContainingFile())
.getBindingContext();
BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(classOrObject);
Set<CallableMemberDescriptor> missingImplementations = collectMethodsToGenerate(classOrObject, bindingContext);
if (missingImplementations.isEmpty() && !implementAll) {
@@ -17,7 +17,8 @@
package org.jetbrains.jet.plugin.codeInsight;
import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor;
import org.jetbrains.jet.lang.descriptors.impl.MutableClassDescriptor;
import org.jetbrains.jet.lang.descriptors.ClassDescriptor;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.resolve.OverrideResolver;
import org.jetbrains.jet.lang.resolve.calls.CallResolverUtil;
@@ -26,10 +27,15 @@ import java.util.Set;
public class OverrideMethodsHandler extends OverrideImplementMethodsHandler {
@Override
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor) {
protected Set<CallableMemberDescriptor> collectMethodsToGenerate(ClassDescriptor descriptor) {
Set<CallableMemberDescriptor> superMethods = OverrideResolver.collectSuperMethods(descriptor).keySet();
for (CallableMemberDescriptor member : descriptor.getDeclaredCallableMembers()) {
superMethods.removeAll(member.getOverriddenDescriptors());
for (DeclarationDescriptor member : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (member instanceof CallableMemberDescriptor) {
CallableMemberDescriptor callable = (CallableMemberDescriptor) member;
if (callable.getKind().isReal()) {
superMethods.removeAll(callable.getOverriddenDescriptors());
}
}
}
Set<CallableMemberDescriptor> result = new HashSet<CallableMemberDescriptor>();
for (CallableMemberDescriptor superMethod : superMethods) {
@@ -38,6 +38,7 @@ import org.jetbrains.jet.lang.psi.JetFile;
import org.jetbrains.jet.lang.resolve.BindingContext;
import org.jetbrains.jet.plugin.JetLightProjectDescriptor;
import org.jetbrains.jet.plugin.project.AnalyzerFacadeWithCache;
import org.jetbrains.jet.plugin.project.ResolveSessionForBodies;
import java.util.ArrayList;
import java.util.Collections;
@@ -121,8 +122,9 @@ public abstract class AbstractOverrideImplementTest extends LightCodeInsightFixt
assertNotNull("Caret should be inside class or object", classOrObject);
final JetFile jetFile = (JetFile) classOrObject.getContainingFile();
final BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(jetFile).getBindingContext();
Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext);
final ResolveSessionForBodies resolveSession = AnalyzerFacadeWithCache.getLazyResolveSessionForFile(jetFile);
Set<CallableMemberDescriptor> descriptors =
handler.collectMethodsToGenerate(classOrObject, resolveSession.resolveToElement(classOrObject));
final CallableMemberDescriptor singleToOverride;
if (memberToOverride == null) {
@@ -151,7 +153,7 @@ public abstract class AbstractOverrideImplementTest extends LightCodeInsightFixt
OverrideImplementMethodsHandler.generateMethods(
myFixture.getEditor(), classOrObject,
OverrideImplementMethodsHandler
.membersFromDescriptors(jetFile, Collections.singletonList(singleToOverride), bindingContext));
.membersFromDescriptors(jetFile, Collections.singletonList(singleToOverride), resolveSession.getBindingContext()));
}
}.execute();
}
@@ -162,8 +164,7 @@ public abstract class AbstractOverrideImplementTest extends LightCodeInsightFixt
assertNotNull("Caret should be inside class or object", classOrObject);
final JetFile jetFile = (JetFile) classOrObject.getContainingFile();
final BindingContext bindingContext = AnalyzerFacadeWithCache.analyzeFileWithCache(jetFile)
.getBindingContext();
final BindingContext bindingContext = AnalyzerFacadeWithCache.getContextForElement(classOrObject);
Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext);
final ArrayList<CallableMemberDescriptor> descriptorsList = new ArrayList<CallableMemberDescriptor>(descriptors);