From 76df8fa06cc348371fad8b8e7c3712118d21f2a5 Mon Sep 17 00:00:00 2001 From: fankesyooni Date: Sat, 23 Aug 2025 22:39:35 +0800 Subject: [PATCH] feat: add final param in HikageView, HikageViewDeclaration --- docs-source/src/en/library/hikage-compiler.md | 28 ++++++++++--------- .../src/zh-cn/library/hikage-compiler.md | 28 ++++++++++--------- .../subprocessor/HikageViewGenerator.kt | 15 ++++++---- .../hikage/annotation/HikageView.kt | 6 +++- .../annotation/HikageViewDeclaration.kt | 6 +++- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/docs-source/src/en/library/hikage-compiler.md b/docs-source/src/en/library/hikage-compiler.md index 6c17c13..39f8384 100644 --- a/docs-source/src/en/library/hikage-compiler.md +++ b/docs-source/src/en/library/hikage-compiler.md @@ -139,12 +139,13 @@ Hikage can automatically generate the `Hikageable` function corresponding to the You can add the `HikageView` annotation on your custom `View` to mark it as a Hikage layout component. -| Parameter Name | Description | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `lparams` | LayoutParams `Class` object, if your custom `View` is a subclass of `ViewGroup`, you can declare or leave it blank to use the default value | -| `alias` | The alias of the layout component, that is, the function name to be generated, gets the name of the current Class by default | -| `requireInit` | Whether to fill in the initialization method block of the layout, the default is the omitted parameters | -| `requirePerformer` | Whether to fill in the `performer` method block of the layout, the default is an omitted parameter, which only takes effect when your custom `View` is a subclass of `ViewGroup` | +| Parameter Name | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `lparams` | LayoutParams `Class` object, if your custom `View` is a subclass of `ViewGroup`, you can declare or leave it blank to use the default value | +| `alias` | The alias of the layout component, that is, the function name to be generated, gets the name of the current Class by default | +| `requireInit` | Whether to fill in the initialization method block of the layout, the default is the omitted parameters | +| `requirePerformer` | Whether to fill in the `performer` method block of the layout, the default is an omitted parameter, which only takes effect when your custom `View` is a subclass of `ViewGroup` | +| `final` | Whether to declare the layout as "final layout", the default is false, that is, whether this layout is `ViewGroup` or its subclasses will not generate the `performer` method block. After set to `true`, `lparams` and `requirePerformer` will no longer be valid. | > The following example @@ -177,13 +178,14 @@ Hikageable { Hikage can also automatically generate layout component functions for the `View` component provided by third parties, and you can use the `HikageViewDeclaration` annotation to complete it. -| Parameter Name | Description | -| ------------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -| `view` | Class object of layout component that needs to be declared | -| `lparams` | LayoutParams `Class` object, if your custom `View` is a subclass of `ViewGroup`, you can declare or leave it blank to use the default value | -| `alias` | The alias of the layout component, that is, the name of the function to be generated, obtains the name of the `view` Class by default | -| `requireInit` | Whether to fill in the initialization method block of the layout, the default is the omitted parameters | -| `requirePerformer` | Whether to fill in the `performer` method block of the layout, the default is an omitted parameter, which only takes effect when your custom `View` is a subclass of `ViewGroup` | +| Parameter Name | Description | +| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `view` | Class object of layout component that needs to be declared | +| `lparams` | LayoutParams `Class` object, if your custom `View` is a subclass of `ViewGroup`, you can declare or leave it blank to use the default value | +| `alias` | The alias of the layout component, that is, the name of the function to be generated, obtains the name of the `view` Class by default | +| `requireInit` | Whether to fill in the initialization method block of the layout, the default is the omitted parameters | +| `requirePerformer` | Whether to fill in the `performer` method block of the layout, the default is an omitted parameter, which only takes effect when your custom `View` is a subclass of `ViewGroup` | +| `final` | Whether to declare the layout as "final layout", the default is false, that is, whether this layout is `ViewGroup` or its subclasses will not generate the `performer` method block. After set to `true`, `lparams` and `requirePerformer` will no longer be valid. | > The following example diff --git a/docs-source/src/zh-cn/library/hikage-compiler.md b/docs-source/src/zh-cn/library/hikage-compiler.md index 5f80584..7f0c217 100644 --- a/docs-source/src/zh-cn/library/hikage-compiler.md +++ b/docs-source/src/zh-cn/library/hikage-compiler.md @@ -136,12 +136,13 @@ Hikage 可以在编译时为指定的布局组件自动生成布局组件对应 你可以在你的自定义 `View` 上加入 `HikageView` 注解,以标记它生成为 Hikage 布局组件。 -| 参数名称 | 描述 | -| ------------------ | --------------------------------------------------------------------------------------------------------------------- | -| `lparams` | 布局参数 `ViewGroup.LayoutParams` Class 对象,如果你的自定义 `View` 是 `ViewGroup` 的子类,则可以声明或留空使用默认值 | -| `alias` | 布局组件的别名,即要生成的函数名称,默认获取当前 Class 的名称 | -| `requireInit` | 是否要求填写布局的初始化方法块,默认为可省略的参数 | -| `requirePerformer` | 是否要求填写布局的 `performer` 方法块,默认为可省略的参数,仅在你的自定义 `View` 是 `ViewGroup` 的子类时生效 | +| 参数名称 | 描述 | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `lparams` | 布局参数 `ViewGroup.LayoutParams` Class 对象,如果你的自定义 `View` 是 `ViewGroup` 的子类,则可以声明或留空使用默认值 | +| `alias` | 布局组件的别名,即要生成的函数名称,默认获取当前 Class 的名称 | +| `requireInit` | 是否要求填写布局的初始化方法块,默认为可省略的参数 | +| `requirePerformer` | 是否要求填写布局的 `performer` 方法块,默认为可省略的参数,仅在你的自定义 `View` 是 `ViewGroup` 的子类时生效 | +| `final` | 是否将布局声明为 “最终布局”,默认否,即此布局是否是 `ViewGroup` 还是从其继承都将不会生成 `performer` 方法块,设置为 `true` 之后,`lparams` 和 `requirePerformer` 将不再有效。 | > 示例如下 @@ -174,13 +175,14 @@ Hikageable { Hikage 同样可以为第三方提供的 `View` 组件自动生成布局组件函数,你可以使用 `HikageViewDeclaration` 注解来完成。 -| 参数名称 | 描述 | -| ------------------ | --------------------------------------------------------------------------------------------------------------------- | -| `view` | 需要声明的布局组件的 Class 对象 | -| `lparams` | 布局参数 `ViewGroup.LayoutParams` Class 对象,如果你的自定义 `View` 是 `ViewGroup` 的子类,则可以声明或留空使用默认值 | -| `alias` | 布局组件的别名,即要生成的函数名称,默认获取 `view` Class 的名称 | -| `requireInit` | 是否要求填写布局的初始化方法块,默认为可省略的参数 | -| `requirePerformer` | 是否要求填写布局的 `performer` 方法块,默认为可省略的参数,仅在你的自定义 `View` 是 `ViewGroup` 的子类时生效 | +| 参数名称 | 描述 | +| ------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `view` | 需要声明的布局组件的 Class 对象 | +| `lparams` | 布局参数 `ViewGroup.LayoutParams` Class 对象,如果你的自定义 `View` 是 `ViewGroup` 的子类,则可以声明或留空使用默认值 | +| `alias` | 布局组件的别名,即要生成的函数名称,默认获取 `view` Class 的名称 | +| `requireInit` | 是否要求填写布局的初始化方法块,默认为可省略的参数 | +| `requirePerformer` | 是否要求填写布局的 `performer` 方法块,默认为可省略的参数,仅在你的自定义 `View` 是 `ViewGroup` 的子类时生效 | +| `final` | 是否将布局声明为 “最终布局”,默认否,即此布局是否是 `ViewGroup` 还是从其继承都将不会生成 `performer` 方法块,设置为 `true` 之后,`lparams` 和 `requirePerformer` 将不再有效。 | > 示例如下 diff --git a/hikage-compiler/src/main/java/com/highcapable/hikage/compiler/subprocessor/HikageViewGenerator.kt b/hikage-compiler/src/main/java/com/highcapable/hikage/compiler/subprocessor/HikageViewGenerator.kt index f57366b..ce8ef12 100644 --- a/hikage-compiler/src/main/java/com/highcapable/hikage/compiler/subprocessor/HikageViewGenerator.kt +++ b/hikage-compiler/src/main/java/com/highcapable/hikage/compiler/subprocessor/HikageViewGenerator.kt @@ -211,7 +211,7 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) if (!performer.annotation.requireInit) defaultValue("{}") }.build() ) - lparamsClass?.second?.let { + lparamsClass?.second?.takeIf { !performer.annotation.final }?.let { addParameter( ParameterSpec.builder( name = "performer", @@ -343,7 +343,8 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) override val lparams: KSClassDeclaration?, override val alias: String?, override val requireInit: Boolean, - override val requirePerformer: Boolean + override val requirePerformer: Boolean, + override val final: Boolean ) : HikageAnnotationSpec { companion object { @@ -360,12 +361,13 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) val alias = annotation.arguments.getOrNull("alias") val requireInit = annotation.arguments.getOrNull("requireInit") ?: false val requirePerformer = annotation.arguments.getOrNull("requirePerformer") ?: false + val final = annotation.arguments.getOrNull("final") ?: false // Solve the actual content of the annotation parameters. val declaration = Processor.createViewDeclaration(NAME, alias, ksClass) val resolvedLparams = Processor.resolvedLparamsDeclaration(NAME, resolver, declaration, lparams) - return HikageViewSpec(resolvedLparams, alias, requireInit, requirePerformer) to declaration + return HikageViewSpec(resolvedLparams, alias, requireInit, requirePerformer, final) to declaration } } } @@ -375,7 +377,8 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) override val lparams: KSClassDeclaration?, override val alias: String?, override val requireInit: Boolean, - override val requirePerformer: Boolean + override val requirePerformer: Boolean, + override val final: Boolean ) : HikageAnnotationSpec { companion object { @@ -393,6 +396,7 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) val alias = annotation.arguments.getOrNull("alias") val requireInit = annotation.arguments.getOrNull("requireInit") ?: false val requirePerformer = annotation.arguments.getOrNull("requirePerformer") ?: false + val final = annotation.arguments.getOrNull("final") ?: false // Solve the actual content of the annotation parameters. val resolvedView = view?.declaration?.getClassDeclaration(resolver) ?: error("Internal error.") @@ -407,7 +411,7 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) } val resolvedLparams = Processor.resolvedLparamsDeclaration(NAME, resolver, declaration, lparams) - return HikageViewDeclarationSpec(resolvedView, resolvedLparams, alias, requireInit, requirePerformer) to declaration + return HikageViewDeclarationSpec(resolvedView, resolvedLparams, alias, requireInit, requirePerformer, final) to declaration } } } @@ -417,6 +421,7 @@ class HikageViewGenerator(override val environment: SymbolProcessorEnvironment) val alias: String? val requireInit: Boolean val requirePerformer: Boolean + val final: Boolean } private data class Performer( diff --git a/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageView.kt b/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageView.kt index 29c277b..04536ee 100644 --- a/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageView.kt +++ b/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageView.kt @@ -45,6 +45,9 @@ import kotlin.reflect.KClass * @param requireInit whether to force the `init` parameter to be called, default is false. * @param requirePerformer whether to force the `performer` parameter to be called, default is false, * this parameter will be ignored when no `performer` parameter is needed here. + * @param final whether to declare this layout as "final layout", default is false, that is, + * whether this layout inherits from or is [ViewGroup], the `performer` parameter will not be generated. + * After set to `true`, [lparams] and [requirePerformer] will no longer be valid. */ @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS) @@ -53,5 +56,6 @@ annotation class HikageView( val lparams: KClass<*> = Any::class, val alias: String = "", val requireInit: Boolean = false, - val requirePerformer: Boolean = false + val requirePerformer: Boolean = false, + val final: Boolean = false ) \ No newline at end of file diff --git a/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageViewDeclaration.kt b/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageViewDeclaration.kt index 4f0f6bc..b95acb9 100644 --- a/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageViewDeclaration.kt +++ b/hikage-core/src/main/java/com/highcapable/hikage/annotation/HikageViewDeclaration.kt @@ -48,6 +48,9 @@ import kotlin.reflect.KClass * @param requireInit whether to force the `init` parameter to be called, default is false. * @param requirePerformer whether to force the `performer` parameter to be called, default is false, * this parameter will be ignored when no `performer` parameter is needed here. + * @param final whether to declare this layout as "final layout", default is false, that is, + * whether this layout inherits from or is [ViewGroup], the `performer` parameter will not be generated. + * After set to `true`, [lparams] and [requirePerformer] will no longer be valid. */ @Retention(AnnotationRetention.BINARY) @Target(AnnotationTarget.CLASS) @@ -57,5 +60,6 @@ annotation class HikageViewDeclaration( val lparams: KClass<*> = Any::class, val alias: String = "", val requireInit: Boolean = false, - val requirePerformer: Boolean = false + val requirePerformer: Boolean = false, + val final: Boolean = false ) \ No newline at end of file