Move: Drop ${...} around shortened qualified expression

#KT-22692 Fixed
This commit is contained in:
Alexey Sedunov
2018-02-16 20:51:05 +03:00
parent e63e48933d
commit 91fdc0e967
12 changed files with 52 additions and 31 deletions
@@ -22,10 +22,7 @@ import org.jetbrains.kotlin.idea.util.ShadowedDeclarationsFilter
import org.jetbrains.kotlin.idea.util.getResolutionScope import org.jetbrains.kotlin.idea.util.getResolutionScope
import org.jetbrains.kotlin.incremental.components.NoLookupLocation import org.jetbrains.kotlin.incremental.components.NoLookupLocation
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.createSmartPointer import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.psi.psiUtil.getParentOfType
import org.jetbrains.kotlin.psi.psiUtil.getQualifiedExpressionForReceiver
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.renderer.DescriptorRenderer import org.jetbrains.kotlin.renderer.DescriptorRenderer
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getCall import org.jetbrains.kotlin.resolve.calls.callUtil.getCall
@@ -578,7 +575,11 @@ class ShortenReferences(val options: (KtElement) -> Options = { Options.DEFAULT
val parens = element.parent as? KtParenthesizedExpression val parens = element.parent as? KtParenthesizedExpression
val requiredParens = parens != null && !KtPsiUtil.areParenthesesUseless(parens) val requiredParens = parens != null && !KtPsiUtil.areParenthesesUseless(parens)
val shortenedElement = element.replace(element.selectorExpression!!) as KtElement val shortenedElement = element.replace(element.selectorExpression!!) as KtElement
if (requiredParens) return shortenedElement.parent.replaced(shortenedElement) val newParent = shortenedElement.parent
if (requiredParens) return newParent.replaced(shortenedElement)
if (newParent is KtBlockStringTemplateEntry && newParent.canDropBraces()) {
newParent.dropBraces()
}
return shortenedElement return shortenedElement
} }
} }
@@ -463,3 +463,12 @@ fun KtModifierList.normalize(): KtModifierList {
modifiers.forEach { newList.add(it) } modifiers.forEach { newList.add(it) }
} }
} }
fun KtBlockStringTemplateEntry.canDropBraces() =
expression is KtNameReferenceExpression && canPlaceAfterSimpleNameEntry(nextSibling)
fun KtBlockStringTemplateEntry.dropBraces(): KtSimpleNameStringTemplateEntry {
val name = (expression as KtNameReferenceExpression).getReferencedName()
val newEntry = KtPsiFactory(this).createSimpleNameStringTemplateEntry(name)
return replaced(newEntry)
}
@@ -20,6 +20,7 @@ import com.intellij.openapi.util.Key
import com.intellij.psi.PsiTreeChangeAdapter import com.intellij.psi.PsiTreeChangeAdapter
import com.intellij.psi.PsiTreeChangeEvent import com.intellij.psi.PsiTreeChangeEvent
import org.jetbrains.kotlin.idea.caches.resolve.analyze import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.core.dropBraces
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.replaced
import org.jetbrains.kotlin.idea.intentions.ConvertToBlockBodyIntention import org.jetbrains.kotlin.idea.intentions.ConvertToBlockBodyIntention
import org.jetbrains.kotlin.idea.intentions.RemoveCurlyBracesFromTemplateIntention import org.jetbrains.kotlin.idea.intentions.RemoveCurlyBracesFromTemplateIntention
@@ -171,7 +172,7 @@ internal class ExpressionReplacementPerformer(
if (templateEntry != null) { if (templateEntry != null) {
val intention = RemoveCurlyBracesFromTemplateIntention() val intention = RemoveCurlyBracesFromTemplateIntention()
if (intention.isApplicableTo(templateEntry)) { if (intention.isApplicableTo(templateEntry)) {
val newEntry = intention.applyTo(templateEntry) val newEntry = templateEntry.dropBraces()
return newEntry.expression return newEntry.expression
} }
} }
@@ -17,29 +17,17 @@
package org.jetbrains.kotlin.idea.intentions package org.jetbrains.kotlin.idea.intentions
import com.intellij.openapi.editor.Editor import com.intellij.openapi.editor.Editor
import org.jetbrains.kotlin.idea.core.replaced import org.jetbrains.kotlin.idea.core.canDropBraces
import org.jetbrains.kotlin.idea.core.dropBraces
import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection import org.jetbrains.kotlin.idea.inspections.IntentionBasedInspection
import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry import org.jetbrains.kotlin.psi.KtBlockStringTemplateEntry
import org.jetbrains.kotlin.psi.KtNameReferenceExpression
import org.jetbrains.kotlin.psi.KtPsiFactory
import org.jetbrains.kotlin.psi.KtSimpleNameStringTemplateEntry
import org.jetbrains.kotlin.psi.psiUtil.canPlaceAfterSimpleNameEntry
class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection<KtBlockStringTemplateEntry>(RemoveCurlyBracesFromTemplateIntention::class) class RemoveCurlyBracesFromTemplateInspection : IntentionBasedInspection<KtBlockStringTemplateEntry>(RemoveCurlyBracesFromTemplateIntention::class)
class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBlockStringTemplateEntry>(KtBlockStringTemplateEntry::class.java, "Remove curly braces") { class RemoveCurlyBracesFromTemplateIntention : SelfTargetingOffsetIndependentIntention<KtBlockStringTemplateEntry>(KtBlockStringTemplateEntry::class.java, "Remove curly braces") {
override fun isApplicableTo(element: KtBlockStringTemplateEntry): Boolean { override fun isApplicableTo(element: KtBlockStringTemplateEntry) = element.canDropBraces()
if (element.expression !is KtNameReferenceExpression) return false
return canPlaceAfterSimpleNameEntry(element.nextSibling)
}
override fun applyTo(element: KtBlockStringTemplateEntry, editor: Editor?) { override fun applyTo(element: KtBlockStringTemplateEntry, editor: Editor?) {
applyTo(element) element.dropBraces()
}
fun applyTo(element: KtBlockStringTemplateEntry): KtSimpleNameStringTemplateEntry {
val name = (element.expression as KtNameReferenceExpression).getReferencedName()
val newEntry = KtPsiFactory(element).createSimpleNameStringTemplateEntry(name)
return element.replaced(newEntry)
} }
} }
@@ -61,13 +61,10 @@ import org.jetbrains.kotlin.idea.KotlinFileType
import org.jetbrains.kotlin.idea.KotlinLanguage import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.* import org.jetbrains.kotlin.idea.caches.resolve.*
import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde import org.jetbrains.kotlin.idea.codeInsight.DescriptorToSourceUtilsIde
import org.jetbrains.kotlin.idea.core.ShortenReferences import org.jetbrains.kotlin.idea.core.*
import org.jetbrains.kotlin.idea.core.getPackage
import org.jetbrains.kotlin.idea.core.quoteSegmentsIfNeeded
import org.jetbrains.kotlin.idea.core.util.showYesNoCancelDialog import org.jetbrains.kotlin.idea.core.util.showYesNoCancelDialog
import org.jetbrains.kotlin.idea.highlighter.markers.actualsForExpected import org.jetbrains.kotlin.idea.highlighter.markers.actualsForExpected
import org.jetbrains.kotlin.idea.highlighter.markers.liftToExpected import org.jetbrains.kotlin.idea.highlighter.markers.liftToExpected
import org.jetbrains.kotlin.idea.intentions.RemoveCurlyBracesFromTemplateIntention
import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices import org.jetbrains.kotlin.idea.j2k.IdeaJavaToKotlinServices
import org.jetbrains.kotlin.idea.project.languageVersionSettings import org.jetbrains.kotlin.idea.project.languageVersionSettings
import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar import org.jetbrains.kotlin.idea.refactoring.changeSignature.KotlinValVar
@@ -779,11 +776,8 @@ fun <T> Pass(body: (T) -> Unit) = object : Pass<T>() {
} }
fun KtExpression.removeTemplateEntryBracesIfPossible(): KtExpression { fun KtExpression.removeTemplateEntryBracesIfPossible(): KtExpression {
val parent = parent val parent = parent as? KtBlockStringTemplateEntry ?: return this
if (parent !is KtBlockStringTemplateEntry) return this val newEntry = if (parent.canDropBraces()) parent.dropBraces() else parent
val intention = RemoveCurlyBracesFromTemplateIntention()
val newEntry = if (intention.isApplicableTo(parent)) intention.applyTo(parent) else parent
return newEntry.expression!! return newEntry.expression!!
} }
@@ -0,0 +1,3 @@
package bar
val someVal = ""
@@ -0,0 +1,7 @@
package foo
import bar.someVal
fun usage() {
println("Usage: $someVal")
}
@@ -0,0 +1,7 @@
package foo
val <caret>someVal = ""
fun usage() {
println("Usage: $someVal")
}
@@ -0,0 +1,5 @@
{
"mainFile": "foo/test.kt",
"type": "MOVE_KOTLIN_TOP_LEVEL_DECLARATIONS",
"targetPackage": "bar"
}
@@ -697,6 +697,12 @@ public class MoveTestGenerated extends AbstractMoveTest {
doTest(fileName); doTest(fileName);
} }
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/shortenStringTemplateEntry/shortenStringTemplateEntry.test")
public void testKotlin_moveTopLevelDeclarations_misc_shortenStringTemplateEntry_ShortenStringTemplateEntry() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/shortenStringTemplateEntry/shortenStringTemplateEntry.test");
doTest(fileName);
}
@TestMetadata("kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test") @TestMetadata("kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test")
public void testKotlin_moveTopLevelDeclarations_misc_singletonsAndStatics_SingletonsAndStatics() throws Exception { public void testKotlin_moveTopLevelDeclarations_misc_singletonsAndStatics_SingletonsAndStatics() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test"); String fileName = KotlinTestUtils.navigationMetadata("idea/testData/refactoring/move/kotlin/moveTopLevelDeclarations/misc/singletonsAndStatics/singletonsAndStatics.test");