diff --git a/compiler/frontend/src/org/jetbrains/kotlin/contracts/parsing/PsiContractParserDispatcher.kt b/compiler/frontend/src/org/jetbrains/kotlin/contracts/parsing/PsiContractParserDispatcher.kt index f6ad47bb77a..21a51bc3c42 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/contracts/parsing/PsiContractParserDispatcher.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/contracts/parsing/PsiContractParserDispatcher.kt @@ -35,10 +35,7 @@ import org.jetbrains.kotlin.contracts.parsing.effects.PsiReturnsEffectParser import org.jetbrains.kotlin.descriptors.ParameterDescriptor import org.jetbrains.kotlin.descriptors.ReceiverParameterDescriptor import org.jetbrains.kotlin.name.Name -import org.jetbrains.kotlin.psi.KtBinaryExpression -import org.jetbrains.kotlin.psi.KtCallExpression -import org.jetbrains.kotlin.psi.KtExpression -import org.jetbrains.kotlin.psi.KtLambdaExpression +import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall import org.jetbrains.kotlin.resolve.calls.callUtil.getType import org.jetbrains.kotlin.storage.StorageManager @@ -129,9 +126,10 @@ internal class PsiContractParserDispatcher( fun parseVariable(expression: KtExpression?): VariableReference? { if (expression == null) return null - val descriptor = expression.getResolvedCall(callContext.bindingContext)?.resultingDescriptor ?: return null + val descriptor = expression.getResolvedCall(callContext.bindingContext)?.resultingDescriptor if (descriptor !is ParameterDescriptor) { - collector.badDescription("only references to parameters are allowed in contract description", expression) + if (expression !is KtConstantExpression) + collector.badDescription("only references to parameters are allowed in contract description", expression) return null } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.kt index 8bb678e638e..73f803b5b4e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/2.kt @@ -25,7 +25,7 @@ fun case_2(value_1: Boolean): Boolean? { // TESTCASE NUMBER: 3 fun case_3(value_1: String): Boolean { - contract { returns(false) implies (value_1 != "") } + contract { returns(false) implies (value_1 != "") } return !(value_1 != "") } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.kt index 659b17e6068..43c8bf7ae95 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/3.kt @@ -37,7 +37,7 @@ fun case_4(value_1: Nothing?, value_2: Boolean?): Boolean? { // TESTCASE NUMBER: 5 fun case_5(value_1: Any?, value_2: String?): Boolean? { - contract { returns(null) implies (value_1 != null && value_2 != null || value_2 == ".") } + contract { returns(null) implies (value_1 != null && value_2 != null || value_2 == ".") } return if (value_1 != null && value_2 != null || value_2 == ".") null else true } diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.kt index 4512fefe0b5..7717898c5e5 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.kt @@ -51,3 +51,22 @@ fun case_6(value_1: Boolean): Boolean? { contract { returns(null) implies contract { returns(null) implies (!value_1) } } return null } + +// TESTCASE NUMBER: 7 +fun case_7(): Int { + contract { + callsInPlace(::case_7, InvocationKind.EXACTLY_ONCE) + } + return 1 +} + +/* + * TESTCASE NUMBER: 8 + * ISSUES: KT-26386 + */ +fun case_8(): () -> Unit { + contract { + callsInPlace(case_8(), InvocationKind.EXACTLY_ONCE) + } + return {} +} \ No newline at end of file diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.txt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.txt index c75b746f078..0d593b9034e 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.txt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/common/neg/5.txt @@ -3,5 +3,8 @@ package public fun case_1(): kotlin.Boolean public fun case_2(): kotlin.Boolean public fun case_3(): kotlin.Boolean +public fun case_4(): kotlin.Boolean? public fun case_5(): kotlin.Boolean? public fun case_6(/*0*/ value_1: kotlin.Boolean): kotlin.Boolean? +public fun case_7(): kotlin.Int +public fun case_8(): () -> kotlin.Unit diff --git a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.kt b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.kt index b30ca3f49db..4c3a30d2924 100644 --- a/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.kt +++ b/compiler/tests-spec/testData/diagnostics/notLinked/contracts/declarations/contractBuilder/effects/returns/neg/4.kt @@ -19,7 +19,7 @@ fun case_1(x: Any?): Boolean { // TESTCASE NUMBER: 2 fun case_2(x: Any?) { - contract { returns() implies (x == "...") } + contract { returns() implies (x == "...") } if (x != "...") throw Exception() }