Code simplifications
This commit is contained in:
@@ -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"))
|
||||
|
||||
Reference in New Issue
Block a user