no-string-refs.js 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. /**
  2. * @fileoverview Prevent string definitions for references and prevent referencing this.refs
  3. * @author Tom Hastjarjanto
  4. */
  5. 'use strict';
  6. const Components = require('../util/Components');
  7. const docsUrl = require('../util/docsUrl');
  8. // ------------------------------------------------------------------------------
  9. // Rule Definition
  10. // ------------------------------------------------------------------------------
  11. module.exports = {
  12. meta: {
  13. docs: {
  14. description: 'Prevent string definitions for references and prevent referencing this.refs',
  15. category: 'Best Practices',
  16. recommended: true,
  17. url: docsUrl('no-string-refs')
  18. },
  19. messages: {
  20. thisRefsDeprecated: 'Using this.refs is deprecated.',
  21. stringInRefDeprecated: 'Using string literals in ref attributes is deprecated.'
  22. },
  23. schema: [{
  24. type: 'object',
  25. properties: {
  26. noTemplateLiterals: {
  27. type: 'boolean'
  28. }
  29. },
  30. additionalProperties: false
  31. }]
  32. },
  33. create: Components.detect((context, components, utils) => {
  34. const detectTemplateLiterals = context.options[0] ? context.options[0].noTemplateLiterals : false;
  35. /**
  36. * Checks if we are using refs
  37. * @param {ASTNode} node The AST node being checked.
  38. * @returns {Boolean} True if we are using refs, false if not.
  39. */
  40. function isRefsUsage(node) {
  41. return Boolean(
  42. (
  43. utils.getParentES6Component()
  44. || utils.getParentES5Component()
  45. )
  46. && node.object.type === 'ThisExpression'
  47. && node.property.name === 'refs'
  48. );
  49. }
  50. /**
  51. * Checks if we are using a ref attribute
  52. * @param {ASTNode} node The AST node being checked.
  53. * @returns {Boolean} True if we are using a ref attribute, false if not.
  54. */
  55. function isRefAttribute(node) {
  56. return Boolean(
  57. node.type === 'JSXAttribute'
  58. && node.name
  59. && node.name.name === 'ref'
  60. );
  61. }
  62. /**
  63. * Checks if a node contains a string value
  64. * @param {ASTNode} node The AST node being checked.
  65. * @returns {Boolean} True if the node contains a string value, false if not.
  66. */
  67. function containsStringLiteral(node) {
  68. return Boolean(
  69. node.value
  70. && node.value.type === 'Literal'
  71. && typeof node.value.value === 'string'
  72. );
  73. }
  74. /**
  75. * Checks if a node contains a string value within a jsx expression
  76. * @param {ASTNode} node The AST node being checked.
  77. * @returns {Boolean} True if the node contains a string value within a jsx expression, false if not.
  78. */
  79. function containsStringExpressionContainer(node) {
  80. return Boolean(
  81. node.value
  82. && node.value.type === 'JSXExpressionContainer'
  83. && node.value.expression
  84. && ((node.value.expression.type === 'Literal' && typeof node.value.expression.value === 'string')
  85. || (node.value.expression.type === 'TemplateLiteral' && detectTemplateLiterals))
  86. );
  87. }
  88. return {
  89. MemberExpression(node) {
  90. if (isRefsUsage(node)) {
  91. context.report({
  92. node,
  93. messageId: 'thisRefsDeprecated'
  94. });
  95. }
  96. },
  97. JSXAttribute(node) {
  98. if (
  99. isRefAttribute(node)
  100. && (containsStringLiteral(node) || containsStringExpressionContainer(node))
  101. ) {
  102. context.report({
  103. node,
  104. messageId: 'stringInRefDeprecated'
  105. });
  106. }
  107. }
  108. };
  109. })
  110. };