Fix testdata after improvements in contract parsing diagnostics

This commit is contained in:
Dmitry Savvinov
2018-08-21 14:04:05 +03:00
committed by Ilya Gorbunov
parent a6bb7d1e89
commit 2179ae496e
14 changed files with 49 additions and 71 deletions
@@ -35,11 +35,12 @@ interface ContractParsingDiagnosticsCollector {
} }
} }
class TraceBasedCollector(private val bindingTrace: BindingTrace, private val mainCall: KtExpression) : ContractParsingDiagnosticsCollector { class TraceBasedCollector(private val bindingTrace: BindingTrace, mainCall: KtExpression) : ContractParsingDiagnosticsCollector {
private val diagnostics: MutableList<Diagnostic> = mutableListOf() private val diagnostics: MutableList<Diagnostic> = mutableListOf()
private val mainCallReportTarget = (mainCall as? KtCallExpression)?.calleeExpression ?: mainCall
override fun contractNotAllowed(message: String) { override fun contractNotAllowed(message: String) {
diagnostics += Errors.CONTRACT_NOT_ALLOWED.on((mainCall as? KtCallExpression)?.calleeExpression ?: mainCall, message) diagnostics += Errors.CONTRACT_NOT_ALLOWED.on(mainCallReportTarget, message)
} }
override fun badDescription(message: String, reportOn: KtElement) { override fun badDescription(message: String, reportOn: KtElement) {
@@ -47,12 +48,15 @@ class TraceBasedCollector(private val bindingTrace: BindingTrace, private val ma
} }
override fun unsupportedFeature(languageVersionSettings: LanguageVersionSettings) { override fun unsupportedFeature(languageVersionSettings: LanguageVersionSettings) {
diagnostics += Errors.UNSUPPORTED_FEATURE.on(mainCall, LanguageFeature.AllowContractsForCustomFunctions to languageVersionSettings) diagnostics += Errors.UNSUPPORTED_FEATURE.on(
mainCallReportTarget,
LanguageFeature.AllowContractsForCustomFunctions to languageVersionSettings
)
} }
override fun flushDiagnostics(parsingFailed: Boolean) { override fun flushDiagnostics(parsingFailed: Boolean) {
if (parsingFailed && diagnostics.isEmpty()) { if (parsingFailed && diagnostics.isEmpty()) {
diagnostics += Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(mainCall, "Error in contract description") diagnostics += Errors.ERROR_IN_CONTRACT_DESCRIPTION.on(mainCallReportTarget, "Error in contract description")
} }
diagnostics.forEach { bindingTrace.report(it) } diagnostics.forEach { bindingTrace.report(it) }
@@ -5,5 +5,5 @@
import kotlin.contracts.* import kotlin.contracts.*
fun emptyContract() { fun emptyContract() {
contract { } <!ERROR_IN_CONTRACT_DESCRIPTION(Error in contract description)!>contract<!> { }
} }
@@ -8,23 +8,23 @@ import kotlin.contracts.*
// ============= Class ===================== // ============= Class =====================
open class Class { open class Class {
fun member(x: Boolean) { fun member(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
inline fun inlineMember(x: Boolean) { inline fun inlineMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
abstract fun abstractMember(x: Boolean) { abstract fun abstractMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
open fun openMemeber(x: Boolean) { open fun openMemeber(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendMember(x: Boolean) { suspend fun suspendMember(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
} }
@@ -39,48 +39,48 @@ inline fun inlineTopLevel(x: Boolean) {
} }
suspend fun suspendTopLevel(x: Boolean) { suspend fun suspendTopLevel(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
// Top-level operator // Top-level operator
operator fun Boolean.plus(x: Boolean): Boolean { operator fun Boolean.plus(x: Boolean): Boolean {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
return x return x
} }
val topLevelLambda: (Boolean) -> Unit = { x: Boolean -> val topLevelLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val topLevelAnonymousFunction = fun (x: Boolean) { val topLevelAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
var topLevelPropertyAccessors: Int? = 42 var topLevelPropertyAccessors: Int? = 42
get() { get() {
contract { returns() implies (field != null) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (field != null) }
return 42 return 42
} }
set(value) { set(value) {
contract { returns() implies (field != null) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (field != null) }
} }
// ============= Local ===================== // ============= Local =====================
fun test() { fun test() {
fun localDeclaration(x: Boolean) { fun localDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
suspend fun suspendlocalDeclaration(x: Boolean) { suspend fun suspendlocalDeclaration(x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED, CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localAnonymousFunction = fun (x: Boolean) { val localAnonymousFunction = fun (x: Boolean) {
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
val localLambda: (Boolean) -> Unit = { x: Boolean -> val localLambda: (Boolean) -> Unit = { x: Boolean ->
contract { returns() implies (x) } <!CONTRACT_NOT_ALLOWED!>contract<!> { returns() implies (x) }
} }
} }
@@ -7,33 +7,20 @@ public inline fun inlineTopLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x Returns(WILDCARD) -> x
public suspend fun suspendTopLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit public suspend fun suspendTopLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public fun test(): kotlin.Unit public fun test(): kotlin.Unit
public fun topLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit public fun topLevel(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x Returns(WILDCARD) -> x
public operator fun kotlin.Boolean.plus(/*0*/ x: kotlin.Boolean): kotlin.Boolean public operator fun kotlin.Boolean.plus(/*0*/ x: kotlin.Boolean): kotlin.Boolean
Returns(WILDCARD) -> x
public open class Class { public open class Class {
public constructor Class() public constructor Class()
public abstract fun abstractMember(/*0*/ x: kotlin.Boolean): kotlin.Unit public abstract fun abstractMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final inline fun inlineMember(/*0*/ x: kotlin.Boolean): kotlin.Unit public final inline fun inlineMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public final fun member(/*0*/ x: kotlin.Boolean): kotlin.Unit public final fun member(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public open fun openMemeber(/*0*/ x: kotlin.Boolean): kotlin.Unit public open fun openMemeber(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public final suspend fun suspendMember(/*0*/ x: kotlin.Boolean): kotlin.Unit public final suspend fun suspendMember(/*0*/ x: kotlin.Boolean): kotlin.Unit
Returns(WILDCARD) -> x
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
@@ -6,50 +6,50 @@ import kotlin.contracts.*
fun ifInContract(x: Any?, boolean: Boolean) { fun ifInContract(x: Any?, boolean: Boolean) {
contract { contract {
if (boolean) { <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>if (boolean) {
returns() implies (x is String) returns() implies (x is String)
} else { } else {
returns() implies (x is Int) returns() implies (x is Int)
} }<!>
} }
} }
fun whenInContract(x: Any?, boolean: Boolean) { fun whenInContract(x: Any?, boolean: Boolean) {
contract { contract {
when (boolean) { <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>when (boolean) {
true -> returns() implies (x is String) true -> returns() implies (x is String)
else -> returns() implies (x is Int) else -> returns() implies (x is Int)
} }<!>
} }
} }
fun forInContract(x: Any?) { fun forInContract(x: Any?) {
contract { contract {
for (i in 0..1) { <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>for (i in 0..1) {
returns() implies (x is String) returns() implies (x is String)
} }<!>
} }
} }
fun whileInContract(x: Any?) { fun whileInContract(x: Any?) {
contract { contract {
while (false) { <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>while (false) {
returns() implies (x is String) returns() implies (x is String)
} }<!>
} }
} }
fun doWhileInContract(x: Any?) { fun doWhileInContract(x: Any?) {
contract { contract {
do { <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>do {
returns() implies (x is String) returns() implies (x is String)
} while (false) } while (false)<!>
} }
} }
fun localValInContract(x: Any?) { fun localValInContract(x: Any?) {
contract { contract {
val y: Int = 42 <!ERROR_IN_CONTRACT_DESCRIPTION(unexpected construction in contract description)!>val y: Int = 42<!>
returns() implies (x is String) returns() implies (x is String)
} }
} }
@@ -4,7 +4,5 @@ public fun doWhileInContract(/*0*/ x: kotlin.Any?): kotlin.Unit
public fun forInContract(/*0*/ x: kotlin.Any?): kotlin.Unit public fun forInContract(/*0*/ x: kotlin.Any?): kotlin.Unit
public fun ifInContract(/*0*/ x: kotlin.Any?, /*1*/ boolean: kotlin.Boolean): kotlin.Unit public fun ifInContract(/*0*/ x: kotlin.Any?, /*1*/ boolean: kotlin.Boolean): kotlin.Unit
public fun localValInContract(/*0*/ x: kotlin.Any?): kotlin.Unit public fun localValInContract(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is String
public fun whenInContract(/*0*/ x: kotlin.Any?, /*1*/ boolean: kotlin.Boolean): kotlin.Unit public fun whenInContract(/*0*/ x: kotlin.Any?, /*1*/ boolean: kotlin.Boolean): kotlin.Unit
public fun whileInContract(/*0*/ x: kotlin.Any?): kotlin.Unit public fun whileInContract(/*0*/ x: kotlin.Any?): kotlin.Unit
@@ -12,7 +12,7 @@ fun equalsWithVariables(x: Any?, y: Any?) {
fun identityEqualsWithVariables(x: Any?, y: Any?) { fun identityEqualsWithVariables(x: Any?, y: Any?) {
contract { contract {
returns() implies (x === y) returns() implies (<!ERROR_IN_CONTRACT_DESCRIPTION(only equality comparisons with 'null' allowed)!>x === y<!>)
} }
} }
@@ -5,7 +5,7 @@
import kotlin.contracts.* import kotlin.contracts.*
fun foo(boolean: Boolean) { fun foo(boolean: Boolean) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION(Error in contract description)!>contract<!> {
(returns() implies (boolean)) <!UNRESOLVED_REFERENCE!>implies<!> (!boolean) (returns() implies (boolean)) <!UNRESOLVED_REFERENCE!>implies<!> (!boolean)
} }
} }
@@ -5,11 +5,11 @@
import kotlin.contracts.* import kotlin.contracts.*
fun passLambdaValue(l: ContractBuilder.() -> Unit) { fun passLambdaValue(l: ContractBuilder.() -> Unit) {
contract(l) contract(<!ERROR_IN_CONTRACT_DESCRIPTION(first argument of 'contract'-call should be a lambda expression)!>l<!>)
} }
fun passAnonymousFunction(x: Boolean) { fun passAnonymousFunction(x: Boolean) {
contract(fun ContractBuilder.() { contract(<!ERROR_IN_CONTRACT_DESCRIPTION(first argument of 'contract'-call should be a lambda expression)!>fun ContractBuilder.() {
returns() implies x returns() implies x
}) }<!>)
} }
@@ -6,7 +6,7 @@ import kotlin.contracts.*
fun foo(y: Boolean) { fun foo(y: Boolean) {
val <!UNUSED_VARIABLE!>x<!>: Int = 42 val <!UNUSED_VARIABLE!>x<!>: Int = 42
<!CONTRACT_NOT_ALLOWED!>contract { <!CONTRACT_NOT_ALLOWED(Contract should be the first statement)!>contract<!> {
returns() implies y returns() implies y
}<!> }
} }
@@ -6,8 +6,8 @@ import kotlin.contracts.*
class Foo(val x: Int?) { class Foo(val x: Int?) {
fun isXNull(): Boolean { fun isXNull(): Boolean {
contract { <!CONTRACT_NOT_ALLOWED!>contract<!> {
returns(false) implies (<!ERROR_IN_CONTRACT_DESCRIPTION(only references to parameters are allowed in contract description)!>x<!> != null) returns(false) implies (x != null)
} }
return x != null return x != null
} }
@@ -6,20 +6,20 @@ import kotlin.contracts.*
inline fun <reified T> referToReifiedGeneric(x: Any?) { inline fun <reified T> referToReifiedGeneric(x: Any?) {
contract { contract {
returns() implies (x is T) returns() implies (x is <!ERROR_IN_CONTRACT_DESCRIPTION(references to type parameters are forbidden in contracts)!>T<!>)
} }
} }
class Generic<T> { class Generic<T> {
fun referToCaptured(x: Any?) { fun referToCaptured(x: Any?) {
contract { <!CONTRACT_NOT_ALLOWED(Contracts are allowed only for top-level functions)!>contract<!> {
returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>T<!>) returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>T<!>)
} }
} }
} }
fun referToSubstituted(x: Any?) { fun referToSubstituted(x: Any?) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION(Error in contract description)!>contract<!> {
returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>Generic<String><!>) returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>Generic<String><!>)
} }
} }
@@ -35,13 +35,13 @@ typealias FunctionalType = () -> Unit
typealias SimpleType = Int typealias SimpleType = Int
fun referToAliasedGeneric(x: Any?) { fun referToAliasedGeneric(x: Any?) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION(Error in contract description)!>contract<!> {
returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>GenericString<!>) returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>GenericString<!>)
} }
} }
fun referToAliasedFunctionType(x: Any?) { fun referToAliasedFunctionType(x: Any?) {
contract { <!ERROR_IN_CONTRACT_DESCRIPTION(Error in contract description)!>contract<!> {
returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>FunctionalType<!>) returns() implies (x is <!CANNOT_CHECK_FOR_ERASED!>FunctionalType<!>)
} }
} }
@@ -1,20 +1,12 @@
package package
public fun referToAliasedFunctionType(/*0*/ x: kotlin.Any?): kotlin.Unit public fun referToAliasedFunctionType(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is Function0<Unit>
public fun referToAliasedGeneric(/*0*/ x: kotlin.Any?): kotlin.Unit public fun referToAliasedGeneric(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is Generic<String>
public fun referToAliasedSimpleType(/*0*/ x: kotlin.Any?): kotlin.Unit public fun referToAliasedSimpleType(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is Int Returns(WILDCARD) -> x is Int
public inline fun </*0*/ reified T> referToReifiedGeneric(/*0*/ x: kotlin.Any?): kotlin.Unit public inline fun </*0*/ reified T> referToReifiedGeneric(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is T
public fun referToSubstituted(/*0*/ x: kotlin.Any?): kotlin.Unit public fun referToSubstituted(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is Generic<String>
public fun referToSubstitutedWithStar(/*0*/ x: kotlin.Any?): kotlin.Unit public fun referToSubstitutedWithStar(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is Generic<*> Returns(WILDCARD) -> x is Generic<*>
@@ -23,8 +15,6 @@ public final class Generic</*0*/ T> {
public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean
public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int
public final fun referToCaptured(/*0*/ x: kotlin.Any?): kotlin.Unit public final fun referToCaptured(/*0*/ x: kotlin.Any?): kotlin.Unit
Returns(WILDCARD) -> x is T
public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String
} }
public typealias FunctionalType = () -> kotlin.Unit public typealias FunctionalType = () -> kotlin.Unit
@@ -1,4 +1,3 @@
package package
public fun kotlin.Any?.foo(): kotlin.Boolean public fun kotlin.Any?.foo(): kotlin.Boolean
Returns(TRUE) -> <this> != null