Skip to content

Commit 1bc67d4

Browse files
committed
set new lint rule for prop value
1 parent 35aa34a commit 1bc67d4

File tree

3 files changed

+155
-0
lines changed

3 files changed

+155
-0
lines changed
Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
const _ = require('lodash');
2+
3+
const MAP_SCHEMA = {
4+
type: 'object',
5+
properties: {
6+
component: {
7+
type: 'string'
8+
},
9+
props: {
10+
type: 'array',
11+
items: {
12+
type: 'object',
13+
required: ['prop', 'value'],
14+
properties: {
15+
prop: {
16+
type: 'string'
17+
},
18+
value: {
19+
type: 'array',
20+
items: {
21+
type: 'object',
22+
required: ['prop', 'message', 'fix'],
23+
properties: {
24+
prop: {
25+
type: 'string'
26+
},
27+
message: {
28+
type: 'string'
29+
},
30+
fix: {
31+
type: 'object',
32+
required: ['propName'],
33+
properties: {
34+
propName: {
35+
type: 'string'
36+
}
37+
}
38+
}
39+
}
40+
}
41+
}
42+
}
43+
}
44+
}
45+
},
46+
additionalProperties: true
47+
};
48+
49+
module.exports = {
50+
meta: {
51+
docs: {
52+
description: "Detect deprecation of prop's value shape",
53+
category: 'Best Practices',
54+
recommended: true
55+
},
56+
messages: {
57+
uiLib: "This prop's value shape is deprecated."
58+
},
59+
fixable: 'code',
60+
schema: [MAP_SCHEMA]
61+
},
62+
create(context) {
63+
function testJSXAttributes(node) {
64+
try {
65+
const {deprecations} = _.get(context, 'options[0]');
66+
const nodeName = _.get(node, 'name.name');
67+
const deprecation = nodeName && deprecations && _.find(deprecations, ['component', nodeName]);
68+
if (deprecation.component && nodeName === deprecation.component) {
69+
_.forEach(node.attributes, attribute => {
70+
const attributeName = _.get(attribute, 'name.name');
71+
const deprecationProps = _.get(deprecation, 'props');
72+
const deprecationProp =
73+
attributeName && deprecationProps && _.find(deprecationProps, ['prop', attributeName]);
74+
const deprecationPropName = _.get(deprecationProp, 'prop');
75+
if (deprecationPropName && attributeName === deprecationPropName) {
76+
const attributeProperties = _.get(attribute, 'value.expression.properties');
77+
for (let i = 0; i <= attributeProperties.length; i++) {
78+
const propertyName = _.get(attributeProperties[i], 'key.name');
79+
const origin =
80+
deprecationProp.value && propertyName && _.find(deprecationProp.value, ['prop', propertyName]);
81+
if (origin.prop && propertyName === origin.prop) {
82+
const destination = _.get(origin, 'fix.propName');
83+
const message = `The shape of '${deprecationPropName}' prop of '${deprecation.component}' doesn't contain '${origin.prop}' anymore. Please use '${destination}' instead (fix is available).`;
84+
context.report({
85+
node,
86+
message,
87+
fix(fixer) {
88+
if (destination && attributeProperties[i].key) {
89+
return fixer.replaceText(attributeProperties[i].key, destination);
90+
}
91+
}
92+
});
93+
}
94+
}
95+
}
96+
});
97+
}
98+
} catch (err) {
99+
console.log('Found error in: ', context.getFilename());
100+
}
101+
}
102+
103+
return {
104+
JSXOpeningElement: testJSXAttributes
105+
};
106+
}
107+
};
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
const RuleTester = require('eslint').RuleTester;
2+
const rule = require('../../../lib/rules/prop-value-shape-deprecation');
3+
const deprecationsJson = require('../../prop-value-shape-deprecation.json');
4+
5+
RuleTester.setDefaultConfig({
6+
parser: 'babel-eslint',
7+
parserOptions: {ecmaVersion: 6, ecmaFeatures: {jsx: true}}
8+
});
9+
10+
const ruleTester = new RuleTester();
11+
12+
const ruleOptions = [{deprecations: deprecationsJson}];
13+
14+
ruleTester.run('prop-value-shape-deprecation', rule, {
15+
valid: [
16+
{
17+
options: ruleOptions,
18+
code: '<ListItem avatar={{source: {uri: some_uri}}}/>'
19+
}
20+
],
21+
invalid: [
22+
{
23+
options: ruleOptions,
24+
code: '<ListItem avatar={{imageSource: {uri: some_uri}}}/>',
25+
errors: [{message: `The shape of 'avatar' prop of 'ListItem' doesn't contain 'imageSource' anymore. Please use 'source' instead (fix is available).`}],
26+
output: '<ListItem avatar={{source: {uri: some_uri}}}/>'
27+
}
28+
]
29+
});
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
[
2+
{
3+
"component": "ListItem",
4+
"props": [
5+
{
6+
"prop": "avatar",
7+
"value": [
8+
{
9+
"prop": "imageSource",
10+
"message": "Please use the 'source' prop instead (fix is available).",
11+
"fix": {
12+
"propName": "source"
13+
}
14+
}
15+
]
16+
}
17+
]
18+
}
19+
]

0 commit comments

Comments
 (0)