-
-
Notifications
You must be signed in to change notification settings - Fork 1.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add Kotlin contracts to exposed Kotlin API #1866
Comments
This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. Thank you for your contribution. |
This sounds like a useful usability feature! |
This issue has been automatically marked as stale because it has not had recent activity. Given the limited bandwidth of the team, it will be automatically closed if no further activity occurs. Thank you for your contribution. |
Please do this. |
This issue has been automatically closed due to inactivity. If you have a good use case for this feature, please feel free to reopen the issue. |
@junit-team What is missing to move this forward? @JLLeitschuh I think these might also be deliverables for full coverage:
|
Is anyone working on this issue? |
Not currently, but I figure at this point it would be safe to do so as Kotlin 1.3 is pretty EOL as of 2 years ago: https://endoflife.date/kotlin |
Also, this library currently supports Kotlin versions 1.3 and above, so it would now be safe to add: junit5/gradle/plugins/common/src/main/kotlin/junitbuild.kotlin-library-conventions.gradle.kts Lines 8 to 14 in e188b1e
If someone wants to open a pull request to add support for this, I'm more than happy to review it |
Okay. |
@JLLeitschuh how can this be tested with automation? Because contracts should induce Kotlin compilation failures. I guess the positive cases of smart casts as results of contract can be tested:
(if the contracts stop working, the above test will not compile) |
As you suggested, I would use the compiler as your validation |
Added assertNull and assertNotNull methods with contracts. Added contracts for assertThrows and assertDoesNotThrow methods. assertInstanceOf can be implemented only with kotlin 1.4, because refined generics [are not supported](https://youtrack.jetbrains.com/issue/KT-28298) in contracts for kotlin 1.3 yet. Issue: junit-team#1866
Kotlin assertNull and assertNotNull methods are marked as experimental. Issue: junit-team#1866
Contracts with reified generics are supported only since kotlin 1.4. Therefore, |
I wondered if the that error is suppressed will it emit 1.4 compatible bytecode for the contract? Therefore making it possible to use the same jar binary from both 1.3 and 1.4. so I tested it... but doesn't seem so(For reference the Kotlin version is declared in kotlin-library-conventions.gradle.kts) // kotlinc -language-version 1.3 -api-version 1.3 -d assertIsInstance.jar -opt-in=kotlin.contracts.ExperimentalContracts assertIsInstance.kt
package test
import kotlin.contracts.contract
inline fun <reified T> assertIsInstance(value: Any?) {
contract {
returns() implies (value is @Suppress("ERROR_IN_CONTRACT_DESCRIPTION") T)
}
require(T::class.java.isInstance(value))
} // kotlinc -language-version 1.4 -api-version 1.4 -cp assertIsInstance.jar usage.kt
import test.assertIsInstance
fun main() {
val cs: CharSequence = ""
assertIsInstance<String>(cs)
val str: String = cs
println(str)
}
// usage.kt:6:23: error: type mismatch: inferred type is CharSequence but String was expected
// val str: String = cs
// ^ If the Funny thing: if |
Lambda invoked in assertThrows is marked as being called UNKNOWN number of times, since contracts do nothing with exception suppression Issue: junit-team#1866
Created another fail method with a non-nullable lambda parameter Issue: junit-team#1866
Added assertNull and assertNotNull methods with contracts. Added contracts for assertThrows and assertDoesNotThrow methods. assertInstanceOf can be implemented only with kotlin 1.4, because refined generics [are not supported](https://youtrack.jetbrains.com/issue/KT-28298) in contracts for kotlin 1.3 yet. Issue: junit-team#1866
Kotlin assertNull and assertNotNull methods are marked as experimental. Issue: junit-team#1866
Lambda invoked in assertThrows is marked as being called UNKNOWN number of times, since contracts do nothing with exception suppression Issue: junit-team#1866
Created another fail method with a non-nullable lambda parameter Issue: junit-team#1866
Since kotlin version has been bumped to 1.6, it should be possible to implement |
Because of kotlin smart casts, there is no need to return a non-nullable value from `assertNotNull` methods Issue: junit-team#1866
Api version is increased to 5.11 for `assertNull` and `assertNotNull` methods Issue: junit-team#1866
Added `assertInstanceOf` assertions with upcasting contracts Issue: junit-team#1866
Invocation kind for the executable is UNKNOWN for assertTimeoutPreemptively methods Issue: junit-team#1866
Foreward
First off, I want to thank the Junit 5 team from being so willing to officially support Kotlin as a first-class citizen in the Junit 5 library. It has been absolutely wonderful being able to use my own contributions in all of my Kotlin projects.
Feature Request
I believe that this API can be further enhanced with the new Kotlin 1.3 feature, Contracts.
Contracts are making guarantees to the compiler that various methods have certain characteristics.
Here's an example from the Kotlin Std-Lib:
Before Kotlin Contracts, the following code wouldn't have compiled:
I believe that JUnit 5 has a few places where these contracts would be valuable.
Examples
assertNotNull
The above would allow something like this:
Alternatively, it would also allow for this sort of use case:
assertThrows
/assertDoesNotThrow
Since the
callable
passed toassertThrows
is only ever called once, we can expose that in the contract.Similar
This would for something like this:
Caveats
Kotlin Contracts are only supported in Kotlin 1.3 and higher.
This would require a discussion regarding what version of Kotlin the Junit 5 team want's to officially support.
Deliverables
assertNotNull
assertNotNull
assertThrows
assertDoesNotThrow
The text was updated successfully, but these errors were encountered: