0
# Module Metadata
1
2
Functionality for reading and writing .kotlin_module files that contain package structure information and compilation metadata. Module metadata files store information about how Kotlin packages are organized and which classes belong to which packages.
3
4
## Capabilities
5
6
### KotlinModuleMetadata Class
7
8
Main class for handling Kotlin module metadata operations.
9
10
```kotlin { .api }
11
/**
12
* Represents Kotlin module metadata from .kotlin_module files
13
* @param kmModule The module structure containing package information
14
* @param version The metadata version used for this module
15
*/
16
class KotlinModuleMetadata(
17
var kmModule: KmModule,
18
var version: JvmMetadataVersion
19
) {
20
/**
21
* Writes the module metadata to a byte array suitable for .kotlin_module files
22
* @return ByteArray containing the serialized module metadata
23
*/
24
fun write(): ByteArray
25
}
26
```
27
28
### Reading Module Metadata
29
30
Static function for reading module metadata from byte arrays.
31
32
```kotlin { .api }
33
companion object {
34
/**
35
* Reads module metadata from a byte array (typically from .kotlin_module files)
36
* @param bytes The byte array containing module metadata
37
* @return KotlinModuleMetadata instance with parsed module information
38
*/
39
@JvmStatic
40
fun read(bytes: ByteArray): KotlinModuleMetadata
41
}
42
```
43
44
**Usage Examples:**
45
46
```kotlin
47
import kotlin.metadata.jvm.KotlinModuleMetadata
48
import java.io.File
49
50
// Read module metadata from file
51
val moduleBytes = File("META-INF/main.kotlin_module").readBytes()
52
val moduleMetadata = KotlinModuleMetadata.read(moduleBytes)
53
54
println("Module version: ${moduleMetadata.version}")
55
println("Package parts: ${moduleMetadata.kmModule.packageParts.keys}")
56
57
// Access package information
58
moduleMetadata.kmModule.packageParts.forEach { (packageName, parts) ->
59
println("Package: $packageName")
60
println(" File facades: ${parts.fileFacades}")
61
println(" Multi-file parts: ${parts.multiFileClassParts}")
62
}
63
64
// Write modified metadata back to bytes
65
val modifiedBytes = moduleMetadata.write()
66
File("META-INF/modified.kotlin_module").writeBytes(modifiedBytes)
67
```
68
69
### KmModule Structure
70
71
Core module structure containing package organization information.
72
73
```kotlin { .api }
74
/**
75
* Represents the structure of a Kotlin module
76
*/
77
class KmModule {
78
/**
79
* Map of package names to their constituent parts
80
* Key: package name (dot-separated)
81
* Value: KmPackageParts containing facades and multi-file class information
82
*/
83
val packageParts: MutableMap<String, KmPackageParts>
84
85
/**
86
* List of optional annotation classes defined in this module
87
*/
88
val optionalAnnotationClasses: MutableList<KmClass>
89
}
90
```
91
92
### KmPackageParts Structure
93
94
Represents the parts that make up a Kotlin package.
95
96
```kotlin { .api }
97
/**
98
* Represents the parts that constitute a Kotlin package
99
* @param fileFacades List of file facade class names for top-level declarations
100
* @param multiFileClassParts Map of multi-file class part names to their facade names
101
*/
102
class KmPackageParts(
103
val fileFacades: MutableList<String>,
104
val multiFileClassParts: MutableMap<String, String>
105
)
106
```
107
108
**Usage Examples:**
109
110
```kotlin
111
// Create new module metadata
112
val module = KmModule()
113
114
// Add package with file facades
115
val packageParts = KmPackageParts(
116
fileFacades = mutableListOf("UtilsKt", "HelpersKt"),
117
multiFileClassParts = mutableMapOf(
118
"StringUtils__Part1Kt" to "StringUtilsKt",
119
"StringUtils__Part2Kt" to "StringUtilsKt"
120
)
121
)
122
module.packageParts["com.example.utils"] = packageParts
123
124
// Create module metadata
125
val moduleMetadata = KotlinModuleMetadata(
126
kmModule = module,
127
version = JvmMetadataVersion(1, 6, 0)
128
)
129
130
// Write to bytes
131
val bytes = moduleMetadata.write()
132
```
133
134
### Working with Package Parts
135
136
Detailed operations on package structure information.
137
138
```kotlin
139
// Examine package structure
140
moduleMetadata.kmModule.packageParts.forEach { (packageName, parts) ->
141
println("Package: $packageName")
142
143
// File facades contain top-level functions and properties
144
if (parts.fileFacades.isNotEmpty()) {
145
println(" File facades:")
146
parts.fileFacades.forEach { facade ->
147
println(" $facade")
148
}
149
}
150
151
// Multi-file class parts are used when @JvmMultifileClass is used
152
if (parts.multiFileClassParts.isNotEmpty()) {
153
println(" Multi-file class parts:")
154
parts.multiFileClassParts.forEach { (partName, facadeName) ->
155
println(" $partName -> $facadeName")
156
}
157
}
158
}
159
160
// Add new package parts
161
val newPackageParts = KmPackageParts(
162
fileFacades = mutableListOf("NewUtilsKt"),
163
multiFileClassParts = mutableMapOf()
164
)
165
moduleMetadata.kmModule.packageParts["com.example.new"] = newPackageParts
166
167
// Modify existing package parts
168
val existingParts = moduleMetadata.kmModule.packageParts["com.example.utils"]
169
existingParts?.fileFacades?.add("AdditionalUtilsKt")
170
```
171
172
### Optional Annotation Classes
173
174
Working with optional annotation classes in modules.
175
176
```kotlin
177
// Access optional annotation classes
178
moduleMetadata.kmModule.optionalAnnotationClasses.forEach { annotationClass ->
179
println("Optional annotation class: ${annotationClass.name}")
180
181
// Examine annotation properties
182
annotationClass.constructors.forEach { constructor ->
183
constructor.valueParameters.forEach { param ->
184
println(" Parameter: ${param.name} of type ${param.type}")
185
}
186
}
187
}
188
189
// Add optional annotation class (requires KmClass from kotlinx-metadata-core)
190
// This would typically be done when creating new module metadata
191
```
192
193
## File Locations
194
195
Module metadata files are typically located at:
196
- `META-INF/main.kotlin_module` - Main module metadata
197
- `META-INF/<source-set>.kotlin_module` - Source set specific metadata
198
199
## Error Handling
200
201
The `read()` function may throw exceptions if the byte array contains invalid or corrupted module metadata. Always handle potential parsing exceptions:
202
203
```kotlin
204
try {
205
val moduleMetadata = KotlinModuleMetadata.read(bytes)
206
// Process metadata
207
} catch (e: Exception) {
208
println("Failed to parse module metadata: ${e.message}")
209
}
210
```