Add Lambda support through Lambdaspec class#16
Add Lambda support through Lambdaspec class#16HliasMpGH wants to merge 2 commits intoRandgalt:masterfrom
Conversation
2007260 to
a496c14
Compare
a496c14 to
0e60e1b
Compare
|
Thanks for this. I think this is a lot better and will pay benefits later on. I'll review when I can. |
I believe so too. Let me know about any additions/ changes needed, when you can of course. |
|
FYI - referring to |
| // true if the function has more than 1 statement in its body | ||
| boolean multiStatementBody = bodySide.contains(";"); | ||
|
|
||
| codeWriter.emit(multiStatementBody ? "{" : ""); |
There was a problem hiding this comment.
What if someone wants braces to start on newlines ala:
x ->
{
//
}
We should support that
There was a problem hiding this comment.
I agree. I can add more modes that support said format. Thanks for the suggestion.
| String bodySide = this.body.toString(); | ||
|
|
||
| // true if the function has more than 1 statement in its body | ||
| boolean multiStatementBody = bodySide.contains(";"); |
There was a problem hiding this comment.
This will break if ; is in a string, etc. This seems like a fragile way of checking for multi statements. Can something be added to CodeWriter to signal more than 1 statement?
There was a problem hiding this comment.
Thats an interesting thought. I will look into that
There was a problem hiding this comment.
The "issue" with CodeWriter is that the components can always use the generic .emit() method, to append code. In that case, the CodeWriter is not aware of how many lines of code its about to append (it just knows that its about to append a String, its not like it will append it line-by-line). The same is true for CodeBlocks (with the .add() method). So essentialy, the problem we are facing is still, given a some code in a string, count how many valid ';' it has. We can probably get over it by the utilization of a parser library. What do you think?
EDIT: A contender for the parser can be the javaparser library.
Here is a quick example of how it can be performed:
public boolean hasMultipleStatements(String code) {
try {
StaticJavaParser.parseExpression(code);
// the string is an Expression
return false;
} catch (ParseProblemException e) {
// the string code requires { }
return true;
}
}
|
@HliasMpGH do you know anyone else who can help review this? |
Not at the moment, i will look into it. |
Is my case different than methods like beginControlFlow(), nextControlFlow(), endControlFlow() of CodeBlock, that perfrom that way by adding said spaces? In the instance that it is different, do you think by adding a mode like |
|
A different way we can approach the problem, and achieve (almost) complete configuration flexibility, is to have a second CodeBlock (that the user can modify) in the LambdaSpec (in addition to the body the user supplies) that gets placed right before the lambda body. That way, the user can add all the spaces/ indents/ new lines they want and they will get placed right before the body they provided. This works perfectly on single statement lambdas without the use of lambda modes, since they are simple. Its not the same when it comes to multistatement bodies, though, because of the braces placement. To achieve similar flexibility on multistatement lambdas we still need to use the
The above changes will result in something like the following: With an output of: The CodeBlock before the body will be modified directly on the Lambda object, the above example is a simplification to present the logic. What do you think of this approach? It will definitely save us the issue of having way to many LambdaModes to account for different formats. |
|
I like the idea of using CodeBlocks. Going even further, we can treat the lambda spec builder as similar to a MethodSpec as MethodSpec handles CodeBlocks already. The bracing involved is handled by |
|
Excuse my delay, i was caught up with some other work for the past two weeks. I will look into pushing some changes as soon as i can. Thank you for your patience! |
The models of lambdas are fully configurable through the builder class. The different modes / attributes of a lambda are handled through the LambdaMode enum, and the user can configure them with the addModes() method. Lambdas can be added in CodeBlocks, MethodSpecs and initialized in FieldSpecs.
0e60e1b to
727a2ac
Compare
Users can now add characters such as new lines, indents and spaces before the arrow, body and after the last curly bracket.
|
What do you think of the latest updates? Its a starting point for the logic we have been discussing about the lambdas and CodeBlocks. Let me know about your thoughts whenever possible. |
I apologize. I started this project because I couldn't get responses from JavaPoet devs and here I am unable to respond on this. I've been slammed with work but will try to get to it soon. I like what I've seen so far I just need a block of time to look further. If you could find someone else knowledgable to review it that would help a lot. |
First Part of #5
This PR supplies the user with the ability to create lambdas and integrate them into his generated code, with the usage of the LambdaSpec class, which acts as a model of an anonymous function. A demonstration of the features' usage can be seen below.
The process of creating some simple lambda functions can be performed as such:
Now that the models are ready, they can be added in generated code:
which results in:
They can be added to CodeBlocks the same way.
For further configuration of the output, such as formatting and optional visibility of components:
Which is a model of:
While
is a model of:
Further configuration (for example indents, new lines and spaces inside the body) can be done by the user though the CodeBlock methods, when creating said CodeBlock). In either case, more configuration types can be easily added and implemented with the help of the LambdaMode enum of the same class. Regarding the spaces between the ->, i left them unconfigurable due to the fact that their placement is a formatting standard (such as a space before the { in a for loop), just like other methods perform in the codebase, when placing similar unspecified spaces (for example beginControlFlow() of CodeBlock class). Here's what's specified in the Google Java Style Guide:
https://google.github.io/styleguide/javaguide.html#s4.6.2-horizontal-whitespace