Skip to content

Extract documentation from Component methods #66

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

Merged
merged 3 commits into from
Apr 6, 2016

Conversation

janicduplessis
Copy link
Contributor

This adds documentation for methods of react components. It works with both React.createClass and classes. It reads from jsdoc blocks for descriptions and flow types for type information.

It supports:

  • name
  • description
  • docblock (the raw docblock for further parsing)
  • parameters (name, type, description)
  • modifiers ('static', 'generator', 'async')
  • return (type, description)

It only removes react component methods and leaves removing private methods to the users if they choose so.

Tested on the react-native codebase.

Closes #17

cc @danez @fkling @vjeux

@vjeux
Copy link

vjeux commented Mar 25, 2016

That's going to make the react native docs so much better thanks! (I haven't written a single line in this codebase so I'm not a good reviewer)

@fkling
Copy link
Member

fkling commented Mar 25, 2016

This is awesome! I looked over the code and it looks great.

I'm not such a big fan of making assumptions and parse the docblock with doctrine, but then again, this is probably the most common use case (having jsdoc-like docblocks), so including these bells and whistles will probably be a good thing?

Thoughts?

@janicduplessis
Copy link
Contributor Author

I think that as long as it doesn't break with other docblock styles than jsdoc (does that even exists) it is fine.

We could always just return the raw docblock and leave the parsing to clients but I think the flow/jsdoc setup is common enough to parse it by default and adds a lot of useful info like description for each parameter.


// Add jsdoc @return description.
if (jsDoc) {
const returnTag = jsDoc.tags.find(tag => tag.title === 'returns');
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should be (tag.title === 'returns' || tag.title === 'return') as 'return' is the synonym.

@danez
Copy link
Collaborator

danez commented Mar 26, 2016

I haven't tested it yet, but looked through it and added some comments.

On thing I noticed is that annotations which are not evaluated in the handlers are completely swallowed right now (for example we use a lot @example), and as the raw docblock is also not there, one would currently need to parse the file again, to get the remaining jsdoc-annotations. But providing them in an array would even more lock-in react-docgen to jsdoc and the format that doctrine uses, so I wouldn't do that. For consistency with the react-compnent I would say to have the raw description in there is probably the best, so one doesn't endup parsing the file a second time.

But the @param and @return tag still add a lot of good information to params, so maybe we could also leave this parts in there, but just change the description to be the raw description?

@janicduplessis
Copy link
Contributor Author

Good point about annotations, we should definitely return the raw docblock so additional parsing can be done. I think we should still keep the description as it is now to avoid having to remove jsdoc tags that we don't want to show in the documentation.

@janicduplessis
Copy link
Contributor Author

Actually I think I should move all the JSDoc stuff in a separate handler and only extract the docblock in componentMethodsHandler. Then I can make a jsDocMethodsHandler that parses the docblock and add type, return and params info so the most common case works well out of the box and users can implement other handlers that parses the docblock again to add their specific use cases. What do you think about that?

@danez
Copy link
Collaborator

danez commented Mar 29, 2016

That sounds like a good plan. 👍

@janicduplessis
Copy link
Contributor Author

@danez I think I addressed most of the things you pointed out.

  • Separated the methods extraction and jsdoc parsing in 2 handlers.
  • I'll leave printing the function declaration in another PR later to add more functionality like default values and optionals.
  • The jsdoc types are now used if there are no flow types.
  • Added support for @return and @returns.
  • Added a raw docblock prop.
  • Removed the visibility prop as I think it's not as commonly used and we can have users parse it from the raw docblock.

@danez
Copy link
Collaborator

danez commented Mar 31, 2016

Awesome, looks good to me. I hope I have time next week to try it out. I can then also make additional PR to add missing edge cases if I ran into any.

@fkling
Copy link
Member

fkling commented Apr 6, 2016

Thanks for all the work and thought you put into this. And thanks for the fruitful discussion!

@fkling fkling merged commit 16fcaa0 into reactjs:master Apr 6, 2016
@janicduplessis
Copy link
Contributor Author

@fkling Could you make a new version on NPM? I'd like to start integrating this on the react-native website :)

@fkling
Copy link
Member

fkling commented Apr 8, 2016

@janicduplessis: Done! (2.8.1 because I messed up the npm publish process). If you have a small input/output example handy, I can update the release notes with it :)

@janicduplessis
Copy link
Contributor Author

Thanks @fkling! I just submitted a PR (#72) to address some minor issues I found when integrating it with the RN website. 2.8.2 maybe? :)

@caabernathy
Copy link
Contributor

Hey @janicduplessis, I chatted with @fkling who suggested I post here with regards to a question I had around improving RN docs. I was exploring whether we could tease out the type definitions, ex: https://github.com/facebook/react-native/blob/master/Libraries/Components/StatusBar/StatusBar.js we have one called StatusBarAnimation that I'd like to list separately with perhaps the option of adding more comments around it.

So the method signature code snippet

setHidden(hidden: boolean, animation?: StatusBarAnimation)

Gets turned into

static setHidden(hidden: boolean, animation: 'none' | 'fade' | 'slide')

The JSON output of parsing doesn't contain any mention of StatusBarAnimation so we could perhaps list it in the doc. A part of it looks like this:

{
  "name": "setHidden",
  "docblock": null,
  "modifiers": [
    "static"
  ],
  "params": [
    {
      "name": "hidden",
      "type": {
        "name": "boolean"
      }
    },
    {
      "name": "animation",
      "type": {
        "name": "$Enum",
        "elements": [
          {
            "name": "signature",
            "type": "object",
            "raw": "{\n  'none': string,\n  'fade': string,\n  'slide': string,\n}",
            "signature": {
              "properties": [
                {
                  "key": "none",
                  "value": {
                    "name": "string",
                    "required": true
                  }
                },
                {
                  "key": "fade",
                  "value": {
                    "name": "string",
                    "required": true
                  }
                },

So the question is, any idea on how we could bring out the custom type name into the returned JSON, StatusBarAnimation in this example?

@janicduplessis
Copy link
Contributor Author

janicduplessis commented Jun 2, 2016

It should be possible to get the name of the type Identifier before resolving the flow type. Here's the relevent code for params and return value

Here's what the ast should look like https://astexplorer.net/#/SSIvYwuj5V. We can probably look for GenericTypeAnnotation and then get it's Identifier name and add this to the returned type object.

Let me know if that makes sense :)

@caabernathy
Copy link
Contributor

@janicduplessis thanks for the pointer. I tried it out by making the following change in getMethodDocumentation.js

const {types: {namedTypes: types}} = recast;
...
function getMethodParamsDoc(methodPath, jsDoc) {
    ...
    if (typePath) {
        type = getFlowType(typePath);
        if (types.GenericTypeAnnotation.check(typePath.node)) {
            type.name = typePath.node.id.name;
        }
    }
    ...

It seems to spit out the right stuff. Is that what you were pointing me towards?

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 29, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants