Skip to content

Commit c98ce02

Browse files
author
Dustin Masters
committed
Fix identifier handling in sort-prop-types
1 parent 69e5201 commit c98ce02

File tree

2 files changed

+80
-45
lines changed

2 files changed

+80
-45
lines changed

lib/rules/sort-prop-types.js

Lines changed: 44 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,25 @@ module.exports = {
7878
return getValueName(node) === 'isRequired';
7979
}
8080

81+
/**
82+
* Find a variable by name in the current scope.
83+
* @param {string} name Name of the variable to look for.
84+
* @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
85+
*/
86+
function findVariableByName(name) {
87+
const variable = variableUtil.variablesInScope(context).find(item => item.name === name);
88+
89+
if (!variable || !variable.defs[0] || !variable.defs[0].node) {
90+
return null;
91+
}
92+
93+
if (variable.defs[0].node.type === 'TypeAlias') {
94+
return variable.defs[0].node.right;
95+
}
96+
97+
return variable.defs[0].node.init;
98+
}
99+
81100
/**
82101
* Checks if propTypes declarations are sorted
83102
* @param {Array} declarations The array of AST nodes being checked.
@@ -143,62 +162,42 @@ module.exports = {
143162
}, declarations[0]);
144163
}
145164

165+
function checkNode(node) {
166+
switch (node && node.type) {
167+
case 'ObjectExpression':
168+
checkSorted(node.properties);
169+
break;
170+
case 'Identifier':
171+
const propTypesObject = findVariableByName(node.name);
172+
if (propTypesObject && propTypesObject.properties) {
173+
checkSorted(propTypesObject.properties);
174+
}
175+
break;
176+
case 'CallExpression':
177+
const innerNode = node.arguments && node.arguments[0];
178+
if (propWrapperFunctions.has(node.callee.name) && innerNode) {
179+
checkNode(innerNode);
180+
}
181+
break;
182+
default:
183+
break;
184+
}
185+
}
186+
146187
return {
147188
ClassProperty: function(node) {
148189
if (!isPropTypesDeclaration(node)) {
149190
return;
150191
}
151-
switch (node.value && node.value.type) {
152-
case 'ObjectExpression':
153-
checkSorted(node.value.properties);
154-
break;
155-
case 'CallExpression':
156-
if (
157-
propWrapperFunctions.has(node.value.callee.name) &&
158-
node.value.arguments && node.value.arguments[0]
159-
) {
160-
checkSorted(node.value.arguments[0].properties);
161-
}
162-
break;
163-
default:
164-
break;
165-
}
192+
checkNode(node.value);
166193
},
167194

168195
MemberExpression: function(node) {
169196
if (!isPropTypesDeclaration(node.property)) {
170197
return;
171198
}
172-
const right = node.parent.right;
173-
let declarations;
174-
switch (right && right.type) {
175-
case 'CallExpression':
176-
if (
177-
propWrapperFunctions.has(right.callee.name) &&
178-
right.arguments && right.arguments[0]
179-
) {
180-
declarations = right.arguments[0].properties;
181-
}
182-
break;
183-
case 'ObjectExpression':
184-
declarations = right.properties;
185-
break;
186-
case 'Identifier':
187-
const variable = variableUtil.variablesInScope(context).find(item => item.name === right.name);
188-
if (
189-
!variable || !variable.defs[0] ||
190-
!variable.defs[0].node.init || !variable.defs[0].node.init.properties
191-
) {
192-
break;
193-
}
194-
declarations = variable.defs[0].node.init.properties;
195-
break;
196-
default:
197-
break;
198-
}
199-
if (declarations) {
200-
checkSorted(declarations);
201-
}
199+
200+
checkNode(node.parent.right);
202201
},
203202

204203
ObjectExpression: function(node) {

tests/lib/rules/sort-prop-types.js

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -563,6 +563,42 @@ ruleTester.run('sort-prop-types', rule, {
563563
column: 5,
564564
type: 'Property'
565565
}]
566+
}, {
567+
code: [
568+
'const First = (props) => <div />;',
569+
'const propTypes = {',
570+
' z: PropTypes.string,',
571+
' a: PropTypes.any,',
572+
'};',
573+
'First.propTypes = forbidExtraProps(propTypes);'
574+
].join('\n'),
575+
settings: {
576+
propWrapperFunctions: ['forbidExtraProps']
577+
},
578+
errors: [{
579+
message: ERROR_MESSAGE,
580+
line: 4,
581+
column: 5,
582+
type: 'Property'
583+
}]
584+
}, {
585+
code: [
586+
'const First = (props) => <div />;',
587+
'const propTypes = {',
588+
' z: PropTypes.string,',
589+
' a: PropTypes.any,',
590+
'};',
591+
'First.propTypes = propTypes;'
592+
].join('\n'),
593+
settings: {
594+
propWrapperFunctions: ['forbidExtraProps']
595+
},
596+
errors: [{
597+
message: ERROR_MESSAGE,
598+
line: 4,
599+
column: 5,
600+
type: 'Property'
601+
}]
566602
}, {
567603
code: [
568604
'var First = createReactClass({',

0 commit comments

Comments
 (0)