|  | 
|  | 1 | +package com.diffplug.atplug.tooling.gradle | 
|  | 2 | + | 
|  | 3 | +import com.diffplug.atplug.tooling.PlugParser | 
|  | 4 | +import java.io.File | 
|  | 5 | +import java.nio.charset.StandardCharsets | 
|  | 6 | +import org.gradle.api.DefaultTask | 
|  | 7 | +import org.gradle.api.file.ConfigurableFileCollection | 
|  | 8 | +import org.gradle.api.file.DirectoryProperty | 
|  | 9 | +import org.gradle.api.tasks.* | 
|  | 10 | +import org.gradle.work.* | 
|  | 11 | + | 
|  | 12 | +/** | 
|  | 13 | + * Incrementally scans compiled classes for @Plug usage and writes discovered plug classes into an | 
|  | 14 | + * output directory. | 
|  | 15 | + */ | 
|  | 16 | +@CacheableTask | 
|  | 17 | +abstract class FindPlugsTask : DefaultTask() { | 
|  | 18 | +	@get:CompileClasspath | 
|  | 19 | +	@get:Incremental | 
|  | 20 | +	@get:InputFiles | 
|  | 21 | +	abstract val classesFolders: ConfigurableFileCollection | 
|  | 22 | + | 
|  | 23 | +	/** Directory where we will store discovered plugs in .txt files, etc. */ | 
|  | 24 | +	@get:OutputDirectory abstract val discoveredPlugsDir: DirectoryProperty | 
|  | 25 | + | 
|  | 26 | +	@TaskAction | 
|  | 27 | +	fun findPlugs(inputChanges: InputChanges) { | 
|  | 28 | +		// If not incremental, clear everything and rescan | 
|  | 29 | +		if (!inputChanges.isIncremental) { | 
|  | 30 | +			discoveredPlugsDir.get().asFile.deleteRecursively() | 
|  | 31 | +		} | 
|  | 32 | + | 
|  | 33 | +		// Make sure our output directory exists | 
|  | 34 | +		discoveredPlugsDir.get().asFile.mkdirs() | 
|  | 35 | + | 
|  | 36 | +		// For each changed file in classesFolders, determine if it has @Plug | 
|  | 37 | +		for (change in inputChanges.getFileChanges(classesFolders)) { | 
|  | 38 | +			if (!change.file.name.endsWith(".class")) { | 
|  | 39 | +				continue | 
|  | 40 | +			} | 
|  | 41 | +			when (change.changeType) { | 
|  | 42 | +				ChangeType.REMOVED -> { | 
|  | 43 | +					// Remove old discovered data for this file | 
|  | 44 | +					removeOldMetadata(change.file) | 
|  | 45 | +				} | 
|  | 46 | +				ChangeType.ADDED, | 
|  | 47 | +				ChangeType.MODIFIED -> { | 
|  | 48 | +					parseAndWriteMetadata(change.file) | 
|  | 49 | +				} | 
|  | 50 | +			} | 
|  | 51 | +		} | 
|  | 52 | +	} | 
|  | 53 | + | 
|  | 54 | +	private fun parseAndWriteMetadata(classFile: File) { | 
|  | 55 | +		val parser = PlugParser() | 
|  | 56 | +		parser.parse(classFile) | 
|  | 57 | +		if (parser.hasPlug()) { | 
|  | 58 | +			// For example: write a single line containing the discovered plug FQN | 
|  | 59 | +			val discoveredFile = discoveredPlugsDir.file(parser.plugClassName + ".txt").get().asFile | 
|  | 60 | +			discoveredFile.parentFile.mkdirs() | 
|  | 61 | +			discoveredFile.writeText( | 
|  | 62 | +					parser.plugClassName!! + "|" + parser.socketClassName!!, StandardCharsets.UTF_8) | 
|  | 63 | +		} else { | 
|  | 64 | +			// If previously discovered, remove it | 
|  | 65 | +			removeOldMetadata(classFile) | 
|  | 66 | +		} | 
|  | 67 | +	} | 
|  | 68 | + | 
|  | 69 | +	private fun removeOldMetadata(classFile: File) { | 
|  | 70 | +		// Remove any discovered file for the old .class | 
|  | 71 | +		val possibleName = classFile.nameWithoutExtension + ".txt" | 
|  | 72 | +		val discoveredFile = discoveredPlugsDir.file(possibleName).get().asFile | 
|  | 73 | +		if (discoveredFile.exists()) { | 
|  | 74 | +			discoveredFile.delete() | 
|  | 75 | +		} | 
|  | 76 | +	} | 
|  | 77 | +} | 
0 commit comments