-
Notifications
You must be signed in to change notification settings - Fork 1.9k
GROOVY-11970: Provide support for compound assignment operator overlo… #2499
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -998,4 +998,34 @@ public static Object bitwiseNegate(final Object value) throws Throwable { | |
| throw unwrap(gre); | ||
| } | ||
| } | ||
|
|
||
| /** | ||
| * GEP-15: dispatcher for compound-assignment operators in dynamic Groovy. | ||
| * If {@code receiver} responds to {@code assignName} with the supplied argument, | ||
| * invoke it and return {@code receiver} (so the caller's STORE assigns the same | ||
| * reference back, leaving the in-place mutation visible). Otherwise fall back to | ||
| * {@code baseName} and return its result for the caller to assign. | ||
| */ | ||
| public static Object compoundAssign(final Object receiver, final Object arg, | ||
| final String assignName, final String baseName) throws Throwable { | ||
| if (receiver != null) { | ||
| MetaClass mc = InvokerHelper.getMetaClass(receiver); | ||
| if (!mc.respondsTo(receiver, assignName, new Object[]{arg}).isEmpty()) { | ||
| mc.invokeMethod(receiver, assignName, arg); | ||
| return receiver; | ||
| } | ||
| } | ||
| return InvokerHelper.invokeMethod(receiver, baseName, arg); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. SCB already has methods for invocation, why not use those? |
||
| } | ||
|
|
||
| /** | ||
| * GEP-15: helper for {@code @OperatorRename(plusAssign="...")} expression rewrites. | ||
| * The user's renamed name is authoritative (no fallback), and the expression value of | ||
| * {@code x op= y} is the (mutated) {@code x}, not the called method's return value. | ||
| */ | ||
| public static Object invokeRenamedCompoundAssign(final Object receiver, final Object arg, | ||
| final String name) throws Throwable { | ||
| InvokerHelper.invokeMethod(receiver, name, arg); | ||
| return receiver; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why not use a normal method call for this then? I don't see why we need an extra method in SCB for this |
||
| } | ||
| } | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
evaluateCompoundAssigndoesn't currently account for null-safe compound assignments (expression.isSafe()), becauseScriptBytecodeAdapter.compoundAssignwill fall back to invoking the base operator even when the receiver isnull. This breaks safe-navigation semantics (the operation should short-circuit without invokingplus/etc when safe and the LHS resolves to null). Consider either handlingexpression.isSafe()here by keeping the legacy safe path, or extending the helper to treatsafe && receiver==nullas a short-circuit.