|
5 | 5 |
|
6 | 6 | 'use strict';
|
7 | 7 |
|
8 |
| -const utils = require('../utils'); |
| 8 | +// ------------------------------------------------------------------------------ |
| 9 | +// Requirements |
| 10 | +// ------------------------------------------------------------------------------ |
9 | 11 |
|
| 12 | +// const utils = require('../utils'); |
| 13 | +const astUtils = require('../ast-utils.js'); |
10 | 14 | // ------------------------------------------------------------------------------
|
11 | 15 | // Rule Definition
|
12 | 16 | // ------------------------------------------------------------------------------
|
13 | 17 |
|
14 | 18 | module.exports = {
|
15 | 19 | meta: {
|
16 | 20 | docs: {
|
17 |
| - description: 'enforces fixer function always return a value', |
18 |
| - category: 'Rules', |
| 21 | + description: 'Expected fixer function to always return a value.', |
| 22 | + category: 'Possible Errors', |
19 | 23 | recommended: false,
|
20 | 24 | },
|
21 |
| - fixable: null, // or "code" or "whitespace" |
22 |
| - schema: [], |
| 25 | + fixable: null, |
23 | 26 | },
|
24 | 27 |
|
25 | 28 | create (context) {
|
26 |
| - // ---------------------------------------------------------------------- |
27 |
| - // Public |
28 |
| - // ---------------------------------------------------------------------- |
29 |
| - const message = 'fixer function is expected to return a value.'; |
30 |
| - const sourceCode = context.getSourceCode(); |
| 29 | + const message = 'Expected fixer function to always return a value.'; |
| 30 | + let funcInfo = { |
| 31 | + upper: null, |
| 32 | + codePath: null, |
| 33 | + hasReturn: false, |
| 34 | + shouldCheck: false, |
| 35 | + node: null, |
| 36 | + }; |
| 37 | + |
| 38 | + /** |
| 39 | + * Checks whether or not the last code path segment is reachable. |
| 40 | + * Then reports this function if the segment is reachable. |
| 41 | + * |
| 42 | + * If the last code path segment is reachable, there are paths which are not |
| 43 | + * returned or thrown. |
| 44 | + * |
| 45 | + * @param {ASTNode} node - A node to check. |
| 46 | + * @returns {void} |
| 47 | + */ |
| 48 | + function checkLastSegment (node) { |
| 49 | + if (funcInfo.shouldCheck && funcInfo.codePath.currentSegments.some(segment => segment.reachable)) { |
| 50 | + context.report({ |
| 51 | + node, |
| 52 | + loc: (node.id || node).loc.start, |
| 53 | + message, |
| 54 | + }); |
| 55 | + } |
| 56 | + } |
31 | 57 |
|
32 | 58 | return {
|
33 |
| - Program (ast) { |
34 |
| - utils.getTestInfo(context, ast).forEach(testRun => { |
35 |
| - [testRun.valid, testRun.invalid].forEach(tests => { |
36 |
| - const cache = Object.create(null); |
37 |
| - // to avoid tests being null |
38 |
| - (tests || []).forEach(test => { |
39 |
| - const testCode = sourceCode.getText(test); |
40 |
| - if (cache[testCode]) { |
41 |
| - context.report({ |
42 |
| - node: test, |
43 |
| - message, |
44 |
| - }); |
45 |
| - } else { |
46 |
| - cache[testCode] = true; |
47 |
| - } |
| 59 | + |
| 60 | + // Stacks this function's information. |
| 61 | + onCodePathStart (codePath, node) { |
| 62 | + const parent = node.parent; |
| 63 | + |
| 64 | + funcInfo = { |
| 65 | + upper: funcInfo, |
| 66 | + codePath, |
| 67 | + hasReturn: false, |
| 68 | + shouldCheck: |
| 69 | + node.type === 'FunctionExpression' && |
| 70 | + node.body.type === 'BlockStatement' && |
| 71 | + // check if it is naming fix |
| 72 | + astUtils.getStaticPropertyName(parent) === 'fix', |
| 73 | + node, |
| 74 | + }; |
| 75 | + }, |
| 76 | + |
| 77 | + // Pops this function's information. |
| 78 | + onCodePathEnd () { |
| 79 | + funcInfo = funcInfo.upper; |
| 80 | + }, |
| 81 | + |
| 82 | + // Checks the return statement is valid. |
| 83 | + ReturnStatement (node) { |
| 84 | + if (funcInfo.shouldCheck) { |
| 85 | + funcInfo.hasReturn = true; |
| 86 | + |
| 87 | + if (!node.argument) { |
| 88 | + context.report({ |
| 89 | + node, |
| 90 | + message, |
48 | 91 | });
|
49 |
| - }); |
50 |
| - }); |
| 92 | + } |
| 93 | + } |
51 | 94 | },
|
| 95 | + |
| 96 | + // Reports a given function if the last path is reachable. |
| 97 | + 'FunctionExpression:exit': checkLastSegment, |
52 | 98 | };
|
53 | 99 | },
|
54 | 100 | };
|
0 commit comments