prefer-await-to-callbacks.js 1.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263
  1. 'use strict'
  2. const getDocsUrl = require('./lib/get-docs-url')
  3. const errorMessage = 'Avoid callbacks. Prefer Async/Await.'
  4. module.exports = {
  5. meta: {
  6. docs: {
  7. url: getDocsUrl('prefer-await-to-callbacks')
  8. }
  9. },
  10. create(context) {
  11. function checkLastParamsForCallback(node) {
  12. const lastParam = node.params[node.params.length - 1] || {}
  13. if (lastParam.name === 'callback' || lastParam.name === 'cb') {
  14. context.report({ node: lastParam, message: errorMessage })
  15. }
  16. }
  17. function isInsideYieldOrAwait() {
  18. return context.getAncestors().some(parent => {
  19. return (
  20. parent.type === 'AwaitExpression' || parent.type === 'YieldExpression'
  21. )
  22. })
  23. }
  24. return {
  25. CallExpression(node) {
  26. // Callbacks aren't allowed.
  27. if (node.callee.name === 'cb' || node.callee.name === 'callback') {
  28. context.report({ node, message: errorMessage })
  29. return
  30. }
  31. // Then-ables aren't allowed either.
  32. const args = node.arguments
  33. const lastArgIndex = args.length - 1
  34. const arg = lastArgIndex > -1 && node.arguments[lastArgIndex]
  35. if (
  36. (arg && arg.type === 'FunctionExpression') ||
  37. arg.type === 'ArrowFunctionExpression'
  38. ) {
  39. // Ignore event listener callbacks.
  40. if (
  41. node.callee.property &&
  42. (node.callee.property.name === 'on' ||
  43. node.callee.property.name === 'once')
  44. ) {
  45. return
  46. }
  47. if (arg.params && arg.params[0] && arg.params[0].name === 'err') {
  48. if (!isInsideYieldOrAwait()) {
  49. context.report({ node: arg, message: errorMessage })
  50. }
  51. }
  52. }
  53. },
  54. FunctionDeclaration: checkLastParamsForCallback,
  55. FunctionExpression: checkLastParamsForCallback,
  56. ArrowFunctionExpression: checkLastParamsForCallback
  57. }
  58. }
  59. }