• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Rule to define spacing before/after arrow function's arrow.
3 * @author Jxck
4 */
5"use strict";
6
7//------------------------------------------------------------------------------
8// Requirements
9//------------------------------------------------------------------------------
10
11const astUtils = require("./utils/ast-utils");
12
13//------------------------------------------------------------------------------
14// Rule Definition
15//------------------------------------------------------------------------------
16
17module.exports = {
18    meta: {
19        type: "layout",
20
21        docs: {
22            description: "enforce consistent spacing before and after the arrow in arrow functions",
23            category: "ECMAScript 6",
24            recommended: false,
25            url: "https://eslint.org/docs/rules/arrow-spacing"
26        },
27
28        fixable: "whitespace",
29
30        schema: [
31            {
32                type: "object",
33                properties: {
34                    before: {
35                        type: "boolean",
36                        default: true
37                    },
38                    after: {
39                        type: "boolean",
40                        default: true
41                    }
42                },
43                additionalProperties: false
44            }
45        ],
46
47        messages: {
48            expectedBefore: "Missing space before =>.",
49            unexpectedBefore: "Unexpected space before =>.",
50
51            expectedAfter: "Missing space after =>.",
52            unexpectedAfter: "Unexpected space after =>."
53        }
54    },
55
56    create(context) {
57
58        // merge rules with default
59        const rule = Object.assign({}, context.options[0]);
60
61        rule.before = rule.before !== false;
62        rule.after = rule.after !== false;
63
64        const sourceCode = context.getSourceCode();
65
66        /**
67         * Get tokens of arrow(`=>`) and before/after arrow.
68         * @param {ASTNode} node The arrow function node.
69         * @returns {Object} Tokens of arrow and before/after arrow.
70         */
71        function getTokens(node) {
72            const arrow = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken);
73
74            return {
75                before: sourceCode.getTokenBefore(arrow),
76                arrow,
77                after: sourceCode.getTokenAfter(arrow)
78            };
79        }
80
81        /**
82         * Count spaces before/after arrow(`=>`) token.
83         * @param {Object} tokens Tokens before/after arrow.
84         * @returns {Object} count of space before/after arrow.
85         */
86        function countSpaces(tokens) {
87            const before = tokens.arrow.range[0] - tokens.before.range[1];
88            const after = tokens.after.range[0] - tokens.arrow.range[1];
89
90            return { before, after };
91        }
92
93        /**
94         * Determines whether space(s) before after arrow(`=>`) is satisfy rule.
95         * if before/after value is `true`, there should be space(s).
96         * if before/after value is `false`, there should be no space.
97         * @param {ASTNode} node The arrow function node.
98         * @returns {void}
99         */
100        function spaces(node) {
101            const tokens = getTokens(node);
102            const countSpace = countSpaces(tokens);
103
104            if (rule.before) {
105
106                // should be space(s) before arrow
107                if (countSpace.before === 0) {
108                    context.report({
109                        node: tokens.before,
110                        messageId: "expectedBefore",
111                        fix(fixer) {
112                            return fixer.insertTextBefore(tokens.arrow, " ");
113                        }
114                    });
115                }
116            } else {
117
118                // should be no space before arrow
119                if (countSpace.before > 0) {
120                    context.report({
121                        node: tokens.before,
122                        messageId: "unexpectedBefore",
123                        fix(fixer) {
124                            return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]);
125                        }
126                    });
127                }
128            }
129
130            if (rule.after) {
131
132                // should be space(s) after arrow
133                if (countSpace.after === 0) {
134                    context.report({
135                        node: tokens.after,
136                        messageId: "expectedAfter",
137                        fix(fixer) {
138                            return fixer.insertTextAfter(tokens.arrow, " ");
139                        }
140                    });
141                }
142            } else {
143
144                // should be no space after arrow
145                if (countSpace.after > 0) {
146                    context.report({
147                        node: tokens.after,
148                        messageId: "unexpectedAfter",
149                        fix(fixer) {
150                            return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]);
151                        }
152                    });
153                }
154            }
155        }
156
157        return {
158            ArrowFunctionExpression: spaces
159        };
160    }
161};
162