Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ dependencies {
kover(project(":semantic"))
kover(project(":cli"))
kover(project(":language-server"))
kover(project(":samt-config"))
}

koverReport {
Expand Down
26 changes: 26 additions & 0 deletions common/src/main/kotlin/tools/samt/common/SamtConfiguration.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package tools.samt.common

data class SamtConfiguration(
val source: String,
val plugins: List<SamtPluginConfiguration>,
val generators: List<SamtGeneratorConfiguration>,
)

sealed interface SamtPluginConfiguration

data class SamtLocalPluginConfiguration(
val path: String,
) : SamtPluginConfiguration

data class SamtMavenPluginConfiguration(
val groupId: String,
val artifactId: String,
val version: String,
val repository: String,
) : SamtPluginConfiguration

data class SamtGeneratorConfiguration(
val name: String,
val output: String,
val options: Map<String, String>,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
package tools.samt.common

data class SamtLinterConfiguration(
val splitModelAndProviders: SplitModelAndProvidersConfiguration,
val namingConventions: NamingConventionsConfiguration,
)

sealed interface SamtRuleConfiguration {
val level: DiagnosticSeverity?
}

data class SplitModelAndProvidersConfiguration(
override val level: DiagnosticSeverity?,
) : SamtRuleConfiguration

data class NamingConventionsConfiguration(
override val level: DiagnosticSeverity?,
val record: NamingConvention,
val recordField: NamingConvention,
val enum: NamingConvention,
val enumValue: NamingConvention,
val typeAlias: NamingConvention,
val service: NamingConvention,
val serviceOperation: NamingConvention,
val serviceOperationParameter: NamingConvention,
val provider: NamingConvention,
val samtPackage: NamingConvention,
val fileName: NamingConvention,
) : SamtRuleConfiguration {
enum class NamingConvention {
PascalCase,
CamelCase,
SnakeCase,
KebabCase,
ScreamingSnakeCase,
}
}
9 changes: 9 additions & 0 deletions samt-config/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
plugins {
id("samt-core.kotlin-conventions")
alias(libs.plugins.kover)
}

dependencies {
implementation(project(":common"))
implementation(libs.kotlinx.serialization.yaml)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
package tools.samt.config

import tools.samt.common.DiagnosticSeverity as CommonDiagnosticSeverity
import tools.samt.common.NamingConventionsConfiguration.NamingConvention as CommonNamingConvention

val recommended = tools.samt.common.SamtLinterConfiguration(
splitModelAndProviders = tools.samt.common.SplitModelAndProvidersConfiguration(
level = CommonDiagnosticSeverity.Info,
),
namingConventions = tools.samt.common.NamingConventionsConfiguration(
level = CommonDiagnosticSeverity.Warning,
record = CommonNamingConvention.PascalCase,
recordField = CommonNamingConvention.CamelCase,
enum = CommonNamingConvention.PascalCase,
enumValue = CommonNamingConvention.ScreamingSnakeCase,
typeAlias = CommonNamingConvention.PascalCase,
service = CommonNamingConvention.PascalCase,
serviceOperation = CommonNamingConvention.CamelCase,
serviceOperationParameter = CommonNamingConvention.CamelCase,
provider = CommonNamingConvention.PascalCase,
samtPackage = CommonNamingConvention.SnakeCase,
fileName = CommonNamingConvention.KebabCase,
),
)

val strict = recommended.copy(
splitModelAndProviders = recommended.splitModelAndProviders.copy(level = CommonDiagnosticSeverity.Warning),
namingConventions = recommended.namingConventions.copy(level = CommonDiagnosticSeverity.Error),
)
49 changes: 49 additions & 0 deletions samt-config/src/main/kotlin/tools/samt/config/SamtConfiguration.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
package tools.samt.config

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class SamtConfiguration(
val source: String = "./src",
val repositories: SamtRepositoriesConfiguration = SamtRepositoriesConfiguration(),
val plugins: List<SamtPluginConfiguration> = emptyList(),
val generators: List<SamtGeneratorConfiguration> = emptyList(),
)

@Serializable
data class SamtRepositoriesConfiguration(
val maven: String = "https://repo.maven.apache.org/maven2"
)

@Serializable
sealed interface SamtPluginConfiguration

@Serializable
@SerialName("local")
data class SamtLocalPluginConfiguration(
val path: String,
) : SamtPluginConfiguration

@Serializable
@SerialName("maven")
data class SamtMavenPluginConfiguration(
val groupId: String,
val artifactId: String,
val version: String,
val repository: String? = null,
) : SamtPluginConfiguration

@Serializable
@SerialName("gradle")
data class SamtGradlePluginConfiguration(
val dependency: String,
val repository: String? = null,
) : SamtPluginConfiguration

@Serializable
data class SamtGeneratorConfiguration(
val name: String,
val output: String = "./out",
val options: Map<String, String> = emptyMap(),
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
package tools.samt.config

import com.charleskorn.kaml.*
import java.nio.file.Path
import kotlin.io.path.exists
import kotlin.io.path.inputStream
import tools.samt.common.DiagnosticSeverity as CommonDiagnosticSeverity
import tools.samt.common.NamingConventionsConfiguration as CommonNamingConventionsConfiguration
import tools.samt.common.NamingConventionsConfiguration.NamingConvention as CommonNamingConvention
import tools.samt.common.SamtConfiguration as CommonSamtConfiguration
import tools.samt.common.SamtGeneratorConfiguration as CommonGeneratorConfiguration
import tools.samt.common.SamtLinterConfiguration as CommonLinterConfiguration
import tools.samt.common.SamtLocalPluginConfiguration as CommonLocalPluginConfiguration
import tools.samt.common.SamtMavenPluginConfiguration as CommonMavenPluginConfiguration
import tools.samt.common.SplitModelAndProvidersConfiguration as CommonSplitModelAndProvidersConfiguration

object SamtConfigurationParser {
private val yaml = Yaml(
configuration = YamlConfiguration(
encodeDefaults = false,
polymorphismStyle = PolymorphismStyle.Property,
singleLineStringStyle = SingleLineStringStyle.Plain,
)
)

fun parseConfiguration(path: Path): CommonSamtConfiguration {
val parsedConfiguration: SamtConfiguration = if (path.exists()) {
yaml.decodeFromStream(path.inputStream())
} else {
SamtConfiguration()
}

return CommonSamtConfiguration(
source = parsedConfiguration.source,
plugins = parsedConfiguration.plugins.map { plugin ->
when (plugin) {
is SamtLocalPluginConfiguration -> CommonLocalPluginConfiguration(
path = plugin.path
)

is SamtMavenPluginConfiguration -> CommonMavenPluginConfiguration(
groupId = plugin.groupId,
artifactId = plugin.artifactId,
version = plugin.version,
repository = plugin.repository ?: parsedConfiguration.repositories.maven
)

is SamtGradlePluginConfiguration -> CommonMavenPluginConfiguration(
groupId = plugin.dependency.split(':')[0],
artifactId = plugin.dependency.split(':')[1],
version = plugin.dependency.split(':')[2],
repository = plugin.repository ?: parsedConfiguration.repositories.maven
)
}
},
generators = parsedConfiguration.generators.map { generator ->
CommonGeneratorConfiguration(
name = generator.name,
output = generator.output,
options = generator.options
)
}
)
}

fun parseLinterConfiguration(path: Path): CommonLinterConfiguration {
val parsedLinterConfiguration: SamtLinterConfiguration = if (path.exists()) {
yaml.decodeFromStream(path.inputStream())
} else {
SamtLinterConfiguration()
}

val base = when (parsedLinterConfiguration.extends) {
"recommended" -> recommended
"strict" -> strict
else -> error("TODO")
}

val userSplitModelAndProvidersConfiguration = parsedLinterConfiguration.rules.filterIsInstance<SplitModelAndProvidersConfiguration>().singleOrNull()
val userNamingConventionsConfiguration = parsedLinterConfiguration.rules.filterIsInstance<NamingConventionsConfiguration>().singleOrNull()

return CommonLinterConfiguration(
splitModelAndProviders = CommonSplitModelAndProvidersConfiguration(
level = userSplitModelAndProvidersConfiguration?.level.toLevelOrDefault(base.splitModelAndProviders.level),
),
namingConventions = CommonNamingConventionsConfiguration(
level = userNamingConventionsConfiguration?.level.toLevelOrDefault(base.namingConventions.level),
record = userNamingConventionsConfiguration?.record.toNamingConventionOrDefault(base.namingConventions.record),
recordField = userNamingConventionsConfiguration?.recordField.toNamingConventionOrDefault(base.namingConventions.recordField),
enum = userNamingConventionsConfiguration?.enum.toNamingConventionOrDefault(base.namingConventions.enum),
enumValue = userNamingConventionsConfiguration?.enumValue.toNamingConventionOrDefault(base.namingConventions.enumValue),
typeAlias = userNamingConventionsConfiguration?.typeAlias.toNamingConventionOrDefault(base.namingConventions.typeAlias),
service = userNamingConventionsConfiguration?.service.toNamingConventionOrDefault(base.namingConventions.service),
serviceOperation = userNamingConventionsConfiguration?.serviceOperation.toNamingConventionOrDefault(base.namingConventions.serviceOperation),
serviceOperationParameter = userNamingConventionsConfiguration?.serviceOperationParameter.toNamingConventionOrDefault(base.namingConventions.serviceOperationParameter),
provider = userNamingConventionsConfiguration?.provider.toNamingConventionOrDefault(base.namingConventions.provider),
samtPackage = userNamingConventionsConfiguration?.samtPackage.toNamingConventionOrDefault(base.namingConventions.samtPackage),
fileName = userNamingConventionsConfiguration?.fileName.toNamingConventionOrDefault(base.namingConventions.fileName),
),
)
}

private fun DiagnosticSeverity?.toLevelOrDefault(default: CommonDiagnosticSeverity?): CommonDiagnosticSeverity? = when (this) {
null -> default
DiagnosticSeverity.Error -> CommonDiagnosticSeverity.Error
DiagnosticSeverity.Warn -> CommonDiagnosticSeverity.Warning
DiagnosticSeverity.Info -> CommonDiagnosticSeverity.Info
DiagnosticSeverity.Off -> null
}

private fun NamingConventionsConfiguration.NamingConventions?.toNamingConventionOrDefault(default: CommonNamingConvention): CommonNamingConvention = when (this) {
null -> default
NamingConventionsConfiguration.NamingConventions.PascalCase -> CommonNamingConvention.PascalCase
NamingConventionsConfiguration.NamingConventions.CamelCase -> CommonNamingConvention.CamelCase
NamingConventionsConfiguration.NamingConventions.SnakeCase -> CommonNamingConvention.SnakeCase
NamingConventionsConfiguration.NamingConventions.KebabCase -> CommonNamingConvention.KebabCase
NamingConventionsConfiguration.NamingConventions.ScreamingSnakeCase -> CommonNamingConvention.ScreamingSnakeCase
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
package tools.samt.config

import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable

@Serializable
data class SamtLinterConfiguration(
val extends: String = "recommended",
val rules: List<SamtRuleConfiguration> = emptyList(),
)

enum class DiagnosticSeverity {
@SerialName("error")
Error,

@SerialName("warn")
Warn,

@SerialName("info")
Info,

@SerialName("off")
Off,
}

@Serializable
sealed interface SamtRuleConfiguration {
val level: DiagnosticSeverity?
}

@Serializable
@SerialName("split-model-and-providers")
data class SplitModelAndProvidersConfiguration(
override val level: DiagnosticSeverity? = null,
) : SamtRuleConfiguration

@Serializable
@SerialName("naming-conventions")
data class NamingConventionsConfiguration(
override val level: DiagnosticSeverity? = null,
val record: NamingConventions? = null,
val recordField: NamingConventions? = null,
val enum: NamingConventions? = null,
val enumValue: NamingConventions? = null,
val typeAlias: NamingConventions? = null,
val service: NamingConventions? = null,
val serviceOperation: NamingConventions? = null,
val serviceOperationParameter: NamingConventions? = null,
val provider: NamingConventions? = null,
@SerialName("package")
val samtPackage: NamingConventions? = null,
val fileName: NamingConventions? = null,
) : SamtRuleConfiguration {
enum class NamingConventions {
@SerialName("PascalCase")
PascalCase,
@SerialName("camelCase")
CamelCase,
@SerialName("snake_case")
SnakeCase,
@SerialName("kebab-case")
KebabCase,
@SerialName("SCREAMING_SNAKE_CASE")
ScreamingSnakeCase,
}
}
Loading