summaryrefslogtreecommitdiff
path: root/tools/eslint/lib/rules/generator-star-spacing.js
blob: fe0b82bd1980e21f72ae972df3cb44a4bc5d8339 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
/**
 * @fileoverview Rule to check the spacing around the * in generator functions.
 * @author Jamund Ferguson
 * @copyright 2015 Brandon Mills. All rights reserved.
 * @copyright 2014 Jamund Ferguson. All rights reserved.
 */

"use strict";

//------------------------------------------------------------------------------
// Rule Definition
//------------------------------------------------------------------------------

module.exports = function(context) {

    var mode = {
        before: { before: true, after: false },
        after: { before: false, after: true },
        both: { before: true, after: true },
        neither: { before: false, after: false }
    }[context.options[0] || "before"];

    /**
     * Checks the spacing between two tokens before or after the star token.
     * @param {string} side Either "before" or "after".
     * @param {Token} leftToken `function` keyword token if side is "before", or
     *     star token if side is "after".
     * @param {Token} rightToken Star token if side is "before", or identifier
     *     token if side is "after".
     * @returns {void}
     */
    function checkSpacing(side, leftToken, rightToken) {
        if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) {
            context.report(
                leftToken.value === "*" ? leftToken : rightToken,
                "{{type}} space {{side}} *.",
                {
                    type: mode[side] ? "Missing" : "Unexpected",
                    side: side
                }
            );
        }
    }

    /**
     * Enforces the spacing around the star if node is a generator function.
     * @param {ASTNode} node A function expression or declaration node.
     * @returns {void}
     */
    function checkFunction(node) {
        var isMethod, starToken, tokenBefore, tokenAfter;

        if (!node.generator) {
            return;
        }

        isMethod = !!context.getAncestors().pop().method;

        if (isMethod) {
            starToken = context.getTokenBefore(node, 1);
        } else {
            starToken = context.getFirstToken(node, 1);
        }

        // Only check before when preceded by `function` keyword
        tokenBefore = context.getTokenBefore(starToken);
        if (tokenBefore.value === "function") {
            checkSpacing("before", tokenBefore, starToken);
        }

        // Only check after when followed by an identifier
        tokenAfter = context.getTokenAfter(starToken);
        if (tokenAfter.type === "Identifier") {
            checkSpacing("after", starToken, tokenAfter);
        }
    }

    return {
        "FunctionDeclaration": checkFunction,
        "FunctionExpression": checkFunction
    };

};