Move to constructor: choose property use-site target more precisely

#KT-26015 Fixed
This commit is contained in:
Toshiaki Kameyama
2018-08-30 12:17:04 +03:00
committed by Mikhail Glukhikh
parent 29390dab42
commit de6fdc5733
15 changed files with 94 additions and 20 deletions
@@ -76,12 +76,9 @@ class MovePropertyToConstructorIntention :
val commentSaver = CommentSaver(element)
val context = element.analyze(BodyResolveMode.PARTIAL)
val propertyAnnotationsText = element.modifierList?.annotationEntries?.joinToString(separator = " ") {
if (it.isApplicableToConstructorParameter()) {
it.getTextWithUseSiteIfMissing(AnnotationUseSiteTarget.FIELD.renderName)
} else {
it.text
}
it.getTextWithUseSite(context)
}
if (constructorParameter != null) {
@@ -129,19 +126,24 @@ class MovePropertyToConstructorIntention :
return parameterDescriptor.source.getPsi() as? KtParameter
}
private fun KtAnnotationEntry.isApplicableToConstructorParameter(): Boolean {
val context = analyze(BodyResolveMode.PARTIAL)
val descriptor = context[BindingContext.ANNOTATION, this] ?: return false
private fun KtAnnotationEntry.getTextWithUseSite(context: BindingContext): String {
if (useSiteTarget != null) return text
val typeReference = this.typeReference?.text ?: return text
val descriptor = context[BindingContext.ANNOTATION, this] ?: return text
val applicableTargets = AnnotationChecker.applicableTargetSet(descriptor)
return applicableTargets.contains(KotlinTarget.VALUE_PARAMETER)
val valueArgumentList = valueArgumentList?.text.orEmpty()
return when {
KotlinTarget.VALUE_PARAMETER !in applicableTargets ->
text
KotlinTarget.PROPERTY in applicableTargets ->
"@${AnnotationUseSiteTarget.PROPERTY.renderName}:$typeReference$valueArgumentList"
KotlinTarget.FIELD in applicableTargets ->
"@${AnnotationUseSiteTarget.FIELD.renderName}:$typeReference$valueArgumentList"
else ->
text
}
}
private fun KtAnnotationEntry.getTextWithUseSiteIfMissing(useSite: String) =
if (useSiteTarget == null)
"@$useSite:${typeReference?.text.orEmpty()}${valueArgumentList?.text.orEmpty()}"
else
text
private fun KotlinType.render() = IdeDescriptorRenderers.SOURCE_CODE.renderType(this)
private fun KtModifierList.getModifiersText() = getModifiers().joinToString(separator = " ") { it.text }
@@ -0,0 +1,23 @@
annotation class Ann1(val i: Int, val j: Int)
@Target(AnnotationTarget.PROPERTY)
annotation class Ann2(val i: Int, val j: Int)
@Target(AnnotationTarget.FIELD)
annotation class Ann3(val i: Int, val j: Int)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Ann4(val i: Int, val j: Int)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
annotation class Ann5(val i: Int, val j: Int)
class Test {
@get:Ann1(0, 0)
@Ann1(1, 11)
@Ann2(2, 22)
@Ann3(3, 33)
@Ann4(4, 44)
@Ann5(5, 55)
val <caret>foo = ""
}
@@ -0,0 +1,16 @@
annotation class Ann1(val i: Int, val j: Int)
@Target(AnnotationTarget.PROPERTY)
annotation class Ann2(val i: Int, val j: Int)
@Target(AnnotationTarget.FIELD)
annotation class Ann3(val i: Int, val j: Int)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD, AnnotationTarget.PROPERTY)
annotation class Ann4(val i: Int, val j: Int)
@Target(AnnotationTarget.VALUE_PARAMETER, AnnotationTarget.FIELD)
annotation class Ann5(val i: Int, val j: Int)
class Test(@get:Ann1(0, 0) @property:Ann1(1, 11) @Ann2(2, 22) @Ann3(3, 33) @property:Ann4(4, 44) @field:Ann5(5, 55) val foo: String = "") {
}
@@ -4,5 +4,5 @@ annotation class Annotation3(val a: Int = 0)
class TestClass(@Annotation1(42) @Annotation3(42) initialText: String = "LoremIpsum") {
private @Annotation1(42) @property:Annotation2(42) val <caret>text = initialText
private @Annotation1(42) @field:Annotation2(42) val <caret>text = initialText
}
@@ -3,5 +3,5 @@ annotation class Annotation2(val a: Int = 0)
annotation class Annotation3(val a: Int = 0)
class TestClass(private @field:Annotation1(42) @property:Annotation2(42) @Annotation1(42) @Annotation3(42) val text: String = "LoremIpsum") {
class TestClass(private @property:Annotation1(42) @field:Annotation2(42) @Annotation1(42) @Annotation3(42) val text: String = "LoremIpsum") {
}
@@ -0,0 +1 @@
public @interface JavaAnn { }
@@ -0,0 +1 @@
public @interface JavaAnn { }
@@ -0,0 +1,7 @@
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
@Target({FIELD})
public @interface JavaFieldAnn {
}
@@ -0,0 +1,7 @@
import java.lang.annotation.Target;
import static java.lang.annotation.ElementType.FIELD;
@Target({FIELD})
public @interface JavaFieldAnn {
}
@@ -0,0 +1,5 @@
class Test {
@JavaAnn
@JavaFieldAnn
val <caret>foo = ""
}
@@ -0,0 +1,2 @@
class Test(@property:JavaAnn @JavaFieldAnn val foo: String = "") {
}
@@ -1,4 +1,4 @@
annotation class SuperAnnotation
class TestClass(@field:SuperAnnotation val text: String) {
class TestClass(@property:SuperAnnotation val text: String) {
}
@@ -4,5 +4,5 @@ annotation class Annotation3(val a: Int = 0)
class TestClass(@Annotation1(42) @Annotation3(42) initialText: String = "LoremIpsum") {
private @Annotation1(42) @property:Annotation2(42) val <caret>text = "dolor sit amet"
private @Annotation1(42) @field:Annotation2(42) val <caret>text = "dolor sit amet"
}
@@ -3,5 +3,5 @@ annotation class Annotation2(val a: Int = 0)
annotation class Annotation3(val a: Int = 0)
class TestClass(@Annotation1(42) @Annotation3(42) initialText: String = "LoremIpsum", private @field:Annotation1(42) @property:Annotation2(42) val text: String = "dolor sit amet") {
class TestClass(@Annotation1(42) @Annotation3(42) initialText: String = "LoremIpsum", private @property:Annotation1(42) @field:Annotation2(42) val text: String = "dolor sit amet") {
}
@@ -11825,6 +11825,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/intentions/movePropertyToConstructor"), Pattern.compile("^([\\w\\-_]+)\\.(kt|kts)$"), TargetBackend.ANY, true);
}
@TestMetadata("annotationTarget.kt")
public void testAnnotationTarget() throws Exception {
runTest("idea/testData/intentions/movePropertyToConstructor/annotationTarget.kt");
}
@TestMetadata("annotationWithUseSite.kt")
public void testAnnotationWithUseSite() throws Exception {
runTest("idea/testData/intentions/movePropertyToConstructor/annotationWithUseSite.kt");
@@ -11850,6 +11855,11 @@ public class IntentionTestGenerated extends AbstractIntentionTest {
runTest("idea/testData/intentions/movePropertyToConstructor/getter.kt");
}
@TestMetadata("javaAnnotation.kt")
public void testJavaAnnotation() throws Exception {
runTest("idea/testData/intentions/movePropertyToConstructor/javaAnnotation.kt");
}
@TestMetadata("lambda.kt")
public void testLambda() throws Exception {
runTest("idea/testData/intentions/movePropertyToConstructor/lambda.kt");