Inline Property: Support "Do not show this dialog" and "Inline this occurrence" options

#KT-12017 Fixed
(cherry picked from commit b53d8da)
This commit is contained in:
Alexey Sedunov
2016-06-24 16:24:58 +03:00
parent 59f37a8291
commit dd7bd2b869
3 changed files with 101 additions and 9 deletions
+4
View File
@@ -121,6 +121,10 @@ These artifacts include extensions for the types available in the latter JDKs, s
- [`KT-12413`](https://youtrack.jetbrains.com/issue/KT-12413) Change Signature: Fix bogus warning about unresolved type parameters/invalid functional type replacement - [`KT-12413`](https://youtrack.jetbrains.com/issue/KT-12413) Change Signature: Fix bogus warning about unresolved type parameters/invalid functional type replacement
- [`KT-12084`](https://youtrack.jetbrains.com/issue/KT-12084) Introduce Property: Do not skip outer classes if extractable expression is contained in object literal - [`KT-12084`](https://youtrack.jetbrains.com/issue/KT-12084) Introduce Property: Do not skip outer classes if extractable expression is contained in object literal
###### New features
- [`KT-12017`](https://youtrack.jetbrains.com/issue/KT-12017) Inline Property: Support "Do not show this dialog" and "Inline this occurrence" options
## 1.0.3 ## 1.0.3
### Compiler ### Compiler
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2016 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.util.text.StringUtil
import com.intellij.psi.PsiReference
import com.intellij.refactoring.JavaRefactoringSettings
import com.intellij.refactoring.inline.AbstractInlineLocalDialog
import org.jetbrains.kotlin.psi.KtProperty
class KotlinInlineValDialog(
element: KtProperty,
ref: PsiReference?,
private val occurrenceCount: Int
) : AbstractInlineLocalDialog(element.project, element, ref, occurrenceCount) {
private val property: KtProperty get() = myElement as KtProperty
private val kind = if (property.isLocal) "local variable" else "property"
private val refactoringName = "Inline ${StringUtil.capitalizeWords(kind, true)}"
init {
myInvokedOnReference = ref != null
title = refactoringName
init()
}
override fun getBorderTitle() = refactoringName
override fun getNameLabelText() = "${kind.capitalize()} ${property.name}"
override fun getInlineAllText(): String? {
val occurrencesString = if (occurrenceCount >= 0) {
" (" + occurrenceCount + " occurrence" + (if (occurrenceCount == 1) ")" else "s)")
} else ""
return "Inline all references and remove the $kind" + occurrencesString
}
override fun isInlineThis() = JavaRefactoringSettings.getInstance().INLINE_LOCAL_THIS
override fun getInlineThisText() = "Inline this occurrence and leave the $kind"
override fun doAction() {
val settings = JavaRefactoringSettings.getInstance()
if (myRbInlineThisOnly.isEnabled && myRbInlineAll.isEnabled) {
settings.INLINE_LOCAL_THIS = isInlineThisOnly
}
close(OK_EXIT_CODE)
}
}
@@ -19,13 +19,17 @@ package org.jetbrains.kotlin.idea.refactoring.inline
import com.google.common.collect.Sets import com.google.common.collect.Sets
import com.intellij.lang.Language import com.intellij.lang.Language
import com.intellij.lang.refactoring.InlineActionHandler import com.intellij.lang.refactoring.InlineActionHandler
import com.intellij.openapi.application.ApplicationManager
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import com.intellij.openapi.editor.ex.EditorSettingsExternalizable
import com.intellij.openapi.project.Project import com.intellij.openapi.project.Project
import com.intellij.openapi.wm.WindowManager import com.intellij.openapi.wm.WindowManager
import com.intellij.psi.PsiElement import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.PsiWhiteSpace import com.intellij.psi.PsiWhiteSpace
import com.intellij.psi.search.searches.ReferencesSearch import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.refactoring.HelpID import com.intellij.refactoring.HelpID
import com.intellij.refactoring.JavaRefactoringSettings
import com.intellij.refactoring.RefactoringBundle import com.intellij.refactoring.RefactoringBundle
import com.intellij.refactoring.util.CommonRefactoringUtil import com.intellij.refactoring.util.CommonRefactoringUtil
import com.intellij.util.containers.MultiMap import com.intellij.util.containers.MultiMap
@@ -55,6 +59,10 @@ import org.jetbrains.kotlin.utils.sure
import java.util.* import java.util.*
class KotlinInlineValHandler : InlineActionHandler() { class KotlinInlineValHandler : InlineActionHandler() {
enum class InlineMode {
ALL, PRIMARY, NONE
}
override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE override fun isEnabledForLanguage(l: Language) = l == KotlinLanguage.INSTANCE
override fun canInlineElement(element: PsiElement): Boolean { override fun canInlineElement(element: PsiElement): Boolean {
@@ -152,12 +160,15 @@ class KotlinInlineValHandler : InlineActionHandler() {
} }
fun performRefactoring() { fun performRefactoring() {
if (!showDialog(project, val primaryExpression = if (editor != null) {
name, val offset = editor.caretModel.offset
RefactoringBundle.message("inline.variable.title"), referenceExpressions.firstOrNull { it.textRange.contains(offset) }
declaration, }
referenceExpressions, else null
HelpID.INLINE_VARIABLE)) { val primaryRef = primaryExpression?.mainReference
val inlineMode = showDialog(declaration, primaryRef, referenceExpressions.size)
if (inlineMode == InlineMode.NONE) {
if (isHighlighting) { if (isHighlighting) {
val statusBar = WindowManager.getInstance().getStatusBar(project) val statusBar = WindowManager.getInstance().getStatusBar(project)
statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting") statusBar?.info = RefactoringBundle.message("press.escape.to.remove.the.highlighting")
@@ -165,8 +176,10 @@ class KotlinInlineValHandler : InlineActionHandler() {
return return
} }
val chosenExpressions = if (inlineMode == InlineMode.ALL) referenceExpressions else listOf(primaryExpression)
project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) { project.executeWriteCommand(RefactoringBundle.message("inline.command", name)) {
val inlinedExpressions = referenceExpressions val inlinedExpressions = chosenExpressions
.flatMap { referenceExpression -> .flatMap { referenceExpression ->
if (assignments.contains(referenceExpression.parent)) return@flatMap emptyList<KtExpression>() if (assignments.contains(referenceExpression.parent)) return@flatMap emptyList<KtExpression>()
@@ -184,8 +197,10 @@ class KotlinInlineValHandler : InlineActionHandler() {
} }
.mapNotNull { postProcessInternalReferences(it) } .mapNotNull { postProcessInternalReferences(it) }
assignments.forEach { it.delete() } if (inlineMode == InlineMode.ALL) {
declaration.delete() assignments.forEach { it.delete() }
declaration.delete()
}
if (inlinedExpressions.isNotEmpty()) { if (inlinedExpressions.isNotEmpty()) {
if (typeArgumentsForCall != null) { if (typeArgumentsForCall != null) {
@@ -224,6 +239,15 @@ class KotlinInlineValHandler : InlineActionHandler() {
CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("inline.variable.title"), HelpID.INLINE_VARIABLE) CommonRefactoringUtil.showErrorHint(project, editor, message, RefactoringBundle.message("inline.variable.title"), HelpID.INLINE_VARIABLE)
} }
private fun showDialog(property: KtProperty, ref: PsiReference?, occurrenceCount: Int): InlineMode {
if (ApplicationManager.getApplication().isUnitTestMode) return InlineMode.ALL
if ((ref == null || occurrenceCount <= 1) && !EditorSettingsExternalizable.getInstance().isShowInlineLocalDialog) return InlineMode.ALL
val dialog = KotlinInlineValDialog(property, ref, occurrenceCount)
if (!dialog.showAndGet()) return InlineMode.NONE
return if (JavaRefactoringSettings.getInstance().INLINE_LOCAL_THIS) InlineMode.PRIMARY else InlineMode.ALL
}
private fun getParametersForFunctionLiteral(initializer: KtExpression): String? { private fun getParametersForFunctionLiteral(initializer: KtExpression): String? {
val functionLiteralExpression = initializer.unpackFunctionLiteral(true) ?: return null val functionLiteralExpression = initializer.unpackFunctionLiteral(true) ?: return null
val context = initializer.analyze(BodyResolveMode.PARTIAL) val context = initializer.analyze(BodyResolveMode.PARTIAL)