Code simplifications

This commit is contained in:
Valentin Kipyatkov
2015-10-15 22:25:55 +03:00
parent 1a13ec0b00
commit ff13bcce1f
3 changed files with 50 additions and 97 deletions
@@ -16,9 +16,6 @@
package org.jetbrains.kotlin.idea.actions
import com.intellij.codeInsight.hint.QuestionAction
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.Editor
import com.intellij.openapi.project.Project
import com.intellij.openapi.ui.popup.JBPopupFactory
@@ -36,10 +33,10 @@ import org.jetbrains.kotlin.idea.JetBundle
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.idea.util.ShortenReferences
import org.jetbrains.kotlin.idea.util.application.executeWriteCommand
import org.jetbrains.kotlin.psi.JetClass
import org.jetbrains.kotlin.psi.JetNamedFunction
import org.jetbrains.kotlin.psi.JetPsiFactory
import java.util.*
/**
* Changes method signature to one of provided signatures.
@@ -48,14 +45,8 @@ import java.util.*
class JetAddFunctionToClassifierAction(
private val project: Project,
private val editor: Editor?,
functionsToAdd: List<FunctionDescriptor>
) : QuestionAction {
private val functionsToAdd: List<FunctionDescriptor>
init {
this.functionsToAdd = ArrayList(functionsToAdd)
}
private val functionsToAdd: List<FunctionDescriptor>
) {
private fun addFunction(
project: Project,
typeDescriptor: ClassDescriptor,
@@ -66,57 +57,40 @@ class JetAddFunctionToClassifierAction(
PsiDocumentManager.getInstance(project).commitAllDocuments()
val classifierDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, typeDescriptor) as JetClass
CommandProcessor.getInstance().executeCommand(project, object : Runnable {
override fun run() {
ApplicationManager.getApplication().runWriteAction(object : Runnable {
override fun run() {
val psiFactory = JetPsiFactory(classifierDeclaration)
val body = classifierDeclaration.getOrCreateBody()
var functionBody = ""
if (typeDescriptor.kind != ClassKind.INTERFACE && functionDescriptor.modality != Modality.ABSTRACT) {
functionBody = "{}"
val returnType = functionDescriptor.returnType
if (returnType == null || !KotlinBuiltIns.isUnit(returnType)) {
functionBody = "{ throw UnsupportedOperationException() }"
}
}
val functionElement = psiFactory.createFunction(signatureString + functionBody)
val anchor = body.rBrace
val insertedFunctionElement = body.addBefore(functionElement, anchor) as JetNamedFunction
project.executeWriteCommand(JetBundle.message("add.function.to.type.action")) {
val body = classifierDeclaration.getOrCreateBody()
ShortenReferences.DEFAULT.process(insertedFunctionElement)
}
})
var functionBody = ""
if (typeDescriptor.kind != ClassKind.INTERFACE && functionDescriptor.modality != Modality.ABSTRACT) {
functionBody = "{}"
val returnType = functionDescriptor.returnType
if (returnType == null || !KotlinBuiltIns.isUnit(returnType)) {
functionBody = "{ throw UnsupportedOperationException() }"
}
}
}, JetBundle.message("add.function.to.type.action"), null)
val functionElement = JetPsiFactory(project).createFunction(signatureString + functionBody)
val insertedFunctionElement = body.addBefore(functionElement, body.rBrace) as JetNamedFunction
ShortenReferences.DEFAULT.process(insertedFunctionElement)
}
}
override fun execute(): Boolean {
if (functionsToAdd.isEmpty()) {
return false
}
fun execute() {
if (functionsToAdd.isEmpty()) return
if (functionsToAdd.size == 1 || editor == null || !editor.component.isShowing) {
addFunction(functionsToAdd.get(0))
}
else {
chooseFunctionAndAdd()
JBPopupFactory.getInstance().createListPopup(functionPopup).showInBestPositionFor(editor)
}
return true
}
private fun chooseFunctionAndAdd() {
JBPopupFactory.getInstance().createListPopup(functionPopup).showInBestPositionFor(editor!!)
}
private val functionPopup: ListPopupStep<*>
get() {
return object : BaseListPopupStep<FunctionDescriptor>(JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
override fun isAutoSelectionEnabled(): Boolean {
return false
}
override fun isAutoSelectionEnabled() = false
override fun onChosen(selectedValue: FunctionDescriptor, finalChoice: Boolean): PopupStep<Any>? {
if (finalChoice) {
@@ -16,7 +16,6 @@
package org.jetbrains.kotlin.idea.quickfix
import com.google.common.collect.Lists
import com.intellij.codeInsight.intention.IntentionAction
import com.intellij.openapi.command.CommandProcessor
import com.intellij.openapi.editor.Editor
@@ -34,12 +33,12 @@ import org.jetbrains.kotlin.psi.JetFile
import org.jetbrains.kotlin.psi.JetNamedFunction
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.types.JetType
import org.jetbrains.kotlin.types.TypeUtils
import org.jetbrains.kotlin.types.checker.JetTypeChecker
import org.jetbrains.kotlin.types.typeUtil.supertypes
import java.util.*
class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNamedFunction>(element) {
private val functionsToAdd: List<FunctionDescriptor> = generateFunctionsToAdd(element)
private val functionsToAdd = generateFunctionsToAdd(element)
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
return super.isAvailable(project, editor, file) && !functionsToAdd.isEmpty()
@@ -48,11 +47,11 @@ class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNa
override fun showHint(editor: Editor) = false
override fun getText(): String {
if (functionsToAdd.size == 1) {
val newFunction = functionsToAdd.get(0)
val supertype = newFunction.containingDeclaration as ClassDescriptor
val single = functionsToAdd.singleOrNull()
if (single != null) {
val supertype = single.containingDeclaration as ClassDescriptor
return JetBundle.message("add.function.to.type.action.single",
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(newFunction),
IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.render(single),
supertype.name.toString())
}
else {
@@ -70,57 +69,46 @@ class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNa
})
}
private fun createAction(project: Project, editor: Editor?): JetAddFunctionToClassifierAction {
return JetAddFunctionToClassifierAction(project, editor, functionsToAdd)
}
private fun createAction(project: Project, editor: Editor?)
= JetAddFunctionToClassifierAction(project, editor, functionsToAdd)
companion object {
companion object: JetSingleIntentionActionFactory() {
override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction::class.java)
return if (function == null) null else AddFunctionToSupertypeFix(function)
}
private fun generateFunctionsToAdd(functionElement: JetNamedFunction): List<FunctionDescriptor> {
val functionDescriptor = functionElement.resolveToDescriptor() as FunctionDescriptor
val containingClass = functionDescriptor.containingDeclaration as? ClassDescriptor ?: return emptyList()
val functions = ArrayList<FunctionDescriptor>()
// TODO: filter out impossible supertypes (for example when argument's type isn't visible in a superclass).
for (supertypeDescriptor in getSupertypes(containingClass)) {
if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.defaultType)) continue
functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor))
}
return functions
return getSupertypes(containingClass)
.filterNot { KotlinBuiltIns.isAnyOrNullableAny(it.defaultType) }
.map { generateFunctionSignatureForType(functionDescriptor, it) }
}
private fun getSupertypes(classDescriptor: ClassDescriptor): List<ClassDescriptor> {
val supertypes = Lists.newArrayList(TypeUtils.getAllSupertypes(classDescriptor.defaultType))
Collections.sort(supertypes, object : Comparator<JetType> {
val supertypes = classDescriptor.defaultType.supertypes().sortedWith(object : Comparator<JetType> {
override fun compare(o1: JetType, o2: JetType): Int {
if (o1 == o2) {
return 0
return when {
o1 == o2 -> 0
JetTypeChecker.DEFAULT.isSubtypeOf(o1, o2) -> -1
JetTypeChecker.DEFAULT.isSubtypeOf(o2, o1) -> 1
else -> o1.toString().compareTo(o2.toString())
}
if (JetTypeChecker.DEFAULT.isSubtypeOf(o1, o2)) {
return -1
}
if (JetTypeChecker.DEFAULT.isSubtypeOf(o2, o1)) {
return 1
}
return o1.toString().compareTo(o2.toString())
}
})
val supertypesDescriptors = Lists.newArrayList<ClassDescriptor>()
for (supertype in supertypes) {
supertypesDescriptors.add(DescriptorUtils.getClassDescriptorForType(supertype))
}
return supertypesDescriptors
return supertypes.map { DescriptorUtils.getClassDescriptorForType(it) }
}
private fun generateFunctionSignatureForType(
functionDescriptor: FunctionDescriptor,
typeDescriptor: ClassDescriptor): FunctionDescriptor {
private fun generateFunctionSignatureForType(functionDescriptor: FunctionDescriptor, typeDescriptor: ClassDescriptor): FunctionDescriptor {
// TODO: support for generics.
var modality = typeDescriptor.modality
if (typeDescriptor.kind == ClassKind.INTERFACE) {
modality = Modality.OPEN
}
val modality = if (typeDescriptor.kind == ClassKind.INTERFACE) Modality.OPEN else typeDescriptor.modality
return functionDescriptor.copy(
typeDescriptor,
modality,
@@ -128,14 +116,5 @@ class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNa
CallableMemberDescriptor.Kind.DECLARATION,
/* copyOverrides = */ false)
}
fun createFactory(): JetIntentionActionsFactory {
return object : JetSingleIntentionActionFactory() {
public override fun createAction(diagnostic: Diagnostic): IntentionAction? {
val function = QuickFixUtil.getParentElementOfType(diagnostic, JetNamedFunction::class.java)
return if (function == null) null else AddFunctionToSupertypeFix(function)
}
}
}
}
}
@@ -91,7 +91,7 @@ public class QuickFixRegistrar : QuickFixContributor {
NOTHING_TO_OVERRIDE.registerFactory( RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OVERRIDE_KEYWORD),
ChangeMemberFunctionSignatureFix,
AddFunctionToSupertypeFix.createFactory())
AddFunctionToSupertypeFix)
VIRTUAL_MEMBER_HIDDEN.registerFactory(AddModifierFix.createFactory(OVERRIDE_KEYWORD))
USELESS_CAST.registerFactory(RemoveRightPartOfBinaryExpressionFix.createRemoveTypeFromBinaryExpressionFactory("Remove cast"))