1/** 2 * @fileoverview Rule to flag for-in loops without if statements inside 3 * @author Nicholas C. Zakas 4 */ 5 6"use strict"; 7 8//------------------------------------------------------------------------------ 9// Rule Definition 10//------------------------------------------------------------------------------ 11 12module.exports = { 13 meta: { 14 type: "suggestion", 15 16 docs: { 17 description: "require `for-in` loops to include an `if` statement", 18 category: "Best Practices", 19 recommended: false, 20 url: "https://eslint.org/docs/rules/guard-for-in" 21 }, 22 23 schema: [], 24 messages: { 25 wrap: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype." 26 } 27 }, 28 29 create(context) { 30 31 return { 32 33 ForInStatement(node) { 34 const body = node.body; 35 36 // empty statement 37 if (body.type === "EmptyStatement") { 38 return; 39 } 40 41 // if statement 42 if (body.type === "IfStatement") { 43 return; 44 } 45 46 // empty block 47 if (body.type === "BlockStatement" && body.body.length === 0) { 48 return; 49 } 50 51 // block with just if statement 52 if (body.type === "BlockStatement" && body.body.length === 1 && body.body[0].type === "IfStatement") { 53 return; 54 } 55 56 // block that starts with if statement 57 if (body.type === "BlockStatement" && body.body.length >= 1 && body.body[0].type === "IfStatement") { 58 const i = body.body[0]; 59 60 // ... whose consequent is a continue 61 if (i.consequent.type === "ContinueStatement") { 62 return; 63 } 64 65 // ... whose consequent is a block that contains only a continue 66 if (i.consequent.type === "BlockStatement" && i.consequent.body.length === 1 && i.consequent.body[0].type === "ContinueStatement") { 67 return; 68 } 69 } 70 71 context.report({ node, messageId: "wrap" }); 72 } 73 }; 74 75 } 76}; 77