Skip to content

Commit 0386003

Browse files
CompuIvesfkling
authored andcommitted
Add checking stateless component default props (#108)
Fixes #69, With this PR we first search for defaultProps of the stateless component (if stateless) and then check using defaultProps or getDefaultProps, it will overwrite the defaultProps of the stateless component if any is found.
1 parent eb0edaa commit 0386003

File tree

2 files changed

+85
-18
lines changed

2 files changed

+85
-18
lines changed

src/handlers/__tests__/defaultPropsHandler-test.js

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -148,4 +148,42 @@ describe('defaultPropsHandler', () => {
148148
});
149149
});
150150

151+
describe('Functional components with default params', () => {
152+
it('should find default props that are literals', () => {
153+
var src = `
154+
({
155+
foo = "bar",
156+
bar = 42,
157+
baz = ["foo", "bar"],
158+
abc = {xyz: abc.def, 123: 42}
159+
}) => <div />
160+
`;
161+
test(parse(src).get('body', 0, 'expression'));
162+
});
163+
164+
it('should override with defaultProps if available', () => {
165+
var src = `
166+
var Foo = ({
167+
foo = "bar",
168+
bar = 42,
169+
baz = ["foo", "bar"],
170+
abc = 'test'
171+
}) => <div />
172+
Foo.defaultProps = { abc: {xyz: abc.def, 123: 42} };
173+
`;
174+
test(parse(src).get('body', 0, 'declarations', 0, 'init'));
175+
});
176+
177+
it('should work with aliases', () => {
178+
var src = `
179+
({
180+
foo = "bar",
181+
bar = 42,
182+
baz = ["foo", "bar"],
183+
abc: defg = {xyz: abc.def, 123: 42}
184+
}) => <div />
185+
`;
186+
test(parse(src).get('body', 0, 'expression'));
187+
});
188+
});
151189
});

src/handlers/defaultPropsHandler.js

Lines changed: 47 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -17,16 +17,21 @@ import getMemberValuePath from '../utils/getMemberValuePath';
1717
import printValue from '../utils/printValue';
1818
import recast from 'recast';
1919
import resolveToValue from '../utils/resolveToValue';
20+
import isStatelessComponent from '../utils/isStatelessComponent';
2021

2122
var {types: {namedTypes: types, visit}} = recast;
2223

23-
function getDefaultValue(path) {
24+
function getDefaultValue(path: NodePath) {
2425
var node = path.node;
2526
var defaultValue;
2627
if (types.Literal.check(node)) {
2728
defaultValue = node.raw;
2829
} else {
29-
path = resolveToValue(path);
30+
if (types.AssignmentPattern.check(path.node)) {
31+
path = resolveToValue(path.get('right'));
32+
} else {
33+
path = resolveToValue(path);
34+
}
3035
if (types.ImportDeclaration.check(path.node)) {
3136
defaultValue = node.name;
3237
} else {
@@ -44,10 +49,11 @@ function getDefaultValue(path) {
4449
}
4550
}
4651

47-
export default function defaultPropsHandler(
48-
documentation: Documentation,
49-
componentDefinition: NodePath
50-
) {
52+
function getStatelessPropsPath(componentDefinition): NodePath {
53+
return resolveToValue(componentDefinition).get('params', 0);
54+
}
55+
56+
function getDefaultPropsPath(componentDefinition: NodePath): ?NodePath {
5157
var defaultPropsPath = getMemberValuePath(
5258
componentDefinition,
5359
'defaultProps'
@@ -75,18 +81,41 @@ export default function defaultPropsHandler(
7581
},
7682
});
7783
}
84+
return defaultPropsPath;
85+
}
7886

79-
if (types.ObjectExpression.check(defaultPropsPath.node)) {
80-
defaultPropsPath.get('properties')
81-
.filter(propertyPath => types.Property.check(propertyPath.node))
82-
.forEach(function(propertyPath) {
83-
var propDescriptor = documentation.getPropDescriptor(
84-
getPropertyName(propertyPath)
85-
);
86-
var defaultValue = getDefaultValue(propertyPath.get('value'));
87-
if (defaultValue) {
88-
propDescriptor.defaultValue = defaultValue;
89-
}
90-
});
87+
function getDefaultValuesFromProps(
88+
properties: NodePath,
89+
documentation: Documentation
90+
) {
91+
properties
92+
.filter(propertyPath => types.Property.check(propertyPath.node))
93+
.forEach(function(propertyPath) {
94+
var propDescriptor = documentation.getPropDescriptor(
95+
getPropertyName(propertyPath)
96+
);
97+
var defaultValue = getDefaultValue(propertyPath.get('value'));
98+
if (defaultValue) {
99+
propDescriptor.defaultValue = defaultValue;
100+
}
101+
});
102+
}
103+
104+
export default function defaultPropsHandler(
105+
documentation: Documentation,
106+
componentDefinition: NodePath
107+
) {
108+
109+
var statelessProps = null;
110+
var defaultPropsPath = getDefaultPropsPath(componentDefinition);
111+
if (isStatelessComponent(componentDefinition)) {
112+
statelessProps = getStatelessPropsPath(componentDefinition);
113+
}
114+
115+
if (statelessProps && types.ObjectPattern.check(statelessProps.node)) {
116+
getDefaultValuesFromProps(statelessProps.get('properties'), documentation);
117+
}
118+
if (defaultPropsPath && types.ObjectExpression.check(defaultPropsPath.node)) {
119+
getDefaultValuesFromProps(defaultPropsPath.get('properties'), documentation);
91120
}
92121
}

0 commit comments

Comments
 (0)