-
Notifications
You must be signed in to change notification settings - Fork 24.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Convert com.facebook.react.uimanager.ViewManagerPropertyUpdater to Ko…
…tlin (#48658) Summary: Pull Request resolved: #48658 Migrate to Kotlin before I make further changes to this. Generics are really tricky due to our previous usage of raw generics on the Java side, but were worked around by some combination of unchecked cast and `Nothing` Changelog: [Internal] Reviewed By: mdvacca, rshest Differential Revision: D68102210
- Loading branch information
1 parent
559d070
commit fe8370b
Showing
3 changed files
with
178 additions
and
179 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
172 changes: 0 additions & 172 deletions
172
...e/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerPropertyUpdater.java
This file was deleted.
Oops, something went wrong.
171 changes: 171 additions & 0 deletions
171
...ive/ReactAndroid/src/main/java/com/facebook/react/uimanager/ViewManagerPropertyUpdater.kt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,171 @@ | ||
/* | ||
* Copyright (c) Meta Platforms, Inc. and affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
package com.facebook.react.uimanager | ||
|
||
import android.view.View | ||
import com.facebook.common.logging.FLog | ||
import com.facebook.react.uimanager.ViewManagersPropertyCache.PropSetter | ||
import java.util.HashMap | ||
|
||
public object ViewManagerPropertyUpdater { | ||
public fun interface Settable { | ||
public fun getProperties(props: MutableMap<String, String>) | ||
} | ||
|
||
@Suppress("FINITE_BOUNDS_VIOLATION_IN_JAVA") | ||
public interface ViewManagerSetter<T : ViewManager<V, *>, V : View> : Settable { | ||
public fun setProperty(manager: T, view: V, name: String, value: Any?) | ||
} | ||
|
||
@Suppress("FINITE_BOUNDS_VIOLATION_IN_JAVA") | ||
public interface ShadowNodeSetter<in T : ReactShadowNode<*>> : Settable { | ||
public fun setProperty(node: T, name: String, value: Any?) | ||
} | ||
|
||
private const val TAG = "ViewManagerPropertyUpdater" | ||
|
||
private val VIEW_MANAGER_SETTER_MAP: MutableMap<Class<*>, ViewManagerSetter<*, *>> = HashMap() | ||
private val SHADOW_NODE_SETTER_MAP: MutableMap<Class<*>, ShadowNodeSetter<*>> = HashMap() | ||
|
||
@JvmStatic | ||
public fun clear(): Unit { | ||
ViewManagersPropertyCache.clear() | ||
VIEW_MANAGER_SETTER_MAP.clear() | ||
SHADOW_NODE_SETTER_MAP.clear() | ||
} | ||
|
||
@JvmStatic | ||
public fun <T : ViewManagerDelegate<V>, V : View> updateProps( | ||
delegate: T, | ||
view: V, | ||
props: ReactStylesDiffMap | ||
) { | ||
val iterator = props.mBackingMap.entryIterator | ||
while (iterator.hasNext()) { | ||
val entry = iterator.next() | ||
delegate.setProperty(view, entry.key, entry.value) | ||
} | ||
} | ||
|
||
@JvmStatic | ||
public fun <V : View> updateProps( | ||
manager: ViewManager<V, *>, | ||
view: V, | ||
props: ReactStylesDiffMap | ||
) { | ||
val setter = findManagerSetter(manager.javaClass) | ||
val iterator = props.mBackingMap.entryIterator | ||
while (iterator.hasNext()) { | ||
val entry = iterator.next() | ||
setter.setProperty(manager, view, entry.key, entry.value) | ||
} | ||
} | ||
|
||
@JvmStatic | ||
public fun <T : ReactShadowNode<T>> updateProps(node: T, props: ReactStylesDiffMap) { | ||
val setter = findNodeSetter(node.javaClass) | ||
val iterator = props.mBackingMap.entryIterator | ||
while (iterator.hasNext()) { | ||
val entry = iterator.next() | ||
setter.setProperty(node, entry.key, entry.value) | ||
} | ||
} | ||
|
||
@JvmStatic | ||
public fun getNativeProps( | ||
viewManagerTopClass: Class<out ViewManager<Nothing, *>>, | ||
shadowNodeTopClass: Class<out Nothing> | ||
): Map<String, String> { | ||
val props: MutableMap<String, String> = HashMap() | ||
findManagerSetter(viewManagerTopClass).getProperties(props) | ||
findNodeSetter(shadowNodeTopClass).getProperties(props) | ||
return props | ||
} | ||
|
||
private fun <V : View> findManagerSetter( | ||
managerClass: Class<out ViewManager<V, *>> | ||
): ViewManagerSetter<ViewManager<V, *>, V> { | ||
var setter = VIEW_MANAGER_SETTER_MAP[managerClass] | ||
if (setter == null) { | ||
setter = findGeneratedSetter(managerClass) | ||
if (setter == null) { | ||
setter = FallbackViewManagerSetter(managerClass) | ||
} | ||
VIEW_MANAGER_SETTER_MAP[managerClass] = setter | ||
} | ||
@Suppress("UNCHECKED_CAST") | ||
return setter as ViewManagerSetter<ViewManager<V, *>, V> | ||
} | ||
|
||
private fun <T : ReactShadowNode<T>> findNodeSetter( | ||
nodeClass: Class<out T> | ||
): ShadowNodeSetter<T> { | ||
var setter = SHADOW_NODE_SETTER_MAP[nodeClass] | ||
if (setter == null) { | ||
setter = findGeneratedSetter(nodeClass) | ||
if (setter == null) { | ||
@Suppress("UNCHECKED_CAST") | ||
setter = FallbackShadowNodeSetter(nodeClass as Class<Nothing>) | ||
} | ||
SHADOW_NODE_SETTER_MAP[nodeClass] = setter | ||
} | ||
@Suppress("UNCHECKED_CAST") | ||
return setter as ShadowNodeSetter<T> | ||
} | ||
|
||
private fun <T> findGeneratedSetter(cls: Class<*>): T? { | ||
val clsName = cls.name | ||
try { | ||
val setterClass = Class.forName("$clsName$\$PropsSetter") | ||
@Suppress("DEPRECATION", "UNCHECKED_CAST") | ||
return setterClass.newInstance() as T | ||
} catch (e: ClassNotFoundException) { | ||
FLog.w(TAG, "Could not find generated setter for $cls") | ||
return null | ||
} catch (e: InstantiationException) { | ||
throw RuntimeException("Unable to instantiate methods getter for $clsName", e) | ||
} catch (e: IllegalAccessException) { | ||
throw RuntimeException("Unable to instantiate methods getter for $clsName", e) | ||
} | ||
} | ||
|
||
private class FallbackViewManagerSetter<V : View>( | ||
viewManagerClass: Class<out ViewManager<V, *>> | ||
) : ViewManagerSetter<ViewManager<V, *>, V> { | ||
private val mPropSetters: Map<String, PropSetter> = | ||
ViewManagersPropertyCache.getNativePropSettersForViewManagerClass(viewManagerClass) | ||
|
||
override fun setProperty(manager: ViewManager<V, *>, view: V, name: String, value: Any?) { | ||
val setter = mPropSetters[name] | ||
setter?.updateViewProp(manager, view, value) | ||
} | ||
|
||
override fun getProperties(props: MutableMap<String, String>) { | ||
for (setter in mPropSetters.values) { | ||
props[setter.propName] = setter.propType | ||
} | ||
} | ||
} | ||
|
||
private class FallbackShadowNodeSetter(shadowNodeClass: Class<out Nothing>) : | ||
ShadowNodeSetter<ReactShadowNode<*>> { | ||
private val propSetters: Map<String, PropSetter> = | ||
ViewManagersPropertyCache.getNativePropSettersForShadowNodeClass(shadowNodeClass) | ||
|
||
override fun setProperty(node: ReactShadowNode<*>, name: String, value: Any?) { | ||
val setter = propSetters[name] | ||
setter?.updateShadowNodeProp(node, value) | ||
} | ||
|
||
override fun getProperties(props: MutableMap<String, String>) { | ||
for (setter in propSetters.values) { | ||
props[setter.propName] = setter.propType | ||
} | ||
} | ||
} | ||
} |