Code simplifications
This commit is contained in:
@@ -16,9 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.actions
|
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.editor.Editor
|
||||||
import com.intellij.openapi.project.Project
|
import com.intellij.openapi.project.Project
|
||||||
import com.intellij.openapi.ui.popup.JBPopupFactory
|
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.codeInsight.DescriptorToSourceUtilsIde
|
||||||
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
|
||||||
import org.jetbrains.kotlin.idea.util.ShortenReferences
|
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.JetClass
|
||||||
import org.jetbrains.kotlin.psi.JetNamedFunction
|
import org.jetbrains.kotlin.psi.JetNamedFunction
|
||||||
import org.jetbrains.kotlin.psi.JetPsiFactory
|
import org.jetbrains.kotlin.psi.JetPsiFactory
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Changes method signature to one of provided signatures.
|
* Changes method signature to one of provided signatures.
|
||||||
@@ -48,14 +45,8 @@ import java.util.*
|
|||||||
class JetAddFunctionToClassifierAction(
|
class JetAddFunctionToClassifierAction(
|
||||||
private val project: Project,
|
private val project: Project,
|
||||||
private val editor: Editor?,
|
private val editor: Editor?,
|
||||||
functionsToAdd: List<FunctionDescriptor>
|
private val functionsToAdd: List<FunctionDescriptor>
|
||||||
) : QuestionAction {
|
) {
|
||||||
private val functionsToAdd: List<FunctionDescriptor>
|
|
||||||
|
|
||||||
init {
|
|
||||||
this.functionsToAdd = ArrayList(functionsToAdd)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun addFunction(
|
private fun addFunction(
|
||||||
project: Project,
|
project: Project,
|
||||||
typeDescriptor: ClassDescriptor,
|
typeDescriptor: ClassDescriptor,
|
||||||
@@ -66,57 +57,40 @@ class JetAddFunctionToClassifierAction(
|
|||||||
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
PsiDocumentManager.getInstance(project).commitAllDocuments()
|
||||||
|
|
||||||
val classifierDeclaration = DescriptorToSourceUtilsIde.getAnyDeclaration(project, typeDescriptor) as JetClass
|
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 = ""
|
project.executeWriteCommand(JetBundle.message("add.function.to.type.action")) {
|
||||||
if (typeDescriptor.kind != ClassKind.INTERFACE && functionDescriptor.modality != Modality.ABSTRACT) {
|
val body = classifierDeclaration.getOrCreateBody()
|
||||||
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
|
|
||||||
|
|
||||||
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 {
|
fun execute() {
|
||||||
if (functionsToAdd.isEmpty()) {
|
if (functionsToAdd.isEmpty()) return
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
if (functionsToAdd.size == 1 || editor == null || !editor.component.isShowing) {
|
if (functionsToAdd.size == 1 || editor == null || !editor.component.isShowing) {
|
||||||
addFunction(functionsToAdd.get(0))
|
addFunction(functionsToAdd.get(0))
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
chooseFunctionAndAdd()
|
JBPopupFactory.getInstance().createListPopup(functionPopup).showInBestPositionFor(editor)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun chooseFunctionAndAdd() {
|
|
||||||
JBPopupFactory.getInstance().createListPopup(functionPopup).showInBestPositionFor(editor!!)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private val functionPopup: ListPopupStep<*>
|
private val functionPopup: ListPopupStep<*>
|
||||||
get() {
|
get() {
|
||||||
return object : BaseListPopupStep<FunctionDescriptor>(JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
|
return object : BaseListPopupStep<FunctionDescriptor>(JetBundle.message("add.function.to.type.action.type.chooser"), functionsToAdd) {
|
||||||
override fun isAutoSelectionEnabled(): Boolean {
|
override fun isAutoSelectionEnabled() = false
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onChosen(selectedValue: FunctionDescriptor, finalChoice: Boolean): PopupStep<Any>? {
|
override fun onChosen(selectedValue: FunctionDescriptor, finalChoice: Boolean): PopupStep<Any>? {
|
||||||
if (finalChoice) {
|
if (finalChoice) {
|
||||||
|
|||||||
@@ -16,7 +16,6 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.quickfix
|
package org.jetbrains.kotlin.idea.quickfix
|
||||||
|
|
||||||
import com.google.common.collect.Lists
|
|
||||||
import com.intellij.codeInsight.intention.IntentionAction
|
import com.intellij.codeInsight.intention.IntentionAction
|
||||||
import com.intellij.openapi.command.CommandProcessor
|
import com.intellij.openapi.command.CommandProcessor
|
||||||
import com.intellij.openapi.editor.Editor
|
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.psi.JetNamedFunction
|
||||||
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
import org.jetbrains.kotlin.resolve.DescriptorUtils
|
||||||
import org.jetbrains.kotlin.types.JetType
|
import org.jetbrains.kotlin.types.JetType
|
||||||
import org.jetbrains.kotlin.types.TypeUtils
|
|
||||||
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
import org.jetbrains.kotlin.types.checker.JetTypeChecker
|
||||||
|
import org.jetbrains.kotlin.types.typeUtil.supertypes
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNamedFunction>(element) {
|
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 {
|
override fun isAvailable(project: Project, editor: Editor?, file: PsiFile): Boolean {
|
||||||
return super.isAvailable(project, editor, file) && !functionsToAdd.isEmpty()
|
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 showHint(editor: Editor) = false
|
||||||
|
|
||||||
override fun getText(): String {
|
override fun getText(): String {
|
||||||
if (functionsToAdd.size == 1) {
|
val single = functionsToAdd.singleOrNull()
|
||||||
val newFunction = functionsToAdd.get(0)
|
if (single != null) {
|
||||||
val supertype = newFunction.containingDeclaration as ClassDescriptor
|
val supertype = single.containingDeclaration as ClassDescriptor
|
||||||
return JetBundle.message("add.function.to.type.action.single",
|
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())
|
supertype.name.toString())
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -70,57 +69,46 @@ class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNa
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createAction(project: Project, editor: Editor?): JetAddFunctionToClassifierAction {
|
private fun createAction(project: Project, editor: Editor?)
|
||||||
return JetAddFunctionToClassifierAction(project, editor, functionsToAdd)
|
= 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> {
|
private fun generateFunctionsToAdd(functionElement: JetNamedFunction): List<FunctionDescriptor> {
|
||||||
val functionDescriptor = functionElement.resolveToDescriptor() as FunctionDescriptor
|
val functionDescriptor = functionElement.resolveToDescriptor() as FunctionDescriptor
|
||||||
|
|
||||||
val containingClass = functionDescriptor.containingDeclaration as? ClassDescriptor ?: return emptyList()
|
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).
|
// TODO: filter out impossible supertypes (for example when argument's type isn't visible in a superclass).
|
||||||
for (supertypeDescriptor in getSupertypes(containingClass)) {
|
return getSupertypes(containingClass)
|
||||||
if (KotlinBuiltIns.isAnyOrNullableAny(supertypeDescriptor.defaultType)) continue
|
.filterNot { KotlinBuiltIns.isAnyOrNullableAny(it.defaultType) }
|
||||||
functions.add(generateFunctionSignatureForType(functionDescriptor, supertypeDescriptor))
|
.map { generateFunctionSignatureForType(functionDescriptor, it) }
|
||||||
}
|
|
||||||
return functions
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getSupertypes(classDescriptor: ClassDescriptor): List<ClassDescriptor> {
|
private fun getSupertypes(classDescriptor: ClassDescriptor): List<ClassDescriptor> {
|
||||||
val supertypes = Lists.newArrayList(TypeUtils.getAllSupertypes(classDescriptor.defaultType))
|
val supertypes = classDescriptor.defaultType.supertypes().sortedWith(object : Comparator<JetType> {
|
||||||
Collections.sort(supertypes, object : Comparator<JetType> {
|
|
||||||
override fun compare(o1: JetType, o2: JetType): Int {
|
override fun compare(o1: JetType, o2: JetType): Int {
|
||||||
if (o1 == o2) {
|
return when {
|
||||||
return 0
|
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) {
|
return supertypes.map { DescriptorUtils.getClassDescriptorForType(it) }
|
||||||
supertypesDescriptors.add(DescriptorUtils.getClassDescriptorForType(supertype))
|
|
||||||
}
|
|
||||||
return supertypesDescriptors
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun generateFunctionSignatureForType(
|
private fun generateFunctionSignatureForType(functionDescriptor: FunctionDescriptor, typeDescriptor: ClassDescriptor): FunctionDescriptor {
|
||||||
functionDescriptor: FunctionDescriptor,
|
|
||||||
typeDescriptor: ClassDescriptor): FunctionDescriptor {
|
|
||||||
// TODO: support for generics.
|
// TODO: support for generics.
|
||||||
var modality = typeDescriptor.modality
|
|
||||||
if (typeDescriptor.kind == ClassKind.INTERFACE) {
|
val modality = if (typeDescriptor.kind == ClassKind.INTERFACE) Modality.OPEN else typeDescriptor.modality
|
||||||
modality = Modality.OPEN
|
|
||||||
}
|
|
||||||
return functionDescriptor.copy(
|
return functionDescriptor.copy(
|
||||||
typeDescriptor,
|
typeDescriptor,
|
||||||
modality,
|
modality,
|
||||||
@@ -128,14 +116,5 @@ class AddFunctionToSupertypeFix(element: JetNamedFunction) : JetHintAction<JetNa
|
|||||||
CallableMemberDescriptor.Kind.DECLARATION,
|
CallableMemberDescriptor.Kind.DECLARATION,
|
||||||
/* copyOverrides = */ false)
|
/* 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),
|
NOTHING_TO_OVERRIDE.registerFactory( RemoveModifierFix.createRemoveModifierFromListOwnerFactory(OVERRIDE_KEYWORD),
|
||||||
ChangeMemberFunctionSignatureFix,
|
ChangeMemberFunctionSignatureFix,
|
||||||
AddFunctionToSupertypeFix.createFactory())
|
AddFunctionToSupertypeFix)
|
||||||
VIRTUAL_MEMBER_HIDDEN.registerFactory(AddModifierFix.createFactory(OVERRIDE_KEYWORD))
|
VIRTUAL_MEMBER_HIDDEN.registerFactory(AddModifierFix.createFactory(OVERRIDE_KEYWORD))
|
||||||
|
|
||||||
USELESS_CAST.registerFactory(RemoveRightPartOfBinaryExpressionFix.createRemoveTypeFromBinaryExpressionFactory("Remove cast"))
|
USELESS_CAST.registerFactory(RemoveRightPartOfBinaryExpressionFix.createRemoveTypeFromBinaryExpressionFactory("Remove cast"))
|
||||||
|
|||||||
Reference in New Issue
Block a user