From bfa6c9f5d4cf889bfe1e90fde1bf19524eb54cbe Mon Sep 17 00:00:00 2001 From: Iwan Eising Date: Fri, 18 Sep 2026 09:20:28 +0400 Subject: [PATCH] feat(api-only-transcriberj-restdocs): mark generated companions as excluded from coverage A project that measures coverage of the source set its contract classes are generated into measured the REST Docs companions too -- code nobody wrote, and nobody should have to test. The core's generated classes carry a marker annotation for exactly that; the companions did not, so half the generated tree was still counted. Every companion and the shared RestDocsFields now carry @ExcludeFromJacocoGeneratedCodeCoverage(justification = "Generated by API-Only TranscriberJ"), the same annotation and the same wording as the classes they describe. The emitter ships no new dependency: the TranscriberJ adds sedr-library to the source sets it generates into, and it is the tests here that need it, because they compile the generated code. They also move to TranscriberJ 0.2.0, the version that carries the annotation and generates from a contract's AsyncAPI document. --- api-only-transcriberj-restdocs/build.gradle | 2 ++ .../gradle/libs.versions.toml | 7 ++++++- .../apionly/transcriberj/restdocs/Sources.java | 2 ++ .../transcriberj/restdocs/RestDocsEmitterTest.java | 12 ++++++++++++ 4 files changed, 22 insertions(+), 1 deletion(-) diff --git a/api-only-transcriberj-restdocs/build.gradle b/api-only-transcriberj-restdocs/build.gradle index b5adc73..643cf52 100644 --- a/api-only-transcriberj-restdocs/build.gradle +++ b/api-only-transcriberj-restdocs/build.gradle @@ -34,6 +34,8 @@ dependencies { testImplementation libs.api.only.transcriberj testImplementation libs.spring.restdocs.core + // The tests compile generated code, which carries the coverage marker annotation. + testImplementation libs.sedr.library testImplementation libs.junit.jupiter testImplementation libs.assertj.core testRuntimeOnly libs.junit.platform.launcher diff --git a/api-only-transcriberj-restdocs/gradle/libs.versions.toml b/api-only-transcriberj-restdocs/gradle/libs.versions.toml index 112a8eb..8e4247c 100644 --- a/api-only-transcriberj-restdocs/gradle/libs.versions.toml +++ b/api-only-transcriberj-restdocs/gradle/libs.versions.toml @@ -13,10 +13,14 @@ junit-platform = "6.1.3" assertj = "3.27.7" # The API-Only TranscriberJ this emitter is built against; its emitter interface is part # of the plugin artifact, published to the Gradle Plugin Portal. -api-only-transcriberj = "0.0.1" +api-only-transcriberj = "0.2.0" # The Spring REST Docs the generated code is tested with; also the version the plugin # adds to a project that declares none (RestDocsEmitter.dependencies()). spring-restdocs = "4.0.1" +# The marker annotation the generated code carries, so a coverage rule does not measure +# code nobody wrote. The TranscriberJ manages it for the projects it generates into; the +# tests here need it because they compile that generated code. +sedr-library = "1.0.0" [libraries] @@ -25,3 +29,4 @@ junit-platform-launcher = { module = "org.junit.platform:junit-platform-launcher assertj-core = { module = "org.assertj:assertj-core", version.ref = "assertj" } api-only-transcriberj = { module = "com.arc-e-tect:api-only-transcriberj", version.ref = "api-only-transcriberj" } spring-restdocs-core = { module = "org.springframework.restdocs:spring-restdocs-core", version.ref = "spring-restdocs" } +sedr-library = { module = "com.arc-e-tect.sedr.utils:sedr-library", version.ref = "sedr-library" } diff --git a/api-only-transcriberj-restdocs/src/main/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/Sources.java b/api-only-transcriberj-restdocs/src/main/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/Sources.java index 2c8090a..8ca807a 100644 --- a/api-only-transcriberj-restdocs/src/main/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/Sources.java +++ b/api-only-transcriberj-restdocs/src/main/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/Sources.java @@ -21,6 +21,7 @@ static String fields(String header, String pkg, String base) { /** * Spring REST Docs descriptors from the field descriptions in {@code %2$s}. */ + @com.arc_e_tect.sedr.utils.jacoco.marker.ExcludeFromJacocoGeneratedCodeCoverage(justification = "Generated by API-Only TranscriberJ") public final class RestDocsFields { private RestDocsFields() { @@ -80,6 +81,7 @@ static String companion(String header, String pkg, String base, String name, Str /** * Spring REST Docs descriptors and snippets of {@link %3$s}. */ + @com.arc_e_tect.sedr.utils.jacoco.marker.ExcludeFromJacocoGeneratedCodeCoverage(justification = "Generated by API-Only TranscriberJ") public final class %3$sDocs { private %3$sDocs() { diff --git a/api-only-transcriberj-restdocs/src/test/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/RestDocsEmitterTest.java b/api-only-transcriberj-restdocs/src/test/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/RestDocsEmitterTest.java index 1c923e8..7f0caf4 100644 --- a/api-only-transcriberj-restdocs/src/test/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/RestDocsEmitterTest.java +++ b/api-only-transcriberj-restdocs/src/test/java/com/arc_e_tect/gradle/apionly/transcriberj/restdocs/RestDocsEmitterTest.java @@ -184,6 +184,18 @@ void everyJsonTypeAndADelegatingResponseAreDescribed() throws Exception { assertThat(relaxed(call(loader, "FoundDocs", "responseFields"))).isFalse(); } + @Test + void everyCompanionSaysItIsGeneratedSoCoverageLeavesItAlone() throws Exception { + userAccount(); + + for (String name : List.of("UserV1Docs", "RestDocsFields")) { + assertThat(directory.resolve("sources/com/example/contract/restdocs/" + name + ".java")) + .as(name).content().contains( + "@com.arc_e_tect.sedr.utils.jacoco.marker.ExcludeFromJacocoGeneratedCodeCoverage(" + + "justification = \"Generated by API-Only TranscriberJ\")"); + } + } + @Test void aDegradedCoreMethodIsNotHiddenByTheCompanion() throws Exception { Path contract = directory.resolve("openapi.yaml");