Skip to content

Commit

Permalink
Several cosmetic fixes for multiline strings (#217)
Browse files Browse the repository at this point in the history
### What's done:
- On multiline strings we forgot to update isMultiline flag while decoding and parsing
- Adding extra info to prettyPrint
- Adding a test for validation of line numbers
- Removing deprecated 'content' from the TomlNode
- Added newline alignment for multiline strings (newlines after/before quotes-separators)
  • Loading branch information
orchestr7 committed May 7, 2023
1 parent 15683ed commit 76bcae0
Show file tree
Hide file tree
Showing 7 changed files with 151 additions and 51 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -101,10 +101,10 @@ public class TomlMainDecoder(
is TomlKeyValuePrimitive -> node
is TomlKeyValueArray -> node
// empty nodes will be filtered by iterateUntilWillFindAnyKnownName() method, but in case we came into this
// branch, we should throw an exception as it is not expected at all and we should catch this in tests
// branch, we should throw an exception as it is not expected at all, and we should catch this in tests
else ->
throw InternalDecodingException(
"Node of type [${node::class}] should not be processed in TomlDecoder.decodeValue(): <${node.content}>."
"Node of type [${node::class}] should not be processed in TomlDecoder.decodeValue(): <$node>."
)
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,6 @@ public sealed class TomlNode(
comments: List<String>,
public val inlineComment: String
) {
@Deprecated(
message = "content was replaced with toString; will be removed in future releases.",
replaceWith = ReplaceWith("toString()")
)
@Suppress("CUSTOM_GETTERS_SETTERS")
public val content: String get() = toString()

/**
* A list of comments prepended to the node.
*/
Expand Down Expand Up @@ -187,20 +180,25 @@ public sealed class TomlNode(

/**
* print the structure of parsed AST tree
* Important: as prettyPrint calls toString() of the node, and not just prints the value, but emits and reconstruct a source string,
* so in some cases (for example in case of multiline strings) it can work incorrectly.
*
* @param emitLine - if true - will print line number in this debug print
*/
@Suppress("DEBUG_PRINT")
public fun prettyPrint() {
public fun prettyPrint(emitLine: Boolean = false) {
val sb = StringBuilder()
prettyPrint(this, sb)
prettyPrint(this, sb, emitLine)
println(sb.toString())
}

/**
* @param emitLine - if true - will print line number in this debug print
* @return the string with AST tree visual representation
*/
public fun prettyStr(): String {
public fun prettyStr(emitLine: Boolean = false): String {
val sb = StringBuilder()
prettyPrint(this, sb)
prettyPrint(this, sb, emitLine)
return sb.toString()
}

Expand Down Expand Up @@ -233,37 +231,6 @@ public sealed class TomlNode(
}
}

@Deprecated(
message = "TomlConfig is deprecated; use TomlOutputConfig instead. Will be removed in next releases.",
replaceWith = ReplaceWith(
"write(emitter, config, multiline)",
"com.akuleshov7.ktoml.TomlOutputConfig"
)
)
public fun write(
emitter: TomlEmitter,
config: TomlConfig,
multiline: Boolean = false
): Unit = write(emitter, config.output, multiline)

/**
* Writes this node as text to [emitter].
*
* @param emitter The [TomlEmitter] instance to write to.
* @param config The [TomlConfig] instance. Defaults to the node's config.
* @param multiline Whether to write the node over multiple lines, if possible.
*/
@Deprecated(
message = "The multiline parameter overload is deprecated, use the multiline" +
" property on supported TomlValue types instead. Will be removed in next releases.",
replaceWith = ReplaceWith("write(emitter, config)")
)
public fun write(
emitter: TomlEmitter,
config: TomlOutputConfig = TomlOutputConfig(),
multiline: Boolean = false
): Unit = write(emitter, config)

/**
* Writes this node as text to [emitter].
*
Expand Down Expand Up @@ -328,26 +295,32 @@ public sealed class TomlNode(
.writeNode(this)
.replace(" = ", "=")

internal fun print(emitLine: Boolean = false): String =
"${this::class.simpleName} ($this)${if (emitLine) "[line:${this.lineNo}]" else ""}\n"

public companion object {
// number of spaces that is used to indent levels
internal const val INDENTING_LEVEL = 4

/**
* recursive print the tree using the current node
*
* @param node
* @param level
* @param result
* @param node that will be printed
* @param level depth of hierarchy for print
* @param result string builder where the result is stored
* @param emitLine if true - will print line number in this debug print
*/
public fun prettyPrint(
node: TomlNode,
result: StringBuilder,
emitLine: Boolean = false,
level: Int = 0
) {
val spaces = " ".repeat(INDENTING_LEVEL * level)
result.append("$spaces - ${node::class.simpleName} ($node)\n")
// we are using print() method here instead of toString()
result.append("$spaces - ${node.print(emitLine)}")
node.children.forEach { child ->
prettyPrint(child, result, level + 1)
prettyPrint(child, result, emitLine, level + 1)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class TomlLiteralString internal constructor(
content: String,
lineNo: Int,
config: TomlInputConfig = TomlInputConfig()
) : this(content.verifyAndTrimQuotes(lineNo, config))
) : this(content.verifyAndTrimQuotes(lineNo, config), content.contains("\n"))

@Deprecated(
message = "TomlConfig is deprecated; use TomlInputConfig instead. Will be removed in next releases."
Expand All @@ -45,7 +45,7 @@ public class TomlLiteralString internal constructor(

override fun write(
emitter: TomlEmitter,
config: TomlOutputConfig
config: TomlOutputConfig,
) {
val content = content as String

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,9 @@ public abstract class TomlEmitter(config: TomlOutputConfig) {
val quotes = if (isLiteral) "'''" else "\"\"\""

emit(quotes)
.emitNewLine()
.emit(string)
.emitNewLine()
.emit(quotes)
} else {
val quote = if (isLiteral) '\'' else '"'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -269,16 +269,22 @@ class EncodingAnnotationTest {
value = File(),
expectedToml = """
mlTextA = $tripleQuotes
\tMultiline
text!
$tripleQuotes
mlTextB = $tripleQuotes
Text with escaped quotes ""\"\
and line break
$tripleQuotes
mlTextC = '''
"Multiline
text!"
'''
""".trimIndent()
)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.akuleshov7.ktoml.encoders

import com.akuleshov7.ktoml.annotations.TomlLiteral
import com.akuleshov7.ktoml.annotations.TomlMultiline
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import kotlin.test.Test
Expand Down Expand Up @@ -81,6 +82,38 @@ class PrimitiveEncoderTest {
)
}

@Test
fun multilineStringsSpecifications() {
@Serializable
data class MultilineLiteralStr(
@TomlMultiline
@TomlLiteral
val a: String
)

@Serializable
data class MultilineBasicStr(
@TomlMultiline
val a: String
)

assertEncodedEquals(
value = MultilineLiteralStr("test \n test \n test \'\'\'"),
expectedToml = """
|a = '''
|test
| test
| test ''\'
|'''
""".trimMargin()
)

assertEncodedEquals(
value = MultilineBasicStr("test \n test \n test \'\'\'"),
expectedToml = "a = \"\"\"\ntest \n test \n test \'\'\'\n\"\"\""
)
}

@Test
fun jsWholeDoubleRegression() {
@Serializable
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
package com.akuleshov7.ktoml.parsers

import com.akuleshov7.ktoml.Toml
import kotlin.test.Test
import kotlin.test.assertEquals

class SetLineNoTest {
@Test
fun checkingLineNumbersGeneral() {
val string =
"""
# comment 1
[a] # comment 2
# comment 3
test = 1 # comment 4
# ====
[[a.b]] # comment 5
test = 1
mlls = '''
1
2
3
'''
mla = [
"a",
"b",
"c"
]
""".trimIndent()
val parsedToml = Toml.tomlParser.parseString(string)

parsedToml.prettyPrint(true)
assertEquals(
"""
| - TomlFile (rootNode)[line:0]
| - TomlTablePrimitive ([a])[line:4]
| - TomlKeyValuePrimitive (test=1)[line:6]
| - TomlArrayOfTables ([[a.b]])[line:10]
| - TomlArrayOfTablesElement (technical_node)[line:10]
| - TomlKeyValuePrimitive (test=1)[line:11]
| - TomlKeyValuePrimitive (mlls='''
| 1
| 2
| 3
|
|''')[line:13]
| - TomlKeyValueArray (mla=[ "a", "b", "c" ])[line:18]
|
""".trimMargin(),
parsedToml.prettyStr(true)
)
}

@Test
fun checkingLineNumbers() {
val string = "\n\n" +
"mlls = '''\n" +
"1\n" +
"\n" +
"2\n" +
"3" +
"'''"
val parsedToml = Toml.tomlParser.parseString(string)
parsedToml.prettyPrint(true)

assertEquals(
"""
| - TomlFile (rootNode)[line:0]
| - TomlKeyValuePrimitive (mlls='''
|1
|
|2
|3
|''')[line:3]
|
""".trimMargin(),
parsedToml.prettyStr(true)
)
}
}

0 comments on commit 76bcae0

Please sign in to comment.