Skip to content

Commit ef7f6eb

Browse files
committed
[Refactor] extract getKeyValue, isAssignmentLHS to ast util
1 parent 13be022 commit ef7f6eb

File tree

5 files changed

+53
-89
lines changed

5 files changed

+53
-89
lines changed

lib/rules/destructuring-assignment.js

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
const Components = require('../util/Components');
88
const docsUrl = require('../util/docsUrl');
9+
const isAssignmentLHS = require('../util/ast').isAssignmentLHS;
910

1011
const DEFAULT_OPTION = 'always';
1112

@@ -38,19 +39,6 @@ module.exports = {
3839
const configuration = context.options[0] || DEFAULT_OPTION;
3940
const ignoreClassFields = context.options[1] && context.options[1].ignoreClassFields === true || false;
4041

41-
/**
42-
* Checks if a prop is being assigned a value props.bar = 'bar'
43-
* @param {ASTNode} node The AST node being checked.
44-
* @returns {Boolean}
45-
*/
46-
47-
function isAssignmentToProp(node) {
48-
return (
49-
node.parent &&
50-
node.parent.type === 'AssignmentExpression' &&
51-
node.parent.left === node
52-
);
53-
}
5442
/**
5543
* @param {ASTNode} node We expect either an ArrowFunctionExpression,
5644
* FunctionDeclaration, or FunctionExpression
@@ -74,7 +62,7 @@ module.exports = {
7462

7563
function handleSFCUsage(node) {
7664
// props.aProp || context.aProp
77-
const isPropUsed = (node.object.name === 'props' || node.object.name === 'context') && !isAssignmentToProp(node);
65+
const isPropUsed = (node.object.name === 'props' || node.object.name === 'context') && !isAssignmentLHS(node);
7866
if (isPropUsed && configuration === 'always') {
7967
context.report({
8068
node,
@@ -99,7 +87,7 @@ module.exports = {
9987
const isPropUsed = (
10088
node.object.type === 'MemberExpression' && node.object.object.type === 'ThisExpression' &&
10189
(node.object.property.name === 'props' || node.object.property.name === 'context' || node.object.property.name === 'state') &&
102-
!isAssignmentToProp(node)
90+
!isAssignmentLHS(node)
10391
);
10492

10593
if (

lib/rules/forbid-foreign-prop-types.js

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
'use strict';
77

88
const docsUrl = require('../util/docsUrl');
9+
const ast = require('../util/ast');
910

1011
module.exports = {
1112
meta: {
@@ -37,10 +38,6 @@ module.exports = {
3738
// Helpers
3839
// --------------------------------------------------------------------------
3940

40-
function isLeftSideOfAssignment(node) {
41-
return node.parent.type === 'AssignmentExpression' && node.parent.left === node;
42-
}
43-
4441
function findParentAssignmentExpression(node) {
4542
let parent = node.parent;
4643

@@ -101,12 +98,12 @@ module.exports = {
10198
!node.computed &&
10299
node.property.type === 'Identifier' &&
103100
node.property.name === 'propTypes' &&
104-
!isLeftSideOfAssignment(node) &&
101+
!ast.isAssignmentLHS(node) &&
105102
!isAllowedAssignment(node)
106103
) || (
107104
(node.property.type === 'Literal' || node.property.type === 'JSXText') &&
108105
node.property.value === 'propTypes' &&
109-
!isLeftSideOfAssignment(node) &&
106+
!ast.isAssignmentLHS(node) &&
110107
!isAllowedAssignment(node)
111108
)
112109
) {

lib/util/ast.js

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,13 +150,54 @@ function isClass(node) {
150150
return node.type === 'ClassDeclaration' || node.type === 'ClassExpression';
151151
}
152152

153+
/**
154+
* Removes quotes from around an identifier.
155+
* @param {string} string the identifier to strip
156+
*/
157+
function stripQuotes(string) {
158+
return string.replace(/^'|'$/g, '');
159+
}
160+
161+
/**
162+
* Retrieve the name of a key node
163+
* @param {Context} context The AST node with the key.
164+
* @param {ASTNode} node The AST node with the key.
165+
* @return {string} the name of the key
166+
*/
167+
function getKeyValue(context, node) {
168+
if (node.type === 'ObjectTypeProperty') {
169+
const tokens = context.getFirstTokens(node, 2);
170+
return (tokens[0].value === '+' || tokens[0].value === '-' ?
171+
tokens[1].value :
172+
stripQuotes(tokens[0].value)
173+
);
174+
}
175+
const key = node.key || node.argument;
176+
return key.type === 'Identifier' ? key.name : key.value;
177+
}
178+
179+
/**
180+
* Checks if a node is being assigned a value: props.bar = 'bar'
181+
* @param {ASTNode} node The AST node being checked.
182+
* @returns {Boolean}
183+
*/
184+
function isAssignmentLHS(node) {
185+
return (
186+
node.parent &&
187+
node.parent.type === 'AssignmentExpression' &&
188+
node.parent.left === node
189+
);
190+
}
191+
153192
module.exports = {
154193
findReturnStatement,
155194
getFirstNodeInLine,
156195
getPropertyName,
157196
getPropertyNameNode,
158197
getComponentProperties,
198+
getKeyValue,
159199
isArrowFunction,
200+
isAssignmentLHS,
160201
isClass,
161202
isFunction,
162203
isFunctionLikeExpression,

lib/util/propTypes.js

Lines changed: 2 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@ const annotations = require('./annotations');
88
const propsUtil = require('./props');
99
const variableUtil = require('./variable');
1010
const versionUtil = require('./version');
11-
const propWrapperUtil = require('../util/propWrapper');
11+
const propWrapperUtil = require('./propWrapper');
12+
const getKeyValue = require('./ast').getKeyValue;
1213

1314
/**
1415
* Checks if we are declaring a props as a generic type in a flow-annotated class.
@@ -25,32 +26,6 @@ function isSuperTypeParameterPropsDeclaration(node) {
2526
return false;
2627
}
2728

28-
/**
29-
* Removes quotes from around an identifier.
30-
* @param {string} string the identifier to strip
31-
*/
32-
function stripQuotes(string) {
33-
return string.replace(/^'|'$/g, '');
34-
}
35-
36-
/**
37-
* Retrieve the name of a key node
38-
* @param {Context} context The AST node with the key.
39-
* @param {ASTNode} node The AST node with the key.
40-
* @return {string} the name of the key
41-
*/
42-
function getKeyValue(context, node) {
43-
if (node.type === 'ObjectTypeProperty') {
44-
const tokens = context.getFirstTokens(node, 2);
45-
return (tokens[0].value === '+' || tokens[0].value === '-' ?
46-
tokens[1].value :
47-
stripQuotes(tokens[0].value)
48-
);
49-
}
50-
const key = node.key || node.argument;
51-
return key.type === 'Identifier' ? key.name : key.value;
52-
}
53-
5429
/**
5530
* Iterates through a properties node, like a customized forEach.
5631
* @param {Object} context Array of properties to iterate.

lib/util/usedPropTypes.js

Lines changed: 4 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66

77
const astUtil = require('./ast');
88
const versionUtil = require('./version');
9+
const ast = require('./ast');
910

1011
// ------------------------------------------------------------------------------
1112
// Constants
@@ -176,31 +177,6 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
176177
return tokens.length && tokens[0].value === '...';
177178
}
178179

179-
/**
180-
* Removes quotes from around an identifier.
181-
* @param {string} string the identifier to strip
182-
*/
183-
function stripQuotes(string) {
184-
return string.replace(/^'|'$/g, '');
185-
}
186-
187-
/**
188-
* Retrieve the name of a key node
189-
* @param {ASTNode} node The AST node with the key.
190-
* @return {string} the name of the key
191-
*/
192-
function getKeyValue(node) {
193-
if (node.type === 'ObjectTypeProperty') {
194-
const tokens = context.getFirstTokens(node, 2);
195-
return (tokens[0].value === '+' || tokens[0].value === '-' ?
196-
tokens[1].value :
197-
stripQuotes(tokens[0].value)
198-
);
199-
}
200-
const key = node.key || node.argument;
201-
return key.type === 'Identifier' ? key.name : key.value;
202-
}
203-
204180
/**
205181
* Retrieve the name of a property node
206182
* @param {ASTNode} node The AST node with the property.
@@ -251,19 +227,6 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
251227
}
252228
}
253229

254-
/**
255-
* Checks if a prop is being assigned a value props.bar = 'bar'
256-
* @param {ASTNode} node The AST node being checked.
257-
* @returns {Boolean}
258-
*/
259-
function isAssignmentToProp(node) {
260-
return (
261-
node.parent &&
262-
node.parent.type === 'AssignmentExpression' &&
263-
node.parent.left === node
264-
);
265-
}
266-
267230
/**
268231
* Checks if we are using a prop
269232
* @param {ASTNode} node The AST node being checked.
@@ -276,7 +239,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
276239
(utils.getParentES6Component() || utils.getParentES5Component()) &&
277240
(isThisPropsUsage || isPropArgumentInSetStateUpdater(node))
278241
);
279-
const isStatelessFunctionUsage = node.object.name === 'props' && !isAssignmentToProp(node);
242+
const isStatelessFunctionUsage = node.object.name === 'props' && !ast.isAssignmentLHS(node);
280243
return isClassUsage || isStatelessFunctionUsage || (isPropsUsage && inLifeCycleMethod());
281244
}
282245

@@ -309,7 +272,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
309272
node.parent.id &&
310273
node.parent.id.properties &&
311274
node.parent.id.properties.length &&
312-
getKeyValue(node.parent.id.properties[0])
275+
ast.getKeyValue(context, node.parent.id.properties[0])
313276
) {
314277
type = 'destructuring';
315278
properties = node.parent.id.properties;
@@ -391,7 +354,7 @@ module.exports = function usedPropTypesInstructions(context, components, utils)
391354
ignoreUnusedPropTypesValidation = true;
392355
break;
393356
}
394-
const propName = getKeyValue(properties[k]);
357+
const propName = ast.getKeyValue(context, properties[k]);
395358

396359
let currentNode = node;
397360
allNames = [];

0 commit comments

Comments
 (0)