no-string-refs.js 3.4 KB

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