NavArgumentResolver.kt
/*
* Copyright 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package androidx.navigation.safe.args.generator
import androidx.navigation.safe.args.generator.models.Argument
import androidx.navigation.safe.args.generator.models.Destination
import androidx.navigation.safe.args.generator.models.ResReference
fun resolveArguments(rootDestination: Destination): Destination {
val destinations = mutableMapOf<ResReference, Destination>()
fun dfs(dest: Destination): Destination {
val nested = dest.nested.filter { it.id != null }.associateBy { it.id!! }
destinations.putAll(nested)
val resolvedActions = dest.actions.map { action ->
val actionDestination = destinations[action.destination]
if (actionDestination != null) {
action.copy(args = mergeArguments(action.args, actionDestination.args))
} else {
action
}
}
val result = dest.copy(nested = dest.nested.map(::dfs), actions = resolvedActions)
nested.keys.forEach { id -> destinations.remove(id) }
return result
}
return dfs(rootDestination)
}
private fun mergeArguments(args1: List<Argument>, args2: List<Argument>) =
args2.fold(args1) { result, arg ->
val duplicate = result.find { it.name == arg.name }
if (duplicate != null) {
if (duplicate.type != arg.type) {
// TODO: needs context to print better exception
throw IllegalArgumentException(
"Incompatible types ${duplicate.type} and " +
"${arg.type} of argument ${arg.name}"
)
}
result
} else {
result + arg
}
}