• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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