Closed bvella closed 6 years ago
Hi @bvella I am not a lawyer but my take is this:
Given I'm the maintainer for this project I think you can just go ahead and do that without any issue.
I'd definitely be interested in seeing the work you have done and exploring whether the projects can be merged.
Hope that helps.
Thanks for the info @JoeHegarty. I will push the library soon following the above. I don't know if these comments are the appropriate place to discuss the changes I made. Here's a summary of the changes and rationale. Feel free to suggest an alternate place to continue the discussion.
API
Although your approach appears to be non-invasive (transforming the same method in-place), the abstraction becomes inconsistent when considering checked exceptions. Considering the method:
CompletionStage<Void> doSomething() throws SomeException;
It is unclear whether the method can throw the exception or whether the completion stage can be rejected with that exception. This led me to change the API such that async methods return type Async
, which is a final class, instead of CompletionStage
or any class implementing it. The methods are then transformed into their async counterparts without the exception in the signature:
Async<Void> doSomething() throws SomeException;
is transformed to
CompletionStage<Void> async$doSomething();
(synthetic) CompletionStage<Void> continuation$async$doSomething(...);
I tried to stick with the semantics of async/await in other languages, namely javascript and .net, where you can only await in async methods, and async method are methods that return Async<>
, while keeping the existing java semantics like e.g. exception handling, intact.
Transformation I tried to simplify the transformation in the following ways:
Async<>
which is a final class, I do not have to deal with detecting subclasses. However, I now need to generate 2 methods: for Async op()
I generate CompletionStage async$op()
and CompletionStage continuation$async$op(..., async$state, async$stage)
async$
method calls the continuation$async$
method with state 0, and wraps the call in a try..catch block. the continuation$async$
method switch at index 0 is the first chunk of code before any await()
calls, indices 1 onwards for code after each await()
. I also call helper methods to compose the continuation instead of calling future.exceptionally(..).thenCompose(..)
, which allows me to do other tricks (e.g. joining asynchronous stack traces) without complicating the transformer.
Other stuff In addition to the above transformations, I have developed some async helpers namely:
I have used this code as a basis for an async/await transformer. I have changed the api significantly, which is why I am not going to submit a pull request. I would not mind discussing the changes though, so we can make both projects better or possibly merge them at some point, but this is for another time.
I have retained the licence text in 2 source filed that I used from this project. Q1: Is it enough to retain the licence text for these files only or does the licence automatically apply to all the artifact?
I would like to publish the compiled artifact to maven central. Since the licence states:
Q2: Do I need to add anything to the compiled artifact? or just deploying the source jar with the licence text in the source files be enough?
Thanks in advance