Skip to content

Commit 38b2ccc

Browse files
authored
support props path in prop-value-shape-deprecation (#1227)
* support path props in prop-value-shape-deprecation * export prop-value-shape-deprecation
1 parent 50d6cc6 commit 38b2ccc

File tree

5 files changed

+296
-45
lines changed

5 files changed

+296
-45
lines changed

eslint-rules/index.js

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,17 @@ module.exports = {
66
'assets-deprecation': require('./lib/rules/assets-deprecation'),
77
'typography-deprecation': require('./lib/rules/typography-deprecation'),
88
'function-deprecation': require('./lib/rules/function-deprecation'),
9+
'prop-value-shape-deprecation': require('./lib/rules/prop-value-shape-deprecation'),
910
// for duplicate rules usage
1011
'component-deprecation_warn': require('./lib/rules/component-deprecation'),
1112
'assets-deprecation_warn': require('./lib/rules/assets-deprecation'),
1213
'typography-deprecation_warn': require('./lib/rules/typography-deprecation'),
1314
'function-deprecation_warn': require('./lib/rules/function-deprecation'),
15+
'prop-value-shape-deprecation_warn': require('./lib/rules/prop-value-shape-deprecation'),
1416
'component-deprecation_error': require('./lib/rules/component-deprecation'),
1517
'assets-deprecation_error': require('./lib/rules/assets-deprecation'),
1618
'typography-deprecation_error': require('./lib/rules/typography-deprecation'),
1719
'function-deprecation_error': require('./lib/rules/function-deprecation'),
18-
},
20+
'prop-value-shape-deprecation_error': require('./lib/rules/prop-value-shape-deprecation')
21+
}
1922
};

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

Lines changed: 52 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
const _ = require('lodash');
2-
const utils = require('../utils_old');
2+
const {findValueNodeOfIdentifier, getComponentName, getPathPrefix, getPathSuffix} = require('../utils_old');
33

44
const MAP_SCHEMA = {
55
type: 'object',
@@ -52,7 +52,7 @@ module.exports = {
5252
},
5353
create(context) {
5454
function reportPropValueShapeDeprecation(propKey, prop, deprecation, node) {
55-
const componentName = utils.getComponentName(node);
55+
const componentName = getComponentName(node);
5656
const newProp = _.get(deprecation, 'fix.propName');
5757
const fixMessage = _.get(deprecation, 'message') ? ' ' + _.get(deprecation, 'message') : '';
5858
const message = `The shape of '${prop}' prop of '${componentName}' doesn't contain '${deprecation.prop}' anymore.${fixMessage}`;
@@ -70,24 +70,13 @@ module.exports = {
7070
function testJSXAttributes(node) {
7171
try {
7272
const {deprecations} = _.get(context, 'options[0]');
73-
const componentName = utils.getComponentName(node);
73+
const componentName = getComponentName(node);
7474
_.forEach(deprecations, deprecation => {
7575
if (_.includes(deprecation.components, componentName)) {
7676
_.forEach(node.attributes, attribute => {
77-
const attributeName = _.get(attribute, 'name.name');
78-
if (attribute.type === 'JSXSpreadAttribute') {
79-
const spreadSource = utils.findValueNodeOfIdentifier(attribute.argument.name, context.getScope());
80-
const spreadSourceName = _.get(spreadSource, 'properties[0].key.name');
81-
checkAttributeProperties(
82-
spreadSource.properties[0].value.properties,
83-
spreadSourceName,
84-
deprecation,
85-
node,
86-
context
87-
);
88-
} else if (_.includes(deprecation.propNames, attributeName)) {
89-
checkAttribute(attribute, deprecation, node);
90-
}
77+
_.forEach(deprecation.propNames, deprecationProp => {
78+
recursiveDeprecation(attribute, deprecationProp, deprecation, deprecationProp, node);
79+
});
9180
});
9281
}
9382
});
@@ -96,34 +85,58 @@ module.exports = {
9685
}
9786
}
9887

99-
function checkAttribute(attribute, deprecation, node) {
100-
const attributeName = _.get(attribute, 'name.name');
101-
const attributeType = _.get(attribute, 'value.expression.type');
102-
if (attributeType === 'Identifier') {
103-
const passedProp = utils.findValueNodeOfIdentifier(attribute.value.expression.name, context.getScope());
104-
if (passedProp && passedProp.properties) {
105-
checkAttributeProperties(passedProp.properties, attributeName, deprecation, node, context);
88+
function recursiveDeprecation(attribute, deprecationProp, deprecation, deprecationPath, node) {
89+
const deprecationPrefix = getPathPrefix(deprecationProp);
90+
const deprecationSuffix = getPathSuffix(deprecationProp);
91+
let passedProps;
92+
let attributeName = _.get(attribute, 'name.name') || _.get(attribute, 'key.name');
93+
if (attribute.type === 'JSXSpreadAttribute' || attribute.type === 'ExperimentalSpreadProperty') {
94+
const spreadSource = findValueNodeOfIdentifier(attribute.argument.name, context.getScope());
95+
const spreadSourceName = _.get(spreadSource, 'properties[0].key.name');
96+
if (deprecationPrefix === spreadSourceName) {
97+
checkAttributeProperties(spreadSource.properties[0].value.properties, deprecationPath, deprecation, node);
10698
}
107-
}
108-
const attributeProps = _.get(attribute, 'value.expression.properties');
109-
for (let index = 0; index < attributeProps.length; index++) {
110-
const spreadElementType = _.get(attribute, `value.expression.properties[${index}].type`);
111-
if (attributeType === 'ObjectExpression' && spreadElementType === 'ExperimentalSpreadProperty') {
112-
const spreadSource = utils.findValueNodeOfIdentifier(
113-
attribute.value.expression.properties[index].argument.name,
114-
context.getScope()
115-
);
116-
if (spreadSource && spreadSource.properties) {
117-
checkAttributeProperties(spreadSource.properties, attributeName, deprecation, node);
118-
}
99+
} else if (!deprecationSuffix && deprecationPrefix === attributeName) {
100+
const attributeType = _.get(attribute, 'value.expression.type') || _.get(attribute, 'type');
101+
if (attributeType === 'Identifier') {
102+
const passedPropsName = _.get(attribute, 'value.expression.name');
103+
passedProps = findValueNodeOfIdentifier(passedPropsName, context.getScope());
104+
}
105+
let attributeProperties = passedProps
106+
? _.get(passedProps, 'properties')
107+
: attributeType === 'Property'
108+
? _.get(attribute, 'value.properties')
109+
: _.get(attribute, 'value.expression.properties');
110+
if (attributeType === 'Property' && !attributeProperties) {
111+
const passedPropsName = _.get(attribute, 'value.name');
112+
passedProps = findValueNodeOfIdentifier(passedPropsName, context.getScope());
113+
attributeProperties = passedProps.properties;
119114
}
115+
checkAttributeProperties(attributeProperties, deprecationPath, deprecation, node);
116+
} else if (deprecationSuffix) {
117+
const attributeType = _.get(attribute, 'value.expression.type');
118+
if (attributeType === 'Identifier') {
119+
const passedPropsName = _.get(attribute, 'value.expression.name');
120+
passedProps = findValueNodeOfIdentifier(passedPropsName, context.getScope());
121+
}
122+
const attributeProperties = passedProps
123+
? _.get(passedProps, 'properties')
124+
: _.get(attribute, 'value.expression.properties') ||
125+
_.get(attribute, 'value.properties') ||
126+
_.get(attribute, 'value.expression.elements[0].properties');
127+
_.forEach(attributeProperties, attributeProperty => {
128+
recursiveDeprecation(attributeProperty, deprecationSuffix, deprecation, deprecationPath, node);
129+
});
120130
}
121-
const attributeProperties = _.get(attribute, 'value.expression.properties');
122-
checkAttributeProperties(attributeProperties, attributeName, deprecation, node);
123131
}
124132

125133
function checkAttributeProperties(attributeProperties, attributeName, deprecation, node) {
126-
for (let i = 0; i <= attributeProperties.length; i++) {
134+
for (let i = 0; i < attributeProperties.length; i++) {
135+
const propertyType = _.get(attributeProperties[i], 'type');
136+
if (propertyType === 'ExperimentalSpreadProperty') {
137+
const spreadProps = findValueNodeOfIdentifier(attributeProperties[i].argument.name, context.getScope());
138+
checkAttributeProperties(spreadProps.properties, attributeName, deprecation, node);
139+
}
127140
const propertyName = _.get(attributeProperties[i], 'key.name');
128141
const origin = propertyName && _.find(deprecation.shape, ['prop', propertyName]);
129142
if (origin && origin.prop && propertyName === origin.prop) {

eslint-rules/lib/utils_old.js

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,10 @@ function findValueNodeOfIdentifier(identifierName, scope) {
5656
}
5757
}
5858
});
59-
return valueNode;
59+
if (scope.upper === null) {
60+
return valueNode;
61+
}
62+
return valueNode || findValueNodeOfIdentifier(identifierName, scope.upper);
6063
}
6164

6265
function getLocalImportSpecifier(node, source, defaultImportName) {
@@ -98,6 +101,16 @@ function getComponentName(node) {
98101
return nodeProperty ? (nodeName + '.' + nodeProperty) : nodeName;
99102
}
100103

104+
function getPathPrefix(str) {
105+
const index = str.indexOf('.');
106+
return index === -1 ? str : str.substring(0, index);
107+
}
108+
109+
function getPathSuffix(str) {
110+
const index = str.indexOf('.');
111+
return index === -1 ? undefined : str.substring(index + 1);
112+
}
113+
101114
module.exports = {
102115
isPropFont,
103116
findAndReportHardCodedValues,
@@ -107,5 +120,7 @@ module.exports = {
107120
findValueNodeOfIdentifier,
108121
getLocalImportSpecifier,
109122
getSpecifierIndex,
110-
getComponentName
123+
getComponentName,
124+
getPathPrefix,
125+
getPathSuffix
111126
};

0 commit comments

Comments
 (0)