Icons are showed for all members from all places

This commit is contained in:
Vladimir Rudev
2012-11-02 00:22:17 +04:00
committed by Nikolay Krasko
parent 98eefd0f1c
commit e17b310411
3 changed files with 66 additions and 35 deletions
@@ -18,15 +18,16 @@ package org.jetbrains.jet.plugin.codeInsight;
import com.intellij.codeInsight.generation.ClassMemberWithElement; import com.intellij.codeInsight.generation.ClassMemberWithElement;
import com.intellij.codeInsight.generation.MemberChooserObject; import com.intellij.codeInsight.generation.MemberChooserObject;
import com.intellij.psi.PsiClass;
import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiMember; import com.intellij.psi.PsiMember;
import com.intellij.psi.util.PsiTreeUtil; import com.intellij.psi.util.PsiTreeUtil;
import com.intellij.ui.SimpleColoredComponent; import com.intellij.ui.SimpleColoredComponent;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor; import org.jetbrains.jet.lang.descriptors.DeclarationDescriptor;
import org.jetbrains.jet.lang.psi.JetDeclaration; import org.jetbrains.jet.lang.psi.JetDeclaration;
import org.jetbrains.jet.lang.psi.JetNamedDeclaration; import org.jetbrains.jet.lang.psi.JetNamedDeclaration;
import org.jetbrains.jet.plugin.JetDescriptorIconProvider;
import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.resolve.DescriptorRenderer;
import javax.swing.*; import javax.swing.*;
@@ -39,38 +40,45 @@ public class DescriptorClassMember implements ClassMemberWithElement {
public static final String NO_PARENT_FOR = "No parent for "; public static final String NO_PARENT_FOR = "No parent for ";
@NotNull @NotNull
private final DeclarationDescriptor myDescriptor; private final DeclarationDescriptor myDescriptor;
@NotNull
private final PsiElement myPsiElement; private final PsiElement myPsiElement;
@Nullable
private final Icon icon;
public DescriptorClassMember(PsiElement element, @NotNull DeclarationDescriptor descriptor) { public DescriptorClassMember(@NotNull PsiElement element, @NotNull DeclarationDescriptor descriptor) {
myPsiElement = element; myPsiElement = element;
myDescriptor = descriptor; myDescriptor = descriptor;
if (myPsiElement.isValid()) {
boolean isClass = myPsiElement instanceof PsiClass;
int flags = isClass ? 0 : 3;
icon = myPsiElement.getIcon(flags);
}
else {
icon = null;
}
} }
@Override @Override
public MemberChooserObject getParentNodeDelegate() { public MemberChooserObject getParentNodeDelegate() {
final DeclarationDescriptor parent = myDescriptor.getContainingDeclaration(); final DeclarationDescriptor parent = myDescriptor.getContainingDeclaration();
PsiElement declaration = null; PsiElement declaration;
if (myPsiElement instanceof JetDeclaration) { if (myPsiElement instanceof JetDeclaration) {
// kotlin // kotlin
declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, JetNamedDeclaration.class); declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, JetNamedDeclaration.class);
} }
else if (myPsiElement != null) { else {
// java or bytecode // java or bytecode
declaration = ((PsiMember) myPsiElement).getContainingClass(); declaration = ((PsiMember) myPsiElement).getContainingClass();
} }
assert parent != null : NO_PARENT_FOR + myDescriptor; assert parent != null : NO_PARENT_FOR + myDescriptor;
assert declaration != null : String.format("No parent of type %s for %s", JetNamedDeclaration.class.getSimpleName(), myPsiElement);
return new DescriptorClassMember(declaration, parent); return new DescriptorClassMember(declaration, 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 != null && myPsiElement.isValid()) { component.setIcon(icon);
component.setIcon(myPsiElement.getIcon(0));
}
else {
component.setIcon(JetDescriptorIconProvider.getBaseIcon(myDescriptor));
}
} }
@Override @Override
@@ -38,6 +38,7 @@ 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.plugin.references.StandardLibraryReferenceResolver;
import org.jetbrains.jet.resolve.DescriptorRenderer; import org.jetbrains.jet.resolve.DescriptorRenderer;
import java.util.*; import java.util.*;
@@ -46,27 +47,43 @@ import java.util.*;
* @author yole * @author yole
*/ */
public abstract class OverrideImplementMethodsHandler implements LanguageCodeInsightActionHandler { public abstract class OverrideImplementMethodsHandler implements LanguageCodeInsightActionHandler {
public static PsiElement getDeclaration(JetFile file, DeclarationDescriptor descriptor, BindingContext bindingContext) {
Collection<PsiElement> elements = BindingContextUtils.descriptorToDeclarations(bindingContext, descriptor);
if (elements.isEmpty()) {
StandardLibraryReferenceResolver libraryReferenceResolver =
file.getProject().getComponent(StandardLibraryReferenceResolver.class);
elements = libraryReferenceResolver.resolveStandardLibrarySymbol(descriptor);
}
if (!elements.isEmpty()) {
return elements.iterator().next();
}
return null;
}
public static List<DescriptorClassMember> membersFromDescriptors( public static List<DescriptorClassMember> membersFromDescriptors(
Iterable<CallableMemberDescriptor> missingImplementations, JetFile file, Iterable<CallableMemberDescriptor> missingImplementations,
BindingContext bindingContext BindingContext bindingContext
) { ) {
List<DescriptorClassMember> members = new ArrayList<DescriptorClassMember>(); List<DescriptorClassMember> members = new ArrayList<DescriptorClassMember>();
for (CallableMemberDescriptor memberDescriptor : missingImplementations) { for (CallableMemberDescriptor memberDescriptor : missingImplementations) {
List<PsiElement> psiElements = BindingContextUtils.descriptorToDeclarations(bindingContext, memberDescriptor);
DescriptorClassMember member; PsiElement declaration = getDeclaration(file, memberDescriptor, bindingContext);
if (psiElements.isEmpty()) { assert declaration != null : "Can not find declaration for descriptor " + memberDescriptor;
member = new DescriptorClassMember(null, memberDescriptor); DescriptorClassMember member = new DescriptorClassMember(declaration, memberDescriptor);
} else {
member = new DescriptorClassMember(psiElements.get(0), memberDescriptor);
}
members.add(member); members.add(member);
} }
return members; return members;
} }
public static void generateMethods(Editor editor, public static void generateMethods(
Editor editor,
JetClassOrObject classOrObject, JetClassOrObject classOrObject,
List<DescriptorClassMember> selectedElements) { List<DescriptorClassMember> selectedElements
) {
final JetClassBody body = classOrObject.getBody(); final JetClassBody body = classOrObject.getBody();
if (body == null) { if (body == null) {
return; return;
@@ -79,11 +96,11 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
} }
List<JetElement> elementsToCompact = new ArrayList<JetElement>(); List<JetElement> elementsToCompact = new ArrayList<JetElement>();
final JetFile file = (JetFile)classOrObject.getContainingFile(); final JetFile file = (JetFile) classOrObject.getContainingFile();
for (JetElement element : generateOverridingMembers(selectedElements, file)) { for (JetElement element : generateOverridingMembers(selectedElements, file)) {
PsiElement added = body.addAfter(element, afterAnchor); PsiElement added = body.addAfter(element, afterAnchor);
afterAnchor = added; afterAnchor = added;
elementsToCompact.add((JetElement)added); elementsToCompact.add((JetElement) added);
} }
ReferenceToClassesShortening.compactReferenceToClasses(elementsToCompact); ReferenceToClassesShortening.compactReferenceToClasses(elementsToCompact);
} }
@@ -116,10 +133,10 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
for (DescriptorClassMember selectedElement : selectedElements) { for (DescriptorClassMember selectedElement : selectedElements) {
final DeclarationDescriptor descriptor = selectedElement.getDescriptor(); final DeclarationDescriptor descriptor = selectedElement.getDescriptor();
if (descriptor instanceof SimpleFunctionDescriptor) { if (descriptor instanceof SimpleFunctionDescriptor) {
overridingMembers.add(overrideFunction(file.getProject(), (SimpleFunctionDescriptor)descriptor)); overridingMembers.add(overrideFunction(file.getProject(), (SimpleFunctionDescriptor) descriptor));
} }
else if (descriptor instanceof PropertyDescriptor) { else if (descriptor instanceof PropertyDescriptor) {
overridingMembers.add(overrideProperty(file.getProject(), (PropertyDescriptor)descriptor)); overridingMembers.add(overrideProperty(file.getProject(), (PropertyDescriptor) descriptor));
} }
} }
return overridingMembers; return overridingMembers;
@@ -176,7 +193,8 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound)) { if (!KotlinBuiltIns.getInstance().getDefaultBound().equals(upperBound)) {
if (firstUpperBound) { if (firstUpperBound) {
bodyBuilder.append(upperBoundText); bodyBuilder.append(upperBoundText);
} else { }
else {
whereRestrictions.add(param.getName() + upperBoundText); whereRestrictions.add(param.getName() + upperBoundText);
} }
} }
@@ -262,7 +280,7 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
private static String displayableVisibility(MemberDescriptor descriptor) { private static String displayableVisibility(MemberDescriptor descriptor) {
Visibility visibility = descriptor.getVisibility(); Visibility visibility = descriptor.getVisibility();
return visibility != Visibilities.INTERNAL ? visibility.toString() + " ": ""; return visibility != Visibilities.INTERNAL ? visibility.toString() + " " : "";
} }
@NotNull @NotNull
@@ -276,8 +294,10 @@ public abstract class OverrideImplementMethodsHandler implements LanguageCodeIns
protected abstract Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor); protected abstract Set<CallableMemberDescriptor> collectMethodsToGenerate(MutableClassDescriptor descriptor);
private MemberChooser<DescriptorClassMember> showOverrideImplementChooser(Project project, private MemberChooser<DescriptorClassMember> showOverrideImplementChooser(
DescriptorClassMember[] members) { Project project,
DescriptorClassMember[] members
) {
final MemberChooser<DescriptorClassMember> chooser = new MemberChooser<DescriptorClassMember>(members, true, true, project); final MemberChooser<DescriptorClassMember> chooser = new MemberChooser<DescriptorClassMember>(members, true, true, project);
chooser.setTitle(getChooserTitle()); chooser.setTitle(getChooserTitle());
chooser.show(); chooser.show();
@@ -305,15 +325,16 @@ 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";
BindingContext bindingContext = WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile)classOrObject.getContainingFile()) BindingContext bindingContext =
.getBindingContext(); WholeProjectAnalyzerFacade.analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile())
.getBindingContext();
Set<CallableMemberDescriptor> missingImplementations = collectMethodsToGenerate(classOrObject, bindingContext); 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, bindingContext); List<DescriptorClassMember> members = membersFromDescriptors((JetFile) file, missingImplementations, bindingContext);
final List<DescriptorClassMember> selectedElements; final List<DescriptorClassMember> selectedElements;
if (implementAll) { if (implementAll) {
@@ -198,8 +198,9 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase {
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 JetFile jetFile = (JetFile) classOrObject.getContainingFile();
final BindingContext bindingContext = WholeProjectAnalyzerFacade final BindingContext bindingContext = WholeProjectAnalyzerFacade
.analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile()) .analyzeProjectWithCacheOnAFile(jetFile)
.getBindingContext(); .getBindingContext();
final Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext); final Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext);
@@ -230,7 +231,7 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase {
OverrideImplementMethodsHandler.generateMethods( OverrideImplementMethodsHandler.generateMethods(
myFixture.getEditor(), classOrObject, myFixture.getEditor(), classOrObject,
OverrideImplementMethodsHandler OverrideImplementMethodsHandler
.membersFromDescriptors(Collections.singletonList(singleToOverride), bindingContext)); .membersFromDescriptors(jetFile, Collections.singletonList(singleToOverride), bindingContext));
} }
}.execute(); }.execute();
} }
@@ -240,8 +241,9 @@ public class OverrideImplementTest extends LightCodeInsightFixtureTestCase {
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 JetFile jetFile = (JetFile) classOrObject.getContainingFile();
final BindingContext bindingContext = WholeProjectAnalyzerFacade final BindingContext bindingContext = WholeProjectAnalyzerFacade
.analyzeProjectWithCacheOnAFile((JetFile) classOrObject.getContainingFile()) .analyzeProjectWithCacheOnAFile(jetFile)
.getBindingContext(); .getBindingContext();
final Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext); final Set<CallableMemberDescriptor> descriptors = handler.collectMethodsToGenerate(classOrObject, bindingContext);
@@ -258,7 +260,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, bindingContext)); OverrideImplementMethodsHandler.membersFromDescriptors(jetFile, descriptorsList, bindingContext));
} }
}.execute(); }.execute();
} }