/** * @fileoverview Prevent string definitions for references and prevent referencing this.refs * @author Tom Hastjarjanto */ 'use strict'; const Components = require('../util/Components'); const docsUrl = require('../util/docsUrl'); // ------------------------------------------------------------------------------ // Rule Definition // ------------------------------------------------------------------------------ module.exports = { meta: { docs: { description: 'Prevent string definitions for references and prevent referencing this.refs', category: 'Best Practices', recommended: true, url: docsUrl('no-string-refs') }, messages: { thisRefsDeprecated: 'Using this.refs is deprecated.', stringInRefDeprecated: 'Using string literals in ref attributes is deprecated.' }, schema: [{ type: 'object', properties: { noTemplateLiterals: { type: 'boolean' } }, additionalProperties: false }] }, create: Components.detect((context, components, utils) => { const detectTemplateLiterals = context.options[0] ? context.options[0].noTemplateLiterals : false; /** * Checks if we are using refs * @param {ASTNode} node The AST node being checked. * @returns {Boolean} True if we are using refs, false if not. */ function isRefsUsage(node) { return Boolean( ( utils.getParentES6Component() || utils.getParentES5Component() ) && node.object.type === 'ThisExpression' && node.property.name === 'refs' ); } /** * Checks if we are using a ref attribute * @param {ASTNode} node The AST node being checked. * @returns {Boolean} True if we are using a ref attribute, false if not. */ function isRefAttribute(node) { return Boolean( node.type === 'JSXAttribute' && node.name && node.name.name === 'ref' ); } /** * Checks if a node contains a string value * @param {ASTNode} node The AST node being checked. * @returns {Boolean} True if the node contains a string value, false if not. */ function containsStringLiteral(node) { return Boolean( node.value && node.value.type === 'Literal' && typeof node.value.value === 'string' ); } /** * Checks if a node contains a string value within a jsx expression * @param {ASTNode} node The AST node being checked. * @returns {Boolean} True if the node contains a string value within a jsx expression, false if not. */ function containsStringExpressionContainer(node) { return Boolean( node.value && node.value.type === 'JSXExpressionContainer' && node.value.expression && ((node.value.expression.type === 'Literal' && typeof node.value.expression.value === 'string') || (node.value.expression.type === 'TemplateLiteral' && detectTemplateLiterals)) ); } return { MemberExpression(node) { if (isRefsUsage(node)) { context.report({ node, messageId: 'thisRefsDeprecated' }); } }, JSXAttribute(node) { if ( isRefAttribute(node) && (containsStringLiteral(node) || containsStringExpressionContainer(node)) ) { context.report({ node, messageId: 'stringInRefDeprecated' }); } } }; }) };