no-await-expression-member.js 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485
  1. 'use strict';
  2. const {
  3. removeParentheses,
  4. removeMemberExpressionProperty,
  5. } = require('./fix/index.js');
  6. const MESSAGE_ID = 'no-await-expression-member';
  7. const messages = {
  8. [MESSAGE_ID]: 'Do not access a member directly from an await expression.',
  9. };
  10. /** @param {import('eslint').Rule.RuleContext} context */
  11. const create = context => {
  12. const sourceCode = context.getSourceCode();
  13. return {
  14. 'MemberExpression[object.type="AwaitExpression"]'(memberExpression) {
  15. const {property} = memberExpression;
  16. const problem = {
  17. node: property,
  18. messageId: MESSAGE_ID,
  19. };
  20. // `const foo = (await bar)[0]`
  21. if (
  22. memberExpression.computed
  23. && !memberExpression.optional
  24. && property.type === 'Literal'
  25. && (property.value === 0 || property.value === 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: 'Forbid member access from await expression.',
  69. },
  70. fixable: 'code',
  71. schema: [],
  72. messages,
  73. },
  74. };