UNPKG

2.44 kBJavaScriptView Raw
1/**
2 * Rule: catch-or-return
3 * Ensures that promises either include a catch() handler
4 * or are returned (to be handled upstream)
5 */
6
7'use strict'
8
9const getDocsUrl = require('./lib/get-docs-url')
10const isPromise = require('./lib/is-promise')
11
12module.exports = {
13 meta: {
14 docs: {
15 url: getDocsUrl('catch-or-return')
16 },
17 messages: {
18 terminationMethod: 'Expected {{ terminationMethod }}() or return'
19 }
20 },
21 create(context) {
22 const options = context.options[0] || {}
23 const allowThen = options.allowThen
24 const allowFinally = options.allowFinally
25 let terminationMethod = options.terminationMethod || 'catch'
26
27 if (typeof terminationMethod === 'string') {
28 terminationMethod = [terminationMethod]
29 }
30
31 function isAllowedPromiseTermination(expression) {
32 // somePromise.then(a, b)
33 if (
34 allowThen &&
35 expression.type === 'CallExpression' &&
36 expression.callee.type === 'MemberExpression' &&
37 expression.callee.property.name === 'then' &&
38 expression.arguments.length === 2
39 ) {
40 return true
41 }
42
43 // somePromise.catch().finally(fn)
44 if (
45 allowFinally &&
46 expression.type === 'CallExpression' &&
47 expression.callee.type === 'MemberExpression' &&
48 expression.callee.property.name === 'finally' &&
49 isPromise(expression.callee.object) &&
50 isAllowedPromiseTermination(expression.callee.object)
51 ) {
52 return true
53 }
54
55 // somePromise.catch()
56 if (
57 expression.type === 'CallExpression' &&
58 expression.callee.type === 'MemberExpression' &&
59 terminationMethod.indexOf(expression.callee.property.name) !== -1
60 ) {
61 return true
62 }
63
64 // somePromise['catch']()
65 if (
66 expression.type === 'CallExpression' &&
67 expression.callee.type === 'MemberExpression' &&
68 expression.callee.property.type === 'Literal' &&
69 expression.callee.property.value === 'catch'
70 ) {
71 return true
72 }
73
74 return false
75 }
76
77 return {
78 ExpressionStatement(node) {
79 if (!isPromise(node.expression)) {
80 return
81 }
82
83 if (isAllowedPromiseTermination(node.expression)) {
84 return
85 }
86
87 context.report({
88 node,
89 messageId: 'terminationMethod',
90 data: { terminationMethod }
91 })
92 }
93 }
94 }
95}