Skip to content

Commit

Permalink
Feat path params (#124)
Browse files Browse the repository at this point in the history
  • Loading branch information
jerrevanveluw authored and wilmveel committed Nov 19, 2023
1 parent 90a0b61 commit ce689d0
Show file tree
Hide file tree
Showing 27 changed files with 223 additions and 186 deletions.
6 changes: 6 additions & 0 deletions buildSrc/src/main/java/Versions.kt
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import Versions.ARROW
import Versions.COROUTINES
import Versions.KOTEST
import Versions.KOTEST_ARROW

object Versions {
const val ARROW = "1.2.1"
const val COROUTINES = "1.6.4"
const val INTELLIJ = "1.15.0"
const val KOTEST = "5.7.2"
const val KOTEST_ARROW = "1.4.0"
}

object Libraries {
const val ARROW_CORE = "io.arrow-kt:arrow-core:$ARROW"
const val KOTLIN_COROUTINES = "org.jetbrains.kotlinx:kotlinx-coroutines-core:$COROUTINES"
const val KOTLIN_COROUTINES_NATIVE = "org.jetbrains.kotlinx:kotlinx-coroutines-core-native:$COROUTINES"
const val KOTLIN_COROUTINES_JVM = "org.jetbrains.kotlinx:kotlinx-coroutines-core-jvm:$COROUTINES"
const val KOTEST_ASSERTIONS = "io.kotest:kotest-assertions-core:$KOTEST"
const val KOTEST_ASSERTIONS_ARROW = "io.kotest.extensions:kotest-assertions-arrow:$KOTEST_ARROW"
}

object Plugins {
Expand Down
2 changes: 2 additions & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ pluginManagement {

val kotlinVersion = "1.9.10"
val shadowVersion = "7.1.2"
val kotestVersion = "5.7.2"

plugins {
kotlin("multiplatform") version kotlinVersion
kotlin("jvm") version kotlinVersion
id("com.github.johnrengelman.shadow") version shadowVersion
id("io.kotest.multiplatform") version kotestVersion
}

repositories {
Expand Down
11 changes: 10 additions & 1 deletion src/compiler/cli/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import Libraries.KOTEST_ASSERTIONS
import Libraries.KOTEST_ASSERTIONS_ARROW
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar
import org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTargetWithHostTests
import org.jetbrains.kotlin.gradle.targets.js.dsl.KotlinJsTargetDsl
Expand All @@ -7,6 +9,7 @@ plugins {
kotlin("jvm") apply false
id("com.github.johnrengelman.shadow")
id("com.goncalossilva.resources") version "0.4.0"
id("io.kotest.multiplatform")
}

group = "${Settings.GROUP_ID}.compiler"
Expand All @@ -30,6 +33,11 @@ kotlin {
js(IR) { build() }
jvm {
withJava()
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(17))
}
}
tasks {
getByName<ShadowJar>("shadowJar") {
archiveBaseName.set(projectName)
Expand All @@ -52,9 +60,10 @@ kotlin {
}
commonTest {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-junit"))
implementation(KOTEST_ASSERTIONS)
implementation(KOTEST_ASSERTIONS_ARROW)
}
}
val desktopMain by creating {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,11 @@ import community.flock.wirespec.compiler.cli.io.JavaFile
import community.flock.wirespec.compiler.cli.io.KotlinFile
import community.flock.wirespec.compiler.cli.io.TypeScriptFile
import community.flock.wirespec.compiler.core.emit.common.DEFAULT_PACKAGE_NAME
import io.kotest.matchers.booleans.shouldBeTrue
import io.kotest.matchers.shouldBe
import io.kotest.matchers.string.shouldContain
import kotlin.test.Ignore
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertTrue

class CliTest {
Expand Down Expand Up @@ -39,7 +41,7 @@ class CliTest {
)
""".trimIndent()
assertEquals(expected, file)
file shouldBe expected
}

@Test
Expand All @@ -61,7 +63,7 @@ class CliTest {
) {};
""".trimIndent()
assertEquals(expected, file)
file shouldBe expected
}

@Test
Expand All @@ -87,7 +89,7 @@ class CliTest {
)
""".trimIndent()

assertTrue(file.contains(expected))
file.contains(expected).shouldBeTrue()
}

@Test
Expand Down Expand Up @@ -138,7 +140,7 @@ class CliTest {
}
""".trimIndent()

assertTrue(file.contains(expected))
file shouldContain expected
}

private fun getRandomString(length: Int) = (1..length)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
package community.flock.wirespec.compiler.cli.io

import kotlin.test.Ignore
import io.kotest.matchers.shouldBe
import kotlin.test.Test

class FullFilePathTest {

@Test
fun testParse() {
val result = FullFilePath.parse("/src/test/resources/test.json")
kotlin.test.assertEquals("/src/test/resources", result.directory)
kotlin.test.assertEquals("test", result.fileName)
kotlin.test.assertEquals(Extension.Json, result.extension)
FullFilePath.parse("/src/test/resources/test.json").run {
directory shouldBe "/src/test/resources"
fileName shouldBe "test"
extension shouldBe Extension.Json
}
}
}
6 changes: 5 additions & 1 deletion src/compiler/core/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,9 +1,12 @@
import Libraries.ARROW_CORE
import Libraries.KOTEST_ASSERTIONS
import Libraries.KOTEST_ASSERTIONS_ARROW

plugins {
kotlin("multiplatform")
kotlin("jvm") apply false
id("com.github.johnrengelman.shadow") apply false
id("io.kotest.multiplatform")
}

group = "${Settings.GROUP_ID}.compiler"
Expand Down Expand Up @@ -37,9 +40,10 @@ kotlin {
}
commonTest {
dependencies {
implementation(kotlin("test-common"))
implementation(kotlin("test-annotations-common"))
implementation(kotlin("test-junit"))
implementation(KOTEST_ASSERTIONS)
implementation(KOTEST_ASSERTIONS_ARROW)
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,21 +7,15 @@ import community.flock.wirespec.compiler.core.tokenize.types.Comma
import community.flock.wirespec.compiler.core.tokenize.types.CustomRegex
import community.flock.wirespec.compiler.core.tokenize.types.CustomType
import community.flock.wirespec.compiler.core.tokenize.types.CustomValue
import community.flock.wirespec.compiler.core.tokenize.types.DELETE
import community.flock.wirespec.compiler.core.tokenize.types.GET
import community.flock.wirespec.compiler.core.tokenize.types.HEAD
import community.flock.wirespec.compiler.core.tokenize.types.ForwardSlash
import community.flock.wirespec.compiler.core.tokenize.types.Invalid
import community.flock.wirespec.compiler.core.tokenize.types.LeftCurly
import community.flock.wirespec.compiler.core.tokenize.types.Method
import community.flock.wirespec.compiler.core.tokenize.types.NewLine
import community.flock.wirespec.compiler.core.tokenize.types.OPTIONS
import community.flock.wirespec.compiler.core.tokenize.types.PATCH
import community.flock.wirespec.compiler.core.tokenize.types.POST
import community.flock.wirespec.compiler.core.tokenize.types.PUT
import community.flock.wirespec.compiler.core.tokenize.types.Path
import community.flock.wirespec.compiler.core.tokenize.types.QuestionMark
import community.flock.wirespec.compiler.core.tokenize.types.RightCurly
import community.flock.wirespec.compiler.core.tokenize.types.StatusCode
import community.flock.wirespec.compiler.core.tokenize.types.TRACE
import community.flock.wirespec.compiler.core.tokenize.types.TokenType
import community.flock.wirespec.compiler.core.tokenize.types.WhiteSpaceExceptNewLine
import community.flock.wirespec.compiler.core.tokenize.types.WsBoolean
Expand Down Expand Up @@ -55,19 +49,13 @@ object Wirespec : LanguageSpec {
Regex("^Integer") to WsInteger,
Regex("^Boolean") to WsBoolean,
Regex("^->") to Arrow,
Regex("^GET") to GET,
Regex("^POST") to POST,
Regex("^PUT") to PUT,
Regex("^DELETE") to DELETE,
Regex("^OPTIONS") to OPTIONS,
Regex("^HEAD") to HEAD,
Regex("^PATCH") to PATCH,
Regex("^TRACE") to TRACE,
Regex("^GET|POST|PUT|DELETE|OPTIONS|HEAD|PATCH|TRACE") to Method,
Regex("^/.*/g") to CustomRegex,
Regex("^[1-5][0-9][0-9]") to StatusCode,
Regex("^[a-z][a-zA-Z]*") to CustomValue,
Regex("^[A-Z][a-zA-Z]*") to CustomType,
Regex("^/[a-z]*") to Path,
Regex("^/[a-z]+") to Path,
Regex("^/") to ForwardSlash,
Regex("^.") to Invalid // Catch all regular expression if none of the above matched
)
}
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
package community.flock.wirespec.compiler.core.parse

import arrow.core.Either
import arrow.core.nel
import arrow.core.raise.either
import community.flock.wirespec.compiler.core.exceptions.WirespecException
import community.flock.wirespec.compiler.core.exceptions.WirespecException.CompilerException.ParserException.WrongTokenException
import community.flock.wirespec.compiler.core.parse.nodes.Endpoint
import community.flock.wirespec.compiler.core.parse.nodes.Type
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Reference.Custom
import community.flock.wirespec.compiler.core.parse.nodes.Type.Shape.Field.Reference.Primitive
import community.flock.wirespec.compiler.core.tokenize.types.Arrow
import community.flock.wirespec.compiler.core.tokenize.types.Brackets
import community.flock.wirespec.compiler.core.tokenize.types.Colon
import community.flock.wirespec.compiler.core.tokenize.types.CustomType
import community.flock.wirespec.compiler.core.tokenize.types.DELETE
import community.flock.wirespec.compiler.core.tokenize.types.GET
import community.flock.wirespec.compiler.core.tokenize.types.HEAD
import community.flock.wirespec.compiler.core.tokenize.types.CustomValue
import community.flock.wirespec.compiler.core.tokenize.types.ForwardSlash
import community.flock.wirespec.compiler.core.tokenize.types.LeftCurly
import community.flock.wirespec.compiler.core.tokenize.types.Method
import community.flock.wirespec.compiler.core.tokenize.types.OPTIONS
import community.flock.wirespec.compiler.core.tokenize.types.PATCH
import community.flock.wirespec.compiler.core.tokenize.types.POST
import community.flock.wirespec.compiler.core.tokenize.types.PUT
import community.flock.wirespec.compiler.core.tokenize.types.Path
import community.flock.wirespec.compiler.core.tokenize.types.RightCurly
import community.flock.wirespec.compiler.core.tokenize.types.StatusCode
import community.flock.wirespec.compiler.core.tokenize.types.TRACE
import community.flock.wirespec.compiler.core.tokenize.types.WirespecType
import community.flock.wirespec.compiler.core.tokenize.types.WsBoolean
import community.flock.wirespec.compiler.core.tokenize.types.WsInteger
Expand All @@ -45,8 +40,17 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
private fun TokenProvider.parseEndpointDefinition(name: String) = either {
eatToken().bind()
token.log()
val method = parseEndpointMethod().bind()
val path = parseEndpointPath().bind()
val method = when (token.type) {
is Method -> Endpoint.Method.valueOf(token.value)
else -> raise(WrongTokenException<Method>(token))
}.also { eatToken().bind() }

val segments = mutableListOf<Endpoint.Segment>().apply {
while (token.type !is Arrow) {
add(parseEndpointSegments().bind())
}
}.also { eatToken().bind() }

when (token.type) {
is LeftCurly -> Unit
else -> raise(WrongTokenException<LeftCurly>(token))
Expand All @@ -57,7 +61,7 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
Endpoint(
name = name,
method = method,
path = path,
path = segments,
query = emptyList(),
headers = emptyList(),
cookies = emptyList(),
Expand All @@ -66,30 +70,42 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
)
}

private fun TokenProvider.parseEndpointMethod() = either {
private fun TokenProvider.parseEndpointSegments() = either {
token.log()
when (token.type) {
is Method -> when (token.type as Method) {
DELETE -> Endpoint.Method.DELETE
GET -> Endpoint.Method.GET
HEAD -> Endpoint.Method.HEAD
OPTIONS -> Endpoint.Method.OPTIONS
PATCH -> Endpoint.Method.PATCH
POST -> Endpoint.Method.POST
PUT -> Endpoint.Method.PUT
TRACE -> Endpoint.Method.TRACE
}

else -> raise(WrongTokenException<Method>(token))
}.also { eatToken().bind() }
is Path -> Endpoint.Segment.Literal(token.value.drop(1)).also { eatToken().bind() }
is ForwardSlash -> parseEndpointSegmentParam().bind()
else -> raise(WrongTokenException<Path>(token))
}
}

private fun TokenProvider.parseEndpointPath() = either {
private fun TokenProvider.parseEndpointSegmentParam() = either {
eatToken().bind()
token.log()
when (token.type) {
is Path -> Endpoint.Segment.Literal(token.value.drop(1)).nel()
else -> raise(WrongTokenException<Path>(token))
}.also { eatToken().bind() }
is LeftCurly -> eatToken().bind()
else -> raise(WrongTokenException<LeftCurly>(token))
}
val identifier = when (token.type) {
is CustomValue -> Type.Shape.Field.Identifier(token.value).also { eatToken().bind() }
else -> raise(WrongTokenException<CustomValue>(token))
}
when (token.type) {
is Colon -> eatToken().bind()
else -> raise(WrongTokenException<Colon>(token))
}
val reference = when (token.type) {
is WirespecType -> parseReference(token.type as WirespecType, token.value).bind()
else -> raise(WrongTokenException<WirespecType>(token))
}
when (token.type) {
is RightCurly -> eatToken().bind()
else -> raise(WrongTokenException<RightCurly>(token))
}
Endpoint.Segment.Param(
identifier = identifier,
reference = reference
)
}

private fun TokenProvider.parseEndpointResponses() = either {
Expand Down Expand Up @@ -125,10 +141,18 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {
}

private fun TokenProvider.parseContent(wsType: WirespecType, value: String) = either {
token.log()
Endpoint.Content(
type = "application/json",
reference = parseReference(wsType, value).bind(),
)
}

private fun TokenProvider.parseReference(wsType: WirespecType, value: String) = either {
eatToken().bind()
token.log()
val isIterable = (token.type is Brackets).also { if (it) eatToken().bind() }
val reference = when (wsType) {
when (wsType) {
is WsString -> Primitive(Primitive.Type.String, isIterable)

is WsInteger -> Primitive(Primitive.Type.Integer, isIterable)
Expand All @@ -138,6 +162,5 @@ class EndpointParser(logger: Logger) : AbstractParser(logger) {

is CustomType -> Custom(value, isIterable)
}
Endpoint.Content(type = "application/json", reference = reference)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ data object RightCurly : TokenType
data object Colon : TokenType
data object Comma : TokenType
data object QuestionMark : TokenType
data object ForwardSlash : TokenType
data object Brackets : TokenType
data object CustomValue : TokenType
data object Invalid : TokenType
Expand All @@ -35,18 +36,11 @@ data object WsNumber : WirespecType
data object WsBoolean : WirespecType
data object CustomType : WirespecType

sealed interface Method : Keyword
data object GET : Method
data object POST : Method
data object PUT : Method
data object DELETE : Method
data object OPTIONS : Method
data object HEAD : Method
data object PATCH : Method
data object TRACE : Method
data object Method : Keyword

data object StatusCode : Keyword
data object Path : Keyword

data object StatusCode : Keyword
data object Arrow : Keyword

data object CustomRegex : TokenType
Loading

0 comments on commit ce689d0

Please sign in to comment.