no-callback-literal.js 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. /**
  2. * Ensures that the callback pattern is followed properly
  3. * with an Error object (or undefined or null) in the first position.
  4. */
  5. 'use strict'
  6. // ------------------------------------------------------------------------------
  7. // Helpers
  8. // ------------------------------------------------------------------------------
  9. /**
  10. * Determine if a node has a possiblity to be an Error object
  11. * @param {ASTNode} node ASTNode to check
  12. * @returns {boolean} True if there is a chance it contains an Error obj
  13. */
  14. function couldBeError (node) {
  15. let exprs
  16. switch (node.type) {
  17. case 'Identifier':
  18. case 'CallExpression':
  19. case 'NewExpression':
  20. case 'MemberExpression':
  21. case 'TaggedTemplateExpression':
  22. case 'YieldExpression':
  23. return true // possibly an error object.
  24. case 'AssignmentExpression':
  25. return couldBeError(node.right)
  26. case 'SequenceExpression':
  27. exprs = node.expressions
  28. return exprs.length !== 0 && couldBeError(exprs[exprs.length - 1])
  29. case 'LogicalExpression':
  30. return couldBeError(node.left) || couldBeError(node.right)
  31. case 'ConditionalExpression':
  32. return couldBeError(node.consequent) || couldBeError(node.alternate)
  33. default:
  34. return node.value === null
  35. }
  36. }
  37. // ------------------------------------------------------------------------------
  38. // Rule Definition
  39. // ------------------------------------------------------------------------------
  40. module.exports = {
  41. meta: {
  42. type: 'suggestion',
  43. docs: {
  44. url: 'https://github.com/standard/eslint-plugin-standard#rules-explanations'
  45. }
  46. },
  47. create: function (context) {
  48. const callbackNames = context.options[0] || ['callback', 'cb']
  49. function isCallback (name) {
  50. return callbackNames.indexOf(name) > -1
  51. }
  52. return {
  53. CallExpression: function (node) {
  54. const errorArg = node.arguments[0]
  55. const calleeName = node.callee.name
  56. if (errorArg && !couldBeError(errorArg) && isCallback(calleeName)) {
  57. context.report(node, 'Unexpected literal in error position of callback.')
  58. }
  59. }
  60. }
  61. }
  62. }