Fix AddTargetVersionCheckQuickFix, generate else branch with TODO

when surrounded statement used as expression

#KT-17786 Fixed
#KT-17788 Fixed
This commit is contained in:
Vyacheslav Gerasimov
2017-05-30 15:32:13 +03:00
parent 33c3ba815f
commit 15bfd4439a
13 changed files with 106 additions and 18 deletions
@@ -278,6 +278,12 @@ public class AndroidLintQuickfixTestGenerated extends AbstractAndroidLintQuickfi
doTest(fileName);
}
@TestMetadata("destructuringDeclaration.kt")
public void testDestructuringDeclaration() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/targetVersionCheck/destructuringDeclaration.kt");
doTest(fileName);
}
@TestMetadata("expressionBody.kt")
public void testExpressionBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/targetVersionCheck/expressionBody.kt");
@@ -290,6 +296,12 @@ public class AndroidLintQuickfixTestGenerated extends AbstractAndroidLintQuickfi
doTest(fileName);
}
@TestMetadata("getterWIthExpressionBody.kt")
public void testGetterWIthExpressionBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/targetVersionCheck/getterWIthExpressionBody.kt");
doTest(fileName);
}
@TestMetadata("if.kt")
public void testIf() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/android/lintQuickfix/targetVersionCheck/if.kt");
@@ -0,0 +1,12 @@
// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... }
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection
import android.app.Activity
import android.graphics.drawable.VectorDrawable
data class ValueProvider(var p1: VectorDrawable, val p2: Int)
val activity = Activity()
fun foo() {
val (v1, v2) = ValueProvider(<caret>VectorDrawable(), 0)
}
@@ -0,0 +1,17 @@
// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... }
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection
import android.app.Activity
import android.graphics.drawable.VectorDrawable
import android.os.Build
data class ValueProvider(var p1: VectorDrawable, val p2: Int)
val activity = Activity()
fun foo() {
val (v1, v2) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ValueProvider(VectorDrawable(), 0)
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
@@ -7,5 +7,7 @@ import android.os.Build
class VectorDrawableProvider {
fun getVectorDrawable(): VectorDrawable = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
@@ -7,8 +7,10 @@ import android.os.Build
class VectorDrawableProvider {
fun getVectorDrawable(): VectorDrawable {
with(this) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return VectorDrawable()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
}
@@ -0,0 +1,7 @@
// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... }
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection
import android.graphics.drawable.VectorDrawable
val v: VectorDrawable
get() = <caret>VectorDrawable()
@@ -0,0 +1,12 @@
// INTENTION_TEXT: Surround with if (VERSION.SDK_INT >= VERSION_CODES.LOLLIPOP) { ... }
// INSPECTION_CLASS: org.jetbrains.android.inspections.klint.AndroidLintInspectionToolProvider$AndroidKLintNewApiInspection
import android.graphics.drawable.VectorDrawable
import android.os.Build
val v: VectorDrawable
get() = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
@@ -8,8 +8,10 @@ class VectorDrawableProvider {
val flag = false
fun getVectorDrawable(): VectorDrawable {
if (flag)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return VectorDrawable()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
}
@@ -8,8 +8,10 @@ class VectorDrawableProvider {
val flag = false
fun getVectorDrawable(): VectorDrawable {
if (flag) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return VectorDrawable()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
}
@@ -5,8 +5,10 @@ import android.os.Build
class Test {
fun foo(): Int {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
return android.R.attr.windowTranslucentStatus
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
android.R.attr.windowTranslucentStatus
} else {
TODO("VERSION.SDK_INT < KITKAT")
}
}
}
@@ -6,8 +6,10 @@ import android.os.Build
class VectorDrawableProvider {
fun getVectorDrawable(): VectorDrawable {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
return VectorDrawable()
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
}
}
@@ -10,6 +10,8 @@ class VectorDrawableProvider {
return when (flag) {
true -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
VectorDrawable()
} else {
TODO("VERSION.SDK_INT < LOLLIPOP")
}
else -> VectorDrawable()
}
@@ -20,18 +20,17 @@ import com.intellij.codeInsight.FileModificationService
import com.intellij.psi.PsiDocumentManager
import com.intellij.psi.PsiElement
import com.intellij.psi.util.PsiTreeUtil
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.codeInsight.surroundWith.statement.KotlinIfSurrounder
import org.jetbrains.kotlin.idea.core.ShortenReferences
import org.jetbrains.kotlin.idea.inspections.findExistingEditor
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.BindingContext
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix {
companion object {
private val IF_SURROUNDER = KotlinIfSurrounder()
}
override fun apply(startElement: PsiElement, endElement: PsiElement, context: AndroidQuickfixContexts.Context) {
val targetExpression = getTargetExpression(startElement)
val project = targetExpression?.project ?: return
@@ -45,7 +44,8 @@ class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix {
return
}
val conditionRange = IF_SURROUNDER.surroundElements(project, editor, arrayOf(targetExpression)) ?: return
val surrounder = getSurrounder(targetExpression, "\"VERSION.SDK_INT < ${getVersionField(api, false)}\"")
val conditionRange = surrounder.surroundElements(project, editor, arrayOf(targetExpression)) ?: return
val conditionText = "android.os.Build.VERSION.SDK_INT >= ${getVersionField(api, true)}"
document.replaceString(conditionRange.startOffset, conditionRange.endOffset, conditionText)
documentManager.commitDocument(document)
@@ -60,14 +60,17 @@ class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix {
override fun getName(): String = "Surround with if (VERSION.SDK_INT >= VERSION_CODES.${getVersionField(api, false)}) { ... }"
// TODO: Delegated property, initializer, annotation parameter
private fun getTargetExpression(element: PsiElement): PsiElement? {
private fun getTargetExpression(element: PsiElement): KtElement? {
var current = PsiTreeUtil.getParentOfType(element, KtExpression::class.java)
while (current != null) {
if (current.parent is KtBlockExpression ||
current.parent is KtContainerNode ||
current.parent is KtWhenEntry ||
current.parent is KtFunction) {
current.parent is KtFunction ||
current.parent is KtPropertyAccessor ||
current.parent is KtProperty ||
current.parent is KtReturnExpression ||
current.parent is KtDestructuringDeclaration) {
break
}
current = PsiTreeUtil.getParentOfType(current, KtExpression::class.java, true)
@@ -75,4 +78,15 @@ class AddTargetVersionCheckQuickFix(val api: Int) : AndroidLintQuickFix {
return current
}
private fun getSurrounder(element: KtElement, todoText: String?): KotlinIfSurrounder {
val used = element.analyze(BodyResolveMode.PARTIAL)[BindingContext.USED_AS_EXPRESSION, element] ?: false
return if (used) {
object : KotlinIfSurrounder() {
override fun getCodeTemplate(): String = "if (a) { \n} else {\nTODO(${todoText ?: ""})\n}"
}
} else {
KotlinIfSurrounder()
}
}
}