-
-
Notifications
You must be signed in to change notification settings - Fork 304
Support flow type spread #241
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
Conversation
It seems like we should change the |
I merged #240, could you please rebase? |
Rebased. The right approach for this PR was a little less obvious to me. I tried to follow the algorithm conventions that existed but I'm not sure if the output of the spread type is what it actually should be. I would appreciate a bit closer review of those pieces. |
type: 'object', | ||
signature: { | ||
properties: [ | ||
{ key: 'OtherProps', value: { name: 'OtherProps', required: true } }, |
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.
I think it is not really clear what this is just from the json alone. It could be also interpreted as
type a = { OtherProps: OtherProps };
What i would try to do is resolve OtherProps
and if it resolves to an other ObjectType within the same file then I would just inline this in the result. We do the same when resolving stuff here https://github.com/reactjs/react-docgen/blob/master/src/utils/resolveObjectKeysToArray.js#L59..L67
In the case when it cannot be resolved I'm not sure what the best approach is. We could either ignore the spread completely then, which we currently do for regular non-type ObjectSpread. Or somehow add a special field in the output aka "inherits" (or some better name) which just contains the names of the Type that was spreaded into the object. If I think about it spreading types is just some kind of multi inheritance and it is probably interesting to know.
{
name: 'signature',
type: 'object',
includes/inherits/implements/??: [ 'OtherProps' ],
signature: {
properties: [
{ key: 'a', value: { name: 'string', required: true } },
]
}
}
Not sure if that makes sense though.
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.
The logic for resolving the local types is already being done. You can see it in action in the component snapshot test, prop OtherLocalProps
.
Yeah, the real question is what to do when the type is imported from another file, 90% of our use case internally. We definitely don't want to ignore the spread. I think for us at least, saying what the types are is pretty explanatory. It's typically things like ...AccessibilityProps
.
An explicit inherits field is interesting. I am not familiar enough with this project and how we consume the output to know what is ideal here. I think I defer to you.
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.
This is an example of a component where we type spread props in and how we'd probably expect them to show up in docs. https://facebook.github.io/react-native/docs/touchableopacity.html#props
}, | ||
"required": false, | ||
}, | ||
"OtherLocalProps": Object { |
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.
It seems like this could be confused with a prop called OtherLocalProps
that has these specific keys. However, since it is being spread in, the properties of OtherLocalProps should probably be flattened into the top level props? Is that correct?
@danez, do you have any more thoughts on these open questions? |
I'm thinking that we want to distinguish between the spread properties and the normal ones. Also, since we want to resolve local types and possibly at some point have a way to reference where the definition originally comes from, we want the inherited list to be objects instead of plain strings. I'm thinking this structure:
|
"flowType": Object { | ||
"name": "OtherComponentProps", | ||
}, | ||
"inherited": true, |
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.
These have a flag for whether it is inherited. This was cleaner than adding a new top level key to the output documentation.
Alright, I think this is good to go now. I broke this into two separate PRs to make it easier to review. |
d6b9300
to
54e709e
Compare
@danez, kind bump. @fkling is on vacation so I can't bug him internally to get this merged and released. :) Other people on my team like @yungsters, have merge permissions here but only you and felix can publish a new version. If you'd like to add the facebook npm user to have publish permissions: https://www.npmjs.com/~fb, then we can take care of it. |
Why did you decide to do it in 2 different ways? Once with |
I could have gone either way, I actually initially had them both as a separate There are a few different reasons I made All in all, I don't feel strongly either direction. I'm happy to change approach if someone with more context has a preference. I mostly just want to get Facebook's UIDocs to stop blowing up on these new flow types. Perhaps we can merge and ship a PR that does that and then we can figure out the best output for these additional types. |
@@ -267,6 +267,35 @@ Object { | |||
"displayName": "MyComponent", | |||
"methods": Array [], | |||
"props": Object { | |||
"OtherComponentProps": Object { |
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.
Move this to composes
"NonExistentFile.OtherCommmponentProps"
if default
then "URI"
}, | ||
"inherited": true, | ||
}, | ||
"OtherLocalProps": Object { |
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.
Inline this into props.
src/handlers/flowTypeHandler.js
Outdated
} | ||
|
||
setPropDescription(documentation, path); |
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.
Add a comment to this.
"description": "", | ||
"displayName": "MyComponent", | ||
"methods": Array [], | ||
"props": Object { | ||
"OtherLocalProps": Object { |
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.
This is wrong. Not spread in far enough.
import { OtherComponentProps as OtherProps } from 'NonExistentFile'; | ||
|
||
type OtherLocalProps = {| | ||
fooProp?: 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.
Add and pull in a docblock comment here.
Looks good to me now. So you now changed it to use |
I think the other one needs a bit more work still. All of the inline comments I left were from doing an in person code review with @fkling. This PR should be good to go though. I’ll try to get Felix to review it closer today. :-) |
Okay I can also otherwise merge it . Sorry for the delay I'm really busy lately, but now off work for this week, so have more time. |
setPropDescriptor(documentation, propertyPath) | ||
}); | ||
} else { | ||
documentation.addComposes(name.node.name); |
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 this takes the variable name used in the spread syntax, right? Did we plan to use the module name instead at some point? I can't remember.
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.
I think where it ended up was that it was too difficult to make something meaningful here.
import type { MyType } from 'MyFile';
type MyFileMyProperty = $PropertyType<MyType, 'myProperty'>;
type Props = {|
...MyFileMyProperty
|}
It doesn't make sense to say that it composes MyFile.MyFileMyProperty
, in this case it would be MyFile.MyType.myProperty
but the logic can get exceedingly complicated and it doesn't make sense for us to try to understand it statically. I think where we landed was to just use the alias, if they want it to be more explicit in the generated docs they can use a more explicit alias.
This still leaves us open to improving it at a future point though.
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.
Alright
Supporting type spread props:
This is a stacked PR on top of #240