[CFA] Mark arguments of all annotation calls as USED_AS_EXPRESSION
Also revert hacky fix of KT-37294 introduced in 80caa063b
#KT-37447 Fixed
This commit is contained in:
@@ -804,9 +804,14 @@ class ControlFlowInformationProvider private constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun markAnnotationArguments() {
|
private fun markAnnotationArguments() {
|
||||||
when (subroutine) {
|
if (subroutine is KtAnnotationEntry) {
|
||||||
is KtAnnotationEntry -> markAnnotationArguments(subroutine)
|
markAnnotationArguments(subroutine)
|
||||||
is KtAnnotated -> subroutine.annotationEntries.forEach { markAnnotationArguments(it) }
|
} else {
|
||||||
|
subroutine.children.forEach { child ->
|
||||||
|
child.forEachDescendantOfType<KtAnnotationEntry>(
|
||||||
|
canGoInside = { it !is KtDeclaration || it is KtParameter }
|
||||||
|
) { markAnnotationArguments(it) }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+104
@@ -0,0 +1,104 @@
|
|||||||
|
== Test_1 ==
|
||||||
|
class Test_1 {
|
||||||
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(@Range(min = -90L) x: Int) = Unit // KtPrefixExpression isn't marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(@Range(min = -90L) x: Int) = Unit // KtPrefixExpression isn't marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(@Range(min = -90L) x: Int)
|
||||||
|
magic[FAKE_INITIALIZER](@Range(min = -90L) x: Int) -> <v0>
|
||||||
|
w(x|<v0>)
|
||||||
|
r(Unit) -> <v1>
|
||||||
|
ret(*|<v1>) L1
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== Test_2 ==
|
||||||
|
class Test_2 {
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
@Range(min = -90L) // KtPrefixExpression is marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
fun foo(x: Int) = Unit
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
@Range(min = -90L) // KtPrefixExpression is marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
fun foo(x: Int) = Unit
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(x: Int)
|
||||||
|
magic[FAKE_INITIALIZER](x: Int) -> <v0>
|
||||||
|
w(x|<v0>)
|
||||||
|
r(Unit) -> <v1>
|
||||||
|
ret(*|<v1>) L1
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== Test_3 ==
|
||||||
|
class Test_3 {
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(x: Int) = @Range(min = -90L) Unit
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(x: Int) = @Range(min = -90L) Unit
|
||||||
|
---------------------
|
||||||
|
L0:
|
||||||
|
1 <START>
|
||||||
|
v(x: Int)
|
||||||
|
magic[FAKE_INITIALIZER](x: Int) -> <v0>
|
||||||
|
w(x|<v0>)
|
||||||
|
r(Unit) -> <v1>
|
||||||
|
ret(*|<v1>) L1
|
||||||
|
L1:
|
||||||
|
<END> NEXT:[<SINK>]
|
||||||
|
error:
|
||||||
|
<ERROR> PREV:[]
|
||||||
|
sink:
|
||||||
|
<SINK> PREV:[<ERROR>, <END>]
|
||||||
|
=====================
|
||||||
+23
@@ -0,0 +1,23 @@
|
|||||||
|
// ISSUE: KT-37447
|
||||||
|
|
||||||
|
class Test_1 {
|
||||||
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(@Range(min = -90L) x: Int) = Unit // KtPrefixExpression isn't marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test_2 {
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
@Range(min = -90L) // KtPrefixExpression is marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
fun foo(x: Int) = Unit
|
||||||
|
}
|
||||||
|
|
||||||
|
class Test_3 {
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(x: Int) = @Range(min = -90L) Unit
|
||||||
|
}
|
||||||
+48
@@ -0,0 +1,48 @@
|
|||||||
|
== Test_1 ==
|
||||||
|
class Test_1 {
|
||||||
|
@Target(AnnotationTarget.VALUE_PARAMETER)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(@Range(min = -90L) x: Int) = Unit // KtPrefixExpression isn't marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(@Range(min = -90L) x: Int) = Unit // KtPrefixExpression isn't marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](@Range(min = -90L) x: Int) -> <v0>
|
||||||
|
Unit <v1>: Unit NEW: r(Unit) -> <v1>
|
||||||
|
=====================
|
||||||
|
== Test_2 ==
|
||||||
|
class Test_2 {
|
||||||
|
@Target(AnnotationTarget.FUNCTION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
@Range(min = -90L) // KtPrefixExpression is marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
fun foo(x: Int) = Unit
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
@Range(min = -90L) // KtPrefixExpression is marked as BindingContext.USED_AS_EXPRESSION
|
||||||
|
fun foo(x: Int) = Unit
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](x: Int) -> <v0>
|
||||||
|
Unit <v1>: Unit NEW: r(Unit) -> <v1>
|
||||||
|
=====================
|
||||||
|
== Test_3 ==
|
||||||
|
class Test_3 {
|
||||||
|
@Target(AnnotationTarget.EXPRESSION)
|
||||||
|
annotation class Range(val min: Long = 0)
|
||||||
|
|
||||||
|
fun foo(x: Int) = @Range(min = -90L) Unit
|
||||||
|
}
|
||||||
|
---------------------
|
||||||
|
=====================
|
||||||
|
== foo ==
|
||||||
|
fun foo(x: Int) = @Range(min = -90L) Unit
|
||||||
|
---------------------
|
||||||
|
<v0>: Int NEW: magic[FAKE_INITIALIZER](x: Int) -> <v0>
|
||||||
|
Unit <v1>: Unit NEW: r(Unit) -> <v1>
|
||||||
|
@Range(min = -90L) Unit <v1>: Unit COPY
|
||||||
|
=====================
|
||||||
@@ -148,6 +148,11 @@ public class ControlFlowTestGenerated extends AbstractControlFlowTest {
|
|||||||
runTest("compiler/testData/cfg/bugs/kt10105.kt");
|
runTest("compiler/testData/cfg/bugs/kt10105.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt37447.kt")
|
||||||
|
public void testKt37447() throws Exception {
|
||||||
|
runTest("compiler/testData/cfg/bugs/kt37447.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7761.kt")
|
@TestMetadata("kt7761.kt")
|
||||||
public void testKt7761() throws Exception {
|
public void testKt7761() throws Exception {
|
||||||
runTest("compiler/testData/cfg/bugs/kt7761.kt");
|
runTest("compiler/testData/cfg/bugs/kt7761.kt");
|
||||||
|
|||||||
@@ -148,6 +148,11 @@ public class PseudoValueTestGenerated extends AbstractPseudoValueTest {
|
|||||||
runTest("compiler/testData/cfg/bugs/kt10105.kt");
|
runTest("compiler/testData/cfg/bugs/kt10105.kt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt37447.kt")
|
||||||
|
public void testKt37447() throws Exception {
|
||||||
|
runTest("compiler/testData/cfg/bugs/kt37447.kt");
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("kt7761.kt")
|
@TestMetadata("kt7761.kt")
|
||||||
public void testKt7761() throws Exception {
|
public void testKt7761() throws Exception {
|
||||||
runTest("compiler/testData/cfg/bugs/kt7761.kt");
|
runTest("compiler/testData/cfg/bugs/kt7761.kt");
|
||||||
|
|||||||
@@ -15,11 +15,8 @@ import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
|
|||||||
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
import org.jetbrains.kotlin.idea.caches.resolve.analyze
|
||||||
import org.jetbrains.kotlin.idea.util.textRangeIn
|
import org.jetbrains.kotlin.idea.util.textRangeIn
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.KtAnnotationEntry
|
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
|
||||||
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
import org.jetbrains.kotlin.psi.KtPrefixExpression
|
||||||
import org.jetbrains.kotlin.psi.prefixExpressionVisitor
|
import org.jetbrains.kotlin.psi.prefixExpressionVisitor
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
|
|
||||||
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
import org.jetbrains.kotlin.resolve.bindingContextUtil.isUsedAsExpression
|
||||||
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
|
||||||
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
import org.jetbrains.kotlin.resolve.lazy.BodyResolveMode
|
||||||
@@ -30,8 +27,6 @@ class UnusedUnaryOperatorInspection : AbstractKotlinInspection() {
|
|||||||
val operationToken = prefix.operationToken
|
val operationToken = prefix.operationToken
|
||||||
if (operationToken != KtTokens.PLUS && operationToken != KtTokens.MINUS) return
|
if (operationToken != KtTokens.PLUS && operationToken != KtTokens.MINUS) return
|
||||||
|
|
||||||
// ISSUE: KT-37447
|
|
||||||
if (prefix.isInAnnotationEntry) return
|
|
||||||
val context = prefix.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
|
val context = prefix.analyze(BodyResolveMode.PARTIAL_WITH_CFA)
|
||||||
if (prefix.isUsedAsExpression(context)) return
|
if (prefix.isUsedAsExpression(context)) return
|
||||||
val operatorDescriptor = prefix.operationReference.getResolvedCall(context)?.resultingDescriptor as? DeclarationDescriptor ?: return
|
val operatorDescriptor = prefix.operationReference.getResolvedCall(context)?.resultingDescriptor as? DeclarationDescriptor ?: return
|
||||||
@@ -58,6 +53,3 @@ class UnusedUnaryOperatorInspection : AbstractKotlinInspection() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val KtPrefixExpression.isInAnnotationEntry: Boolean
|
|
||||||
get() = parentsWithSelf.takeWhile { it is KtExpression }.last().parent?.parent?.parent is KtAnnotationEntry
|
|
||||||
Reference in New Issue
Block a user