1 | /**
|
2 | * @fileoverview enforce the location of arrow function bodies
|
3 | * @author Sharmila Jesupaul
|
4 | */
|
5 | ;
|
6 |
|
7 | //------------------------------------------------------------------------------
|
8 | // Rule Definition
|
9 | //------------------------------------------------------------------------------
|
10 | module.exports = {
|
11 | meta: {
|
12 | docs: {
|
13 | description: "enforce the location of arrow function bodies",
|
14 | category: "Stylistic Issues",
|
15 | recommended: false,
|
16 | url: "https://eslint.org/docs/rules/implicit-arrow-linebreak"
|
17 | },
|
18 | fixable: "whitespace",
|
19 | schema: [
|
20 | {
|
21 | enum: ["beside", "below"]
|
22 | }
|
23 | ]
|
24 | },
|
25 |
|
26 | create(context) {
|
27 | const sourceCode = context.getSourceCode();
|
28 |
|
29 | //----------------------------------------------------------------------
|
30 | // Helpers
|
31 | //----------------------------------------------------------------------
|
32 | /**
|
33 | * Gets the applicable preference for a particular keyword
|
34 | * @returns {string} The applicable option for the keyword, e.g. 'beside'
|
35 | */
|
36 | function getOption() {
|
37 | return context.options[0] || "beside";
|
38 | }
|
39 |
|
40 | /**
|
41 | * Validates the location of an arrow function body
|
42 | * @param {ASTNode} node The arrow function body
|
43 | * @param {string} keywordName The applicable keyword name for the arrow function body
|
44 | * @returns {void}
|
45 | */
|
46 | function validateExpression(node) {
|
47 | const option = getOption();
|
48 |
|
49 | let tokenBefore = sourceCode.getTokenBefore(node.body);
|
50 | const hasParens = tokenBefore.value === "(";
|
51 |
|
52 | if (node.type === "BlockStatement") {
|
53 | return;
|
54 | }
|
55 |
|
56 | let fixerTarget = node.body;
|
57 |
|
58 | if (hasParens) {
|
59 |
|
60 | // Gets the first token before the function body that is not an open paren
|
61 | tokenBefore = sourceCode.getTokenBefore(node.body, token => token.value !== "(");
|
62 | fixerTarget = sourceCode.getTokenAfter(tokenBefore);
|
63 | }
|
64 |
|
65 | if (tokenBefore.loc.end.line === fixerTarget.loc.start.line && option === "below") {
|
66 | context.report({
|
67 | node: fixerTarget,
|
68 | message: "Expected a linebreak before this expression.",
|
69 | fix: fixer => fixer.insertTextBefore(fixerTarget, "\n")
|
70 | });
|
71 | } else if (tokenBefore.loc.end.line !== fixerTarget.loc.start.line && option === "beside") {
|
72 | context.report({
|
73 | node: fixerTarget,
|
74 | message: "Expected no linebreak before this expression.",
|
75 | fix: fixer => fixer.replaceTextRange([tokenBefore.range[1], fixerTarget.range[0]], " ")
|
76 | });
|
77 | }
|
78 | }
|
79 |
|
80 | //----------------------------------------------------------------------
|
81 | // Public
|
82 | //----------------------------------------------------------------------
|
83 | return {
|
84 | ArrowFunctionExpression: node => validateExpression(node)
|
85 | };
|
86 | }
|
87 | };
|