-
-
Notifications
You must be signed in to change notification settings - Fork 755
/
DetektInvoker.kt
130 lines (114 loc) · 4.22 KB
/
DetektInvoker.kt
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package io.gitlab.arturbosch.detekt.invoke
import io.gitlab.arturbosch.detekt.internal.ClassLoaderCache
import io.gitlab.arturbosch.detekt.internal.GlobalClassLoaderCache
import org.gradle.api.GradleException
import org.gradle.api.Project
import org.gradle.api.file.ConfigurableFileCollection
import org.gradle.api.file.FileCollection
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.Property
import org.gradle.workers.WorkAction
import org.gradle.workers.WorkParameters
import java.io.PrintStream
import java.lang.reflect.InvocationTargetException
internal interface DetektInvoker {
fun invokeCli(
arguments: List<String>,
classpath: FileCollection,
taskName: String,
ignoreFailures: Boolean = false
)
companion object {
fun create(isDryRun: Boolean = false): DetektInvoker =
if (isDryRun) {
DryRunInvoker()
} else {
DefaultCliInvoker()
}
}
}
private const val DRY_RUN_PROPERTY = "detekt-dry-run"
internal fun Project.isDryRunEnabled(): Boolean {
return hasProperty(DRY_RUN_PROPERTY) && property(DRY_RUN_PROPERTY) == "true"
}
interface DetektWorkParameters : WorkParameters {
val arguments: ListProperty<String>
val ignoreFailures: Property<Boolean>
val dryRun: Property<Boolean>
val taskName: Property<String>
val classpath: ConfigurableFileCollection
}
abstract class DetektWorkAction : WorkAction<DetektWorkParameters> {
@Suppress("SwallowedException", "TooGenericExceptionCaught")
override fun execute() {
if (parameters.dryRun.getOrElse(false)) {
DryRunInvoker().invokeCli(
parameters.arguments.get(),
parameters.classpath,
parameters.taskName.get(),
parameters.ignoreFailures.getOrElse(false)
)
return
}
try {
@Suppress("DEPRECATION")
val runner = io.gitlab.arturbosch.detekt.cli.buildRunner(
parameters.arguments.get().toTypedArray(),
System.out,
System.err
)
runner.execute()
} catch (e: Exception) {
if (isBuildFailure(e.message) && parameters.ignoreFailures.get()) {
return
} else {
throw GradleException(e.message ?: "There was a problem running detekt.")
}
}
}
private fun isBuildFailure(msg: String?) =
msg != null && "Build failed with" in msg && "issues" in msg
}
internal class DefaultCliInvoker(
private val classLoaderCache: ClassLoaderCache = GlobalClassLoaderCache
) : DetektInvoker {
override fun invokeCli(
arguments: List<String>,
classpath: FileCollection,
taskName: String,
ignoreFailures: Boolean
) {
try {
val loader = classLoaderCache.getOrCreate(classpath)
val clazz = loader.loadClass("io.gitlab.arturbosch.detekt.cli.Main")
val runner = clazz.getMethod(
"buildRunner",
Array<String>::class.java,
PrintStream::class.java,
PrintStream::class.java
).invoke(null, arguments.toTypedArray(), System.out, System.err)
runner::class.java.getMethod("execute").invoke(runner)
} catch (reflectionWrapper: InvocationTargetException) {
val message = reflectionWrapper.targetException.message
if (message != null && isAnalysisFailure(message) && ignoreFailures) {
return
}
throw GradleException(message ?: "There was a problem running detekt.", reflectionWrapper)
}
}
private fun isAnalysisFailure(msg: String) = "Analysis failed with" in msg && "issues" in msg
}
private class DryRunInvoker : DetektInvoker {
override fun invokeCli(
arguments: List<String>,
classpath: FileCollection,
taskName: String,
ignoreFailures: Boolean
) {
println("Invoking detekt with dry-run.")
println("Task: $taskName")
println("Arguments: ${arguments.joinToString(" ")}")
println("Classpath: ${classpath.files}")
println("Ignore failures: $ignoreFailures")
}
}