Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

context dependency injection #320

Merged
merged 4 commits into from
Jan 24, 2025
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
3 changes: 2 additions & 1 deletion examples/gradle-ktor/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import community.flock.wirespec.compiler.core.emit.shared.KotlinShared
import community.flock.wirespec.compiler.core.parse.AST
import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.utils.noLogger
import community.flock.wirespec.plugin.FileExtension
import community.flock.wirespec.plugin.Language
import community.flock.wirespec.plugin.gradle.CompileWirespecTask
Expand Down Expand Up @@ -80,7 +81,7 @@ tasks.register<CompileWirespecTask>("wirespec-typescript") {
languages = listOf(Language.TypeScript)
}

class KotlinSerializableEmitter : KotlinEmitter("community.flock.wirespec.generated.kotlin") {
class KotlinSerializableEmitter : KotlinEmitter("community.flock.wirespec.generated.kotlin", noLogger) {

override fun emit(type: Type, ast: AST): String = """
|@kotlinx.serialization.Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,42 +3,40 @@ package community.flock.wirespec.compiler.core
import arrow.core.Either
import arrow.core.Nel
import arrow.core.NonEmptyList
import community.flock.wirespec.compiler.core.Reported.EMITTED
import community.flock.wirespec.compiler.core.Reported.PARSED
import community.flock.wirespec.compiler.core.Reported.TOKENIZED
import community.flock.wirespec.compiler.core.Reported.VALIDATED
import community.flock.wirespec.compiler.core.Stage.EMITTED
import community.flock.wirespec.compiler.core.Stage.PARSED
import community.flock.wirespec.compiler.core.Stage.TOKENIZED
import community.flock.wirespec.compiler.core.Stage.VALIDATED
import community.flock.wirespec.compiler.core.emit.common.Emitted
import community.flock.wirespec.compiler.core.emit.common.Emitter
import community.flock.wirespec.compiler.core.emit.common.HasEmitter
import community.flock.wirespec.compiler.core.exceptions.WirespecException
import community.flock.wirespec.compiler.core.parse.AST
import community.flock.wirespec.compiler.core.parse.Parser
import community.flock.wirespec.compiler.core.tokenize.tokenize
import community.flock.wirespec.compiler.core.validate.validate
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.HasLogger

fun LanguageSpec.parse(source: String): (Logger) -> Either<NonEmptyList<WirespecException>, AST> =
{ logger ->
tokenize(source)
.also((TOKENIZED::report)(logger))
.let(Parser(logger)::parse)
.also((PARSED::report)(logger))
.map { it.validate() }
.also((VALIDATED::report)(logger))
}
interface CompilationContext : ParseContext, HasEmitter

fun LanguageSpec.compile(source: String): (Logger) -> (Emitter) -> Either<Nel<WirespecException>, List<Emitted>> =
{ logger ->
{ emitter ->
parse(source)(logger)
.map(emitter::emit)
.also((EMITTED::report)(logger))
}
}
fun CompilationContext.compile(source: String): Either<Nel<WirespecException>, List<Emitted>> =
parse(source)
.map(emitter::emit)
.also(EMITTED::log)

interface ParseContext : HasLanguageSpec, HasLogger

fun ParseContext.parse(source: String): Either<NonEmptyList<WirespecException>, AST> =
spec.tokenize(source)
.also(TOKENIZED::log)
.let(Parser(logger)::parse)
.also(PARSED::log)
.map { it.validate() }
.also(VALIDATED::log)

private enum class Reported {
private enum class Stage {
TOKENIZED, PARSED, VALIDATED, EMITTED;

fun report(logger: Logger): (Any) -> Unit = {
fun log(it: Any): HasLogger.() -> Unit = {
logger.info("********** $name **********\n$it\n########## $name ##########")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ interface LanguageSpec {
val orderedMatchers: List<TokenMatcher>
}

interface HasLanguageSpec {
val spec: LanguageSpec get() = WirespecSpec
}

object WirespecSpec : LanguageSpec {
override val customType = WsCustomType
override val orderedMatchers = listOf(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,10 @@ import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.core.parse.Union
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.noLogger

open class JavaEmitter(
private val packageName: String = DEFAULT_GENERATED_PACKAGE_STRING,
logger: Logger = noLogger,
logger: Logger,
) : DefinitionModelEmitter, Emitter(logger, true) {

val import = """
Expand Down Expand Up @@ -275,12 +274,7 @@ open class JavaEmitter(
""".trimMargin()

fun Endpoint.Response.emit() = """
|${Spacer}record Response${status.firstToUpper()}(${
listOfNotNull(
headers.joinToString { it.emit() }.orNull(),
content?.let { "${it.emit()} body" }
).joinToString()
}) implements Response${status.first()}XX<${content.emit()}>, Response${content.emit().concatGenerics()} {
|${Spacer}record Response${status.firstToUpper()}(${listOfNotNull(headers.joinToString { it.emit() }.orNull(), content?.let { "${it.emit()} body" }).joinToString()}) implements Response${status.first()}XX<${content.emit()}>, Response${content.emit().concatGenerics()} {
|${Spacer(2)}@Override public int getStatus() { return ${status.fixStatus()}; }
|${Spacer(2)}${headers.joinToString { emit(it.identifier) }.let { "@Override public Headers getHeaders() { return new Headers($it); }" }}
|${Spacer(2)}@Override public ${content.emit()} getBody() { return ${if(content == null) "null" else "body"}; }
Expand Down Expand Up @@ -354,7 +348,7 @@ open class JavaEmitter(
else -> this
}

fun String.sanitizeSymbol() = this
private fun String.sanitizeSymbol() = this
.split(".", " ", "-")
.mapIndexed { index, s -> if(index > 0) s.firstToUpper() else s }
.joinToString("")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,10 @@ import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.core.parse.Union
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.noLogger

open class KotlinEmitter(
private val packageName: String = DEFAULT_GENERATED_PACKAGE_STRING,
logger: Logger = noLogger,
logger: Logger,
) : DefinitionModelEmitter, Emitter(logger, false) {

val import = """
Expand Down Expand Up @@ -322,5 +321,4 @@ open class KotlinEmitter(
"typeof", "val", "var", "when", "while", "private", "public"
)
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,10 @@ import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.core.parse.Union
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.noLogger

open class ScalaEmitter(
private val packageName: String = DEFAULT_GENERATED_PACKAGE_STRING,
logger: Logger = noLogger
logger: Logger,
) : DefinitionModelEmitter, Emitter(logger) {

val import = """
Expand Down Expand Up @@ -79,14 +78,16 @@ open class ScalaEmitter(
is Reference.Custom -> value
is Reference.Primitive -> when (type) {
is Reference.Primitive.Type.String -> "String"
is Reference.Primitive.Type.Integer -> when(type.precision){
is Reference.Primitive.Type.Integer -> when (type.precision) {
Reference.Primitive.Type.Precision.P32 -> "Int"
Reference.Primitive.Type.Precision.P64 -> "Long"
}
is Reference.Primitive.Type.Number -> when(type.precision){

is Reference.Primitive.Type.Number -> when (type.precision) {
Reference.Primitive.Type.Precision.P32 -> "Float"
Reference.Primitive.Type.Precision.P64 -> "Double"
}

is Reference.Primitive.Type.Boolean -> "Boolean"
is Reference.Primitive.Type.Bytes -> "Array[Byte]"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,8 @@ import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.core.parse.Union
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.noLogger

open class TypeScriptEmitter(logger: Logger = noLogger) : DefinitionModelEmitter, Emitter(logger) {
open class TypeScriptEmitter(logger: Logger) : DefinitionModelEmitter, Emitter(logger) {

override fun Definition.emitName(): String = when (this) {
is Endpoint -> emit(identifier)
Expand Down Expand Up @@ -149,7 +148,9 @@ open class TypeScriptEmitter(logger: Logger = noLogger) : DefinitionModelEmitter
""".trimIndent()

private fun Endpoint.Request.emitFunction(endpoint: Endpoint) = """
|${Spacer}export const request = (${paramList(endpoint).takeIf { it.isNotEmpty() }?.let { "props: ${it.joinToObject { it.emit() }}" }.orEmpty()}): Request => ({
|${Spacer}export const request = (${
paramList(endpoint).takeIf { it.isNotEmpty() }?.let { "props: ${it.joinToObject { it.emit() }}" }.orEmpty()
}): Request => ({
|${Spacer(2)}path: ${endpoint.pathParams.joinToObject { "${emit(it.identifier)}: props.${emit(it.identifier)}" }},
|${Spacer(2)}method: "${endpoint.method}",
|${Spacer(2)}queries: ${endpoint.queries.joinToObject { "${emit(it.identifier)}: props.${emit(it.identifier)}" }},
Expand All @@ -159,7 +160,9 @@ open class TypeScriptEmitter(logger: Logger = noLogger) : DefinitionModelEmitter
""".trimIndent()

private fun Endpoint.Response.emitFunction(endpoint: Endpoint) = """
|${Spacer}export const response${status.firstToUpper()} = (${paramList().takeIf { it.isNotEmpty() }?.let { "props: ${it.joinToObject { it.emit() }}" }.orEmpty()}): Response${status.firstToUpper()} => ({
|${Spacer}export const response${status.firstToUpper()} = (${
paramList().takeIf { it.isNotEmpty() }?.let { "props: ${it.joinToObject { it.emit() }}" }.orEmpty()
}): Response${status.firstToUpper()} => ({
|${Spacer(2)}status: ${status},
|${Spacer(2)}headers: ${endpoint.headers.joinToObject { "${emit(it.identifier)}: props.${emit(it.identifier)}" }},
|${Spacer(2)}body: ${content?.let { "props.body" } ?: "undefined"},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,8 @@ import community.flock.wirespec.compiler.core.parse.Refined
import community.flock.wirespec.compiler.core.parse.Type
import community.flock.wirespec.compiler.core.parse.Union
import community.flock.wirespec.compiler.utils.Logger
import community.flock.wirespec.compiler.utils.noLogger

open class WirespecEmitter(logger: Logger = noLogger) : DefinitionModelEmitter, Emitter(logger) {
open class WirespecEmitter(logger: Logger) : DefinitionModelEmitter, Emitter(logger) {

override fun Definition.emitName(): String = when (this) {
is Endpoint -> emit(identifier)
Expand All @@ -46,9 +45,11 @@ open class WirespecEmitter(logger: Logger = noLogger) : DefinitionModelEmitter,

override fun Field.emit() = "${emit(identifier)}: ${reference.emit()}${if (isNullable) "?" else ""}"

override fun emit(identifier: Identifier) = when(identifier){
is DefinitionIdentifier -> identifier.run { if (value in reservedKeywords) value.addBackticks() else value }
is FieldIdentifier -> identifier.run { if (value in reservedKeywords || value.first().isUpperCase()) value.addBackticks() else value }
override fun emit(identifier: Identifier) = when (identifier) {
is DefinitionIdentifier -> identifier.run { if (value in reservedKeywords) value.addBackticks() else value }
is FieldIdentifier -> identifier.run {
if (value in reservedKeywords || value.first().isUpperCase()) value.addBackticks() else value
}
}

override fun emit(channel: Channel): String =
Expand All @@ -62,11 +63,12 @@ open class WirespecEmitter(logger: Logger = noLogger) : DefinitionModelEmitter,
is Reference.Primitive.Type.String -> "String"
is Reference.Primitive.Type.Boolean -> "Boolean"
is Reference.Primitive.Type.Bytes -> "Bytes"
is Reference.Primitive.Type.Integer -> when(type.precision){
is Reference.Primitive.Type.Integer -> when (type.precision) {
Reference.Primitive.Type.Precision.P32 -> "Integer32"
Reference.Primitive.Type.Precision.P64 -> "Integer"
}
is Reference.Primitive.Type.Number -> when(type.precision){

is Reference.Primitive.Type.Number -> when (type.precision) {
Reference.Primitive.Type.Precision.P32 -> "Number32"
Reference.Primitive.Type.Precision.P64 -> "Number"
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,7 @@ abstract class Emitter(
)
}
}

interface HasEmitter {
val emitter: Emitter
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,4 +43,8 @@ open class Logger(logLevel: Level?) {
}
}

interface HasLogger {
val logger: Logger
}

val noLogger = object : Logger(logLevel = null) {}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ class CompileChannelTest {
|
""".trimMargin()

compiler(KotlinEmitter()) shouldBeRight kotlin
compiler { KotlinEmitter(logger = it) } shouldBeRight kotlin
}

@Test
Expand All @@ -39,7 +39,7 @@ class CompileChannelTest {
|
""".trimMargin()

compiler(JavaEmitter()) shouldBeRight java
compiler { JavaEmitter(logger = it) } shouldBeRight java
}

@Test
Expand All @@ -51,7 +51,7 @@ class CompileChannelTest {
|
""".trimMargin()

compiler(ScalaEmitter()) shouldBeRight scala
compiler { ScalaEmitter(logger = it) } shouldBeRight scala
}

@Test
Expand All @@ -61,7 +61,7 @@ class CompileChannelTest {
|
""".trimMargin()

compiler(TypeScriptEmitter()) shouldBeRight ts
compiler { TypeScriptEmitter(logger = it) } shouldBeRight ts
}

@Test
Expand All @@ -70,6 +70,6 @@ class CompileChannelTest {
|channel Queue -> String
""".trimMargin()

compiler(WirespecEmitter()) shouldBeRight wirespec
compiler { WirespecEmitter(logger = it) } shouldBeRight wirespec
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ class CompileEnumTest {
|
""".trimMargin()

compiler(KotlinEmitter()) shouldBeRight kotlin
compiler { KotlinEmitter(logger = it) } shouldBeRight kotlin
}

@Test
Expand Down Expand Up @@ -67,7 +67,7 @@ class CompileEnumTest {
|
""".trimMargin()

compiler(JavaEmitter()) shouldBeRight java
compiler { JavaEmitter(logger = it) } shouldBeRight java
}

@Test
Expand All @@ -87,7 +87,7 @@ class CompileEnumTest {
|
""".trimMargin()

compiler(ScalaEmitter()) shouldBeRight scala
compiler { ScalaEmitter(logger = it) } shouldBeRight scala
}

@Test
Expand All @@ -97,7 +97,7 @@ class CompileEnumTest {
|
""".trimMargin()

compiler(TypeScriptEmitter()) shouldBeRight ts
compiler { TypeScriptEmitter(logger = it) } shouldBeRight ts
}

@Test
Expand All @@ -109,6 +109,6 @@ class CompileEnumTest {
|
""".trimMargin()

compiler(WirespecEmitter()) shouldBeRight wirespec
compiler { WirespecEmitter(logger = it) } shouldBeRight wirespec
}
}
Loading
Loading