Skip to content

Commit b2199eb

Browse files
committed
refactor(resource): add subclass opt-in annotation for Resource interfaces
1 parent 654371b commit b2199eb

File tree

7 files changed

+73
-21
lines changed

7 files changed

+73
-21
lines changed

simbot-api/api/simbot-api.api

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2608,6 +2608,9 @@ public final class love/forte/simbot/resource/ResourceBase64Serializer : kotlinx
26082608
public fun serialize (Lkotlinx/serialization/encoding/Encoder;Llove/forte/simbot/resource/Resource;)V
26092609
}
26102610

2611+
public abstract interface annotation class love/forte/simbot/resource/ResourceImplementation : java/lang/annotation/Annotation {
2612+
}
2613+
26112614
public abstract interface class love/forte/simbot/resource/ResourceResolver {
26122615
public static final field Companion Llove/forte/simbot/resource/ResourceResolver$Companion;
26132616
public static fun resolve (Llove/forte/simbot/resource/ResourceResolver;Llove/forte/simbot/resource/Resource;Ljava/lang/Object;)V

simbot-api/build.gradle.kts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,9 @@ kotlin {
6767
freeCompilerArgs.addAll(
6868
"-Xexpect-actual-classes"
6969
)
70+
optIn.add(
71+
"love.forte.simbot.resource.ResourceImplementation"
72+
)
7073
}
7174

7275
sourceSets {

simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/Resource.kt

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* Project https://github.com/simple-robot/simpler-robot
55
@@ -65,7 +65,8 @@ import kotlin.jvm.JvmName
6565
*
6666
* ## 第三方实现不稳定
6767
*
68-
* [Resource] 主要由内部实现,不保证对第三方实现的稳定与兼容
68+
* [Resource] 主要由内部实现,不保证对第三方实现的稳定与兼容。
69+
* 参考 [ResourceImplementation]。
6970
*
7071
* @see ByteArrayResource
7172
* @see SourceResource
@@ -94,6 +95,7 @@ public fun ByteArray.toResource(): ByteArrayResource = ByteArrayResourceImpl(thi
9495
*
9596
* @author forte
9697
*/
98+
@SubclassOptInRequired(ResourceImplementation::class)
9799
public interface ByteArrayResource : Resource, SourceResource {
98100
/**
99101
* 获取到字节数组结果。
@@ -162,6 +164,7 @@ private data class ByteArrayResourceImpl(private val raw: ByteArray) : ByteArray
162164
* 一个可以读取到 [String] 内容物的拓展类型。
163165
* 是其他 [Resource] 类型的附加能力,但不属于一个标准的 [Resource] 类型。
164166
*/
167+
@SubclassOptInRequired(ResourceImplementation::class)
165168
public interface StringReadableResource : SourceResource {
166169
/**
167170
* 读取此资源的 [String] 内容。
@@ -179,6 +182,7 @@ public interface StringReadableResource : SourceResource {
179182
/**
180183
* 直接使用 [String] 作为内容的 [Resource]。
181184
*/
185+
@SubclassOptInRequired(ResourceImplementation::class)
182186
public interface StringResource : StringReadableResource {
183187
/**
184188
* 读取此资源的 [String] 内容。
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*
2+
* Copyright (c) 2025. ForteScarlet.
3+
*
4+
* Project https://github.com/simple-robot/simpler-robot
5+
6+
*
7+
* This file is part of the Simple Robot Library (Alias: simple-robot, simbot, etc.).
8+
*
9+
* This program is free software: you can redistribute it and/or modify
10+
* it under the terms of the GNU Lesser General Public License as published by
11+
* the Free Software Foundation, either version 3 of the License, or
12+
* (at your option) any later version.
13+
*
14+
* This program is distributed in the hope that it will be useful,
15+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
* Lesser GNU General Public License for more details.
18+
*
19+
* You should have received a copy of the Lesser GNU General Public License
20+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
21+
*
22+
*/
23+
24+
package love.forte.simbot.resource
25+
26+
/**
27+
* [Resource] 的外部实现是不稳定的,[Resource] 的实现应该是内部的,目前 [Resource] 不保证第三方实现未来的稳定与兼容。
28+
*
29+
* @since 4.11.0
30+
*/
31+
@Target(AnnotationTarget.CLASS, AnnotationTarget.ANNOTATION_CLASS)
32+
@RequiresOptIn(
33+
message = "`Resource` implementation is unstable. " +
34+
"The implementation of `Resource` should be internal. " +
35+
"Currently, `Resource` does not guarantee the stability " +
36+
"and compatibility of third-party implementations in the future.",
37+
level = RequiresOptIn.Level.WARNING
38+
)
39+
@MustBeDocumented
40+
public annotation class ResourceImplementation

simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/ResourceResolver.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* Project https://github.com/simple-robot/simpler-robot
55
@@ -34,7 +34,9 @@ import kotlin.jvm.JvmStatic
3434
@RequiresOptIn(
3535
message = "计划被废弃的与 `Resource` 相关的API. 详见 " +
3636
"`love.forte.simbot.resource.ResourceResolver` 和 " +
37-
"`love.forte.simbot.resource.Resource` 中的有关说明。"
37+
"`love.forte.simbot.resource.Resource` 中的有关说明。",
38+
// since 4.11.0
39+
level = RequiresOptIn.Level.ERROR
3840
)
3941
@Retention(BINARY)
4042
@Target(CLASS, FUNCTION)

simbot-api/src/commonMain/kotlin/love/forte/simbot/resource/SourceResource.kt

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* Project https://github.com/simple-robot/simpler-robot
55
@@ -98,7 +98,7 @@ public fun fileResource(base: String, vararg parts: String): SourceResource {
9898
}
9999

100100
/**
101-
* 使用 [Path] 直接构建一个 [FilePathResource]
101+
* 使用 [Path] 直接构建一个 [KotlinIOPathResource]
102102
*
103103
* 对文件存在性的校验和错误报告可能不会立即报告,而是被推迟到真正读取数据时,
104104
* 参考 [SourceResource.source] 的可能异常。
@@ -109,7 +109,7 @@ public fun fileResource(base: String, vararg parts: String): SourceResource {
109109
*/
110110
@JvmName("valueOf")
111111
public fun Path.toResource(): SourceResource {
112-
return FilePathResource(this)
112+
return KotlinIOPathResource(this)
113113
}
114114

115115
/**
@@ -123,7 +123,7 @@ public fun Path.toResource(): SourceResource {
123123
*/
124124
@JvmName("valueOfSourceProvider")
125125
public fun sourceResource(provider: () -> Source): SourceResource {
126-
return SourceResourceImpl(provider)
126+
return SourceProviderResource(provider)
127127
}
128128

129129

@@ -138,6 +138,7 @@ public fun sourceResource(provider: () -> Source): SourceResource {
138138
*
139139
* @since 4.7.0
140140
*/
141+
@SubclassOptInRequired(ResourceImplementation::class)
141142
public interface SourceResource : Resource {
142143
/**
143144
* 得到一个用于本次数据读取的 [Source].
@@ -169,7 +170,7 @@ public interface SourceResource : Resource {
169170
override fun data(): ByteArray = source().use { it.readByteArray() }
170171
}
171172

172-
private data class FilePathResource(val path: Path) : SourceResource {
173+
private data class KotlinIOPathResource(val path: Path) : SourceResource {
173174
private val source
174175
get() = SystemFileSystem.source(path)
175176

@@ -180,6 +181,6 @@ private data class FilePathResource(val path: Path) : SourceResource {
180181
/**
181182
* @since 4.10.0
182183
*/
183-
private data class SourceResourceImpl(val provider: () -> Source) : SourceResource {
184+
private data class SourceProviderResource(val provider: () -> Source) : SourceResource {
184185
override fun source(): Source = provider()
185186
}

simbot-api/src/jvmMain/kotlin/love/forte/simbot/resource/Resource.jvm.kt

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2024. ForteScarlet.
2+
* Copyright (c) 2024-2025. ForteScarlet.
33
*
44
* Project https://github.com/simple-robot/simpler-robot
55
@@ -83,9 +83,7 @@ public sealed interface JvmSourceResource : SourceResource
8383
*
8484
* @author forte
8585
*/
86-
@Deprecated(
87-
"Just use `SourceResource.inputStream()` to get InputStream from Source"
88-
)
86+
@Deprecated("Just use `SourceResource.inputStream()` to get InputStream from Source")
8987
public interface InputStreamResource : SourceResource {
9088
/**
9189
* 获取可用于读取当前资源数据的输入流。
@@ -99,6 +97,7 @@ public interface InputStreamResource : SourceResource {
9997
* 与 [StringReadableResource] 相比,对相关方法增加了 [Charset] 参数。
10098
* 默认情况下使用 [Charsets.UTF_8] 格式编码。
10199
*/
100+
@SubclassOptInRequired(ResourceImplementation::class)
102101
public interface JvmStringReadableResource : StringReadableResource {
103102
/**
104103
* 读取此资源的 [String] 内容。
@@ -130,9 +129,7 @@ public interface JvmStringReadableResource : StringReadableResource {
130129
*
131130
* @author forte
132131
*/
133-
@Deprecated(
134-
"Just use `SourceResource.inputStream()` to get InputStream from Source"
135-
)
132+
@Deprecated("Just use `SourceResource.inputStream()` to get InputStream from Source")
136133
public interface ReaderResource : JvmStringReadableResource {
137134
/**
138135
* 读取当前资源的字符串数据。
@@ -161,6 +158,7 @@ public interface ReaderResource : JvmStringReadableResource {
161158
* @author forte
162159
*/
163160
@Suppress("DEPRECATION")
161+
@SubclassOptInRequired(ResourceImplementation::class)
164162
public interface FileResource :
165163
JvmSourceResource,
166164
InputStreamResource,
@@ -228,7 +226,7 @@ public fun File.toResource(charset: Charset = DEFAULT_CHARSET): FileResource =
228226
FileResourceImpl(this, charset)
229227

230228
private data class FileResourceImpl(override val file: File, private val charset: Charset) :
231-
FileResource, SourceResource {
229+
FileResource {
232230
override fun string(): String = string(charset)
233231
override fun reader(): Reader = reader(charset)
234232

@@ -265,6 +263,7 @@ private data class FileResourceImpl(override val file: File, private val charset
265263
* @author forte
266264
*/
267265
@Suppress("DEPRECATION")
266+
@SubclassOptInRequired(ResourceImplementation::class)
268267
public interface PathResource :
269268
JvmSourceResource,
270269
InputStreamResource,
@@ -323,7 +322,7 @@ private data class PathResourceImpl(
323322
override val path: Path,
324323
private val charset: Charset,
325324
private val openOptions: Array<out OpenOption>
326-
) : PathResource, SourceResource {
325+
) : PathResource {
327326
override fun inputStream(): InputStream = path.inputStream(options = openOptions)
328327

329328
override fun reader(): Reader = reader(charset)
@@ -371,6 +370,7 @@ private data class PathResourceImpl(
371370
* @author forte
372371
*/
373372
@Suppress("DEPRECATION")
373+
@SubclassOptInRequired(ResourceImplementation::class)
374374
public interface URIResource :
375375
JvmSourceResource,
376376
InputStreamResource,
@@ -445,8 +445,7 @@ public fun URI.toResource(charset: Charset = DEFAULT_CHARSET): URIResource =
445445
URIResourceImpl(this, charset, null)
446446

447447
private class URIResourceImpl(override val uri: URI, val charset: Charset, private var url: URL? = null) :
448-
URIResource,
449-
SourceResource {
448+
URIResource {
450449
private val urlValue: URL
451450
get() = url ?: run {
452451
uri.toURL().also { url = it }

0 commit comments

Comments
 (0)