Repository: ktorio/ktor
File: ktor-server/ktor-server-core/common/src/io/ktor/server/config/MergedApplicationConfig.kt (Kotlin)

Code before:
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.merge)
 */
@Deprecated(
    "Use mergeWith/withFallback instead.",
    level = DeprecationLevel.ERROR
)
public fun List<ApplicationConfig>.merge(): ApplicationConfig {
    require(isNotEmpty()) { "List of configs can not be empty" }
    return foldRight(last()) { config, acc -> config.withFallback(acc) }
}

/**
 * Merge configuration combining all their keys.
 * If the key exists in this and [other] config, the value from the [other] config will be used.
 *
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.mergeWith)
 *
 * @see [withFallback]
 */
public fun ApplicationConfig.mergeWith(other: ApplicationConfig): ApplicationConfig =
    when {
        keys().isEmpty() -> other
        other.keys().isEmpty() -> this
        else -> MergedApplicationConfig(other, this)
    }

/**
 * Merge configuration combining all their keys.
 * If the key exists in this and [other] config, the value from this config will be used.
 *
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.withFallback)
 *
 * @see [mergeWith]
 */
public fun ApplicationConfig.withFallback(other: ApplicationConfig): ApplicationConfig {
    return MergedApplicationConfig(this, other)
}

internal class MergedApplicationConfig(
    val first: ApplicationConfig,
    val second: ApplicationConfig
) : ApplicationConfig {

    private val firstKeys by lazy { first.keys() }
    private val secondKeys by lazy { second.keys() }

    override fun property(path: String): ApplicationConfigValue =
        merge(first.propertyOrNull(path), second.propertyOrNull(path)) ?: second.property(path)


Review comment (suggestion):
Is `ApplicationConfig` immutable? If it is possible to add keys after `mergeWith` called, new behavior might be surprising.

Code after:
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.merge)
 */
@Deprecated(
    "Use mergeWith/withFallback instead.",
    level = DeprecationLevel.ERROR
)
public fun List<ApplicationConfig>.merge(): ApplicationConfig {
    require(isNotEmpty()) { "List of configs can not be empty" }
    return foldRight(last()) { config, acc -> config.withFallback(acc) }
}

/**
 * Merge configuration combining all their keys.
 * If the key exists in this and [other] config, the value from the [other] config will be used.
 *
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.mergeWith)
 *
 * @see [withFallback]
 */
public fun ApplicationConfig.mergeWith(other: ApplicationConfig): ApplicationConfig =
    when {
        keys().isEmpty() -> other
        other.keys().isEmpty() -> this
        else -> MergedApplicationConfig(other, this)
    }

/**
 * Merge configuration combining all their keys.
 * If the key exists in this and [other] config, the value from this config will be used.
 *
 *
 * [Report a problem](https://ktor.io/feedback/?fqname=io.ktor.server.config.withFallback)
 *
 * @see [mergeWith]
 */
public fun ApplicationConfig.withFallback(other: ApplicationConfig): ApplicationConfig {
    return MergedApplicationConfig(this, other)
}

internal class MergedApplicationConfig(
    val first: ApplicationConfig,
    val second: ApplicationConfig
) : ApplicationConfig {

    private val firstKeys by lazy { first.keys() }
    private val secondKeys by lazy { second.keys() }

    override fun property(path: String): ApplicationConfigValue =
        merge(first.propertyOrNull(path), second.propertyOrNull(path)) ?: second.property(path)