Data flow values: more accurate handling of postfix ++ and --

This commit is contained in:
Mikhail Glukhikh
2016-07-25 10:49:49 +03:00
parent 7c66f632ca
commit c7af3f7865
4 changed files with 39 additions and 5 deletions
@@ -22,6 +22,7 @@ import org.jetbrains.kotlin.cfg.ControlFlowInformationProvider
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.LocalVariableDescriptor
import org.jetbrains.kotlin.descriptors.impl.SyntheticFieldDescriptor
import org.jetbrains.kotlin.lexer.KtToken
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.before
@@ -140,10 +141,11 @@ object DataFlowValueFactory {
type: KotlinType
) = DataFlowValue(ExpressionIdentifierInfo(expression, stableComplex = true), type)
private data class PostfixIdentifierInfo(val argumentInfo: IdentifierInfo) : IdentifierInfo {
// For only ++ and -- postfix operations
private data class PostfixIdentifierInfo(val argumentInfo: IdentifierInfo, val op: KtToken) : IdentifierInfo {
override val kind: DataFlowValue.Kind get() = argumentInfo.kind
override fun toString() = "$argumentInfo (postfix)"
override fun toString() = "$argumentInfo($op)"
}
class ExpressionIdentifierInfo(val expression: KtExpression, stableComplex: Boolean = false) : IdentifierInfo {
@@ -157,12 +159,12 @@ object DataFlowValueFactory {
override fun toString() = expression.text ?: "(empty expression)"
}
private fun postfix(argumentInfo: IdentifierInfo) =
private fun postfix(argumentInfo: IdentifierInfo, op: KtToken) =
if (argumentInfo == IdentifierInfo.NO) {
IdentifierInfo.NO
}
else {
PostfixIdentifierInfo(argumentInfo)
PostfixIdentifierInfo(argumentInfo, op)
}
private fun getIdForStableIdentifier(
@@ -195,7 +197,8 @@ object DataFlowValueFactory {
is KtPostfixExpression -> {
val operationType = expression.operationReference.getReferencedNameElementType()
if (operationType === KtTokens.PLUSPLUS || operationType === KtTokens.MINUSMINUS) {
postfix(getIdForStableIdentifier(expression.baseExpression, bindingContext, containingDeclarationOrModule))
postfix(getIdForStableIdentifier(expression.baseExpression, bindingContext, containingDeclarationOrModule),
operationType)
}
else {
IdentifierInfo.NO
@@ -0,0 +1,20 @@
fun foo(arg: Int?): Int {
var i = arg
if (i != null && <!DEBUG_INFO_SMARTCAST!>i<!>++ == 5) {
return <!DEBUG_INFO_SMARTCAST!><!DEBUG_INFO_SMARTCAST!>i<!>--<!> + <!DEBUG_INFO_SMARTCAST!>i<!>
}
return 0
}
operator fun Long?.inc() = this?.let { it + 1 }
fun bar(arg: Long?): Long {
var i = arg
if (i++ == 5L) {
return i<!UNSAFE_CALL!>--<!> <!DEBUG_INFO_ELEMENT_WITH_ERROR_TYPE!>+<!> i
}
if (i++ == 7L) {
return i++ <!NONE_APPLICABLE!>+<!> i
}
return 0L
}
@@ -0,0 +1,5 @@
package
public fun bar(/*0*/ arg: kotlin.Long?): kotlin.Long
public fun foo(/*0*/ arg: kotlin.Int?): kotlin.Int
public operator fun kotlin.Long?.inc(): kotlin.Long?
@@ -18728,6 +18728,12 @@ public class DiagnosticsTestGenerated extends AbstractDiagnosticsTest {
doTest(fileName);
}
@TestMetadata("plusplusMinusminus.kt")
public void testPlusplusMinusminus() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varnotnull/plusplusMinusminus.kt");
doTest(fileName);
}
@TestMetadata("postfixNotnullClassIncrement.kt")
public void testPostfixNotnullClassIncrement() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/smartCasts/varnotnull/postfixNotnullClassIncrement.kt");