├── _latest-gradle-test ├── gradle.properties ├── gradle-plugin-android-test │ ├── src │ │ ├── androidTest │ │ │ ├── kotlin │ │ │ │ └── gradle-plugin-android-tests-proxy.kt │ │ │ └── AndroidManifest.xml │ │ ├── main │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── tests-gradle-plugin-android.kt │ │ └── test │ │ │ └── kotlin │ │ │ └── tests-gradle-plugin-android-unit-jvm.kt │ ├── proguard-rules.pro │ └── build.gradle.kts ├── settings.gradle.kts └── build.gradle.kts ├── jvm-agent ├── gradle.properties ├── tests-ja │ ├── src │ │ └── test │ │ │ ├── java │ │ │ └── module-info.java │ │ │ └── kotlin │ │ │ └── tests-jvm-agent.kt │ └── build.gradle.kts ├── src │ └── main │ │ └── kotlin │ │ └── jvmAgent.kt └── jdk8-tests-ja │ ├── src │ └── test │ │ └── kotlin │ │ └── tests-jdk8-jvm-agent.kt │ └── build.gradle.kts ├── mh-invoker ├── gradle.properties └── src │ └── main │ ├── resources │ └── META-INF │ │ └── services │ │ ├── dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker │ │ └── dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker │ ├── java │ └── module-info.java │ └── kotlin │ └── internal │ ├── unknown.kt │ └── mh-invoker.kt ├── provider ├── gradle.properties └── src │ └── main │ ├── java │ └── module-info.java │ └── kotlin │ └── internal │ ├── utils-provider.kt │ ├── provider-api-internal.kt │ └── provider.kt ├── .github └── FUNDING.yml ├── _plugins ├── bytecode-processor │ ├── gradle.properties │ ├── intrinsics │ │ ├── src │ │ │ └── main │ │ │ │ ├── java │ │ │ │ └── module-info.java │ │ │ │ └── kotlin │ │ │ │ ├── deleteClass-intrinsics.kt │ │ │ │ ├── getCurrentFileName-intrinsincs.kt │ │ │ │ ├── utils-intrinsics.kt │ │ │ │ ├── makeStatic-intrinsics.kt │ │ │ │ ├── changeInvocationsOwner-intrinsics.kt │ │ │ │ ├── skipInvocations-intrinsics.kt │ │ │ │ ├── changeClassName-intrinsics.kt │ │ │ │ ├── getOwnerClass-intrinsics.kt │ │ │ │ └── loadConstant-intrinsics.kt │ │ └── build.gradle.kts │ ├── build.gradle.kts │ ├── api │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ └── asm-plugin-api.kt │ ├── settings.gradle.kts │ ├── plugins │ │ ├── build.gradle.kts │ │ └── src │ │ │ └── main │ │ │ └── kotlin │ │ │ ├── deleteClass-plugins.kt │ │ │ └── internal │ │ │ └── utils-plugins.kt │ └── gradle-plugin │ │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── api-gradle-plugin-bytecode-processor.kt │ │ └── build.gradle.kts ├── force-variant-java-version │ ├── settings.gradle.kts │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── forceVariantJavaVersion.kt └── gradle-plugin-test │ ├── settings.gradle.kts │ ├── runtime-settings │ └── build.gradle.kts │ ├── embedded-debug-probes-stdlib │ └── build.gradle.kts │ ├── intrinsics │ └── build.gradle.kts │ ├── provider │ └── build.gradle.kts │ ├── base-continuation-accessor │ └── build.gradle.kts │ └── embedded-debug-probes-xcoroutines │ └── build.gradle.kts ├── _tests ├── latest-kotlin-kmp-gradle-plugin-test │ ├── gradle.properties │ ├── src │ │ ├── androidMain │ │ │ ├── res │ │ │ │ ├── values │ │ │ │ │ └── strings.xml │ │ │ │ ├── mipmap-hdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-mdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-xxxhdpi │ │ │ │ │ ├── ic_launcher.png │ │ │ │ │ └── ic_launcher_round.png │ │ │ │ ├── mipmap-anydpi-v26 │ │ │ │ │ ├── ic_launcher.xml │ │ │ │ │ └── ic_launcher_round.xml │ │ │ │ └── drawable-v24 │ │ │ │ │ └── ic_launcher_foreground.xml │ │ │ ├── kotlin │ │ │ │ └── org │ │ │ │ │ └── example │ │ │ │ │ └── project │ │ │ │ │ ├── Platform.android.kt │ │ │ │ │ └── MainActivity.kt │ │ │ └── AndroidManifest.xml │ │ ├── wasmJsMain │ │ │ ├── resources │ │ │ │ ├── styles.css │ │ │ │ └── index.html │ │ │ └── kotlin │ │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── project │ │ │ │ ├── Platform.wasmJs.kt │ │ │ │ └── main.kt │ │ ├── commonMain │ │ │ └── kotlin │ │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── project │ │ │ │ ├── Platform.kt │ │ │ │ ├── Greeting.kt │ │ │ │ └── App.kt │ │ ├── desktopMain │ │ │ └── kotlin │ │ │ │ └── org │ │ │ │ └── example │ │ │ │ └── project │ │ │ │ ├── Platform.jvm.kt │ │ │ │ └── main.kt │ │ ├── androidInstrumentedTest │ │ │ └── kotlin │ │ │ │ └── tests-last-kotlin-kmp-gradle-plugin-android.kt │ │ └── androidUnitTest │ │ │ └── kotlin │ │ │ └── tests-last-kotlin-kmp-gradle-plugin-android-unit-test.kt │ └── settings.gradle.kts └── latest-kotlin-gradle-plugin-test │ ├── gradle.properties │ ├── settings.gradle.kts │ ├── custom-loader │ └── build.gradle.kts │ ├── src │ └── test │ │ └── kotlin │ │ └── last-kotlin-gradle-plugin-test.kt │ ├── build.gradle.kts │ └── test-utils │ └── build.gradle.kts ├── .gitignore ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── gradle.properties ├── common └── src │ └── main │ ├── resources │ └── META-INF │ │ └── services │ │ └── dev.reformator.stacktracedecoroutinator.provider.internal.DecoroutinatorProvider │ ├── kotlin │ ├── internal │ │ ├── utils-mh-api-common.kt │ │ └── interfaces-common.kt │ └── intrinsics │ │ └── intrinsics-common.kt │ └── java │ └── module-info.java ├── test-utils ├── retrace-repack │ ├── src │ │ └── main │ │ │ └── java │ │ │ ├── dev │ │ │ └── reformator │ │ │ │ └── retracerepack │ │ │ │ ├── retrace │ │ │ │ └── _dummy.java │ │ │ │ └── obfuscate │ │ │ │ └── _dummy.java │ │ │ └── module-info.java │ └── build.gradle.kts ├── base-continuation-accessor-stub │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider │ │ │ ├── java │ │ │ └── module-info.java │ │ │ └── kotlin │ │ │ └── base-continuation-accessor-stub.kt │ └── build.gradle.kts ├── base-continuation-accessor-reflect-stub │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider │ │ │ └── kotlin │ │ │ └── base-continuation-accessor-reflect-stub.kt │ └── build.gradle.kts ├── src │ └── main │ │ ├── java │ │ └── module-info.java │ │ └── kotlin │ │ └── test-utils.kt ├── custom-loader │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ ├── test-utils-custom-loader.kt │ │ │ └── stub-test-utils-custom-loader.kt │ └── build.gradle.kts └── build.gradle.kts ├── gradle-plugin ├── src │ └── main │ │ ├── resources │ │ └── META-INF │ │ │ └── services │ │ │ └── dev.reformator.stacktracedecoroutinator.gradleplugin.GroovyDslInitializer │ │ ├── kotlin │ │ ├── gradle-plugin-utils.kt │ │ ├── attribute-gradle-plugin.kt │ │ ├── gradle-noop-transformer.kt │ │ └── api-gradle-plugin-decoroutinator.kt │ │ └── groovy │ │ └── GroovyDslInitializerImpl.groovy ├── embedded-debug-probes-xcoroutines │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── kotlin.coroutines.jvm.internal.DecoroutinatorDebugProbesProvider │ │ │ └── kotlin │ │ │ └── embedded-debug-probes-provider.kt │ └── build.gradle.kts ├── base-continuation-accessor │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider │ │ │ └── kotlin │ │ │ └── base-continuation-accessor.kt │ └── build.gradle.kts ├── duplicate-entity-jar-builder │ ├── src │ │ └── main │ │ │ ├── java │ │ │ └── module-info.java │ │ │ └── kotlin │ │ │ └── proxyCaller.kt │ └── build.gradle.kts ├── android-tests │ ├── src │ │ ├── main │ │ │ └── AndroidManifest.xml │ │ ├── androidTest │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ │ └── gradle-plugin-android-tests-proxy.kt │ │ └── test │ │ │ └── kotlin │ │ │ └── tests-gradle-plugin-android-unit-jvm.kt │ └── proguard-rules.pro ├── android-legacy-tests │ ├── src │ │ ├── main │ │ │ └── AndroidManifest.xml │ │ └── androidTest │ │ │ ├── AndroidManifest.xml │ │ │ └── kotlin │ │ │ └── gradle-plugin-android-legacy-tests-proxy.kt │ └── proguard-rules.pro ├── empty-module-tests │ └── build.gradle.kts ├── tests-gp │ ├── src │ │ └── test │ │ │ ├── java │ │ │ ├── dev │ │ │ │ └── reformator │ │ │ │ │ └── stacktracedecoroutinator │ │ │ │ │ └── gradleplugintests │ │ │ │ │ └── DebugProbesAccessor.java │ │ │ └── module-info.java │ │ │ └── kotlin │ │ │ └── tests-gradle-plugin.kt │ └── build.gradle.kts ├── embedded-debug-probes-stdlib │ ├── build.gradle.kts │ └── src │ │ └── main │ │ └── kotlin │ │ └── embedded-debug-probes-stdlib.kt ├── gradle-groovy-dsl-tests │ └── build.gradle ├── aar-builder │ ├── src │ │ └── main │ │ │ └── kotlin │ │ │ └── aar-builder.kt │ └── build.gradle.kts └── jdk8-tests-gp │ ├── build.gradle.kts │ └── src │ └── test │ └── kotlin │ └── tests-jdk8-gradle-plugin.kt ├── mh-invoker-android └── src │ └── main │ ├── resources │ └── META-INF │ │ └── services │ │ ├── dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker │ │ └── dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker │ └── kotlin │ └── mh-invoker-android.kt ├── mh-invoker-jvm ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ ├── dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker │ │ │ │ └── dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker │ │ ├── kotlin │ │ │ └── internal │ │ │ │ └── unknown-mh-invoker-jvm.kt │ │ └── java │ │ │ └── module-info.java │ └── test │ │ ├── kotlin │ │ └── tests-mh-invoker-jvm.kt │ │ └── java │ │ └── module-info.java └── jdk8-tests-mij │ ├── src │ └── test │ │ └── kotlin │ │ └── tests-mh-invoker-jvm.kt │ └── build.gradle.kts ├── generator-android └── src │ ├── main │ └── resources │ │ └── META-INF │ │ └── services │ │ └── dev.reformator.stacktracedecoroutinator.common.internal.SpecMethodsFactory │ └── test │ └── kotlin │ └── jvm-tests-generator-android.kt ├── generator-jvm ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ ├── dev.reformator.stacktracedecoroutinator.common.internal.SpecMethodsFactory │ │ │ │ └── dev.reformator.stacktracedecoroutinator.common.internal.AnnotationMetadataResolver │ │ ├── java │ │ │ └── module-info.java │ │ └── kotlin │ │ │ └── internal │ │ │ ├── specMethodsFactory-generator.kt │ │ │ └── classLoader-generator.kt │ └── test │ │ ├── kotlin │ │ ├── tests-generator.kt │ │ ├── printSpecMethod.kt │ │ └── showResumeWithAppendix.kt │ │ └── java │ │ └── module-info.java ├── jdk8-tests-g │ ├── src │ │ └── test │ │ │ └── kotlin │ │ │ └── tests-jdk8-generator.kt │ └── build.gradle.kts └── android-wrong-generator-tests │ ├── src │ └── androidTest │ │ └── kotlin │ │ └── android-tests-generator-jvm.kt │ └── build.gradle.kts ├── intrinsics ├── src │ └── main │ │ ├── java │ │ └── module-info.java │ │ └── kotlin │ │ └── intrinsics.kt └── build.gradle.kts ├── jvm-agent-common ├── src │ ├── main │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider │ │ ├── kotlin │ │ │ └── internal │ │ │ │ ├── utils-jvm-agent-common.kt │ │ │ │ ├── di-jvm-agent-common.kt │ │ │ │ └── base-continuation-accessor-agent-common.kt │ │ └── java │ │ │ └── module-info.java │ └── test │ │ └── kotlin │ │ └── showBaseContinuation.kt └── suspend-class-stub │ ├── src │ └── main │ │ └── kotlin │ │ └── jvm-agent-common-stub.kt │ └── build.gradle.kts ├── class-transformer └── src │ └── main │ ├── kotlin │ └── internal │ │ └── interfaces-class-transformer.kt │ └── java │ └── module-info.java ├── jvm ├── src │ ├── main │ │ ├── kotlin │ │ │ ├── internal │ │ │ │ └── utils-jvm.kt │ │ │ └── api-jvm.kt │ │ └── java │ │ │ └── module-info.java │ └── test │ │ ├── java │ │ └── module-info.java │ │ └── kotlin │ │ ├── example.kt │ │ └── tests-jvm.kt └── jdk8-tests-j │ ├── build.gradle.kts │ └── src │ └── test │ └── kotlin │ └── tests-jdk8-jvm.kt ├── test-utils-jvm ├── src │ └── main │ │ ├── java │ │ └── module-info.java │ │ └── kotlin │ │ ├── test-utils.kt │ │ └── jvm-test.kt └── build.gradle.kts ├── spec-method-builder └── src │ └── main │ ├── java │ └── module-info.java │ └── kotlin │ └── internal │ └── utils-spec-method-builder.kt ├── runtime-settings ├── src │ └── main │ │ ├── java │ │ └── module-info.java │ │ └── kotlin │ │ ├── runtime-settings.kt │ │ └── internal │ │ └── runtime-settings-internal.kt └── build.gradle.kts ├── settings.gradle.kts └── gradlew.bat /_latest-gradle-test/gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /jvm-agent/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.stdlib.default.dependency=false 2 | -------------------------------------------------------------------------------- /mh-invoker/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.stdlib.default.dependency=false 2 | -------------------------------------------------------------------------------- /provider/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.stdlib.default.dependency=false 2 | -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | github: Anamorphosee 2 | buy_me_a_coffee: reformator 3 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.jvm.target.validation.mode=ignore 2 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/gradle.properties: -------------------------------------------------------------------------------- 1 | android.useAndroidX=true 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .gradle 2 | .idea 3 | .kotlin 4 | build 5 | local.properties 6 | *.hprof 7 | yarn.lock 8 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.jvm.target.validation.mode=ignore 2 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /gradle.properties: -------------------------------------------------------------------------------- 1 | kotlin.code.style=official 2 | android.useAndroidX=true 3 | kotlin.jvm.target.validation.mode=ignore 4 | kotlin.incremental=false 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/values/strings.xml: -------------------------------------------------------------------------------- 1 | 2 | GarbKmp 3 | -------------------------------------------------------------------------------- /common/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.provider.internal.DecoroutinatorProvider: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.common.internal.Provider 2 | -------------------------------------------------------------------------------- /test-utils/retrace-repack/src/main/java/dev/reformator/retracerepack/retrace/_dummy.java: -------------------------------------------------------------------------------- 1 | package dev.reformator.retracerepack.retrace; 2 | 3 | @SuppressWarnings("unused") 4 | public class _dummy { } 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/wasmJsMain/resources/styles.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | width: 100%; 3 | height: 100%; 4 | margin: 0; 5 | padding: 0; 6 | overflow: hidden; 7 | } -------------------------------------------------------------------------------- /mh-invoker/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularVarHandleInvoker 2 | -------------------------------------------------------------------------------- /test-utils/retrace-repack/src/main/java/dev/reformator/retracerepack/obfuscate/_dummy.java: -------------------------------------------------------------------------------- 1 | package dev.reformator.retracerepack.obfuscate; 2 | 3 | @SuppressWarnings("unused") 4 | public class _dummy { } 5 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.gradleplugin.GroovyDslInitializer: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.gradleplugin.groovy.GroovyDslInitializerImpl 2 | -------------------------------------------------------------------------------- /mh-invoker-android/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvokerandroid.AndroidVarHandleInvoker 2 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvokerjvm.internal.JvmVarHandleInvoker 2 | -------------------------------------------------------------------------------- /mh-invoker/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularMethodHandleInvoker 2 | -------------------------------------------------------------------------------- /generator-android/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.SpecMethodsFactory: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.generatorandroid.AndroidSpecMethodsFactory 2 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvokerjvm.internal.JvmMethodHandleInvoker 2 | -------------------------------------------------------------------------------- /test-utils/retrace-repack/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.retracerepack { 2 | exports dev.reformator.retracerepack.retrace; 3 | exports dev.reformator.retracerepack.obfuscate; 4 | } 5 | -------------------------------------------------------------------------------- /generator-jvm/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.SpecMethodsFactory: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.generatorjvm.internal.GeneratorJvmSpecMethodsFactory 2 | -------------------------------------------------------------------------------- /mh-invoker-android/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.mhinvokerandroid.AndroidMethodHandleInvoker 2 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.bytecodeprocessor.intrinsics { 2 | requires static kotlin.stdlib; 3 | exports dev.reformator.bytecodeprocessor.intrinsics; 4 | } -------------------------------------------------------------------------------- /gradle-plugin/embedded-debug-probes-xcoroutines/src/main/resources/META-INF/services/kotlin.coroutines.jvm.internal.DecoroutinatorDebugProbesProvider: -------------------------------------------------------------------------------- 1 | kotlinx.coroutines.debug.internal.DecoroutinatorDebugProbesProviderImpl 2 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/commonMain/kotlin/org/example/project/Platform.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | interface Platform { 4 | val name: String 5 | } 6 | 7 | expect fun getPlatform(): Platform -------------------------------------------------------------------------------- /generator-jvm/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.common.internal.AnnotationMetadataResolver: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.generatorjvm.internal.AnnotationMetadataResolverImpl 2 | -------------------------------------------------------------------------------- /gradle-plugin/base-continuation-accessor/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider: -------------------------------------------------------------------------------- 1 | kotlin.coroutines.jvm.internal.DecoroutinatorBaseContinuationAccessorImpl 2 | -------------------------------------------------------------------------------- /intrinsics/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module intrinsics { 2 | requires static dev.reformator.bytecodeprocessor.intrinsics; 3 | requires kotlin.stdlib; 4 | exports dev.reformator.stacktracedecoroutinator.intrinsics; 5 | } 6 | 7 | -------------------------------------------------------------------------------- /jvm-agent-common/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal.AgentBaseContinuationAccessorProvider 2 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-hdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-hdpi/ic_launcher.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-mdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-mdpi/ic_launcher.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xhdpi/ic_launcher.png -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/src/androidTest/kotlin/gradle-plugin-android-tests-proxy.kt: -------------------------------------------------------------------------------- 1 | import androidx.annotation.Keep 2 | 3 | @Keep 4 | class TestLocalFile: dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.TestLocalFile() 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxxhdpi/ic_launcher.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionBase=GRADLE_USER_HOME 2 | distributionPath=wrapper/dists 3 | distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.3-bin.zip 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-hdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-mdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /_latest-gradle-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | include("gradle-plugin-android-test") 2 | 3 | dependencyResolutionManagement { 4 | versionCatalogs { 5 | create("libs") { 6 | from(files("../gradle/libs.versions.toml")) 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Anamorphosee/stacktrace-decoroutinator/HEAD/_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-xxxhdpi/ic_launcher_round.png -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/commonMain/kotlin/org/example/project/Greeting.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | class Greeting { 4 | private val platform = getPlatform() 5 | 6 | fun greet(): String { 7 | return "Hello, ${platform.name}!" 8 | } 9 | } -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-stub/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub.TestBaseContinuationAccessorProviderAccessor 2 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/wasmJsMain/kotlin/org/example/project/Platform.wasmJs.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | class WasmPlatform: Platform { 4 | override val name: String = "Web with Kotlin/Wasm" 5 | } 6 | 7 | actual fun getPlatform(): Platform = WasmPlatform() -------------------------------------------------------------------------------- /_plugins/force-variant-java-version/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "force-variant-java-version" 2 | 3 | dependencyResolutionManagement { 4 | versionCatalogs { 5 | create("libs") { 6 | from(files("../../gradle/libs.versions.toml")) 7 | } 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-reflect-stub/src/main/resources/META-INF/services/dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider: -------------------------------------------------------------------------------- 1 | dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub.TestReflectBaseContinuationAccessorProviderAccessor 2 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/desktopMain/kotlin/org/example/project/Platform.jvm.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | class JVMPlatform: Platform { 4 | override val name: String = "Java ${System.getProperty("java.version")}" 5 | } 6 | 7 | actual fun getPlatform(): Platform = JVMPlatform() -------------------------------------------------------------------------------- /gradle-plugin/duplicate-entity-jar-builder/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.duplicatejar { 2 | requires static dev.reformator.bytecodeprocessor.intrinsics; 3 | requires kotlin.stdlib; 4 | exports dev.reformator.stacktracedecoroutinator.duplicatejar; 5 | } 6 | -------------------------------------------------------------------------------- /gradle-plugin/android-tests/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/deleteClass-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | @Retention(AnnotationRetention.BINARY) 6 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 7 | annotation class DeleteClass 8 | -------------------------------------------------------------------------------- /generator-jvm/jdk8-tests-g/src/test/kotlin/tests-jdk8-generator.kt: -------------------------------------------------------------------------------- 1 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 2 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 3 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 4 | -------------------------------------------------------------------------------- /gradle-plugin/android-legacy-tests/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /gradle-plugin/android-tests/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/getCurrentFileName-intrinsincs.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | val currentFileName: String 6 | get() { fail() } 7 | 8 | val currentLineNumber: Int 9 | get() { fail() } 10 | -------------------------------------------------------------------------------- /gradle-plugin/android-legacy-tests/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /gradle-plugin/android-tests/src/test/kotlin/tests-gradle-plugin-android-unit-jvm.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.TestLocalFile 2 | import org.junit.Test 3 | 4 | class AccessTest { 5 | @Test 6 | fun accessFileInMainModule() { 7 | TestLocalFile::class.java.name 8 | } 9 | } -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/src/main/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/utils-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | fun fail(): Nothing { error("intrinsic failed") } 6 | 7 | @Suppress("ClassName") internal class noClass 8 | internal const val NO_NAME = "\$no name\$" 9 | -------------------------------------------------------------------------------- /jvm-agent/tests-ja/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.jvmagent.tests { 2 | requires dev.reformator.stacktracedecoroutinator.testutils; 3 | requires dev.reformator.stacktracedecoroutinator.testutilsjvm; 4 | requires kotlinx.coroutines.core; 5 | requires kotlin.test.junit5; 6 | } 7 | -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/src/androidTest/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/src/test/kotlin/tests-gradle-plugin-android-unit-jvm.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.TestLocalFile 2 | import org.junit.Test 3 | 4 | class AccessTest { 5 | @Test 6 | fun accessFileInMainModule() { 7 | TestLocalFile::class.java.name 8 | } 9 | } -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/kotlin/org/example/project/Platform.android.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | import android.os.Build 4 | 5 | class AndroidPlatform : Platform { 6 | override val name: String = "Android ${Build.VERSION.SDK_INT}" 7 | } 8 | 9 | actual fun getPlatform(): Platform = AndroidPlatform() -------------------------------------------------------------------------------- /class-transformer/src/main/kotlin/internal/interfaces-class-transformer.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.classtransformer.internal 2 | 3 | class DebugMetadataInfo internal constructor( 4 | internal val specClassInternalClassName: String, 5 | internal val methodName: String, 6 | internal val lineNumbers: Set 7 | ) 8 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/makeStatic-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | @Retention(AnnotationRetention.BINARY) 6 | @Target(AnnotationTarget.FUNCTION) 7 | annotation class MakeStatic( 8 | val addToStaticInitializer: Boolean = false 9 | ) 10 | -------------------------------------------------------------------------------- /jvm/src/main/kotlin/internal/utils-jvm.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.jvm.internal 4 | 5 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorTransformed 6 | 7 | val Class<*>.isTransformed: Boolean 8 | get() = getDeclaredAnnotation(DecoroutinatorTransformed::class.java) != null 9 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-anydpi-v26/ic_launcher.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/mipmap-anydpi-v26/ic_launcher_round.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | dependencies { 8 | classpath(libs.kotlin.gradle.plugin) 9 | } 10 | } 11 | 12 | subprojects { 13 | group = "dev.reformator.bytecodeprocessor" 14 | version = "0.0.1-SNAPSHOT" 15 | } 16 | -------------------------------------------------------------------------------- /generator-jvm/src/test/kotlin/tests-generator.kt: -------------------------------------------------------------------------------- 1 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 2 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 3 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 4 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 5 | -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/src/main/kotlin/tests-gradle-plugin-android.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch", "JUnitMixedFramework") 2 | 3 | package dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests 4 | 5 | import org.junit.Test 6 | 7 | open class TestLocalFile { 8 | @Test 9 | fun localTest() { 10 | println("OK") 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/test/kotlin/tests-mh-invoker-jvm.kt: -------------------------------------------------------------------------------- 1 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 2 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 3 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 4 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/desktopMain/kotlin/org/example/project/main.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | import androidx.compose.ui.window.Window 4 | import androidx.compose.ui.window.application 5 | 6 | fun main() = application { 7 | Window( 8 | onCloseRequest = ::exitApplication, 9 | title = "GarbKmp", 10 | ) { 11 | App() 12 | } 13 | } -------------------------------------------------------------------------------- /mh-invoker-jvm/jdk8-tests-mij/src/test/kotlin/tests-mh-invoker-jvm.kt: -------------------------------------------------------------------------------- 1 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 2 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 3 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 4 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 5 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/wasmJsMain/kotlin/org/example/project/main.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | import androidx.compose.ui.ExperimentalComposeUiApi 4 | import androidx.compose.ui.window.ComposeViewport 5 | import kotlinx.browser.document 6 | 7 | @OptIn(ExperimentalComposeUiApi::class) 8 | fun main() { 9 | ComposeViewport(document.body!!) { 10 | App() 11 | } 12 | } -------------------------------------------------------------------------------- /gradle-plugin/empty-module-tests/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | java { 12 | sourceCompatibility = JavaVersion.VERSION_1_9 13 | targetCompatibility = JavaVersion.VERSION_1_9 14 | } 15 | 16 | kotlin { 17 | compilerOptions { 18 | jvmTarget = JvmTarget.JVM_1_8 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/main/kotlin/internal/unknown-mh-invoker-jvm.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dcunknownjvm 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.ownerClass 6 | import java.lang.invoke.MethodHandles 7 | 8 | internal fun getUnknownPackageLookup(): MethodHandles.Lookup = 9 | MethodHandles.lookup() 10 | 11 | internal fun getUnknownPackageName(): String = 12 | ownerClass.packageName 13 | -------------------------------------------------------------------------------- /test-utils-jvm/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.testutilsjvm { 2 | requires kotlinx.coroutines.core; 3 | requires org.junit.jupiter.api; 4 | requires io.github.oshai.kotlinlogging; 5 | requires static dev.reformator.bytecodeprocessor.intrinsics; 6 | 7 | exports dev.reformator.stacktracedecoroutinator.testjvm; 8 | opens dev.reformator.stacktracedecoroutinator.testjvm; 9 | } 10 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/wasmJsMain/resources/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | GarbKmp 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.mhinvokerjvm.tests { 2 | requires kotlin.stdlib; 3 | requires dev.reformator.stacktracedecoroutinator.common; 4 | requires dev.reformator.stacktracedecoroutinator.testutils; 5 | requires dev.reformator.stacktracedecoroutinator.provider; 6 | requires org.junit.jupiter.api; 7 | requires dev.reformator.stacktracedecoroutinator.testutilsjvm; 8 | } 9 | -------------------------------------------------------------------------------- /jvm-agent/src/main/kotlin/jvmAgent.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("DecoroutinatorAgentKt") 3 | 4 | package dev.reformator.stacktracedecoroutinator.jvmagent 5 | 6 | import dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal.addDecoroutinatorTransformer 7 | import java.lang.instrument.Instrumentation 8 | 9 | fun premain(@Suppress("UNUSED_PARAMETER") args: String?, inst: Instrumentation) { 10 | addDecoroutinatorTransformer(inst) 11 | } 12 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/changeInvocationsOwner-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | import kotlin.reflect.KClass 6 | 7 | @Retention(AnnotationRetention.BINARY) 8 | @Target(AnnotationTarget.FUNCTION) 9 | annotation class ChangeInvocationsOwner( 10 | val to: KClass<*> = noClass::class, 11 | val toName: String = NO_NAME, 12 | val deleteAfterChanging: Boolean = true 13 | ) 14 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/skipInvocations-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | @Retention(AnnotationRetention.BINARY) 6 | @Target( 7 | AnnotationTarget.FUNCTION, 8 | AnnotationTarget.PROPERTY, 9 | AnnotationTarget.PROPERTY_GETTER, 10 | AnnotationTarget.PROPERTY_SETTER 11 | ) 12 | annotation class SkipInvocations( 13 | val deleteAfterChanging: Boolean = true 14 | ) 15 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/changeClassName-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | import kotlin.reflect.KClass 6 | 7 | @Retention(AnnotationRetention.BINARY) 8 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 9 | annotation class ChangeClassName( 10 | val to: KClass<*> = noClass::class, 11 | val toName: String = NO_NAME, 12 | val deleteAfterChanging: Boolean = false 13 | ) 14 | -------------------------------------------------------------------------------- /gradle-plugin/tests-gp/src/test/java/dev/reformator/stacktracedecoroutinator/gradleplugintests/DebugProbesAccessor.java: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.gradleplugintests; 2 | 3 | import kotlinx.coroutines.debug.internal.DebugProbesImpl; 4 | import org.jetbrains.annotations.NotNull; 5 | 6 | import java.util.List; 7 | 8 | public class DebugProbesAccessor { 9 | public static @NotNull List dumpCoroutinesInfo() { 10 | return DebugProbesImpl.INSTANCE.dumpCoroutinesInfo(); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /jvm-agent-common/suspend-class-stub/src/main/kotlin/jvm-agent-common-stub.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.ClassNameConstant 6 | import kotlin.coroutines.suspendCoroutine 7 | 8 | @Suppress("unused") 9 | @ClassNameConstant("jvmAgentCommonSuspendClassName") 10 | private class PreloadStub { 11 | suspend fun suspendFun() { 12 | suspendCoroutine { } 13 | suspendCoroutine { } 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /jvm/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.jvm.tests { 2 | requires dev.reformator.stacktracedecoroutinator.jvm; 3 | requires kotlin.test.junit5; 4 | requires dev.reformator.stacktracedecoroutinator.common; 5 | requires dev.reformator.stacktracedecoroutinator.provider; 6 | requires dev.reformator.stacktracedecoroutinator.testutils; 7 | requires dev.reformator.stacktracedecoroutinator.testutilsjvm; 8 | requires kotlinx.coroutines.core; 9 | 10 | exports dev.reformator.stacktracedecoroutinator.jvmtests; 11 | } 12 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/getOwnerClass-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | @Retention(AnnotationRetention.BINARY) 6 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER) 7 | annotation class GetOwnerClass( 8 | val deleteAfterModification: Boolean = true 9 | ) 10 | 11 | val ownerClass: Class<*> 12 | get() { fail() } 13 | 14 | val ownerClassName: String 15 | get() { fail() } 16 | 17 | val ownerMethodName: String 18 | get() { fail() } 19 | -------------------------------------------------------------------------------- /generator-jvm/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.generator.tests { 2 | requires kotlin.stdlib; 3 | requires org.objectweb.asm.util; 4 | requires dev.reformator.stacktracedecoroutinator.generatorjvm; 5 | requires dev.reformator.stacktracedecoroutinator.common; 6 | requires jdk.unsupported; 7 | requires dev.reformator.stacktracedecoroutinator.testutils; 8 | requires dev.reformator.stacktracedecoroutinator.provider; 9 | requires org.junit.jupiter.api; 10 | requires dev.reformator.stacktracedecoroutinator.testutilsjvm; 11 | } 12 | -------------------------------------------------------------------------------- /common/src/main/kotlin/internal/utils-mh-api-common.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("NewApi", "PackageDirectoryMismatch") 2 | @file:AndroidLegacyKeep 3 | 4 | package dev.reformator.stacktracedecoroutinator.common.internal 5 | 6 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorSpec 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.AndroidLegacyKeep 8 | import java.lang.invoke.MethodType 9 | import kotlin.jvm.java 10 | 11 | val specMethodType: MethodType = MethodType.methodType( 12 | Object::class.java, 13 | DecoroutinatorSpec::class.java, 14 | Object::class.java 15 | ) 16 | -------------------------------------------------------------------------------- /jvm/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.jvm { 2 | requires dev.reformator.stacktracedecoroutinator.jvmagentcommon; 3 | requires dev.reformator.stacktracedecoroutinator.common; 4 | requires dev.reformator.stacktracedecoroutinator.provider; 5 | requires net.bytebuddy.agent; 6 | requires java.instrument; 7 | requires kotlin.stdlib; 8 | 9 | exports dev.reformator.stacktracedecoroutinator.jvm; 10 | 11 | exports dev.reformator.stacktracedecoroutinator.jvm.internal to 12 | dev.reformator.stacktracedecoroutinator.jvm.tests; 13 | } 14 | -------------------------------------------------------------------------------- /spec-method-builder/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.specmethodbuilder { 2 | requires static intrinsics; 3 | 4 | requires kotlin.stdlib; 5 | requires org.objectweb.asm.tree; 6 | requires dev.reformator.stacktracedecoroutinator.provider; 7 | 8 | exports dev.reformator.stacktracedecoroutinator.specmethodbuilder.internal to 9 | dev.reformator.stacktracedecoroutinator.generatorjvm, 10 | dev.reformator.stacktracedecoroutinator.generator.tests, 11 | dev.reformator.stacktracedecoroutinator.classtransformer; 12 | } 13 | -------------------------------------------------------------------------------- /class-transformer/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.classtransformer { 2 | requires static dev.reformator.bytecodeprocessor.intrinsics; 3 | 4 | requires kotlin.stdlib; 5 | requires dev.reformator.stacktracedecoroutinator.provider; 6 | requires dev.reformator.stacktracedecoroutinator.specmethodbuilder; 7 | requires org.objectweb.asm.tree; 8 | requires dev.reformator.kotlinmetadatajvmrepack; 9 | 10 | exports dev.reformator.stacktracedecoroutinator.classtransformer.internal to 11 | dev.reformator.stacktracedecoroutinator.jvmagentcommon; 12 | } 13 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "gradle-plugin-test" 2 | 3 | include("embedded-debug-probes-stdlib") 4 | include("embedded-debug-probes-xcoroutines") 5 | include("base-continuation-accessor") 6 | include("runtime-settings") 7 | include("intrinsics") 8 | include("provider") 9 | 10 | includeBuild("../bytecode-processor") 11 | 12 | pluginManagement { 13 | includeBuild("../bytecode-processor") 14 | } 15 | 16 | dependencyResolutionManagement { 17 | versionCatalogs { 18 | create("libs") { 19 | from(files("../../gradle/libs.versions.toml")) 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "latest-kotlin-gradle-plugin-test" 2 | 3 | includeBuild("../../_plugins/gradle-plugin-test") 4 | includeBuild("../../_plugins/bytecode-processor") 5 | 6 | pluginManagement { 7 | includeBuild("../../_plugins/gradle-plugin-test") 8 | includeBuild("../../_plugins/bytecode-processor") 9 | } 10 | 11 | dependencyResolutionManagement { 12 | versionCatalogs { 13 | create("libs") { 14 | from(files("../../gradle/libs.versions.toml")) 15 | } 16 | } 17 | } 18 | 19 | include("custom-loader") 20 | include("test-utils") 21 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-stub/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub.TestBaseContinuationAccessorProviderAccessor; 2 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider; 3 | 4 | module dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub { 5 | requires kotlin.stdlib; 6 | requires static intrinsics; 7 | requires dev.reformator.stacktracedecoroutinator.provider; 8 | 9 | provides BaseContinuationAccessorProvider with TestBaseContinuationAccessorProviderAccessor; 10 | } -------------------------------------------------------------------------------- /gradle-plugin/android-legacy-tests/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn javax.** 2 | -dontwarn reactor.** 3 | -dontwarn android.test.AndroidTestCase 4 | -dontwarn android.test.InstrumentationTestCase 5 | -dontwarn com.google.errorprone.annotations.** 6 | 7 | -keepclasseswithmembers class * { 8 | @org.junit.Test ; 9 | (); 10 | } 11 | -keepclasseswithmembers class * { 12 | @org.junit.Before ; 13 | (); 14 | } 15 | -keep class androidx.test.runner.AndroidJUnitRunner { *; } 16 | -keep class dev.reformator.stacktracedecoroutinator.test.Test_utilsKt { 17 | setRetraceMappingFiles(java.lang.String[]); 18 | } 19 | -------------------------------------------------------------------------------- /gradle-plugin/tests-gp/src/test/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.gradleplugintests { 2 | requires static dev.reformator.bytecodeprocessor.intrinsics; 3 | 4 | requires dev.reformator.stacktracedecoroutinator.testutils; 5 | //noinspection JavaModuleDefinition 6 | requires kotlinx.coroutines.core; 7 | requires kotlin.test.junit5; 8 | requires dev.reformator.stacktracedecoroutinator.testutilsjvm; 9 | requires dev.reformator.stacktracedecoroutinator.duplicatejar; 10 | requires org.jetbrains.annotations; 11 | 12 | exports dev.reformator.stacktracedecoroutinator.gradleplugintests; 13 | } 14 | -------------------------------------------------------------------------------- /runtime-settings/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.runtimesettings.DecoroutinatorRuntimeSettingsProvider; 2 | 3 | module dev.reformator.stacktracedecoroutinator.runtimesettings { 4 | requires kotlin.stdlib; 5 | 6 | exports dev.reformator.stacktracedecoroutinator.runtimesettings; 7 | exports dev.reformator.stacktracedecoroutinator.runtimesettings.internal to 8 | dev.reformator.stacktracedecoroutinator.common, 9 | dev.reformator.stacktracedecoroutinator.jvmagentcommon, 10 | kotlinx.coroutines.core; 11 | 12 | uses DecoroutinatorRuntimeSettingsProvider; 13 | } 14 | -------------------------------------------------------------------------------- /test-utils/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | module dev.reformator.stacktracedecoroutinator.testutils { 2 | requires kotlinx.coroutines.core; 3 | requires org.junit.jupiter.api; 4 | requires junit; 5 | requires io.github.oshai.kotlinlogging; 6 | //noinspection JavaModuleDefinition 7 | requires dev.reformator.retracerepack; 8 | 9 | requires static dev.reformator.stacktracedecoroutinator.common; 10 | requires static dev.reformator.bytecodeprocessor.intrinsics; 11 | 12 | exports dev.reformator.stacktracedecoroutinator.test; 13 | 14 | //noinspection JavaModuleDefinition 15 | opens dev.reformator.stacktracedecoroutinator.test; 16 | } 17 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/kotlin/org/example/project/MainActivity.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | import android.os.Bundle 4 | import androidx.activity.ComponentActivity 5 | import androidx.activity.compose.setContent 6 | import androidx.compose.runtime.Composable 7 | import androidx.compose.ui.tooling.preview.Preview 8 | 9 | class MainActivity : ComponentActivity() { 10 | override fun onCreate(savedInstanceState: Bundle?) { 11 | super.onCreate(savedInstanceState) 12 | 13 | setContent { 14 | App() 15 | } 16 | } 17 | } 18 | 19 | @Preview 20 | @Composable 21 | fun AppAndroidPreview() { 22 | App() 23 | } -------------------------------------------------------------------------------- /gradle-plugin/android-tests/src/androidTest/kotlin/gradle-plugin-android-tests-proxy.kt: -------------------------------------------------------------------------------- 1 | import androidx.annotation.Keep 2 | 3 | @Keep 4 | class TestLocalFile: dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.TestLocalFile() 5 | 6 | @Keep 7 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.TailCallDeoptimizeTest() 8 | 9 | @Keep 10 | class DebugProbesTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.DebugProbesTest() 11 | 12 | @Keep 13 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests.RuntimeTest() 14 | 15 | @Keep 16 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 17 | -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn edu.umd.cs.findbugs.annotations.** 2 | -dontwarn java.** 3 | -dontwarn javax.** 4 | -dontwarn reactor.** 5 | -dontwarn com.google.errorprone.annotations.** 6 | 7 | -keepclasseswithmembers class * { 8 | @org.junit.Test ; 9 | (); 10 | } 11 | -keepclasseswithmembers class * { 12 | @org.junit.Before ; 13 | (); 14 | } 15 | -keepclasseswithmembers class * { 16 | @org.junit.Rule ; 17 | (); 18 | } 19 | -keep class androidx.test.runner.AndroidJUnitRunner { *; } 20 | -keep class dev.reformator.stacktracedecoroutinator.test.Test_utilsKt { 21 | setRetraceMappingFiles(java.lang.String[]); 22 | } 23 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/api/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | api(libs.asm.utils) 13 | 14 | testImplementation(kotlin("test")) 15 | } 16 | 17 | tasks.test { 18 | useJUnitPlatform() 19 | } 20 | 21 | java { 22 | sourceCompatibility = JavaVersion.VERSION_1_8 23 | targetCompatibility = JavaVersion.VERSION_1_8 24 | } 25 | 26 | tasks.withType { 27 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 28 | } 29 | 30 | kotlin { 31 | compilerOptions { 32 | jvmTarget = JvmTarget.JVM_1_8 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/src/main/kotlin/loadConstant-intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.intrinsics 4 | 5 | @Retention(AnnotationRetention.BINARY) 6 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER) 7 | annotation class LoadConstant( 8 | val key: String, 9 | val deleteAfterModification: Boolean = true 10 | ) 11 | 12 | @Retention(AnnotationRetention.BINARY) 13 | @Target(AnnotationTarget.CLASS) 14 | annotation class ClassNameConstant(val key: String) 15 | 16 | @Retention(AnnotationRetention.BINARY) 17 | @Target(AnnotationTarget.FUNCTION, AnnotationTarget.PROPERTY_GETTER, AnnotationTarget.PROPERTY_SETTER) 18 | annotation class MethodNameConstant(val key: String) 19 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "bytecode-processor" 2 | include( 3 | "api", 4 | "plugins", 5 | "intrinsics", 6 | "gradle-plugin" 7 | ) 8 | project(":api").name = "bytecode-processor-api" 9 | project(":plugins").name = "bytecode-processor-plugins" 10 | project(":intrinsics").name = "bytecode-processor-intrinsics" 11 | project(":gradle-plugin").name = "bytecode-processor-gradle-plugin" 12 | 13 | includeBuild("../force-variant-java-version") 14 | 15 | pluginManagement { 16 | includeBuild("../force-variant-java-version") 17 | } 18 | 19 | dependencyResolutionManagement { 20 | versionCatalogs { 21 | create("libs") { 22 | from(files("../../gradle/libs.versions.toml")) 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /jvm-agent-common/suspend-class-stub/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.LoadConstantProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | //noinspection UseTomlInstead 15 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 16 | } 17 | 18 | bytecodeProcessor { 19 | processors = listOf(LoadConstantProcessor) 20 | } 21 | 22 | tasks.withType { 23 | options.compilerArgs.addAll(listOf("-parameters")) 24 | } 25 | 26 | kotlin { 27 | compilerOptions { 28 | jvmTarget = JvmTarget.JVM_1_8 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /gradle-plugin/android-legacy-tests/src/androidTest/kotlin/gradle-plugin-android-legacy-tests-proxy.kt: -------------------------------------------------------------------------------- 1 | import androidx.annotation.Keep 2 | 3 | @Keep 4 | class TestLocalFile: dev.reformator.stacktracedecoroutinator.gradlepluginandroidlegacytests.TestLocalFile() 5 | 6 | @Keep 7 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidlegacytests.TailCallDeoptimizeTest() 8 | 9 | @Keep 10 | class DebugProbesTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidlegacytests.DebugProbesTest() 11 | 12 | @Keep 13 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidlegacytests.RuntimeTest() 14 | 15 | @Keep 16 | class OldAndroidTest: dev.reformator.stacktracedecoroutinator.gradlepluginandroidlegacytests.OldAndroidTest() 17 | -------------------------------------------------------------------------------- /jvm-agent-common/src/test/kotlin/showBaseContinuation.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package showbasecontinuation 4 | 5 | import dev.reformator.stacktracedecoroutinator.intrinsics.BASE_CONTINUATION_CLASS_NAME 6 | import dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal.getResourceAsStream 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.internalName 8 | import org.objectweb.asm.ClassReader 9 | import org.objectweb.asm.util.TraceClassVisitor 10 | import java.io.PrintWriter 11 | 12 | fun main() { 13 | val classReader = ClassReader(getResourceAsStream(BASE_CONTINUATION_CLASS_NAME.internalName + ".class")) 14 | PrintWriter(System.out.writer()).use { 15 | classReader.accept(TraceClassVisitor(it), 0) 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/runtime-settings/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | java { 12 | sourceCompatibility = JavaVersion.VERSION_1_8 13 | targetCompatibility = JavaVersion.VERSION_1_8 14 | } 15 | 16 | kotlin { 17 | compilerOptions { 18 | jvmTarget = JvmTarget.JVM_1_8 19 | } 20 | } 21 | 22 | sourceSets { 23 | main { 24 | kotlin.destinationDirectory = java.destinationDirectory 25 | } 26 | test { 27 | kotlin.destinationDirectory = java.destinationDirectory 28 | } 29 | } 30 | 31 | val kotlinSources = sourceSets.main.get().kotlin 32 | kotlinSources.srcDirs("../../../runtime-settings/src/main/kotlin") 33 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/kotlin/gradle-plugin-utils.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.gradleplugin 4 | 5 | import java.util.Base64 6 | import java.util.zip.ZipInputStream 7 | 8 | internal fun ArtifactBuilder.addJarClassesAndResources(jarBase64: String) { 9 | ZipInputStream(Base64.getDecoder().decode(jarBase64).inputStream()).use { input -> 10 | while (true) { 11 | val entry = input.nextEntry ?: break 12 | if (!entry.isDirectory && entry.name != "META-INF/MANIFEST.MF") { 13 | val path = entry.name.split("/") 14 | val body = input.readBytes() 15 | ensureDirAndAndAddFile(path, body.inputStream()) 16 | } 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gradle-plugin/android-tests/proguard-rules.pro: -------------------------------------------------------------------------------- 1 | -dontwarn edu.umd.cs.findbugs.annotations.** 2 | -dontwarn java.** 3 | -dontwarn javax.** 4 | -dontwarn reactor.** 5 | -dontwarn com.google.errorprone.annotations.** 6 | -dontwarn android.test.AndroidTestCase 7 | -dontwarn android.test.InstrumentationTestCase 8 | 9 | -keepclasseswithmembers class * { 10 | @org.junit.Test ; 11 | (); 12 | } 13 | -keepclasseswithmembers class * { 14 | @org.junit.Before ; 15 | (); 16 | } 17 | -keepclasseswithmembers class * { 18 | @org.junit.Rule ; 19 | (); 20 | } 21 | -keep class androidx.test.runner.AndroidJUnitRunner { *; } 22 | -keep class dev.reformator.stacktracedecoroutinator.test.Test_utilsKt { 23 | setRetraceMappingFiles(java.lang.String[]); 24 | } 25 | -------------------------------------------------------------------------------- /mh-invoker/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker; 2 | import dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker; 3 | import dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularMethodHandleInvoker; 4 | import dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularVarHandleInvoker; 5 | 6 | module dev.reformator.stacktracedecoroutinator.mhinvoker { 7 | requires static dev.reformator.bytecodeprocessor.intrinsics; 8 | 9 | requires dev.reformator.stacktracedecoroutinator.provider; 10 | requires dev.reformator.stacktracedecoroutinator.common; 11 | 12 | provides MethodHandleInvoker with RegularMethodHandleInvoker; 13 | provides VarHandleInvoker with RegularVarHandleInvoker; 14 | } 15 | -------------------------------------------------------------------------------- /jvm/src/test/kotlin/example.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.jvmtests 2 | 3 | import dev.reformator.stacktracedecoroutinator.jvm.DecoroutinatorJvmApi 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.yield 6 | 7 | object Test { 8 | suspend fun rec(depth: Int) { 9 | if (depth == 0) { 10 | yield() 11 | throw Exception("exception at ${System.currentTimeMillis()}") 12 | } 13 | rec(depth - 1) 14 | } 15 | } 16 | 17 | fun main() { 18 | DecoroutinatorJvmApi.install() // enable stacktrace-decoroutinator runtime 19 | try { 20 | runBlocking { 21 | Test.rec(10) 22 | } 23 | } catch (e: Exception) { 24 | e.printStackTrace() // print full stack trace with 10 recursive calls 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/plugins/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | implementation(project(":bytecode-processor-api")) 13 | implementation(project(":bytecode-processor-intrinsics")) 14 | 15 | testImplementation(kotlin("test")) 16 | } 17 | 18 | tasks.test { 19 | useJUnitPlatform() 20 | } 21 | 22 | java { 23 | sourceCompatibility = JavaVersion.VERSION_1_8 24 | targetCompatibility = JavaVersion.VERSION_1_8 25 | } 26 | 27 | tasks.withType { 28 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 29 | } 30 | 31 | kotlin { 32 | compilerOptions { 33 | jvmTarget = JvmTarget.JVM_1_8 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /gradle-plugin/duplicate-entity-jar-builder/src/main/kotlin/proxyCaller.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.duplicatejar 2 | 3 | import dev.reformator.bytecodeprocessor.intrinsics.GetOwnerClass 4 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 5 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 6 | import dev.reformator.bytecodeprocessor.intrinsics.fail 7 | 8 | suspend fun call(callIt: suspend () -> Any?): Any? { 9 | duplicateJarCallLineNumber = currentLineNumber + 1 10 | return callIt() 11 | } 12 | 13 | private val currentFileClass: Class<*> 14 | @GetOwnerClass get() { fail() } 15 | 16 | val duplicateJarCallClassName = currentFileClass.name 17 | val duplicateJarCallMethodName = ::call.name 18 | var duplicateJarCallLineNumber = 0 19 | val duplicateJarFileName = currentFileName 20 | -------------------------------------------------------------------------------- /jvm-agent-common/src/main/kotlin/internal/utils-jvm-agent-common.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal 2 | 3 | import dev.reformator.bytecodeprocessor.intrinsics.ownerClass 4 | import java.io.InputStream 5 | 6 | internal fun getResourceAsStream(name: String): InputStream? = 7 | try { 8 | Thread.currentThread().contextClassLoader.getResourceAsStream(name) 9 | } catch (_: Throwable) { 10 | null 11 | } ?: try { 12 | ownerClass.classLoader.getResourceAsStream(name) 13 | } catch (_: Throwable) { 14 | null 15 | } ?: try { 16 | ClassLoader.getSystemClassLoader().getResourceAsStream(name) 17 | } catch (_: Throwable) { 18 | null 19 | } ?: try { 20 | ClassLoader.getSystemResourceAsStream(name) 21 | } catch (_: Throwable) { 22 | null 23 | } 24 | -------------------------------------------------------------------------------- /test-utils/custom-loader/src/main/kotlin/test-utils-custom-loader.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.test 4 | 5 | import org.junit.jupiter.api.Assertions.assertTrue 6 | 7 | fun checkStacktrace(vararg elements: StackTraceElement) { 8 | if (elements.isEmpty()) { 9 | return 10 | } 11 | Exception().stackTrace.also { stacktrace -> 12 | val startIndex = stacktrace.indexOfFirst { it eq elements[0] } 13 | elements.forEachIndexed { index, element -> 14 | assertTrue(element eq stacktrace[startIndex + index]) 15 | } 16 | } 17 | } 18 | 19 | private infix fun StackTraceElement.eq(element: StackTraceElement) = 20 | this.className == element.className && this.methodName == element.methodName && 21 | this.lineNumber == element.lineNumber 22 | 23 | -------------------------------------------------------------------------------- /generator-jvm/jdk8-tests-g/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | id("decoroutinatorTransformBaseContinuation") 4 | } 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | testRuntimeOnly(project(":stacktrace-decoroutinator-generator-jvm")) 12 | testRuntimeOnly(project(":stacktrace-decoroutinator-mh-invoker")) 13 | 14 | testImplementation(kotlin("test")) 15 | testImplementation(project(":test-utils")) 16 | testImplementation(project(":test-utils-jvm")) 17 | testRuntimeOnly(project(":test-utils:base-continuation-accessor-stub")) 18 | } 19 | 20 | afterEvaluate { 21 | configurations.testRuntimeClasspath.get().attributes.attribute(decoroutinatorTransformedBaseContinuationAttribute, true) 22 | } 23 | 24 | tasks.test { 25 | useJUnitPlatform() 26 | } 27 | 28 | kotlin { 29 | jvmToolchain(8) 30 | } 31 | -------------------------------------------------------------------------------- /mh-invoker-jvm/jdk8-tests-mij/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | id("decoroutinatorTransformBaseContinuation") 4 | } 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | testRuntimeOnly(project(":stacktrace-decoroutinator-generator-jvm")) 12 | testRuntimeOnly(project(":stacktrace-decoroutinator-mh-invoker-jvm")) 13 | 14 | testImplementation(kotlin("test")) 15 | testImplementation(project(":test-utils")) 16 | testImplementation(project(":test-utils-jvm")) 17 | testRuntimeOnly(project(":test-utils:base-continuation-accessor-stub")) 18 | } 19 | 20 | afterEvaluate { 21 | configurations.testRuntimeClasspath.get().attributes.attribute(decoroutinatorTransformedBaseContinuationAttribute, true) 22 | } 23 | 24 | tasks.test { 25 | useJUnitPlatform() 26 | } 27 | 28 | kotlin { 29 | jvmToolchain(8) 30 | } 31 | -------------------------------------------------------------------------------- /mh-invoker-jvm/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker; 2 | import dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker; 3 | import dev.reformator.stacktracedecoroutinator.mhinvokerjvm.internal.JvmMethodHandleInvoker; 4 | import dev.reformator.stacktracedecoroutinator.mhinvokerjvm.internal.JvmVarHandleInvoker; 5 | 6 | module dev.reformator.stacktracedecoroutinator.mhinvokerjvm { 7 | requires static dev.reformator.bytecodeprocessor.intrinsics; 8 | requires static intrinsics; 9 | 10 | requires dev.reformator.stacktracedecoroutinator.provider; 11 | requires dev.reformator.stacktracedecoroutinator.common; 12 | requires kotlin.stdlib; 13 | 14 | provides MethodHandleInvoker with JvmMethodHandleInvoker; 15 | provides VarHandleInvoker with JvmVarHandleInvoker; 16 | } 17 | -------------------------------------------------------------------------------- /generator-android/src/test/kotlin/jvm-tests-generator-android.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.methodHandleInvoker 2 | import kotlinx.coroutines.runBlocking 3 | import kotlinx.coroutines.yield 4 | import org.junit.Test 5 | import kotlin.test.assertEquals 6 | import kotlin.test.assertTrue 7 | 8 | class JvmTestsGeneratorAndroid { 9 | @Test 10 | fun runJvmWithGeneratorAndroid() { 11 | val message = "OK" 12 | 13 | suspend fun f() { 14 | yield() 15 | error(message) 16 | } 17 | 18 | try { 19 | runBlocking { 20 | f() 21 | } 22 | } catch (e: IllegalStateException) { 23 | assertEquals(message, e.message) 24 | assertTrue(e.stackTrace.any { it.className == methodHandleInvoker.unknownSpecMethodClass.name }) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /_plugins/bytecode-processor/plugins/src/main/kotlin/deleteClass-plugins.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.plugins 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.DeleteClass 6 | import dev.reformator.bytecodeprocessor.api.BytecodeProcessorContext 7 | import dev.reformator.bytecodeprocessor.api.ProcessingDirectory 8 | import dev.reformator.bytecodeprocessor.api.Processor 9 | import dev.reformator.bytecodeprocessor.plugins.internal.find 10 | 11 | object DeleteClassProcessor: Processor { 12 | override fun process(directory: ProcessingDirectory, context: BytecodeProcessorContext) { 13 | directory.classes.forEach { processingClass -> 14 | processingClass.node.invisibleAnnotations.find(DeleteClass::class.java) ?: return@forEach 15 | 16 | processingClass.delete() 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/gradle-plugin/src/main/kotlin/api-gradle-plugin-bytecode-processor.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package org.gradle.kotlin.dsl 4 | 5 | import dev.reformator.bytecodeprocessor.gradleplugin.BytecodeProcessorPluginExtension 6 | import dev.reformator.bytecodeprocessor.gradleplugin.EXTENSION_NAME 7 | import dev.reformator.bytecodeprocessor.gradleplugin.INIT_TASK_NAME 8 | import org.gradle.api.Project 9 | import org.gradle.api.Task 10 | 11 | fun Project.bytecodeProcessor(configure: BytecodeProcessorPluginExtension.() -> Unit) { 12 | extensions.configure(EXTENSION_NAME, configure) 13 | } 14 | 15 | val Project.bytecodeProcessor: BytecodeProcessorPluginExtension 16 | get() = extensions.getByName(EXTENSION_NAME) as BytecodeProcessorPluginExtension 17 | 18 | val Project.bytecodeProcessorInitTask: Task 19 | get() = tasks.findByName(INIT_TASK_NAME)!! 20 | -------------------------------------------------------------------------------- /test-utils-jvm/src/main/kotlin/test-utils.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.testjvm 4 | 5 | import org.junit.jupiter.api.Assertions.assertTrue 6 | 7 | fun checkStacktrace(vararg elements: StackTraceElement) { 8 | if (elements.isEmpty()) { 9 | return 10 | } 11 | Exception().stackTrace.also { stacktrace -> 12 | val startIndex = stacktrace.indexOfFirst { elements[0] eq it } 13 | elements.forEachIndexed { index, element -> 14 | assertTrue(element eq stacktrace[startIndex + index]) 15 | } 16 | } 17 | } 18 | 19 | private infix fun StackTraceElement.eq(element: StackTraceElement) = 20 | this.className == element.className && (this.methodName == element.methodName || this.methodName == ANY) && 21 | this.lineNumber == element.lineNumber 22 | 23 | const val ANY = "" 24 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/intrinsics/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | id("dev.reformator.forcevariantjavaversion") 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation(libs.asm.utils) 14 | testImplementation(kotlin("test")) 15 | } 16 | 17 | tasks.test { 18 | useJUnitPlatform() 19 | } 20 | 21 | java { 22 | sourceCompatibility = JavaVersion.VERSION_1_9 23 | targetCompatibility = JavaVersion.VERSION_1_9 24 | } 25 | 26 | tasks.withType { 27 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 28 | } 29 | 30 | kotlin { 31 | compilerOptions { 32 | jvmTarget = JvmTarget.JVM_1_8 33 | } 34 | } 35 | 36 | sourceSets { 37 | main { 38 | kotlin.destinationDirectory = java.destinationDirectory 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /_latest-gradle-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | 8 | dependencies { 9 | classpath(libs.kotlin.gradle.plugin.latest) 10 | classpath(libs.android.gradle.plugin) 11 | classpath(fileTree("../gradle-plugin/build/libs") { include("*.jar") }) 12 | classpath(libs.kotlin.logging.jvm) 13 | classpath(fileTree("../provider/build/libs") { include("*.jar") }) 14 | classpath(fileTree("../class-transformer/build/libs") { include("*.jar") }) 15 | classpath(fileTree("../spec-method-builder/build/libs") { include("*.jar") }) 16 | classpath(libs.kotlin.metadata.jvm) 17 | classpath(libs.asm.utils) 18 | } 19 | } 20 | 21 | subprojects { 22 | group = "dev.reformator.stacktracedecoroutinator-latest-gradle" 23 | version = "1.0.0-SNAPSHOT" 24 | } 25 | -------------------------------------------------------------------------------- /test-utils/retrace-repack/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | id("java") 3 | alias(libs.plugins.shadow) 4 | id("dev.reformator.forcevariantjavaversion") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | implementation(libs.retrace) 13 | } 14 | 15 | java { 16 | sourceCompatibility = JavaVersion.VERSION_1_9 17 | targetCompatibility = JavaVersion.VERSION_1_9 18 | } 19 | 20 | tasks.shadowJar { 21 | duplicatesStrategy = DuplicatesStrategy.EXCLUDE 22 | failOnDuplicateEntries = true 23 | archiveClassifier = "" 24 | relocate("proguard", "dev.reformator.retracerepack") 25 | excludes.remove("module-info.class") 26 | exclude("**/_dummy.class") 27 | exclude("com/**") 28 | exclude("kotlin/**") 29 | exclude("org/**") 30 | exclude("META-INF/versions/**") 31 | exclude("META-INF/*.kotlin_module") 32 | exclude("META-INF/services/*") 33 | } 34 | -------------------------------------------------------------------------------- /generator-jvm/android-wrong-generator-tests/src/androidTest/kotlin/android-tests-generator-jvm.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.methodHandleInvoker 2 | import kotlinx.coroutines.runBlocking 3 | import kotlinx.coroutines.yield 4 | import org.junit.Assert.assertEquals 5 | import org.junit.Assert.assertTrue 6 | import org.junit.Test 7 | 8 | class AndroidTestsGeneratorJvm { 9 | @Test 10 | fun runAndroidWithGeneratorJvm() { 11 | val message = "OK" 12 | 13 | suspend fun f() { 14 | yield() 15 | error(message) 16 | } 17 | 18 | try { 19 | runBlocking { 20 | f() 21 | } 22 | } catch (e: IllegalStateException) { 23 | assertEquals(message, e.message) 24 | assertTrue(e.stackTrace.any { it.className == methodHandleInvoker.unknownSpecMethodClass.name }) 25 | } 26 | } 27 | } -------------------------------------------------------------------------------- /gradle-plugin/embedded-debug-probes-stdlib/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | //noinspection UseTomlInstead 13 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 14 | 15 | implementation(project(":stacktrace-decoroutinator-runtime-settings")) 16 | } 17 | 18 | java { 19 | sourceCompatibility = JavaVersion.VERSION_1_9 20 | targetCompatibility = JavaVersion.VERSION_1_9 21 | } 22 | 23 | kotlin { 24 | compilerOptions { 25 | jvmTarget = JvmTarget.JVM_1_8 26 | freeCompilerArgs.add("-Xallow-kotlin-package") 27 | } 28 | } 29 | 30 | sourceSets { 31 | main { 32 | kotlin.destinationDirectory = java.destinationDirectory 33 | } 34 | test { 35 | kotlin.destinationDirectory = java.destinationDirectory 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /jvm-agent-common/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal.AgentBaseContinuationAccessorProvider; 2 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider; 3 | 4 | module dev.reformator.stacktracedecoroutinator.jvmagentcommon { 5 | requires static intrinsics; 6 | requires static dev.reformator.bytecodeprocessor.intrinsics; 7 | 8 | requires kotlin.stdlib; 9 | requires dev.reformator.stacktracedecoroutinator.runtimesettings; 10 | requires dev.reformator.stacktracedecoroutinator.provider; 11 | requires java.instrument; 12 | requires dev.reformator.stacktracedecoroutinator.classtransformer; 13 | 14 | exports dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal to 15 | dev.reformator.stacktracedecoroutinator.jvm; 16 | 17 | provides BaseContinuationAccessorProvider with AgentBaseContinuationAccessorProvider; 18 | } 19 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/custom-loader/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | 3 | plugins { 4 | alias(libs.plugins.kotlin.jvm.latest) 5 | id("dev.reformator.bytecodeprocessor") 6 | alias(libs.plugins.shadow) 7 | } 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | //noinspection UseTomlInstead 15 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 16 | implementation(libs.kotlinx.coroutines.jdk8.build) 17 | implementation(libs.junit5.api) 18 | } 19 | 20 | tasks.shadowJar { 21 | failOnDuplicateEntries = true 22 | } 23 | 24 | bytecodeProcessor { 25 | processors = setOf( 26 | GetCurrentFileNameProcessor, 27 | GetOwnerClassProcessor 28 | ) 29 | } 30 | 31 | tasks.test { 32 | useJUnitPlatform() 33 | } 34 | 35 | val kotlinSources = sourceSets.main.get().kotlin 36 | kotlinSources.srcDirs("../../../test-utils/custom-loader/src/main/kotlin") 37 | -------------------------------------------------------------------------------- /intrinsics/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.ChangeClassNameProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.forcevariantjavaversion") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 16 | testImplementation(kotlin("test")) 17 | } 18 | 19 | tasks.test { 20 | useJUnitPlatform() 21 | } 22 | 23 | java { 24 | sourceCompatibility = JavaVersion.VERSION_1_9 25 | targetCompatibility = JavaVersion.VERSION_1_9 26 | } 27 | 28 | kotlin { 29 | compilerOptions { 30 | jvmTarget = JvmTarget.JVM_1_8 31 | } 32 | } 33 | 34 | sourceSets { 35 | main { 36 | kotlin.destinationDirectory = java.destinationDirectory 37 | } 38 | } 39 | 40 | bytecodeProcessor { 41 | processors = listOf( 42 | ChangeClassNameProcessor 43 | ) 44 | skipUpdate = true 45 | } 46 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-reflect-stub/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | compileOnly(project(":intrinsics")) 15 | implementation(project(":stacktrace-decoroutinator-provider")) 16 | } 17 | 18 | bytecodeProcessor { 19 | dependentProjects = listOf( 20 | project(":intrinsics"), 21 | project(":stacktrace-decoroutinator-provider") 22 | ) 23 | processors = listOf( 24 | ChangeClassNameProcessor 25 | ) 26 | } 27 | 28 | java { 29 | sourceCompatibility = JavaVersion.VERSION_1_8 30 | targetCompatibility = JavaVersion.VERSION_1_8 31 | } 32 | 33 | tasks.withType { 34 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 35 | } 36 | 37 | kotlin { 38 | compilerOptions { 39 | jvmTarget = JvmTarget.JVM_1_8 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/embedded-debug-probes-stdlib/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | } 10 | 11 | dependencies { 12 | //noinspection UseTomlInstead 13 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 14 | compileOnly(project(":intrinsics")) 15 | } 16 | 17 | java { 18 | sourceCompatibility = JavaVersion.VERSION_1_8 19 | targetCompatibility = JavaVersion.VERSION_1_8 20 | } 21 | 22 | kotlin { 23 | compilerOptions { 24 | jvmTarget = JvmTarget.JVM_1_8 25 | freeCompilerArgs.add("-Xallow-kotlin-package") 26 | } 27 | } 28 | 29 | sourceSets { 30 | main { 31 | kotlin.destinationDirectory = java.destinationDirectory 32 | } 33 | test { 34 | kotlin.destinationDirectory = java.destinationDirectory 35 | } 36 | } 37 | 38 | val kotlinSources = sourceSets.main.get().kotlin 39 | kotlinSources.srcDirs("../../../gradle-plugin/embedded-debug-probes-stdlib/src/main/kotlin") 40 | -------------------------------------------------------------------------------- /gradle-plugin/gradle-groovy-dsl-tests/build.gradle: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | id 'dev.reformator.stacktracedecoroutinator' 5 | id 'org.jetbrains.kotlin.jvm' 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | stacktraceDecoroutinator { 13 | regularDependencyConfigurations.include = [] 14 | androidDependencyConfigurations.include = [] 15 | jvmDependencyConfigurations.include = [] 16 | addJvmRuntimeDependency = false 17 | } 18 | 19 | java { 20 | sourceCompatibility = JavaVersion.VERSION_1_9 21 | targetCompatibility = JavaVersion.VERSION_1_9 22 | } 23 | 24 | kotlin { 25 | compilerOptions { 26 | jvmTarget = JvmTarget.JVM_1_8 27 | } 28 | } 29 | 30 | assertTrue(decoroutinatorCommon().startsWith("dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-common:")) 31 | assertTrue(File.class.isInstance(decoroutinatorAndroidProGuardRules())) 32 | 33 | static def assertTrue(Boolean value) { 34 | if (!value) { 35 | throw new RuntimeException("check failed") 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /provider/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.provider.internal.DecoroutinatorProvider; 2 | 3 | module dev.reformator.stacktracedecoroutinator.provider { 4 | requires static kotlin.stdlib; 5 | requires static dev.reformator.bytecodeprocessor.intrinsics; 6 | 7 | exports dev.reformator.stacktracedecoroutinator.provider; 8 | exports dev.reformator.stacktracedecoroutinator.provider.internal to 9 | kotlin.stdlib, 10 | dev.reformator.stacktracedecoroutinator.common, 11 | dev.reformator.stacktracedecoroutinator.mhinvoker, 12 | dev.reformator.stacktracedecoroutinator.generatorjvm, 13 | dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub, 14 | dev.reformator.stacktracedecoroutinator.jvmagentcommon, 15 | dev.reformator.stacktracedecoroutinator.generator.tests, 16 | dev.reformator.stacktracedecoroutinator.specmethodbuilder, 17 | dev.reformator.stacktracedecoroutinator.classtransformer; 18 | 19 | uses DecoroutinatorProvider; 20 | } 21 | -------------------------------------------------------------------------------- /_plugins/force-variant-java-version/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | buildscript { 4 | repositories { 5 | mavenCentral() 6 | gradlePluginPortal() 7 | } 8 | } 9 | 10 | plugins { 11 | alias(libs.plugins.kotlin.jvm.build) 12 | alias(libs.plugins.gradle.plugin.publish) 13 | } 14 | 15 | group = "dev.reformator.forcevariantjavaversion" 16 | version = "0.0.1-SNAPSHOT" 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | implementation(libs.kotlin.logging.jvm) 24 | } 25 | 26 | java { 27 | sourceCompatibility = JavaVersion.VERSION_1_8 28 | targetCompatibility = JavaVersion.VERSION_1_8 29 | } 30 | 31 | kotlin { 32 | compilerOptions { 33 | jvmTarget = JvmTarget.JVM_1_8 34 | } 35 | } 36 | 37 | 38 | gradlePlugin { 39 | plugins { 40 | create("forcevariantjavaversionPlugin") { 41 | id = "dev.reformator.forcevariantjavaversion" 42 | implementationClass = "dev.reformator.forcevariantjavaversion.ForceVariantJavaVersionPlugin" 43 | } 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /jvm-agent/jdk8-tests-ja/src/test/kotlin/tests-jdk8-jvm-agent.kt: -------------------------------------------------------------------------------- 1 | import kotlinx.coroutines.runBlocking 2 | import kotlinx.coroutines.yield 3 | import kotlin.test.Test 4 | 5 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 6 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 7 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 8 | class CustomClassLoaderTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTailCallDeoptimizedTest() 9 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 10 | class JvmTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTailCallDeoptimizedTest() 11 | 12 | // Jacoco only instruments this class 13 | class JacocoInstrumentedMethodTest { 14 | @Test 15 | fun jacocoInstrumentedMethodTest(): Unit = runBlocking { 16 | suspend fun jacocoInstrumentedMethod() { 17 | yield() 18 | yield() 19 | } 20 | jacocoInstrumentedMethod() 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/AndroidManifest.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 11 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | -------------------------------------------------------------------------------- /_plugins/force-variant-java-version/src/main/kotlin/forceVariantJavaVersion.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.forcevariantjavaversion 4 | 5 | import org.gradle.api.Plugin 6 | import org.gradle.api.Project 7 | import org.gradle.api.attributes.java.TargetJvmVersion.TARGET_JVM_VERSION_ATTRIBUTE 8 | 9 | class ForceVariantJavaVersionPlugin: Plugin { 10 | override fun apply(target: Project) { 11 | with(target) { 12 | afterEvaluate { _ -> 13 | configurations.forEach { conf -> 14 | if (conf.attributes.getAttribute(TARGET_JVM_VERSION_ATTRIBUTE) == 9) { 15 | conf.attributes.attribute(TARGET_JVM_VERSION_ATTRIBUTE, 8) 16 | } 17 | conf.outgoing.variants.forEach { variant -> 18 | if (variant.attributes.getAttribute(TARGET_JVM_VERSION_ATTRIBUTE) == 9) { 19 | variant.attributes.attribute(TARGET_JVM_VERSION_ATTRIBUTE, 8) 20 | } 21 | } 22 | } 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /gradle-plugin/embedded-debug-probes-stdlib/src/main/kotlin/embedded-debug-probes-stdlib.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("DebugProbesKt") 3 | 4 | package kotlin.coroutines.jvm.internal 5 | 6 | import java.util.ServiceLoader 7 | import kotlin.coroutines.Continuation 8 | 9 | interface DecoroutinatorDebugProbesProvider { 10 | fun probeCoroutineCreated(completion: Continuation): Continuation 11 | fun probeCoroutineResumed(frame: Continuation<*>) 12 | fun probeCoroutineSuspended(frame: Continuation<*>) 13 | } 14 | 15 | private val provider: DecoroutinatorDebugProbesProvider = 16 | ServiceLoader.load(DecoroutinatorDebugProbesProvider::class.java).iterator().next() 17 | 18 | @Suppress("unused") 19 | fun probeCoroutineCreated(completion: Continuation): Continuation = 20 | provider.probeCoroutineCreated(completion) 21 | 22 | @Suppress("unused") 23 | fun probeCoroutineResumed(frame: Continuation<*>) { 24 | provider.probeCoroutineResumed(frame) 25 | } 26 | 27 | @Suppress("unused") 28 | fun probeCoroutineSuspended(frame: Continuation<*>) { 29 | provider.probeCoroutineSuspended(frame) 30 | } 31 | -------------------------------------------------------------------------------- /gradle-plugin/base-continuation-accessor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.ChangeClassNameProcessor 2 | import dev.reformator.bytecodeprocessor.plugins.LoadConstantProcessor 3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 4 | 5 | plugins { 6 | kotlin("jvm") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | bytecodeProcessor { 11 | dependentProjects = listOf(project(":intrinsics")) 12 | processors = listOf( 13 | ChangeClassNameProcessor, 14 | LoadConstantProcessor 15 | ) 16 | } 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | //noinspection UseTomlInstead 24 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 25 | compileOnly(project(":stacktrace-decoroutinator-provider")) 26 | compileOnly(project(":intrinsics")) 27 | } 28 | 29 | java { 30 | sourceCompatibility = JavaVersion.VERSION_1_8 31 | targetCompatibility = JavaVersion.VERSION_1_8 32 | } 33 | 34 | kotlin { 35 | compilerOptions { 36 | jvmTarget = JvmTarget.JVM_1_8 37 | freeCompilerArgs.add("-Xallow-kotlin-package") 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /test-utils/custom-loader/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | alias(libs.plugins.shadow) 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | //noinspection UseTomlInstead 16 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 17 | 18 | implementation(libs.kotlinx.coroutines.jdk8.build) 19 | implementation(libs.junit5.api) 20 | } 21 | 22 | tasks.shadowJar { 23 | failOnDuplicateEntries = true 24 | } 25 | 26 | bytecodeProcessor { 27 | processors = listOf( 28 | GetCurrentFileNameProcessor, 29 | GetOwnerClassProcessor 30 | ) 31 | } 32 | 33 | java { 34 | sourceCompatibility = JavaVersion.VERSION_1_8 35 | targetCompatibility = JavaVersion.VERSION_1_8 36 | } 37 | 38 | tasks.withType { 39 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 40 | } 41 | 42 | kotlin { 43 | compilerOptions { 44 | jvmTarget = JvmTarget.JVM_1_8 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gradle-plugin/aar-builder/src/main/kotlin/aar-builder.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.aarbuilder 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 6 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 7 | import dev.reformator.bytecodeprocessor.intrinsics.ownerClassName 8 | import dev.reformator.bytecodeprocessor.intrinsics.ownerMethodName 9 | 10 | @Suppress("unused") 11 | val suspendFunFromAarOwnerClassName = ownerClassName 12 | @Suppress("unused") 13 | val suspendFunFromAarMethodName: String 14 | get() = _suspendFunFromAarMethodName 15 | @Suppress("unused") 16 | val suspendFunFromAarFileName = currentFileName 17 | @Suppress("unused") 18 | val suspendFunFromAarLineNumber: Int 19 | get() = _suspendFunFromAarLineNumber 20 | 21 | @Suppress("unused") 22 | suspend fun suspendFunFromAar(body: suspend () -> T): T { 23 | _suspendFunFromAarMethodName = ownerMethodName 24 | _suspendFunFromAarLineNumber = currentLineNumber + 1 25 | return body() 26 | } 27 | 28 | 29 | private lateinit var _suspendFunFromAarMethodName: String 30 | private var _suspendFunFromAarLineNumber = 0 31 | -------------------------------------------------------------------------------- /gradle-plugin/base-continuation-accessor/src/main/kotlin/base-continuation-accessor.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package kotlin.coroutines.jvm.internal 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.ClassNameConstant 6 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessor 8 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider 9 | import java.lang.invoke.MethodHandles 10 | 11 | @Suppress("unused") 12 | @ClassNameConstant("baseContinuationAccessorImplClassName") 13 | class DecoroutinatorBaseContinuationAccessorImpl: BaseContinuationAccessor, BaseContinuationAccessorProvider { 14 | override fun invokeSuspend(baseContinuation: Any, result: Any?): Any? = 15 | (baseContinuation as BaseContinuation).invokeSuspend(result) 16 | 17 | override fun releaseIntercepted(baseContinuation: Any) { 18 | (baseContinuation as BaseContinuation).releaseIntercepted() 19 | } 20 | 21 | override fun createAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor = 22 | this 23 | } 24 | -------------------------------------------------------------------------------- /jvm-agent/tests-ja/src/test/kotlin/tests-jvm-agent.kt: -------------------------------------------------------------------------------- 1 | import kotlinx.coroutines.runBlocking 2 | import kotlinx.coroutines.yield 3 | import kotlin.test.Test 4 | 5 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 6 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 7 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 8 | class CustomClassLoaderTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTailCallDeoptimizedTest() 9 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 10 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 11 | class JvmTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTailCallDeoptimizedTest() 12 | 13 | // Jacoco only instruments this class 14 | class JacocoInstrumentedMethodTest { 15 | @Test 16 | fun jacocoInstrumentedMethodTest(): Unit = runBlocking { 17 | suspend fun jacocoInstrumentedMethod() { 18 | yield() 19 | yield() 20 | } 21 | jacocoInstrumentedMethod() 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/intrinsics/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.ChangeClassNameProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | //noinspection UseTomlInstead 15 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 16 | } 17 | 18 | java { 19 | sourceCompatibility = JavaVersion.VERSION_1_8 20 | targetCompatibility = JavaVersion.VERSION_1_8 21 | } 22 | 23 | kotlin { 24 | compilerOptions { 25 | jvmTarget = JvmTarget.JVM_1_8 26 | } 27 | } 28 | 29 | sourceSets { 30 | main { 31 | kotlin.destinationDirectory = java.destinationDirectory 32 | } 33 | test { 34 | kotlin.destinationDirectory = java.destinationDirectory 35 | } 36 | } 37 | 38 | bytecodeProcessor { 39 | processors = listOf( 40 | ChangeClassNameProcessor 41 | ) 42 | skipUpdate = true 43 | } 44 | 45 | val kotlinSources = sourceSets.main.get().kotlin 46 | kotlinSources.srcDirs("../../../intrinsics/src/main/kotlin") 47 | -------------------------------------------------------------------------------- /jvm-agent/jdk8-tests-ja/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | 3 | plugins { 4 | kotlin("jvm") 5 | jacoco 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | testImplementation(project(":test-utils")) 14 | testImplementation(project(":test-utils-jvm")) 15 | testImplementation(kotlin("test")) 16 | testImplementation(libs.kotlinx.coroutines.jdk8.build) 17 | testImplementation(project(":stacktrace-decoroutinator-jvm-agent", configuration = "shadow")) 18 | } 19 | 20 | tasks.test { 21 | useJUnitPlatform() 22 | val shadowJarTask = project(":stacktrace-decoroutinator-jvm-agent").tasks.named("shadowJar") 23 | dependsOn(shadowJarTask) 24 | val agentJar = shadowJarTask.get().outputs.files.singleFile 25 | jvmArgs( 26 | "-javaagent:${agentJar.absolutePath}", 27 | "-Ddev.reformator.stacktracedecoroutinator.jvmAgentDebugMetadataInfoResolveStrategy=SYSTEM_RESOURCE" 28 | ) 29 | extensions.configure(JacocoTaskExtension::class) { 30 | includes = listOf("JacocoInstrumentedMethodTest*") 31 | } 32 | } 33 | 34 | kotlin { 35 | jvmToolchain(8) 36 | } 37 | -------------------------------------------------------------------------------- /mh-invoker/src/main/kotlin/internal/unknown.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:AndroidKeep 3 | 4 | package dcunknown 5 | 6 | import dev.reformator.bytecodeprocessor.intrinsics.GetOwnerClass 7 | import dev.reformator.bytecodeprocessor.intrinsics.fail 8 | import dev.reformator.stacktracedecoroutinator.common.internal.specMethodType 9 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorSpec 10 | import dev.reformator.stacktracedecoroutinator.provider.internal.AndroidKeep 11 | import java.lang.invoke.MethodHandle 12 | import java.lang.invoke.MethodHandles 13 | 14 | internal val unknownSpecClass: Class<*> 15 | @GetOwnerClass get() = fail() 16 | 17 | @Suppress("unused") 18 | private fun unknown(spec: DecoroutinatorSpec, result: Any?): Any? { 19 | val updatedResult = if (!spec.isLastSpec) { 20 | spec.nextSpecHandle.invokeExact(spec.nextSpec, result) 21 | } else { 22 | result 23 | } 24 | return spec.resumeNext(updatedResult) 25 | } 26 | 27 | internal fun getUnknownSpecMethodHandle(): MethodHandle = 28 | MethodHandles.lookup().findStatic( 29 | unknownSpecClass, 30 | ::unknown.name, 31 | specMethodType 32 | ) 33 | -------------------------------------------------------------------------------- /gradle-plugin/embedded-debug-probes-xcoroutines/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.DeleteClassProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | bytecodeProcessor { 10 | processors = setOf( 11 | DeleteClassProcessor 12 | ) 13 | } 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | //noinspection UseTomlInstead 21 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 22 | compileOnly(project(":gradle-plugin:embedded-debug-probes-stdlib")) 23 | 24 | implementation(project(":stacktrace-decoroutinator-runtime-settings")) 25 | } 26 | 27 | java { 28 | sourceCompatibility = JavaVersion.VERSION_1_9 29 | targetCompatibility = JavaVersion.VERSION_1_9 30 | } 31 | 32 | kotlin { 33 | compilerOptions { 34 | jvmTarget = JvmTarget.JVM_1_8 35 | } 36 | } 37 | 38 | sourceSets { 39 | main { 40 | kotlin.destinationDirectory = java.destinationDirectory 41 | } 42 | test { 43 | kotlin.destinationDirectory = java.destinationDirectory 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "latest-kotlin-kmp-gradle-plugin-test" 2 | 3 | includeBuild("../../_plugins/gradle-plugin-test") 4 | includeBuild("../../_plugins/bytecode-processor") 5 | 6 | pluginManagement { 7 | includeBuild("../../_plugins/gradle-plugin-test") 8 | includeBuild("../../_plugins/bytecode-processor") 9 | repositories { 10 | google { 11 | mavenContent { 12 | includeGroupAndSubgroups("androidx") 13 | includeGroupAndSubgroups("com.android") 14 | includeGroupAndSubgroups("com.google") 15 | } 16 | } 17 | mavenCentral() 18 | gradlePluginPortal() 19 | } 20 | } 21 | 22 | dependencyResolutionManagement { 23 | versionCatalogs { 24 | create("libs") { 25 | from(files("../../gradle/libs.versions.toml")) 26 | } 27 | } 28 | repositories { 29 | google { 30 | mavenContent { 31 | includeGroupAndSubgroups("androidx") 32 | includeGroupAndSubgroups("com.android") 33 | includeGroupAndSubgroups("com.google") 34 | } 35 | } 36 | mavenCentral() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /provider/src/main/kotlin/internal/utils-provider.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.provider.internal 2 | 3 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorSpec 4 | import java.lang.invoke.MethodHandle 5 | 6 | val specLineNumberMethodName: String = DecoroutinatorSpec::class.java.methods 7 | .find { it.returnType == Int::class.javaPrimitiveType }!! 8 | .name 9 | 10 | val isLastSpecMethodName: String = DecoroutinatorSpec::class.java.methods 11 | .find { it.returnType == Boolean::class.javaPrimitiveType }!! 12 | .name 13 | 14 | @Suppress("NewApi") 15 | val nextSpecHandleMethodName: String = DecoroutinatorSpec::class.java.methods 16 | .find { it.returnType == MethodHandle::class.java }!! 17 | .name 18 | 19 | val nextSpecMethodName: String = DecoroutinatorSpec::class.java.methods 20 | .find { it.returnType == DecoroutinatorSpec::class.java }!! 21 | .name 22 | 23 | val resumeNextMethodName: String = DecoroutinatorSpec::class.java.methods 24 | .find { it.returnType == Object::class.java && it.parameterCount == 1 }!! 25 | .name 26 | 27 | @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN") 28 | val String.internalName: String 29 | get() = (this as java.lang.String).replace('.', '/') 30 | -------------------------------------------------------------------------------- /generator-jvm/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.AnnotationMetadataResolver; 2 | import dev.reformator.stacktracedecoroutinator.generatorjvm.internal.GeneratorJvmSpecMethodsFactory; 3 | import dev.reformator.stacktracedecoroutinator.common.internal.SpecMethodsFactory; 4 | import dev.reformator.stacktracedecoroutinator.generatorjvm.internal.AnnotationMetadataResolverImpl; 5 | 6 | module dev.reformator.stacktracedecoroutinator.generatorjvm { 7 | requires static dev.reformator.bytecodeprocessor.intrinsics; 8 | requires static intrinsics; 9 | 10 | requires kotlin.stdlib; 11 | requires org.objectweb.asm.tree; 12 | requires dev.reformator.stacktracedecoroutinator.provider; 13 | requires dev.reformator.stacktracedecoroutinator.common; 14 | requires dev.reformator.stacktracedecoroutinator.specmethodbuilder; 15 | 16 | exports dev.reformator.stacktracedecoroutinator.generatorjvm.internal to 17 | dev.reformator.stacktracedecoroutinator.jvmagentcommon, 18 | dev.reformator.stacktracedecoroutinator.generator.tests; 19 | 20 | provides SpecMethodsFactory with GeneratorJvmSpecMethodsFactory; 21 | provides AnnotationMetadataResolver with AnnotationMetadataResolverImpl; 22 | } 23 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/src/test/kotlin/last-kotlin-gradle-plugin-test.kt: -------------------------------------------------------------------------------- 1 | import kotlinx.coroutines.ExperimentalCoroutinesApi 2 | import kotlinx.coroutines.debug.DebugProbes 3 | import kotlinx.coroutines.runBlocking 4 | import kotlinx.coroutines.suspendCancellableCoroutine 5 | import org.junit.jupiter.api.Assertions.assertTrue 6 | import org.junit.jupiter.api.Test 7 | import kotlin.coroutines.resume 8 | 9 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 10 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 11 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() 12 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 13 | class JvmTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTailCallDeoptimizedTest() 14 | 15 | @OptIn(ExperimentalCoroutinesApi::class) 16 | class DebugProbesTest { 17 | @Test 18 | fun performDebugProbes() { 19 | runBlocking { 20 | suspendCancellableCoroutine { continuation -> 21 | assertTrue(DebugProbes.dumpCoroutinesInfo().isNotEmpty()) 22 | continuation.resume(Unit) 23 | } 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /jvm/jdk8-tests-j/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | kotlin("jvm") 3 | jacoco 4 | } 5 | 6 | repositories { 7 | mavenCentral() 8 | } 9 | 10 | dependencies { 11 | testImplementation(project(":stacktrace-decoroutinator-provider")) 12 | testImplementation(project(":stacktrace-decoroutinator-jvm")) 13 | testImplementation(libs.kotlinx.coroutines.jdk8.build) 14 | testImplementation(kotlin("test")) 15 | testImplementation(project(":test-utils")) 16 | testImplementation(project(":test-utils-jvm")) 17 | 18 | testCompileOnly(project(":intrinsics")) 19 | } 20 | 21 | tasks.test { 22 | useJUnitPlatform() 23 | extensions.configure(JacocoTaskExtension::class) { 24 | includes = listOf("JacocoInstrumentedMethodTest*") 25 | } 26 | systemProperty("testReloadBaseConfiguration", false) 27 | } 28 | 29 | val testReloadBaseConfigurationTask = tasks.register("testReloadBaseConfiguration") { 30 | useJUnitPlatform() 31 | classpath = tasks.test.get().classpath 32 | extensions.configure(JacocoTaskExtension::class) { 33 | excludes = listOf("*") 34 | } 35 | systemProperty("testReloadBaseConfiguration", true) 36 | } 37 | tasks.test.get().dependsOn(testReloadBaseConfigurationTask) 38 | 39 | kotlin { 40 | jvmToolchain(8) 41 | } 42 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-stub/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | id("dev.reformator.forcevariantjavaversion") 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | compileOnly(project(":intrinsics")) 16 | implementation(project(":stacktrace-decoroutinator-provider")) 17 | } 18 | 19 | bytecodeProcessor { 20 | dependentProjects = listOf( 21 | project(":intrinsics"), 22 | project(":stacktrace-decoroutinator-provider") 23 | ) 24 | processors = listOf( 25 | ChangeClassNameProcessor 26 | ) 27 | } 28 | 29 | java { 30 | sourceCompatibility = JavaVersion.VERSION_1_9 31 | targetCompatibility = JavaVersion.VERSION_1_9 32 | } 33 | 34 | tasks.withType { 35 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 36 | } 37 | 38 | kotlin { 39 | compilerOptions { 40 | jvmTarget = JvmTarget.JVM_1_8 41 | freeCompilerArgs.add("-Xjvm-default=all") 42 | } 43 | } 44 | 45 | sourceSets { 46 | main { 47 | kotlin.destinationDirectory = java.destinationDirectory 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/gradle-plugin/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 2 | 3 | plugins { 4 | kotlin("jvm") 5 | alias(libs.plugins.gradle.plugin.publish) 6 | } 7 | 8 | repositories { 9 | mavenCentral() 10 | } 11 | 12 | dependencies { 13 | implementation(libs.kotlin.gradle.plugin.api) 14 | api(project(":bytecode-processor-api")) 15 | api(project(":bytecode-processor-plugins")) 16 | implementation(libs.asm.utils) 17 | implementation(libs.jackson.core) 18 | implementation(libs.jackson.kotlin) 19 | testImplementation(kotlin("test")) 20 | } 21 | 22 | tasks.test { 23 | useJUnitPlatform() 24 | } 25 | 26 | java { 27 | sourceCompatibility = JavaVersion.VERSION_1_8 28 | targetCompatibility = JavaVersion.VERSION_1_8 29 | } 30 | 31 | tasks.withType { 32 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 33 | } 34 | 35 | kotlin { 36 | compilerOptions { 37 | jvmTarget = JvmTarget.JVM_1_8 38 | } 39 | } 40 | 41 | gradlePlugin { 42 | plugins { 43 | create("bytecodeProcessor") { 44 | id = "dev.reformator.bytecodeprocessor" 45 | implementationClass = "dev.reformator.bytecodeprocessor.gradleplugin.BytecodeProcessorPlugin" 46 | } 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /gradle-plugin/aar-builder/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.GetCurrentFileNameProcessor 2 | import dev.reformator.bytecodeprocessor.plugins.GetOwnerClassProcessor 3 | 4 | plugins { 5 | alias(libs.plugins.android.library) 6 | kotlin("android") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | google() 13 | } 14 | 15 | dependencies { 16 | //noinspection UseTomlInstead 17 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 18 | } 19 | 20 | bytecodeProcessor { 21 | processors = listOf( 22 | GetOwnerClassProcessor, 23 | GetCurrentFileNameProcessor 24 | ) 25 | } 26 | 27 | android { 28 | namespace = "dev.reformator.stacktracedecoroutinator.aarbuilder" 29 | compileSdk = 36 30 | defaultConfig { 31 | minSdk = 26 32 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 33 | } 34 | packaging { 35 | resources.pickFirsts.add("META-INF/*") 36 | resources.excludes.add("win32-x86-64/attach_hotspot_windows.dll") 37 | resources.excludes.add("win32-x86/attach_hotspot_windows.dll") 38 | resources.excludes.add("META-INF/licenses/*") 39 | } 40 | kotlin { 41 | jvmToolchain(8) 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /test-utils-jvm/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | id("dev.reformator.forcevariantjavaversion") 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | //noinspection UseTomlInstead 16 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 17 | 18 | implementation(libs.junit5.api) 19 | implementation(libs.kotlinx.coroutines.jdk8.build) 20 | implementation(libs.kotlin.logging.jvm) 21 | 22 | runtimeOnly(libs.logback.classic) 23 | } 24 | 25 | bytecodeProcessor { 26 | processors = setOf( 27 | GetCurrentFileNameProcessor, 28 | GetOwnerClassProcessor 29 | ) 30 | } 31 | 32 | java { 33 | sourceCompatibility = JavaVersion.VERSION_1_9 34 | targetCompatibility = JavaVersion.VERSION_1_9 35 | } 36 | 37 | tasks.withType { 38 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 39 | } 40 | 41 | kotlin { 42 | compilerOptions { 43 | jvmTarget = JvmTarget.JVM_1_8 44 | freeCompilerArgs.add("-Xjvm-default=all") 45 | } 46 | } 47 | 48 | sourceSets { 49 | main { 50 | kotlin.destinationDirectory = java.destinationDirectory 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /jvm-agent-common/src/main/kotlin/internal/di-jvm-agent-common.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal 4 | 5 | import dev.reformator.stacktracedecoroutinator.runtimesettings.DecoroutinatorMetadataInfoResolveStrategy 6 | import dev.reformator.stacktracedecoroutinator.runtimesettings.internal.getRuntimeSettingsValue 7 | 8 | internal val isBaseContinuationRedefinitionAllowed = 9 | getRuntimeSettingsValue({ isBaseContinuationRedefinitionAllowed }) { 10 | System.getProperty( 11 | "dev.reformator.stacktracedecoroutinator.isBaseContinuationRedefinitionAllowed", 12 | "true" 13 | ).toBoolean() 14 | } 15 | 16 | internal val isRedefinitionAllowed = 17 | getRuntimeSettingsValue({ isRedefinitionAllowed }) { 18 | System.getProperty( 19 | "dev.reformator.stacktracedecoroutinator.isRedefinitionAllowed", 20 | "false" 21 | ).toBoolean() 22 | } 23 | 24 | internal val metadataInfoResolveStrategy = 25 | getRuntimeSettingsValue({ metadataInfoResolveStrategy }) { 26 | DecoroutinatorMetadataInfoResolveStrategy.valueOf(System.getProperty( 27 | "dev.reformator.stacktracedecoroutinator.metadataInfoResolveStrategy", 28 | DecoroutinatorMetadataInfoResolveStrategy.SYSTEM_RESOURCE_AND_CLASS.name 29 | )) 30 | }.resolveFunction 31 | -------------------------------------------------------------------------------- /generator-jvm/android-wrong-generator-tests/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.library) 3 | kotlin("android") 4 | id("decoroutinatorTransformBaseContinuation") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | google() 10 | } 11 | 12 | android { 13 | namespace = "dev.reformator.stacktracedecoroutinator.generatorjvm.androidwronggeneratortests" 14 | compileSdk = 36 15 | defaultConfig { 16 | minSdk = 14 17 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 18 | } 19 | packaging { 20 | resources.pickFirsts.add("META-INF/*") 21 | } 22 | kotlin { 23 | jvmToolchain(8) 24 | } 25 | } 26 | 27 | dependencies { 28 | androidTestImplementation(project(":stacktrace-decoroutinator-common")) 29 | androidTestImplementation(libs.kotlinx.coroutines.jdk8.build) 30 | androidTestImplementation(libs.junit4) 31 | 32 | androidTestRuntimeOnly(libs.androidx.test.runner) 33 | androidTestRuntimeOnly(project(":test-utils:base-continuation-accessor-reflect-stub")) 34 | androidTestRuntimeOnly(project(":stacktrace-decoroutinator-mh-invoker-android")) 35 | androidTestRuntimeOnly(project(":stacktrace-decoroutinator-generator-jvm")) 36 | } 37 | 38 | afterEvaluate { 39 | configurations["debugAndroidTestRuntimeClasspath"].attributes.attribute(decoroutinatorTransformedBaseContinuationAttribute, true) 40 | } 41 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/provider/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.* 2 | import dev.reformator.bytecodeprocessor.plugins.GetOwnerClassProcessor 3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 4 | 5 | plugins { 6 | kotlin("jvm") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | repositories { 11 | mavenCentral() 12 | } 13 | 14 | dependencies { 15 | //noinspection UseTomlInstead 16 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 17 | 18 | testImplementation(kotlin("test")) 19 | } 20 | 21 | bytecodeProcessor { 22 | processors = listOf( 23 | RemoveKotlinStdlibProcessor, 24 | GetOwnerClassProcessor, 25 | LoadConstantProcessor 26 | ) 27 | } 28 | 29 | tasks.test { 30 | useJUnitPlatform() 31 | } 32 | 33 | java { 34 | sourceCompatibility = JavaVersion.VERSION_1_8 35 | targetCompatibility = JavaVersion.VERSION_1_8 36 | } 37 | 38 | tasks.withType { 39 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 40 | } 41 | 42 | kotlin { 43 | compilerOptions { 44 | jvmTarget = JvmTarget.JVM_1_8 45 | } 46 | } 47 | 48 | sourceSets { 49 | main { 50 | kotlin.destinationDirectory = java.destinationDirectory 51 | } 52 | } 53 | 54 | val kotlinSources = sourceSets.main.get().kotlin 55 | kotlinSources.srcDirs("../../../provider/src/main/kotlin") 56 | -------------------------------------------------------------------------------- /generator-jvm/src/test/kotlin/printSpecMethod.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package printspecmethod 4 | 5 | import dev.reformator.stacktracedecoroutinator.specmethodbuilder.internal.buildSpecMethodNode 6 | import org.objectweb.asm.ClassReader 7 | import org.objectweb.asm.ClassWriter 8 | import org.objectweb.asm.Opcodes 9 | import org.objectweb.asm.Type 10 | import org.objectweb.asm.tree.* 11 | import org.objectweb.asm.util.TraceClassVisitor 12 | import java.io.PrintWriter 13 | 14 | fun main() { 15 | val classNode = ClassNode(Opcodes.ASM9).apply { 16 | version = Opcodes.V1_8 17 | access = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER 18 | name = "dev/reformator/stacktracedecoroutinator/jvmcommon/StacktraceMethodPrinter" 19 | superName = Type.getInternalName(java.lang.Object::class.java) 20 | sourceFile = "internal/unknown.kt" 21 | } 22 | classNode.methods = mutableListOf(buildSpecMethodNode( 23 | methodName = "stacktraceMethod", 24 | lineNumbers = setOf(10, 20, 25, 30), 25 | makePrivate = true, 26 | makeFinal = true 27 | )) 28 | 29 | val classWriter = ClassWriter(ClassWriter.COMPUTE_FRAMES) 30 | classNode.accept(classWriter) 31 | val classReader = ClassReader(classWriter.toByteArray()) 32 | 33 | PrintWriter(System.out.writer()).use { 34 | classReader.accept(TraceClassVisitor(it), 0) 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /generator-jvm/src/main/kotlin/internal/specMethodsFactory-generator.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.generatorjvm.internal 4 | 5 | import dev.reformator.stacktracedecoroutinator.common.internal.* 6 | import java.lang.invoke.MethodHandle 7 | import java.util.concurrent.CopyOnWriteArrayList 8 | 9 | internal class GeneratorJvmSpecMethodsFactory: BaseSpecMethodsFactory() { 10 | init { 11 | //assert the platform 12 | DecoroutinatorClassLoader().buildClassAndGetSpecHandlesByMethod( 13 | className = "stub", 14 | fileName = "unknown", 15 | lineNumbersByMethod = emptyMap() 16 | ) 17 | } 18 | 19 | override fun generateSpecMethodHandles( 20 | className: String, 21 | classRevision: Int, 22 | fileName: String?, 23 | lineNumbersByMethod: Map> 24 | ): Map { 25 | while (loadersByRevision.size <= classRevision) loadersByRevision.add(DecoroutinatorClassLoader()) 26 | val loader = loadersByRevision[classRevision] 27 | return loader.buildClassAndGetSpecHandlesByMethod( 28 | className = className, 29 | fileName = fileName, 30 | lineNumbersByMethod = lineNumbersByMethod 31 | ) 32 | } 33 | 34 | private val loadersByRevision: MutableList = CopyOnWriteArrayList() 35 | } -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidInstrumentedTest/kotlin/tests-last-kotlin-kmp-gradle-plugin-android.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 2 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 3 | import dev.reformator.stacktracedecoroutinator.test.checkStacktrace 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.yield 6 | import org.junit.Test 7 | 8 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 9 | 10 | class TestLocalFile { 11 | @Test 12 | fun localTest(): Unit = runBlocking { 13 | fun1() 14 | } 15 | 16 | suspend fun fun1() { 17 | fun2(currentLineNumber) 18 | } 19 | 20 | suspend fun fun2(fun1LineNumber: Int) { 21 | val fun1Frame = StackTraceElement( 22 | TestLocalFile::class.qualifiedName, 23 | ::fun1.name, 24 | currentFileName, 25 | fun1LineNumber 26 | ) 27 | yield() 28 | fun3(fun1Frame, currentLineNumber) 29 | } 30 | 31 | suspend fun fun3(fun1Frame: StackTraceElement, fun2LineNumber: Int) { 32 | val fun2Frame = StackTraceElement( 33 | TestLocalFile::class.qualifiedName, 34 | ::fun2.name, 35 | currentFileName, 36 | fun2LineNumber 37 | ) 38 | yield() 39 | checkStacktrace(fun2Frame, fun1Frame) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidUnitTest/kotlin/tests-last-kotlin-kmp-gradle-plugin-android-unit-test.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 2 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 3 | import dev.reformator.stacktracedecoroutinator.test.checkStacktrace 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.yield 6 | import org.junit.Test 7 | 8 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 9 | 10 | class TestLocalFile { 11 | @Test 12 | fun localTest(): Unit = runBlocking { 13 | fun1() 14 | } 15 | 16 | suspend fun fun1() { 17 | fun2(currentLineNumber) 18 | } 19 | 20 | suspend fun fun2(fun1LineNumber: Int) { 21 | val fun1Frame = StackTraceElement( 22 | TestLocalFile::class.qualifiedName, 23 | ::fun1.name, 24 | currentFileName, 25 | fun1LineNumber 26 | ) 27 | yield() 28 | fun3(fun1Frame, currentLineNumber) 29 | } 30 | 31 | suspend fun fun3(fun1Frame: StackTraceElement, fun2LineNumber: Int) { 32 | val fun2Frame = StackTraceElement( 33 | TestLocalFile::class.qualifiedName, 34 | ::fun2.name, 35 | currentFileName, 36 | fun2LineNumber 37 | ) 38 | yield() 39 | checkStacktrace(fun2Frame, fun1Frame) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /jvm/src/main/kotlin/api-jvm.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.jvm 4 | 5 | import dev.reformator.stacktracedecoroutinator.intrinsics.BASE_CONTINUATION_CLASS_NAME 6 | import dev.reformator.stacktracedecoroutinator.jvm.internal.isTransformed 7 | import dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal.addDecoroutinatorTransformer 8 | import net.bytebuddy.agent.ByteBuddyAgent 9 | import java.util.concurrent.locks.ReentrantLock 10 | import kotlin.concurrent.withLock 11 | 12 | object DecoroutinatorJvmApi { 13 | fun install() { 14 | lock.withLock { 15 | if (!initialized) { 16 | val inst = ByteBuddyAgent.install() 17 | addDecoroutinatorTransformer(inst) 18 | initialized = true 19 | } 20 | } 21 | val baseContinuation = Class.forName(BASE_CONTINUATION_CLASS_NAME) 22 | if (!baseContinuation.isTransformed) { 23 | ByteBuddyAgent.install().retransformClasses(baseContinuation) 24 | } 25 | if (!baseContinuation.isTransformed) { 26 | error("Cannot install Decoroutinator runtime " + 27 | "because class [$BASE_CONTINUATION_CLASS_NAME] is already loaded " + 28 | "and class retransformations is not allowed.") 29 | } 30 | } 31 | 32 | private val lock = ReentrantLock() 33 | private var initialized = false 34 | } 35 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/base-continuation-accessor/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.ChangeClassNameProcessor 2 | import dev.reformator.bytecodeprocessor.plugins.LoadConstantProcessor 3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 4 | 5 | plugins { 6 | kotlin("jvm") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | bytecodeProcessor { 11 | dependentProjects = listOf( 12 | project(":intrinsics") 13 | ) 14 | processors = listOf( 15 | LoadConstantProcessor, 16 | ChangeClassNameProcessor 17 | ) 18 | } 19 | 20 | repositories { 21 | mavenCentral() 22 | } 23 | 24 | dependencies { 25 | //noinspection UseTomlInstead 26 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 27 | compileOnly(project(":provider")) 28 | compileOnly(project(":intrinsics")) 29 | } 30 | 31 | java { 32 | sourceCompatibility = JavaVersion.VERSION_1_8 33 | targetCompatibility = JavaVersion.VERSION_1_8 34 | } 35 | 36 | kotlin { 37 | compilerOptions { 38 | jvmTarget = JvmTarget.JVM_1_8 39 | freeCompilerArgs.add("-Xallow-kotlin-package") 40 | } 41 | } 42 | 43 | val kotlinSources = sourceSets.main.get().kotlin 44 | val resourcesSources = sourceSets.main.get().resources 45 | kotlinSources.srcDirs("../../../gradle-plugin/base-continuation-accessor/src/main/kotlin") 46 | resourcesSources.srcDirs("../../../gradle-plugin/base-continuation-accessor/src/main/resources") 47 | -------------------------------------------------------------------------------- /_plugins/gradle-plugin-test/embedded-debug-probes-xcoroutines/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.DeleteClassProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | bytecodeProcessor { 10 | processors = setOf( 11 | DeleteClassProcessor 12 | ) 13 | } 14 | 15 | repositories { 16 | mavenCentral() 17 | } 18 | 19 | dependencies { 20 | //noinspection UseTomlInstead 21 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 22 | compileOnly(project(":runtime-settings")) 23 | compileOnly(project(":embedded-debug-probes-stdlib")) 24 | } 25 | 26 | java { 27 | sourceCompatibility = JavaVersion.VERSION_1_8 28 | targetCompatibility = JavaVersion.VERSION_1_8 29 | } 30 | 31 | kotlin { 32 | compilerOptions { 33 | jvmTarget = JvmTarget.JVM_1_8 34 | } 35 | } 36 | 37 | sourceSets { 38 | main { 39 | kotlin.destinationDirectory = java.destinationDirectory 40 | } 41 | test { 42 | kotlin.destinationDirectory = java.destinationDirectory 43 | } 44 | } 45 | 46 | val kotlinSources = sourceSets.main.get().kotlin 47 | val resourcesSources = sourceSets.main.get().resources 48 | kotlinSources.srcDirs("../../../gradle-plugin/embedded-debug-probes-xcoroutines/src/main/kotlin") 49 | resourcesSources.srcDirs("../../../gradle-plugin/embedded-debug-probes-xcoroutines/src/main/resources") 50 | -------------------------------------------------------------------------------- /generator-jvm/src/test/kotlin/showResumeWithAppendix.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.provider.internal.awakeBaseContinuation 2 | import dev.reformator.stacktracedecoroutinator.provider.internal.baseContinuationAccessor 3 | import dev.reformator.stacktracedecoroutinator.provider.internal.getElementFactoryStacktraceElement 4 | import dev.reformator.stacktracedecoroutinator.provider.internal.prepareBaseContinuationAccessor 5 | import dev.reformator.stacktracedecoroutinator.provider.isDecoroutinatorEnabled 6 | import dev.reformator.stacktracedecoroutinator.provider.isUsingElementFactoryForBaseContinuationEnabled 7 | import org.junit.jupiter.api.Assertions.fail 8 | import java.lang.invoke.MethodHandles 9 | 10 | class BaseContinuation 11 | 12 | @Suppress("unused") 13 | fun BaseContinuation.resumeWith(result: Any?) { 14 | if (isDecoroutinatorEnabled) { 15 | awakeBaseContinuation( 16 | accessor = baseContinuationAccessor ?: prepareBaseContinuationAccessor(MethodHandles.lookup()), 17 | baseContinuation = this, 18 | result =result 19 | ) 20 | return 21 | } 22 | default() 23 | } 24 | 25 | @Suppress("unused") 26 | fun BaseContinuation.getStackTraceElement(): StackTraceElement? { 27 | if (isUsingElementFactoryForBaseContinuationEnabled) { 28 | return getElementFactoryStacktraceElement(this) 29 | } 30 | default() 31 | } 32 | 33 | @Suppress("UnusedReceiverParameter") 34 | fun BaseContinuation.default(): Nothing = fail() 35 | -------------------------------------------------------------------------------- /common/src/main/java/module-info.java: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.common.internal.*; 2 | import dev.reformator.stacktracedecoroutinator.provider.internal.DecoroutinatorProvider; 3 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider; 4 | 5 | module dev.reformator.stacktracedecoroutinator.common { 6 | requires static dev.reformator.bytecodeprocessor.intrinsics; 7 | requires static intrinsics; 8 | 9 | requires kotlin.stdlib; 10 | requires dev.reformator.stacktracedecoroutinator.provider; 11 | requires dev.reformator.stacktracedecoroutinator.runtimesettings; 12 | 13 | exports dev.reformator.stacktracedecoroutinator.common; 14 | exports dev.reformator.stacktracedecoroutinator.common.internal to 15 | dev.reformator.stacktracedecoroutinator.generatorjvm, 16 | dev.reformator.stacktracedecoroutinator.jvmagentcommon, 17 | dev.reformator.stacktracedecoroutinator.jvm, 18 | dev.reformator.stacktracedecoroutinator.generator.tests, 19 | dev.reformator.stacktracedecoroutinator.jvm.tests, 20 | dev.reformator.stacktracedecoroutinator.mhinvoker, 21 | dev.reformator.stacktracedecoroutinator.mhinvokerjvm; 22 | 23 | provides DecoroutinatorProvider with Provider; 24 | 25 | uses SpecMethodsFactory; 26 | uses AnnotationMetadataResolver; 27 | uses MethodHandleInvoker; 28 | uses VarHandleInvoker; 29 | uses BaseContinuationAccessorProvider; 30 | } 31 | -------------------------------------------------------------------------------- /provider/src/main/kotlin/internal/provider-api-internal.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("DecoroutinatorProviderInternalApiKt") 3 | 4 | package dev.reformator.stacktracedecoroutinator.provider.internal 5 | 6 | import dev.reformator.bytecodeprocessor.intrinsics.GetOwnerClass 7 | import dev.reformator.bytecodeprocessor.intrinsics.MethodNameConstant 8 | import dev.reformator.bytecodeprocessor.intrinsics.fail 9 | import java.lang.invoke.MethodHandles 10 | 11 | val baseContinuationAccessor: BaseContinuationAccessor? 12 | @MethodNameConstant("getBaseContinuationAccessorMethodName") get() = provider.baseContinuationAccessor 13 | 14 | @MethodNameConstant("prepareBaseContinuationAccessorMethodName") 15 | fun prepareBaseContinuationAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor = 16 | provider.prepareBaseContinuationAccessor(lookup) 17 | 18 | @MethodNameConstant("awakeBaseContinuationMethodName") 19 | fun awakeBaseContinuation(accessor: BaseContinuationAccessor, baseContinuation: Any, result: Any?) { 20 | provider.awakeBaseContinuation( 21 | accessor = accessor, 22 | baseContinuation = baseContinuation, 23 | result = result 24 | ) 25 | } 26 | 27 | @MethodNameConstant("getElementFactoryStacktraceElementMethodName") 28 | fun getElementFactoryStacktraceElement(baseContinuation: Any): StackTraceElement? = 29 | provider.getElementFactoryStacktraceElement(baseContinuation) 30 | 31 | val providerInternalApiClass: Class<*> 32 | @GetOwnerClass get() { fail() } 33 | -------------------------------------------------------------------------------- /test-utils-jvm/src/main/kotlin/jvm-test.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.testjvm 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 6 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 7 | import dev.reformator.bytecodeprocessor.intrinsics.ownerClassName 8 | import dev.reformator.bytecodeprocessor.intrinsics.ownerMethodName 9 | import kotlinx.coroutines.runBlocking 10 | import kotlinx.coroutines.yield 11 | import org.junit.jupiter.api.Test 12 | 13 | 14 | open class JvmTest { 15 | @Test 16 | fun `load method with spaces`() = runBlocking { 17 | yield() 18 | } 19 | 20 | @Test 21 | fun `method with spaces`() = runBlocking { 22 | val lineNumber = currentLineNumber + 1 23 | check(StackTraceElement( 24 | ownerClassName, 25 | ownerMethodName, 26 | currentFileName, 27 | lineNumber 28 | )) 29 | tailCallDeoptimize() 30 | } 31 | } 32 | 33 | open class JvmTailCallDeoptimizedTest { 34 | @Test 35 | fun `method with spaces`() = runBlocking { 36 | val lineNumber = currentLineNumber + 1 37 | check(StackTraceElement( 38 | ownerClassName, 39 | ownerMethodName, 40 | currentFileName, 41 | lineNumber 42 | )) 43 | } 44 | } 45 | 46 | private fun tailCallDeoptimize() { } 47 | 48 | private suspend fun check(parent: StackTraceElement) { 49 | yield() 50 | checkStacktrace(parent) 51 | } 52 | -------------------------------------------------------------------------------- /gradle-plugin/jdk8-tests-gp/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.GetCurrentFileNameProcessor 2 | 3 | plugins { 4 | kotlin("jvm") 5 | id("dev.reformator.stacktracedecoroutinator") 6 | id("dev.reformator.bytecodeprocessor") 7 | } 8 | 9 | stacktraceDecoroutinator { 10 | regularDependencyConfigurations.include = emptySet() 11 | androidDependencyConfigurations.include = emptySet() 12 | jvmDependencyConfigurations.include = emptySet() 13 | addJvmRuntimeDependency = false 14 | useTransformedClassesForCompilation = true 15 | embeddedDebugProbesConfigurations.include = setOf("runtimeClasspath", "testRuntimeClasspath") 16 | } 17 | 18 | repositories { 19 | mavenCentral() 20 | } 21 | 22 | dependencies { 23 | //noinspection UseTomlInstead 24 | testCompileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 25 | 26 | testRuntimeOnly(project(":stacktrace-decoroutinator-common")) 27 | testRuntimeOnly(project(":stacktrace-decoroutinator-mh-invoker")) 28 | 29 | testImplementation(project(":test-utils")) 30 | testImplementation(project(":test-utils-jvm")) 31 | testImplementation(kotlin("test")) 32 | testImplementation(libs.kotlinx.coroutines.jdk8.build) 33 | testImplementation(libs.kotlinx.coroutines.debug.build) 34 | testRuntimeOnly(project(":stacktrace-decoroutinator-runtime-settings")) 35 | } 36 | 37 | bytecodeProcessor { 38 | processors = listOf( 39 | GetCurrentFileNameProcessor 40 | ) 41 | } 42 | 43 | tasks.test { 44 | useJUnitPlatform() 45 | } 46 | 47 | kotlin { 48 | jvmToolchain(8) 49 | } 50 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/kotlin/attribute-gradle-plugin.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("AttributeGradlePluginKt") 3 | 4 | package dev.reformator.stacktracedecoroutinator.gradleplugin 5 | 6 | import io.github.oshai.kotlinlogging.KotlinLogging 7 | import org.gradle.api.Plugin 8 | import org.gradle.api.Project 9 | import org.gradle.api.artifacts.type.ArtifactTypeDefinition 10 | import org.gradle.kotlin.dsl.stacktraceDecoroutinatorAttribute 11 | 12 | private val log = KotlinLogging.logger { } 13 | 14 | @Suppress("unused") 15 | class DecoroutinatorAttributePlugin: Plugin { 16 | override fun apply(target: Project) { 17 | log.debug { "applying Decoroutinator attribute plugin to [${target.name}]" } 18 | with (target) { 19 | val pluginExtension = extensions.create( 20 | ::stacktraceDecoroutinatorAttribute.name, 21 | DecoroutinatorAttributePluginExtension::class.java 22 | ) 23 | afterEvaluate { _ -> 24 | createUnsetDecoroutinatorTransformedStateAttributeAction( 25 | artifactTypes = pluginExtension.artifactTypesForAttributes 26 | ).execute(target) 27 | } 28 | } 29 | } 30 | } 31 | 32 | open class DecoroutinatorAttributePluginExtension { 33 | var artifactTypesForAttributes = setOf( 34 | ArtifactTypeDefinition.JAR_TYPE, 35 | ArtifactTypeDefinition.JVM_CLASS_DIRECTORY, 36 | ArtifactTypeDefinition.ZIP_TYPE, 37 | "aar", 38 | "android-classes-directory", 39 | "android-classes-jar" 40 | ) 41 | } 42 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/commonMain/kotlin/org/example/project/App.kt: -------------------------------------------------------------------------------- 1 | package org.example.project 2 | 3 | import androidx.compose.animation.AnimatedVisibility 4 | import androidx.compose.foundation.Image 5 | import androidx.compose.foundation.layout.Column 6 | import androidx.compose.foundation.layout.fillMaxWidth 7 | import androidx.compose.material.Button 8 | import androidx.compose.material.MaterialTheme 9 | import androidx.compose.material.Text 10 | import androidx.compose.runtime.* 11 | import androidx.compose.ui.Alignment 12 | import androidx.compose.ui.Modifier 13 | import latest_kotlin_kmp_gradle_plugin_test.generated.resources.Res 14 | import latest_kotlin_kmp_gradle_plugin_test.generated.resources.compose_multiplatform 15 | import org.jetbrains.compose.resources.painterResource 16 | import org.jetbrains.compose.ui.tooling.preview.Preview 17 | 18 | 19 | @Composable 20 | @Preview 21 | fun App() { 22 | MaterialTheme { 23 | var showContent by remember { mutableStateOf(false) } 24 | Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { 25 | Button(onClick = { showContent = !showContent }) { 26 | Text("Click me!") 27 | } 28 | AnimatedVisibility(showContent) { 29 | val greeting = remember { Greeting().greet() } 30 | Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) { 31 | Image(painterResource(Res.drawable.compose_multiplatform), null) 32 | Text("Compose: $greeting") 33 | } 34 | } 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /intrinsics/src/main/kotlin/intrinsics.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.intrinsics 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.ChangeClassName 6 | import dev.reformator.bytecodeprocessor.intrinsics.fail 7 | import kotlin.coroutines.Continuation 8 | import kotlin.coroutines.jvm.internal.CoroutineStackFrame 9 | 10 | const val BASE_CONTINUATION_CLASS_NAME = "kotlin.coroutines.jvm.internal.BaseContinuationImpl" 11 | const val UNKNOWN_LINE_NUMBER = -1 12 | const val PROVIDER_MODULE_NAME = "dev.reformator.stacktracedecoroutinator.provider" 13 | const val LABEL_FIELD_NAME = "label" 14 | 15 | @ChangeClassName(toName = BASE_CONTINUATION_CLASS_NAME, deleteAfterChanging = true) 16 | abstract class BaseContinuation: Continuation, CoroutineStackFrame { 17 | @Suppress("RedundantNullableReturnType") 18 | val completion: Continuation? 19 | get() { fail() } 20 | 21 | final override fun resumeWith(result: Result) { fail() } 22 | 23 | init { fail() } 24 | 25 | override fun getStackTraceElement(): StackTraceElement? { fail() } 26 | 27 | abstract fun invokeSuspend(result: Any?): Any? 28 | 29 | open fun releaseIntercepted() { fail() } 30 | 31 | override val callerFrame: CoroutineStackFrame? 32 | get() = fail() 33 | } 34 | 35 | @ChangeClassName( 36 | toName = "kotlin.coroutines.jvm.internal.DebugMetadata", 37 | deleteAfterChanging = true 38 | ) 39 | @Target(AnnotationTarget.CLASS) 40 | annotation class DebugMetadata( 41 | val f: String = "", 42 | val l: IntArray = [], 43 | val m: String = "", 44 | val c: String = "" 45 | ) 46 | -------------------------------------------------------------------------------- /spec-method-builder/src/main/kotlin/internal/utils-spec-method-builder.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.specmethodbuilder.internal 2 | 3 | import dev.reformator.stacktracedecoroutinator.intrinsics.DebugMetadata 4 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorTransformed 5 | import org.objectweb.asm.ClassReader 6 | import org.objectweb.asm.Opcodes 7 | import org.objectweb.asm.Type 8 | import org.objectweb.asm.tree.AnnotationNode 9 | import org.objectweb.asm.tree.ClassNode 10 | import java.io.InputStream 11 | 12 | fun getClassNode(classBody: InputStream, skipCode: Boolean = false): ClassNode? { 13 | return try { 14 | val classReader = ClassReader(classBody) 15 | val classNode = ClassNode(Opcodes.ASM9) 16 | classReader.accept(classNode, if (skipCode) ClassReader.SKIP_CODE else 0) 17 | classNode 18 | } catch (_: Exception) { 19 | null 20 | } 21 | } 22 | 23 | val ClassNode.decoroutinatorTransformedAnnotation: AnnotationNode? 24 | get() = visibleAnnotations 25 | .orEmpty() 26 | .firstOrNull { it.desc == Type.getDescriptor(DecoroutinatorTransformed::class.java) } 27 | 28 | fun AnnotationNode.getField(name: String): Any? { 29 | var index = 0 30 | while (index < values.orEmpty().size) { 31 | if (values[index] == name) { 32 | return values[index + 1] 33 | } 34 | index += 2 35 | } 36 | return null 37 | } 38 | 39 | val ClassNode.kotlinDebugMetadataAnnotation: AnnotationNode? 40 | get() = visibleAnnotations 41 | .orEmpty() 42 | .firstOrNull { it.desc == Type.getDescriptor(DebugMetadata::class.java) } 43 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/kotlin/gradle-noop-transformer.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.gradleplugin 4 | 5 | import io.github.oshai.kotlinlogging.KotlinLogging 6 | import org.gradle.api.artifacts.transform.CacheableTransform 7 | import org.gradle.api.artifacts.transform.InputArtifact 8 | import org.gradle.api.artifacts.transform.TransformAction 9 | import org.gradle.api.artifacts.transform.TransformOutputs 10 | import org.gradle.api.artifacts.transform.TransformParameters 11 | import org.gradle.api.file.FileSystemLocation 12 | import org.gradle.api.provider.Provider 13 | import org.gradle.api.tasks.PathSensitive 14 | import org.gradle.api.tasks.PathSensitivity 15 | 16 | private val log = KotlinLogging.logger { } 17 | 18 | @CacheableTransform 19 | abstract class DecoroutinatorNoopTransformAction: TransformAction { 20 | @get:InputArtifact 21 | @get:PathSensitive(PathSensitivity.RELATIVE) 22 | abstract val inputArtifact: Provider 23 | 24 | override fun transform(outputs: TransformOutputs) { 25 | val root = inputArtifact.get().asFile 26 | log.debug { "noop transformation for [${root.absolutePath}]" } 27 | if (root.isFile) { 28 | log.debug { "artifact [${root.absolutePath}] is a file" } 29 | outputs.file(inputArtifact) 30 | } else if (root.isDirectory) { 31 | log.debug { "artifact [${root.absolutePath}] is a directory" } 32 | outputs.dir(inputArtifact) 33 | } else { 34 | log.debug { "artifact [${root.absolutePath}] does not exist" } 35 | } 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /test-utils/custom-loader/src/main/kotlin/stub-test-utils-custom-loader.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.test 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 6 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 7 | import dev.reformator.bytecodeprocessor.intrinsics.ownerMethodName 8 | import kotlinx.coroutines.runBlocking 9 | import kotlinx.coroutines.yield 10 | 11 | @Suppress("unused") 12 | class ClassWithSuspendFunctionsStub { 13 | fun performCheck(allowTailCallOptimization: Boolean) { 14 | runBlocking { 15 | if (allowTailCallOptimization) { 16 | tailCallOptimizedCheck() 17 | } else { 18 | basicCheck() 19 | } 20 | } 21 | } 22 | 23 | suspend fun tailCallOptimizedCheck() { 24 | val lineNumber = currentLineNumber + 1 25 | check(StackTraceElement( 26 | ClassWithSuspendFunctionsStub::class.java.name, 27 | ownerMethodName, 28 | currentFileName, 29 | lineNumber 30 | )) 31 | tailCallDeoptimizer() 32 | } 33 | 34 | suspend fun basicCheck() { 35 | val lineNumber = currentLineNumber + 1 36 | check(StackTraceElement( 37 | ClassWithSuspendFunctionsStub::class.java.name, 38 | ownerMethodName, 39 | currentFileName, 40 | lineNumber 41 | )) 42 | } 43 | 44 | suspend fun check(parentFrame: StackTraceElement) { 45 | yield() 46 | checkStacktrace(parentFrame) 47 | } 48 | 49 | private fun tailCallDeoptimizer() { } 50 | } 51 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/api/src/main/kotlin/asm-plugin-api.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.api 4 | 5 | import org.objectweb.asm.tree.ClassNode 6 | import org.objectweb.asm.tree.ModuleNode 7 | 8 | interface ProcessingClass { 9 | val node: ClassNode 10 | fun markModified() 11 | fun delete() 12 | } 13 | 14 | interface ProcessingModule { 15 | val node: ModuleNode 16 | fun markModified() 17 | } 18 | 19 | interface ProcessingDirectory { 20 | val classes: Sequence 21 | val module: ProcessingModule? 22 | } 23 | 24 | interface BytecodeProcessorContext { 25 | interface Key { 26 | val id: String 27 | val default: T 28 | fun merge(value1: T, value2: T): T 29 | } 30 | 31 | operator fun get(key: Key): T 32 | 33 | fun merge(key: Key, value: T): T 34 | } 35 | 36 | @JvmInline 37 | value class BytecodeProcessorContextImpl private constructor( 38 | val values: MutableMap 39 | ): BytecodeProcessorContext { 40 | constructor(): this(hashMapOf()) 41 | 42 | @Suppress("UNCHECKED_CAST") 43 | override fun get(key: BytecodeProcessorContext.Key): T = 44 | values[key.id]?.let { it as T } ?: key.default 45 | 46 | @Suppress("UNCHECKED_CAST") 47 | override fun merge(key: BytecodeProcessorContext.Key, value: T): T = 48 | values.merge(key.id, value) { value1, value2 -> 49 | key.merge(value1 as T, value2 as T) 50 | } as T 51 | } 52 | 53 | fun interface Processor { 54 | fun process(directory: ProcessingDirectory, context: BytecodeProcessorContext) 55 | } 56 | -------------------------------------------------------------------------------- /jvm-agent/tests-ja/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | jacoco 7 | } 8 | 9 | repositories { 10 | mavenCentral() 11 | } 12 | 13 | dependencies { 14 | testImplementation(project(":test-utils")) { 15 | exclude(module = "stacktrace-decoroutinator-common") 16 | exclude(module = "stacktrace-decoroutinator-provider") 17 | } 18 | testImplementation(project(":test-utils-jvm")) 19 | testImplementation(kotlin("test")) 20 | testImplementation(libs.kotlinx.coroutines.jdk8.build) 21 | testImplementation(project(":stacktrace-decoroutinator-jvm-agent", configuration = "shadow")) 22 | } 23 | 24 | tasks.test { 25 | useJUnitPlatform() 26 | val shadowJarTask = project(":stacktrace-decoroutinator-jvm-agent").tasks.named("shadowJar") 27 | dependsOn(shadowJarTask) 28 | val agentJar = shadowJarTask.get().outputs.files.singleFile 29 | jvmArgs( 30 | "-javaagent:${agentJar.absolutePath}", 31 | "-Ddev.reformator.stacktracedecoroutinator.jvmAgentDebugMetadataInfoResolveStrategy=SYSTEM_RESOURCE" 32 | ) 33 | extensions.configure(JacocoTaskExtension::class) { 34 | includes = listOf("JacocoInstrumentedMethodTest*") 35 | } 36 | } 37 | 38 | java { 39 | sourceCompatibility = JavaVersion.VERSION_1_9 40 | targetCompatibility = JavaVersion.VERSION_1_9 41 | } 42 | 43 | kotlin { 44 | compilerOptions { 45 | jvmTarget = JvmTarget.JVM_1_8 46 | } 47 | } 48 | 49 | sourceSets { 50 | main { 51 | kotlin.destinationDirectory = java.destinationDirectory 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-stub/src/main/kotlin/base-continuation-accessor-stub.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub 4 | 5 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 6 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessor 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider 8 | import java.lang.invoke.MethodHandles 9 | import java.lang.invoke.MethodType 10 | 11 | class TestBaseContinuationAccessorProviderAccessor: BaseContinuationAccessorProvider { 12 | override fun createAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor { 13 | val invokeSuspendHandle = lookup.findVirtual( 14 | BaseContinuation::class.java, 15 | BaseContinuation::invokeSuspend.name, 16 | MethodType.methodType(Object::class.java, Object::class.java) 17 | ) 18 | val releaseInterceptedHandle = lookup.findVirtual( 19 | BaseContinuation::class.java, 20 | BaseContinuation::releaseIntercepted.name, 21 | MethodType.methodType(Void::class.javaPrimitiveType) 22 | ) 23 | return object : BaseContinuationAccessor { 24 | override fun invokeSuspend(baseContinuation: Any, result: Any?): Any? = 25 | invokeSuspendHandle.invokeExact(baseContinuation as BaseContinuation, result) 26 | 27 | override fun releaseIntercepted(baseContinuation: Any) { 28 | releaseInterceptedHandle.invokeExact(baseContinuation as BaseContinuation) 29 | } 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /test-utils/base-continuation-accessor-reflect-stub/src/main/kotlin/base-continuation-accessor-reflect-stub.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.test.basecontinuationaccessorstub 4 | 5 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 6 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessor 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider 8 | import java.lang.invoke.MethodHandles 9 | import java.lang.reflect.InvocationTargetException 10 | 11 | class TestReflectBaseContinuationAccessorProviderAccessor: BaseContinuationAccessorProvider { 12 | override fun createAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor { 13 | val invokeSuspendMethod = BaseContinuation::class.java.getDeclaredMethod( 14 | BaseContinuation::invokeSuspend.name, 15 | Object::class.java 16 | ) 17 | invokeSuspendMethod.isAccessible = true 18 | val releaseInterceptedMethod = 19 | BaseContinuation::class.java.getDeclaredMethod(BaseContinuation::releaseIntercepted.name) 20 | releaseInterceptedMethod.isAccessible = true 21 | return object: BaseContinuationAccessor { 22 | override fun invokeSuspend(baseContinuation: Any, result: Any?): Any? = 23 | try { 24 | invokeSuspendMethod.invoke(baseContinuation, result) 25 | } catch (e: InvocationTargetException) { 26 | e.cause?.let { throw it } 27 | throw e 28 | } 29 | 30 | override fun releaseIntercepted(baseContinuation: Any) { 31 | releaseInterceptedMethod.invoke(baseContinuation) 32 | } 33 | } 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /mh-invoker-android/src/main/kotlin/mh-invoker-android.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("MhInvokerAndroidKt") 3 | 4 | package dev.reformator.stacktracedecoroutinator.mhinvokerandroid 5 | 6 | import android.util.Base64 7 | import dev.reformator.bytecodeprocessor.intrinsics.LoadConstant 8 | import dev.reformator.bytecodeprocessor.intrinsics.fail 9 | import dalvik.system.InMemoryDexClassLoader 10 | import dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker 11 | import dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker 12 | import java.nio.ByteBuffer 13 | 14 | internal class AndroidMethodHandleInvoker: MethodHandleInvoker by loadRegularMethodHandleInvoker() 15 | 16 | internal class AndroidVarHandleInvoker: VarHandleInvoker by loadRegularVarHandleInvoker() 17 | 18 | private val regularMethodHandleDexBase64: String 19 | @LoadConstant("regularMethodHandleDexBase64") get() { fail() } 20 | 21 | private val String.decodeBase64: ByteArray 22 | get() = Base64.decode(this, Base64.DEFAULT) 23 | 24 | @Suppress("NewApi") 25 | private val regularMethodHandleLoader = InMemoryDexClassLoader( 26 | ByteBuffer.wrap(regularMethodHandleDexBase64.decodeBase64), 27 | MethodHandleInvoker::class.java.classLoader 28 | ) 29 | 30 | private fun loadRegularMethodHandleInvoker(): MethodHandleInvoker = 31 | regularMethodHandleLoader.loadClass("dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularMethodHandleInvoker") 32 | .getDeclaredConstructor() 33 | .newInstance() as MethodHandleInvoker 34 | 35 | private fun loadRegularVarHandleInvoker(): VarHandleInvoker = 36 | regularMethodHandleLoader.loadClass("dev.reformator.stacktracedecoroutinator.mhinvoker.internal.RegularVarHandleInvoker") 37 | .getDeclaredConstructor() 38 | .newInstance() as VarHandleInvoker 39 | -------------------------------------------------------------------------------- /runtime-settings/src/main/kotlin/runtime-settings.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.runtimesettings 4 | 5 | import dev.reformator.stacktracedecoroutinator.runtimesettings.internal.defaultValue 6 | 7 | interface DecoroutinatorRuntimeSettingsProvider { 8 | //Common settings 9 | 10 | val enabled: Boolean 11 | get() = defaultValue() 12 | 13 | val recoveryExplicitStacktrace: Boolean 14 | get() = defaultValue() 15 | 16 | val recoveryExplicitStacktraceTimeoutMs: UInt 17 | get() = defaultValue() 18 | 19 | val tailCallDeoptimize: Boolean 20 | get() = defaultValue() 21 | 22 | val methodsNumberThreshold: Int 23 | get() = defaultValue() 24 | 25 | val fillUnknownElementsWithClassName: Boolean 26 | get() = defaultValue() 27 | 28 | val isUsingElementFactoryForBaseContinuationEnabled: Boolean 29 | get() = defaultValue() 30 | 31 | // JVM Agent settings 32 | 33 | val metadataInfoResolveStrategy: DecoroutinatorMetadataInfoResolveStrategy 34 | get() = defaultValue() 35 | 36 | val isBaseContinuationRedefinitionAllowed: Boolean 37 | get() = defaultValue() 38 | 39 | val isRedefinitionAllowed: Boolean 40 | get() = defaultValue() 41 | 42 | // Embedded Debug Probes settings 43 | 44 | val enableCreationStackTraces: Boolean 45 | get() = defaultValue() 46 | 47 | val installDebugProbes: Boolean 48 | get() = defaultValue() 49 | 50 | // Generator Android settings 51 | 52 | val androidGeneratorAttemptsCount: Int 53 | get() = defaultValue() 54 | 55 | // end 56 | 57 | val priority: Int 58 | get() = 0 59 | } 60 | 61 | enum class DecoroutinatorMetadataInfoResolveStrategy { 62 | SYSTEM_RESOURCE, CLASS, SYSTEM_RESOURCE_AND_CLASS 63 | } 64 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-kmp-gradle-plugin-test/src/androidMain/res/drawable-v24/ic_launcher_foreground.xml: -------------------------------------------------------------------------------- 1 | 7 | 8 | 9 | 15 | 18 | 21 | 22 | 23 | 24 | 30 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/groovy/GroovyDslInitializerImpl.groovy: -------------------------------------------------------------------------------- 1 | //file:noinspection GrPackage 2 | 3 | package dev.reformator.stacktracedecoroutinator.gradleplugin.groovy 4 | 5 | import dev.reformator.stacktracedecoroutinator.gradleplugin.GroovyDslInitializer 6 | import org.gradle.api.Project 7 | import org.gradle.kotlin.dsl.ApiGradlePluginDecoroutinatorKt 8 | import org.jetbrains.annotations.NotNull 9 | 10 | 11 | class GroovyDslInitializerImpl implements GroovyDslInitializer { 12 | @Override 13 | void initGroovyDsl(@NotNull Project target) { 14 | target.metaClass.decoroutinatorAndroidProGuardRules = { -> 15 | ApiGradlePluginDecoroutinatorKt.decoroutinatorAndroidProGuardRules(target) 16 | } 17 | 18 | target.metaClass.decoroutinatorCommon = { -> 19 | ApiGradlePluginDecoroutinatorKt.decoroutinatorCommon() 20 | } 21 | 22 | target.metaClass.decoroutinatorJvmRuntime = { -> 23 | ApiGradlePluginDecoroutinatorKt.decoroutinatorJvmRuntime() 24 | } 25 | 26 | target.metaClass.decoroutinatorAndroidRuntime = { -> 27 | ApiGradlePluginDecoroutinatorKt.decoroutinatorAndroidRuntime() 28 | } 29 | 30 | target.metaClass.decoroutinatorRegularMethodHandleInvoker = { -> 31 | ApiGradlePluginDecoroutinatorKt.decoroutinatorRegularMethodHandleInvoker() 32 | } 33 | 34 | target.metaClass.decoroutinatorAndroidMethodHandleInvoker = { -> 35 | ApiGradlePluginDecoroutinatorKt.decoroutinatorAndroidMethodHandleInvoker() 36 | } 37 | 38 | target.metaClass.decoroutinatorJvmMethodHandleInvoker = { -> 39 | ApiGradlePluginDecoroutinatorKt.decoroutinatorJvmMethodHandleInvoker() 40 | } 41 | 42 | target.metaClass.decoroutinatorRuntimeSettings = { -> 43 | ApiGradlePluginDecoroutinatorKt.decoroutinatorRuntimeSettings() 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | buildscript { 2 | repositories { 3 | google() 4 | mavenCentral() 5 | gradlePluginPortal() 6 | } 7 | 8 | dependencies { 9 | classpath(libs.shadow.gradle.plugin) 10 | } 11 | } 12 | 13 | plugins { 14 | alias(libs.plugins.kotlin.jvm.latest) 15 | id("dev.reformator.stacktracedecoroutinator") 16 | } 17 | 18 | stacktraceDecoroutinator { 19 | regularDependencyConfigurations.include = emptySet() 20 | androidDependencyConfigurations.include = emptySet() 21 | jvmDependencyConfigurations.include = emptySet() 22 | addJvmRuntimeDependency = false 23 | useTransformedClassesForCompilation = true 24 | embeddedDebugProbesConfigurations.include = setOf("runtimeClasspath", "testRuntimeClasspath") 25 | } 26 | 27 | repositories { 28 | mavenCentral() 29 | } 30 | 31 | dependencies { 32 | runtimeOnly(files("../../provider/build/libs/").asFileTree) 33 | implementation(files("../../common/build/libs/").asFileTree) 34 | implementation(files("../../mh-invoker/build/libs/").asFileTree) 35 | implementation(files("../../generator-jvm/build/libs/").asFileTree) 36 | implementation(files("../../runtime-settings/build/libs/").asFileTree) 37 | implementation(files("../../class-transformer/build/libs/").asFileTree) 38 | implementation(files("../../spec-method-builder/build/libs/").asFileTree) 39 | runtimeOnly(libs.asm.utils) 40 | 41 | //noinspection UseTomlInstead 42 | testCompileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 43 | 44 | implementation(libs.kotlinx.coroutines.jdk8.latest) 45 | implementation(libs.kotlinx.coroutines.debug.latest) 46 | testImplementation(kotlin("test")) 47 | testImplementation(project(":test-utils")) 48 | testImplementation(files("../../test-utils/retrace-repack/build/libs/").asFileTree) 49 | } 50 | 51 | tasks.test { 52 | useJUnitPlatform() 53 | } 54 | -------------------------------------------------------------------------------- /_latest-gradle-test/gradle-plugin-android-test/build.gradle.kts: -------------------------------------------------------------------------------- 1 | plugins { 2 | alias(libs.plugins.android.application) 3 | kotlin("android") 4 | id("dev.reformator.stacktracedecoroutinator") 5 | } 6 | 7 | repositories { 8 | mavenCentral() 9 | google() 10 | } 11 | 12 | stacktraceDecoroutinator { 13 | regularDependencyConfigurations.include = emptySet() 14 | androidDependencyConfigurations.include = emptySet() 15 | jvmDependencyConfigurations.include = emptySet() 16 | addJvmRuntimeDependency = false 17 | addAndroidRuntimeDependency = false 18 | useTransformedClassesForCompilation = true 19 | embedDebugProbesForAndroid = true 20 | runtimeSettingsDependencyConfigurations.include = emptySet() 21 | } 22 | 23 | dependencies { 24 | implementation(libs.junit4) 25 | 26 | runtimeOnly(libs.androidx.test.runner) 27 | } 28 | 29 | android { 30 | namespace = "dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests" 31 | compileSdk = 36 32 | defaultConfig { 33 | applicationId = "dev.reformator.stacktracedecoroutinator.gradlepluginandroidtests" 34 | versionCode = 1 35 | versionName = "1.0" 36 | minSdk = 26 37 | testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" 38 | } 39 | packaging { 40 | resources.pickFirsts.add("META-INF/*") 41 | resources.excludes.add("win32-x86-64/attach_hotspot_windows.dll") 42 | resources.excludes.add("win32-x86/attach_hotspot_windows.dll") 43 | resources.excludes.add("META-INF/licenses/*") 44 | } 45 | kotlin { 46 | jvmToolchain(8) 47 | } 48 | buildTypes { 49 | debug { 50 | isMinifyEnabled = true 51 | isDebuggable = false 52 | testProguardFiles(decoroutinatorAndroidProGuardRules(), "proguard-rules.pro") 53 | proguardFiles(decoroutinatorAndroidProGuardRules(), "proguard-rules.pro") 54 | } 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /gradle-plugin/tests-gp/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.GetCurrentFileNameProcessor 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | id("dev.reformator.stacktracedecoroutinator") 7 | id("dev.reformator.bytecodeprocessor") 8 | } 9 | 10 | stacktraceDecoroutinator { 11 | regularDependencyConfigurations.include = emptySet() 12 | androidDependencyConfigurations.include = emptySet() 13 | jvmDependencyConfigurations.include = emptySet() 14 | addJvmRuntimeDependency = false 15 | useTransformedClassesForCompilation = true 16 | embeddedDebugProbesConfigurations.include = setOf("runtimeClasspath", "testRuntimeClasspath") 17 | } 18 | 19 | repositories { 20 | mavenCentral() 21 | } 22 | 23 | dependencies { 24 | implementation(project(":gradle-plugin:empty-module-tests")) 25 | 26 | //noinspection UseTomlInstead 27 | testCompileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 28 | 29 | testRuntimeOnly(project(":stacktrace-decoroutinator-common")) 30 | testRuntimeOnly(project(":stacktrace-decoroutinator-mh-invoker")) 31 | 32 | testImplementation(project(":test-utils")) 33 | testImplementation(project(":test-utils-jvm")) 34 | testImplementation(kotlin("test")) 35 | testImplementation(libs.kotlinx.coroutines.jdk8.build) 36 | testImplementation(project(":gradle-plugin:duplicate-entity-jar-builder", configuration = "duplicateJar")) 37 | } 38 | 39 | bytecodeProcessor { 40 | processors = listOf( 41 | GetCurrentFileNameProcessor, 42 | ) 43 | } 44 | 45 | tasks.test { 46 | useJUnitPlatform() 47 | } 48 | 49 | java { 50 | sourceCompatibility = JavaVersion.VERSION_1_9 51 | targetCompatibility = JavaVersion.VERSION_1_9 52 | } 53 | 54 | kotlin { 55 | compilerOptions { 56 | jvmTarget = JvmTarget.JVM_1_8 57 | } 58 | } 59 | 60 | sourceSets { 61 | test { 62 | kotlin.destinationDirectory = java.destinationDirectory 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /mh-invoker/src/main/kotlin/internal/mh-invoker.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.mhinvoker.internal 4 | 5 | import dcunknown.getUnknownSpecMethodHandle 6 | import dcunknown.unknownSpecClass 7 | import dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker 8 | import dev.reformator.stacktracedecoroutinator.common.internal.VarHandleInvoker 9 | import dev.reformator.stacktracedecoroutinator.common.internal.assert 10 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorSpec 11 | import dev.reformator.stacktracedecoroutinator.provider.internal.AndroidKeep 12 | import java.lang.invoke.MethodHandle 13 | import java.lang.invoke.MethodHandles 14 | import java.lang.invoke.VarHandle 15 | 16 | internal class RegularMethodHandleInvoker: MethodHandleInvoker { 17 | override val unknownSpecMethodHandle = getUnknownSpecMethodHandle() 18 | 19 | override fun callSpecMethod(handle: MethodHandle, spec: DecoroutinatorSpec, result: Any?): Any? = 20 | handle.invokeExact(spec, result) 21 | 22 | override val unknownSpecMethodClass: Class<*> 23 | get() = unknownSpecClass 24 | 25 | override val supportsVarHandle: Boolean = 26 | try { 27 | _supportsVarHandleStub().verify() 28 | true 29 | } catch (_: Throwable) { 30 | false 31 | } 32 | } 33 | 34 | internal class RegularVarHandleInvoker: VarHandleInvoker { 35 | override fun getIntVar(handle: VarHandle, owner: Any): Int = 36 | handle[owner] as Int 37 | } 38 | 39 | @Suppress("ClassName") 40 | @AndroidKeep 41 | private class _supportsVarHandleStub { 42 | private var field: Int = 0 43 | fun verify() { 44 | val varHandle = MethodHandles.lookup().findVarHandle( 45 | _supportsVarHandleStub::class.java, 46 | ::field.name, 47 | Int::class.javaPrimitiveType 48 | ) 49 | val fieldValue = varHandle[this] as Int 50 | assert { fieldValue == 0 } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /_tests/latest-kotlin-gradle-plugin-test/test-utils/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | import dev.reformator.bytecodeprocessor.plugins.* 3 | 4 | 5 | 6 | plugins { 7 | alias(libs.plugins.kotlin.jvm.latest) 8 | id("dev.reformator.bytecodeprocessor") 9 | } 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | implementation(files("../../../test-utils/retrace-repack/build/libs/").asFileTree) 17 | implementation(files("../../../common/build/libs/").asFileTree) 18 | implementation(kotlin("test")) 19 | implementation(libs.junit5.api) 20 | implementation(libs.junit4) 21 | implementation(libs.kotlinx.coroutines.jdk8.latest) 22 | implementation(libs.kotlin.logging.jvm) 23 | 24 | //noinspection UseTomlInstead 25 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 26 | 27 | runtimeOnly(libs.ktor.io.jvm) 28 | runtimeOnly(libs.logback.classic) 29 | } 30 | 31 | bytecodeProcessor { 32 | processors = setOf( 33 | GetCurrentFileNameProcessor, 34 | GetOwnerClassProcessor, 35 | LoadConstantProcessor 36 | ) 37 | } 38 | 39 | val fillConstantProcessorTask = tasks.register("fillConstantProcessor") { 40 | val customLoaderProject = project(":custom-loader") 41 | val customLoaderJarTask = customLoaderProject.tasks.named("shadowJar") 42 | dependsOn(customLoaderJarTask) 43 | doLast { 44 | val customLoaderJarUri = customLoaderJarTask.get().archiveFile.get().asFile.toURI().toString() 45 | bytecodeProcessor { 46 | initContext { 47 | LoadConstantProcessor.addValues( 48 | context = this, 49 | valuesByKeys = mapOf("customLoaderJarUri" to customLoaderJarUri) 50 | ) 51 | } 52 | } 53 | } 54 | } 55 | 56 | bytecodeProcessorInitTask.dependsOn(fillConstantProcessorTask) 57 | 58 | val kotlinSources = sourceSets.main.get().kotlin 59 | kotlinSources.srcDirs("../../../test-utils/src/main/kotlin") 60 | kotlinSources.srcDirs("../../../test-utils-jvm/src/main/kotlin") 61 | -------------------------------------------------------------------------------- /common/src/main/kotlin/intrinsics/intrinsics-common.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.common.intrinsics 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.ChangeClassName 6 | import dev.reformator.bytecodeprocessor.intrinsics.ChangeInvocationsOwner 7 | import dev.reformator.bytecodeprocessor.intrinsics.SkipInvocations 8 | import dev.reformator.bytecodeprocessor.intrinsics.fail 9 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 10 | import kotlin.coroutines.Continuation 11 | import kotlin.coroutines.CoroutineContext 12 | import kotlin.coroutines.jvm.internal.CoroutineStackFrame 13 | 14 | @ChangeClassName( 15 | toName = "kotlin.Result\$Failure", 16 | deleteAfterChanging = true 17 | ) 18 | internal class FailureResult { 19 | @JvmField val exception: Throwable = fail() 20 | } 21 | 22 | @ChangeClassName( 23 | toName = "kotlin._Assertions", 24 | deleteAfterChanging = true 25 | ) 26 | @PublishedApi 27 | @Suppress("ClassName") 28 | internal object _Assertions { 29 | @JvmField 30 | val ENABLED: Boolean = fail() 31 | } 32 | 33 | @Suppress("UnusedReceiverParameter") 34 | internal val Any?.toResult: Result<*> 35 | @SkipInvocations get() { fail() } 36 | 37 | @Suppress("UNUSED_PARAMETER") 38 | @ChangeInvocationsOwner( 39 | toName = "kotlin.coroutines.jvm.internal.DebugProbesKt", 40 | deleteAfterChanging = true 41 | ) 42 | internal fun probeCoroutineResumed(frame: Continuation<*>) { fail() } 43 | 44 | @Suppress("UNUSED_PARAMETER") 45 | @ChangeInvocationsOwner( 46 | toName = "kotlin.ResultKt", 47 | deleteAfterChanging = true 48 | ) 49 | internal fun createFailure(exception: Throwable): Any { fail() } 50 | 51 | @ChangeClassName(toName = "kotlin.coroutines.jvm.internal.ContinuationImpl", deleteAfterChanging = true) 52 | internal abstract class ContinuationImpl( 53 | @Suppress("UNUSED_PARAMETER") completion: Continuation? 54 | ): BaseContinuation(), CoroutineStackFrame { 55 | override val context: CoroutineContext 56 | get() { fail() } 57 | 58 | override val callerFrame: CoroutineStackFrame? 59 | get() { fail() } 60 | 61 | override fun getStackTraceElement(): StackTraceElement? { fail() } 62 | } 63 | -------------------------------------------------------------------------------- /gradle-plugin/jdk8-tests-gp/src/test/kotlin/tests-jdk8-gradle-plugin.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 2 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 3 | import dev.reformator.stacktracedecoroutinator.test.checkStacktrace 4 | import kotlinx.coroutines.ExperimentalCoroutinesApi 5 | import kotlinx.coroutines.debug.DebugProbes 6 | import kotlinx.coroutines.runBlocking 7 | import kotlinx.coroutines.suspendCancellableCoroutine 8 | import kotlinx.coroutines.yield 9 | import org.junit.jupiter.api.Assertions.* 10 | import kotlin.coroutines.resume 11 | import kotlin.test.Test 12 | 13 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 14 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 15 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 16 | class JvmTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTailCallDeoptimizedTest() 17 | 18 | class TestLocalFile { 19 | @Test 20 | fun localTest(): Unit = runBlocking { 21 | fun1() 22 | } 23 | 24 | suspend fun fun1() { 25 | fun2(currentLineNumber) 26 | } 27 | 28 | suspend fun fun2(fun1LineNumber: Int) { 29 | val fun1Frame = StackTraceElement( 30 | TestLocalFile::class.qualifiedName, 31 | ::fun1.name, 32 | currentFileName, 33 | fun1LineNumber 34 | ) 35 | yield() 36 | fun3(fun1Frame, currentLineNumber) 37 | } 38 | 39 | suspend fun fun3(fun1Frame: StackTraceElement, fun2LineNumber: Int) { 40 | val fun2Frame = StackTraceElement( 41 | TestLocalFile::class.qualifiedName, 42 | ::fun2.name, 43 | currentFileName, 44 | fun2LineNumber 45 | ) 46 | yield() 47 | checkStacktrace(fun2Frame, fun1Frame) 48 | } 49 | } 50 | 51 | @OptIn(ExperimentalCoroutinesApi::class) 52 | class DebugProbesTest { 53 | @Test 54 | fun performDebugProbes() { 55 | runBlocking { 56 | suspendCancellableCoroutine { continuation -> 57 | assertTrue(DebugProbes.dumpCoroutinesInfo().isNotEmpty()) 58 | continuation.resume(Unit) 59 | } 60 | } 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /test-utils/src/main/kotlin/test-utils.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.test 4 | 5 | import dev.reformator.retracerepack.obfuscate.MappingReader 6 | import dev.reformator.retracerepack.retrace.FrameInfo 7 | import dev.reformator.retracerepack.retrace.FrameRemapper 8 | import org.junit.jupiter.api.Assertions.assertTrue 9 | import java.io.File 10 | 11 | private var mappers = emptyList() 12 | 13 | fun setRetraceMappingFiles(vararg files: String) { 14 | mappers = files.map { file -> 15 | val reader = MappingReader(File(file)) 16 | FrameRemapper().apply { reader.pump(this) } 17 | } 18 | } 19 | 20 | fun Array.checkStacktrace(vararg elements: StackTraceElement, fromIndex: Int = 0) { 21 | if (elements.isEmpty()) { 22 | return 23 | } 24 | var startIndex = fromIndex 25 | while (!(this[startIndex] eq elements[0])) startIndex++ 26 | elements.forEachIndexed { index, element -> 27 | assertTrue(element eq this[startIndex + index]) 28 | } 29 | } 30 | 31 | fun checkStacktrace(vararg elements: StackTraceElement) { 32 | Exception().stackTrace.checkStacktrace(*elements) 33 | } 34 | 35 | private infix fun StackTraceElement.eq(other: StackTraceElement): Boolean { 36 | if ( 37 | className == other.className && 38 | methodName == other.methodName && 39 | fileName == other.fileName && 40 | lineNumber == other.lineNumber 41 | ) return true 42 | 43 | fun StackTraceElement.toFrameInfo() = 44 | FrameInfo(className, null, lineNumber, null, null, methodName, null) 45 | 46 | val frame1 = toFrameInfo() 47 | val frame2 = other.toFrameInfo() 48 | mappers.forEach { mapper -> 49 | infix fun FrameInfo.deobfuscateEq(other: FrameInfo) = 50 | mapper.transform(this).orEmpty().any { deobfuscatedFrame -> 51 | deobfuscatedFrame.className == other.className && deobfuscatedFrame.methodName == other.methodName && 52 | deobfuscatedFrame.lineNumber == other.lineNumber 53 | } 54 | 55 | if (frame1 deobfuscateEq frame2 || frame2 deobfuscateEq frame1) { 56 | return true 57 | } 58 | } 59 | 60 | return false 61 | } 62 | 63 | typealias Junit4Test = org.junit.Test 64 | typealias Junit5Test = org.junit.jupiter.api.Test 65 | -------------------------------------------------------------------------------- /_plugins/bytecode-processor/plugins/src/main/kotlin/internal/utils-plugins.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.bytecodeprocessor.plugins.internal 4 | 5 | import org.objectweb.asm.ClassReader 6 | import org.objectweb.asm.Opcodes 7 | import org.objectweb.asm.Type 8 | import org.objectweb.asm.tree.* 9 | 10 | val String.internalName: String 11 | get() = replace('.', '/') 12 | 13 | internal fun List?.find(type: Class): AnnotationNode? = 14 | this?.find { it.desc == Type.getDescriptor(type) } 15 | 16 | internal fun AnnotationNode.getParameter(name: String): Any? { 17 | var index = 0 18 | while (index < values.orEmpty().size) { 19 | if (values[index] == name) return values[index + 1] 20 | index += 2 21 | } 22 | return null 23 | } 24 | 25 | internal fun AnnotationNode.setParameter(name: String, value: Any) { 26 | val parameters: MutableList = values ?: run { values = mutableListOf(); values } 27 | var index = 0 28 | while (index < parameters.size) { 29 | if (parameters[index] == name) { 30 | parameters[index + 1] = value 31 | return 32 | } 33 | index += 2 34 | } 35 | parameters.add(name) 36 | parameters.add(value) 37 | } 38 | 39 | internal val MethodNode.isStatic: Boolean 40 | get() = access and Opcodes.ACC_STATIC != 0 41 | 42 | 43 | internal fun ClassNode.getOrCreateClinit(): MethodNode = 44 | methods?.firstOrNull { 45 | it.name == "" && it.desc == "()V" && it.isStatic 46 | } ?: MethodNode(Opcodes.ASM9).apply { 47 | name = "" 48 | desc = "()V" 49 | access = Opcodes.ACC_STATIC or Opcodes.ACC_SYNTHETIC 50 | instructions.add(InsnNode(Opcodes.RETURN)) 51 | val methods: MutableList = methods ?: run { methods = mutableListOf(); methods } 52 | methods.add(this) 53 | } 54 | 55 | internal fun Class<*>.readAsm(): ClassNode = 56 | classLoader.getResourceAsStream(name.internalName + ".class")!!.use { 57 | val classReader = ClassReader(it) 58 | val classNode = ClassNode(Opcodes.ASM9) 59 | classReader.accept(classNode, 0) 60 | classNode 61 | } 62 | 63 | internal infix fun MethodInsnNode.eq(other: MethodInsnNode): Boolean = 64 | opcode == other.opcode && owner == other.owner && name == other.name && desc == other.desc 65 | -------------------------------------------------------------------------------- /test-utils/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar 2 | import dev.reformator.bytecodeprocessor.plugins.* 3 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 4 | 5 | plugins { 6 | kotlin("jvm") 7 | id("dev.reformator.bytecodeprocessor") 8 | id("dev.reformator.forcevariantjavaversion") 9 | } 10 | 11 | repositories { 12 | mavenCentral() 13 | } 14 | 15 | dependencies { 16 | //noinspection UseTomlInstead 17 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 18 | 19 | implementation(libs.junit5.api) 20 | implementation(libs.junit4) 21 | implementation(libs.kotlinx.coroutines.core.build) 22 | implementation(libs.kotlin.logging.jvm) 23 | implementation(project(":test-utils:retrace-repack", configuration = "shadow")) 24 | implementation(project(":stacktrace-decoroutinator-common")) 25 | 26 | runtimeOnly(libs.ktor.io.jvm) { 27 | exclude(group = "org.jetbrains.kotlinx", module = "kotlinx-coroutines-jdk8") 28 | } 29 | runtimeOnly(libs.logback.classic) 30 | } 31 | 32 | bytecodeProcessor { 33 | processors = listOf( 34 | GetCurrentFileNameProcessor, 35 | GetOwnerClassProcessor, 36 | LoadConstantProcessor 37 | ) 38 | } 39 | 40 | val fillConstantProcessorTask = tasks.register("fillConstantProcessor") { 41 | val customLoaderProject = project(":test-utils:custom-loader") 42 | val customLoaderJarTask = customLoaderProject.tasks.named("shadowJar") 43 | dependsOn(customLoaderJarTask) 44 | doLast { 45 | val customLoaderJarUri = customLoaderJarTask.get().archiveFile.get().asFile.toURI().toString() 46 | bytecodeProcessor { 47 | initContext { 48 | LoadConstantProcessor.addValues( 49 | context = this, 50 | valuesByKeys = mapOf("customLoaderJarUri" to customLoaderJarUri) 51 | ) 52 | } 53 | } 54 | } 55 | } 56 | 57 | bytecodeProcessorInitTask.dependsOn(fillConstantProcessorTask) 58 | 59 | java { 60 | sourceCompatibility = JavaVersion.VERSION_1_9 61 | targetCompatibility = JavaVersion.VERSION_1_9 62 | } 63 | 64 | tasks.withType { 65 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 66 | } 67 | 68 | kotlin { 69 | compilerOptions { 70 | jvmTarget = JvmTarget.JVM_1_8 71 | freeCompilerArgs.add("-Xjvm-default=all") 72 | } 73 | } 74 | 75 | sourceSets { 76 | main { 77 | kotlin.destinationDirectory = java.destinationDirectory 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /jvm/jdk8-tests-j/src/test/kotlin/tests-jdk8-jvm.kt: -------------------------------------------------------------------------------- 1 | import dev.reformator.stacktracedecoroutinator.intrinsics.BASE_CONTINUATION_CLASS_NAME 2 | import dev.reformator.stacktracedecoroutinator.jvm.DecoroutinatorJvmApi 3 | import dev.reformator.stacktracedecoroutinator.jvm.internal.isTransformed 4 | import kotlinx.coroutines.runBlocking 5 | import kotlinx.coroutines.yield 6 | import org.junit.jupiter.api.condition.DisabledIfSystemProperty 7 | import org.junit.jupiter.api.condition.EnabledIfSystemProperty 8 | import kotlin.test.BeforeTest 9 | import kotlin.test.Test 10 | import kotlin.test.assertFalse 11 | import kotlin.test.assertTrue 12 | 13 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 14 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() { 15 | @BeforeTest 16 | fun setup() { 17 | setupTest() 18 | } 19 | } 20 | 21 | // Jacoco only instruments this class 22 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 23 | class JacocoInstrumentedMethodTest { 24 | @BeforeTest 25 | fun setup() { 26 | setupTest() 27 | } 28 | 29 | @Test 30 | fun jacocoInstrumentedMethodTest(): Unit = runBlocking { 31 | suspend fun jacocoInstrumentedMethod() { 32 | yield() 33 | yield() 34 | } 35 | jacocoInstrumentedMethod() 36 | } 37 | } 38 | 39 | @EnabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 40 | class ReloadBaseContinuationTest { 41 | @Test 42 | fun reloadBaseContinuation() { 43 | val baseContinuationClass = Class.forName(BASE_CONTINUATION_CLASS_NAME) 44 | assertFalse(baseContinuationClass.isTransformed) 45 | DecoroutinatorJvmApi.install() 46 | assertTrue(baseContinuationClass.isTransformed) 47 | } 48 | } 49 | 50 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 51 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() { 52 | @BeforeTest 53 | fun setup() { 54 | setupTest() 55 | } 56 | } 57 | 58 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 59 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() { 60 | @BeforeTest 61 | fun setup() { 62 | setupTest() 63 | } 64 | } 65 | 66 | fun setupTest() { 67 | System.setProperty( 68 | "dev.reformator.stacktracedecoroutinator.jvmAgentDebugMetadataInfoResolveStrategy", 69 | "SYSTEM_RESOURCE" 70 | ) 71 | DecoroutinatorJvmApi.install() 72 | } 73 | -------------------------------------------------------------------------------- /gradle-plugin/src/main/kotlin/api-gradle-plugin-decoroutinator.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("ApiGradlePluginDecoroutinatorKt") 3 | 4 | package org.gradle.kotlin.dsl 5 | 6 | import dev.reformator.bytecodeprocessor.intrinsics.LoadConstant 7 | import dev.reformator.bytecodeprocessor.intrinsics.fail 8 | import dev.reformator.stacktracedecoroutinator.gradleplugin.ANDROID_CURRENT_PROGUARD_RULES_FILE_NAME 9 | import dev.reformator.stacktracedecoroutinator.gradleplugin.DecoroutinatorAttributePluginExtension 10 | import dev.reformator.stacktracedecoroutinator.gradleplugin.DecoroutinatorPluginExtension 11 | import dev.reformator.stacktracedecoroutinator.gradleplugin.decoroutinatorDir 12 | import org.gradle.api.Project 13 | import java.io.File 14 | 15 | fun Project.stacktraceDecoroutinator(configure: DecoroutinatorPluginExtension.() -> Unit) { 16 | extensions.configure(::stacktraceDecoroutinator.name, configure) 17 | } 18 | 19 | fun Project.stacktraceDecoroutinatorAttribute(configure: DecoroutinatorAttributePluginExtension.() -> Unit) { 20 | extensions.configure(::stacktraceDecoroutinatorAttribute.name, configure) 21 | } 22 | 23 | @Suppress("unused") 24 | @Deprecated("replace with method", replaceWith = ReplaceWith("decoroutinatorAndroidProGuardRules()")) 25 | val Project.decoroutinatorAndroidProGuardRules: File 26 | get() = decoroutinatorAndroidProGuardRules() 27 | 28 | fun Project.decoroutinatorAndroidProGuardRules(): File = 29 | decoroutinatorDir.resolve(ANDROID_CURRENT_PROGUARD_RULES_FILE_NAME) 30 | 31 | fun decoroutinatorCommon(): Any = 32 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-common:$projectVersionIntrinsic" 33 | 34 | fun decoroutinatorJvmRuntime(): Any = 35 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-generator-jvm:$projectVersionIntrinsic" 36 | 37 | fun decoroutinatorAndroidRuntime(): Any = 38 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-generator-android:$projectVersionIntrinsic" 39 | 40 | fun decoroutinatorRegularMethodHandleInvoker(): Any = 41 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-mh-invoker:$projectVersionIntrinsic" 42 | 43 | fun decoroutinatorAndroidMethodHandleInvoker(): Any = 44 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-mh-invoker-android:$projectVersionIntrinsic" 45 | 46 | fun decoroutinatorJvmMethodHandleInvoker(): Any = 47 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-mh-invoker-jvm:$projectVersionIntrinsic" 48 | 49 | fun decoroutinatorRuntimeSettings(): Any = 50 | "dev.reformator.stacktracedecoroutinator:stacktrace-decoroutinator-runtime-settings:$projectVersionIntrinsic" 51 | 52 | private val projectVersionIntrinsic: String 53 | @LoadConstant("version") get() { fail() } 54 | -------------------------------------------------------------------------------- /runtime-settings/src/main/kotlin/internal/runtime-settings-internal.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.runtimesettings.internal 4 | 5 | import dev.reformator.stacktracedecoroutinator.runtimesettings.DecoroutinatorRuntimeSettingsProvider 6 | import java.util.ServiceLoader 7 | 8 | @Suppress("ObjectInheritsException", "JavaIoSerializableObjectMustHaveReadResolve") 9 | private object DefaultValueException: Exception() 10 | 11 | internal fun defaultValue(): Nothing = 12 | throw DefaultValueException 13 | 14 | sealed interface RuntimeSettingsValue { 15 | object Default: RuntimeSettingsValue 16 | class Value(val value: T): RuntimeSettingsValue 17 | } 18 | 19 | private class RuntimeSettingsProviderWithPriority( 20 | val provider: DecoroutinatorRuntimeSettingsProvider, 21 | val priority: Int 22 | ) 23 | 24 | private val runtimeSettingsProviderInstances = 25 | ServiceLoader.load(DecoroutinatorRuntimeSettingsProvider::class.java) 26 | .asSequence() 27 | .map { RuntimeSettingsProviderWithPriority(it, it.priority) } 28 | .sortedByDescending { it.priority } 29 | .toList() 30 | 31 | fun getRuntimeSettingsValue(get: DecoroutinatorRuntimeSettingsProvider.() -> T): RuntimeSettingsValue { 32 | var index = 0 33 | val value = run { 34 | while (index < runtimeSettingsProviderInstances.size) { 35 | try { 36 | return@run runtimeSettingsProviderInstances[index].provider.get() 37 | } catch (_: DefaultValueException) { 38 | index++ 39 | } 40 | } 41 | return RuntimeSettingsValue.Default 42 | } 43 | val provider = runtimeSettingsProviderInstances[index].provider 44 | val priority = runtimeSettingsProviderInstances[index].priority 45 | index++ 46 | while (index < runtimeSettingsProviderInstances.size && runtimeSettingsProviderInstances[index].priority == priority) { 47 | try { 48 | val otherProvider = runtimeSettingsProviderInstances[index].provider 49 | val otherValue = otherProvider.get() 50 | if (otherValue != value) { 51 | error("different values with the same priority[$priority]: [$value] from [$provider] and [$otherValue] from [$otherProvider]") 52 | } 53 | } catch (_: DefaultValueException) { } 54 | index++ 55 | } 56 | return RuntimeSettingsValue.Value(value) 57 | } 58 | 59 | inline fun getRuntimeSettingsValue( 60 | noinline get: DecoroutinatorRuntimeSettingsProvider.() -> T, 61 | default: () -> T 62 | ): T = 63 | when(val value = getRuntimeSettingsValue(get)) { 64 | is RuntimeSettingsValue.Value -> value.value 65 | RuntimeSettingsValue.Default -> default() 66 | } 67 | -------------------------------------------------------------------------------- /common/src/main/kotlin/internal/interfaces-common.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.common.internal 4 | 5 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 6 | import dev.reformator.stacktracedecoroutinator.provider.DecoroutinatorSpec 7 | import dev.reformator.stacktracedecoroutinator.provider.internal.AndroidLegacyKeep 8 | import java.io.InputStream 9 | import java.lang.invoke.MethodHandle 10 | import java.lang.invoke.MethodHandles 11 | import java.lang.invoke.VarHandle 12 | 13 | interface TransformedClassesRegistry { 14 | class TransformedClassSpec( 15 | val transformedClass: Class<*>, 16 | val fileName: String?, 17 | val lookup: MethodHandles.Lookup, 18 | val lineNumbersByMethod: Map, 19 | val skipSpecMethods: Boolean 20 | ) 21 | 22 | fun interface Listener { 23 | fun onNewTransformedClass(spec: TransformedClassSpec) 24 | fun onException(exception: Throwable) { } 25 | } 26 | 27 | val transformedClasses: Collection 28 | operator fun get(clazz: Class<*>): TransformedClassSpec? 29 | fun addListener(listener: Listener) 30 | fun registerTransformedClass(lookup: MethodHandles.Lookup) 31 | } 32 | 33 | fun interface SpecMethodsFactory { 34 | fun getSpecMethodHandle(element: StackTraceElement): MethodHandle? 35 | } 36 | 37 | data class TransformationMetadata( 38 | val fileName: String?, 39 | val methods: List, 40 | val skipSpecMethods: Boolean 41 | ) { 42 | class Method( 43 | val name: String, 44 | val lineNumbers: IntArray 45 | ) 46 | } 47 | 48 | @Suppress("ArrayInDataClass") 49 | data class KotlinDebugMetadata( 50 | val sourceFile: String, 51 | val className: String, 52 | val methodName: String, 53 | val lineNumbers: IntArray 54 | ) 55 | 56 | interface AnnotationMetadataResolver { 57 | fun getTransformationMetadata(classBody: InputStream): TransformationMetadata? 58 | fun getKotlinDebugMetadata(classBody: InputStream): KotlinDebugMetadata? 59 | } 60 | 61 | @AndroidLegacyKeep 62 | interface MethodHandleInvoker { 63 | val unknownSpecMethodHandle: MethodHandle 64 | fun callSpecMethod(handle: MethodHandle, spec: DecoroutinatorSpec, result: Any?): Any? 65 | val unknownSpecMethodClass: Class<*> 66 | val supportsVarHandle: Boolean 67 | } 68 | 69 | @AndroidLegacyKeep 70 | interface VarHandleInvoker { 71 | fun getIntVar(handle: VarHandle, owner: Any): Int 72 | } 73 | 74 | internal interface StacktraceElementsFactory { 75 | fun getStacktraceElement(baseContinuation: BaseContinuation): StackTraceElement? 76 | fun getLabel(baseContinuation: BaseContinuation): Int 77 | } 78 | 79 | internal const val NONE_LABEL = Int.MIN_VALUE / 2 80 | internal const val UNKNOWN_LABEL = NONE_LABEL - 1 81 | -------------------------------------------------------------------------------- /gradle-plugin/duplicate-entity-jar-builder/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import dev.reformator.bytecodeprocessor.plugins.GetCurrentFileNameProcessor 2 | import dev.reformator.bytecodeprocessor.plugins.GetOwnerClassProcessor 3 | import org.apache.tools.zip.ZipEntry 4 | import org.apache.tools.zip.ZipOutputStream 5 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 6 | import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile 7 | 8 | plugins { 9 | kotlin("jvm") 10 | id("dev.reformator.bytecodeprocessor") 11 | } 12 | 13 | repositories { 14 | mavenCentral() 15 | } 16 | 17 | dependencies { 18 | //noinspection UseTomlInstead 19 | compileOnly("dev.reformator.bytecodeprocessor:bytecode-processor-intrinsics") 20 | } 21 | 22 | bytecodeProcessor { 23 | processors = setOf( 24 | GetCurrentFileNameProcessor, 25 | GetOwnerClassProcessor 26 | ) 27 | } 28 | 29 | tasks.test { 30 | useJUnitPlatform() 31 | } 32 | 33 | java { 34 | sourceCompatibility = JavaVersion.VERSION_1_9 35 | targetCompatibility = JavaVersion.VERSION_1_9 36 | } 37 | 38 | kotlin { 39 | compilerOptions { 40 | jvmTarget = JvmTarget.JVM_1_8 41 | } 42 | } 43 | 44 | sourceSets { 45 | main { 46 | kotlin.destinationDirectory = java.destinationDirectory 47 | } 48 | } 49 | 50 | val duplicateJarConfig = configurations.create("duplicateJar") 51 | 52 | val createDuplicateJarTask = tasks.register("createDuplicateJar") { 53 | val compileJavaTask = tasks.named("compileJava") 54 | val compileKotlinTask = tasks.named("compileKotlin") 55 | dependsOn(compileJavaTask, compileKotlinTask) 56 | outputs.file(layout.buildDirectory.file("duplicate-entities.jar")) 57 | doLast { 58 | ZipOutputStream(outputs.files.singleFile).use { output -> 59 | output.putDirectoryDuplicate(compileJavaTask.get().destinationDirectory.asFile.get()) 60 | output.putDirectoryDuplicate(compileKotlinTask.get().destinationDirectory.asFile.get()) 61 | } 62 | } 63 | } 64 | 65 | artifacts.add(duplicateJarConfig.name, createDuplicateJarTask) 66 | 67 | fun ZipOutputStream.putDirectoryDuplicate(root: File) { 68 | root.walk().forEach { file -> 69 | if (file == root) return@forEach 70 | val path = file.relativeTo(root).path.replace(File.pathSeparatorChar, '/') 71 | if (file.isDirectory) { 72 | val dirPath = "$path/" 73 | putEntry(dirPath) 74 | putEntry(dirPath) 75 | } else { 76 | val buffer = file.readBytes() 77 | putEntry(path) 78 | write(buffer) 79 | putEntry(path) 80 | write(buffer) 81 | } 82 | } 83 | } 84 | 85 | private fun ZipOutputStream.putEntry(name: String) { 86 | putNextEntry(ZipEntry(name).apply { 87 | method = ZipEntry.DEFLATED 88 | }) 89 | } 90 | -------------------------------------------------------------------------------- /runtime-settings/build.gradle.kts: -------------------------------------------------------------------------------- 1 | import org.jetbrains.dokka.gradle.AbstractDokkaTask 2 | import org.jetbrains.kotlin.gradle.dsl.JvmTarget 3 | 4 | plugins { 5 | kotlin("jvm") 6 | alias(libs.plugins.dokka) 7 | `maven-publish` 8 | signing 9 | id("dev.reformator.forcevariantjavaversion") 10 | } 11 | 12 | repositories { 13 | mavenCentral() 14 | } 15 | 16 | java { 17 | sourceCompatibility = JavaVersion.VERSION_1_9 18 | targetCompatibility = JavaVersion.VERSION_1_9 19 | } 20 | 21 | tasks.withType { 22 | options.compilerArgs.addAll(listOf("-parameters", "-Xlint:-module")) 23 | } 24 | 25 | kotlin { 26 | compilerOptions { 27 | jvmTarget = JvmTarget.JVM_1_8 28 | freeCompilerArgs.add("-Xjvm-default=all") 29 | } 30 | } 31 | 32 | sourceSets { 33 | main { 34 | kotlin.destinationDirectory = java.destinationDirectory 35 | } 36 | } 37 | 38 | val dokkaJavadocsJar = tasks.register("dokkaJavadocsJar") { 39 | val dokkaJavadocTask = tasks.named("dokkaJavadoc").get() 40 | dependsOn(dokkaJavadocTask) 41 | archiveClassifier.set("javadoc") 42 | from(dokkaJavadocTask.outputDirectory) 43 | } 44 | 45 | val mavenPublicationName = "maven" 46 | 47 | publishing { 48 | publications { 49 | create(mavenPublicationName) { 50 | from(components["java"]) 51 | artifact(dokkaJavadocsJar) 52 | artifact(tasks.named("kotlinSourcesJar")) 53 | pom { 54 | name.set("Stacktrace-decoroutinator runtime settings provider lib.") 55 | description.set("Library for recovering stack trace in exceptions thrown in Kotlin coroutines.") 56 | url.set("https://github.com/Anamorphosee/stacktrace-decoroutinator") 57 | licenses { 58 | license { 59 | name.set("The Apache License, Version 2.0") 60 | url.set("http://www.apache.org/licenses/LICENSE-2.0.txt") 61 | } 62 | } 63 | developers { 64 | developer { 65 | name.set("Denis Berestinskii") 66 | email.set("berestinsky@gmail.com") 67 | url.set("https://github.com/Anamorphosee") 68 | } 69 | } 70 | scm { 71 | connection.set("scm:git:git://github.com/Anamorphosee/stacktrace-decoroutinator.git") 72 | developerConnection.set("scm:git:ssh://github.com:Anamorphosee/stacktrace-decoroutinator.git") 73 | url.set("http://github.com/Anamorphosee/stacktrace-decoroutinator/tree/master") 74 | } 75 | } 76 | } 77 | } 78 | } 79 | 80 | signing { 81 | useGpgCmd() 82 | sign(publishing.publications[mavenPublicationName]) 83 | } 84 | -------------------------------------------------------------------------------- /jvm/src/test/kotlin/tests-jvm.kt: -------------------------------------------------------------------------------- 1 | package dev.reformator.stacktracedecoroutinator.jvmtests 2 | 3 | import dev.reformator.stacktracedecoroutinator.intrinsics.BASE_CONTINUATION_CLASS_NAME 4 | import dev.reformator.stacktracedecoroutinator.jvm.DecoroutinatorJvmApi 5 | import dev.reformator.stacktracedecoroutinator.jvm.internal.isTransformed 6 | import kotlinx.coroutines.runBlocking 7 | import kotlinx.coroutines.yield 8 | import org.junit.jupiter.api.condition.DisabledIfSystemProperty 9 | import org.junit.jupiter.api.condition.EnabledIfSystemProperty 10 | import kotlin.test.BeforeTest 11 | import kotlin.test.Test 12 | import kotlin.test.assertFalse 13 | import kotlin.test.assertTrue 14 | 15 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 16 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() { 17 | @BeforeTest 18 | fun setup() { 19 | setupTest() 20 | } 21 | } 22 | 23 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 24 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() { 25 | @BeforeTest 26 | fun setup() { 27 | setupTest() 28 | } 29 | } 30 | 31 | // Jacoco only instruments this class 32 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 33 | class JacocoInstrumentedMethodTest { 34 | @BeforeTest 35 | fun setup() { 36 | setupTest() 37 | } 38 | 39 | @Test 40 | fun jacocoInstrumentedMethodTest(): Unit = runBlocking { 41 | suspend fun jacocoInstrumentedMethod() { 42 | yield() 43 | yield() 44 | } 45 | 46 | jacocoInstrumentedMethod() 47 | } 48 | } 49 | 50 | @EnabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 51 | class ReloadBaseContinuationTest { 52 | @Test 53 | fun reloadBaseContinuation() { 54 | val baseContinuationClass = Class.forName(BASE_CONTINUATION_CLASS_NAME) 55 | assertFalse(baseContinuationClass.isTransformed) 56 | DecoroutinatorJvmApi.install() 57 | assertTrue(baseContinuationClass.isTransformed) 58 | } 59 | } 60 | 61 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 62 | class CustomClassLoaderTest: dev.reformator.stacktracedecoroutinator.test.CustomClassLoaderTest() { 63 | @BeforeTest 64 | fun setup() { 65 | setupTest() 66 | } 67 | } 68 | 69 | @DisabledIfSystemProperty(named = "testReloadBaseConfiguration", matches = "true") 70 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() { 71 | @BeforeTest 72 | fun setup() { 73 | setupTest() 74 | } 75 | } 76 | 77 | fun setupTest() { 78 | System.setProperty( 79 | "dev.reformator.stacktracedecoroutinator.jvmAgentDebugMetadataInfoResolveStrategy", 80 | "SYSTEM_RESOURCE" 81 | ) 82 | DecoroutinatorJvmApi.install() 83 | } 84 | -------------------------------------------------------------------------------- /settings.gradle.kts: -------------------------------------------------------------------------------- 1 | rootProject.name = "stacktrace-decoroutinator" 2 | include( 3 | "provider", 4 | "common", 5 | "generator-jvm", 6 | "gradle-plugin", 7 | "jvm-agent-common", 8 | "jvm", 9 | "jvm-agent", 10 | "generator-android", 11 | "mh-invoker", 12 | "mh-invoker-android", 13 | "mh-invoker-jvm", 14 | "runtime-settings", 15 | "class-transformer", 16 | "spec-method-builder", 17 | 18 | "intrinsics", 19 | "test-utils", 20 | "test-utils:base-continuation-accessor-stub", 21 | "test-utils:base-continuation-accessor-reflect-stub", 22 | "test-utils-jvm", 23 | "test-utils:custom-loader", 24 | "generator-jvm:jdk8-tests-g", 25 | "gradle-plugin:tests-gp", 26 | "gradle-plugin:android-tests", 27 | "gradle-plugin:jdk8-tests-gp", 28 | "gradle-plugin:duplicate-entity-jar-builder", 29 | "gradle-plugin:android-legacy-tests", 30 | "gradle-plugin:empty-module-tests", 31 | "gradle-plugin:embedded-debug-probes-stdlib", 32 | "gradle-plugin:embedded-debug-probes-xcoroutines", 33 | "gradle-plugin:base-continuation-accessor", 34 | "jvm-agent:tests-ja", 35 | "jvm-agent:jdk8-tests-ja", 36 | "jvm:jdk8-tests-j", 37 | "mh-invoker-jvm:jdk8-tests-mij", 38 | "jvm-agent-common:suspend-class-stub", 39 | "generator-jvm:android-wrong-generator-tests", 40 | "gradle-plugin:gradle-groovy-dsl-tests", 41 | "test-utils:retrace-repack", 42 | "gradle-plugin:aar-builder" 43 | ) 44 | project(":provider").name = "stacktrace-decoroutinator-provider" 45 | project(":common").name = "stacktrace-decoroutinator-common" 46 | project(":generator-jvm").name = "stacktrace-decoroutinator-generator-jvm" 47 | project(":gradle-plugin").name = "stacktrace-decoroutinator-gradle-plugin" 48 | project(":jvm-agent-common").name = "stacktrace-decoroutinator-jvm-agent-common" 49 | project(":jvm").name = "stacktrace-decoroutinator-jvm" 50 | project(":jvm-agent").name = "stacktrace-decoroutinator-jvm-agent" 51 | project(":generator-android").name = "stacktrace-decoroutinator-generator-android" 52 | project(":mh-invoker").name = "stacktrace-decoroutinator-mh-invoker" 53 | project(":mh-invoker-android").name = "stacktrace-decoroutinator-mh-invoker-android" 54 | project(":mh-invoker-jvm").name = "stacktrace-decoroutinator-mh-invoker-jvm" 55 | project(":runtime-settings").name = "stacktrace-decoroutinator-runtime-settings" 56 | project(":class-transformer").name = "stacktrace-decoroutinator-class-transformer" 57 | project(":spec-method-builder").name = "stacktrace-decoroutinator-spec-method-builder" 58 | 59 | includeBuild("_plugins/bytecode-processor") 60 | includeBuild("_plugins/gradle-plugin-test") 61 | includeBuild("_plugins/force-variant-java-version") 62 | 63 | includeBuild("_tests/latest-kotlin-gradle-plugin-test") 64 | includeBuild("_tests/latest-kotlin-kmp-gradle-plugin-test") 65 | 66 | pluginManagement { 67 | includeBuild("_plugins/bytecode-processor") 68 | includeBuild("_plugins/gradle-plugin-test") 69 | includeBuild("_plugins/force-variant-java-version") 70 | } 71 | -------------------------------------------------------------------------------- /generator-jvm/src/main/kotlin/internal/classLoader-generator.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | @file:JvmName("ClassLoaderGeneratorKt") 3 | 4 | package dev.reformator.stacktracedecoroutinator.generatorjvm.internal 5 | 6 | import dev.reformator.bytecodeprocessor.intrinsics.MakeStatic 7 | import dev.reformator.stacktracedecoroutinator.common.internal.MethodHandleInvoker 8 | import dev.reformator.stacktracedecoroutinator.common.internal.specMethodType 9 | import dev.reformator.stacktracedecoroutinator.provider.internal.internalName 10 | import dev.reformator.stacktracedecoroutinator.specmethodbuilder.internal.buildSpecMethodNode 11 | import org.objectweb.asm.ClassWriter 12 | import org.objectweb.asm.Opcodes 13 | import org.objectweb.asm.Type 14 | import org.objectweb.asm.tree.ClassNode 15 | import java.lang.invoke.MethodHandle 16 | import java.lang.invoke.MethodHandles 17 | 18 | internal class DecoroutinatorClassLoader: ClassLoader(MethodHandleInvoker::class.java.classLoader) { 19 | fun buildClassAndGetSpecHandlesByMethod( 20 | className: String, 21 | fileName: String?, 22 | lineNumbersByMethod: Map> 23 | ): Map { 24 | val body = getClassBody( 25 | className = className, 26 | fileName = fileName, 27 | lineNumbersByMethod = lineNumbersByMethod 28 | ) 29 | val clazz = defineClass(className, body) 30 | return lineNumbersByMethod.mapValues { (methodName, _) -> 31 | MethodHandles.publicLookup().findStatic(clazz, methodName, specMethodType) 32 | } 33 | } 34 | 35 | @Suppress("unused") 36 | @MakeStatic(addToStaticInitializer = true) 37 | private fun clinit() { 38 | assert(registerAsParallelCapable()) 39 | } 40 | 41 | private fun defineClass(className: String, classBody: ByteArray): Class<*> { 42 | synchronized(getClassLoadingLock(className)) { 43 | return defineClass(className, classBody, 0, classBody.size) 44 | } 45 | } 46 | } 47 | 48 | private fun getClassBody( 49 | className: String, 50 | fileName: String?, 51 | lineNumbersByMethod: Map> 52 | ): ByteArray { 53 | val classNode = ClassNode(Opcodes.ASM9).apply { 54 | version = Opcodes.V1_8 55 | access = Opcodes.ACC_PUBLIC or Opcodes.ACC_FINAL or Opcodes.ACC_SUPER 56 | name = className.internalName 57 | superName = Type.getInternalName(Object::class.java) 58 | sourceFile = fileName 59 | methods = lineNumbersByMethod.asSequence() 60 | .map { (methodName, lineNumbers) -> 61 | buildSpecMethodNode( 62 | methodName = methodName, 63 | lineNumbers = lineNumbers, 64 | makePrivate = false, 65 | makeFinal = true 66 | ) 67 | } 68 | .toList() 69 | } 70 | val writer = ClassWriter(ClassWriter.COMPUTE_MAXS) 71 | classNode.accept(writer) 72 | return writer.toByteArray() 73 | } 74 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @rem 2 | @rem Copyright 2015 the original author or authors. 3 | @rem 4 | @rem Licensed under the Apache License, Version 2.0 (the "License"); 5 | @rem you may not use this file except in compliance with the License. 6 | @rem You may obtain a copy of the License at 7 | @rem 8 | @rem https://www.apache.org/licenses/LICENSE-2.0 9 | @rem 10 | @rem Unless required by applicable law or agreed to in writing, software 11 | @rem distributed under the License is distributed on an "AS IS" BASIS, 12 | @rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | @rem See the License for the specific language governing permissions and 14 | @rem limitations under the License. 15 | @rem 16 | 17 | @if "%DEBUG%" == "" @echo off 18 | @rem ########################################################################## 19 | @rem 20 | @rem Gradle startup script for Windows 21 | @rem 22 | @rem ########################################################################## 23 | 24 | @rem Set local scope for the variables with windows NT shell 25 | if "%OS%"=="Windows_NT" setlocal 26 | 27 | set DIRNAME=%~dp0 28 | if "%DIRNAME%" == "" set DIRNAME=. 29 | set APP_BASE_NAME=%~n0 30 | set APP_HOME=%DIRNAME% 31 | 32 | @rem Resolve any "." and ".." in APP_HOME to make it shorter. 33 | for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi 34 | 35 | @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. 36 | set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" 37 | 38 | @rem Find java.exe 39 | if defined JAVA_HOME goto findJavaFromJavaHome 40 | 41 | set JAVA_EXE=java.exe 42 | %JAVA_EXE% -version >NUL 2>&1 43 | if "%ERRORLEVEL%" == "0" goto execute 44 | 45 | echo. 46 | echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 47 | echo. 48 | echo Please set the JAVA_HOME variable in your environment to match the 49 | echo location of your Java installation. 50 | 51 | goto fail 52 | 53 | :findJavaFromJavaHome 54 | set JAVA_HOME=%JAVA_HOME:"=% 55 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 56 | 57 | if exist "%JAVA_EXE%" goto execute 58 | 59 | echo. 60 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 61 | echo. 62 | echo Please set the JAVA_HOME variable in your environment to match the 63 | echo location of your Java installation. 64 | 65 | goto fail 66 | 67 | :execute 68 | @rem Setup the command line 69 | 70 | set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar 71 | 72 | 73 | @rem Execute Gradle 74 | "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* 75 | 76 | :end 77 | @rem End local scope for the variables with windows NT shell 78 | if "%ERRORLEVEL%"=="0" goto mainEnd 79 | 80 | :fail 81 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 82 | rem the _cmd.exe /c_ return code! 83 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 84 | exit /b 1 85 | 86 | :mainEnd 87 | if "%OS%"=="Windows_NT" endlocal 88 | 89 | :omega 90 | -------------------------------------------------------------------------------- /provider/src/main/kotlin/internal/provider.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.provider.internal 4 | 5 | import java.lang.invoke.MethodHandles 6 | import java.util.ServiceLoader 7 | 8 | interface DecoroutinatorProvider { 9 | val isDecoroutinatorEnabled: Boolean 10 | val baseContinuationAccessor: BaseContinuationAccessor? 11 | fun prepareBaseContinuationAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor 12 | fun awakeBaseContinuation(accessor: BaseContinuationAccessor, baseContinuation: Any, result: Any?) 13 | fun registerTransformedClass(lookup: MethodHandles.Lookup) 14 | fun getBaseContinuation( 15 | completion: Any?, 16 | fileName: String?, 17 | className: String, 18 | methodName: String, 19 | lineNumber: Int 20 | ): Any? 21 | val isUsingElementFactoryForBaseContinuationEnabled: Boolean 22 | fun getElementFactoryStacktraceElement(baseContinuation: Any): StackTraceElement? 23 | } 24 | 25 | internal val provider: DecoroutinatorProvider = 26 | try { 27 | ServiceLoader.load(DecoroutinatorProvider::class.java).iterator().next() 28 | } catch (_: Throwable) { 29 | null 30 | } ?: NoopProvider() 31 | 32 | private class NoopProvider: DecoroutinatorProvider { 33 | override val isDecoroutinatorEnabled: Boolean 34 | get() = false 35 | 36 | override val baseContinuationAccessor: BaseContinuationAccessor 37 | get() = error("not supported") 38 | 39 | override fun prepareBaseContinuationAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor = 40 | error("not supported") 41 | 42 | override fun awakeBaseContinuation( 43 | accessor: BaseContinuationAccessor, 44 | baseContinuation: Any, 45 | result: Any? 46 | ) { 47 | error("not supported") 48 | } 49 | 50 | override fun registerTransformedClass(lookup: MethodHandles.Lookup) { 51 | error("not supported") 52 | } 53 | 54 | override fun getBaseContinuation( 55 | completion: Any?, 56 | fileName: String?, 57 | className: String, 58 | methodName: String, 59 | lineNumber: Int 60 | ): Any? = 61 | completion 62 | 63 | override val isUsingElementFactoryForBaseContinuationEnabled: Boolean 64 | get() = false 65 | 66 | override fun getElementFactoryStacktraceElement(baseContinuation: Any): StackTraceElement = 67 | error("not supported") 68 | } 69 | 70 | interface BaseContinuationAccessor { 71 | fun invokeSuspend(baseContinuation: Any, result: Any?): Any? 72 | fun releaseIntercepted(baseContinuation: Any) 73 | } 74 | 75 | fun interface BaseContinuationAccessorProvider { 76 | fun createAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor 77 | } 78 | 79 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 80 | @Retention(AnnotationRetention.BINARY) 81 | annotation class AndroidKeep 82 | 83 | @Target(AnnotationTarget.CLASS, AnnotationTarget.FILE) 84 | @Retention(AnnotationRetention.BINARY) 85 | annotation class AndroidLegacyKeep 86 | -------------------------------------------------------------------------------- /jvm-agent-common/src/main/kotlin/internal/base-continuation-accessor-agent-common.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package dev.reformator.stacktracedecoroutinator.jvmagentcommon.internal 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.LoadConstant 6 | import dev.reformator.bytecodeprocessor.intrinsics.fail 7 | import dev.reformator.stacktracedecoroutinator.intrinsics.BaseContinuation 8 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessor 9 | import dev.reformator.stacktracedecoroutinator.provider.internal.BaseContinuationAccessorProvider 10 | import java.lang.invoke.MethodHandles 11 | import java.lang.invoke.MethodType 12 | import java.util.Base64 13 | import java.util.zip.ZipInputStream 14 | 15 | internal class AgentBaseContinuationAccessorProvider: BaseContinuationAccessorProvider { 16 | override fun createAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor { 17 | try { 18 | return loadRegularAccessor(lookup) 19 | } catch (_: Throwable) { } 20 | 21 | val invokeSuspendHandle = lookup.findVirtual( 22 | BaseContinuation::class.java, 23 | BaseContinuation::invokeSuspend.name, 24 | MethodType.methodType(Object::class.java, Object::class.java) 25 | ) 26 | val releaseInterceptedHandle = lookup.findVirtual( 27 | BaseContinuation::class.java, 28 | BaseContinuation::releaseIntercepted.name, 29 | MethodType.methodType(Void::class.javaPrimitiveType) 30 | ) 31 | return object: BaseContinuationAccessor { 32 | override fun invokeSuspend(baseContinuation: Any, result: Any?): Any? = 33 | invokeSuspendHandle.invokeExact(baseContinuation as BaseContinuation, result) 34 | 35 | override fun releaseIntercepted(baseContinuation: Any) { 36 | releaseInterceptedHandle.invokeExact(baseContinuation as BaseContinuation) 37 | } 38 | } 39 | } 40 | } 41 | 42 | private fun loadRegularAccessor(lookup: MethodHandles.Lookup): BaseContinuationAccessor { 43 | var baseContinuationAccessorClass: Class<*>? = null 44 | ZipInputStream(Base64.getDecoder().decode(baseContinuationAccessorJarBase64).inputStream()).use { input -> 45 | while (true) { 46 | val entry = input.nextEntry ?: break 47 | if (entry.name.endsWith(".class")) { 48 | val body = input.readBytes() 49 | lookup.defineClass(body).let { definedClass -> 50 | if (definedClass.name == baseContinuationAccessorImplClassName) { 51 | baseContinuationAccessorClass = definedClass 52 | } 53 | } 54 | } 55 | } 56 | } 57 | return baseContinuationAccessorClass!!.getDeclaredConstructor().newInstance() as BaseContinuationAccessor 58 | } 59 | 60 | private val baseContinuationAccessorJarBase64: String 61 | @LoadConstant("baseContinuationAccessorJarBase64") get() { fail() } 62 | 63 | private val baseContinuationAccessorImplClassName: String 64 | @LoadConstant("baseContinuationAccessorImplClassName") get() { fail() } 65 | -------------------------------------------------------------------------------- /gradle-plugin/embedded-debug-probes-xcoroutines/src/main/kotlin/embedded-debug-probes-provider.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("PackageDirectoryMismatch") 2 | 3 | package kotlinx.coroutines.debug.internal 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.DeleteClass 6 | import dev.reformator.bytecodeprocessor.intrinsics.fail 7 | import dev.reformator.stacktracedecoroutinator.runtimesettings.internal.getRuntimeSettingsValue 8 | import kotlin.coroutines.Continuation 9 | import kotlin.coroutines.jvm.internal.DecoroutinatorDebugProbesProvider 10 | 11 | @Suppress("unused") 12 | class DecoroutinatorDebugProbesProviderImpl: DecoroutinatorDebugProbesProvider { 13 | init { 14 | val enableCreationStackTraces = getRuntimeSettingsValue({ enableCreationStackTraces }) { 15 | System.getProperty( 16 | "dev.reformator.stacktracedecoroutinator.enableCreationStackTraces", 17 | "false" 18 | ).toBoolean() 19 | } 20 | val installDebugProbes = getRuntimeSettingsValue({ installDebugProbes }) { 21 | System.getProperty( 22 | "dev.reformator.stacktracedecoroutinator.installDebugProbes", 23 | "true" 24 | ).toBoolean() 25 | } 26 | AgentInstallationType.isInstalledStatically = true 27 | DebugProbesImpl.enableCreationStackTraces = enableCreationStackTraces 28 | if (installDebugProbes) { 29 | DebugProbesImpl.install() 30 | } 31 | } 32 | 33 | override fun probeCoroutineCreated(completion: Continuation): Continuation = 34 | DebugProbesImpl.probeCoroutineCreated(completion) 35 | 36 | override fun probeCoroutineResumed(frame: Continuation<*>) { 37 | DebugProbesImpl.probeCoroutineResumed(frame) 38 | } 39 | 40 | override fun probeCoroutineSuspended(frame: Continuation<*>) { 41 | DebugProbesImpl.probeCoroutineSuspended(frame) 42 | } 43 | } 44 | 45 | @DeleteClass 46 | @Suppress("UNUSED_PARAMETER") 47 | private object DebugProbesImpl { 48 | var enableCreationStackTraces: Boolean 49 | @JvmName("getEnableCreationStackTraces\$kotlinx_coroutines_core") 50 | get() = fail() 51 | @JvmName("setEnableCreationStackTraces\$kotlinx_coroutines_core") 52 | set(value) { fail() } 53 | 54 | @JvmName("install\$kotlinx_coroutines_core") 55 | fun install() { fail() } 56 | 57 | @JvmName("probeCoroutineCreated\$kotlinx_coroutines_core") 58 | fun probeCoroutineCreated(completion: Continuation): Continuation { fail() } 59 | 60 | @JvmName("probeCoroutineResumed\$kotlinx_coroutines_core") 61 | fun probeCoroutineResumed(frame: Continuation<*>) { fail() } 62 | 63 | @JvmName("probeCoroutineSuspended\$kotlinx_coroutines_core") 64 | fun probeCoroutineSuspended(frame: Continuation<*>) { fail() } 65 | } 66 | 67 | @DeleteClass 68 | @Suppress("UNUSED_PARAMETER") 69 | private object AgentInstallationType { 70 | var isInstalledStatically: Boolean 71 | @JvmName("isInstalledStatically\$kotlinx_coroutines_core") 72 | get() = fail() 73 | @JvmName("setInstalledStatically\$kotlinx_coroutines_core") 74 | set(value) { fail() } 75 | } 76 | -------------------------------------------------------------------------------- /gradle-plugin/tests-gp/src/test/kotlin/tests-gradle-plugin.kt: -------------------------------------------------------------------------------- 1 | @file:Suppress("JAVA_MODULE_DOES_NOT_EXPORT_PACKAGE") 2 | 3 | package dev.reformator.stacktracedecoroutinator.gradleplugintests 4 | 5 | import dev.reformator.bytecodeprocessor.intrinsics.currentFileName 6 | import dev.reformator.bytecodeprocessor.intrinsics.currentLineNumber 7 | import dev.reformator.stacktracedecoroutinator.duplicatejar.* 8 | import dev.reformator.stacktracedecoroutinator.test.checkStacktrace 9 | import kotlinx.coroutines.flow.collect 10 | import kotlinx.coroutines.flow.flowOf 11 | import kotlinx.coroutines.flow.transform 12 | import kotlinx.coroutines.runBlocking 13 | import kotlinx.coroutines.suspendCancellableCoroutine 14 | import kotlinx.coroutines.yield 15 | import org.junit.jupiter.api.Assertions.* 16 | import kotlin.coroutines.resume 17 | import kotlin.test.Test 18 | 19 | class PerformanceTest: dev.reformator.stacktracedecoroutinator.test.PerformanceTest() 20 | class RuntimeTest: dev.reformator.stacktracedecoroutinator.test.RuntimeTest() 21 | class TailCallDeoptimizeTest: dev.reformator.stacktracedecoroutinator.test.TailCallDeoptimizeTest() 22 | class JvmTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTest() 23 | class JvmTailCallDeoptimizedTest: dev.reformator.stacktracedecoroutinator.testjvm.JvmTailCallDeoptimizedTest() 24 | 25 | class TestLocalFile { 26 | @Test 27 | fun localTest(): Unit = runBlocking { 28 | fun1() 29 | } 30 | 31 | @Test 32 | fun inlineTransformedClassForKotlinc() { 33 | runBlocking { 34 | flowOf(1) 35 | .transform { emit(it) } 36 | .collect() 37 | } 38 | } 39 | 40 | @Test 41 | fun transformedDuplicateEntityJar() { 42 | runBlocking { 43 | call { 44 | yield() 45 | checkStacktrace(StackTraceElement( 46 | duplicateJarCallClassName, 47 | duplicateJarCallMethodName, 48 | duplicateJarFileName, 49 | duplicateJarCallLineNumber 50 | )) 51 | } 52 | } 53 | } 54 | 55 | suspend fun fun1() { 56 | fun2(currentLineNumber) 57 | } 58 | 59 | suspend fun fun2(fun1LineNumber: Int) { 60 | val fun1Frame = StackTraceElement( 61 | TestLocalFile::class.qualifiedName, 62 | ::fun1.name, 63 | currentFileName, 64 | fun1LineNumber 65 | ) 66 | yield() 67 | fun3(fun1Frame, currentLineNumber) 68 | } 69 | 70 | suspend fun fun3(fun1Frame: StackTraceElement, fun2LineNumber: Int) { 71 | val fun2Frame = StackTraceElement( 72 | TestLocalFile::class.qualifiedName, 73 | ::fun2.name, 74 | currentFileName, 75 | fun2LineNumber 76 | ) 77 | yield() 78 | checkStacktrace(fun2Frame, fun1Frame) 79 | } 80 | } 81 | 82 | class DebugProbesTest { 83 | @Test 84 | fun performDebugProbes() { 85 | runBlocking { 86 | suspendCancellableCoroutine { continuation -> 87 | assertTrue(DebugProbesAccessor.dumpCoroutinesInfo().isNotEmpty()) 88 | continuation.resume(Unit) 89 | } 90 | } 91 | } 92 | } 93 | --------------------------------------------------------------------------------