UNPKG

3.53 kBJavaScriptView Raw
1/**
2 * @fileoverview A rule to control the style of variable initializations.
3 * @author Colin Ihrig
4 * @copyright 2015 Colin Ihrig. All rights reserved.
5 */
6
7"use strict";
8
9//------------------------------------------------------------------------------
10// Helpers
11//------------------------------------------------------------------------------
12
13/**
14 * Checks whether or not a given node is a for loop.
15 * @param {ASTNode} block - A node to check.
16 * @returns {boolean} `true` when the node is a for loop.
17 */
18function isForLoop(block) {
19 return block.type === "ForInStatement" ||
20 block.type === "ForOfStatement" ||
21 block.type === "ForStatement";
22}
23
24/**
25 * Checks whether or not a given declarator node has its initializer.
26 * @param {ASTNode} node - A declarator node to check.
27 * @returns {boolean} `true` when the node has its initializer.
28 */
29function isInitialized(node) {
30 var declaration = node.parent;
31 var block = declaration.parent;
32
33 if (isForLoop(block)) {
34 if (block.type === "ForStatement") {
35 return block.init === declaration;
36 }
37 return block.left === declaration;
38 }
39 return Boolean(node.init);
40}
41
42//------------------------------------------------------------------------------
43// Rule Definition
44//------------------------------------------------------------------------------
45
46module.exports = function(context) {
47
48 var MODE_ALWAYS = "always",
49 MODE_NEVER = "never";
50
51 var mode = context.options[0] || MODE_ALWAYS;
52 var params = context.options[1] || {};
53 //--------------------------------------------------------------------------
54 // Public API
55 //--------------------------------------------------------------------------
56
57 return {
58 "VariableDeclaration:exit": function(node) {
59
60 var kind = node.kind,
61 declarations = node.declarations;
62
63 for (var i = 0; i < declarations.length; ++i) {
64 var declaration = declarations[i],
65 id = declaration.id,
66 initialized = isInitialized(declaration),
67 isIgnoredForLoop = params.ignoreForLoopInit && isForLoop(node.parent);
68 if (id.type !== "Identifier") {
69 continue;
70 }
71
72 if (mode === MODE_ALWAYS && !initialized) {
73 context.report(declaration, "Variable '" + id.name + "' should be initialized on declaration.");
74 } else if (mode === MODE_NEVER && kind !== "const" && initialized && !isIgnoredForLoop) {
75 context.report(declaration, "Variable '" + id.name + "' should not be initialized on declaration.");
76 }
77 }
78 }
79 };
80};
81
82module.exports.schema = {
83 "anyOf": [
84 {
85 "type": "array",
86 "items": [
87 {
88 "enum": ["always"]
89 }
90 ],
91 "minItems": 0,
92 "maxItems": 1
93 },
94 {
95 "type": "array",
96 "items": [
97 {
98 "enum": ["never"]
99 },
100 {
101 "type": "object",
102 "properties": {
103 "ignoreForLoopInit": {
104 "type": "boolean"
105 }
106 },
107 "additionalProperties": false
108 }
109 ],
110 "minItems": 0,
111 "maxItems": 2
112 }
113 ]
114};