aboutsummaryrefslogtreecommitdiff
path: root/docs-developer/src/doc/docs/developer_guide/architecture/data_model/extra.md
blob: d7412e36ea402d72432ccb5da927f514c73dba5d (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# Extra

## Introduction

`ExtraProperty` is used to store any additional information that falls outside of the regular model. It is highly 
recommended to use extras to provide any additional information when creating custom Dokka plugins.

`ExtraProperty` classes are available both in the [Documentable](documentable_model.md) and the [Content](page_content.md#content-model)
models.

To create a new extra, you need to implement the `ExtraProperty` interface. It is advised to use the following pattern
when declaring new extras:

```kotlin
data class CustomExtra(
    [any data relevant to your extra], 
    [any data relevant to your extra] 
): ExtraProperty<Documentable> {
    override val key: CustomExtra.Key<Documentable, *> = CustomExtra
    companion object : CustomExtra.Key<Documentable, CustomExtra>
}
```

Merge strategy (the `mergeStrategyFor` method) for extras is invoked during the
[merging](../extension_points/core_extension_points.md#documentablemerger) of the documentables from different 
[source sets](https://kotlinlang.org/docs/multiplatform-discover-project.html#source-sets), when the documentables being
merged have their own `Extra` of the same type. 

## PropertyContainer

All extras for `ContentNode` and `Documentable` classes are stored in the `PropertyContainer<C : Any>` class instances.

```kotlin
data class DFunction(
    ...
    override val extra: PropertyContainer<DFunction> = PropertyContainer.empty()
    ...
) : WithExtraProperties<DFunction>
```

`PropertyContainer` has a number of convenient functions for handling extras in a collection-like manner.

The generic class parameter `C` limits the types of properties that can be stored in the container - it must
match the generic `C` class parameter from the `ExtraProperty` interface. This allows creating extra properties
which can only be stored in a specific `Documentable`.

## Usage example

In following example we will create a `DFunction`-only extra property, store it and then retrieve its value:

```kotlin
// Extra that is applicable only to DFunction
data class CustomExtra(val customExtraValue: String) : ExtraProperty<DFunction> {
    override val key: ExtraProperty.Key<Documentable, *> = CustomExtra
    companion object: ExtraProperty.Key<Documentable, CustomExtra>
}

// Storing it inside the documentable
fun DFunction.withCustomExtraProperty(data: String): DFunction {
    return this.copy(
        extra = extra + CustomExtra(data)
    )
}

// Retrieveing it from the documentable
fun DFunction.getCustomExtraPropertyValue(): String? {
    return this.extra[CustomExtra]?.customExtraValue
}
```

___

You can also use extras as markers, without storing any data in them:

```kotlin

object MarkerExtra : ExtraProperty<Any>, ExtraProperty.Key<Any, MarkerExtra> {
    override val key: ExtraProperty.Key<Any, *> = this
}

fun Documentable.markIfFunction(): Documentable {
    return when(this) {
        is DFunction -> this.copy(extra = extra + MarkerExtra)
        else -> this
    }
}

fun WithExtraProperties<Documentable>.isMarked(): Boolean {
    return this.extra[MarkerExtra] != null
}
```