Comments (6)
Had a couple of issues with that approach:
- Creating a class that has the target external classes as members to generate their DSL produces a wrapper layer that is hard to get rid of.
- Creating a super class of the target to apply
@AutoDsl
there only works if the target class is open, while it doesn't produce the target type anyway. Also a bit problematic in case of data classes. - In either case of the above there is no way for fine grained config, e.g. DSL name or collection tweaks like
AutoDslCollection
)
from autodsl.
Hi @manosbatsis ! thanks for this cool idea! I didn't think about it and I like it.
In order to provide a feature like this, we will need to integrate that (in some way) into the current process of AutoDsl as imagine this scenario where you have a mix of classes with and without AutoDsl
// External module/dep
class PersonExt(val wallet: WalletExt)
class WalletExt(val money: MoneyExt)
@AutoDsl
class MoneyExt()
// internal module
@AutoDslMixin(..)
class PersonMixin
@AutoDslMixin(..)
class WalletMixin
When creating the PersonExt Builder, you will need to lookup for its dependencies not only annotated with AutoDsl but also find (in some way) that the class WalletExt (which is not annotated at all) has a corresponding AutoDslMixin. One concern here is that this lookup could make the entire process to slow down. Another problem that I see with this is that you will be creating unnecessary classes to provide a builder to another class (like the PersonMixin class)
The first idea that comes to my mind is maybe having an interface and annotate there all the external classes that you want to support:
@AutoDslExternal(
classes = PersonExt::class, WalletExt::class, etc..
)
interface AutoDslDep
and integrate in the current AutoDsl process the lookup in that list in case you have an scenario like this:
// external module
class WalletExt
// internal module
@AutoDsl
class Person(val wallet: WalletExt)
@AutoDslExternal(
classes = WalletExt::class
)
interface AutoDslDep
and once it finish the regular AutoDsl process, it continues with the builder creation process for the AutoDslExternal list.
But still I need to think a little more about this. I really like the idea!
from autodsl.
Hey @juanchosaravia, thanks for the quick reply. To give a clearer picture, my annotation processors typically treat sources and mixins equally. For example, this:
@AutoDsl(dslName = "myBox")
class Box(
val name: String,
@AutoDslCollection(concreteType = ArrayList::class, inline = true)
val stamps: List<Stamp>?
)
... would produce exactly the same as:
@AutoDslMixin(dslName = "myBox", dslSource = Box::class)
class BoxMixin(
@AutoDslCollection(concreteType = ArrayList::class, inline = true)
val stamps: List<Stamp>?
)
For each regular or mixin/ext annotation, the processor will create an AnnotatedElementInfo and process that to create e.g. a DTO or, in our case, the DSL. The mixin above provides the AutoDslCollection
info as if it where in the original code.
In other words, both the mixin annotated element and it's dslSource
are TypeElement
s as far as the annotation processor is concerned, with the mixin only providing information that cannot be added to the original source. The annotated elements are given directly to the processor by kapt so there is no need to perform any manual scanning - it just handles both regular and mixin annotations equally.
As you can imagine, the main reason I tend to use classes VS interfaces as mixins is pure laziness: it's easier to process them using the exact same code in the processor, e.g. when looking for constructor fields. That said, it's rather trivial to use interfaces too.
About AutoDslExternal
: you'll have to help me there, i really see no need for it - just seems like a redundant point for the user to maintain.
Happy to discuss as needed and/or work on a branch, this feature would be of great help in a project i have right in front of me right now ;-)
from autodsl.
So what you are saying is to make a copy of each class that you want to have AutoDsl? hmm if that's the case, not sure about that approach. Seems redundant and requires maintainability. My proposal was to avoid this class duplication. And how would you handle those the case of a mix between external class and internal?
from autodsl.
So what you are saying is to make a copy of each class that you want to have AutoDsl?
Oh no, not at all. The mixin class/interface will usually be totally empty, with mixin members optionally emulating the annotation of a member in the original source. To make this clearer, this:
@AutoDsl(dslName = "myBox")
class Box(
val field1: String,
val field2: String,
val field3: String,
val field4: String,
@AutoDslCollection(concreteType = ArrayList::class, inline = true)
val field5: List<Stamp>?
)
... would produce exactly the same as:
@AutoDslMixin(dslName = "myBox", dslSource = Box::class)
class BoxMixin(
@AutoDslCollection(concreteType = ArrayList::class, inline = true)
val field5: List<Stamp>?
)
from autodsl.
I'm concern of the need to create new classes to generate builders for other classes. Seems to be a lot of code just to provide support to external class that should not really be exposed in a DSL. You could easily create a class to encapsulate the internal classes that you use or any class from any library. In that case you will not need to expose that class with your DSL and then no need to apply AutoDsl to that internal class.
from autodsl.
Related Issues (10)
- Not nullable property with default value will not work HOT 1
- About collection handling HOT 7
- Compile-time check for required value HOT 2
- Problem with nested class HOT 1
- about selead class HOT 2
- Publish library into Maven Central HOT 1
- Android Sample App: compilation fails with latest Kotlin and Gradle version HOT 4
- Any plans to support kotlin multiplatform HOT 1
- I found this wonderful thing, but it can't be used. Is it really impossible to use it in 1.4x HOT 2
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from autodsl.