@@ -9,6 +9,9 @@ import japicmp.model.JApiField
99import japicmp.model.JApiMethod
1010import javassist.CtMethod
1111import me.champeau.gradle.japicmp.JapicmpTask
12+ import me.champeau.gradle.japicmp.report.RichReportData
13+ import me.champeau.gradle.japicmp.report.RichReportRenderer
14+ import me.champeau.gradle.japicmp.report.Severity
1215import me.champeau.gradle.japicmp.report.Violation
1316import me.champeau.gradle.japicmp.report.stdrules.AbstractRecordingSeenMembers
1417import me.champeau.gradle.japicmp.report.stdrules.BinaryIncompatibleRule
@@ -21,6 +24,7 @@ import org.gradle.api.publish.maven.MavenPublication
2124import org.gradle.api.tasks.Exec
2225import org.gradle.kotlin.dsl.property
2326import org.gradle.language.base.plugins.LifecycleBasePlugin
27+ import java.io.File
2428import java.nio.file.Files
2529import javax.inject.Inject
2630
@@ -198,8 +202,9 @@ public abstract class MapboxJApiCmpExtension @Inject constructor(objects: Object
198202 addDefaultRules.set(true )
199203 addSetupRule(RecordSeenMembersSetup ::class .java)
200204 addRule(InternalFilterRule ::class .java)
201- destinationDir.set(rootProject.layout.buildDirectory.dir(" reports/japi/" ))
202- reportName.set(" ${project.path.drop(1 )} .html" )
205+ destinationDir.set(rootProject.layout.projectDirectory.dir(" japicmp-report/" ))
206+ reportName.set(" ${project.path.drop(1 )} .txt" )
207+ renderer(CompatibilityReportRenderer ::class .java)
203208 }
204209
205210 htmlOutputFile.set(
@@ -208,6 +213,33 @@ public abstract class MapboxJApiCmpExtension @Inject constructor(objects: Object
208213 }
209214 }
210215
216+ /* *
217+ * Custom renderer to write compatibility violations to a file.
218+ */
219+ internal class CompatibilityReportRenderer : RichReportRenderer {
220+ override fun render (
221+ destinationDir : File ? ,
222+ data : RichReportData ?
223+ ) {
224+ // we only care about breaking changes
225+ // otherwise report might be noisy since japicmp will report info and accepted changes too
226+ val violations = data?.violations?.map { it.value }?.flatten()
227+ ?.filter { it.severity == Severity .error }
228+ ?.sortedBy { it.toString() }
229+
230+ if (violations.isNullOrEmpty()) {
231+ // remove destination file as it'll be empty otherwise
232+ destinationDir?.delete()
233+ return
234+ }
235+ destinationDir?.bufferedWriter().use { writer ->
236+ violations.forEach { violation ->
237+ writer?.appendLine(violation.toString())
238+ }
239+ }
240+ }
241+ }
242+
211243 internal companion object {
212244 private val semverRegex = " ^(0|[1-9]\\ d*)\\ .(0|[1-9]\\ d*)\\ .(0|[1-9]\\ d*)" .toRegex()
213245 }
0 commit comments