• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/**
2 * @fileoverview Rule to check the spacing around the * in yield* expressions.
3 * @author Bryan Smith
4 */
5
6"use strict";
7
8//------------------------------------------------------------------------------
9// Rule Definition
10//------------------------------------------------------------------------------
11
12module.exports = {
13    meta: {
14        type: "layout",
15
16        docs: {
17            description: "require or disallow spacing around the `*` in `yield*` expressions",
18            category: "ECMAScript 6",
19            recommended: false,
20            url: "https://eslint.org/docs/rules/yield-star-spacing"
21        },
22
23        fixable: "whitespace",
24
25        schema: [
26            {
27                oneOf: [
28                    {
29                        enum: ["before", "after", "both", "neither"]
30                    },
31                    {
32                        type: "object",
33                        properties: {
34                            before: { type: "boolean" },
35                            after: { type: "boolean" }
36                        },
37                        additionalProperties: false
38                    }
39                ]
40            }
41        ],
42        messages: {
43            missingBefore: "Missing space before *.",
44            missingAfter: "Missing space after *.",
45            unexpectedBefore: "Unexpected space before *.",
46            unexpectedAfter: "Unexpected space after *."
47        }
48    },
49
50    create(context) {
51        const sourceCode = context.getSourceCode();
52
53        const mode = (function(option) {
54            if (!option || typeof option === "string") {
55                return {
56                    before: { before: true, after: false },
57                    after: { before: false, after: true },
58                    both: { before: true, after: true },
59                    neither: { before: false, after: false }
60                }[option || "after"];
61            }
62            return option;
63        }(context.options[0]));
64
65        /**
66         * Checks the spacing between two tokens before or after the star token.
67         * @param {string} side Either "before" or "after".
68         * @param {Token} leftToken `function` keyword token if side is "before", or
69         *     star token if side is "after".
70         * @param {Token} rightToken Star token if side is "before", or identifier
71         *     token if side is "after".
72         * @returns {void}
73         */
74        function checkSpacing(side, leftToken, rightToken) {
75            if (sourceCode.isSpaceBetweenTokens(leftToken, rightToken) !== mode[side]) {
76                const after = leftToken.value === "*";
77                const spaceRequired = mode[side];
78                const node = after ? leftToken : rightToken;
79                let messageId = "";
80
81                if (spaceRequired) {
82                    messageId = side === "before" ? "missingBefore" : "missingAfter";
83                } else {
84                    messageId = side === "before" ? "unexpectedBefore" : "unexpectedAfter";
85                }
86
87                context.report({
88                    node,
89                    messageId,
90                    fix(fixer) {
91                        if (spaceRequired) {
92                            if (after) {
93                                return fixer.insertTextAfter(node, " ");
94                            }
95                            return fixer.insertTextBefore(node, " ");
96                        }
97                        return fixer.removeRange([leftToken.range[1], rightToken.range[0]]);
98                    }
99                });
100            }
101        }
102
103        /**
104         * Enforces the spacing around the star if node is a yield* expression.
105         * @param {ASTNode} node A yield expression node.
106         * @returns {void}
107         */
108        function checkExpression(node) {
109            if (!node.delegate) {
110                return;
111            }
112
113            const tokens = sourceCode.getFirstTokens(node, 3);
114            const yieldToken = tokens[0];
115            const starToken = tokens[1];
116            const nextToken = tokens[2];
117
118            checkSpacing("before", yieldToken, starToken);
119            checkSpacing("after", starToken, nextToken);
120        }
121
122        return {
123            YieldExpression: checkExpression
124        };
125
126    }
127};
128