diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.java b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.java deleted file mode 100644 index 11331a8cdf4..00000000000 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.core.codeInsight; - -import com.intellij.codeInsight.generation.ClassMemberWithElement; -import com.intellij.codeInsight.generation.MemberChooserObject; -import com.intellij.codeInsight.generation.MemberChooserObjectBase; -import com.intellij.codeInsight.generation.PsiElementMemberChooserObject; -import com.intellij.openapi.util.Iconable; -import com.intellij.psi.PsiClass; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiMember; -import com.intellij.psi.util.PsiTreeUtil; -import kotlin.Unit; -import kotlin.jvm.functions.Function1; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.idea.JetDescriptorIconProvider; -import org.jetbrains.kotlin.psi.JetClass; -import org.jetbrains.kotlin.psi.JetDeclaration; -import org.jetbrains.kotlin.psi.JetFile; -import org.jetbrains.kotlin.psi.JetNamedDeclaration; -import org.jetbrains.kotlin.renderer.*; -import org.jetbrains.kotlin.resolve.DescriptorUtils; - -import javax.swing.*; -import java.util.Collections; - -public class DescriptorClassMember extends MemberChooserObjectBase implements ClassMemberWithElement { - - public static final String NO_PARENT_FOR = "No parent for "; - @NotNull - private final DeclarationDescriptor myDescriptor; - @NotNull - private final PsiElement myPsiElement; - - private static final DescriptorRenderer MEMBER_RENDERER = DescriptorRenderer.Companion.withOptions( - new Function1() { - @Override - public Unit invoke(DescriptorRendererOptions options) { - options.setWithDefinedIn(false); - options.setModifiers(Collections.emptySet()); - options.setStartFromName(true); - options.setNameShortness(NameShortness.SHORT); - return Unit.INSTANCE$; - } - } - ); - - public DescriptorClassMember(@NotNull PsiElement element, @NotNull DeclarationDescriptor descriptor) { - super(getText(descriptor), getIcon(element, descriptor)); - myPsiElement = element; - myDescriptor = descriptor; - } - - private static String getText(DeclarationDescriptor descriptor) { - if (descriptor instanceof ClassDescriptor) { - return RendererPackage.render(DescriptorUtils.getFqNameSafe(descriptor)); - } - else { - return MEMBER_RENDERER.render(descriptor); - } - } - - private static Icon getIcon(PsiElement element, DeclarationDescriptor declarationDescriptor) { - if (element.isValid()) { - boolean isClass = element instanceof PsiClass || element instanceof JetClass; - int flags = isClass ? 0 : Iconable.ICON_FLAG_VISIBILITY; - if (element instanceof JetDeclaration) { // kotlin declaration - // visibility and abstraction better detect by a descriptor - return JetDescriptorIconProvider.getIcon(declarationDescriptor, element, flags); - } - else { - // it is better to show java icons for java code - return element.getIcon(flags); - } - } - - return JetDescriptorIconProvider.getIcon(declarationDescriptor, element, 0); - } - - @Override - public MemberChooserObject getParentNodeDelegate() { - DeclarationDescriptor parent = myDescriptor.getContainingDeclaration(); - PsiElement declaration; - if (myPsiElement instanceof JetDeclaration) { - // kotlin - declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, JetNamedDeclaration.class); - if (declaration == null) { - declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, JetFile.class); - } - } - else { - // java or bytecode - declaration = ((PsiMember) myPsiElement).getContainingClass(); - } - assert parent != null : NO_PARENT_FOR + myDescriptor; - assert declaration != null : NO_PARENT_FOR + myPsiElement; - - if (declaration instanceof JetFile) { - JetFile file = (JetFile) declaration; - return new PsiElementMemberChooserObject(file, file.getName()); - } - - return new DescriptorClassMember(declaration, parent); - } - - public DeclarationDescriptor getDescriptor() { - return myDescriptor; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - DescriptorClassMember that = (DescriptorClassMember) o; - - if (!myDescriptor.equals(that.myDescriptor)) return false; - - return true; - } - - @Override - public int hashCode() { - return myDescriptor.hashCode(); - } - - @Override - public PsiElement getElement() { - return myPsiElement; - } -} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.kt new file mode 100644 index 00000000000..f60057f338e --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/DescriptorClassMember.kt @@ -0,0 +1,125 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.core.codeInsight + +import com.intellij.codeInsight.generation.ClassMemberWithElement +import com.intellij.codeInsight.generation.MemberChooserObject +import com.intellij.codeInsight.generation.MemberChooserObjectBase +import com.intellij.codeInsight.generation.PsiElementMemberChooserObject +import com.intellij.openapi.util.Iconable +import com.intellij.psi.PsiClass +import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMember +import com.intellij.psi.util.PsiTreeUtil +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.DeclarationDescriptor +import org.jetbrains.kotlin.idea.JetDescriptorIconProvider +import org.jetbrains.kotlin.psi.JetClass +import org.jetbrains.kotlin.psi.JetDeclaration +import org.jetbrains.kotlin.psi.JetFile +import org.jetbrains.kotlin.psi.JetNamedDeclaration +import org.jetbrains.kotlin.renderer.DescriptorRenderer +import org.jetbrains.kotlin.renderer.DescriptorRendererModifier +import org.jetbrains.kotlin.renderer.NameShortness +import org.jetbrains.kotlin.renderer.render +import org.jetbrains.kotlin.resolve.DescriptorUtils +import javax.swing.Icon + +public class DescriptorClassMember(private val myPsiElement: PsiElement, public val descriptor: DeclarationDescriptor) : MemberChooserObjectBase(DescriptorClassMember.getText(descriptor), DescriptorClassMember.getIcon(myPsiElement, descriptor)), ClassMemberWithElement { + + override fun getParentNodeDelegate(): MemberChooserObject { + val parent = descriptor.containingDeclaration + var declaration: PsiElement? + if (myPsiElement is JetDeclaration) { + // kotlin + declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, javaClass()) + if (declaration == null) { + declaration = PsiTreeUtil.getStubOrPsiParentOfType(myPsiElement, javaClass()) + } + } + else { + // java or bytecode + declaration = (myPsiElement as PsiMember).containingClass + } + assert(parent != null) { "$NO_PARENT_FOR$descriptor" } + assert(declaration != null) { "$NO_PARENT_FOR$myPsiElement" } + + if (declaration is JetFile) { + return PsiElementMemberChooserObject(declaration, declaration.name) + } + + return DescriptorClassMember(declaration!!, parent!!) + } + + override fun equals(other: Any?): Boolean { + if (this === other) return true + if (other == null || javaClass != other.javaClass) return false + + val that = other as DescriptorClassMember + + if (descriptor != that.descriptor) return false + + return true + } + + override fun hashCode(): Int { + return descriptor.hashCode() + } + + override fun getElement(): PsiElement { + return myPsiElement + } + + companion object { + + public val NO_PARENT_FOR: String = "No parent for " + + private val MEMBER_RENDERER = DescriptorRenderer.withOptions { + withDefinedIn = false + modifiers = emptySet() + startFromName = true + nameShortness = NameShortness.SHORT + } + + private fun getText(descriptor: DeclarationDescriptor): String { + if (descriptor is ClassDescriptor) { + return DescriptorUtils.getFqNameSafe(descriptor).render() + } + else { + return MEMBER_RENDERER.render(descriptor) + } + } + + private fun getIcon(element: PsiElement, declarationDescriptor: DeclarationDescriptor): Icon { + if (element.isValid) { + val isClass = element is PsiClass || element is JetClass + val flags = if (isClass) 0 else Iconable.ICON_FLAG_VISIBILITY + if (element is JetDeclaration) { + // kotlin declaration + // visibility and abstraction better detect by a descriptor + return JetDescriptorIconProvider.getIcon(declarationDescriptor, element, flags) + } + else { + // it is better to show java icons for java code + return element.getIcon(flags) + } + } + + return JetDescriptorIconProvider.getIcon(declarationDescriptor, element, 0) + } + } +} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.java b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.java deleted file mode 100644 index 2062876e899..00000000000 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.core.codeInsight; - -import com.intellij.codeInsight.intention.IntentionAction; -import com.intellij.openapi.editor.Editor; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.idea.JetBundle; -import org.jetbrains.kotlin.resolve.OverrideResolver; - -import java.util.Set; - -public class ImplementMethodsHandler extends OverrideImplementMethodsHandler implements IntentionAction { - @Override - protected Set collectMethodsToGenerate(@NotNull ClassDescriptor descriptor) { - return OverrideResolver.getMissingImplementations(descriptor); - } - - @Override - protected String getChooserTitle() { - return "Implement Members"; - } - - @Override - protected String getNoMethodsFoundHint() { - return "No methods to implement have been found"; - } - - @NotNull - @Override - public String getText() { - return JetBundle.message("implement.members"); - } - - @NotNull - @Override - public String getFamilyName() { - return JetBundle.message("implement.members"); - } - - @Override - public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { - return isValidFor(editor, file); - } -} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.kt new file mode 100644 index 00000000000..ab4e02d6190 --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/ImplementMethodsHandler.kt @@ -0,0 +1,52 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.core.codeInsight + +import com.intellij.codeInsight.intention.IntentionAction +import com.intellij.openapi.editor.Editor +import com.intellij.openapi.project.Project +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.idea.JetBundle +import org.jetbrains.kotlin.resolve.OverrideResolver + +public class ImplementMethodsHandler : OverrideImplementMethodsHandler(), IntentionAction { + override fun collectMethodsToGenerate(descriptor: ClassDescriptor): Set { + return OverrideResolver.getMissingImplementations(descriptor) + } + + override fun getChooserTitle(): String { + return "Implement Members" + } + + override fun getNoMethodsFoundHint(): String { + return "No methods to implement have been found" + } + + override fun getText(): String { + return JetBundle.message("implement.members") + } + + override fun getFamilyName(): String { + return JetBundle.message("implement.members") + } + + override fun isAvailable(project: Project, editor: Editor, file: PsiFile): Boolean { + return isValidFor(editor, file) + } +} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideImplementMethodsHandler.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideImplementMethodsHandler.kt index ab571fcc557..2ac8ab4c4e7 100644 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideImplementMethodsHandler.kt +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideImplementMethodsHandler.kt @@ -221,7 +221,7 @@ public abstract class OverrideImplementMethodsHandler : LanguageCodeInsightActio classOrObject: JetClassOrObject): List { val overridingMembers = ArrayList() for (selectedElement in selectedElements) { - val descriptor = selectedElement.getDescriptor() + val descriptor = selectedElement.descriptor if (descriptor is SimpleFunctionDescriptor) { overridingMembers.add(overrideFunction(classOrObject, descriptor)) } diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.java b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.java deleted file mode 100644 index f7d3ca18584..00000000000 --- a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2010-2015 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.jetbrains.kotlin.idea.core.codeInsight; - -import com.google.common.collect.LinkedHashMultimap; -import com.google.common.collect.Multimap; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor; -import org.jetbrains.kotlin.descriptors.ClassDescriptor; -import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; -import org.jetbrains.kotlin.resolve.OverrideResolver; -import org.jetbrains.kotlin.resolve.OverridingUtil; -import org.jetbrains.kotlin.resolve.calls.callResolverUtil.CallResolverUtilPackage; -import org.jetbrains.kotlin.types.JetType; - -import java.util.HashSet; -import java.util.LinkedHashSet; -import java.util.Set; - -import static org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE; - -public class OverrideMethodsHandler extends OverrideImplementMethodsHandler { - @Override - protected Set collectMethodsToGenerate(@NotNull ClassDescriptor descriptor) { - Set superMethods = collectSuperMethods(descriptor); - for (DeclarationDescriptor member : descriptor.getDefaultType().getMemberScope().getAllDescriptors()) { - if (member instanceof CallableMemberDescriptor) { - CallableMemberDescriptor callable = (CallableMemberDescriptor) member; - if (callable.getKind() == CallableMemberDescriptor.Kind.DECLARATION) { - superMethods.removeAll(callable.getOverriddenDescriptors()); - } - } - } - Set result = new HashSet(); - for (CallableMemberDescriptor superMethod : superMethods) { - if (superMethod.getModality().isOverridable()) { - if (!CallResolverUtilPackage.isOrOverridesSynthesized(superMethod)) { - result.add(superMethod); - } - } - } - return result; - } - - @NotNull - private static Set collectSuperMethods(@NotNull ClassDescriptor classDescriptor) { - Set inheritedFunctions = new LinkedHashSet(); - for (JetType supertype : classDescriptor.getTypeConstructor().getSupertypes()) { - for (DeclarationDescriptor descriptor : supertype.getMemberScope().getAllDescriptors()) { - if (descriptor instanceof CallableMemberDescriptor) { - inheritedFunctions.add((CallableMemberDescriptor) descriptor); - } - } - } - - // Only those actually inherited - Set filteredMembers = OverrideResolver.filterOutOverridden(inheritedFunctions); - - // Group members with "the same" signature - Multimap factoredMembers = LinkedHashMultimap.create(); - for (CallableMemberDescriptor one : filteredMembers) { - if (factoredMembers.values().contains(one)) continue; - for (CallableMemberDescriptor another : filteredMembers) { -// if (one == another) continue; - factoredMembers.put(one, one); - if (OverridingUtil.DEFAULT.isOverridableBy(one, another).getResult() == OVERRIDABLE - || OverridingUtil.DEFAULT.isOverridableBy(another, one).getResult() == OVERRIDABLE) { - factoredMembers.put(one, another); - } - } - } - - return factoredMembers.keySet(); - } - - @Override - protected String getChooserTitle() { - return "Override Members"; - } - - @Override - protected String getNoMethodsFoundHint() { - return "No methods to override have been found"; - } -} diff --git a/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.kt b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.kt new file mode 100644 index 00000000000..4d6de32bc38 --- /dev/null +++ b/idea/idea-core/src/org/jetbrains/kotlin/idea/core/codeInsight/OverrideMethodsHandler.kt @@ -0,0 +1,86 @@ +/* + * Copyright 2010-2015 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.jetbrains.kotlin.idea.core.codeInsight + +import com.google.common.collect.LinkedHashMultimap +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.resolve.OverrideResolver +import org.jetbrains.kotlin.resolve.OverridingUtil +import org.jetbrains.kotlin.resolve.OverridingUtil.OverrideCompatibilityInfo.Result.OVERRIDABLE +import org.jetbrains.kotlin.resolve.calls.callResolverUtil.isOrOverridesSynthesized +import java.util.HashSet +import java.util.LinkedHashSet + +public class OverrideMethodsHandler : OverrideImplementMethodsHandler() { + override fun collectMethodsToGenerate(descriptor: ClassDescriptor): Set { + val superMethods = collectSuperMethods(descriptor) + for (member in descriptor.defaultType.memberScope.getAllDescriptors()) { + if (member is CallableMemberDescriptor) { + if (member.kind == CallableMemberDescriptor.Kind.DECLARATION) { + superMethods.removeAll(member.overriddenDescriptors) + } + } + } + val result = HashSet() + for (superMethod in superMethods) { + if (superMethod.modality.isOverridable) { + if (!isOrOverridesSynthesized(superMethod)) { + result.add(superMethod) + } + } + } + return result + } + + private fun collectSuperMethods(classDescriptor: ClassDescriptor): MutableSet { + val inheritedFunctions = LinkedHashSet() + for (supertype in classDescriptor.typeConstructor.supertypes) { + for (descriptor in supertype.memberScope.getAllDescriptors()) { + if (descriptor is CallableMemberDescriptor) { + inheritedFunctions.add(descriptor) + } + } + } + + // Only those actually inherited + val filteredMembers = OverrideResolver.filterOutOverridden(inheritedFunctions) + + // Group members with "the same" signature + val factoredMembers = LinkedHashMultimap.create() + for (one in filteredMembers) { + if (factoredMembers.values().contains(one)) continue + for (another in filteredMembers) { + // if (one == another) continue; + factoredMembers.put(one, one) + if (OverridingUtil.DEFAULT.isOverridableBy(one, another).result == OVERRIDABLE || OverridingUtil.DEFAULT.isOverridableBy(another, one).result == OVERRIDABLE) { + factoredMembers.put(one, another) + } + } + } + + return factoredMembers.keySet() + } + + override fun getChooserTitle(): String { + return "Override Members" + } + + override fun getNoMethodsFoundHint(): String { + return "No methods to override have been found" + } +}