Marc Reichelt
01/03/2018, 4:40 PMswagger.yaml
file ourselves. Using https://editor.swagger.io/ eased the pain, especially since it provides validation errors and code completion. Now I wonder whether I could write a Kotlin DSL for OpenAPI, and generate the swagger.yaml
on the fly.
So the initial results look tempting, as I can write:
openapi {
openapi { "3.0.1" }
info {
title { "Swagger Petstore" }
version { "1.0.0" }
}
}
But there are two things I dislike with this solution. One: I have to write a lot of code to get this basic functionality. And two: Nobody prevents me from calling info
or title
multiple times, or even omitting them totally. For example, this would be invalid:
openapi {
info {
title { "Swagger Petstore" }
title { "Swagger Petstore 2" }
version { "1.0.0" }
}
}
In contrast, writing the OpenAPI spec with data classes gains me more functionality than writing a custom DSL:
Document(
openapi = "3.0.1",
info = Info(
title = "Swagger Petstore",
version = "1.0.0"
)
)
Here I have to add openapi
and info
because they are both required, and IntelliJ tells me if there is a duplication error.
So my question is: What do I gain from writing a DSL in this case, or is the OpenAPI spec not a good use case for it?helpermethod
01/04/2018, 5:11 PMfoo {
bar("bar") // this is required
baz() // this is optional
}
kristofdho
01/23/2018, 11:45 AMdoThis
etc calls, not sure if that's a problemkikitux
02/22/2018, 4:14 PMsnowe
06/16/2018, 4:42 PMAny
and that definitely isn't a good idea. Wait, unless, can I define unaryPlus
just in the context of a block?Dominaezzz
11/13/2018, 10:29 AMtjb
11/20/2018, 4:44 AMtjb
11/26/2018, 3:03 AMfun match(block: MatchBuilder.() -> Unit = {}) {
val matchBuilder = MatchBuilder()
matchBuilder.block()
match = match.plus(matchBuilder.build())
}
tjb
11/26/2018, 3:10 AMmatch {
optional = false
}
with {
"hello, world"
}
Marc Knaup
01/08/2019, 11:04 AMdigitalsanctum
01/14/2019, 8:06 PMMarc Reichelt
01/28/2019, 12:44 PMConfiguration
class does not have an isDirectory
property - but how could the Groovy code then work in the first place?GarouDan
01/29/2019, 1:10 AMgroup "com.company.team.project"
version "0.0.1"
in our build.gradle
how can we convert this to a build.gradle.kts
file?
I tried something like:
group("com.company.team.project")
version("0.0.1")
but it didn’t work.ribesg
01/29/2019, 10:07 AMsnowe
01/31/2019, 6:05 PMapi()
? I thought it might be apiElements
but then the module that uses apiElements
fails to find the symbols in that jar.GarouDan
02/09/2019, 8:47 PMSystem.getProperty("configuration.build.dir")
is not right. It is returning null but I could verify that a non empty value is passed in xcode.GarouDan
02/11/2019, 11:09 PMjsJar.dependsOn(populateWebFolder)
from a build.gradle
file to a build.gradle.kts
. How can I do this?
This is part of:
def webFolder = new File(project.buildDir, "../src/jsMain/web")
def jsCompilations = kotlin.targets.js.compilations
task populateWebFolder(dependsOn: [jsMainClasses]) {
doLast {
copy {
from jsCompilations.main.output
from kotlin.sourceSets.jsMain.resources.srcDirs
jsCompilations.test.runtimeDependencyFiles.each {
if (it.exists() && !it.isDirectory()) {
from zipTree(it.absolutePath).matching { include '*.js' }
}
}
into webFolder
}
}
}
jsJar.dependsOn(populateWebFolder)
task run(type: JavaExec, dependsOn: [jvmMainClasses, jsJar]) {
main = "sample.SampleJvmKt"
classpath { [
kotlin.targets.jvm.compilations.main.output.allOutputs.files,
configurations.jvmRuntimeClasspath,
] }
args = []
}
GarouDan
02/25/2019, 6:29 PMbuild.gradle.kts
?
compileTestKotlin2Js {
kotlinOptions.metaInfo = true
kotlinOptions.outputFile = "$project.buildDir.path/js-tests/${project.name}-tests.js"
kotlinOptions.sourceMap = true
kotlinOptions.moduleKind = 'commonjs'
// kotlinOptions.moduleName = project.name + "-test"
kotlinOptions.main = "call"
}
This one here I could do something like:
compileKotlin2Js {
kotlinOptions.metaInfo = true
kotlinOptions.outputFile = "$project.buildDir.path/js/${project.name}.js"
kotlinOptions.sourceMap = true
kotlinOptions.moduleKind = 'commonjs'
kotlinOptions.main = "call"
}
tasks.withType<Kotlin2JsCompile> {
kotlinOptions {
// languageVersion = "1.3"
metaInfo = true
outputFile = "${project.buildDir.path}/js/${project.name}.js"
sourceMap = true
sourceMapEmbedSources = "always"
moduleKind = "commonjs" // umd
main = "call"
}
}
Marc Knaup
02/25/2019, 8:03 PMKirill Grouchnikov
03/28/2019, 6:13 PMmgrzechocinski
04/12/2019, 7:11 AMMarc Reichelt
05/01/2019, 12:21 PMMarc Knaup
05/08/2019, 10:04 PMMarc Knaup
05/09/2019, 3:28 PMSlackbot
05/22/2019, 6:05 AMmingkangpan
05/26/2019, 2:52 PM@SqlMarker
object SQLBuilder {
fun query(init: SqlSelectBuilder.() -> Unit): SqlSelectBuilder {
val builder = SqlSelectBuilder()
builder.init()
return builder
}
}
jw
08/12/2019, 6:02 PMAny?
allowing any object to be returned. This lambda's receiver is also a DSL type meaning there are functions you can call inside of it. The problem is that these functions return Unit
thus completing the contract of the enclosing lambda and avoiding the need to actually return an object. Is there any way to avoid this?
@MyDsl interface Foo {
fun bar(lambda: Bar.() -> Any?)
}
@MyDsl interface Bar {
fun someHelper(size: Int)
fun otherHelper(flag: Boolean)
}
bar {
someHelper(2)
otherHelper(true)
// should be required to return an object here
}
I tried to get clever with an overload of bar
whose lambda returned Unit
and was marked as an error, but you can't @JvmName
an interface function. converting it to a class results in the Unit
-returned lambda always being preferred. There's a Kotlin-internal annotation to lower its overload precedence, but I don't have access to that.Shawn
09/05/2019, 5:58 PMbenfleis
09/18/2019, 7:16 AMMarc Knaup
10/04/2019, 7:26 AMsomeFuncReturningBool() && otherFuncReturningBool()
and someFuncReturningBool() and otherFuncReturningBool()
is not the same. The former short-circuits, the latter doesn’t.
That hit me unexpectedly when I thought “oh that’s nice, I can just use and
instead of &&
in my DSL to make it more human-readable”.
rule {
condition {
terms.assignmentAddress.isProvided() and
terms.assignmentAddress.country.isNotSupported() // exception because access not allowed if isProvided() returns false
}
issue {
"Terms: The address of the assignment is located in a country that is not supported."
}
}
I presume there are only two ways to fix this.
a) Use &&
instead of and
😥
b) Make all the functions which can be used in condition {}
that currently return Boolean
return something like Condition
instead. That in turn would have an and
infix operator which makes two Condition
instances form a new Condition
and thus allows for chaining with and
. That would basically build a tree of Condition
.
I guess there are no alternatives for supporting and
here?Marc Knaup
10/04/2019, 7:26 AMsomeFuncReturningBool() && otherFuncReturningBool()
and someFuncReturningBool() and otherFuncReturningBool()
is not the same. The former short-circuits, the latter doesn’t.
That hit me unexpectedly when I thought “oh that’s nice, I can just use and
instead of &&
in my DSL to make it more human-readable”.
rule {
condition {
terms.assignmentAddress.isProvided() and
terms.assignmentAddress.country.isNotSupported() // exception because access not allowed if isProvided() returns false
}
issue {
"Terms: The address of the assignment is located in a country that is not supported."
}
}
I presume there are only two ways to fix this.
a) Use &&
instead of and
😥
b) Make all the functions which can be used in condition {}
that currently return Boolean
return something like Condition
instead. That in turn would have an and
infix operator which makes two Condition
instances form a new Condition
and thus allows for chaining with and
. That would basically build a tree of Condition
.
I guess there are no alternatives for supporting and
here?efemoney
10/08/2019, 12:46 AMand
is a bitwise operator not a boolean operator.Marc Knaup
10/08/2019, 3:29 AMBoolean
, hence the confusion :)