no-return-wrap.js 2.3 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. /**
  2. * Rule: no-return-wrap function
  3. * Prevents unnecessary wrapping of results in Promise.resolve
  4. * or Promise.reject as the Promise will do that for us
  5. */
  6. 'use strict'
  7. const getDocsUrl = require('./lib/get-docs-url')
  8. const isPromise = require('./lib/is-promise')
  9. function isInPromise(context) {
  10. let functionNode = context
  11. .getAncestors()
  12. .filter((node) => {
  13. return (
  14. node.type === 'ArrowFunctionExpression' ||
  15. node.type === 'FunctionExpression'
  16. )
  17. })
  18. .reverse()[0]
  19. while (
  20. functionNode &&
  21. functionNode.parent &&
  22. functionNode.parent.type === 'MemberExpression' &&
  23. functionNode.parent.object === functionNode &&
  24. functionNode.parent.property.type === 'Identifier' &&
  25. functionNode.parent.property.name === 'bind' &&
  26. functionNode.parent.parent &&
  27. functionNode.parent.parent.type === 'CallExpression' &&
  28. functionNode.parent.parent.callee === functionNode.parent
  29. ) {
  30. functionNode = functionNode.parent.parent
  31. }
  32. return functionNode && functionNode.parent && isPromise(functionNode.parent)
  33. }
  34. module.exports = {
  35. meta: {
  36. type: 'suggestion',
  37. docs: {
  38. url: getDocsUrl('no-return-wrap'),
  39. },
  40. messages: {
  41. resolve: 'Avoid wrapping return values in Promise.resolve',
  42. reject: 'Expected throw instead of Promise.reject',
  43. },
  44. },
  45. create(context) {
  46. const options = context.options[0] || {}
  47. const allowReject = options.allowReject
  48. /**
  49. * Checks a call expression, reporting if necessary.
  50. * @param callExpression The call expression.
  51. * @param node The node to report.
  52. */
  53. function checkCallExpression({ callee }, node) {
  54. if (
  55. isInPromise(context) &&
  56. callee.type === 'MemberExpression' &&
  57. callee.object.name === 'Promise'
  58. ) {
  59. if (callee.property.name === 'resolve') {
  60. context.report({ node, messageId: 'resolve' })
  61. } else if (!allowReject && callee.property.name === 'reject') {
  62. context.report({ node, messageId: 'reject' })
  63. }
  64. }
  65. }
  66. return {
  67. ReturnStatement(node) {
  68. if (node.argument && node.argument.type === 'CallExpression') {
  69. checkCallExpression(node.argument, node)
  70. }
  71. },
  72. 'ArrowFunctionExpression > CallExpression'(node) {
  73. checkCallExpression(node, node)
  74. },
  75. }
  76. },
  77. }