1
1
package org.checkerframework.gradle.plugin
2
2
3
+ import org.gradle.api.Task
3
4
import org.gradle.api.artifacts.DependencyResolutionListener
4
5
import org.gradle.api.artifacts.ResolvableDependencies
5
6
import org.gradle.api.internal.artifacts.dependencies.DefaultExternalModuleDependency
6
7
import org.gradle.api.internal.artifacts.dependencies.DefaultSelfResolvingDependency
8
+ import org.gradle.util.GradleVersion
7
9
8
10
import java.util.jar.JarFile
9
11
@@ -49,17 +51,40 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
49
51
*/
50
52
private final static def manifestLocation = " /checkerframework/"
51
53
54
+ /**
55
+ * Configure each task in {@code project } with the given {@code taskType }.
56
+ * <p >
57
+ * We prefer to configure with {@link
58
+ * org.gradle.api.tasks.TaskCollection#configureEach(org.gradle.api.Action)}
59
+ * rather than {@link
60
+ * org.gradle.api.tasks.TaskCollection#all(org.gradle.api.Action)}, but {@code
61
+ * configureEach } is only available on Gradle 4.9 and newer, so this method
62
+ * dynamically picks the better candidate based on the current Gradle version.
63
+ * <p >
64
+ * See also: <a href =" https://docs.gradle.org/current/userguide/task_configuration_avoidance.html" >
65
+ * Gradle documentation: Task Configuration Avoidance</a>
66
+ */
67
+ private static <S extends Task > void configureTasks (Project project , Class<S> taskType , Action<? super S> configure ) {
68
+ if (GradleVersion . current() < GradleVersion . version(" 4.9" )) {
69
+ project. tasks. withType(taskType). all configure
70
+ } else {
71
+ project. tasks. withType(taskType). configureEach configure
72
+ }
73
+ }
74
+
52
75
@Override void apply (Project project ) {
53
76
// Either get an existing CF config, or create a new one if none exists
54
77
CheckerFrameworkExtension userConfig = project. extensions. findByType(CheckerFrameworkExtension . class)?:
55
78
project. extensions. create(" checkerFramework" , CheckerFrameworkExtension )
56
79
boolean applied = false
57
80
(ANDROID_IDS + " java" ). each { id ->
58
81
project. pluginManager. withPlugin(id) {
59
- LOG . info(' Found plugin {}, applying checker compiler options.' , id)
60
- configureProject(project, userConfig)
61
- applyToProject(project, userConfig)
62
- if (! applied) applied = true
82
+ if (! applied) {
83
+ LOG . info(' Found plugin {}, applying checker compiler options.' , id)
84
+ configureProject(project, userConfig)
85
+ applyToProject(project, userConfig)
86
+ applied = true
87
+ }
63
88
}
64
89
}
65
90
@@ -215,10 +240,20 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
215
240
void afterResolve (ResolvableDependencies resolvableDependencies ) {}
216
241
})
217
242
218
- project. tasks. withType(AbstractCompile ). all { AbstractCompile compile ->
219
- CheckerFrameworkTaskExtension checkerExtension =
220
- compile. extensions. create(" checkerFramework" , CheckerFrameworkTaskExtension )
221
- }
243
+ configureTasks(project, AbstractCompile , { AbstractCompile compile ->
244
+ def ext = compile. extensions. findByName(" checkerFramework" )
245
+ if (ext == null ) {
246
+ LOG . info(" Adding checkerFramework extension to task {}" , compile. name)
247
+ compile. extensions. create(" checkerFramework" , CheckerFrameworkTaskExtension )
248
+ } else if (ext instanceof CheckerFrameworkTaskExtension ) {
249
+ LOG . debug(" Task {} in project {} already has checkerFramework added to it;" +
250
+ " make sure you're applying the org.checkerframework plugin after the Java plugin" , compile. name,
251
+ compile. project)
252
+ } else {
253
+ throw new IllegalStateException (" Task " + compile. name + " in project " + compile. project +
254
+ " already has a checkerFramework extension, but it's of an incorrect type " + ext. class)
255
+ }
256
+ })
222
257
}
223
258
224
259
/**
@@ -281,8 +316,7 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
281
316
}
282
317
} catch (Exception e) {
283
318
versionString = LIBRARY_VERSION
284
- LOG . warn(" Unable to determine Checker Framework version. Assuming default is being used." )
285
- LOG . debug(e)
319
+ LOG . warn(" Unable to determine Checker Framework version. Assuming default is being used: {}" , versionString, e. toString())
286
320
}
287
321
288
322
if (javaSourceVersion. java8 && jvmVersion. isJava8()) {
@@ -297,8 +331,7 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
297
331
// errorprone javac is required
298
332
needErrorProneJavac = true
299
333
LOG . warn(" Defaulting to ErrorProne Javac, because on a Java 8 JVM and" +
300
- " cannot determine exact Checker Framework version." )
301
- LOG . debug(e)
334
+ " cannot determine exact Checker Framework version." , e)
302
335
}
303
336
}
304
337
@@ -309,10 +342,17 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
309
342
createManifestTask. checkers = userConfig. checkers
310
343
}
311
344
312
- project. tasks. withType(AbstractCompile ). all { AbstractCompile compile ->
313
- if (! compile. extensions. checkerFramework. skipCheckerFramework
314
- && compile. hasProperty(' options' )
315
- && ! (userConfig. excludeTests && compile. name. toLowerCase(). contains(" test" ))) {
345
+ configureTasks(project, AbstractCompile , { AbstractCompile compile ->
346
+ if (compile. extensions. checkerFramework. skipCheckerFramework) {
347
+ LOG . info(" skipping the Checker Framework for task " + compile. name +
348
+ " because skipCheckerFramework property is set" )
349
+ return
350
+ }
351
+ if (userConfig. excludeTests && compile. name. toLowerCase(). contains(" test" )) {
352
+ LOG . info(" skipping the Checker Framework for task {} because excludeTests property is set" , compile. name)
353
+ return
354
+ }
355
+ if (compile. hasProperty(' options' )) {
316
356
compile. options. annotationProcessorPath = compile. options. annotationProcessorPath == null ?
317
357
project. configurations. checkerFramework :
318
358
project. configurations. checkerFramework. plus(compile. options. annotationProcessorPath)
@@ -361,12 +401,12 @@ final class CheckerFrameworkPlugin implements Plugin<Project> {
361
401
362
402
ANDROID_IDS . each { id ->
363
403
project. plugins. withId(id) {
364
- options. bootstrapClasspath = project. files(System . getProperty(" sun.boot.class.path" )) + options. bootstrapClasspath
404
+ compile . options. bootstrapClasspath = project. files(System . getProperty(" sun.boot.class.path" )) + compile . options. bootstrapClasspath
365
405
}
366
406
}
367
- options. fork = true
407
+ compile . options. fork = true
368
408
}
369
- }
409
+ })
370
410
}
371
411
}
372
412
}
0 commit comments