概览
- 前端检查
- ir生成
- recompose判断
常见注解
- @Composable
- @ComposeCompilerApi
- @InternalComposeApi
- @DisallowComposableCalls
- @ReadOnlyComposable
- @NonRestartableComposable
- @StableMarker
- @Immutable
- @Stable
1. Frontend checker
- ComposableCallChecker : 检查是否可以调用 @Composable 函数
- ComposableDeclarationChecker : 检查 @Composable 的位置是否正确
- ComposableTargetChecker
- ComposeDiagnosticSuppressor : 屏蔽不必要的编译诊断错误
2. IRCodeLower
Lowering 是编译原理中的概念,在编译过程的每一步,使用不同的 Lower 来来逐步删除高级特征,并生成更低级别特征的 IR。这样做足够多次,最终你会得到一个足够简单的IR,可以编译到汇编级
ComposeIrGenerationExtension.kt
class ComposeIrGenerationExtension(...) : IrGenerationExtension {
override fun generate(moduleFragment: IrModuleFragment,pluginContext: IrPluginContext) {
ClassStabilityTransformer(pluginContext,//..)
.lower(moduleFragment)
LiveLiteralTransformer( pluginContext, //..)
.lower(moduleFragment)
ComposableFunInterfaceLowering(pluginContext)
.lower(moduleFragment)
// Memoize normal lambdas and wrap composable lambdas
ComposerLambdaMemoization( pluginContext, //..)
.lower(moduleFragment)
CopyDefaultValuesFromExpectLowering()
.lower(moduleFragment)
if (decoysEnabled) { }
// transform all composable functions to have an extra synthetic composer
// parameter. this will also transform all types and calls to include the extra
// parameter.
ComposerParamTransformer(pluginContext, //..)
.lower(moduleFragment)
ComposableTargetAnnotationsTransformer(pluginContext,//..)
.lower(moduleFragment)
// transform calls to the currentComposer to just use the local parameter from the
// previous transform
ComposerIntrinsicTransformer(pluginContext, decoysEnabled)
.lower(moduleFragment)
ComposableFunctionBodyTransformer(pluginContext,//..)
.lower(moduleFragment)
if (decoysEnabled) { }
if (isKlibTarget) { }
if (pluginContext.platform.isJs()) {}
}
}2.1 ClassStabilityTransformer
判断类型稳定性, 为 Class 添加@StabilityInferred 注解, 并为 Class 生成 $stable 静态变量,服务于 Stability.Runtime 的代码生成。(用于后续compose判断重组代码生成)
2.2 LiveLiteralTransformer
将常量文字表达式转换为读取 MutableState 实例的表达式,以便无需重新编译即可将对常量文字源代码的更改传达给运行时。 这种转变旨在改善开发人员体验,永远不应在发布版本中启用,因为它会显着放慢对性能敏感的代码
在gradle的ComposeOption中 使用useLiveLiterals开启/关闭
//file: Foo.kt origin
fun Foo() {
print("Hello World")
}
//file: Foo.kt into
fun Foo() {
print(LiveLiterals$FooKt.getString$arg-0$call-print$fun-Foo())
}
object LiveLiterals$FooKt {
var String$arg-0$call-print$fun-Foo: String = "Hello World"
var State$String$arg-0$call-print$fun-Foo: MutableState<String>? = null
fun getString$arg-0$call-print$fun-Foo(): String {
val field = this.String$arg-0$call-print$fun-Foo
val state = if (field == null) {
val tmp = liveLiteral(
"String$arg-0$call-print$fun-Foo",
this.String$arg-0$call-print$fun-Foo
)
this.String$arg-0$call-print$fun-Foo = tmp
tmp
} else field
return field.value
}
}2.3 ComposableFunInterfaceLowering
2.4 ComposerLambdaMemoization
2.5 CopyDefaultValuesFromExpectLowering
2.6 ComposerParamTransformer
为@Composable 函数增加 $compsoer 等参数
@Composable
fun Counter() {
//..
}
//转换成
@Composable
fun Counter($composer:Composer, $changed: Int) {
//...
}源码部分
// 1.添加$composer参数
val composerParam = fn.addValueParameter {
name = KtxNameConventions.COMPOSER_PARAMETER
type = composerType.makeNullable()
origin = IrDeclarationOrigin.DEFINED
isAssignable = true
}
// 2.添加$changed[n]参数
val changed = KtxNameConventions.CHANGED_PARAMETER.identifier
for (i in 0 until changedParamCount(realParams, fn.thisParamCount)) {
fn.addValueParameter(
if (i == 0) changed else "$changed$i",
context.irBuiltIns.intType
)
}
// 3.添加$default[n]参数
if (oldFn.requiresDefaultParameter()) {
val defaults = KtxNameConventions.DEFAULT_PARAMETER.identifier
for (i in 0 until defaultParamCount(currentParams)) {
fn.addValueParameter(
if (i == 0) defaults else "$defaults$i",
context.irBuiltIns.intType,
IrDeclarationOrigin.MASK_FOR_DEFAULT_FUNCTION
)
}
}2.7 ComposableTargetAnnotationsTransformer
2.8 ComposerIntrinsicTransformer
2.9 ComposableFunctionBodyTransformer
非常复杂的一个trasnfromer, Composable 函数体内生成 startXXXGroup/endXXXGroup/recompose 等相关代码

/**
* This IR Transform is responsible for the main transformations of the body of a composable
* function.
*
* 1. Control-Flow Group Generation
* 2. Default arguments
* 3. Composable Function Skipping
* 4. Comparison Propagation
* 5. Recomposability
* 6. Source location information (when enabled)
*