Skip to content

Commit

Permalink
Initial implementation of ArrayOfTables
Browse files Browse the repository at this point in the history
### What's done:
- Small refactoring related to sealed classes limitations
- Initial test impplemetation of array of tables
- Kotlin update to 1.6.10
  • Loading branch information
orchestr7 committed Feb 11, 2022
1 parent a5a7801 commit 769eb2a
Show file tree
Hide file tree
Showing 16 changed files with 89 additions and 59 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ As this young and big project [is needed](https://github.com/Kotlin/kotlinx.seri
We will be glad if you will test `ktoml` or contribute to this project.
In case you don't have much time for this - at least spend 5 seconds to give us a star to attract other contributors!

**Thanks!** :pray:
**Thanks!** :pray: :partying_face:

## Acknowledgement
Special thanks to those awesome developers who give us great suggestions, help us to maintain and improve this project:
Expand Down
4 changes: 4 additions & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,10 @@ allprojects {
}
configureDiktat()
configureDetekt()

tasks.withType<org.cqfn.diktat.plugin.gradle.DiktatJavaExecTaskBase> {
jvmArgs("--add-opens", "java.base/java.lang=ALL-UNNAMED")
}
}
createDiktatTask()
createDetektTask()
Expand Down
2 changes: 1 addition & 1 deletion diktat-analysis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
configuration:
useRecommendedImportsOrder: true
- name: FILE_WILDCARD_IMPORTS
enabled: true
enabled: false
configuration:
allowedWildcards: "kotlinx.serialization.*"
- name: BRACES_BLOCK_STRUCTURE_ERROR
Expand Down
2 changes: 0 additions & 2 deletions ktoml-core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
import com.akuleshov7.buildutils.configurePublishing
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem
import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest

plugins {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ public value class TomlParser(private val config: TomlConfig) {
* @return the root node of the resulted toml tree
* @throws InternalAstException - if toml node does not inherit TomlNode class
*/
@Suppress("TOO_LONG_FUNCTION")
public fun parseStringsToTomlTree(tomlLines: List<String>, config: TomlConfig): TomlFile {
var currentParentalNode: TomlNode = TomlFile(config)
val tomlFileHead = currentParentalNode as TomlFile
Expand Down Expand Up @@ -74,7 +75,7 @@ public value class TomlParser(private val config: TomlConfig) {
throw InternalAstException("All Toml nodes should always inherit TomlNode class." +
" Check [${keyValue.key}] with $keyValue type")
}

// inserting the key-value record to the tree
if (keyValue.key.isDotted) {
// in case parser has faced dot-separated complex key (a.b.c) it should create proper table [a.b],
// because table is the same as dotted key
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
/**
* Array of tables https://toml.io/en/v1.0.0#array-of-tables
*/

package com.akuleshov7.ktoml.tree

import com.akuleshov7.ktoml.TomlConfig
Expand All @@ -6,36 +10,31 @@ import com.akuleshov7.ktoml.parsers.splitKeyToTokens
import com.akuleshov7.ktoml.parsers.trimDoubleBrackets
import com.akuleshov7.ktoml.parsers.trimQuotes

/**
* @property isSynthetic
*/
// FixMe: this class is mostly identical to the TomlTable - we should unify them together
public class TomlArrayOfTables(
content: String,
lineNo: Int,
config: TomlConfig = TomlConfig(),
public val isSynthetic: Boolean = false
) : TomlTable(content, lineNo, config) {
) : TomlTable(
content,
lineNo,
config
) {
public override val type: TableType = TableType.ARRAY

// short table name (only the name without parental prefix, like a - it is used in decoder and encoder)
override val name: String

// list of tables (including sub-tables) that are included in this table (e.g.: {a, a.b, a.b.c} in a.b.c)
public override lateinit var tablesList: List<String>

// full name of the table (like a.b.c.d)
public override lateinit var fullTableName: String

// short table name (only the name without parental prefix, like a - it is used in decoder and encoder)
override val name: String

internal val keyValues: MutableList<MutableList<TomlKeyValue>> = mutableListOf()

internal fun insertKeyValue(keyValue: TomlKeyValue, isNewElementInArray: Boolean) {
if (isNewElementInArray) {
// creating a new bucket for the array
keyValues.add(mutableListOf(keyValue))
} else {
// adding new keyValue to the last bucket (it should have been created on the previous step)
keyValues[keyValues.lastIndex].add(keyValue)
}
}

init {
// getting the content inside brackets ([a.b] -> a.b)
val sectionFromContent = content.trim().trimDoubleBrackets().trim()
Expand All @@ -55,15 +54,12 @@ public class TomlArrayOfTables(
}

/**
* this is a hack to cover empty TOML tables that have missing key-values
* According the spec: "Empty tables are allowed and simply have no key/value pairs within them."
*
* Instances of this stub will be added as children to such parsed tables
* This class is used to store elements of array of tables (bucket for key-value records)
*/
public class TomlArrayOfTablesElement(lineNo: Int, config: TomlConfig = TomlConfig()) : TomlNode(
EMPTY_TECHNICAL_NODE,
lineNo,
config) {
config
) {
override val name: String = EMPTY_TECHNICAL_NODE
}

Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,10 @@ import com.akuleshov7.ktoml.exceptions.InternalAstException
public class TomlFile(config: TomlConfig = TomlConfig()) : TomlNode(
"rootNode",
0,
config) {
config
) {
override val name: String = "rootNode"

override fun getNeighbourNodes(): MutableSet<TomlNode> =
throw InternalAstException("Invalid call to getNeighbourNodes() for TomlFile node")
throw InternalAstException("Invalid call to getNeighbourNodes() for TomlFile node")
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ package com.akuleshov7.ktoml.tree
import com.akuleshov7.ktoml.TomlConfig

/**
* Class for parsing and storing Array in AST. It receives a pair of two strings as an input and converts it to a pair
* of TomlKey and TomlValue (as TomlArray)
* Class for parsing and storing Array of Tables in AST.
* @property lineNo
* @property key
* @property value
Expand All @@ -16,7 +15,12 @@ public class TomlKeyValueArray(
override val lineNo: Int,
override val name: String,
config: TomlConfig = TomlConfig()
) : TomlNode(key, value, lineNo, config), TomlKeyValue {
) : TomlNode(
key,
value,
lineNo,
config
), TomlKeyValue {
// adaptor for a string pair of key-value
public constructor(
keyValuePair: Pair<String, String>,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,12 @@ public class TomlKeyValuePrimitive(
override val lineNo: Int,
override val name: String,
config: TomlConfig = TomlConfig()
) : TomlNode(key, value, lineNo, config), TomlKeyValue {
) : TomlNode(
key,
value,
lineNo,
config
), TomlKeyValue {
// adaptor for a string pair of key-value
public constructor(
keyValuePair: Pair<String, String>,
Expand All @@ -28,4 +33,3 @@ public class TomlKeyValuePrimitive(
TomlKey(keyValuePair.first, lineNo).content
)
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

package com.akuleshov7.ktoml.tree

import com.akuleshov7.ktoml.Toml
import com.akuleshov7.ktoml.TomlConfig
import com.akuleshov7.ktoml.exceptions.ParseException

Expand Down Expand Up @@ -38,7 +37,8 @@ public sealed class TomlNode(
key: TomlKey,
value: TomlValue,
lineNo: Int,
config: TomlConfig = TomlConfig()) : this(
config: TomlConfig = TomlConfig()
) : this(
"${key.content}=${value.content}",
lineNo,
config
Expand Down Expand Up @@ -75,9 +75,9 @@ public sealed class TomlNode(
type: TableType
): List<TomlTable> {
val result =
// we need to filter nodes by the type of table that we are inserting to the tree (array/primitive)
// we need to filter nodes by the type of table that we are inserting to the tree (array/primitive)
if (this is TomlTable && this.type == type &&
this.fullTableName == searchedTableName && currentLevel == searchedLevel) {
this.fullTableName == searchedTableName && currentLevel == searchedLevel) {
mutableListOf(this)
} else {
mutableListOf()
Expand All @@ -104,10 +104,15 @@ public sealed class TomlNode(
* a.c a.d
* \
* a.d.e
* @param type
* @return table that was found or null in case of not found
* @throws ParseException if found several tables with the same name
*/
public fun findTableInAstByName(searchedTableName: String, searchedLevel: Int, type: TableType): TomlTable? {
public fun findTableInAstByName(
searchedTableName: String,
searchedLevel: Int,
type: TableType
): TomlTable? {
val searchedTable = findTableInAstByName(searchedTableName, searchedLevel, 0, type)

if (searchedTable.size > 1) {
Expand All @@ -119,15 +124,15 @@ public sealed class TomlNode(
return if (searchedTable.isEmpty()) null else searchedTable[0]
}


/**
* Method inserts a table (section) to tree. It parses the section name and creates all missing nodes in the tree
* (even parental). For [a.b.c] it will create 3 nodes: a, b, and c
*
* @param tomlTable - a table (section) that should be inserted into the tree
* @param type
* @return inserted table
*/
public fun <T: TomlTable> insertTableToTree(tomlTable: T, type: TableType): TomlNode {
public fun <T : TomlTable> insertTableToTree(tomlTable: T, type: TableType): TomlNode {
// prevParentNode - saved node that is used in a chain
var prevParentNode: TomlNode = this
// [a.b.c.d] -> for each section node checking existing node in a tree
Expand Down Expand Up @@ -209,4 +214,3 @@ public sealed class TomlNode(
}
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import com.akuleshov7.ktoml.TomlConfig
public class TomlStubEmptyNode(lineNo: Int, config: TomlConfig = TomlConfig()) : TomlNode(
EMPTY_TECHNICAL_NODE,
lineNo,
config) {
config
) {
override val name: String = EMPTY_TECHNICAL_NODE
}
Original file line number Diff line number Diff line change
@@ -1,22 +1,36 @@
/**
* Common class for tables
*/

package com.akuleshov7.ktoml.tree

import com.akuleshov7.ktoml.TomlConfig
import com.akuleshov7.ktoml.exceptions.ParseException

/**
* Interface that contains all common methods that are used in KeyValue nodes
* Abstract class to represent all types of tables: primitive/arrays/etc.
* @property content - raw string name of the table
* @property lineNo - line number
* @property config - toml configuration
*/
public abstract class TomlTable (
public abstract class TomlTable(
override val content: String,
override val lineNo: Int,
override val config: TomlConfig = TomlConfig()
): TomlNode(content, lineNo, config) {
abstract public var fullTableName: String
abstract public var tablesList: List<String>
abstract public val type: TableType
) : TomlNode(
content,
lineNo,
config
) {
public abstract var fullTableName: String
public abstract var tablesList: List<String>
public abstract val type: TableType
}

/**
* Special Enum that is used in a logic related to insertion of tables to AST
*/
public enum class TableType {
ARRAY,
PRIMITIVE
PRIMITIVE,
;
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,18 +20,20 @@ public class TomlTablePrimitive(
content: String,
lineNo: Int,
config: TomlConfig = TomlConfig(),
public val isSynthetic: Boolean = false) : TomlTable(
public val isSynthetic: Boolean = false
) : TomlTable(
content,
lineNo,
config) {
config
) {
public override val type: TableType = TableType.PRIMITIVE

// list of tables (including sub-tables) that are included in this table (e.g.: {a, a.b, a.b.c} in a.b.c)
public override lateinit var tablesList: List<String>

// short table name (only the name without parental prefix, like a - it is used in decoder and encoder)
override val name: String

// list of tables (including sub-tables) that are included in this table (e.g.: {a, a.b, a.b.c} in a.b.c)
public override lateinit var tablesList: List<String>

// full name of the table (like a.b.c.d)
public override lateinit var fullTableName: String

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,8 @@ internal constructor(
) : this(
rawContent.parse(lineNo, config),
rawContent,
lineNo) {
lineNo
) {
validateBrackets()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,7 +146,8 @@ public abstract class TomlEmitter(config: TomlConfig) {
public fun emitValue(
string: String,
isLiteral: Boolean = false,
isMultiline: Boolean = false): Unit =
isMultiline: Boolean = false
): Unit =
if (isMultiline) {
val quotes = if (isLiteral) "'''" else "\"\"\""

Expand Down
1 change: 0 additions & 1 deletion ktoml-file/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import com.akuleshov7.buildutils.configurePublishing
import org.gradle.nativeplatform.platform.internal.DefaultNativePlatform.getCurrentOperatingSystem
import org.jetbrains.kotlin.gradle.targets.jvm.tasks.KotlinJvmTest

plugins {
Expand Down

0 comments on commit 769eb2a

Please sign in to comment.