no-await-expression-member.js 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. 'use strict';
  2. const {
  3. removeParentheses,
  4. removeMemberExpressionProperty,
  5. } = require('./fix/index.js');
  6. const {isLiteral} = require('./ast/index.js');
  7. const MESSAGE_ID = 'no-await-expression-member';
  8. const messages = {
  9. [MESSAGE_ID]: 'Do not access a member directly from an await expression.',
  10. };
  11. /** @param {import('eslint').Rule.RuleContext} context */
  12. const create = context => {
  13. const sourceCode = context.getSourceCode();
  14. return {
  15. 'MemberExpression[object.type="AwaitExpression"]'(memberExpression) {
  16. const {property} = memberExpression;
  17. const problem = {
  18. node: property,
  19. messageId: MESSAGE_ID,
  20. };
  21. // `const foo = (await bar)[0]`
  22. if (
  23. memberExpression.computed
  24. && !memberExpression.optional
  25. && (isLiteral(property, 0) || isLiteral(property, 1))
  26. && memberExpression.parent.type === 'VariableDeclarator'
  27. && memberExpression.parent.init === memberExpression
  28. && memberExpression.parent.id.type === 'Identifier'
  29. ) {
  30. problem.fix = function * (fixer) {
  31. const variable = memberExpression.parent.id;
  32. yield fixer.insertTextBefore(variable, property.value === 0 ? '[' : '[, ');
  33. yield fixer.insertTextAfter(variable, ']');
  34. yield removeMemberExpressionProperty(fixer, memberExpression, sourceCode);
  35. yield * removeParentheses(memberExpression.object, fixer, sourceCode);
  36. };
  37. return problem;
  38. }
  39. // `const foo = (await bar).foo`
  40. if (
  41. !memberExpression.computed
  42. && !memberExpression.optional
  43. && property.type === 'Identifier'
  44. && memberExpression.parent.type === 'VariableDeclarator'
  45. && memberExpression.parent.init === memberExpression
  46. && memberExpression.parent.id.type === 'Identifier'
  47. && memberExpression.parent.id.name === property.name
  48. ) {
  49. problem.fix = function * (fixer) {
  50. const variable = memberExpression.parent.id;
  51. yield fixer.insertTextBefore(variable, '{');
  52. yield fixer.insertTextAfter(variable, '}');
  53. yield removeMemberExpressionProperty(fixer, memberExpression, sourceCode);
  54. yield * removeParentheses(memberExpression.object, fixer, sourceCode);
  55. };
  56. return problem;
  57. }
  58. return problem;
  59. },
  60. };
  61. };
  62. /** @type {import('eslint').Rule.RuleModule} */
  63. module.exports = {
  64. create,
  65. meta: {
  66. type: 'suggestion',
  67. docs: {
  68. description: 'Disallow member access from await expression.',
  69. },
  70. fixable: 'code',
  71. messages,
  72. },
  73. };