Conversation
28e4f75 to
22f6f33
Compare
|
Update: I migrated the tests of |
|
Wow!! Very nice!! This is going to take a while to go through but it seem to be working with everything I throw at it. =) I moved your discussion on implementation to #675 where we can talk more in detail. Will keep PR related stuff here. |
|
The grammar is not happy. We will need to massage that until it is and also get both the slices and lambdas to be happy. Reading from file /home/intriazen/git/beanshell-securityguard/target/javacc-1723296930414/node/bsh.jj ...
Warning: Choice conflict in [...] construct at line 798, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "="
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in [...] construct at line 817, column 42.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "?"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 825, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "??"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 834, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "||"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 843, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "&&"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 852, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "|"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 861, column 7.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "^"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 870, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "&"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 879, column 6.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "=="
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in [...] construct at line 889, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "instanceof"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 896, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "<"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 906, column 3.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "<<"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 916, column 4.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "+"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 925, column 6.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "*"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict in (...)* construct at line 934, column 6.
Expansion nested within construct and expansion following construct
have common prefixes, one of which is: "**"
Consider using a lookahead of 2 or more for nested expansion.
Warning: Choice conflict involving two expansions at
line 983, column 5 and line 983, column 15 respectively.
A common prefix is: "{" <IDENTIFIER>
Consider using a lookahead of 3 or more for earlier expansion. |
Not sure why you did this, I see the old test case (casts.bsh) still succeeds. Would be nice if we can start some lambda tests in a test-script for reference purposes. This will not be code coverage tests per se but useful for reference and documentation supplements. |
Be grateful you still have such a thing as free time =) Thank you for your efforts this is awesome!! |
|
I not we have conflicts now, may need to rebase from fresh HEAD |
Codecov ReportAttention: Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## master #766 +/- ##
============================================
+ Coverage 74.26% 75.66% +1.39%
- Complexity 3114 3196 +82
============================================
Files 112 115 +3
Lines 9572 9872 +300
Branches 1880 1931 +51
============================================
+ Hits 7109 7470 +361
+ Misses 2115 2056 -59
+ Partials 348 346 -2
Flags with carried forward coverage won't be shown. Click here to find out more. ☔ View full report in Codecov by Sentry. |
|
Just some updates:
|
|
I'm also working in some things right now: Static method reference to non-static methodsI forgot to implement a support for some things like Grammar warningsI fixed the gramar problem of method references and slices but I still didn't see why there is so many warning messages in the console, I'm going to see that after resolving the issues with method references and signature stuff. SecurityGuardIt's probably the simplest thing to do in this list, but explaining, I'm going to add support of Lambda into SecurityGuard; I mean, a call for Code fixes and improvementsI'm improving the tests too and also reviewing the code to make some improvements, an example is removing all 'invoke' methods of |
Hello @nickl- , here I'm again 😁
This is probably my last PR, but it's a great one.
Introduction
The basic idea of this PR is implement support for lambdas by lambda expressions and method references, as in the snippet bellow for reference:
I read entirely the issue 645, and here I'm with my solution to this issue :D
Implementation
The implementation is kinda tricky, so I'll first explain the main idea and after explain the details.
The basic idea is that lambda expressions and method references must return an instance of
bsh.BshLambda, and when we use this lambda ( call some method, set to a variable, etc... ) we convert thisbsh.BshLambdato an instance of that specific functional interface, and we do it basically calling the methodbsh.BshLambda.convertTo(Class)( I'll explain this method but you can see the method implementation here ).Here is a BeanShell snippet showing what I'm talking about:
The code above is a step-by-step code, but it also works:
Okay, but you might be thinking "how the bsh.BshLambda.convertTo() works ?", and here we go. The implementation idea is the tricky part as I already said, because we have a instance of
bsh.BshLambda, so we can just callbsh.BshLambda.invoke()to run the lambda, but unfortunatelly Java is strong typed, so we must have a strict type to lambda works, so to solve that, we make a wrapper ofbsh.BshLambdathat implements our desired functional interface.Here is a code snippet showing the idea of wrapper:
So, basically, the method
bsh.BshLambda.convertTo()create the wrapper class using ASM and then the method return an instance of the wrapper.Note: I used ASM to created the class byte code and load it in JVM because this way seems more lightweight than using
java.lang.invoke.LambdaMetafactory.It's the basic explanation about how I implemented this Lambda Support, but there is a bunch of details that I did to make this Lambda Support "java strict" that would take a bunch of paragraphs to explain, so if you wanna know all features of this Lambda Support, you can read the test file because I did JUnit tests to them all 😅
The "method overload with lambda types alike" issue
This lambda support works really well, but there is just one case that it wouldn't work as clean as in Java, that is in method overload with lambda types where the difference is just the lambda return type. Here is a code showing this:
But there are some disclaimers:
(MapSupplier) () -> new HashMap<>()would solve this issueHashMap::newwould also solve this problem.eval()method for all nodes in a different way where we don't wanna really evaluate the code, but instead, we wanna evaluate the return type of the code, but it's a HUGE PROBLEM to solve, I tried but it's too much work, so being honest, I don't wanna solve that because of the previous disclaimers: it's an extremelly rare scenario and there is simple workarrounds to solve that.Tests and Code coverage
The code coverage is 100%, I make all kind of tests to ensure that the behaviour is as in standard Java.

Note: I did ~1400 lines of tests 🫠
Conclusion
I guess that this Lambda Support is really good, and will be perfect for users, and if you see something wrong or that isn't that good, I can fix that, but it's probably my last PR 😢, because I shoud be using my free time after my job to study to go to college/university :V
after writing this big text, now I'll waiting your response 😊
Note: my PR for Security Guard is also waiting for you ;)