UNPKG

3.54 kBJavaScriptView Raw
1/**
2 * @fileoverview Rule to check the spacing around the * in generator functions.
3 * @author Jamund Ferguson
4 * @copyright 2015 Brandon Mills. All rights reserved.
5 * @copyright 2014 Jamund Ferguson. All rights reserved.
6 */
7
8"use strict";
9
10module.exports = function(context) {
11
12 var mode = (function(option) {
13 if (option == null || typeof option === "string") {
14 return {
15 before: { before: true, after: false },
16 after: { before: false, after: true },
17 both: { before: true, after: true },
18 neither: { before: false, after: false }
19 }[option || "before"];
20 }
21 return option;
22 }(context.options[0]));
23
24 function isAsyncGenerator(node){
25 return context.getFirstToken(node, 2).value === '*'
26 }
27
28 /**
29 * Checks the spacing between two tokens before or after the star token.
30 * @param {string} side Either "before" or "after".
31 * @param {Token} leftToken `function` keyword token if side is "before", or
32 * star token if side is "after".
33 * @param {Token} rightToken Star token if side is "before", or identifier
34 * token if side is "after".
35 * @returns {void}
36 */
37 function checkSpacing(side, leftToken, rightToken) {
38 if (!!(rightToken.range[0] - leftToken.range[1]) !== mode[side]) {
39 context.report(
40 leftToken.value === "*" ? leftToken : rightToken,
41 "{{type}} space {{side}} *.",
42 {
43 type: mode[side] ? "Missing" : "Unexpected",
44 side: side
45 }
46 );
47 }
48 }
49
50 /**
51 * Enforces the spacing around the star if node is a generator function.
52 * @param {ASTNode} node A function expression or declaration node.
53 * @returns {void}
54 */
55 function checkFunction(node) {
56 var first = context.getFirstToken(node)
57 , isMethod = node.parent.method || node.parent.type === "MethodDefinition"
58 , isAsync = first.value === 'async';
59
60 var prevToken, starToken, nextToken;
61
62
63 if ( !node.generator || (isAsync && !isAsyncGenerator(node))) {
64 return;
65 }
66
67 if (isMethod) {
68 starToken = context.getTokenBefore(node, 1);
69 } else {
70 starToken = context.getFirstToken(node, isAsync ? 2 : 1);
71 }
72
73 // Only check before when preceded by `function` keyword
74 prevToken = context.getTokenBefore(starToken);
75 if (prevToken.value === "function" || prevToken.value === "static") {
76 checkSpacing("before", prevToken, starToken);
77 }
78
79 // Only check after when followed by an identifier
80 nextToken = context.getTokenAfter(starToken);
81 if (nextToken.type === "Identifier") {
82 checkSpacing("after", starToken, nextToken);
83 }
84 }
85
86 return {
87 "FunctionDeclaration": checkFunction,
88 "FunctionExpression": checkFunction
89 };
90
91};
92
93module.exports.schema = [
94 {
95 "oneOf": [
96 {
97 "enum": ["before", "after", "both", "neither"]
98 },
99 {
100 "type": "object",
101 "properties": {
102 "before": {"type": "boolean"},
103 "after": {"type": "boolean"}
104 },
105 "additionalProperties": false
106 }
107 ]
108 }
109];