Skip to content

Commit

Permalink
Fix identifier handling in sort-prop-types
Browse files Browse the repository at this point in the history
  • Loading branch information
Dustin Masters committed Aug 11, 2017
1 parent 69e5201 commit c98ce02
Show file tree
Hide file tree
Showing 2 changed files with 80 additions and 45 deletions.
89 changes: 44 additions & 45 deletions lib/rules/sort-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,25 @@ module.exports = {
return getValueName(node) === 'isRequired';
}

/**
* Find a variable by name in the current scope.
* @param {string} name Name of the variable to look for.
* @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
*/
function findVariableByName(name) {
const variable = variableUtil.variablesInScope(context).find(item => item.name === name);

if (!variable || !variable.defs[0] || !variable.defs[0].node) {
return null;
}

if (variable.defs[0].node.type === 'TypeAlias') {
return variable.defs[0].node.right;
}

return variable.defs[0].node.init;
}

/**
* Checks if propTypes declarations are sorted
* @param {Array} declarations The array of AST nodes being checked.
Expand Down Expand Up @@ -143,62 +162,42 @@ module.exports = {
}, declarations[0]);
}

function checkNode(node) {
switch (node && node.type) {
case 'ObjectExpression':
checkSorted(node.properties);
break;
case 'Identifier':
const propTypesObject = findVariableByName(node.name);
if (propTypesObject && propTypesObject.properties) {
checkSorted(propTypesObject.properties);
}
break;
case 'CallExpression':
const innerNode = node.arguments && node.arguments[0];
if (propWrapperFunctions.has(node.callee.name) && innerNode) {
checkNode(innerNode);
}
break;
default:
break;
}
}

return {
ClassProperty: function(node) {
if (!isPropTypesDeclaration(node)) {
return;
}
switch (node.value && node.value.type) {
case 'ObjectExpression':
checkSorted(node.value.properties);
break;
case 'CallExpression':
if (
propWrapperFunctions.has(node.value.callee.name) &&
node.value.arguments && node.value.arguments[0]
) {
checkSorted(node.value.arguments[0].properties);
}
break;
default:
break;
}
checkNode(node.value);
},

MemberExpression: function(node) {
if (!isPropTypesDeclaration(node.property)) {
return;
}
const right = node.parent.right;
let declarations;
switch (right && right.type) {
case 'CallExpression':
if (
propWrapperFunctions.has(right.callee.name) &&
right.arguments && right.arguments[0]
) {
declarations = right.arguments[0].properties;
}
break;
case 'ObjectExpression':
declarations = right.properties;
break;
case 'Identifier':
const variable = variableUtil.variablesInScope(context).find(item => item.name === right.name);
if (
!variable || !variable.defs[0] ||
!variable.defs[0].node.init || !variable.defs[0].node.init.properties
) {
break;
}
declarations = variable.defs[0].node.init.properties;
break;
default:
break;
}
if (declarations) {
checkSorted(declarations);
}

checkNode(node.parent.right);
},

ObjectExpression: function(node) {
Expand Down
36 changes: 36 additions & 0 deletions tests/lib/rules/sort-prop-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,42 @@ ruleTester.run('sort-prop-types', rule, {
column: 5,
type: 'Property'
}]
}, {
code: [
'const First = (props) => <div />;',
'const propTypes = {',
' z: PropTypes.string,',
' a: PropTypes.any,',
'};',
'First.propTypes = forbidExtraProps(propTypes);'
].join('\n'),
settings: {
propWrapperFunctions: ['forbidExtraProps']
},
errors: [{
message: ERROR_MESSAGE,
line: 4,
column: 5,
type: 'Property'
}]
}, {
code: [
'const First = (props) => <div />;',
'const propTypes = {',
' z: PropTypes.string,',
' a: PropTypes.any,',
'};',
'First.propTypes = propTypes;'
].join('\n'),
settings: {
propWrapperFunctions: ['forbidExtraProps']
},
errors: [{
message: ERROR_MESSAGE,
line: 4,
column: 5,
type: 'Property'
}]
}, {
code: [
'var First = createReactClass({',
Expand Down

0 comments on commit c98ce02

Please sign in to comment.