KT-12100 convert try / finally to use: safe close() is allowed in finally + correct new lines

This commit is contained in:
Mikhail Glukhikh
2016-12-01 19:23:18 +03:00
parent 0ac443066e
commit 0cc52e2ff8
9 changed files with 37 additions and 11 deletions
@@ -24,7 +24,6 @@ import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.contentRange import org.jetbrains.kotlin.psi.psiUtil.contentRange
import org.jetbrains.kotlin.resolve.BindingContext import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.callUtil.isSafeCall
import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe import org.jetbrains.kotlin.resolve.descriptorUtil.fqNameSafe
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver import org.jetbrains.kotlin.resolve.scopes.receivers.ImplicitReceiver
@@ -40,7 +39,7 @@ class ConvertTryFinallyToUseCallIntention : SelfTargetingOffsetIndependentIntent
override fun applyTo(element: KtTryExpression, editor: Editor?) { override fun applyTo(element: KtTryExpression, editor: Editor?) {
val finallySection = element.finallyBlock!! val finallySection = element.finallyBlock!!
val finallyExpression = finallySection.finalExpression.statements.single() val finallyExpression = finallySection.finalExpression.statements.single()
val finallyExpressionReceiver = (finallyExpression as? KtDotQualifiedExpression)?.receiverExpression val finallyExpressionReceiver = (finallyExpression as? KtQualifiedExpression)?.receiverExpression
val resourceReference = finallyExpressionReceiver as? KtNameReferenceExpression val resourceReference = finallyExpressionReceiver as? KtNameReferenceExpression
val resourceName = resourceReference?.getReferencedNameAsName() val resourceName = resourceReference?.getReferencedNameAsName()
@@ -61,9 +60,10 @@ class ConvertTryFinallyToUseCallIntention : SelfTargetingOffsetIndependentIntent
appendName(resourceName) appendName(resourceName)
appendFixedText("->") appendFixedText("->")
} }
appendFixedText("\n")
appendChildRange(element.tryBlock.contentRange()) appendChildRange(element.tryBlock.contentRange())
appendFixedText("}") appendFixedText("\n}")
} }
element.replace(useCallExpression) element.replace(useCallExpression)
@@ -77,8 +77,8 @@ class ConvertTryFinallyToUseCallIntention : SelfTargetingOffsetIndependentIntent
val context = element.analyze() val context = element.analyze()
val resolvedCall = finallyExpression.getResolvedCall(context) ?: return false val resolvedCall = finallyExpression.getResolvedCall(context) ?: return false
if (resolvedCall.call.isSafeCall()) return false
if (resolvedCall.candidateDescriptor.name.asString() != "close") return false if (resolvedCall.candidateDescriptor.name.asString() != "close") return false
if (resolvedCall.extensionReceiver != null) return false
val receiver = resolvedCall.dispatchReceiver ?: return false val receiver = resolvedCall.dispatchReceiver ?: return false
if (receiver.type.supertypes().all { if (receiver.type.supertypes().all {
it.constructor.declarationDescriptor?.fqNameSafe?.asString().let { it.constructor.declarationDescriptor?.fqNameSafe?.asString().let {
@@ -3,5 +3,7 @@ import java.io.File
fun main(args: Array<String>) { fun main(args: Array<String>) {
val reader = File("hello-world.txt").bufferedReader() val reader = File("hello-world.txt").bufferedReader()
reader.use { reader -> // do stuff with reader } reader.use { reader ->
// do stuff with reader
}
} }
@@ -3,5 +3,7 @@ import java.io.File
import java.io.BufferedReader import java.io.BufferedReader
fun BufferedReader.foo() { fun BufferedReader.foo() {
use { readLine() } use {
readLine()
}
} }
@@ -3,5 +3,7 @@ import java.io.File
import java.io.BufferedReader import java.io.BufferedReader
fun foo(reader: BufferedReader) { fun foo(reader: BufferedReader) {
reader.use { reader -> reader.readLine() } reader.use { reader ->
reader.readLine()
}
} }
@@ -1,11 +1,13 @@
// IS_APPLICABLE: false
// WITH_RUNTIME // WITH_RUNTIME
import java.io.File import java.io.File
import java.io.BufferedReader import java.io.BufferedReader
fun bar() {}
fun foo(reader: BufferedReader?) { fun foo(reader: BufferedReader?) {
try { try {
reader?.readLine() reader?.readLine()
bar()
} }
<caret>finally { <caret>finally {
reader?.close() reader?.close()
@@ -0,0 +1,12 @@
// WITH_RUNTIME
import java.io.File
import java.io.BufferedReader
fun bar() {}
fun foo(reader: BufferedReader?) {
reader.use { reader ->
reader?.readLine()
bar()
}
}
@@ -3,5 +3,7 @@ import java.io.File
fun main(args: Array<String>) { fun main(args: Array<String>) {
val reader = File("hello-world.txt").bufferedReader() val reader = File("hello-world.txt").bufferedReader()
reader.use { reader -> reader.readLine() } reader.use { reader ->
reader.readLine()
}
} }
@@ -3,5 +3,7 @@ import java.io.File
import java.io.BufferedReader import java.io.BufferedReader
fun BufferedReader.foo() { fun BufferedReader.foo() {
this.use { this.readLine() } this.use {
this.readLine()
}
} }
@@ -8,6 +8,8 @@ class MyCloseable : Closeable {
fun process(x: Int) = x fun process(x: Int) = x
fun Int.foo() { fun Int.foo() {
this@MyCloseable.use { this@MyCloseable.process(this) } this@MyCloseable.use {
this@MyCloseable.process(this)
}
} }
} }