Add icons to override/implements dialog

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