Skip to content

Commit

Permalink
contrib: Integrate uchuhimo#48 into this fork.
Browse files Browse the repository at this point in the history
chore: Clean up grammar and code style across the entire codebase.
  • Loading branch information
nhubbard committed Feb 10, 2024
1 parent ffd39a1 commit b2f3c98
Show file tree
Hide file tree
Showing 56 changed files with 697 additions and 392 deletions.
80 changes: 64 additions & 16 deletions src/main/kotlin/com/moandjiezana/toml/Toml4jWriter.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@ import com.moandjiezana.toml.BooleanValueReaderWriter.BOOLEAN_VALUE_READER_WRITE
import com.moandjiezana.toml.DateValueReaderWriter.DATE_VALUE_READER_WRITER
import com.moandjiezana.toml.NumberValueReaderWriter.NUMBER_VALUE_READER_WRITER
import com.moandjiezana.toml.StringValueReaderWriter.STRING_VALUE_READER_WRITER
import com.nhubbard.konfig.ListNode
import com.nhubbard.konfig.TreeNode
import com.nhubbard.konfig.ValueNode
import java.io.IOException
import java.io.StringWriter
import java.io.Writer
Expand Down Expand Up @@ -93,7 +96,7 @@ internal object Toml4jValueWriters {
return valueWriter
}
}
return NewMapValueWriter
error("Can't find writer for ${value::class.qualifiedName}")
}

private val VALUE_WRITERS = arrayOf<ValueWriter>(
Expand All @@ -107,59 +110,97 @@ internal object Toml4jValueWriters {
}

internal object NewArrayValueWriter : ArrayValueWriter() {
override fun canWrite(value: Any?): Boolean = isArrayish(value)
override fun canWrite(value: Any?): Boolean = isArrayish(value) || value is ListNode

override fun write(o: Any, context: WriterContext) {
val values = normalize(o)
val node = o as? ListNode
val values = normalize(node?.list ?: o)

context.writeComments(node)
context.write('[')
context.writeArrayDelimiterPadding()

var first = true
var firstWriter: ValueWriter? = null

val hasAnyComments = values.any { it is TreeNode && it.comments.isNotEmpty() }
if (hasAnyComments) context.write('\n')

for (value in values) {
if (value == null) continue

val fromNode = value as? TreeNode
val fromValue = fromNode?.value ?: value

if (hasAnyComments) context.indent()

if (first) {
firstWriter = Toml4jValueWriters.findWriterFor(value!!)
firstWriter = Toml4jValueWriters.findWriterFor(fromValue)
first = false
} else {
val writer = Toml4jValueWriters.findWriterFor(value!!)
val writer = Toml4jValueWriters.findWriterFor(fromValue)
if (writer !== firstWriter) {
throw IllegalStateException(
context.contextPath +
": cannot write a heterogeneous array; first element was of type " + firstWriter +
" but found " + writer
)
}
if (hasAnyComments)
context.write('\n')
context.write(", ")
}

val writer = Toml4jValueWriters.findWriterFor(value)
val writer = Toml4jValueWriters.findWriterFor(fromValue)
val isNestedOldValue = NewMapValueWriter.isNested
if (writer == NewMapValueWriter) {
NewMapValueWriter.isNested = true
}
writer.write(value, context)
context.writeComments(fromNode)
writer.write(fromValue, context)
if (writer == NewMapValueWriter) {
NewMapValueWriter.isNested = isNestedOldValue
}
}

context.writeArrayDelimiterPadding()
if (hasAnyComments)
context.write('\n')
context.write(']')
}
}

private val TreeNode.value: Any
get() = when (this) {
is ValueNode -> this.value
is ListNode -> this.list
else -> this.children
}

private fun WriterContext.writeComments(node: TreeNode?, newLineAfter: Boolean = true) {
if (node == null || node.comments.isEmpty()) return
val comments = node.comments.split("\n")
comments.forEach { comment ->
write('\n')
indent()
write("# $comment")
}
if (newLineAfter) write('\n')
}

internal object NewMapValueWriter : ValueWriter {

override fun canWrite(value: Any): Boolean {
return value is Map<*, *>
return value is Map<*, *> || (value is TreeNode && value !is ValueNode && value !is ListNode)
}

var isNested: Boolean = false

override fun write(value: Any, context: WriterContext) {
val from = value as Map<*, *>
val node = value as? TreeNode
val from = node?.children ?: value as Map<*, *>

context.writeComments(node, newLineAfter = false)

if (hasPrimitiveValues(from)) {
if (isNested) {
Expand All @@ -173,10 +214,14 @@ internal object NewMapValueWriter : ValueWriter {
// Render primitive types and arrays of primitive first so they are
// grouped under the same table (if there is one)
for ((key, value1) in from) {
val fromValue = value1 ?: continue
if (value1 == null) continue

val fromNode = value1 as? TreeNode
val fromValue = fromNode?.value ?: value1

val valueWriter = Toml4jValueWriters.findWriterFor(fromValue)
if (valueWriter.isPrimitiveType()) {
if (valueWriter.isPrimitiveType) {
context.writeComments(fromNode)
context.indent()
context.write(quoteKey(key!!)).write(" = ")
valueWriter.write(fromValue, context)
Expand All @@ -186,6 +231,7 @@ internal object NewMapValueWriter : ValueWriter {
context.write('\n')
} else if (valueWriter === NewArrayValueWriter) {
context.setArrayKey(key.toString())
context.writeComments(fromNode)
context.write(quoteKey(key!!)).write(" = ")
valueWriter.write(fromValue, context)
if (isNested) {
Expand All @@ -199,9 +245,8 @@ internal object NewMapValueWriter : ValueWriter {
for (key in from.keys) {
val fromValue = from[key] ?: continue

val valueWriter = Toml4jValueWriters.findWriterFor(fromValue)
if (valueWriter === this) {
valueWriter.write(fromValue, context.pushTable(quoteKey(key!!)))
if (canWrite(fromValue)) {
write(fromValue, context.pushTable(quoteKey(key!!)))
}
}
if (isNested) {
Expand All @@ -228,10 +273,13 @@ internal object NewMapValueWriter : ValueWriter {

private fun hasPrimitiveValues(values: Map<*, *>): Boolean {
for (key in values.keys) {
val fromValue = values[key] ?: continue
val value = values[key] ?: continue

val fromNode = value as? TreeNode
val fromValue = fromNode?.value ?: value

val valueWriter = Toml4jValueWriters.findWriterFor(fromValue)
if (valueWriter.isPrimitiveType() || valueWriter === NewArrayValueWriter) {
if (valueWriter.isPrimitiveType || valueWriter === NewArrayValueWriter) {
return true
}
}
Expand Down
57 changes: 44 additions & 13 deletions src/main/kotlin/com/nhubbard/konfig/BaseConfig.kt
Original file line number Diff line number Diff line change
Expand Up @@ -138,6 +138,29 @@ open class BaseConfig(
(node as ItemNode).item to name
} + (parent?.itemWithNames ?: listOf())

override fun toTree(): TreeNode {
return ContainerNode(mutableMapOf()).apply {
lock.read {
itemWithNames.forEach { (item, name) ->
val value = try {
getOrNull(item, errorWhenNotFound = true).toCompatibleValue(mapper)
} catch (_: UnsetValueException) {
return@forEach
}
set(name, value.asTree(item.description))
}
// Add spec descriptions
specs.forEach { spec ->
val path = spec.prefix.toPath()
val node = tree.getOrNull(path)
if (node != null && node.comments.isNotEmpty()) {
getOrNull(path)?.comments = node.comments
}
}
}
}
}

override fun toMap(): Map<String, Any> {
return lock.read {
itemWithNames.map { (item, name) ->
Expand Down Expand Up @@ -175,7 +198,6 @@ open class BaseConfig(
): Any? {
val valueState = lock.read { nodeByItem[item]?.value }
if (valueState != null) {
@Suppress("UNCHECKED_CAST")
when (valueState) {
is ValueState.Unset ->
if (errorWhenNotFound) {
Expand Down Expand Up @@ -229,13 +251,13 @@ open class BaseConfig(
}
}
} else {
if (parent != null) {
return parent!!.getOrNull(item, errorWhenNotFound, errorWhenGetDefault, lazyContext)
return if (parent != null) {
parent!!.getOrNull(item, errorWhenNotFound, errorWhenGetDefault, lazyContext)
} else {
if (errorWhenNotFound) {
throw NoSuchItemException(item)
} else {
return null
null
}
}
}
Expand Down Expand Up @@ -318,15 +340,15 @@ open class BaseConfig(
containsInLayer(path) || (parent?.contains(path) ?: false)

override fun nameOf(item: Item<*>): String {
return nameByItem[item] ?: {
val name = lock.read { tree.firstPath { it is ItemNode && it.item == item } }?.name
if (name != null) {
nameByItem[item] = name
name
return nameByItem[item] ?: run {
val name1 = lock.read { tree.firstPath { it is ItemNode && it.item == item } }?.name
if (name1 != null) {
nameByItem[item] = name1
name1
} else {
parent?.nameOf(item) ?: throw NoSuchItemException(item)
}
}()
}
}

open fun addBeforeSetFunction(beforeSetFunction: (item: Item<*>, value: Any?) -> Unit) {
Expand Down Expand Up @@ -638,6 +660,13 @@ open class BaseConfig(
throw RepeatedItemException(name)
}
}
val description = spec.description
if (description.isNotEmpty()) {
val node = this.tree.getOrNull(spec.prefix.toPath())
if (node != null && node.comments.isEmpty()) {
node.comments = description
}
}
spec.innerSpecs.forEach { innerSpec ->
addSpec(innerSpec.withPrefix(spec.prefix))
}
Expand Down Expand Up @@ -730,13 +759,15 @@ open class BaseConfig(
return "Config(items=${toMap()})"
}

class ItemNode(override var value: ValueState, val item: Item<*>) : ValueNode
class ItemNode(override var value: ValueState, val item: Item<*>) : ValueNode {
override var comments = this.item.description
}

data class Value<T>(var value: T)

sealed class ValueState {
object Unset : ValueState()
object Null : ValueState()
data object Unset : ValueState()
data object Null : ValueState()
data class Lazy<T>(val thunk: (config: ItemContainer) -> T) : ValueState()
data class Value(val value: Any) : ValueState()
data class Default(val value: Any?) : ValueState()
Expand Down
Loading

0 comments on commit b2f3c98

Please sign in to comment.