variable.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. /**
  2. * @fileoverview Utility functions for React components detection
  3. * @author Yannick Croissant
  4. */
  5. 'use strict';
  6. const getScope = require('./eslint').getScope;
  7. /**
  8. * Search a particular variable in a list
  9. * @param {Array} variables The variables list.
  10. * @param {string} name The name of the variable to search.
  11. * @returns {boolean} True if the variable was found, false if not.
  12. */
  13. function findVariable(variables, name) {
  14. return variables.some((variable) => variable.name === name);
  15. }
  16. /**
  17. * Find and return a particular variable in a list
  18. * @param {Array} variables The variables list.
  19. * @param {string} name The name of the variable to search.
  20. * @returns {Object} Variable if the variable was found, null if not.
  21. */
  22. function getVariable(variables, name) {
  23. return variables.find((variable) => variable.name === name);
  24. }
  25. /**
  26. * Searches for a variable in the given scope.
  27. *
  28. * @param {Object} context The current rule context.
  29. * @param {ASTNode} node The node to start looking from.
  30. * @param {string} name The name of the variable to search.
  31. * @returns {Object | undefined} Variable if the variable was found, undefined if not.
  32. */
  33. function getVariableFromContext(context, node, name) {
  34. let scope = getScope(context, node);
  35. while (scope) {
  36. let variable = getVariable(scope.variables, name);
  37. if (!variable && scope.childScopes.length) {
  38. variable = getVariable(scope.childScopes[0].variables, name);
  39. if (!variable && scope.childScopes[0].childScopes.length) {
  40. variable = getVariable(scope.childScopes[0].childScopes[0].variables, name);
  41. }
  42. }
  43. if (variable) {
  44. return variable;
  45. }
  46. scope = scope.upper;
  47. }
  48. return undefined;
  49. }
  50. /**
  51. * Find a variable by name in the current scope.
  52. * @param {Object} context The current rule context.
  53. * @param {ASTNode} node The node to check. Must be an Identifier node.
  54. * @param {string} name Name of the variable to look for.
  55. * @returns {ASTNode|null} Return null if the variable could not be found, ASTNode otherwise.
  56. */
  57. function findVariableByName(context, node, name) {
  58. const variable = getVariableFromContext(context, node, name);
  59. if (!variable || !variable.defs[0] || !variable.defs[0].node) {
  60. return null;
  61. }
  62. if (variable.defs[0].node.type === 'TypeAlias') {
  63. return variable.defs[0].node.right;
  64. }
  65. if (variable.defs[0].type === 'ImportBinding') {
  66. return variable.defs[0].node;
  67. }
  68. return variable.defs[0].node.init;
  69. }
  70. /**
  71. * Returns the latest definition of the variable.
  72. * @param {Object} variable
  73. * @returns {Object | undefined} The latest variable definition or undefined.
  74. */
  75. function getLatestVariableDefinition(variable) {
  76. return variable.defs[variable.defs.length - 1];
  77. }
  78. module.exports = {
  79. findVariable,
  80. findVariableByName,
  81. getVariable,
  82. getVariableFromContext,
  83. getLatestVariableDefinition,
  84. };