From e303a38f9e043c0db605b7380e367567250a8869 Mon Sep 17 00:00:00 2001 From: Alexey Sedunov Date: Tue, 7 Jul 2015 18:43:09 +0300 Subject: [PATCH] Member Info: Extended implementation (for Pull Up/Push Down) --- .../org/jetbrains/kotlin/types/TypeUtils.kt | 3 +- .../{ => memberInfo}/KotlinMemberInfo.kt | 15 +++- .../memberInfo/KotlinMemberInfoStorage.kt | 79 ++++++++++++++++++ .../KotlinMemberSelectionPanel.kt | 3 +- .../memberInfo/KotlinMemberSelectionTable.kt | 82 +++++++++++++++++++ .../MoveKotlinTopLevelDeclarationsDialog.java | 6 +- .../ui/KotlinMemberSelectionTable.kt | 41 ---------- 7 files changed, 178 insertions(+), 51 deletions(-) rename idea/src/org/jetbrains/kotlin/idea/refactoring/{ => memberInfo}/KotlinMemberInfo.kt (67%) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfoStorage.kt rename idea/src/org/jetbrains/kotlin/idea/refactoring/{ui => memberInfo}/KotlinMemberSelectionPanel.kt (93%) create mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionTable.kt delete mode 100644 idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionTable.kt diff --git a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt index 32bb997691e..ab40691203b 100644 --- a/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt +++ b/core/descriptors/src/org/jetbrains/kotlin/types/TypeUtils.kt @@ -45,7 +45,8 @@ public fun JetType.nullability(): TypeNullability { fun JetType.makeNullable() = TypeUtils.makeNullable(this) fun JetType.makeNotNullable() = TypeUtils.makeNotNullable(this) -fun JetType.supertypes(): Set = TypeUtils.getAllSupertypes(this) +fun JetType.immediateSupertypes(): Collection = TypeUtils.getImmediateSupertypes(this) +fun JetType.supertypes(): Collection = TypeUtils.getAllSupertypes(this) fun JetType.isNothing(): Boolean = KotlinBuiltIns.isNothing(this) fun JetType.isUnit(): Boolean = KotlinBuiltIns.isUnit(this) diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinMemberInfo.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfo.kt similarity index 67% rename from idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinMemberInfo.kt rename to idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfo.kt index 848cf7fabbd..5356f422296 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/KotlinMemberInfo.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfo.kt @@ -14,10 +14,11 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.refactoring +package org.jetbrains.kotlin.idea.refactoring.memberInfo import com.intellij.refactoring.classMembers.MemberInfoBase -import com.intellij.refactoring.classMembers.MemberInfoModel +import org.jetbrains.kotlin.descriptors.CallableMemberDescriptor +import org.jetbrains.kotlin.descriptors.Modality import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers import org.jetbrains.kotlin.psi.JetFile @@ -25,7 +26,13 @@ import org.jetbrains.kotlin.psi.JetNamedDeclaration public class KotlinMemberInfo(member: JetNamedDeclaration) : MemberInfoBase(member) { init { + val memberDescriptor = member.resolveToDescriptor() isStatic = member.getParent() is JetFile - displayName = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(member.resolveToDescriptor()) + displayName = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(memberDescriptor) + + val overriddenDescriptors = (memberDescriptor as? CallableMemberDescriptor)?.getOverriddenDescriptors() ?: emptySet() + if (overriddenDescriptors.isNotEmpty()) { + overrides = overriddenDescriptors.any { it.getModality() != Modality.ABSTRACT } + } } -} \ No newline at end of file +} diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfoStorage.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfoStorage.kt new file mode 100644 index 00000000000..e3fa91be9f9 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberInfoStorage.kt @@ -0,0 +1,79 @@ +/* + * 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.refactoring.memberInfo + +import com.intellij.refactoring.classMembers.AbstractMemberInfoStorage +import org.jetbrains.kotlin.descriptors.ClassDescriptor +import org.jetbrains.kotlin.descriptors.FunctionDescriptor +import org.jetbrains.kotlin.descriptors.PropertyDescriptor +import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor +import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde +import org.jetbrains.kotlin.psi.JetClassOrObject +import org.jetbrains.kotlin.psi.JetConstructor +import org.jetbrains.kotlin.psi.JetNamedDeclaration +import org.jetbrains.kotlin.psi.JetObjectDeclaration +import org.jetbrains.kotlin.resolve.DescriptorUtils +import org.jetbrains.kotlin.resolve.OverloadUtil +import org.jetbrains.kotlin.resolve.source.getPsi +import org.jetbrains.kotlin.types.typeUtil.immediateSupertypes +import java.util.ArrayList + +public class KotlinMemberInfoStorage( + classOrObject: JetClassOrObject, + filter: (JetNamedDeclaration) -> Boolean = { true } +): AbstractMemberInfoStorage(classOrObject, filter) { + override fun memberConflict(member1: JetNamedDeclaration, member: JetNamedDeclaration): Boolean { + val descriptor1 = member1.resolveToDescriptor() + val descriptor = member.resolveToDescriptor() + if (descriptor1.getName() != descriptor.getName()) return false + + return when { + descriptor1 is FunctionDescriptor && descriptor is FunctionDescriptor -> { + !OverloadUtil.isOverloadable(descriptor1, descriptor).isSuccess() + } + descriptor1 is PropertyDescriptor && descriptor is PropertyDescriptor, + descriptor1 is ClassDescriptor && descriptor is ClassDescriptor -> true + else -> false + } + } + + override fun buildSubClassesMap(aClass: JetClassOrObject) { + val classDescriptor = aClass.resolveToDescriptor() as ClassDescriptor + val classType = classDescriptor.getDefaultType() + for (supertype in classType.immediateSupertypes()) { + val superClass = supertype.getConstructor().getDeclarationDescriptor()?.getSource()?.getPsi() as? JetClassOrObject + ?: continue + getSubclasses(superClass).add(aClass) + buildSubClassesMap(superClass) + } + } + + override fun isInheritor(baseClass: JetClassOrObject, aClass: JetClassOrObject): Boolean { + val baseDescriptor = baseClass.resolveToDescriptor() as ClassDescriptor + val currentDescriptor = aClass.resolveToDescriptor() as ClassDescriptor + return DescriptorUtils.isSubclass(currentDescriptor, baseDescriptor) + } + + override fun extractClassMembers(aClass: JetClassOrObject, temp: ArrayList) { + aClass.getDeclarations() + .filter { it is JetNamedDeclaration + && it !is JetConstructor<*> + && !(it is JetObjectDeclaration && it.isCompanion()) + && myFilter.includeMember(it) } + .mapTo(temp) { KotlinMemberInfo(it as JetNamedDeclaration) } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionPanel.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionPanel.kt similarity index 93% rename from idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionPanel.kt rename to idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionPanel.kt index 829219b13af..581646a832b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionPanel.kt +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionPanel.kt @@ -14,12 +14,11 @@ * limitations under the License. */ -package org.jetbrains.kotlin.idea.refactoring.ui +package org.jetbrains.kotlin.idea.refactoring.memberInfo import com.intellij.refactoring.ui.AbstractMemberSelectionPanel import com.intellij.ui.ScrollPaneFactory import com.intellij.ui.SeparatorFactory -import org.jetbrains.kotlin.idea.refactoring.KotlinMemberInfo import org.jetbrains.kotlin.psi.JetNamedDeclaration import java.awt.BorderLayout diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionTable.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionTable.kt new file mode 100644 index 00000000000..8b6020e87a5 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/memberInfo/KotlinMemberSelectionTable.kt @@ -0,0 +1,82 @@ +/* + * 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.refactoring.memberInfo + +import com.intellij.icons.AllIcons +import com.intellij.psi.PsiMethod +import com.intellij.psi.PsiModifier +import com.intellij.refactoring.classMembers.MemberInfoModel +import com.intellij.refactoring.ui.AbstractMemberSelectionTable +import com.intellij.refactoring.ui.MemberSelectionTable +import com.intellij.ui.RowIcon +import org.jetbrains.kotlin.idea.JetIconProvider +import org.jetbrains.kotlin.lexer.JetTokens +import org.jetbrains.kotlin.psi.JetNamedDeclaration +import org.jetbrains.kotlin.psi.JetNamedFunction +import org.jetbrains.kotlin.psi.JetProperty +import javax.swing.Icon + +public class KotlinMemberSelectionTable( + memberInfos: List, + memberInfoModel: MemberInfoModel?, + abstractColumnHeader: String? +) : AbstractMemberSelectionTable(memberInfos, memberInfoModel, abstractColumnHeader) { + override fun getAbstractColumnValue(memberInfo: KotlinMemberInfo): Any? { + if (memberInfo.isStatic()) return null + + val member = memberInfo.getMember() + if (member !is JetNamedFunction && member !is JetProperty) return null + + if (member.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { + myMemberInfoModel.isFixedAbstract(memberInfo)?.let { return it } + } + if (myMemberInfoModel.isAbstractEnabled(memberInfo)) return memberInfo.isToAbstract() + return myMemberInfoModel.isAbstractWhenDisabled(memberInfo) + } + + override fun isAbstractColumnEditable(rowIndex: Int): Boolean { + val memberInfo = myMemberInfos.get(rowIndex) + + if (memberInfo.isStatic()) return false + + val member = memberInfo.getMember() + if (member !is JetNamedFunction && member !is JetProperty) return false + + if (member.hasModifier(JetTokens.ABSTRACT_KEYWORD)) { + myMemberInfoModel.isFixedAbstract(memberInfo)?.let { return false } + } + + return memberInfo.isChecked() && myMemberInfoModel.isAbstractEnabled(memberInfo) + } + + override fun setVisibilityIcon(memberInfo: KotlinMemberInfo, icon: RowIcon) { + icon.setIcon(JetIconProvider.getVisibilityIcon(memberInfo.getMember().getModifierList()), 1); + } + + override fun getOverrideIcon(memberInfo: KotlinMemberInfo): Icon? { + val defaultIcon = AbstractMemberSelectionTable.EMPTY_OVERRIDE_ICON + + val member = memberInfo.getMember() + if (member !is JetNamedFunction && member !is JetProperty) return defaultIcon + + return when (memberInfo.getOverrides()) { + true -> AllIcons.General.OverridingMethod + false -> AllIcons.General.ImplementingMethod + else -> defaultIcon + } + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java index 9cdeb825807..93c4b0bb12b 100644 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java +++ b/idea/src/org/jetbrains/kotlin/idea/refactoring/move/moveTopLevelDeclarations/ui/MoveKotlinTopLevelDeclarationsDialog.java @@ -61,11 +61,11 @@ import org.jetbrains.kotlin.idea.JetFileType; import org.jetbrains.kotlin.idea.core.CorePackage; import org.jetbrains.kotlin.idea.core.refactoring.RefactoringPackage; import org.jetbrains.kotlin.idea.refactoring.JetRefactoringBundle; -import org.jetbrains.kotlin.idea.refactoring.KotlinMemberInfo; +import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberInfo; import org.jetbrains.kotlin.idea.refactoring.move.MovePackage; import org.jetbrains.kotlin.idea.refactoring.move.moveTopLevelDeclarations.*; -import org.jetbrains.kotlin.idea.refactoring.ui.KotlinMemberSelectionPanel; -import org.jetbrains.kotlin.idea.refactoring.ui.KotlinMemberSelectionTable; +import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionPanel; +import org.jetbrains.kotlin.idea.refactoring.memberInfo.KotlinMemberSelectionTable; import org.jetbrains.kotlin.idea.util.application.ApplicationPackage; import org.jetbrains.kotlin.name.FqName; import org.jetbrains.kotlin.psi.JetFile; diff --git a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionTable.kt b/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionTable.kt deleted file mode 100644 index 5284d400c20..00000000000 --- a/idea/src/org/jetbrains/kotlin/idea/refactoring/ui/KotlinMemberSelectionTable.kt +++ /dev/null @@ -1,41 +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.refactoring.ui - -import com.intellij.refactoring.classMembers.MemberInfoModel -import com.intellij.refactoring.ui.AbstractMemberSelectionTable -import com.intellij.ui.RowIcon -import com.intellij.util.IconUtil -import org.jetbrains.kotlin.idea.JetIconProvider -import org.jetbrains.kotlin.idea.refactoring.KotlinMemberInfo -import org.jetbrains.kotlin.psi.JetNamedDeclaration - -public class KotlinMemberSelectionTable( - memberInfos: List, - memberInfoModel: MemberInfoModel?, - abstractColumnHeader: String? -) : AbstractMemberSelectionTable(memberInfos, memberInfoModel, abstractColumnHeader) { - override fun getAbstractColumnValue(memberInfo: KotlinMemberInfo) = null - - override fun isAbstractColumnEditable(rowIndex: Int) = false - - override fun setVisibilityIcon(memberInfo: KotlinMemberInfo, icon: RowIcon) { - icon.setIcon(JetIconProvider.getVisibilityIcon(memberInfo.getMember().getModifierList()), 1); - } - - override fun getOverrideIcon(memberInfo: KotlinMemberInfo) = AbstractMemberSelectionTable.EMPTY_OVERRIDE_ICON -} \ No newline at end of file