@@ -7,34 +7,42 @@ import org.gradle.api.file.DirectoryProperty
77import org.gradle.api.invocation.BuildInvocationDetails
88import org.gradle.api.provider.ListProperty
99import org.gradle.api.provider.Property
10+ import org.gradle.api.tasks.Classpath
11+ import org.gradle.api.tasks.Input
12+ import org.gradle.api.tasks.InputDirectory
13+ import org.gradle.api.tasks.InputFiles
14+ import org.gradle.api.tasks.Optional
15+ import org.gradle.api.tasks.OutputDirectory
16+ import org.gradle.api.tasks.TaskAction
1017import org.gradle.api.tasks.compile.AbstractCompile
1118import org.gradle.jvm.toolchain.JavaLanguageVersion
1219import org.gradle.jvm.toolchain.JavaToolchainService
1320import org.gradle.workers.WorkAction
1421import org.gradle.workers.WorkParameters
1522import org.gradle.workers.WorkerExecutor
1623
24+ import javax.inject.Inject
1725import java.util.regex.Matcher
1826
1927/**
2028 * instrument<Language> task plugin which performs build-time instrumentation of classes.
2129 */
30+ @SuppressWarnings (' unused' )
2231class InstrumentPlugin implements Plugin<Project > {
23-
2432 @Override
2533 void apply (Project project ) {
2634 InstrumentExtension extension = project. extensions. create(' instrument' , InstrumentExtension )
2735
2836 project. tasks. matching {
2937 it. name in [' compileJava' , ' compileScala' , ' compileKotlin' ] ||
30- it. name =~ / compileMain_(?:.+) Java/
38+ it. name =~ / compileMain_.+ Java/
3139 }. all {
3240 AbstractCompile compileTask = it as AbstractCompile
3341 Matcher versionMatcher = it. name =~ / compileMain_(.+)Java/
3442 project. afterEvaluate {
3543 if (! compileTask. source. empty) {
36- String sourceSetSuffix
37- String javaVersion
44+ String sourceSetSuffix = null
45+ String javaVersion = null
3846 if (versionMatcher. matches()) {
3947 sourceSetSuffix = versionMatcher. group(1 )
4048 if (sourceSetSuffix ==~ / java\d +/ ) {
@@ -50,14 +58,28 @@ class InstrumentPlugin implements Plugin<Project> {
5058
5159 // insert task between compile and jar, and before test*
5260 String instrumentTaskName = compileTask. name. replace(' compile' , ' instrument' )
53- def instrumentTask = project. task([' type' : InstrumentTask ], instrumentTaskName) {
54- description = " Instruments the classes compiled by ${ compileTask.name} "
55- doLast {
56- instrument(javaVersion, project, extension, rawClassesDir, classesDir, it)
61+ def instrumentTask = project. tasks. register(instrumentTaskName, InstrumentTask ) {
62+ // Task configuration
63+ it. group = ' Byte Buddy'
64+ it. description = " Instruments the classes compiled by ${ compileTask.name} "
65+ it. inputs. dir(compileTask. destinationDirectory)
66+ it. outputs. dir(classesDir)
67+ // Task inputs
68+ it. javaVersion = javaVersion
69+ def instrumenterConfiguration = project. configurations. named(' instrumentPluginClasspath' )
70+ if (instrumenterConfiguration. present) {
71+ it. pluginClassPath. from(instrumenterConfiguration. get())
5772 }
73+ it. plugins = extension. plugins
74+ it. instrumentingClassPath. from(
75+ findCompileClassPath(project, it. name) +
76+ rawClassesDir +
77+ findAdditionalClassPath(extension, it. name)
78+ )
79+ it. sourceDirectory = rawClassesDir
80+ // Task output
81+ it. targetDirectory = classesDir
5882 }
59- instrumentTask. inputs. dir(compileTask. destinationDirectory)
60- instrumentTask. outputs. dir(classesDir)
6183 if (javaVersion) {
6284 project. tasks. named(project. sourceSets. " main_java${ javaVersion} " . classesTaskName) {
6385 it. dependsOn(instrumentTask)
@@ -71,6 +93,22 @@ class InstrumentPlugin implements Plugin<Project> {
7193 }
7294 }
7395 }
96+
97+ static findCompileClassPath (Project project , String taskName ) {
98+ def matcher = taskName =~ / instrument([A-Z].+)Java/
99+ def cfgName = matcher. matches() ? " ${ matcher.group(1).uncapitalize()} CompileClasspath" : ' compileClasspath'
100+ project. configurations. named(cfgName). findAll {
101+ it. name != ' previous-compilation-data.bin' && ! it. name. endsWith(' .gz' )
102+ }
103+ }
104+
105+ static findAdditionalClassPath (InstrumentExtension extension , String taskName ) {
106+ extension. additionalClasspath. getOrDefault(taskName, []). collect {
107+ // insert intermediate 'raw' directory for unprocessed classes
108+ def fileName = it. get(). asFile. name
109+ it. get(). dir(" ../${ fileName.replaceFirst('^main', 'raw')} " )
110+ }
111+ }
74112}
75113
76114abstract class InstrumentExtension {
@@ -79,51 +117,52 @@ abstract class InstrumentExtension {
79117}
80118
81119abstract class InstrumentTask extends DefaultTask {
82- {
83- group = ' Byte Buddy'
84- }
85-
86- @javax.inject.Inject
120+ @Input @Optional
121+ String javaVersion
122+ @InputFiles @Classpath
123+ abstract ConfigurableFileCollection getPluginClassPath ()
124+ @Input
125+ ListProperty<String > plugins
126+ @InputFiles @Classpath
127+ abstract ConfigurableFileCollection getInstrumentingClassPath ()
128+ @InputDirectory
129+ Directory sourceDirectory
130+
131+ @OutputDirectory
132+ Directory targetDirectory
133+
134+ @Inject
87135 abstract JavaToolchainService getJavaToolchainService ()
88-
89- @javax.inject.Inject
136+ @Inject
90137 abstract BuildInvocationDetails getInvocationDetails ()
91-
92- @javax.inject.Inject
138+ @Inject
93139 abstract WorkerExecutor getWorkerExecutor ()
94140
95- void instrument (String javaVersion ,
96- Project project ,
97- InstrumentExtension extension ,
98- Directory sourceDirectory ,
99- Directory targetDirectory ,
100- InstrumentTask instrumentTask )
101- {
102- def workQueue
103- if (javaVersion) {
104- def javaLauncher = javaToolchainService. launcherFor { spec ->
105- spec. languageVersion. set(JavaLanguageVersion . of(javaVersion))
141+ @TaskAction
142+ instrument () {
143+ workQueue(). submit(InstrumentAction . class, parameters -> {
144+ parameters. buildStartedTime. set(this . invocationDetails. buildStartedTime)
145+ parameters. pluginClassPath. from(this . pluginClassPath)
146+ parameters. plugins. set(this . plugins)
147+ parameters. instrumentingClassPath. setFrom(this . instrumentingClassPath)
148+ parameters. sourceDirectory. set(this . sourceDirectory. asFile)
149+ parameters. targetDirectory. set(this . targetDirectory. asFile)
150+ })
151+ }
152+
153+ private workQueue () {
154+ if (this . javaVersion) {
155+ def javaLauncher = this . javaToolchainService. launcherFor { spec ->
156+ spec. languageVersion. set(JavaLanguageVersion . of(this . javaVersion))
106157 }. get()
107- workQueue = workerExecutor. processIsolation { spec ->
158+ return this . workerExecutor. processIsolation { spec ->
108159 spec. forkOptions { fork ->
109160 fork. executable = javaLauncher. executablePath
110161 }
111162 }
112163 } else {
113- workQueue = workerExecutor. noIsolation()
164+ return this . workerExecutor. noIsolation()
114165 }
115- workQueue. submit(InstrumentAction . class, parameters -> {
116- parameters. buildStartedTime. set(invocationDetails. buildStartedTime)
117- parameters. pluginClassPath. setFrom(project. configurations. findByName(' instrumentPluginClasspath' ) ?: [])
118- parameters. plugins. set(extension. plugins)
119- def matcher = instrumentTask. name =~ / instrument([A-Z].+)Java/
120- def cfgName = matcher. matches() ? " ${ matcher.group(1).uncapitalize()} CompileClasspath" : ' compileClasspath'
121- parameters. instrumentingClassPath. setFrom(project. configurations[cfgName]. findAll {
122- it. name != ' previous-compilation-data.bin' && ! it. name. endsWith(" .gz" )
123- } + sourceDirectory + (extension. additionalClasspath[instrumentTask. name] ?: [])* . get())
124- parameters. sourceDirectory. set(sourceDirectory. asFile)
125- parameters. targetDirectory. set(targetDirectory. asFile)
126- })
127166 }
128167}
129168
0 commit comments