Skip to content

Commit 8b96ea0

Browse files
committed
More speedup by reusing the parser buffer.
1 parent bba5c30 commit 8b96ea0

File tree

3 files changed

+34
-44
lines changed

3 files changed

+34
-44
lines changed

atplug-plugin-gradle/src/main/java/com/diffplug/atplug/tooling/PlugParser.kt

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ import org.objectweb.asm.Type
2626
class PlugParser {
2727
private var buffer = ByteArray(64 * 1024)
2828

29-
fun parse(file: File) {
29+
fun parse(file: File): Pair<String, String>? {
3030
val filelen = (file.length() + 1).toInt() // +1 prevents infinite loop
3131
if (buffer.size < filelen) {
3232
buffer = ByteArray(filelen)
@@ -42,18 +42,17 @@ class PlugParser {
4242
}
4343
}
4444
val reader = ClassReader(buffer, 0, pos)
45-
plugClassName = asmToJava(reader.className)
45+
val plugClassName = asmToJava(reader.className)
46+
this.plugClassName = plugClassName
4647
socketClassName = null
48+
// set socketClassName if there is an `@Plug`
4749
reader.accept(
4850
classVisitor, ClassReader.SKIP_FRAMES or ClassReader.SKIP_DEBUG or ClassReader.SKIP_CODE)
51+
return socketClassName?.let { plugClassName to it }
4952
}
5053

51-
fun hasPlug(): Boolean {
52-
return socketClassName != null
53-
}
54-
55-
var plugClassName: String? = null
56-
var socketClassName: String? = null
54+
private var plugClassName: String? = null
55+
private var socketClassName: String? = null
5756

5857
private val classVisitor: ClassVisitor =
5958
object : ClassVisitor(API) {
@@ -73,7 +72,7 @@ class PlugParser {
7372
}
7473

7574
companion object {
76-
fun asmToJava(className: String): String {
75+
private fun asmToJava(className: String): String {
7776
return className.replace("/", ".")
7877
}
7978

atplug-plugin-gradle/src/main/java/com/diffplug/atplug/tooling/gradle/FindPlugsTask.kt

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package com.diffplug.atplug.tooling.gradle
22

33
import com.diffplug.atplug.tooling.PlugParser
44
import java.io.File
5-
import java.nio.charset.StandardCharsets
65
import org.gradle.api.DefaultTask
76
import org.gradle.api.file.ConfigurableFileCollection
87
import org.gradle.api.file.DirectoryProperty
@@ -20,7 +19,7 @@ abstract class FindPlugsTask : DefaultTask() {
2019
@get:InputFiles
2120
abstract val classesFolders: ConfigurableFileCollection
2221

23-
/** Directory where we will store discovered plugs in .txt files, etc. */
22+
/** Directory where we will store discovered plugs. */
2423
@get:OutputDirectory abstract val discoveredPlugsDir: DirectoryProperty
2524

2625
@TaskAction
@@ -34,6 +33,7 @@ abstract class FindPlugsTask : DefaultTask() {
3433
discoveredPlugsDir.get().asFile.mkdirs()
3534

3635
// For each changed file in classesFolders, determine if it has @Plug
36+
val parser = PlugParser()
3737
for (change in inputChanges.getFileChanges(classesFolders)) {
3838
if (!change.file.name.endsWith(".class")) {
3939
continue
@@ -45,21 +45,26 @@ abstract class FindPlugsTask : DefaultTask() {
4545
}
4646
ChangeType.ADDED,
4747
ChangeType.MODIFIED -> {
48-
parseAndWriteMetadata(change.file)
48+
parseAndWriteMetadata(parser, change.file)
4949
}
5050
}
5151
}
5252
}
5353

54-
private fun parseAndWriteMetadata(classFile: File) {
55-
val parser = PlugParser()
56-
parser.parse(classFile)
57-
if (parser.hasPlug()) {
54+
private fun parseAndWriteMetadata(parser: PlugParser, classFile: File) {
55+
val plugToSocket = parser.parse(classFile)
56+
if (plugToSocket != null) {
5857
// 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)
58+
val discoveredFile = discoveredPlugsDir.file(classFile.nameWithoutExtension).get().asFile
59+
if (discoveredFile.exists()) {
60+
val existing = discoveredFile.readText().split("|")
61+
check(existing[0] == plugToSocket.first) {
62+
"You need to rename one of these plugs because they have the same classfile name: ${existing[0]} and $plugToSocket"
63+
}
64+
} else {
65+
discoveredFile.parentFile.mkdirs()
66+
}
67+
discoveredFile.writeText(plugToSocket.let { "${it.first}|${it.second}" })
6368
} else {
6469
// If previously discovered, remove it
6570
removeOldMetadata(classFile)
@@ -68,7 +73,7 @@ abstract class FindPlugsTask : DefaultTask() {
6873

6974
private fun removeOldMetadata(classFile: File) {
7075
// Remove any discovered file for the old .class
71-
val possibleName = classFile.nameWithoutExtension + ".txt"
76+
val possibleName = classFile.nameWithoutExtension
7277
val discoveredFile = discoveredPlugsDir.file(possibleName).get().asFile
7378
if (discoveredFile.exists()) {
7479
discoveredFile.delete()

atplug-plugin-gradle/src/main/java/com/diffplug/atplug/tooling/gradle/PlugGenerateTask.kt

Lines changed: 9 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -73,34 +73,20 @@ abstract class PlugGenerateTask : DefaultTask() {
7373

7474
@TaskAction
7575
fun build() {
76-
// 1) Collect the discovered classes
77-
val discoveredFiles =
78-
discoveredPlugsDir.get().asFile.listFiles().orEmpty().filter {
79-
it.isFile && it.name.endsWith(".txt")
76+
val discoveredFiles = discoveredPlugsDir.get().asFile.listFiles().orEmpty().filter { it.isFile }
77+
val plugsToSockets =
78+
discoveredFiles.associate {
79+
val pieces = it.readText().split("|")
80+
pieces[0] to pieces[1]
8081
}
81-
82-
// Turn them into a list of (plugClass, socketClass)
83-
val discoveredPlugs =
84-
discoveredFiles
85-
.map { file ->
86-
val line = file.readText(StandardCharsets.UTF_8).trim()
87-
val split = line.split("|")
88-
check(split.size == 2) { "Malformed discovered line in ${file.name}: '$line'" }
89-
val (plugClassName, socketClassName) = split
90-
plugClassName to socketClassName
91-
}
92-
.toMap()
93-
94-
// 2) Use reflection logic, now that we have jarsToLinkAgainst, to produce final metadata
95-
// This is where you'd adapt the old PlugGenerator invocation, but no scanning is needed
96-
if (discoveredPlugs.isEmpty()) {
82+
if (plugsToSockets.isEmpty()) {
9783
// no discovered plugs
9884
FileMisc.cleanDir(atplugInfFolder)
9985
return
10086
}
10187

10288
// generate the metadata
103-
val result = generate(discoveredPlugs)
89+
val result = generate(plugsToSockets)
10490

10591
// clean out the ATPLUG-INF folder, and put the map's content into the folder
10692
FileMisc.cleanDir(atplugInfFolder)
@@ -110,8 +96,8 @@ abstract class PlugGenerateTask : DefaultTask() {
11096
}
11197

11298
// the resources directory *needs* the Service-Component entry of the manifest to exist in order
113-
// for tests to work
114-
// so we'll get a manifest (empty if necessary, but preferably we'll load what already exists)
99+
// for tests to work so we'll get a manifest (empty if necessary, but preferably we'll load what
100+
// already exists)
115101
val manifest = loadManifest()
116102
val componentsCmd = atplugComponents(atplugInfFolder)
117103
val componentsActual = manifest.mainAttributes.getValue(PlugPlugin.SERVICE_COMPONENT)

0 commit comments

Comments
 (0)