yahoo / squidb

SquiDB is a SQLite database library for Android and iOS
https://github.com/yahoo/squidb/wiki
Apache License 2.0
1.31k stars 132 forks source link

SquidDatabase.getTables() - could this be code-generated? #138

Open danhawkes opened 8 years ago

danhawkes commented 8 years ago

When working with squidb, my workflow is typically:

So, for my use-case at least, getTables() is boilerplate and it'd be nice if it wasn't necessary to implement it manually.

I realise the SquidDatabase class isn't code generated at the moment, and doing so would probably screw up the various subclasses (ReactiveSquidDatabase etc.), but something akin to TableModel.PROPERTIES for tables might be a substitute. What are your thoughts?

sbosley commented 8 years ago

Hmm I'm not sure if this is possible to do via APT code generation. The main obstacle is that the APT apis don't guarantee that every annotated class will be present in every round -- for instance, if only one model spec has changed since the last compile, I believe the compiler is free to optimize and only call the annotation processing for that single class. I'm not sure that I see a reliable way to guarantee that a complete list of tables can be accumulated on every compile. The other unfortunate obstacle is that the APT api can only generate new files, not modify existing ones.

This may have already been obvious to you, but the main reason we throw an exception in this case rather than just look up the table object reflectively is that the table has to be declared in getTables() so it can be created for new databases, and we want to make sure that the user remembers to do that.

I have two out of the box ideas that we could try -- and you're welcome to collaborate with us on them if you're interested!

  1. I've never tried it, but what if you declared all of your model specs as public static inner classes in a single file, and wrote your own annotation processor to process a custom annotation declared on the root class? You'd have to enforce a convention on yourself that all your models would be declared in this monolithic container (which admittedly could get ugly for big schemas), but if you did that, you'd have a complete listing of all classes annotated with @TableModelSpec available at compile time, and you could conceivably generate a small class containing only a generated Table[] as a public constant.
  2. Rather than try to use the APT apis, maybe it would be possible to create some kind of gradle task that would scan all files in the directory where APT generates its files after compilation is done and look for the pattern "ClassName extends TableModel", and generate a new file containing a constant Table[] that way. I'm not a gradle expert but it feels doable.

Do either of those sound appealing? Or do any other ideas come to mind?