-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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 filter for Kotlin lateinit properties #707
Conversation
Hi @fabianishere , first of all thank you for your contribution ❤️ Usually coverage report for test code is not created, not sure if this makes sense in general, so I guess that your screenshot doesn't demonstrate all ways to use For
Kotlin compiler generates (
one could assume from this that possible to cover all branches just by invocation of However similarly to your example for
in addition to
Furthermore exactly as in your example in case of a Setter can be made
In this case I'm wondering why Kotlin compiler generates setter at all - it looks like dead code since can't be called from Java without reflection and Kotlin code doesn't use it? Maybe guys from JetBrains can give us a hint? 👋 @goodwinnk 😉 Local variable also can be
From the above clear that However this alone seems to be not enough to claim completeness of filter for Before this changeAfter this changeTo me seems that the only ways to handle setter are: either reading of kotlin metadata or detection of it based on assumption that it always comes strictly after getter that we can detect. Or to postpone this case as known limitation. @marchof WDYT? BTW and for the fun - here is reports produced by coverage engine built into IntelliJ IDEA: 😆 😉 With increasing amount of filters dedicated to Kotlin, might be valuable to introduce validation tests similar to ones that we have for Last but not least
If there is problem with performance, then restriction of filter to classes generated by Kotlin compiler will not solve problem and just hide it from projects that do not use Kotlin. IMO iself iteration over all instructions is not a big issue - anyway we already do this in We can question allocation of But without measurements, I would call all this as unnecessary premature micro optimizations. And here is our usual quick sanity check - analysis of
from which doubtful that this change brings big performance problems. |
Hi @Godin , Thanks for the detailed review! I see I forgot to cover all cases. I guess I cheered a bit to soon :p
|
Thanks for information and link!
This is very valuable addition to my reverse engineering - indeed in case of
and
From the above I'm even not sure that
Case of generation of
This won't be as simple as just addition of dependency, because AFAIK Kotlin compiler requires Java 1.6, while our tests should be runnable under Java 1.5 since this is our minimal supported version - see https://www.jacoco.org/jacoco/trunk/doc/build.html and https://travis-ci.org/jacoco/jacoco/ So this might require some dancing around Maven and even not sure that final result could be as nice as one could achieve for example with Gradle. If you're anyway willing to give a try - good luck 😉 but please do this separately from this PR.
My point was that except
the rest doesn't seem to require change.
In any case (no matter from where you start - from |
c4533a4
to
9857a09
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@fabianishere I left few minor comments and can even address them by myself prior to merge if you prefer so.
org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
Outdated
Show resolved
Hide resolved
org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
Outdated
Show resolved
Hide resolved
org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
Outdated
Show resolved
Hide resolved
org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
Outdated
Show resolved
Hide resolved
org.jacoco.core.test/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilterTest.java
Outdated
Show resolved
Hide resolved
org.jacoco.core/src/org/jacoco/core/internal/analysis/filter/KotlinLateinitFilter.java
Outdated
Show resolved
Hide resolved
Oh that is not a problem. Will look into it tomorrow. |
This change adds a new filter for Kotlin lateinit properties by searching in the bytecode for the following sequence of instructions: IFNONNULL ... LDC "..." INVOKESTATIC kotlin/jvm/internal/Intrinsics.throwUninitializedPropertyAccessException (Ljava/lang/String;)V and ignoring this sequence if found. The downside of this approach is that every instruction in every method must be scanned. Perhaps this filter could only be limited to Kotlin classes.
9857a09
to
221b926
Compare
I have addressed the feedback in 221b926. Do you prefer to have the commit rebased onto |
LGTM! Thanks a lot @fabianishere for your contribution 👍 which is now recorded in changelog ❤️ and thanks for your patience about our pedantism 😉 For the fun, for future readers of this thread and for possible future inclusion into validations tests for Kotlin: One might expect partial coverage in case of access to uninitialized |
Regarding public properties with private setters having unused generated setter: this issue apparently already reported. See https://youtrack.jetbrains.com/issue/KT-20344. However, it has not receive a lot of attention since it has been reported. |
This change adds a new filter for Kotlin lateinit properties by searching in the bytecode for the following sequence of instructions:
and ignoring this sequence if found.
This approach scans through all instructions in every method found, so maybe it might be an idea to only apply the filter on Kotlin classes. I haven't run any integration tests to measure the performance impact except for a small Kotlin project to verify results:
Before:
After: