name.remal.gradle_plugins.dsl.extensions.org.gradle.testing.jacoco.tasks.JacocoReportBase.kt Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Show all versions of gradle-plugins-kotlin-dsl Show documentation
Remal Gradle plugins: gradle-plugins-kotlin-dsl
package name.remal.gradle_plugins.dsl.extensions
import name.remal.ASM_API
import name.remal.gradle_plugins.api.ExcludeFromCodeCoverage
import name.remal.gradle_plugins.dsl.internal.RelocatedClass
import name.remal.newTempFile
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.testing.jacoco.tasks.JacocoReportBase
import org.objectweb.asm.AnnotationVisitor
import org.objectweb.asm.ClassReader
import org.objectweb.asm.ClassReader.SKIP_CODE
import org.objectweb.asm.ClassReader.SKIP_DEBUG
import org.objectweb.asm.ClassReader.SKIP_FRAMES
import org.objectweb.asm.ClassVisitor
import org.objectweb.asm.Type.getDescriptor
import java.io.File
import java.lang.reflect.Method
private val jacocoReportBaseGetExecutionDataMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod(FileCollection::class.java, "getExecutionData")
.apply { isAccessible = true }
}
private val jacocoReportBaseSetExecutionDataMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod("setExecutionData", FileCollection::class.java)
.apply { isAccessible = true }
}
var JacocoReportBase.executionDataCompatible: FileCollection
get() = (jacocoReportBaseGetExecutionDataMethod.invoke(this) as? FileCollection) ?: project.files()
set(value) {
val executionData: FileCollection? = jacocoReportBaseGetExecutionDataMethod.invoke(this) as? FileCollection
if (executionData == value) return
if (executionData is ConfigurableFileCollection) {
executionData.setFrom(value as Any)
} else {
jacocoReportBaseSetExecutionDataMethod.invoke(this, value)
}
}
private val jacocoReportBaseGetSourceDirectoriesMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod(FileCollection::class.java, "getSourceDirectories")
.apply { isAccessible = true }
}
private val jacocoReportBaseSetSourceDirectoriesMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod("setSourceDirectories", FileCollection::class.java)
.apply { isAccessible = true }
}
var JacocoReportBase.sourceDirectoriesCompatible: FileCollection
get() = (jacocoReportBaseGetSourceDirectoriesMethod.invoke(this) as? FileCollection) ?: project.files()
set(value) {
val sourceDirectories: FileCollection? = jacocoReportBaseGetSourceDirectoriesMethod.invoke(this) as? FileCollection
if (sourceDirectories == value) return
if (sourceDirectories is ConfigurableFileCollection) {
sourceDirectories.setFrom(value as Any)
} else {
jacocoReportBaseSetSourceDirectoriesMethod.invoke(this, value)
}
}
private val jacocoReportBaseGetClassDirectoriesMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod(FileCollection::class.java, "getClassDirectories")
.apply { isAccessible = true }
}
private val jacocoReportBaseSetClassDirectoriesMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod("setClassDirectories", FileCollection::class.java)
.apply { isAccessible = true }
}
var JacocoReportBase.classDirectoriesCompatible: FileCollection
get() = (jacocoReportBaseGetClassDirectoriesMethod.invoke(this) as? FileCollection) ?: project.files()
set(value) {
val classDirectories: FileCollection? = jacocoReportBaseGetClassDirectoriesMethod.invoke(this) as? FileCollection
if (classDirectories == value) return
if (classDirectories is ConfigurableFileCollection) {
classDirectories.setFrom(value as Any)
} else {
jacocoReportBaseSetClassDirectoriesMethod.invoke(this, value)
}
}
private val jacocoReportBaseGetAdditionalClassDirsMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod(FileCollection::class.java, "getAdditionalClassDirs")
.apply { isAccessible = true }
}
private val jacocoReportBaseSetAdditionalClassDirsMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod("setAdditionalClassDirs", FileCollection::class.java)
.apply { isAccessible = true }
}
var JacocoReportBase.additionalClassDirsCompatible: FileCollection
get() = (jacocoReportBaseGetAdditionalClassDirsMethod.invoke(this) as? FileCollection) ?: project.files()
set(value) {
val additionalClassDirs: FileCollection? = jacocoReportBaseGetAdditionalClassDirsMethod.invoke(this) as? FileCollection
if (additionalClassDirs == value) return
if (additionalClassDirs is ConfigurableFileCollection) {
additionalClassDirs.setFrom(value as Any)
} else {
jacocoReportBaseSetAdditionalClassDirsMethod.invoke(this, value)
}
}
private val jacocoReportBaseGetAdditionalSourceDirsMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod(FileCollection::class.java, "getAdditionalSourceDirs")
.apply { isAccessible = true }
}
private val jacocoReportBaseSetAdditionalSourceDirsMethod: Method by lazy {
JacocoReportBase::class.java
.getCompatibleMethod("setAdditionalSourceDirs", FileCollection::class.java)
.apply { isAccessible = true }
}
var JacocoReportBase.additionalSourceDirsCompatible: FileCollection
get() = (jacocoReportBaseGetAdditionalSourceDirsMethod.invoke(this) as? FileCollection) ?: project.files()
set(value) {
val additionalSourceDirs: FileCollection? = jacocoReportBaseGetAdditionalSourceDirsMethod.invoke(this) as? FileCollection
if (additionalSourceDirs == value) return
if (additionalSourceDirs is ConfigurableFileCollection) {
additionalSourceDirs.setFrom(value as Any)
} else {
jacocoReportBaseSetAdditionalSourceDirsMethod.invoke(this, value)
}
}
fun JacocoReportBase.prepareExecutionData() {
var result = executionDataCompatible
result = project.files(*result.files.filter(File::exists).toTypedArray())
if (result.isEmpty) result = project.files(newTempFile("jacoco-", ".exec"))
executionDataCompatible = result
}
private val excludeFromCodeCoverageDescs = setOf(
getDescriptor(ExcludeFromCodeCoverage::class.java),
getDescriptor(RelocatedClass::class.java)
)
fun JacocoReportBase.applyExcludeFromCodeCoverage() {
fun FileCollection.applyExcludeFromCodeCoverage(): FileCollection {
return project.files(this.files).asFileTree.filter { file ->
if (!file.isFile) return@filter false
if ("class" == file.extension) {
var isExcluded = false
ClassReader(file.readBytes()).accept(
object : ClassVisitor(ASM_API) {
override fun visitAnnotation(desc: String?, visible: Boolean): AnnotationVisitor? {
if (desc in excludeFromCodeCoverageDescs) isExcluded = true
return null
}
},
SKIP_DEBUG or SKIP_FRAMES or SKIP_CODE
)
return@filter !isExcluded
} else {
return@filter true
}
}
}
classDirectoriesCompatible = classDirectoriesCompatible.applyExcludeFromCodeCoverage()
additionalClassDirsCompatible = additionalClassDirsCompatible.applyExcludeFromCodeCoverage()
}