-
Notifications
You must be signed in to change notification settings - Fork 64
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
Destructuring in styled interpolation functions #403
Destructuring in styled interpolation functions #403
Conversation
font-size: ${(props) => props.textSize}px; | ||
background-color: ${(props) => { | ||
return props.bgColor; | ||
}}; | ||
border: 5px ${(props) => props.borderStyle} black; | ||
border: 5px ${({ borderStyle }) => borderStyle} black; |
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.
can we add these tests as well please 😄
({ borderStyle: bs }) => bs
propz => propz.borderStyle
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.
Sure sure
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.
Looks little bit tricky. Damn. We have hardcoded props
check as of now. propz
is now dynamic 😅
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.
yeah 😅
make it work, make it right, make it fast? hehe
if its a lot of effort to allow props
to be dynamically named e.g. propz
we can leave it for now. we can potentially force it to be called props
and just rename any member expressions to props
? clever workarounds.
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.
Was lil bit tricky. Damn! Finally 😅
a3add01
to
1a727b9
Compare
* 1. `propz.loading` in `border-color: \${(propz) => (propz.loading ? colors.N100 : colors.N200)};` | ||
* Outcome: It will replace `propz.loading` with `props.loading`. | ||
* | ||
* 2. `prop.notValidProp` in `border-color: \${(props) => (props.notValidProp ? colors.N100 : colors.N200)};` |
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.
what is the edge case here? that the arg is props
but we're using prop
?
in this case should we just do nothing? could we delete some of this code and get away with it?
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.
oops..it should be props.notValidProp
. Sorry 😅
expect(actual).toIncludeMultiple([ | ||
'{as:C="span",style,isLoading,loading,...props}', | ||
'isLoading?colors.N20:colors.N40', | ||
'loading?colors.N50:colors.N10', |
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.
hmm i think this is smart (instead of using l
you use loading
) - because it gets around the potential of naming collisions
can we have one test that asserts that so the knowledge is passed onto the next developer?
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.
🎉 yups sure
@@ -145,6 +145,109 @@ const traverseStyledBinaryExpression = (node: t.BinaryExpression, nestedVisitor: | |||
return node; | |||
}; | |||
|
|||
/** | |||
* Handles cases like: | |||
* 1. `propz.loading` in `border-color: \${(propz) => (propz.loading ? colors.N100 : colors.N200)};` |
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.
nit: could we handle this in an enter()
visitor instead? so the logic of "rename propz to props" only needs to function once - instead of needing to traverse up the parent
🤔 thinking about it i see we check for arrow function or binary expression on L273/L277. perhaps this is fine?
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 we are already traversing down. Here we are making sure propz
is coming from function params. We picked member expression property, traversed to make sure it is coming from function params, and renamed it. Earlier we hardcoded the check to props
.
* @param path MemberExpression path | ||
* @param propsToDestructure Array which gets mutated with props which are not valid eg. props.notValidProp | ||
*/ | ||
const handleMemberExpressionInStyledInterpolations = ( |
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.
nit:
-handleMemberExpressionInStyledInterpolations
+handleMemberExpressionInStyledInterpolation
* @param path Identifier path | ||
* @param propsToDestructure Array which gets mutated with props which extracted from destructuring | ||
*/ | ||
const handleDestructuringInStyledInterpolations = ( |
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.
nit:
-handleDestructuringInStyledInterpolations
+handleDestructuringInStyledInterpolation
const traversedUpFunctionPath = path.find((parentPath) => parentPath.isFunction()); | ||
const memberExpressionKeyName = memberExpressionKey.name; | ||
|
||
const isMemberExpressionKeyNameEqualsFunctionParams = |
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.
nit: isMemberExpressionNameTheSameAsFunctionFirstParam
?
return; | ||
} | ||
|
||
if (!propsToDestructure.includes(memberExpressionValueName)) { |
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.
can we add some comments here explaining what we're doing
(if valid html attribute let it through - else destructure to prevent)
|
||
if (isPropValid(memberExpressionValueName)) { | ||
// Convert cases like propz.color to props.color | ||
if (memberExpressionKeyName !== 'props') { |
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.
can we move 'props'
to module scope and reuse it? or move to constants.tsx
? 🤔
path: NodePath<t.Identifier>, | ||
propsToDestructure: string[] | ||
) => { | ||
// We are not interested in parent object property like `({ loading: l }) => l` |
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.
is this comment wrong? im not following unfortunately. more context?
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 in this statement, ({ loading: l }) => l
when we are checking for Identifier
, both : l
and => l
are identifiers and function is parent for both. We are not interested in modifying : l
. We just need to modify => l
to => loading
. If we don't skip, => l
will not be modified because we have modified : l
earlier and second identifier is nowhere to be found inside function params.
Hope this makes sense 😅
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.
ahhh 🤔
so why don't we add loading
to props to de-structure here?
alternatively now that i think about it - should we be adding destructured props anyway? currently the behaviour should be
- am i a valid HTML element? you will be passed down to the raw HTML element
- am i not valid? you will be destructured
do we need to rework anything to support this behaviour? 🤔
*/ | ||
const handleDestructuringInStyledInterpolations = ( | ||
path: NodePath<t.Identifier>, | ||
propsToDestructure: string[] |
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.
instead of leaking props to destructure can we instead return any identifiers we've found that we want to destructure?
*/ | ||
const handleMemberExpressionInStyledInterpolations = ( | ||
path: NodePath<t.MemberExpression>, | ||
propsToDestructure: string[] |
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.
instead of leaking props to destructure can we instead return any identifiers we've found that we want to destructure?
}: { | ||
name: string; | ||
node: t.Expression | undefined; | ||
resolveFor?: 'key' | 'value'; |
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.
what if we just returned both?
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.
Yups we can 😃
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.
Another thought. Here we are traversing until we hit dead end. We either need to search for key
or value
. I mean where we will break the recursion. When either key
is found or value
is found?
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.
no worries then :)
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.
hey! left some comments have a look :)
looking pretty great! biggest thoughts are:
- reworking the need to pass through
propsToDestructure
, and - seeing if we can do something about needing to traverse back up the AST to find the parent function
for 2) its more of a thought than anything, if it makes the code shittier then let's not bother
:fingerguns:
First is fine. Second one hmm 🤔. Problem is how we can find where it is coming from. Looks like |
1a727b9
to
ebaca9a
Compare
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.
lgtm
This closes #397