diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorClassMember.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorClassMember.java index f450380ba6b..836c5dc6d11 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorClassMember.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/DescriptorClassMember.java @@ -16,10 +16,14 @@ package org.jetbrains.jet.plugin.codeInsight; -import com.intellij.codeInsight.generation.ClassMember; +import com.intellij.codeInsight.generation.ClassMemberWithElement; import com.intellij.codeInsight.generation.MemberChooserObject; +import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import com.intellij.ui.SimpleColoredComponent; +import com.intellij.util.PsiIconUtil; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; +import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.resolve.DescriptorRenderer; import javax.swing.*; @@ -27,22 +31,27 @@ import javax.swing.*; /** * @author yole */ -public class DescriptorClassMember implements ClassMember { +public class DescriptorClassMember implements ClassMemberWithElement { private final DeclarationDescriptor myDescriptor; + private final PsiElement myPsiElement; - public DescriptorClassMember(DeclarationDescriptor descriptor) { + public DescriptorClassMember(PsiElement element, DeclarationDescriptor descriptor) { + myPsiElement = element; myDescriptor = descriptor; } @Override public MemberChooserObject getParentNodeDelegate() { final DeclarationDescriptor parent = myDescriptor.getContainingDeclaration(); - return new DescriptorClassMember(parent); + return new DescriptorClassMember(PsiTreeUtil.getParentOfType(myPsiElement, JetNamedDeclaration.class), parent); } @Override public void renderTreeNode(SimpleColoredComponent component, JTree tree) { component.append(getText()); + if (myPsiElement.isValid()) { + component.setIcon(PsiIconUtil.getProvidersIcon(myPsiElement, 0)); + } } @Override @@ -70,4 +79,9 @@ public class DescriptorClassMember implements ClassMember { public int hashCode() { return myDescriptor != null ? myDescriptor.hashCode() : 0; } + + @Override + public PsiElement getElement() { + return myPsiElement; + } } diff --git a/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java b/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java index f3d4722f676..d9020df71e1 100644 --- a/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java +++ b/idea/src/org/jetbrains/jet/plugin/codeInsight/OverrideImplementMethodsHandler.java @@ -33,41 +33,31 @@ import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.*; import org.jetbrains.jet.lang.psi.*; import org.jetbrains.jet.lang.resolve.BindingContext; +import org.jetbrains.jet.lang.resolve.BindingContextUtils; +import org.jetbrains.jet.lang.resolve.scopes.receivers.ReceiverDescriptor; import org.jetbrains.jet.lang.types.JetType; import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns; import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import org.jetbrains.jet.resolve.DescriptorRenderer; -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.Set; +import java.util.*; /** * @author yole */ public abstract class OverrideImplementMethodsHandler implements LanguageCodeInsightActionHandler { - public static List membersFromDescriptors(Iterable missingImplementations) { + public static List membersFromDescriptors( + Iterable missingImplementations, + BindingContext bindingContext + ) { List members = new ArrayList(); for (CallableMemberDescriptor memberDescriptor : missingImplementations) { - members.add(new DescriptorClassMember(memberDescriptor)); + PsiElement psiElement = BindingContextUtils.descriptorToDeclaration(bindingContext, memberDescriptor); + members.add(new DescriptorClassMember(psiElement, memberDescriptor)); } return members; } - @NotNull - public Set collectMethodsToGenerate(@NotNull JetClassOrObject classOrObject) { - BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)classOrObject.getContainingFile()) - .getBindingContext(); - final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); - if (descriptor instanceof MutableClassDescriptor) { - return collectMethodsToGenerate((MutableClassDescriptor)descriptor); - } - return Collections.emptySet(); - } - - protected abstract Set collectMethodsToGenerate(MutableClassDescriptor descriptor); - public static void generateMethods(Editor editor, JetClassOrObject classOrObject, List selectedElements) { @@ -92,7 +82,6 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns ReferenceToClassesShortening.compactReferenceToClasses(elementsToCompact); } - @Nullable private static PsiElement findInsertAfterAnchor(Editor editor, final JetClassBody body) { PsiElement afterAnchor = body.getLBrace(); @@ -243,8 +232,8 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns } private static void addReceiverParameter(CallableDescriptor descriptor, StringBuilder bodyBuilder) { - ReceiverParameterDescriptor receiverParameter = descriptor.getReceiverParameter(); - if (receiverParameter != null) { + ReceiverDescriptor receiverParameter = descriptor.getReceiverParameter(); + if (receiverParameter.exists()) { bodyBuilder.append(receiverParameter.getType()).append("."); } } @@ -270,6 +259,17 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns return visibility != Visibilities.INTERNAL ? visibility.toString() + " ": ""; } + @NotNull + public Set collectMethodsToGenerate(@NotNull JetClassOrObject classOrObject, BindingContext bindingContext) { + final DeclarationDescriptor descriptor = bindingContext.get(BindingContext.DECLARATION_TO_DESCRIPTOR, classOrObject); + if (descriptor instanceof MutableClassDescriptor) { + return collectMethodsToGenerate((MutableClassDescriptor) descriptor); + } + return Collections.emptySet(); + } + + protected abstract Set collectMethodsToGenerate(MutableClassDescriptor descriptor); + private MemberChooser showOverrideImplementChooser(Project project, DescriptorClassMember[] members) { final MemberChooser chooser = new MemberChooser(members, true, true, project); @@ -299,12 +299,15 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns assert classOrObject != null : "ClassObject should be checked in isValidFor method"; - Set missingImplementations = collectMethodsToGenerate(classOrObject); + BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)classOrObject.getContainingFile()) + .getBindingContext(); + + Set missingImplementations = collectMethodsToGenerate(classOrObject, bindingContext); if (missingImplementations.isEmpty() && !implementAll) { HintManager.getInstance().showErrorHint(editor, getNoMethodsFoundHint()); return; } - List members = membersFromDescriptors(missingImplementations); + List members = membersFromDescriptors(missingImplementations, bindingContext); final List selectedElements; if (implementAll) { diff --git a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java index f1618ea0720..a9da5407d30 100644 --- a/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java +++ b/idea/tests/org/jetbrains/jet/plugin/codeInsight/OverrideImplementTest.java @@ -26,8 +26,11 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.jet.lang.descriptors.CallableMemberDescriptor; import org.jetbrains.jet.lang.psi.JetClassOrObject; +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.PluginTestCaseBase; +import org.jetbrains.jet.plugin.project.WholeProjectAnalyzerFacade; import java.util.ArrayList; import java.util.Collections; @@ -70,7 +73,7 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { public void testJavaParameters() { doImplementDirectoryTest(); } - + public void testGenericMethod() { doImplementFileTest(); } @@ -194,7 +197,11 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class); assertNotNull("Caret should be inside class or object", classOrObject); - final Set descriptors = handler.collectMethodsToGenerate(classOrObject); + + final BindingContext bindingContext = WholeProjectAnalyzerFacade + .analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile()) + .getBindingContext(); + final Set descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext); final CallableMemberDescriptor singleToOverride; if (memberToOverride == null) { @@ -222,7 +229,8 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { protected void run(Result result) throws Throwable { OverrideImplementMethodsHandler.generateMethods( myFixture.getEditor(), classOrObject, - OverrideImplementMethodsHandler.membersFromDescriptors(Collections.singletonList(singleToOverride))); + OverrideImplementMethodsHandler + .membersFromDescriptors(Collections.singletonList(singleToOverride), bindingContext)); } }.execute(); } @@ -231,7 +239,11 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { final PsiElement elementAtCaret = myFixture.getFile().findElementAt(myFixture.getEditor().getCaretModel().getOffset()); final JetClassOrObject classOrObject = PsiTreeUtil.getParentOfType(elementAtCaret, JetClassOrObject.class); assertNotNull("Caret should be inside class or object", classOrObject); - final Set descriptors = handler.collectMethodsToGenerate(classOrObject); + + final BindingContext bindingContext = WholeProjectAnalyzerFacade + .analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile()) + .getBindingContext(); + final Set descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext); final ArrayList descriptorsList = new ArrayList(descriptors); Collections.sort(descriptorsList, new Comparator() { @@ -246,7 +258,7 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase { protected void run(Result result) throws Throwable { OverrideImplementMethodsHandler.generateMethods( myFixture.getEditor(), classOrObject, - OverrideImplementMethodsHandler.membersFromDescriptors(descriptorsList)); + OverrideImplementMethodsHandler.membersFromDescriptors(descriptorsList, bindingContext)); } }.execute(); }