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