Skip to content

Commit 4debe82

Browse files
committed
refactor propShapeValueDeprecation
1 parent 1e6c8af commit 4debe82

File tree

2 files changed

+99
-70
lines changed

2 files changed

+99
-70
lines changed

eslint-rules/lib/rules/prop-value-shape-deprecation.js

Lines changed: 46 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -29,14 +29,12 @@ const MAP_SCHEMA = {
2929
type: 'string'
3030
},
3131
fix: {
32-
type: 'object',
33-
additionalProperties: true
32+
type: 'object'
3433
}
3534
}
3635
}
3736
}
38-
},
39-
additionalProperties: true
37+
}
4038
};
4139

4240
module.exports = {
@@ -53,6 +51,21 @@ module.exports = {
5351
schema: [MAP_SCHEMA]
5452
},
5553
create(context) {
54+
function reportPropValueShapeDeprecation(attributePropertyKey, attributeName, origin, node) {
55+
const nodeName = _.get(node, 'name.name');
56+
const destination = _.get(origin, 'fix.propName');
57+
const message = `The shape of '${attributeName}' prop of '${nodeName}' doesn't contain '${origin.prop}' anymore. Please use '${destination}' instead (fix is available).`;
58+
context.report({
59+
node,
60+
message,
61+
fix(fixer) {
62+
if (destination && attributePropertyKey) {
63+
return fixer.replaceText(attributePropertyKey, destination);
64+
}
65+
}
66+
});
67+
}
68+
5669
function testJSXAttributes(node) {
5770
try {
5871
const {deprecations} = _.get(context, 'options[0]');
@@ -68,43 +81,11 @@ module.exports = {
6881
spreadSource.properties[0].value.properties,
6982
spreadSourceName,
7083
deprecation,
71-
nodeName,
7284
node,
7385
context
7486
);
7587
} else if (_.includes(deprecation.propNames, attributeName)) {
76-
const attributeType = _.get(attribute, 'value.expression.type');
77-
if (attributeType === 'Identifier') {
78-
const passedProp = utils.findValueNodeOfIdentifier(
79-
attribute.value.expression.name,
80-
context.getScope()
81-
);
82-
if (passedProp && passedProp.properties) {
83-
checkAttributeProperties(
84-
passedProp.properties,
85-
attributeName,
86-
deprecation,
87-
nodeName,
88-
node,
89-
context
90-
);
91-
}
92-
}
93-
const attributeProps = _.get(attribute, 'value.expression.properties');
94-
for (let index = 0; index < attributeProps.length; index++) {
95-
const spreadElementType = _.get(attribute, `value.expression.properties[${index}].type`);
96-
if (attributeType === 'ObjectExpression' && spreadElementType === 'ExperimentalSpreadProperty') {
97-
const spreadSource = utils.findValueNodeOfIdentifier(
98-
attribute.value.expression.properties[index].argument.name,
99-
context.getScope()
100-
);
101-
if (spreadSource && spreadSource.properties) {
102-
checkAttributeProperties(spreadSource.properties, attributeName, deprecation, nodeName, node, context);
103-
}
104-
}
105-
}
106-
const attributeProperties = _.get(attribute, 'value.expression.properties');
107-
checkAttributeProperties(attributeProperties, attributeName, deprecation, nodeName, node, context);
88+
checkAttribute(attribute, deprecation, node);
10889
}
10990
});
11091
}
@@ -114,22 +95,38 @@ module.exports = {
11495
}
11596
}
11697

117-
function checkAttributeProperties(attributeProperties, attributeName, deprecation, nodeName, node, context) {
98+
function checkAttribute(attribute, deprecation, node) {
99+
const attributeName = _.get(attribute, 'name.name');
100+
const attributeType = _.get(attribute, 'value.expression.type');
101+
if (attributeType === 'Identifier') {
102+
const passedProp = utils.findValueNodeOfIdentifier(attribute.value.expression.name, context.getScope());
103+
if (passedProp && passedProp.properties) {
104+
checkAttributeProperties(passedProp.properties, attributeName, deprecation, node, context);
105+
}
106+
}
107+
const attributeProps = _.get(attribute, 'value.expression.properties');
108+
for (let index = 0; index < attributeProps.length; index++) {
109+
const spreadElementType = _.get(attribute, `value.expression.properties[${index}].type`);
110+
if (attributeType === 'ObjectExpression' && spreadElementType === 'ExperimentalSpreadProperty') {
111+
const spreadSource = utils.findValueNodeOfIdentifier(
112+
attribute.value.expression.properties[index].argument.name,
113+
context.getScope()
114+
);
115+
if (spreadSource && spreadSource.properties) {
116+
checkAttributeProperties(spreadSource.properties, attributeName, deprecation, node);
117+
}
118+
}
119+
}
120+
const attributeProperties = _.get(attribute, 'value.expression.properties');
121+
checkAttributeProperties(attributeProperties, attributeName, deprecation, node);
122+
}
123+
124+
function checkAttributeProperties(attributeProperties, attributeName, deprecation, node) {
118125
for (let i = 0; i <= attributeProperties.length; i++) {
119126
const propertyName = _.get(attributeProperties[i], 'key.name');
120127
const origin = propertyName && _.find(deprecation.shape, ['prop', propertyName]);
121128
if (origin && origin.prop && propertyName === origin.prop) {
122-
const destination = _.get(origin, 'fix.propName');
123-
const message = `The shape of '${attributeName}' prop of '${nodeName}' doesn't contain '${origin.prop}' anymore. Please use '${destination}' instead (fix is available).`;
124-
context.report({
125-
node,
126-
message,
127-
fix(fixer) {
128-
if (destination && attributeProperties[i].key) {
129-
return fixer.replaceText(attributeProperties[i].key, destination);
130-
}
131-
}
132-
});
129+
reportPropValueShapeDeprecation(attributeProperties[i].key, attributeName, origin, node);
133130
}
134131
}
135132
}

eslint-rules/tests/lib/rules/prop-value-shape-deprecation.js

Lines changed: 53 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,21 @@ RuleTester.setDefaultConfig({
88
});
99

1010
const ruleTester = new RuleTester();
11-
11+
const imageSource = 'imageSource: {uri: some_uri}';
12+
const source = 'source: {uri: some_uri}';
1213
const ruleOptions = [{deprecations: deprecationsJson}];
1314
const PassedPropExampleCode = `
1415
const myProps = {
1516
goodProp: goodValue,
16-
imageSource: {uri: some_uri}
17+
${imageSource}
1718
};
1819
1920
<Label avatar={myProps}/>
2021
`;
2122
const PassedPropExampleOutput = `
2223
const myProps = {
2324
goodProp: goodValue,
24-
source: {uri: some_uri}
25+
${source}
2526
};
2627
2728
<Label avatar={myProps}/>
@@ -31,7 +32,7 @@ const firstLevelSpreadCode = `
3132
const myProps = {
3233
avatarProps: {
3334
goodProp: goodValue,
34-
imageSource: {uri: some_uri}
35+
${imageSource}
3536
}
3637
};
3738
@@ -42,7 +43,7 @@ const firstLevelSpreadOutput = `
4243
const myProps = {
4344
avatarProps: {
4445
goodProp: goodValue,
45-
source: {uri: some_uri}
46+
${source}
4647
}
4748
};
4849
@@ -52,7 +53,7 @@ const myProps = {
5253
const secondLevelSpreadCode = `
5354
const myProps = {
5455
goodProp: goodValue,
55-
imageSource: {uri: some_uri}
56+
${imageSource}
5657
};
5758
5859
<Label avatar={{goodProp: goodValue, ...myProps}}/>
@@ -61,55 +62,86 @@ const myProps = {
6162
const secondLevelSpreadOutput = `
6263
const myProps = {
6364
goodProp: goodValue,
64-
source: {uri: some_uri}
65+
${source}
6566
};
6667
6768
<Label avatar={{goodProp: goodValue, ...myProps}}/>
6869
`;
6970

70-
7171
ruleTester.run('prop-value-shape-deprecation', rule, {
7272
valid: [
7373
{
7474
options: ruleOptions,
75-
code: '<ListItem avatar={{source: {uri: some_uri}}}/>'
75+
code: `<ListItem avatar={{${source}}}/>`
76+
},
77+
{
78+
options: ruleOptions,
79+
code: `<ListItem avatar={{someProp: goodValue, ${source}}}/>`
80+
},
81+
{
82+
options: ruleOptions,
83+
code: `<ListItem goodProp={{${imageSource}}} avatar={{${source}}}/>`
7684
}
7785
],
7886
invalid: [
7987
{
8088
options: ruleOptions,
81-
code: '<ListItem avatar={{imageSource: {uri: some_uri}, someProp: someValue}}/>',
82-
errors: [{message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
83-
output: '<ListItem avatar={{source: {uri: some_uri}, someProp: someValue}}/>'
89+
code: `<ListItem avatar={{${imageSource}, someProp: someValue}}/>`,
90+
errors: [
91+
{
92+
message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
93+
}
94+
],
95+
output: `<ListItem avatar={{${source}, someProp: someValue}}/>`
8496
},
8597
{
8698
options: ruleOptions,
87-
code: '<ListItem avatar={{someProp: someValue, imageSource: {uri: some_uri}}}/>',
88-
errors: [{message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
89-
output: '<ListItem avatar={{someProp: someValue, source: {uri: some_uri}}}/>'
99+
code: `<ListItem avatar={{someProp: someValue, ${imageSource}}}/>`,
100+
errors: [
101+
{
102+
message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
103+
}
104+
],
105+
output: `<ListItem avatar={{someProp: someValue, ${source}}}/>`
90106
},
91107
{
92108
options: ruleOptions,
93-
code: '<ListItem someProp={someValue} avatar={{imageSource: {uri: some_uri}}}/>',
94-
errors: [{message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
95-
output: '<ListItem someProp={someValue} avatar={{source: {uri: some_uri}}}/>'
109+
code: `<ListItem someProp={someValue} avatar={{${imageSource}}}/>`,
110+
errors: [
111+
{
112+
message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
113+
}
114+
],
115+
output: `<ListItem someProp={someValue} avatar={{${source}}}/>`
96116
},
97117
{
98118
options: ruleOptions,
99119
code: PassedPropExampleCode,
100-
errors: [{message: `The shape of 'avatar' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
120+
errors: [
121+
{
122+
message: `The shape of 'avatar' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
123+
}
124+
],
101125
output: PassedPropExampleOutput
102126
},
103127
{
104128
options: ruleOptions,
105129
code: firstLevelSpreadCode,
106-
errors: [{message: `The shape of 'avatarProps' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
130+
errors: [
131+
{
132+
message: `The shape of 'avatarProps' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
133+
}
134+
],
107135
output: firstLevelSpreadOutput
108136
},
109137
{
110138
options: ruleOptions,
111139
code: secondLevelSpreadCode,
112-
errors: [{message: `The shape of 'avatar' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
140+
errors: [
141+
{
142+
message: `The shape of 'avatar' prop of 'Label' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`
143+
}
144+
],
113145
output: secondLevelSpreadOutput
114146
}
115147
]

0 commit comments

Comments
 (0)