Skip to content

Commit

Permalink
Merge pull request #61 from aPureBase/v3.3.1
Browse files Browse the repository at this point in the history
Revert naming strategy breaking change and add naming strategy enum f…
  • Loading branch information
AndreasVolkmann authored May 15, 2021
2 parents a61025b + 74c2f18 commit 5869d68
Show file tree
Hide file tree
Showing 12 changed files with 128 additions and 16 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
# 3.3.1
* Revert breaking change to argument name resolution.
The naming strategy can be changed in `configureArkenv`.

# 3.3.0
* Support common JVM type: `File`, `Path`, `URL`, `URI`

# 3.2.0
* #29 Common prefix support
* #43 New feature syntax
Expand Down
6 changes: 6 additions & 0 deletions arkenv/src/main/kotlin/com/apurebase/arkenv/ArkenvBuilder.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.apurebase.arkenv

import com.apurebase.arkenv.argument.ArkenvArgumentNamingStrategy
import com.apurebase.arkenv.feature.*
import com.apurebase.arkenv.feature.cli.CliFeature
import com.apurebase.arkenv.util.key
Expand All @@ -25,6 +26,11 @@ class ArkenvBuilder(installAdvancedFeatures: Boolean = true) {
*/
var clearInputAfterParse = false

/**
* Defines the argument naming strategy that will be used to determine the applicable names.
*/
var namingStrategy: ArkenvArgumentNamingStrategy = ArkenvArgumentNamingStrategy.ParameterNameOnlyIfNotSpecified

internal val features: MutableList<ArkenvFeature> = mutableListOf()
internal val processorFeatures: MutableList<ProcessorFeature> = mutableListOf()
internal val modules: MutableList<Arkenv> = mutableListOf()
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.apurebase.arkenv.argument

import com.apurebase.arkenv.Arkenv
import com.apurebase.arkenv.argument.ArkenvArgumentNamingStrategy.*
import com.apurebase.arkenv.util.isAdvancedName
import com.apurebase.arkenv.util.mapRelaxed
import com.apurebase.arkenv.util.toSnakeCase
import kotlin.reflect.KProperty

internal class ArgumentNameProcessor(
private val prefix: String?
private val prefix: String?,
private val namingStrategy: ArkenvArgumentNamingStrategy
) {

/**
Expand All @@ -19,13 +20,22 @@ internal class ArgumentNameProcessor(
argument.names = getNames(argument.names, property.name)
}

private fun getNames(names: List<String>, propName: String) = names
.ifEmpty { listOf(propName.toSnakeCase()) }
.map {
it.ensureStartsWithDash()
.prefix(prefix ?: "")
.mapRelaxed()
private fun getNames(argumentNames: List<String>, propName: String): List<String> =
getNameList(argumentNames, propName).map(::processName)

private fun getNameList(argumentNames: List<String>, propName: String): List<String> {
return when (namingStrategy) {
ParameterNameOnlyIfNotSpecified -> {
argumentNames.ifEmpty { listOf(propName.toSnakeCase()) }
}
ParameterNameAlwaysIncluded -> argumentNames + propName.toSnakeCase()
}
}

private fun processName(name: String) = name
.ensureStartsWithDash()
.prefix(prefix ?: "")
.mapRelaxed()

private fun String.ensureStartsWithDash() =
if (!startsWith("-")) "--$this" else this
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ interface ArkenvArgument<T : Any?> : ReadOnlyProperty<Any, T> {
}

private fun getNames(): Collection<String> {
return argument.names + property.name.toSnakeCase()
return argument.names
}

private fun checkNullable(value: T) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package com.apurebase.arkenv.argument

/**
* Determines how argument names are resolved.
*/
enum class ArkenvArgumentNamingStrategy {
/**
* Always include the parameter name, even when custom names are specified.
*/
ParameterNameAlwaysIncluded,

/**
* Only include the parameter name when no custom names are specified.
*/
ParameterNameOnlyIfNotSpecified
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ class ArkenvDelegateLoader<T : Any>(
private val argument: Argument<T>,
private val arkenv: Arkenv
) {
private val argumentNameProcessor = ArgumentNameProcessor(arkenv.configuration.prefix)
private val argumentNameProcessor = ArgumentNameProcessor(
arkenv.configuration.prefix, arkenv.configuration.namingStrategy)

operator fun provideDelegate(thisRef: Arkenv, prop: KProperty<*>): ReadOnlyProperty<Arkenv, T> {
argumentNameProcessor.processArgumentNames(argument, prop)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,8 @@ internal class ArkenvSimpleArgument<T : Any?>(
this.property = property
if (!isInitialized) {
val prefix = moduleConfiguration?.prefix ?: arkenv.configuration.prefix
val argumentNameProcessor = ArgumentNameProcessor(prefix)
val namingStrategy = arkenv.configuration.namingStrategy
val argumentNameProcessor = ArgumentNameProcessor(prefix, namingStrategy)
argumentNameProcessor.processArgumentNames(argument, property)
isInitialized = true
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,11 @@ class ArkenvParser<T : Any>(
private fun parseConstructorArgs(parameters: Collection<KParameter>): Map<KParameter, Any?> {
return parameters
.filterNot { it.name.isNullOrBlank() }
.mapNotNull(::parseParameter)
.mapNotNull(::parseConstructorParameter)
.toMap()
}

private fun parseParameter(parameter: KParameter): Pair<KParameter, Any?>? {
private fun parseConstructorParameter(parameter: KParameter): Pair<KParameter, Any?>? {
val name = parameter.name!!.toSnakeCase()
val value = arkenv.getOrNull(name)
return if (parameter.isOptional && value == null) null
Expand Down
30 changes: 30 additions & 0 deletions arkenv/src/test/kotlin/com/apurebase/arkenv/GeneralTest.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.apurebase.arkenv

import com.apurebase.arkenv.argument.ArkenvArgumentNamingStrategy
import com.apurebase.arkenv.test.*
import com.apurebase.arkenv.util.argument
import com.apurebase.arkenv.util.mainArgument
Expand All @@ -8,6 +9,7 @@ import org.amshove.kluent.shouldBe
import org.amshove.kluent.shouldBeEqualTo
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.assertThrows
import strikt.api.expectThat
import strikt.assertions.contains
import strikt.assertions.isEqualTo
import strikt.assertions.isTrue
Expand Down Expand Up @@ -188,4 +190,32 @@ class GeneralTest {
get { port }.isEqualTo(expectedPort)
}
}

@Test fun `should only use fully qualified env name`() {
MockSystem("USER" to "jeggy")
val ark = object: Arkenv() {
val user: String by argument("--db-user") {
defaultValue = { "postgres" }
}
}.parse()

expectThat(ark) {
get { user } isEqualTo "postgres"
}
}

@Test fun `ParameterNameAlwaysIncluded - should consider parameter name`() {
MockSystem("USER" to "jeggy")
val ark = object : Arkenv(configuration = configureArkenv {
namingStrategy = ArkenvArgumentNamingStrategy.ParameterNameAlwaysIncluded
}) {
val user: String by argument("--db-user") {
defaultValue = { "postgres" }
}
}.parse()

expectThat(ark) {
get { user } isEqualTo "jeggy"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.apurebase.arkenv.argument

import org.junit.jupiter.api.Test
import strikt.api.expectThat
import strikt.assertions.hasSize

internal class ArgumentNameProcessorTest {

private val target = object {
val argument: Int = 1
}

@Test fun `processArgumentNames - ParameterNameOnlyIfNotSpecified - param name excluded`() {
// Arrange
val expected = "expected"
val namingStrategy = ArkenvArgumentNamingStrategy.ParameterNameOnlyIfNotSpecified
val processor = ArgumentNameProcessor(null, namingStrategy)
val argument = Argument<Int>(listOf(expected))

// Act
processor.processArgumentNames(argument, target::argument)

// Assert
expectThat(argument.names) { hasSize(1) }
}

@Test fun `processArgumentNames - ParameterNameAlwaysIncluded - param name included`() {
// Arrange
val expected = "expected"
val namingStrategy = ArkenvArgumentNamingStrategy.ParameterNameAlwaysIncluded
val processor = ArgumentNameProcessor(null, namingStrategy)
val argument = Argument<Int>(listOf(expected))

// Act
processor.processArgumentNames(argument, target::argument)

// Assert
expectThat(argument.names) { hasSize(2) }
}

}
4 changes: 2 additions & 2 deletions gradle.properties
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
group=com.apurebase
version=3.3.0
version=3.3.1

# Versions
junitVersion=5.7.0
junitVersion=5.7.1
snakeyamlVersion=1.28
jmockitVersion=1.49
kluentVersion=1.65
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

0 comments on commit 5869d68

Please sign in to comment.