This repository has been archived by the owner on Feb 11, 2022. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 28
/
KtlintConfigurator.groovy
180 lines (157 loc) · 7.59 KB
/
KtlintConfigurator.groovy
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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
package com.novoda.staticanalysis.internal.ktlint
import com.novoda.staticanalysis.StaticAnalysisExtension
import com.novoda.staticanalysis.Violations
import com.novoda.staticanalysis.internal.Configurator
import com.novoda.staticanalysis.internal.VariantFilter
import com.novoda.staticanalysis.internal.checkstyle.CollectCheckstyleViolationsTask
import org.gradle.api.GradleException
import org.gradle.api.NamedDomainObjectContainer
import org.gradle.api.Project
import org.gradle.api.Task
import org.gradle.api.file.RegularFileProperty
import static com.novoda.staticanalysis.internal.Exceptions.handleException
import static com.novoda.staticanalysis.internal.TasksCompat.createTask
class KtlintConfigurator implements Configurator {
private static final String KTLINT_PLUGIN = 'org.jlleitschuh.gradle.ktlint'
private static final String KTLINT_NOT_APPLIED = 'The Ktlint plugin is configured but not applied. Please apply the plugin in your build script.\nFor more information see https://github.com/JLLeitschuh/ktlint-gradle/#how-to-use'
private static final String XML_REPORT_NOT_ENABLED = 'XML report must be enabled. Please make sure to add "CHECKSTYLE" into reports in your Ktlint configuration'
private static final String KTLINT_OUTPUT_FILES_NOT_DEFINED = 'No property for KtLint output files. Please check if the KtLint plugin has changed.'
private static final String LAST_COMPATIBLE_KTLINT_VERSION = '8.0.0'
private static final String MIN_COMPATIBLE_KTLINT_VERSION = '6.2.1' // Do not forget to update ktlint.md
private static final String KTLINT_CONFIGURATION_ERROR = """\
A problem occurred while configuring Ktlint. Please make sure to use a compatible version:
Minimum compatible Ktlint Plugin version: $MIN_COMPATIBLE_KTLINT_VERSION
Last tested compatible version: $LAST_COMPATIBLE_KTLINT_VERSION
"""
private final Project project
private final Violations violations
private final Task evaluateViolations
private final VariantFilter variantFilter
protected boolean configured = false
static KtlintConfigurator create(Project project,
NamedDomainObjectContainer<Violations> violationsContainer,
Task evaluateViolations) {
Violations violations = violationsContainer.maybeCreate('ktlint')
return new KtlintConfigurator(project, violations, evaluateViolations)
}
KtlintConfigurator(Project project, Violations violations, Task evaluateViolations) {
this.project = project
this.violations = violations
this.evaluateViolations = evaluateViolations
this.variantFilter = new VariantFilter(project)
}
@Override
void execute() {
project.extensions.findByType(StaticAnalysisExtension).ext.ktlint = { Closure config ->
if (!project.plugins.hasPlugin(KTLINT_PLUGIN)) {
throw new GradleException(KTLINT_NOT_APPLIED)
}
configureKtlintExtension(config)
project.plugins.withId("kotlin") {
configureKotlinProject()
}
project.plugins.withId("kotlin2js") {
configureKotlinProject()
}
project.plugins.withId("kotlin-platform-common") {
configureKotlinProject()
}
project.plugins.withId("org.jetbrains.kotlin.multiplatform") {
configureKotlinProject()
}
project.plugins.withId('com.android.application') {
configureAndroidWithVariants(variantFilter.filteredApplicationVariants)
}
project.plugins.withId('com.android.library') {
configureAndroidWithVariants(variantFilter.filteredLibraryVariants)
}
}
}
private void configureKtlintExtension(Closure config) {
try {
def ktlint = project.ktlint
ktlint.ignoreFailures = true
ktlint.ext.includeVariants = { Closure<Boolean> filter ->
variantFilter.includeVariantsFilter = filter
}
config.delegate = ktlint
config.resolveStrategy = Closure.DELEGATE_FIRST
config()
} catch (Exception exception) {
handleException(KTLINT_CONFIGURATION_ERROR, exception)
}
}
private void configureKotlinProject() {
project.sourceSets.each {
def collectViolations = createCollectViolationsTask(violations, it.name)
evaluateViolations.dependsOn collectViolations
}
}
private void configureAndroidWithVariants(def mainVariants) {
if (configured) return
project.android.sourceSets.all { sourceSet ->
createCollectViolationsTask(violations, sourceSet.name)
}
mainVariants.all { configureAndroidVariant(it) }
variantFilter.filteredTestVariants.all { configureAndroidVariant(it) }
variantFilter.filteredUnitTestVariants.all { configureAndroidVariant(it) }
configured = true
}
private void configureAndroidVariant(def variant) {
def collectViolations = createVariantMetaTask(variant)
evaluateViolations.dependsOn collectViolations
}
private def createVariantMetaTask(variant) {
createTask(project, "collectKtlint${variant.name.capitalize()}VariantViolations", Task) { task ->
variant.sourceSets.forEach { sourceSet ->
task.dependsOn "collectKtlint${sourceSet.name.capitalize()}Violations"
}
}
}
private def createCollectViolationsTask(Violations violations, def sourceSetName) {
createTask(project, "collectKtlint${sourceSetName.capitalize()}Violations", CollectCheckstyleViolationsTask) { task ->
Task ktlintTask = project.tasks.findByName("ktlint${sourceSetName.capitalize()}SourceSetCheck")
if (ktlintTask == null) {
ktlintTask = project.tasks.findByName("ktlint${sourceSetName.capitalize()}Check")
}
File xmlReportFile = null
File txtReportFile = null
try {
Map<String, RegularFileProperty> outputFiles = getOutputFilesMap(ktlintTask)
outputFiles.each { key, fileProp ->
def file = fileProp.get().asFile
if (file.name.endsWith('.xml')) {
xmlReportFile = file
}
if (file.name.endsWith('.txt')) {
txtReportFile = file
}
}
if (xmlReportFile == null) {
throw new GradleException(XML_REPORT_NOT_ENABLED)
}
} catch (Exception exception) {
handleException(KTLINT_CONFIGURATION_ERROR, exception)
}
task.xmlReportFile = xmlReportFile
task.htmlReportFile = txtReportFile
task.violations = violations
task.dependsOn ktlintTask
}
}
/**
* This change was made to support version 9.0.0 of the JLLeitschuh/ktlint-gradle plugin which renamed
* `reportOutputFiles` to `allReportsOutputFiles`
*
* https://github.com/JLLeitschuh/ktlint-gradle/blob/master/CHANGELOG.md#900---2019-09-30
*/
private static Map<String, RegularFileProperty> getOutputFilesMap(Task ktlintTask) {
if (ktlintTask.hasProperty("allReportsOutputFiles")) {
return ktlintTask.allReportsOutputFiles
} else if(ktlintTask.hasProperty("reportOutputFiles")) {
return ktlintTask.reportOutputFiles
} else {
throw new GradleException(KTLINT_OUTPUT_FILES_NOT_DEFINED)
}
}
}