kotlinpoet
kotlinpoet copied to clipboard
Properties with inferred types
It would be nice to be able to create PropertySpecs that do not have types declared and are auto-inferred by Kotlin, e.g. val someProperty = initialiser
over val someProperty: <type> = initialiser
.
Right now, PropertySpec.Builder requires a Type of some sort and PropertySpec.emit() also always emits the type info.
What's the use case?
Extension properties for a Java class. I have to manually convert Java->Kotlin types for the property type when the compiler can do it for me (and way better then I could, too).
I think this is a legit use case, inferring correct types is not trivial. We should look into making the types optional where possible.
As we've decided to generate library mode-compliant code by default, and this requires that types for public members are declared explicitly, this feature will have to be limited to non-public properties. Does this change things? Should we still keep this issue in the backlog, or close it?
For the usage case I had back when I opened this, that would be fundamentally useless.
I have a similar case:
private val something: Map<String, Class<*>> = mapOf(/**/)
How to generate code like this, it's difficult to declare the Class<*>
@JakeWharton @Egorand Any suggestion?
TypeName.STAR
will give you the *
. Then just parameterize a TypeName
which represents Class
using it.
cool,thanks
Works like a charm 👍
Map::class.asClassName().parameterizedBy(
String::class.asTypeName(),
Class::class.asTypeName().parameterizedBy(STAR)
)
Output
Map<String, Class<*>>
has anyone fixed this!!!!
No. And without a compelling case for it we have no plans to. Sorry.
I would like to generate this:
companion object { val postgreSQLContainer = PostgreSQLContainer("postgres:15.3") }
That's valid Kotlin code and is running just fine (and avoiding issues with this container classes), so why not to support it?
Can you explain why you are unable to know the type of the expression?
The library does not endeavor to support 100% of all possible syntax forms so if you know the type then we don't actually need to support implicit types.
It this particular case you need to add a custom type first and cast it, something like
val postgreSQLContainer:PostgreSQLContainerType = (PostgreSQLContainerType)PostgreSQLContainer("postgres:15.3")
That's a very ugly workaround and can easily be avoided by removing the type. Also I think many Kotlin developers like to avoid the types when they are not needed, as this makes the code shorter. But up to you I guess if you want to support this. Having a builder without a type would be enough.
If you generate val postgreSQLContainer = PostgreSQLContainer("postgres:15.3")
the inferred type will be PostgreSQLContainer
though, right? Not sure I understand how being able to avoid explicit types helps improve val postgreSQLContainer:PostgreSQLContainerType = (PostgreSQLContainerType)PostgreSQLContainer("postgres:15.3")
.
Moreover, if there's a need to cast it means you're actually changing the type which would otherwise be inferred to something else.
That's a specific Kotlin issue with recursive generic types, see here https://stackoverflow.com/questions/59007414/testcontainers-postgresqlcontainer-with-kotlin-unit-test-not-enough-informatioThere are many workarounds, but just leaving out the type is working for me (and providing it will create errors). -------- Original message --------From: Egor Andreevich @.> Date: 6/9/23 18:22 (GMT+01:00) To: square/kotlinpoet @.> Cc: tleipzig @.>, Comment @.> Subject: Re: [square/kotlinpoet] Properties with inferred types (#858) If you generate val postgreSQLContainer = PostgreSQLContainer("postgres:15.3") the inferred type will be PostgreSQLContainer though, right? Not sure I understand how being able to avoid explicit types helps improve val postgreSQLContainer:PostgreSQLContainerType = (PostgreSQLContainerType)PostgreSQLContainer("postgres:15.3").
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>
Right so I have used this library before and recall the problem. It uses a recursive generic which is something you really only want to do on an abstract base class but they use it on a non-abstract class that is instantiable. These types are non-denotable when used directly in both Java and Kotlin. I think the standard practice in Java is to use a raw type, but obviously Kotlin does not have raw types. The workarounds are to subclass where the type parameter can become your subtype, or to do all configuration of the type in an apply
block and have the parameter type use a wildcard and optionally be a supertype like JdbcDatabaseContainer
.
In any case, while I understand it's annoying, I don't think is enough to warrant adding what is otherwise a somewhat dangerous feature to the library. It also would break the ability to use the explicit API mode which currently all code generated by the library will support by default.
Thank you very much for your understanding and looking into this! This is quite an edge case of cause, and if the implications of a change are so big, it's probably better to keep the current state. -------- Original message --------From: Jake Wharton @.> Date: 6/9/23 21:23 (GMT+01:00) To: square/kotlinpoet @.> Cc: tleipzig @.>, Comment @.> Subject: Re: [square/kotlinpoet] Properties with inferred types (#858) Right so I have used this library before and recall the problem. It uses a recursive generic which is something you really only want to do on an abstract base class but they use it on a non-abstract class that is instantiable. These types are non-denotable when used directly in both Java and Kotlin. I think the standard practice in Java is to use a raw type, but obviously Kotlin does not have raw types. The workarounds are to subclass where the type parameter can become your subtype, or to do all configuration of the type in an apply block and have the parameter type use a wildcard and optionally be a supertype like JdbcDatabaseContainer. In any case, while I understand it's annoying, I don't think is enough to warrant adding what is otherwise a somewhat dangerous feature to the library. It also would break the ability to use the explicit API mode which currently all code generated by the library will support by default.
—Reply to this email directly, view it on GitHub, or unsubscribe.You are receiving this because you commented.Message ID: @.***>