Jacoco 1 of 4 branch is missing - kotlin

I am using Jacoco to check the coverage of my test, i tried lots of way but it still warning 1 of 4 branches missed
fun countingDeleteDemo() : Int {
return list.count { it.isDeleted() }
}
How can I know what branch is missed? I have read some posts about the logic true && false, but is there any documents or official link about the mistake of the coverage tools?

Jacoco checks the code coverage on byte code and not on source code. As far as I know Jacoco does not show which branch is missing.
If you use IntelliJ IDEA, you can check the kotlin bytecode.
Here, the missing branch in my IDE.
// ... omitted
INVOKESTATIC kotlin/collections/CollectionsKt.throwCountOverflow ()V
// ... omitted
Kotlin's has many builtin extension function count for Iterable, Array ...
I presume that your list is a simple List, so an Iterable.
You do not have much more elements than Int.MAX_VALUE which will make the count negative.
But one can pass an iterable which may have beyond Int.MAX_VALUE elements to count.
As a good citizen, the kotlin jvm implementation checks count overflow.
You can check out the implementation details.
public inline fun <T> Iterable<T>.count(predicate: (T) -> Boolean): Int {
if (this is Collection && isEmpty()) return 0
var count = 0
for (element in this) if (predicate(element)) checkCountOverflow(++count)
return count
}
#PublishedApi
#SinceKotlin("1.3")
#InlineOnly
internal actual inline fun checkCountOverflow(count: Int): Int {
if (count < 0) {
if (apiVersionIsAtLeast(1, 3, 0))
throwCountOverflow()
else
throw ArithmeticException("Count overflow has happened.")
}
return count
}
https://github.com/JetBrains/kotlin/blob/b8ea48fdc29678b6d99cb1b7bad312f917ea9529/libraries/stdlib/jvm/src/kotlin/collections/CollectionsJVM.kt#L111

Related

Pre-initialize size of List/Collection/etc [duplicate]

I'm creating a list of values, in a context where it so happens that, though the values are being added one at a time, the eventual number is known in advance. This is in a function that will be called many times, so the faster it runs, the better.
In Java, I would use the ArrayList constructor that specifies an initial capacity, because in theory this makes it slightly faster because it avoids resizing.
In Kotlin, one normally uses mutableListOf(), but this does not allow an initial capacity; in theory this should result in slightly slower code.
Is the recommended/idiomatic Kotlin solution in this case:
Go ahead and use the ArrayList constructor; ArrayList is a perfectly valid MutableList.
Ignore the issue; the initial capacity never actually makes a measurable difference to speed.
Something else?
Fill an immutable list
val doubles = List(5) { i -> i * 2 }
result --> [0, 2, 4, 6, 8]
Fill a mutable list of five elements with zeros
val ints = MutableList(5) { 0 }
result --> [0, 0, 0, 0, 0]
Updated Answer
I was actually confused with capacity and size. There is no implementation of using a default capacity MutableList currently in Kotlin stdlib.
You can make one yourself.
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
// creates a MutableList of Int with capacity of 5.
val mutableList = mutableListWithCapacity<Int>(5)
Outdated Answer
One of the reason why mutableListOf does not allow for default capacity is because default values in kotlin is not null.
However there is a utility function defined in kotlin.collections package.
public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> {
val list = ArrayList<T>(size)
repeat(size) { index -> list.add(init(index)) }
return list
}
You can create a List with a List function or MutableList function with a default capacity and its mapping.
// creates a list of ints with default capacity of 10 and having nulls.
// But I highly doubt you should initialize it with a null since Kotlin is a null-safe language.
val list = MutableList<Int?>(10) { null }
But since there should not be nulls in Kotlin if it is intended use of non-null list else you have to do a null check using operators like ?. !!..
You can wrap this mutableList() predefined function in a function like the following
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
this will return a MutableList of size size but also with null assigned to all of its cells. Now if you want to access any index value, your program will not crash with java.lang.IndexOutOfBoundsException like it would if you use the solution in the accepted answer. Here is what I mean:
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
fun main() {
val mutableList1 = mutableListWithCapacity<Int>(20)
val mutableList2 = emptyMutableList<Int>(20)
mutableList1[10] // this will throw a java.lang.IndexOutOfBoundsException
mutableList2[10] // this will not throw an exception but it will return null
}
Of course everything depends on how memory efficient vs crash-free you want your program to be.
Happy coding!

Why do I get the information Enum argument can be null in Java, but exhaustive when contains no null branch in Kotlin?

Code B works well, but the Code A get the following warning prompt (It can run), why?
Enum argument can be null in Java, but exhaustive when contains no null branch
I think _playState.value can be null in Code B too, do I should add null branch when I use exhaustive when in Code B?
Code A
private val _selectAction = MutableLiveData<ESelect>()
val selectAction: LiveData<ESelect> = _selectAction
selectAction.observe(mLifecycleOwner) {
when(it) { //Enum argument can be null in Java, but exhaustive when contains no null branch
ESelect.SelectAll -> binding.chSelect.isChecked = true
ESelect.UnselectAll -> binding.chSelect.isChecked = false
ESelect.NoAction -> Unit
}
}
enum class ESelect{
SelectAll,
UnselectAll,
NoAction
}
Code B
private val _playState=MutableLiveData<EPlayState>()
override fun playOrPause(filename: String) {
when (_playState.value) {
EPlayState.STOPPED -> play(filename)
EPlayState.PLAYING -> pause()
EPlayState.PAUSED -> resume()
}
}
enum class EPlayState {
STOPPED,
PLAYING,
PAUSED
}
LiveData is written in Java. The second parameter that you pass to the observe() function is an anonymous implementation of Java interface Observer. Since Java doesn't know anything about nullability in Kotlin, the parameter it assumed to be nullable.

Kotlin MutableList initial capacity

I'm creating a list of values, in a context where it so happens that, though the values are being added one at a time, the eventual number is known in advance. This is in a function that will be called many times, so the faster it runs, the better.
In Java, I would use the ArrayList constructor that specifies an initial capacity, because in theory this makes it slightly faster because it avoids resizing.
In Kotlin, one normally uses mutableListOf(), but this does not allow an initial capacity; in theory this should result in slightly slower code.
Is the recommended/idiomatic Kotlin solution in this case:
Go ahead and use the ArrayList constructor; ArrayList is a perfectly valid MutableList.
Ignore the issue; the initial capacity never actually makes a measurable difference to speed.
Something else?
Fill an immutable list
val doubles = List(5) { i -> i * 2 }
result --> [0, 2, 4, 6, 8]
Fill a mutable list of five elements with zeros
val ints = MutableList(5) { 0 }
result --> [0, 0, 0, 0, 0]
Updated Answer
I was actually confused with capacity and size. There is no implementation of using a default capacity MutableList currently in Kotlin stdlib.
You can make one yourself.
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
// creates a MutableList of Int with capacity of 5.
val mutableList = mutableListWithCapacity<Int>(5)
Outdated Answer
One of the reason why mutableListOf does not allow for default capacity is because default values in kotlin is not null.
However there is a utility function defined in kotlin.collections package.
public inline fun <T> MutableList(size: Int, init: (index: Int) -> T): MutableList<T> {
val list = ArrayList<T>(size)
repeat(size) { index -> list.add(init(index)) }
return list
}
You can create a List with a List function or MutableList function with a default capacity and its mapping.
// creates a list of ints with default capacity of 10 and having nulls.
// But I highly doubt you should initialize it with a null since Kotlin is a null-safe language.
val list = MutableList<Int?>(10) { null }
But since there should not be nulls in Kotlin if it is intended use of non-null list else you have to do a null check using operators like ?. !!..
You can wrap this mutableList() predefined function in a function like the following
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
this will return a MutableList of size size but also with null assigned to all of its cells. Now if you want to access any index value, your program will not crash with java.lang.IndexOutOfBoundsException like it would if you use the solution in the accepted answer. Here is what I mean:
fun <E> emptyMutableList(size: Int = 0): MutableList<E?> {
return MutableList(size) {
null
}
}
fun <T> mutableListWithCapacity(capacity: Int): MutableList<T> =
ArrayList(capacity)
fun main() {
val mutableList1 = mutableListWithCapacity<Int>(20)
val mutableList2 = emptyMutableList<Int>(20)
mutableList1[10] // this will throw a java.lang.IndexOutOfBoundsException
mutableList2[10] // this will not throw an exception but it will return null
}
Of course everything depends on how memory efficient vs crash-free you want your program to be.
Happy coding!

Why unresolved reference error thrown with while loop, whereas for for loop worked fine in kotlin

Just encountered a problem while working with kotlin. check below code example. The below code executes with out compilation error. But initially I had while in place of for loop in below code. and that was throwing unresolved reference error to element.
Why are we having such weird and unexpected behaviour in Kotlin.Just started out with kotlin please excuse.
fun main(args: Array<String>) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
val myarr=intArrayOf(1,2,3,4)
for(element in myarr){
println(element)
}
}
Below is code for which i am having an error. My question is why is it working for for loop and not for while
fun main(args: Array<String>) {
/* Enter your code here. Read input from STDIN. Print output to STDOUT */
val myarr=intArrayOf(1,2,3,4)
while(element in myarr){
println(element)
}
}
while loops require a boolean argument. in isn't a iterator in this case, it's equivalent to the in boolean check. Example:
fun demo(){
val x = 2;
val l = listOf(1, 2, 3);
while(x in l){
}
}
Note that this is horrible code and it will cause an infinite loop. But it does show you the point; in a while loop, in is for booleans, and not a range. This also applies to arrays.
The reason it's an unresolved reference is because you are doing a boolean check, and not a for loop. For loops auto-declare the field, where as a while, but also if requires an existing field (i.e. val x = something), or a direct declaration (i.e. while (2 in l)). The latter removes the variable name.
So while loops don't take iterables like for. You have five options for iterating through an iterable:
for(i in 0 until list.size) - list.size can be any call, as long as it's an int
for (item in list) - this requires list to be an iterable.
var i = 0;
while(i < list.size) {
// remember to increment `i`, otherwise it's an infinite loop
}
list.forEach { } and list.forEachIndexed { i, item -> TODO() }
I do not recommend this, since there are better options using the Kotlin stdlib, but it's still an option: list.stream().forEach({ item -> TODO() })
If you CTRL+click in IntelliJ on in in the while loop, you'll get redirected to override fun contains(element: #UnsafeVariance E): Boolean. As you see, this method returns a boolean. If you do the same in a for loop, you'll get redirected to override fun iterator(): Iterator<E>. As you see, these have two very different return types. The while loop uses the boolean one, and a for loop would use the iterator one. in is merely syntactical in this case.
And to end this, I highly recommend you use for loops, especially since you have an array. There's nothing wrong with a while loop though, using for is a personal preference.
And to close off what I said, the reason you get an unresolved reference is because the while loop doesn't actually declare a variable. If you add a variable, your code would compile, but it would be an infinite loop if the item is in the array:
fun main(args: Array<String>) {
val myarr=intArrayOf(1,2,3,4)
var element = 0; //if this is in the list, the the while loop is an infinite loop.
while(element in myarr){
println(element)
}
}
It is not good to use in in while loop. However you can do something like below:
fun main(args: Array<String>) {
var i = 0
val myarr=intArrayOf(1,2,3,4)
while (i < myarr.size)
println(myarr[i++])
}
Ref:
http://kotlinlang.org/docs/reference/control-flow.html#while-loops

type inference on empty arrays kotlin

Let's say I have a piece of code like:
fun temp2 (li : MutableList<Int>):Int {
if (li.isEmpty()) return 0
val pos=li.filter { it>0 }
val neg=li.filter { it<0 }
if (pos.isEmpty() && neg.isNotEmpty()){
// this gives compiling error because Required: Int, Found: Int?
// But I just checked one line higher that neg is Not Empty, so there (at least I guess)
// no possible way to have an NPE?
//return neg.max()
return neg.max()!! //this works fine
}
Is there any particular reason why compiler doesn't infer that .max() can only yield an Int, and thus this should not be an error, or am I missing something?
Kotlin's documentation proudly points out about Smart Casts, and I think this is a quite similar and easy inference to make?
That can’t be handled by smart casting, you're using a max() extension function which always returns a nullable type, Int? in your case:
public fun <T : Comparable<T>> Iterable<T>.max(): T?
The compiler does what this method signature suggests: it makes you handle the possible null. How should the compiler know wether max works as intended? It might be implemented wrongly.
The following, on the other hand, works thanks to smart casting:
val maxNeg: Int? = li.filter { it < 0 }.max()
if (maxNeg != null) {
return maxNeg //Can be used as Int
}