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

Shortcut functions #496

Closed

Conversation

friedrich-goetze
Copy link

For my own Project, I created these shortcuts for many of kotlinpoets builders and I like to share them.

pros for usercode:

  • will be less cluttered
  • less lines
  • less indentations, therefore less space taken by indentation
  • correct builders are selected automatically (i.e. FunSpec.constructorBuilder(...) for TypeSpec.primaryConstructor(...), FunSpec.getterBuilder(...) for PropertySpec.getter(...) etc...

I also added a Test which is also a small demonstration.

Shortcuts I didn't use are missing, i.e. for TypeAliasSpec.

Here's a preview snipped taken from the testclass:

fileSpec("com.squareup.kotlinpoet.test", "FooBar") {
  propertySpec("foo", String::class, INTERNAL)

  classSpec("FooClass") {
    primaryConstructorSpec {
      addCode("println(\"Hello World\")")
    }

    varPropertySpec("foo", String::class, INTERNAL) {
      initializer("\"the foo\"")
    }

    propertySpec("foobar", String::class) {
      getterSpec { addCode("return \"\${foo}bar\"") }
    }

    funSpec("dooTheFooBar") {
      returns(Int::class.asTypeName().asNullable())
      addParameter("howLong", Period::class, INTERNAL)
      addCode("println(\"\$foobar\")")
    }
  }

  interfaceSpec("FooInterface") {
    funSpec("calcMagicNumber") {
      returns(Long::class)
      addCode("return 42L")
    }
  }

  objectSpec("FooObject") {
  }
}

@JakeWharton
Copy link
Collaborator

Without the use of @DslContext on the builders you can create weird representations in the DSL that don't map to what you expect. Otherwise these seem like mostly okay as far as DSLs go. Perhaps you want to illicit discussion on #62 first.

@friedrich-goetze
Copy link
Author

Using @DslMarker should really help, but this annotation has to be applied to another annotation (you have to define yourself), which then has to be applied all Foo.Builder types. Therefore, after creating an annotation like @KotlinPoetDsl, one of the following has to be done:

  • Annotate every builder-class with it
  • Make the builder open, so an inherited class can be annotated
  • Add annotated wrapperclasses for each builder

@JakeWharton
Copy link
Collaborator

JakeWharton commented Oct 15, 2018 via email

@tieskedh
Copy link

tieskedh commented Oct 31, 2018

there is a fourth option:

@Target(AnnotationTarget.TYPE)
@DslMarker
annotation class KotlinPoetDSL

private typealias ABuilder = (@KotlinPoetDSL A).() -> Unit

class A{
    val aval : String = ""
}
class B {
    val bval :String = ""
}
fun a( block: ABuilder): Unit = TODO()
fun A.b(block : (@KotlinPoetDSL B).() -> Unit): Unit = TODO()
fun main(args: Array<String>) {
    a {
        aval
        b {
            aval //can't access
            bval
        }
    }
}

(I think with typealias is better, because then you can't forget to apply the dsl-marker.

@JakeWharton
Copy link
Collaborator

We control the types, though. Why wouldn't we just annotate them directly?

@tieskedh
Copy link

don't know ;-)
I placed this in the discussion as well.
The only reason I can come up to don't do it is that in this way you can add it as a plugin.
I added it because I misread the . in your answer for a , :-).

@swankjesse
Copy link
Collaborator

I don't think we want this in the core library. It's neat and nice but it means we offer two competing APIs. This one is nice if you have full context, but the Builder API is most flexible.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants