JakeWharton / RxBinding

RxJava binding APIs for Android's UI widgets.
Apache License 2.0
9.69k stars 971 forks source link

Script to generate kotlin bindings. #39

Closed JakeWharton closed 9 years ago

JakeWharton commented 9 years ago

The Kotlin bindings are fun, but are completely mechanical in how they are created. There's no reason they should be created by hand and doing so is an error-prone endeavor. Write a script that parses the Java declarations and automatically generates them for all modules. Care must be taken for all the variations of things like Javadoc, generics, and multiple arguments.

JakeWharton commented 9 years ago

Another approach: write a Gradle plugin in buildSrc which each Kotlin module uses to generate the sources at build time. This means they never have to be checked in and we don't have to worry about them being stale (and writing the Travis CI hooks to prevent staleness).

dlew commented 9 years ago

:+1: the buildSrc method. That's essentially how Victor works and we've also got other scripts working internally to do similar.

I wonder if registerJavaGeneratingTask() will work for Kotlin. I'm not exactly sure how it all fits together.

JakeWharton commented 9 years ago

Yeah it should work. Will have to try. I'm not too eager about writing it in a JVM-based language, but maybe I can spin that into an advantage.

nschwermann commented 9 years ago

might look to https://github.com/JetBrains/anko for some inspiration or technique they are generating a lot of kotlin code by crawling through java files.

ZacSweers commented 9 years ago

JVM-based is probably going to be the easiest, because pretty much the go-to library for parsing java files is google/eclipse's JavaParser.

I've gotten some decent familiarity working with it recently for an internal gradle plugin recently, and it looks like that's what Anko is using as well.

If no one else is working on it already, I'd be happy to take a crack at it while the iron's hot.

JakeWharton commented 9 years ago

Please do! My threshold of pain is high so I don't mind doing it manually for now...

ZacSweers commented 9 years ago

hehe, alright. Traveling this week, but I should be able to ramp up on it next weekend

ZacSweers commented 9 years ago

Had some time on my flight this morning and have hacked together a basic working implementation for the project in its current state. Not pretty, but it's a start and I can work on improving it from here.

https://github.com/hzsweers/RxBinding/tree/kotlingen

One change I wanted to check with you on is this one. I couldn't think of a way to statically resolve what the parent type's parameter bounds are, so I think it would be better to just be explicit in the Rx* implementation itself, unless there's a specific reason you wanted it to be an unbounded wildcard. Thoughts?

JakeWharton commented 9 years ago

That generic bounds change looks fine. Do you want to submit just it as a PR?

As to the generator, it looks awesome! I would like to eventually get to a place where we can delete the actual *.kt files in the kotlin modules and just have the plugin generate them on-the-fly during a build. But, as a first step, keeping them checked in and simply using the plugin to update them is wise.

ZacSweers commented 9 years ago

Sure, I'll PR that separately.

I'm going to clean up the generator code this weekend, but not sure what the scope of it should be. It currently only supports the conditions that exist in the current binding java code. There are some areas that can be future proofed (java long -> kotlin Long, resolving nested levels of parameterized types, etc), but there's no guarantee that it'll work for all future situations. I'm happy to update it as new cases arise, but not sure if you'd prefer something more robust.

JakeWharton commented 9 years ago

We can keep the generated code committed in that case. This will allow auditing the changes it makes. I'd rather get it in right away and iterate on it as things come up than wait to make sure every little thing works.

ZacSweers commented 9 years ago

Alright! I'll PR both tomorrow or Monday sometime.

JakeWharton commented 9 years ago

I'll just suck in that commit now. I might just fire off a 1.0 tonight...

ZacSweers commented 9 years ago

Cool. Might want to get this one in too, as it also has generated bindings for some that weren't implemented before: https://github.com/hzsweers/RxBinding/commit/d19f7b61d38b293c7a92b477f1eefc0474d9708f

JakeWharton commented 9 years ago

Released a v0.1.0, FYI.

JakeWharton commented 9 years ago
{@code view}

should become

`view`
JakeWharton commented 9 years ago
JakeWharton commented 9 years ago

There is one occurrence of {@link View#GONE View.GONE} which I am removing because it ends up needed to become:

[`View.GONE`][View.GONE]

which is stupid because it could just be

[View.GONE]

but in order to keep things simple I'm changing it to {@code View.GONE}.

ZacSweers commented 9 years ago

Good examples, I wasn't sure how those references carried over in kotlin docs. I've been busier than expected this week, but planning to sit down and do those polishes tomorrow!

JakeWharton commented 9 years ago

Cool. I didn't mean to imply there was a rush! I just want to document things that I noticed otherwise I'll never remember to follow-up on them.

ZacSweers commented 9 years ago

haha no worries, I understand. Just wanted to give an update from my end as well!

JakeWharton commented 9 years ago

ITSHAPPENING.gif