-
-
Notifications
You must be signed in to change notification settings - Fork 225
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
Shorten assignments to itself #230
Changes from 5 commits
3344baa
a4d10bc
c666da1
c6ec99d
6b913fe
c1aa0ca
6dfe218
6813842
5ddc5f8
2c7a0d5
4f7e8eb
64ed8d9
8c0a456
6eaded6
edd236f
b058bd0
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 |
---|---|---|
|
@@ -28,6 +28,17 @@ module.exports = ({ types: t }) => { | |
const or = (a, b) => t.logicalExpression("||", a, b); | ||
const and = (a, b) => t.logicalExpression("&&", a, b); | ||
|
||
const operators = new Set([ | ||
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. We need to consider splitting plugins into multiple modules. This kind of mixing of helpers and supplemental stuff is not great ^. I think we could even strive for 1 type-of-transform per file. |
||
'+', '-', '*', '%', | ||
'<<', '>>', '>>>', | ||
'&', '|', '^', '/', | ||
'**' | ||
]); | ||
|
||
const updateOperators = new Set([ | ||
'+', '-' | ||
]); | ||
|
||
return { | ||
name: "minify-simplify", | ||
visitor: { | ||
|
@@ -124,6 +135,49 @@ module.exports = ({ types: t }) => { | |
], | ||
}, | ||
|
||
AssignmentExpression(path) { | ||
|
||
const right = path.get('right'); | ||
const left = path.get('left'); | ||
|
||
const canShorten = ( | ||
right.type === 'BinaryExpression' && | ||
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.
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. Good to know, thanks! |
||
operators.has(right.node.operator) && | ||
left.node.name === right.node.left.name | ||
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. requires |
||
); | ||
|
||
if (!canShorten) return; | ||
|
||
const canBeUpdateExpression = ( | ||
right.node.right.type === 'NumericLiteral' && | ||
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.
|
||
right.node.right.value === 1 && | ||
updateOperators.has(right.node.operator)); | ||
|
||
if (left.node.name === undefined) { | ||
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.
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. I wasn't sure if it's always going to be member expression. This felt like a broader/safer check. But sure, probably ok to change it. |
||
// TODO: transform MemberExpressions as well | ||
// e.g. foo.bar = foo.bar + 123; | ||
return; | ||
} | ||
|
||
if (canBeUpdateExpression) { | ||
|
||
const newExpression = t.updateExpression( | ||
right.node.operator + right.node.operator, | ||
t.identifier(left.node.name)); | ||
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. probably needs to handle member expression here ? 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. Wonder if we can make a generic utility for handling both Identifier/MemberExpression? |
||
|
||
path.replaceWith(newExpression); | ||
} | ||
else { | ||
|
||
const newExpression = t.assignmentExpression( | ||
right.node.operator + '=', | ||
t.identifier(left.node.name), | ||
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. handle memberExpressions |
||
t.clone(right.node.right)); | ||
|
||
path.replaceWith(newExpression); | ||
} | ||
}, | ||
|
||
ConditionalExpression: { | ||
enter: [ | ||
// !foo ? 'foo' : 'bar' -> foo ? 'bar' : 'foo' | ||
|
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.
here you compare two arrays and even if one fails in the list, the others still run. But when you do
forEach
when one of them fails, all else that follows won't be run at all.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.
So you're thinking to wrap them in try/catch?