-
-
Notifications
You must be signed in to change notification settings - Fork 297
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
infer displayName when not defined #59
Conversation
} | ||
displayNamePath = displayNamePath.node.value | ||
} else if (!displayNamePath) { | ||
displayNamePath = path.node.id ? path.node.id.name : path.node.declarations[0].id.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.
Would like a second pair of eyes on this, specifically around path.node.declarations[0].id.name
. I'm not sure if I like 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.
See my comment above :) (which should make this a non-issue)
Thanks for working on this! I will add some comments inline. |
expect(documentation.displayName).toBe('FooBar'); | ||
|
||
definition = statement(` | ||
var 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.
Unfortunately this is not useful test, because the displayNameHandler
function will never be passed a VariableDeclaration.
If you look at getMemberValuePath
, you can see the node types which represent component definitions:
var LOOKUP_METHOD = {
[types.ArrowFunctionExpression.name]: getMemberExpressionValuePath,
[types.FunctionExpression.name]: getMemberExpressionValuePath,
[types.FunctionDeclaration.name]: getMemberExpressionValuePath,
[types.VariableDeclaration.name]: getMemberExpressionValuePath,
[types.ObjectExpression.name]: getPropertyValuePath,
[types.ClassDeclaration.name]: getClassMemberValuePath,
[types.ClassExpression.name]: getClassMemberValuePath,
};
For some of them, inferring the name is easy: You can simple take the id
of named classes and functions.
For all others, you need to traverse up the tree to find and assignment or export and inspect that one to get the name.
Here is how getMemberExpressionValuePath
does it:
react-docgen/src/utils/getMemberExpressionValuePath.js
Lines 36 to 45 in 9042c91
if ( | |
types.FunctionExpression.check(path.node) || | |
types.ArrowFunctionExpression.check(path.node) | |
) { | |
if (!types.VariableDeclarator.check(path.parent.node)) { | |
return; // eslint-disable-line consistent-return | |
} | |
return path.parent.get('id', 'name').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.
Okay so, I still want to be able to infer the name and assign them as the displayName of stateless functional components.
What would you think about exporting resolveName()
from /getMemberExpressionValuePath.js
, importing it into displayNameHandler
and using that to grab the variable declaration display names?
blah, fail test. ill check. edit: ah, okay, test is doing commonjs require, so really just wants one export per file. Makes sense. Would breaking resolveName into separate file be cool? edit2: I can add some tests around this too if this is considered an okay approach |
Sure! Can you also update the tests to verify whether these cases are covered?
It was also be great to get some test coverage for |
You're talking about mainly updating the |
Yes. |
Almost got this, named exports giving me a little trouble, but I think I should have something tomorrow. |
The biggest issue I'm running into with Named Exports has to do with Basically, inside //checks if named export, then redefines the componentDefinition to be the export's declaration
if (componentDefinition.node.type === types.ExportNamedDeclaration.name) {
componentDefinition = componentDefinition.get('declaration').value;
} However, once I grab it and redefine I think I can make it work all around, but it's gonna be a bigger refactor than just 1 file. |
After looking at the AST, it seems named exports should actually be covered by variable declarations, no? Regarding
If you have something new to share, I'm happy to take a look. |
Oh neat, didn't know that ast tool existed. (I'm still pretty new to parsing the AST) well, so, first thing I did was just add a test to it('infers the displayName with named export', () => {
var definition = statement(`
export var Foo = function() {}
`);
displayNameHandler(documentation, definition);
expect(documentation.displayName).toBe('Foo');
}); But of course, that throws an error because the definition type is So my line of reasoning was to go one level deeper into the |
i expect this latest to trip travis-ci. just pushing so i have it up there for now. |
Was able to get infer name on es6 exports to work on classes, function expressions and variable declarations. (though I had to do some stuff that feels very clunky for variable declaration) now to get |
Got a version of infering displayName on commonJS exports working. Not sure if I like the solution right now. Need to add more tests around exports and attaching displayName vs. inferring it and make sure the more explicit attaching of displayName takes precedent. |
|
||
} else if (declaration.type === types.VariableDeclaration.name) { | ||
|
||
declarationPath = resolveExportDeclaration(path)[0].parentPath.parentPath.parentPath; |
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 don't really like this solution, but I'm not sure of how else to get this value while keeping 'NodePath' type intact.
Looking at stuff over again today, I decided it's probably best to keep current behavior in regards to an example like: export class Foo {
static displayName = foo.bar;
} Initially, I was going to try and have it infer the class name as the displayName in that case, but I think the better behavior might be to keep it empty returning as it currently is. All tests are passing, would like a review, especially on how I'm handling immediately exported variable declarations. Other than that though, I think this satisfies #30 as far as I can tell. |
|
||
}); | ||
|
||
describe('defaultPropsHandler with ES6 Exports', () => { |
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 guess this should be "dispayNameHandler".
I'll take a closer look again today, thanks! |
hmmm....tests passed on stable and node 5 but failed on node 4 It passes locally for me on Node 4. CI looks like it's failing on a file this pull request doesn't touch. Seems like it's maybe a fluke fail? |
looks like this is what is keeping #97 from passing as well. I did a bit of digging and found a jest issue mentioning this: This seems to be an intermittent fail from what I can tell. perhaps updating jest from If you think getting jest updated is important, I can work and get a PR in for that. |
We can at least give it a try yes! |
Oh also, I 100% completely understand if this branch/feature isn't something you'd want merged into the main trunk. It solves a problem for my purposes though, so I've been linking to a fork of this for my projects. Along those lines, I'd like to ask your permission for me to create a npm package with this feature included in it so I can stop linking directly to github in a few of my projects. |
@NogsMPLS I'm also very interested in using this. If it is not going into upstream, could you create a separate npm package for this handler? |
Ah, interesting, I didn't see that post about future of react-docgen. yeah I can look into making this into a custom handler. |
yeah, that would be the best solution for now. I'm happy to merge any fixes that would need to be done to core utilities though. |
@NogsMPLS So, I've had some spare time and went ahead and created a displayName handler. Would that be covering all of your use cases too? https://github.com/nerdlabs/react-docgen-displayname-handler |
@ZauberNerd nice! Ill check it out sometime this week and let you know |
Is this PR died? It would be really nice to have this feature! @NogsMPLS |
@danny-andrews I believe the display-name-handler that @ZauberNerd created does a decent job of covering what this PR was meant to do. I know of at least 1 pretty popular repo that is using that display-name-handler plugin: https://github.com/styleguidist/react-styleguidist I am going to go ahead and close this PR with the advice that people look into using that plugin instead of anything in this PR specifically. |
Yeah, we’re using display-name-handler in React Styleguidist and it works perfectly! |
Thanks! |
For helping out with #30.
Added tests and passes tests on my end for es6 class with no static displayName attached and also stateless component.
Would like a second pair of eyes in
src/handlers/displayNameHandler.js
online 34
. I'm not sure if I like that solution using[0]
, but not sure how to test around it.