Skip to content

Commit cc14018

Browse files
committed
fix(defaultProps): Resolve local spreads in defaultProps
1 parent 18e2e1a commit cc14018

File tree

3 files changed

+120
-11
lines changed

3 files changed

+120
-11
lines changed

src/handlers/__tests__/__snapshots__/defaultPropsHandler-test.js.snap

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,23 @@ Object {
4040
}
4141
`;
4242

43+
exports[`defaultPropsHandler ClassDeclaration with static defaultProps should resolve local spreads 1`] = `
44+
Object {
45+
"bar": Object {
46+
"defaultValue": Object {
47+
"computed": false,
48+
"value": "\\"foo\\"",
49+
},
50+
},
51+
"foo": Object {
52+
"defaultValue": Object {
53+
"computed": false,
54+
"value": "\\"bar\\"",
55+
},
56+
},
57+
}
58+
`;
59+
4360
exports[`defaultPropsHandler ClassExpression with static defaultProps should find prop default values that are literals 1`] = `
4461
Object {
4562
"abc": Object {
@@ -69,6 +86,23 @@ Object {
6986
}
7087
`;
7188

89+
exports[`defaultPropsHandler Functional components with default params resolves local spreads 1`] = `
90+
Object {
91+
"bar": Object {
92+
"defaultValue": Object {
93+
"computed": false,
94+
"value": "\\"foo\\"",
95+
},
96+
},
97+
"foo": Object {
98+
"defaultValue": Object {
99+
"computed": false,
100+
"value": "\\"bar\\"",
101+
},
102+
},
103+
}
104+
`;
105+
72106
exports[`defaultPropsHandler Functional components with default params should find default props that are literals 1`] = `
73107
Object {
74108
"abc": Object {
@@ -197,6 +231,23 @@ Object {
197231
}
198232
`;
199233

234+
exports[`defaultPropsHandler ObjectExpression resolves local spreads 1`] = `
235+
Object {
236+
"bar": Object {
237+
"defaultValue": Object {
238+
"computed": false,
239+
"value": "\\"foo\\"",
240+
},
241+
},
242+
"foo": Object {
243+
"defaultValue": Object {
244+
"computed": false,
245+
"value": "\\"bar\\"",
246+
},
247+
},
248+
}
249+
`;
250+
200251
exports[`defaultPropsHandler ObjectExpression should find prop default values that are literals 1`] = `
201252
Object {
202253
"abc": Object {

src/handlers/__tests__/defaultPropsHandler-test.js

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,26 @@ describe('defaultPropsHandler', () => {
7575
);
7676
expect(documentation.descriptors).toMatchSnapshot();
7777
});
78+
79+
it('resolves local spreads', () => {
80+
const src = `
81+
const other = { bar: "foo" };
82+
83+
({
84+
getDefaultProps: function() {
85+
return {
86+
foo: "bar",
87+
...other,
88+
};
89+
}
90+
})
91+
`;
92+
defaultPropsHandler(
93+
documentation,
94+
parse(src).get('body', 1, 'expression'),
95+
);
96+
expect(documentation.descriptors).toMatchSnapshot();
97+
});
7898
});
7999

80100
describe('ClassDeclaration with static defaultProps', () => {
@@ -93,6 +113,21 @@ describe('defaultPropsHandler', () => {
93113
expect(documentation.descriptors).toMatchSnapshot();
94114
});
95115

116+
it('should resolve local spreads', () => {
117+
const src = `
118+
const other = { bar: "foo" };
119+
120+
class Foo {
121+
static defaultProps = {
122+
foo: "bar",
123+
...other
124+
};
125+
}
126+
`;
127+
defaultPropsHandler(documentation, parse(src).get('body', 1));
128+
expect(documentation.descriptors).toMatchSnapshot();
129+
});
130+
96131
it('should find prop default values that are imported variables', () => {
97132
const src = `
98133
import ImportedComponent from './ImportedComponent';
@@ -177,6 +212,19 @@ describe('defaultPropsHandler', () => {
177212
expect(documentation.descriptors).toMatchSnapshot();
178213
});
179214

215+
it('resolves local spreads', () => {
216+
const src = `
217+
const other = { bar: "foo" };
218+
var Foo = (props) => <div />
219+
Foo.defaultProps = { foo: "bar", ...other };
220+
`;
221+
defaultPropsHandler(
222+
documentation,
223+
parse(src).get('body', 1, 'declarations', 0, 'init'),
224+
);
225+
expect(documentation.descriptors).toMatchSnapshot();
226+
});
227+
180228
it('should work with aliases', () => {
181229
const src = `
182230
({

src/handlers/defaultPropsHandler.js

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -90,25 +90,35 @@ function getDefaultValuesFromProps(
9090
isStateless: boolean,
9191
) {
9292
properties
93-
.filter(propertyPath => t.Property.check(propertyPath.node))
9493
// Don't evaluate property if component is functional and the node is not an AssignmentPattern
9594
.filter(
9695
propertyPath =>
9796
!isStateless ||
9897
t.AssignmentPattern.check(propertyPath.get('value').node),
9998
)
10099
.forEach(propertyPath => {
101-
const propName = getPropertyName(propertyPath);
102-
if (!propName) return;
100+
if (t.Property.check(propertyPath.node)) {
101+
const propName = getPropertyName(propertyPath);
102+
if (!propName) return;
103103

104-
const propDescriptor = documentation.getPropDescriptor(propName);
105-
const defaultValue = getDefaultValue(
106-
isStateless
107-
? propertyPath.get('value', 'right')
108-
: propertyPath.get('value'),
109-
);
110-
if (defaultValue) {
111-
propDescriptor.defaultValue = defaultValue;
104+
const propDescriptor = documentation.getPropDescriptor(propName);
105+
const defaultValue = getDefaultValue(
106+
isStateless
107+
? propertyPath.get('value', 'right')
108+
: propertyPath.get('value'),
109+
);
110+
if (defaultValue) {
111+
propDescriptor.defaultValue = defaultValue;
112+
}
113+
} else if (t.SpreadElement.check(propertyPath.node)) {
114+
const resolvedValuePath = resolveToValue(propertyPath.get('argument'));
115+
if (t.ObjectExpression.check(resolvedValuePath.node)) {
116+
getDefaultValuesFromProps(
117+
resolvedValuePath.get('properties'),
118+
documentation,
119+
isStateless,
120+
);
121+
}
112122
}
113123
});
114124
}

0 commit comments

Comments
 (0)