1 /* 2 * Copyright 2021 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package androidx.compose.runtime.tooling 18 19 import androidx.compose.runtime.CompositionContext 20 import androidx.compose.runtime.internal.JvmDefaultWithCompatibility 21 import androidx.compose.runtime.rememberCompositionContext 22 23 /** 24 * A [CompositionData] is the data tracked by the composer during composition. 25 * 26 * This interface is not intended to be used directly and is provided to allow the tools API to have 27 * access to data tracked during composition. The tools API should be used instead which provides a 28 * more usable interpretation of the slot table. 29 */ 30 interface CompositionData { 31 /** 32 * Iterate the composition data in the group. The composition data is structured as a tree of 33 * values that corresponds to the call graph of the functions that produced the tree. 34 * Interspersed are groups that represents the nodes themselves. 35 */ 36 val compositionGroups: Iterable<CompositionGroup> 37 38 /** 39 * Returns true if no composition data has been collected. This occurs when the first 40 * composition into this composition data has not completed yet or, if it is a group, it doesn't 41 * contain any child groups. 42 */ 43 val isEmpty: Boolean 44 45 /** 46 * Find a sub-group by identity. Returns `null` if the group is not found or the implementation 47 * of this interface does not support finding groups by their identity. In other words, a `null` 48 * result from this method should not be interpreted as the identity is not a group in the 49 * composition data. 50 */ findnull51 fun find(identityToFind: Any): CompositionGroup? = null 52 } 53 54 /** 55 * [CompositionGroup] is a group of data slots tracked independently by composition. These groups 56 * correspond to flow control branches (such as if statements and function calls) as well as 57 * emitting of a node to the tree. 58 * 59 * This interface is not intended to be used directly and is provided to allow the tools API to have 60 * access to data tracked during composition. The tools API should be used instead which provides a 61 * more usable interpretation of the slot table. 62 */ 63 @JvmDefaultWithCompatibility 64 interface CompositionGroup : CompositionData { 65 /** 66 * A value used to identify the group within its siblings and is typically a compiler generated 67 * integer but can be an object if the [key] composable is used. 68 */ 69 val key: Any 70 71 /** 72 * Information recorded by the compiler to help tooling identify the source that generated the 73 * group. The format of this string is internal and is interpreted by the tools API which 74 * translates this information into source file name and offsets. 75 */ 76 val sourceInfo: String? 77 78 /** 79 * If the group represents a node this returns a non-null value which is the node that was 80 * emitted for the group. 81 */ 82 val node: Any? 83 84 /** 85 * The data stored in the slot table for this group. This information includes the values stored 86 * for parameters that are checked for change, any value passed as a parameter for 87 * [androidx.compose.runtime.remember] and the last value returned by 88 * [androidx.compose.runtime.remember], etc. 89 */ 90 val data: Iterable<Any?> 91 92 /** A value that identifies a Group independently of movement caused by recompositions. */ 93 val identity: Any? 94 get() = null 95 96 /** The total number of groups, including itself, that this group contains. */ 97 val groupSize: Int 98 get() = 0 99 100 val slotsSize: Int 101 get() = 0 102 } 103 104 /** 105 * [CompositionInstance] provides information about the composition of which a [CompositionData] is 106 * part. 107 */ 108 interface CompositionInstance { 109 /** 110 * The parent composition instance, if the instance is part of a sub-composition. If this is the 111 * root of a composition (such as the content of a ComposeView), then [parent] will be `null`. 112 */ 113 val parent: CompositionInstance? 114 115 /** The [CompositionData] for the instance */ 116 val data: CompositionData 117 118 /** 119 * Find the [CompositionGroup] that contains the [CompositionContext] created by a call to 120 * [rememberCompositionContext] that is the parent context for this composition. If this is the 121 * root of the composition (e.g. [parent] is `null`) then this method also returns `null`. 122 */ findContextGroupnull123 fun findContextGroup(): CompositionGroup? 124 } 125 126 /** 127 * Find the [CompositionInstance] associated with the root [CompositionData]. This is only valid for 128 * instances of [CompositionData] that are recorded in a [LocalInspectionTables] table directly. 129 * 130 * Even though [CompositionGroup]s implement the [CompositionData] interface, only the root 131 * [CompositionData] has an associated [CompositionInstance]. All [CompositionGroup] instances will 132 * return `null`. 133 */ 134 fun CompositionData.findCompositionInstance(): CompositionInstance? = this as? CompositionInstance 135