diff --git a/lib/util/stylesheet.js b/lib/util/stylesheet.js index 0b8a6ef..0edc46e 100644 --- a/lib/util/stylesheet.js +++ b/lib/util/stylesheet.js @@ -101,9 +101,16 @@ const astHelpers = { node && node.type === 'CallExpression' && node.callee && - node.callee.object && - node.callee.object.name && - objectNames.includes(node.callee.object.name) + node.callee.object && (( + node.callee.object.type === 'Identifier' && + node.callee.object.name && + objectNames.includes(node.callee.object.name) + ) || ( + node.callee.object.type === 'MemberExpression' && + node.callee.object.object.type === 'Identifier' && + objectNames.includes(node.callee.object.property.name) && + astHelpers.getImportSource(node.callee.object.object) === 'react-native' + )) ); }, @@ -463,6 +470,50 @@ const astHelpers = { } }, + getRoot: function (node) { + let currentNode = node; + while (currentNode && currentNode.parent) { + currentNode = currentNode.parent; + } + + return currentNode; + }, + + getImportVariable: function (node) { + if (node && node.type === 'ImportDeclaration') { + for (let i = 0; i < node.specifiers.length; i += 1) { + const specifier = node.specifiers[i]; + if ( + specifier && ( + specifier.type === 'ImportDefaultSpecifier' || + specifier.type === 'ImportNamespaceSpecifier' + ) && + specifier.local && + specifier.local.type === 'Identifier' + ) { + return specifier.local.name; + } + } + } + }, + + getImportSource: function (node) { + if (node && node.type === 'Identifier' && node.name) { + const rootNode = astHelpers.getRoot(node); + if (rootNode && rootNode.body) { + for (let i = 0; i < rootNode.body.length; i += 1) { + const bodyNode = rootNode.body[i]; + if ( + astHelpers.getImportVariable(bodyNode) === node.name && + bodyNode.source && bodyNode.source.type === 'Literal' + ) { + return bodyNode.source.value; + } + } + } + } + }, + getPotentialStyleReferenceFromMemberExpression: function (node) { if ( node && diff --git a/tests/lib/rules/no-unused-styles.js b/tests/lib/rules/no-unused-styles.js index c99d3e6..ee6d4f7 100644 --- a/tests/lib/rules/no-unused-styles.js +++ b/tests/lib/rules/no-unused-styles.js @@ -215,6 +215,31 @@ const tests = { } }); `, + }, { + code: ` + import RN from 'react-native'; + const styles = RN.StyleSheet.create({ + name: {} + }); + const Hello = React.createClass({ + render: function() { + return Hello {this.props.name}; + } + }); + `, + }, { + code: ` + import React from 'react'; + import RN from 'react-native'; + const styles = RN.StyleSheet.create({ + name: {} + }); + const Hello = React.createClass({ + render: function() { + return Hello {this.props.name}; + } + }); + `, }], invalid: [{ @@ -276,6 +301,22 @@ const tests = { errors: [{ message: 'Unused style detected: styles.bar', }], + }, { + code: ` + import RN from 'react-native'; + const styles = RN.StyleSheet.create({ + name: {} + }); + const Hello = React.createClass({ + render: function() { + return Hello {this.props.name}; + } + }); + `, + errors: [{ + message: 'Unused style detected: styles.name', + }], + }], };