eslint 1.7.1 → 1.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/README.md +1 -0
  2. package/conf/eslint.json +3 -0
  3. package/lib/cli-engine.js +74 -74
  4. package/lib/cli.js +12 -10
  5. package/lib/eslint.js +15 -26
  6. package/lib/logging.js +25 -0
  7. package/lib/options.js +7 -2
  8. package/lib/rules/array-bracket-spacing.js +2 -2
  9. package/lib/rules/arrow-body-style.js +71 -0
  10. package/lib/rules/comma-dangle.js +26 -10
  11. package/lib/rules/comma-spacing.js +72 -36
  12. package/lib/rules/eol-last.js +10 -4
  13. package/lib/rules/indent.js +8 -7
  14. package/lib/rules/key-spacing.js +13 -25
  15. package/lib/rules/linebreak-style.js +45 -10
  16. package/lib/rules/max-nested-callbacks.js +1 -1
  17. package/lib/rules/no-arrow-condition.js +88 -0
  18. package/lib/rules/no-case-declarations.js +47 -0
  19. package/lib/rules/no-extend-native.js +3 -3
  20. package/lib/rules/no-magic-numbers.js +22 -5
  21. package/lib/rules/no-mixed-spaces-and-tabs.js +23 -19
  22. package/lib/rules/no-multiple-empty-lines.js +39 -13
  23. package/lib/rules/no-plusplus.js +22 -1
  24. package/lib/rules/no-shadow.js +22 -4
  25. package/lib/rules/no-use-before-define.js +1 -1
  26. package/lib/rules/no-warning-comments.js +1 -1
  27. package/lib/rules/radix.js +36 -6
  28. package/lib/rules/space-in-parens.js +148 -199
  29. package/lib/rules/spaced-comment.js +3 -3
  30. package/lib/rules/valid-jsdoc.js +36 -19
  31. package/lib/rules.js +13 -9
  32. package/lib/testers/rule-tester.js +62 -7
  33. package/lib/util/estraverse.js +54 -0
  34. package/lib/util/glob-util.js +149 -0
  35. package/lib/util/source-code-fixer.js +1 -1
  36. package/lib/util/source-code.js +11 -1
  37. package/lib/util.js +15 -9
  38. package/package.json +21 -21
@@ -6,6 +6,8 @@
6
6
  */
7
7
  "use strict";
8
8
 
9
+ var astUtils = require("../ast-utils");
10
+
9
11
  //------------------------------------------------------------------------------
10
12
  // Rule Definition
11
13
  //------------------------------------------------------------------------------
@@ -14,258 +16,205 @@ module.exports = function(context) {
14
16
 
15
17
  var MISSING_SPACE_MESSAGE = "There must be a space inside this paren.",
16
18
  REJECTED_SPACE_MESSAGE = "There should be no spaces inside this paren.",
17
- exceptionsArray = (context.options.length === 2) ? context.options[1].exceptions : [],
19
+ ALWAYS = context.options[0] === "always",
20
+
21
+ exceptionsArrayOptions = (context.options.length === 2) ? context.options[1].exceptions : [],
18
22
  options = {},
19
- rejectedSpaceRegExp,
20
- missingSpaceRegExp,
21
- spaceChecks;
22
-
23
- if (exceptionsArray && exceptionsArray.length) {
24
- options.braceException = exceptionsArray.indexOf("{}") !== -1 || false;
25
- options.bracketException = exceptionsArray.indexOf("[]") !== -1 || false;
26
- options.parenException = exceptionsArray.indexOf("()") !== -1 || false;
27
- options.empty = exceptionsArray.indexOf("empty") !== -1 || false;
23
+ exceptions;
24
+
25
+ if (exceptionsArrayOptions.length) {
26
+ options.braceException = exceptionsArrayOptions.indexOf("{}") !== -1;
27
+ options.bracketException = exceptionsArrayOptions.indexOf("[]") !== -1;
28
+ options.parenException = exceptionsArrayOptions.indexOf("()") !== -1;
29
+ options.empty = exceptionsArrayOptions.indexOf("empty") !== -1;
28
30
  }
29
31
 
30
32
  /**
31
- * Used with the `never` option to produce, given the exception options,
32
- * two regular expressions to check for missing and rejected spaces.
33
+ * Produces an object with the opener and closer exception values
33
34
  * @param {Object} opts The exception options
34
- * @returns {Object} `missingSpace` and `rejectedSpace` regular expressions
35
+ * @returns {Object} `openers` and `closers` exception values
35
36
  * @private
36
37
  */
37
- function getNeverChecks(opts) {
38
- var missingSpaceOpeners = [],
39
- missingSpaceClosers = [],
40
- rejectedSpaceOpeners = ["\\s"],
41
- rejectedSpaceClosers = ["\\s"],
42
- missingSpaceCheck,
43
- rejectedSpaceCheck;
44
-
45
- // Populate openers and closers
46
- if (opts.braceException) {
47
- missingSpaceOpeners.push("\\{");
48
- missingSpaceClosers.push("\\}");
49
- rejectedSpaceOpeners.push("\\{");
50
- rejectedSpaceClosers.push("\\}");
51
- }
52
- if (opts.bracketException) {
53
- missingSpaceOpeners.push("\\[");
54
- missingSpaceClosers.push("\\]");
55
- rejectedSpaceOpeners.push("\\[");
56
- rejectedSpaceClosers.push("\\]");
57
- }
58
- if (opts.parenException) {
59
- missingSpaceOpeners.push("\\(");
60
- missingSpaceClosers.push("\\)");
61
- rejectedSpaceOpeners.push("\\(");
62
- rejectedSpaceClosers.push("\\)");
63
- }
64
- if (opts.empty) {
65
- missingSpaceOpeners.push("\\)");
66
- missingSpaceClosers.push("\\(");
67
- rejectedSpaceOpeners.push("\\)");
68
- rejectedSpaceClosers.push("\\(");
38
+ function getExceptions() {
39
+ var openers = [],
40
+ closers = [];
41
+ if (options.braceException) {
42
+ openers.push("{");
43
+ closers.push("}");
69
44
  }
70
45
 
71
- if (missingSpaceOpeners.length) {
72
- missingSpaceCheck = "\\((" + missingSpaceOpeners.join("|") + ")";
73
- if (missingSpaceClosers.length) {
74
- missingSpaceCheck += "|";
75
- }
46
+ if (options.bracketException) {
47
+ openers.push("[");
48
+ closers.push("]");
76
49
  }
77
- if (missingSpaceClosers.length) {
78
- missingSpaceCheck += "(" + missingSpaceClosers.join("|") + ")\\)";
79
- }
80
-
81
- // compose the rejected regexp
82
- rejectedSpaceCheck = "\\( +[^" + rejectedSpaceOpeners.join("") + "]";
83
- rejectedSpaceCheck += "|[^" + rejectedSpaceClosers.join("") + "] +\\)";
84
50
 
85
- return {
86
- // e.g. \((\{)|(\})\) --- where {} is an exception
87
- missingSpace: missingSpaceCheck || ".^",
88
- // e.g. \( +[^ \n\r\{]|[^ \n\r\}] +\) --- where {} is an exception
89
- rejectedSpace: rejectedSpaceCheck
90
- };
91
- }
92
-
93
- /**
94
- * Used with the `always` option to produce, given the exception options,
95
- * two regular expressions to check for missing and rejected spaces.
96
- * @param {Object} opts The exception options
97
- * @returns {Object} `missingSpace` and `rejectedSpace` regular expressions
98
- * @private
99
- */
100
- function getAlwaysChecks(opts) {
101
- var missingSpaceOpeners = ["\\s", "\\)"],
102
- missingSpaceClosers = ["\\s", "\\("],
103
- rejectedSpaceOpeners = [],
104
- rejectedSpaceClosers = [],
105
- missingSpaceCheck,
106
- rejectedSpaceCheck;
107
-
108
- // Populate openers and closers
109
- if (opts.braceException) {
110
- missingSpaceOpeners.push("\\{");
111
- missingSpaceClosers.push("\\}");
112
- rejectedSpaceOpeners.push(" \\{");
113
- rejectedSpaceClosers.push("\\} ");
114
- }
115
- if (opts.bracketException) {
116
- missingSpaceOpeners.push("\\[");
117
- missingSpaceClosers.push("\\]");
118
- rejectedSpaceOpeners.push(" \\[");
119
- rejectedSpaceClosers.push("\\] ");
51
+ if (options.parenException) {
52
+ openers.push("(");
53
+ closers.push(")");
120
54
  }
121
- if (opts.parenException) {
122
- missingSpaceOpeners.push("\\(");
123
- missingSpaceClosers.push("\\)");
124
- rejectedSpaceOpeners.push(" \\(");
125
- rejectedSpaceClosers.push("\\) ");
126
- }
127
- if (opts.empty) {
128
- rejectedSpaceOpeners.push(" \\)");
129
- rejectedSpaceClosers.push("\\( ");
130
- }
131
-
132
- // compose the allowed regexp
133
- missingSpaceCheck = "\\([^" + missingSpaceOpeners.join("") + "]";
134
- missingSpaceCheck += "|[^" + missingSpaceClosers.join("") + "]\\)";
135
55
 
136
- // compose the rejected regexp
137
- if (rejectedSpaceOpeners.length) {
138
- rejectedSpaceCheck = "\\((" + rejectedSpaceOpeners.join("|") + ")";
139
- if (rejectedSpaceClosers.length) {
140
- rejectedSpaceCheck += "|";
141
- }
142
- }
143
- if (rejectedSpaceClosers.length) {
144
- rejectedSpaceCheck += "(" + rejectedSpaceClosers.join("|") + ")\\)";
56
+ if (options.empty) {
57
+ openers.push(")");
58
+ closers.push("(");
145
59
  }
146
60
 
147
61
  return {
148
- // e.g. \([^ \)\r\n\{]|[^ \(\r\n\}]\) --- where {} is an exception
149
- missingSpace: missingSpaceCheck,
150
- // e.g. \(( \{})|(\} )\) --- where {} is an excpetion
151
- rejectedSpace: rejectedSpaceCheck || ".^"
62
+ openers: openers,
63
+ closers: closers
152
64
  };
153
65
  }
154
66
 
155
- spaceChecks = (context.options[0] === "always") ? getAlwaysChecks(options) : getNeverChecks(options);
156
- missingSpaceRegExp = new RegExp(spaceChecks.missingSpace, "mg");
157
- rejectedSpaceRegExp = new RegExp(spaceChecks.rejectedSpace, "mg");
158
-
159
-
160
67
  //--------------------------------------------------------------------------
161
68
  // Helpers
162
69
  //--------------------------------------------------------------------------
163
-
164
- var skipRanges = [];
70
+ var sourceCode = context.getSourceCode();
165
71
 
166
72
  /**
167
- * Adds the range of a node to the set to be skipped when checking parens
168
- * @param {ASTNode} node The node to skip
169
- * @returns {void}
170
- * @private
73
+ * Determines if a token is one of the exceptions for the opener paren
74
+ * @param {Object} token The token to check
75
+ * @returns {boolean} True if the token is one of the exceptions for the opener paren
171
76
  */
172
- function addSkipRange(node) {
173
- skipRanges.push(node.range);
77
+ function isOpenerException(token) {
78
+ return token.type === "Punctuator" && exceptions.openers.indexOf(token.value) >= 0;
174
79
  }
175
80
 
176
81
  /**
177
- * Sorts the skipRanges array. Must be called before shouldSkip
178
- * @returns {void}
179
- * @private
82
+ * Determines if a token is one of the exceptions for the closer paren
83
+ * @param {Object} token The token to check
84
+ * @returns {boolean} True if the token is one of the exceptions for the closer paren
180
85
  */
181
- function sortSkipRanges() {
182
- skipRanges.sort(function(a, b) {
183
- return a[0] - b[0];
184
- });
86
+ function isCloserException(token) {
87
+ return token.type === "Punctuator" && exceptions.closers.indexOf(token.value) >= 0;
185
88
  }
186
89
 
187
90
  /**
188
- * Checks if a certain position in the source should be skipped
189
- * @param {Number} pos The 0-based index in the source
190
- * @returns {boolean} whether the position should be skipped
191
- * @private
91
+ * Determines if an opener paren should have a missing space after it
92
+ * @param {Object} left The paren token
93
+ * @param {Object} right The token after it
94
+ * @returns {boolean} True if the paren should have a space
192
95
  */
193
- function shouldSkip(pos) {
194
- var i, len, range;
195
- for (i = 0, len = skipRanges.length; i < len; i += 1) {
196
- range = skipRanges[i];
197
- if (pos < range[0]) {
198
- break;
199
- } else if (pos < range[1]) {
200
- return true;
96
+ function shouldOpenerHaveSpace(left, right) {
97
+ if (sourceCode.isSpaceBetweenTokens(left, right)) {
98
+ return false;
99
+ }
100
+
101
+ if (ALWAYS) {
102
+ if (right.type === "Punctuator" && right.value === ")") {
103
+ return false;
201
104
  }
105
+ return !isOpenerException(right);
106
+ } else {
107
+ return isOpenerException(right);
202
108
  }
203
- return false;
204
109
  }
205
110
 
111
+ /**
112
+ * Determines if an closer paren should have a missing space after it
113
+ * @param {Object} left The token before the paren
114
+ * @param {Object} right The paren token
115
+ * @returns {boolean} True if the paren should have a space
116
+ */
117
+ function shouldCloserHaveSpace(left, right) {
118
+ if (left.type === "Punctuator" && left.value === "(") {
119
+ return false;
120
+ }
206
121
 
207
- //--------------------------------------------------------------------------
208
- // Public
209
- //--------------------------------------------------------------------------
122
+ if (sourceCode.isSpaceBetweenTokens(left, right)) {
123
+ return false;
124
+ }
210
125
 
211
- return {
126
+ if (ALWAYS) {
127
+ return !isCloserException(left);
128
+ } else {
129
+ return isCloserException(left);
130
+ }
131
+ }
212
132
 
213
- "Program:exit": function checkParenSpaces(node) {
214
-
215
- var nextMatch,
216
- nextLine,
217
- column,
218
- line = 1,
219
- source = context.getSource(),
220
- pos = 0;
221
-
222
- /**
223
- * Check the match
224
- * @param {object} match Object to match
225
- * @param {string} message Message to report
226
- * @returns {void}
227
- * @private
228
- */
229
- function checkMatch(match, message) {
230
- if (source.charAt(match.index) !== "(") {
231
- // Matched a closing paren pattern
232
- match.index += 1;
233
- }
133
+ /**
134
+ * Determines if an opener paren should not have an existing space after it
135
+ * @param {Object} left The paren token
136
+ * @param {Object} right The token after it
137
+ * @returns {boolean} True if the paren should reject the space
138
+ */
139
+ function shouldOpenerRejectSpace(left, right) {
140
+ if (right.type === "Line") {
141
+ return false;
142
+ }
234
143
 
235
- if (!shouldSkip(match.index)) {
236
- while ((nextLine = source.indexOf("\n", pos)) !== -1 && nextLine < match.index) {
237
- pos = nextLine + 1;
238
- line += 1;
239
- }
240
- column = match.index - pos;
144
+ if (!astUtils.isTokenOnSameLine(left, right)) {
145
+ return false;
146
+ }
241
147
 
242
- context.report(node, { line: line, column: column }, message);
243
- }
244
- }
148
+ if (!sourceCode.isSpaceBetweenTokens(left, right)) {
149
+ return false;
150
+ }
245
151
 
246
- sortSkipRanges();
152
+ if (ALWAYS) {
153
+ return isOpenerException(right);
154
+ } else {
155
+ return !isOpenerException(right);
156
+ }
157
+ }
247
158
 
248
- while ((nextMatch = rejectedSpaceRegExp.exec(source)) !== null) {
249
- checkMatch(nextMatch, REJECTED_SPACE_MESSAGE);
250
- }
159
+ /**
160
+ * Determines if an closer paren should not have an existing space after it
161
+ * @param {Object} left The token before the paren
162
+ * @param {Object} right The paren token
163
+ * @returns {boolean} True if the paren should reject the space
164
+ */
165
+ function shouldCloserRejectSpace(left, right) {
166
+ if (left.type === "Punctuator" && left.value === "(") {
167
+ return false;
168
+ }
251
169
 
252
- while ((nextMatch = missingSpaceRegExp.exec(source)) !== null) {
253
- checkMatch(nextMatch, MISSING_SPACE_MESSAGE);
254
- }
170
+ if (!astUtils.isTokenOnSameLine(left, right)) {
171
+ return false;
172
+ }
255
173
 
256
- },
174
+ if (!sourceCode.isSpaceBetweenTokens(left, right)) {
175
+ return false;
176
+ }
257
177
 
178
+ if (ALWAYS) {
179
+ return isCloserException(left);
180
+ } else {
181
+ return !isCloserException(left);
182
+ }
183
+ }
258
184
 
259
- // These nodes can contain parentheses that this rule doesn't care about
185
+ //--------------------------------------------------------------------------
186
+ // Public
187
+ //--------------------------------------------------------------------------
260
188
 
261
- LineComment: addSkipRange,
189
+ return {
190
+ "Program": function checkParenSpaces(node) {
191
+ var tokens, prevToken, nextToken;
192
+ exceptions = getExceptions();
193
+ tokens = sourceCode.tokensAndComments;
262
194
 
263
- BlockComment: addSkipRange,
195
+ tokens.forEach(function(token, i) {
196
+ prevToken = tokens[i - 1];
197
+ nextToken = tokens[i + 1];
264
198
 
265
- Literal: addSkipRange,
199
+ if (token.type !== "Punctuator") {
200
+ return;
201
+ }
266
202
 
267
- TemplateElement: addSkipRange
203
+ if (token.value !== "(" && token.value !== ")") {
204
+ return;
205
+ }
268
206
 
207
+ if (token.value === "(" && shouldOpenerHaveSpace(token, nextToken)) {
208
+ context.report(node, token.loc.end, MISSING_SPACE_MESSAGE);
209
+ } else if (token.value === "(" && shouldOpenerRejectSpace(token, nextToken)) {
210
+ context.report(node, token.loc.end, REJECTED_SPACE_MESSAGE);
211
+ } else if (token.value === ")" && shouldCloserHaveSpace(prevToken, token)) {
212
+ context.report(node, token.loc.end, MISSING_SPACE_MESSAGE);
213
+ } else if (token.value === ")" && shouldCloserRejectSpace(prevToken, token)) {
214
+ context.report(node, token.loc.end, REJECTED_SPACE_MESSAGE);
215
+ }
216
+ });
217
+ }
269
218
  };
270
219
 
271
220
  };
@@ -165,16 +165,16 @@ module.exports = function(context) {
165
165
  if (requireSpace) {
166
166
  if (!rule.regex.test(node.value)) {
167
167
  if (rule.hasExceptions) {
168
- context.report(node, "Expected exception block, space or tab after " + commentIdentifier + " in comment.");
168
+ context.report(node, "Expected exception block, space or tab after \"" + commentIdentifier + "\" in comment.");
169
169
  } else {
170
- context.report(node, "Expected space or tab after " + commentIdentifier + " in comment.");
170
+ context.report(node, "Expected space or tab after \"" + commentIdentifier + "\" in comment.");
171
171
  }
172
172
  }
173
173
  } else {
174
174
  var matched = rule.regex.exec(node.value);
175
175
  if (matched) {
176
176
  if (!matched[1]) {
177
- context.report(node, "Unexpected space or tab after " + commentIdentifier + " in comment.");
177
+ context.report(node, "Unexpected space or tab after \"" + commentIdentifier + "\" in comment.");
178
178
  } else {
179
179
  context.report(node, "Unexpected space or tab after marker (" + matched[1] + ") in comment.");
180
180
  }
@@ -33,6 +33,16 @@ module.exports = function(context) {
33
33
  // Using a stack to store if a function returns or not (handling nested functions)
34
34
  var fns = [];
35
35
 
36
+ /**
37
+ * Check if node type is a Class
38
+ * @param {ASTNode} node node to check.
39
+ * @returns {boolean} True is its a class
40
+ * @private
41
+ */
42
+ function isTypeClass(node) {
43
+ return node.type === "ClassExpression" || node.type === "ClassDeclaration";
44
+ }
45
+
36
46
  /**
37
47
  * When parsing a new function, store it in our function stack.
38
48
  * @param {ASTNode} node A function node to check.
@@ -41,7 +51,8 @@ module.exports = function(context) {
41
51
  */
42
52
  function startFunction(node) {
43
53
  fns.push({
44
- returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement")
54
+ returnPresent: (node.type === "ArrowFunctionExpression" && node.body.type !== "BlockStatement") ||
55
+ isTypeClass(node)
45
56
  });
46
57
  }
47
58
 
@@ -158,14 +169,14 @@ module.exports = function(context) {
158
169
  }
159
170
 
160
171
  // check tag preferences
161
- if (prefer.hasOwnProperty(tag.title)) {
172
+ if (prefer.hasOwnProperty(tag.title) && tag.title !== prefer[tag.title]) {
162
173
  context.report(jsdocNode, "Use @{{name}} instead.", { name: prefer[tag.title] });
163
174
  }
164
175
 
165
176
  });
166
177
 
167
178
  // check for functions missing @returns
168
- if (!isOverride && !hasReturns && !hasConstructor && node.parent.kind !== "get") {
179
+ if (!isOverride && !hasReturns && !hasConstructor && node.parent.kind !== "get" && !isTypeClass(node)) {
169
180
  if (requireReturn || functionData.returnPresent) {
170
181
  context.report(jsdocNode, "Missing JSDoc @" + (prefer.returns || "returns") + " for function.");
171
182
  }
@@ -174,23 +185,25 @@ module.exports = function(context) {
174
185
  // check the parameters
175
186
  var jsdocParams = Object.keys(params);
176
187
 
177
- node.params.forEach(function(param, i) {
178
- var name = param.name;
179
-
180
- // TODO(nzakas): Figure out logical things to do with destructured, default, rest params
181
- if (param.type === "Identifier") {
182
- if (jsdocParams[i] && (name !== jsdocParams[i])) {
183
- context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
184
- name: name,
185
- jsdocName: jsdocParams[i]
186
- });
187
- } else if (!params[name] && !isOverride) {
188
- context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
189
- name: name
190
- });
188
+ if (node.params) {
189
+ node.params.forEach(function(param, i) {
190
+ var name = param.name;
191
+
192
+ // TODO(nzakas): Figure out logical things to do with destructured, default, rest params
193
+ if (param.type === "Identifier") {
194
+ if (jsdocParams[i] && (name !== jsdocParams[i])) {
195
+ context.report(jsdocNode, "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.", {
196
+ name: name,
197
+ jsdocName: jsdocParams[i]
198
+ });
199
+ } else if (!params[name] && !isOverride) {
200
+ context.report(jsdocNode, "Missing JSDoc for parameter '{{name}}'.", {
201
+ name: name
202
+ });
203
+ }
191
204
  }
192
- }
193
- });
205
+ });
206
+ }
194
207
 
195
208
  if (options.matchDescription) {
196
209
  var regex = new RegExp(options.matchDescription);
@@ -212,9 +225,13 @@ module.exports = function(context) {
212
225
  "ArrowFunctionExpression": startFunction,
213
226
  "FunctionExpression": startFunction,
214
227
  "FunctionDeclaration": startFunction,
228
+ "ClassExpression": startFunction,
229
+ "ClassDeclaration": startFunction,
215
230
  "ArrowFunctionExpression:exit": checkJSDoc,
216
231
  "FunctionExpression:exit": checkJSDoc,
217
232
  "FunctionDeclaration:exit": checkJSDoc,
233
+ "ClassExpression:exit": checkJSDoc,
234
+ "ClassDeclaration:exit": checkJSDoc,
218
235
  "ReturnStatement": addReturn
219
236
  };
220
237
 
package/lib/rules.js CHANGED
@@ -31,8 +31,6 @@ function define(ruleId, ruleModule) {
31
31
  rules[ruleId] = ruleModule;
32
32
  }
33
33
 
34
- exports.define = define;
35
-
36
34
  /**
37
35
  * Loads and registers all rules from passed rules directory.
38
36
  * @param {String} [rulesDir] Path to rules directory, may be relative. Defaults to `lib/rules`.
@@ -45,43 +43,49 @@ function load(rulesDir) {
45
43
  });
46
44
  }
47
45
 
48
- exports.load = load;
49
-
50
46
  /**
51
47
  * Registers all given rules of a plugin.
52
48
  * @param {Object} pluginRules A key/value map of rule definitions.
53
49
  * @param {String} pluginName The name of the plugin without prefix (`eslint-plugin-`).
54
50
  * @returns {void}
55
51
  */
56
- exports.import = function(pluginRules, pluginName) {
52
+ function importPlugin(pluginRules, pluginName) {
57
53
  Object.keys(pluginRules).forEach(function(ruleId) {
58
54
  var qualifiedRuleId = pluginName + "/" + ruleId,
59
55
  rule = pluginRules[ruleId];
60
56
 
61
57
  define(qualifiedRuleId, rule);
62
58
  });
63
- };
59
+ }
64
60
 
65
61
  /**
66
62
  * Access rule handler by id (file name).
67
63
  * @param {String} ruleId Rule id (file name).
68
64
  * @returns {Function} Rule handler.
69
65
  */
70
- exports.get = function(ruleId) {
66
+ function get(ruleId) {
71
67
  if (typeof rules[ruleId] === "string") {
72
68
  return require(rules[ruleId]);
73
69
  } else {
74
70
  return rules[ruleId];
75
71
  }
76
- };
72
+ }
77
73
 
78
74
  /**
79
75
  * Reset rules storage.
80
76
  * Should be used only in tests.
81
77
  * @returns {void}
82
78
  */
83
- exports.testClear = function() {
79
+ function testClear() {
84
80
  rules = Object.create(null);
81
+ }
82
+
83
+ module.exports = {
84
+ define: define,
85
+ load: load,
86
+ import: importPlugin,
87
+ get: get,
88
+ testClear: testClear
85
89
  };
86
90
 
87
91
  //------------------------------------------------------------------------------