jacoco / jacoco/example-jacoco-kotlin-compose

@Preview composable excluded only when not wrapped in themed @Composable

Open
#82 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Kotlin
Stars
2
Forks
3
PR merge metrics
No merged PRs in 30d

Description

Custom exclusion annotation works for a plain @Preview but fails when the preview wraps content in an annotated theme function.

Reproducer: fresh clone of repo https://github.com/jacoco/example-jacoco-kotlin-compose Command: ./gradlew clean test jacocoTestReport

Snippet:

@Retention(AnnotationRetention.RUNTIME)
@Target(AnnotationTarget.FUNCTION, AnnotationTarget.CLASS)
annotation class ExcludeFromJacocoGeneratedReport
package org.example

import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.material.Button
import androidx.compose.material.Text
import androidx.compose.runtime.*

@Composable
fun example() {
    var counter by remember { mutableStateOf(0) }
    if (counter == 2) {
        return
    }
    Button(onClick = { counter++ }) {
        if (counter == 0) {
            Text("Click me")
        } else {
            Text("Click me again")
        }
    }

}

@Composable
@ExcludeFromJacocoGeneratedReport
fun DummyTheme(content: @Composable () -> Unit) {
    content()
}


@Preview
@Composable
@ExcludeFromJacocoGeneratedReport
fun NoThemePreview() {
    example()
}

@Preview
@Composable
@ExcludeFromJacocoGeneratedReport
fun ThemedPreview() {
    DummyTheme @ExcludeFromJacocoGeneratedReport {
        example()
    }
}

Expected: Both previews fully excluded.
Actual: NoThemePreview excluded, ThemedPreview counted (lines attributed to generated synthetic methods).

Question:

  1. Is this an expected limitation of how the Compose compiler rewrites @Composable / @Preview functions?
  2. What is the recommended JaCoCo filter (class/method name patterns or annotations) to exclude every @Preview function and any helper lambdas they generate?

===========

Description

Generated jacocoTestReport.xml:

<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<!DOCTYPE report PUBLIC "-//JACOCO//DTD Report 1.1//EN" "report.dtd">
<report name="example-jacoco-kotlin-compose">
    <sessioninfo id="Tomass-MacBook-Pro-3.local-6e2358ea" start="1760083990908" dump="1760083992584"/>
    <package name="org/example">
        <class name="org/example/ExampleKt" sourcefilename="Example.kt">
            <method name="example" desc="(Landroidx/compose/runtime/Composer;I)V" line="9">
                <counter type="INSTRUCTION" missed="0" covered="74"/>
                <counter type="BRANCH" missed="0" covered="2"/>
                <counter type="LINE" missed="0" covered="6"/>
                <counter type="COMPLEXITY" missed="0" covered="2"/>
                <counter type="METHOD" missed="0" covered="1"/>
            </method>
            <method name="example$lambda$1" desc="(Landroidx/compose/runtime/MutableState;)I" line="10">
                <counter type="INSTRUCTION" missed="0" covered="10"/>
                <counter type="LINE" missed="0" covered="1"/>
                <counter type="COMPLEXITY" missed="0" covered="1"/>
                <counter type="METHOD" missed="0" covered="1"/>
            </method>
            <method name="example$lambda$2" desc="(Landroidx/compose/runtime/MutableState;I)V" line="10">
                <counter type="INSTRUCTION" missed="0" covered="12"/>
                <counter type="LINE" missed="0" covered="1"/>
                <counter type="COMPLEXITY" missed="0" covered="1"/>
                <counter type="METHOD" missed="0" covered="1"/>
            </method>
            <method name="example$lambda$4$0" desc="(Landroidx/compose/runtime/MutableState;)Lkotlin/Unit;" line="14">
                <counter type="INSTRUCTION" missed="0" covered="10"/>
                <counter type="LINE" missed="0" covered="1"/>
                <counter type="COMPLEXITY" missed="0" covered="1"/>
                <counter type="METHOD" missed="0" covered="1"/>
            </method>
            <method name="example$lambda$5" desc="(Landroidx/compose/runtime/MutableState;Landroidx/compose/foundation/layout/RowScope;Landroidx/compose/runtime/Composer;I)Lkotlin/Unit;" line="15">
                <counter type="INSTRUCTION" missed="0" covered="67"/>
                <counter type="BRANCH" missed="0" covered="2"/>
                <counter type="LINE" missed="0" covered="5"/>
                <counter type="COMPLEXITY" missed="0" covered="2"/>
                <counter type="METHOD" missed="0" covered="1"/>
            </method>
            <counter type="INSTRUCTION" missed="0" covered="173"/>
            <counter type="BRANCH" missed="0" covered="4"/>
            <counter type="LINE" missed="0" covered="11"/>
            <counter type="COMPLEXITY" missed="0" covered="7"/>
            <counter type="METHOD" missed="0" covered="5"/>
            <counter type="CLASS" missed="0" covered="1"/>
        </class>
        <class name="org/example/ComposableSingletons$ExampleKt$lambda$-545336751$1" sourcefilename="Example.kt"/>
        <class name="org/example/ExcludeFromJacocoGeneratedReport" sourcefilename="ExcludeFromJacocoGeneratedReport.kt"/>
        <class name="org/example/ComposableSingletons$ExampleKt" sourcefilename="Example.kt">
            <method name="&lt;clinit&gt;" desc="()V" line="42">
                <counter type="INSTRUCTION" missed="7" covered="0"/>
                <counter type="LINE" missed="1" covered="0"/>
                <counter type="COMPLEXITY" missed="1" covered="0"/>
                <counter type="METHOD" missed="1" covered="0"/>
            </method>
            <counter type="INSTRUCTION" missed="7" covered="0"/>
            <counter type="LINE" missed="1" covered="0"/>
            <counter type="COMPLEXITY" missed="1" covered="0"/>
            <counter type="METHOD" missed="1" covered="0"/>
            <counter type="CLASS" missed="1" covered="0"/>
        </class>
        <sourcefile name="Example.kt">
            <line nr="9" mi="0" ci="4" mb="0" cb="0"/>
            <line nr="10" mi="0" ci="41" mb="0" cb="0"/>
            <line nr="11" mi="0" ci="5" mb="0" cb="2"/>
            <line nr="12" mi="0" ci="4" mb="0" cb="0"/>
            <line nr="14" mi="0" ci="45" mb="0" cb="0"/>
            <line nr="15" mi="0" ci="12" mb="0" cb="2"/>
            <line nr="16" mi="0" ci="22" mb="0" cb="0"/>
            <line nr="17" mi="0" ci="9" mb="0" cb="0"/>
            <line nr="18" mi="0" ci="22" mb="0" cb="0"/>
            <line nr="20" mi="0" ci="2" mb="0" cb="0"/>
            <line nr="22" mi="0" ci="7" mb="0" cb="0"/>
            <line nr="42" mi="7" ci="0" mb="0" cb="0"/>
            <counter type="INSTRUCTION" missed="7" covered="173"/>
            <counter type="BRANCH" missed="0" covered="4"/>
            <counter type="LINE" missed="1" covered="11"/>
            <counter type="COMPLEXITY" missed="1" covered="7"/>
            <counter type="METHOD" missed="1" covered="5"/>
            <counter type="CLASS" missed="1" covered="1"/>
        </sourcefile>
        <sourcefile name="ExcludeFromJacocoGeneratedReport.kt"/>
        <counter type="INSTRUCTION" missed="7" covered="173"/>
        <counter type="BRANCH" missed="0" covered="4"/>
        <counter type="LINE" missed="1" covered="11"/>
        <counter type="COMPLEXITY" missed="1" covered="7"/>
        <counter type="METHOD" missed="1" covered="5"/>
        <counter type="CLASS" missed="1" covered="1"/>
    </package>
    <counter type="INSTRUCTION" missed="7" covered="173"/>
    <counter type="BRANCH" missed="0" covered="4"/>
    <counter type="LINE" missed="1" covered="11"/>
    <counter type="COMPLEXITY" missed="1" covered="7"/>
    <counter type="METHOD" missed="1" covered="5"/>
    <counter type="CLASS" missed="1" covered="1"/>
</report>```

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the Compose preview examples in Example.kt and reproduce the report using ./gradlew clean test jacocoTestReport. Inspect jacocoTestReport.xml, especially the generated synthetic methods and ComposableSingletons entries, and compare NoThemePreview with ThemedPreview. Done means the behavior or limitation is documented and a recommended exclusion approach is established for previews and their generated helpers.

Written by the indexing model from the issue text.

Assessment

Tech stack
kotlin
Domain
testing-qa
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.