CFG: mark annotation arguments as "used as expressions" #KT-24596 Fixed
NB: only classes / function / properties annotations are considered here, not including local declarations and other annotations
This commit is contained in:
@@ -32,6 +32,7 @@ import org.jetbrains.kotlin.idea.MainFunctionDetector
|
|||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
import org.jetbrains.kotlin.psi.psiUtil.containingClassOrObject
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
import org.jetbrains.kotlin.resolve.*
|
import org.jetbrains.kotlin.resolve.*
|
||||||
import org.jetbrains.kotlin.resolve.BindingContext.*
|
import org.jetbrains.kotlin.resolve.BindingContext.*
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
@@ -97,6 +98,7 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
markStatements()
|
markStatements()
|
||||||
|
markAnnotationArguments()
|
||||||
|
|
||||||
markUnusedExpressions()
|
markUnusedExpressions()
|
||||||
|
|
||||||
@@ -799,6 +801,21 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun markAnnotationArguments() {
|
||||||
|
when (subroutine) {
|
||||||
|
is KtAnnotationEntry -> markAnnotationArguments(subroutine)
|
||||||
|
is KtAnnotated -> subroutine.annotationEntries.forEach { markAnnotationArguments(it) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun markAnnotationArguments(entry: KtAnnotationEntry) {
|
||||||
|
for (argument in entry.valueArguments) {
|
||||||
|
argument.getArgumentExpression()?.forEachDescendantOfType<KtExpression> {
|
||||||
|
trace.record(USED_AS_EXPRESSION, it, true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private fun checkIfExpressions() = pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
private fun checkIfExpressions() = pseudocode.traverse(TraversalOrder.FORWARD) { instruction ->
|
||||||
val value = (instruction as? InstructionWithValue)?.outputValue
|
val value = (instruction as? InstructionWithValue)?.outputValue
|
||||||
for (element in instruction.owner.getValueElements(value)) {
|
for (element in instruction.owner.getValueElements(value)) {
|
||||||
|
|||||||
@@ -0,0 +1,25 @@
|
|||||||
|
private const val <caret>TAG = "Tagged"
|
||||||
|
|
||||||
|
annotation class InAnn(val value: String)
|
||||||
|
|
||||||
|
@InAnn(TAG) class AnnHolder
|
||||||
|
|
||||||
|
@InAnn(value = TAG) class AnotherAnnHolder
|
||||||
|
|
||||||
|
@InAnn("This is $TAG") class ComplexAnnHolder {
|
||||||
|
@InAnn("That is $TAG") fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InAnn("This is also $TAG") fun bar() {}
|
||||||
|
|
||||||
|
fun baz(@InAnn("This is $TAG too") x: Int) {}
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class ExprAnn(val value: String)
|
||||||
|
|
||||||
|
val inProperty = TAG
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val x = @ExprAnn(TAG) inProperty
|
||||||
|
}
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
annotation class InAnn(val value: String)
|
||||||
|
|
||||||
|
@InAnn("Tagged") class AnnHolder
|
||||||
|
|
||||||
|
@InAnn(value = "Tagged") class AnotherAnnHolder
|
||||||
|
|
||||||
|
@InAnn("This is Tagged") class ComplexAnnHolder {
|
||||||
|
@InAnn("That is Tagged") fun foo() {}
|
||||||
|
}
|
||||||
|
|
||||||
|
@InAnn("This is also Tagged") fun bar() {}
|
||||||
|
|
||||||
|
fun baz(@InAnn("This is ${} too") x: Int) {}
|
||||||
|
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class ExprAnn(val value: String)
|
||||||
|
|
||||||
|
val inProperty = "Tagged"
|
||||||
|
|
||||||
|
fun foo() {
|
||||||
|
val x = @ExprAnn() inProperty
|
||||||
|
}
|
||||||
+5
@@ -521,6 +521,11 @@ public class InlineTestGenerated extends AbstractInlineTest {
|
|||||||
runTest("idea/testData/refactoring/inline/inlineVariableOrProperty/ifInQualifiedExpression.kt");
|
runTest("idea/testData/refactoring/inline/inlineVariableOrProperty/ifInQualifiedExpression.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("InAnnotation.kt")
|
||||||
|
public void testInAnnotation() throws Exception {
|
||||||
|
runTest("idea/testData/refactoring/inline/inlineVariableOrProperty/InAnnotation.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("InFunctionLiteral.kt")
|
@TestMetadata("InFunctionLiteral.kt")
|
||||||
public void testInFunctionLiteral() throws Exception {
|
public void testInFunctionLiteral() throws Exception {
|
||||||
runTest("idea/testData/refactoring/inline/inlineVariableOrProperty/InFunctionLiteral.kt");
|
runTest("idea/testData/refactoring/inline/inlineVariableOrProperty/InFunctionLiteral.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user