Skip to content

Commit

Permalink
refactor(core.transform-kit): 简化代码,并剥离对旧Transform API的依赖到Wrapper类
Browse files Browse the repository at this point in the history
ClassTransform是抽象的,它不知道字节码编辑工具是Javassist,也不知道Transform框架是AGP的还是Gradle的。
它定义了TransformInput,由外部Transform框架的适配器(如DeprecatedTransformWrapper)将外部Transform
框架的输入适配进来。

TransformInput支持DIR和JAR两种输入,对应ClassTransform.input中通过TransformInput拿到输入的class文件或
jar文件,然后交给loadDotClassFile和loadClassFromJar两个抽象方法加载类到字节码编辑框架中。
input同时将加载的类名记录到TransformInput.getInputClassNames中,以便output时知道该输出哪些类。
注意1个TransformInput对应多个Class。

此次简化去掉了InputClass类。这个类之前主要的作用是记录每个输入的class对应的输出文件。
这个输出文件其实不需要逐个记录路径或者entryname,可以由类名自己拼接出来。
所以这次简化改为了在output时再根据classname生成文件路径和entryname。

将ctClassInputMap: Map<CtClass, InputClass>改为allInputCtClass: Set<CtClass>
,去掉renameOutput方法,都是因为早在 f1d0f5b 引入新的Fragment支持方案时,
就不再需要修改输出类名。也就是现在所有Transform操作都不会影响输入的类名,也不会增加或减少类。
因此不再需要将控制输出文件的InputClass传给TransformManager。

最后将对已经Deprecated,即将在AGP 8中删除的Transform API的依赖代码都移到DeprecatedTransformWrapper中。

#1212
  • Loading branch information
shifujun committed Dec 5, 2023
1 parent e83adb1 commit 73586b8
Show file tree
Hide file tree
Showing 8 changed files with 285 additions and 279 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.android.build.gradle.api.ApplicationVariant
import com.android.sdklib.AndroidVersion.VersionCodes
import com.tencent.shadow.core.gradle.extensions.PackagePluginExtension
import com.tencent.shadow.core.manifest_parser.generatePluginManifest
import com.tencent.shadow.core.transform.DeprecatedTransformWrapper
import com.tencent.shadow.core.transform.ShadowTransform
import com.tencent.shadow.core.transform_kit.AndroidClassPoolBuilder
import com.tencent.shadow.core.transform_kit.ClassPoolBuilder
Expand Down Expand Up @@ -51,11 +52,15 @@ class ShadowPlugin : Plugin<Project> {

val shadowExtension = project.extensions.create("shadow", ShadowExtension::class.java)
if (!project.hasProperty("disable_shadow_transform")) {
baseExtension.registerTransform(ShadowTransform(
project,
lateInitBuilder,
{ shadowExtension.transformConfig.useHostContext }
))
baseExtension.registerTransform(
DeprecatedTransformWrapper(project,
ShadowTransform(
project,
lateInitBuilder,
{ shadowExtension.transformConfig.useHostContext }
)
)
)
}

addFlavorForTransform(baseExtension)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,15 @@

package com.tencent.shadow.core.transform_kit

import com.android.build.api.transform.TransformInvocation
import javassist.ClassPool
import javassist.CtClass
import org.gradle.api.Project
import java.io.*
import java.io.BufferedWriter
import java.io.DataOutputStream
import java.io.File
import java.io.FileOutputStream
import java.io.FileWriter
import java.io.OutputStream
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import kotlin.system.measureTimeMillis
Expand All @@ -46,8 +50,8 @@ abstract class AbstractTransform(
mDebugClassJarZOS = ZipOutputStream(FileOutputStream(mDebugClassJar))
}

override fun beforeTransform(invocation: TransformInvocation) {
super.beforeTransform(invocation)
override fun beforeTransform() {
super.beforeTransform()
ReplaceClassName.resetErrorCount()
cleanDebugClassFileDir()
}
Expand All @@ -57,12 +61,12 @@ abstract class AbstractTransform(
//原本预期是不会产生任何影响的。造成了ApplicationInfoTest失败,测试Activity没有被修改superclass。
// mOverrideCheck.prepare(mCtClassInputMap.keys.toSet())

mTransformManager.setupAll()
mTransformManager.fireAll()
mTransformManager.setupAll(allInputCtClass)
mTransformManager.fireAll(allInputCtClass)
}

override fun afterTransform(invocation: TransformInvocation) {
super.afterTransform(invocation)
override fun afterTransform() {
super.afterTransform()

mDebugClassJarZOS.flush()
mDebugClassJarZOS.close()
Expand All @@ -71,18 +75,18 @@ abstract class AbstractTransform(
//所以需要重新创建一个ClassPool,加载转换后的类,用于各种转换后的检查。
val debugClassPool = classPoolBuilder.build()
debugClassPool.appendClassPath(mDebugClassJar.absolutePath)
val inputClassNames = mCtClassInputMap.keys.map { it.name }
val inputClassNames = allInputCtClass.map { it.name }
onCheckTransformedClasses(debugClassPool, inputClassNames)
}

override fun onOutputClass(entryName: String?, className: String, outputStream: OutputStream) {
classPool[className].debugWriteJar(entryName, mDebugClassJarZOS)
super.onOutputClass(entryName, className, outputStream)
override fun onOutputClass(className: String, outputStream: OutputStream) {
classPool[className].debugWriteJar(mDebugClassJarZOS)
super.onOutputClass(className, outputStream)
}

private fun CtClass.debugWriteJar(outputEntryName: String?, outputStream: ZipOutputStream) {
private fun CtClass.debugWriteJar(outputStream: ZipOutputStream) {
try {
val entryName = outputEntryName ?: (name.replace('.', '/') + ".class")
val entryName = name.replace('.', '/') + ".class"
outputStream.putNextEntry(ZipEntry(entryName))
val p = stopPruning(true)
toBytecode(DataOutputStream(outputStream))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,24 +21,19 @@ package com.tencent.shadow.core.transform_kit
import javassist.ClassPool
import javassist.CtClass

abstract class AbstractTransformManager(
ctClassInputMap: Map<CtClass, InputClass>,
private val classPool: ClassPool
) {
private val allInputClass = ctClassInputMap.keys

abstract class AbstractTransformManager(private val classPool: ClassPool) {
abstract val mTransformList: List<SpecificTransform>

fun setupAll() {
fun setupAll(allInputCtClass: Set<CtClass>) {
mTransformList.forEach {
it.mClassPool = classPool
it.setup(allInputClass)
it.setup(allInputCtClass)
}
}

fun fireAll() {
fun fireAll(allInputCtClass: Set<CtClass>) {
mTransformList.flatMap { it.list }.forEach { transform ->
transform.filter(allInputClass).forEach {
transform.filter(allInputCtClass).forEach {
transform.transform(it)
}
}
Expand Down
Loading

0 comments on commit 73586b8

Please sign in to comment.