Extract common class from two KotlinInline<...>Dialogs #KT-17212 Fixed

This commit is contained in:
Mikhail Glukhikh
2017-12-15 18:28:40 +03:00
parent 3e1f471121
commit ce441e2163
3 changed files with 91 additions and 73 deletions
@@ -0,0 +1,77 @@
/*
* Copyright 2010-2017 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.inline
import com.intellij.openapi.project.Project
import com.intellij.openapi.util.text.StringUtil
import com.intellij.psi.ElementDescriptionUtil
import com.intellij.refactoring.inline.InlineOptionsDialog
import com.intellij.usageView.UsageViewTypeLocation
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.psi.KtCallableDeclaration
abstract class AbstractKotlinInlineDialog(
protected val callable: KtCallableDeclaration,
protected val reference: KtSimpleNameReference?,
project: Project = callable.project
) : InlineOptionsDialog(project, true, callable) {
protected val occurrencesNumber = initOccurrencesNumber(callable)
private val occurrencesString get() = if (occurrencesNumber >= 0) {
"" + occurrencesNumber + " " + StringUtil.pluralize("occurrence", occurrencesNumber)
} else null
private val kind: String = ElementDescriptionUtil.getElementDescription(callable, UsageViewTypeLocation.INSTANCE)
private val refactoringName get() = "Inline ${StringUtil.capitalizeWords(kind, true)}"
init {
myInvokedOnReference = reference != null
title = refactoringName
}
// If this is true, "inline all & remove" is disabled,
// "inline all and keep" is disabled on references and enabled on original declaration.
// Independent on this, "inline this only" is enabled on references and disabled on original declaration
// If this is false, "inline all & remove" is dependent on next flag (allowInlineAll),
// "inline all and keep" is enabled
override fun canInlineThisOnly() = false
// If this is false, "inline all & remove" is disabled
// If this is true, it can be enabled if 'canInlineThisOnly' is false (see above)
override fun allowInlineAll() = true
override fun getBorderTitle() = refactoringName
override fun getNameLabelText(): String {
val occurrencesString =
if (occurrencesNumber >= 0) " - $occurrencesString"
else ""
return "${kind.capitalize()} ${callable.nameAsSafeName} $occurrencesString"
}
override fun getInlineAllText() =
"Inline all references and remove the $kind ($occurrencesString)"
override fun getKeepTheDeclarationText(): String? =
// With non-writable callable refactoring does not work anyway (for both property or function)
if (callable.isWritable && occurrencesNumber > 1) "Inline all references and keep the $kind ($occurrencesString)"
else null
override fun getInlineThisText() = "Inline this occurrence and leave the $kind"
}
@@ -20,58 +20,28 @@ import com.intellij.openapi.help.HelpManager
import com.intellij.openapi.project.Project
import com.intellij.refactoring.HelpID
import com.intellij.refactoring.JavaRefactoringSettings
import com.intellij.refactoring.inline.InlineOptionsDialog
import org.jetbrains.kotlin.idea.codeInliner.PropertyUsageReplacementStrategy
import org.jetbrains.kotlin.idea.codeInliner.UsageReplacementStrategy
import org.jetbrains.kotlin.idea.quickfix.createFromUsage.callableBuilder.getReturnTypeReference
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.psi.KtConstructor
import org.jetbrains.kotlin.psi.KtNamedFunction
// NB: similar to IDEA InlineMethodDialog / KotlinInlineValDialog
class KotlinInlineFunctionDialog(
project: Project,
private val function: KtNamedFunction,
private val reference: KtSimpleNameReference?,
function: KtNamedFunction,
reference: KtSimpleNameReference?,
private val replacementStrategy: UsageReplacementStrategy,
private val allowInlineThisOnly: Boolean
) : InlineOptionsDialog(project, true, function) {
private var occurrencesNumber = initOccurrencesNumber(function)
) : AbstractKotlinInlineDialog(function, reference, project) {
init {
myInvokedOnReference = reference != null
title = "Inline function"
init()
}
override fun allowInlineAll() = true
override fun getNameLabelText(): String {
val occurrencesString =
if (occurrencesNumber > -1) " - $occurrencesNumber occurrence${if (occurrencesNumber == 1) "" else "s"}"
else ""
val functionText = "${function.nameAsSafeName}" + function.valueParameters.joinToString(prefix = "(", postfix = ")") {
"${it.nameAsSafeName}: ${it.typeReference?.text}"
} + (function.getReturnTypeReference()?.let { ": " + it.text } ?: "")
return "Function $functionText $occurrencesString"
}
override fun getBorderTitle() = "Inline"
override fun getInlineThisText() = "Inline this only and keep the function"
override fun getInlineAllText() =
if (function.isWritable) "Inline all and remove the function"
else "All invocations in project"
override fun getKeepTheDeclarationText(): String? =
if (function.isWritable) "Inline all and keep the function"
else super.getKeepTheDeclarationText()
override fun isInlineThis() = JavaRefactoringSettings.getInstance().INLINE_METHOD_THIS
public override fun doAction() {
invokeRefactoring(
KotlinInlineCallableProcessor(project, replacementStrategy, function, reference,
KotlinInlineCallableProcessor(project, replacementStrategy, callable, reference,
inlineThisOnly = isInlineThisOnly || allowInlineThisOnly,
deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration && !allowInlineThisOnly)
)
@@ -83,9 +53,7 @@ class KotlinInlineFunctionDialog(
}
override fun doHelpAction() =
HelpManager.getInstance().invokeHelp(if (function is KtConstructor<*>) HelpID.INLINE_CONSTRUCTOR else HelpID.INLINE_METHOD)
HelpManager.getInstance().invokeHelp(if (callable is KtConstructor<*>) HelpID.INLINE_CONSTRUCTOR else HelpID.INLINE_METHOD)
override fun canInlineThisOnly() = allowInlineThisOnly
override fun isInlineThis() = JavaRefactoringSettings.getInstance().INLINE_METHOD_THIS
}
@@ -18,33 +18,27 @@ package org.jetbrains.kotlin.idea.refactoring.inline
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
import com.intellij.openapi.ui.DialogWrapper
import com.intellij.openapi.util.text.StringUtil
import com.intellij.refactoring.JavaRefactoringSettings
import com.intellij.refactoring.inline.InlineOptionsDialog
import org.jetbrains.kotlin.idea.codeInliner.UsageReplacementStrategy
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtProperty
class KotlinInlineValDialog(
private val property: KtProperty,
private val reference: KtSimpleNameReference?,
property: KtProperty,
reference: KtSimpleNameReference?,
private val replacementStrategy: UsageReplacementStrategy,
private val assignmentToDelete: KtBinaryExpression?,
withPreview: Boolean = true
) : InlineOptionsDialog(property.project, true, property) {
) : AbstractKotlinInlineDialog(property, reference) {
private var occurrenceCount = initOccurrencesNumber(property)
private val isLocal = (callable as KtProperty).isLocal
private val kind = if (property.isLocal) "local variable" else "property"
private val refactoringName = "Inline ${StringUtil.capitalizeWords(kind, true)}"
private val simpleLocal = isLocal && (reference == null || occurrencesNumber == 1)
init {
myInvokedOnReference = reference != null
title = refactoringName
setPreviewResults(withPreview && shouldBeShown())
if (forSimpleLocal()) {
if (simpleLocal) {
setDoNotAskOption(object : DialogWrapper.DoNotAskOption {
override fun isToBeShown() = EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog
@@ -62,34 +56,13 @@ class KotlinInlineValDialog(
init()
}
private fun forSimpleLocal() = property.isLocal && (reference == null || occurrenceCount == 1)
fun shouldBeShown() = !forSimpleLocal() || EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog
override fun allowInlineAll() = true
override fun getBorderTitle() = refactoringName
override fun getNameLabelText() = "${kind.capitalize()} ${property.name}"
private val occurrencesString get() = if (occurrenceCount >= 0) {
" (" + occurrenceCount + " occurrence" + (if (occurrenceCount == 1) ")" else "s)")
} else ""
override fun getInlineAllText() =
"Inline all references and remove the $kind" + occurrencesString
override fun getKeepTheDeclarationText(): String? =
if (property.isWritable) "Inline all references and keep the $kind" + occurrencesString
else super.getKeepTheDeclarationText()
fun shouldBeShown() = !simpleLocal || EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog
override fun isInlineThis() = JavaRefactoringSettings.getInstance().INLINE_LOCAL_THIS
override fun getInlineThisText() = "Inline this occurrence and leave the $kind"
public override fun doAction() {
invokeRefactoring(
KotlinInlineCallableProcessor(project, replacementStrategy, property, reference,
KotlinInlineCallableProcessor(project, replacementStrategy, callable, reference,
inlineThisOnly = isInlineThisOnly,
deleteAfter = !isInlineThisOnly && !isKeepTheDeclaration,
statementToDelete = assignmentToDelete)