UNPKG

107 kBJavaScriptView Raw
1(function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.coffeelint = f()}})(function(){var define,module,exports;return (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2module.exports={
3 "name": "coffeelint",
4 "description": "Lint your CoffeeScript",
5 "version": "2.0.4",
6 "homepage": "http://www.coffeelint.org",
7 "keywords": [
8 "lint",
9 "coffeescript",
10 "coffee-script"
11 ],
12 "author": "Matthew Perpick <clutchski@gmail.com>",
13 "main": "./lib/coffeelint.js",
14 "engines": {
15 "npm": ">=1.3.7",
16 "node": ">=6.9.1"
17 },
18 "repository": {
19 "type": "git",
20 "url": "git://github.com/clutchski/coffeelint.git"
21 },
22 "bin": {
23 "coffeelint": "./bin/coffeelint"
24 },
25 "dependencies": {
26 "coffeescript": "2.0.0",
27 "glob": "^7.0.6",
28 "ignore": "^3.0.9",
29 "optimist": "^0.6.1",
30 "resolve": "^0.6.3",
31 "strip-json-comments": "^1.0.2"
32 },
33 "devDependencies": {
34 "vows": ">=0.8.1",
35 "underscore": ">=1.4.4"
36 },
37 "license": "MIT",
38 "scripts": {
39 "pretest": "cake compile",
40 "test": "./vowsrunner.js --spec test/*.coffee test/*.litcoffee",
41 "testrule": "npm run compile && ./vowsrunner.js --spec",
42 "posttest": "npm run lint",
43 "prepublish": "cake prepublish",
44 "postpublish": "cake postpublish",
45 "publish": "cake publish",
46 "lint": "cake compile && ./bin/coffeelint .",
47 "lint-csv": "cake compile && ./bin/coffeelint --csv .",
48 "lint-jslint": "cake compile && ./bin/coffeelint --jslint .",
49 "compile": "cake compile"
50 }
51}
52},{}],2:[function(require,module,exports){
53var ASTApi, ASTLinter, BaseLinter, hasChildren, node_children,
54 hasProp = {}.hasOwnProperty,
55 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
56
57BaseLinter = require('./base_linter.coffee');
58
59node_children = {
60 Class: ['variable', 'parent', 'body'],
61 Code: ['params', 'body'],
62 For: ['body', 'source', 'guard', 'step'],
63 If: ['condition', 'body', 'elseBody'],
64 Obj: ['properties'],
65 Op: ['first', 'second'],
66 Switch: ['subject', 'cases', 'otherwise'],
67 Try: ['attempt', 'recovery', 'ensure'],
68 Value: ['base', 'properties'],
69 While: ['condition', 'guard', 'body']
70};
71
72hasChildren = function(node, children) {
73 var ref;
74 return (node != null ? (ref = node.children) != null ? ref.length : void 0 : void 0) === children.length && (node != null ? node.children.every(function(elem, i) {
75 return elem === children[i];
76 }) : void 0);
77};
78
79ASTApi = (function() {
80 function ASTApi(config1) {
81 this.config = config1;
82 }
83
84 ASTApi.prototype.getNodeName = function(node) {
85 var children, name, ref;
86 name = node != null ? (ref = node.constructor) != null ? ref.name : void 0 : void 0;
87 if (node_children[name]) {
88 return name;
89 } else {
90 for (name in node_children) {
91 if (!hasProp.call(node_children, name)) continue;
92 children = node_children[name];
93 if (hasChildren(node, children)) {
94 return name;
95 }
96 }
97 }
98 };
99
100 return ASTApi;
101
102})();
103
104module.exports = ASTLinter = (function(superClass) {
105 extend(ASTLinter, superClass);
106
107 function ASTLinter(source, config, rules, CoffeeScript) {
108 this.CoffeeScript = CoffeeScript;
109 ASTLinter.__super__.constructor.call(this, source, config, rules);
110 this.astApi = new ASTApi(this.config);
111 }
112
113 ASTLinter.prototype.acceptRule = function(rule) {
114 return typeof rule.lintAST === 'function';
115 };
116
117 ASTLinter.prototype.lint = function() {
118 var coffeeError, err, errors, j, len, ref, rule, v;
119 errors = [];
120 try {
121 this.node = this.CoffeeScript.nodes(this.source);
122 } catch (error) {
123 coffeeError = error;
124 err = this._parseCoffeeScriptError(coffeeError);
125 if (err != null) {
126 errors.push(err);
127 }
128 return errors;
129 }
130 ref = this.rules;
131 for (j = 0, len = ref.length; j < len; j++) {
132 rule = ref[j];
133 this.astApi.createError = (function(_this) {
134 return function(attrs) {
135 if (attrs == null) {
136 attrs = {};
137 }
138 return _this.createError(rule.rule.name, attrs);
139 };
140 })(this);
141 rule.errors = errors;
142 v = this.normalizeResult(rule, rule.lintAST(this.node, this.astApi));
143 if (v != null) {
144 return v;
145 }
146 }
147 return errors;
148 };
149
150 ASTLinter.prototype._parseCoffeeScriptError = function(coffeeError) {
151 var attrs, lineNumber, match, message, rule;
152 rule = this.config['coffeescript_error'];
153 message = coffeeError.toString();
154 lineNumber = -1;
155 if (coffeeError.location != null) {
156 lineNumber = coffeeError.location.first_line + 1;
157 } else {
158 match = /line (\d+)/.exec(message);
159 if ((match != null ? match.length : void 0) > 1) {
160 lineNumber = parseInt(match[1], 10);
161 }
162 }
163 attrs = {
164 message: message,
165 level: rule.level,
166 lineNumber: lineNumber
167 };
168 return this.createError('coffeescript_error', attrs);
169 };
170
171 return ASTLinter;
172
173})(BaseLinter);
174
175
176},{"./base_linter.coffee":3}],3:[function(require,module,exports){
177var BaseLinter, defaults, extend,
178 slice = [].slice;
179
180extend = function() {
181 var destination, i, k, len, source, sources, v;
182 destination = arguments[0], sources = 2 <= arguments.length ? slice.call(arguments, 1) : [];
183 for (i = 0, len = sources.length; i < len; i++) {
184 source = sources[i];
185 for (k in source) {
186 v = source[k];
187 destination[k] = v;
188 }
189 }
190 return destination;
191};
192
193defaults = function(source, defaults) {
194 return extend({}, defaults, source);
195};
196
197module.exports = BaseLinter = (function() {
198 function BaseLinter(source1, config, rules) {
199 this.source = source1;
200 this.config = config;
201 this.setupRules(rules);
202 }
203
204 BaseLinter.prototype.isObject = function(obj) {
205 return obj === Object(obj);
206 };
207
208 BaseLinter.prototype.createError = function(ruleName, attrs) {
209 var level;
210 if (attrs == null) {
211 attrs = {};
212 }
213 if (attrs.level == null) {
214 attrs.level = this.config[ruleName].level;
215 }
216 level = attrs.level;
217 if (level !== 'ignore' && level !== 'warn' && level !== 'error') {
218 throw new Error("unknown level " + level + " for rule: " + ruleName);
219 }
220 if (level === 'error' || level === 'warn') {
221 attrs.rule = ruleName;
222 return defaults(attrs, this.config[ruleName]);
223 } else {
224 return null;
225 }
226 };
227
228 BaseLinter.prototype.acceptRule = function(rule) {
229 throw new Error('acceptRule needs to be overridden in the subclass');
230 };
231
232 BaseLinter.prototype.setupRules = function(rules) {
233 var RuleConstructor, level, name, results, rule;
234 this.rules = [];
235 results = [];
236 for (name in rules) {
237 RuleConstructor = rules[name];
238 level = this.config[name].level;
239 if (level === 'error' || level === 'warn') {
240 rule = new RuleConstructor(this, this.config);
241 if (this.acceptRule(rule)) {
242 results.push(this.rules.push(rule));
243 } else {
244 results.push(void 0);
245 }
246 } else if (level !== 'ignore') {
247 throw new Error("unknown level " + level + " for rule: " + rule);
248 } else {
249 results.push(void 0);
250 }
251 }
252 return results;
253 };
254
255 BaseLinter.prototype.normalizeResult = function(p, result) {
256 if (result === true) {
257 return this.createError(p.rule.name);
258 }
259 if (this.isObject(result)) {
260 return this.createError(p.rule.name, result);
261 }
262 };
263
264 return BaseLinter;
265
266})();
267
268
269},{}],4:[function(require,module,exports){
270
271/*
272CoffeeLint
273
274Copyright (c) 2011 Matthew Perpick.
275CoffeeLint is freely distributable under the MIT license.
276 */
277var ASTLinter, CoffeeScript, ERROR, ErrorReport, IGNORE, LexicalLinter, LineLinter, RULES, WARN, _rules, cache, coffeelint, defaults, difference, extend, hasSyntaxError, mergeDefaultConfig, nodeRequire, packageJSON, sameJSON, union,
278 slice = [].slice,
279 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
280
281coffeelint = exports;
282
283nodeRequire = require;
284
285if (typeof window !== "undefined" && window !== null) {
286 CoffeeScript = window.CoffeeScript;
287}
288
289if (CoffeeScript == null) {
290 CoffeeScript = nodeRequire('coffeescript');
291}
292
293if (CoffeeScript == null) {
294 throw new Error('Unable to find CoffeeScript');
295}
296
297packageJSON = require('./../package.json');
298
299coffeelint.VERSION = packageJSON.version;
300
301ERROR = 'error';
302
303WARN = 'warn';
304
305IGNORE = 'ignore';
306
307coffeelint.RULES = RULES = require('./rules.coffee');
308
309extend = function() {
310 var destination, j, k, len, source, sources, v;
311 destination = arguments[0], sources = 2 <= arguments.length ? slice.call(arguments, 1) : [];
312 for (j = 0, len = sources.length; j < len; j++) {
313 source = sources[j];
314 for (k in source) {
315 v = source[k];
316 destination[k] = v;
317 }
318 }
319 return destination;
320};
321
322defaults = function(source, defaults) {
323 return extend({}, defaults, source);
324};
325
326union = function(a, b) {
327 var c, j, len, len1, n, results, x;
328 c = {};
329 for (j = 0, len = a.length; j < len; j++) {
330 x = a[j];
331 c[x] = true;
332 }
333 for (n = 0, len1 = b.length; n < len1; n++) {
334 x = b[n];
335 c[x] = true;
336 }
337 results = [];
338 for (x in c) {
339 results.push(x);
340 }
341 return results;
342};
343
344difference = function(a, b) {
345 var j, len, results, x;
346 results = [];
347 for (j = 0, len = a.length; j < len; j++) {
348 x = a[j];
349 if (indexOf.call(b, x) < 0) {
350 results.push(x);
351 }
352 }
353 return results;
354};
355
356LineLinter = require('./line_linter.coffee');
357
358LexicalLinter = require('./lexical_linter.coffee');
359
360ASTLinter = require('./ast_linter.coffee');
361
362cache = null;
363
364mergeDefaultConfig = function(userConfig) {
365 var config, rule, ruleConfig, ruleLoader;
366 try {
367 ruleLoader = nodeRequire('./ruleLoader');
368 ruleLoader.loadFromConfig(coffeelint, userConfig);
369 } catch (error) {}
370 config = {};
371 if (userConfig.coffeelint) {
372 config.coffeelint = userConfig.coffeelint;
373 }
374 for (rule in RULES) {
375 ruleConfig = RULES[rule];
376 config[rule] = defaults(userConfig[rule], ruleConfig);
377 }
378 return config;
379};
380
381sameJSON = function(a, b) {
382 return JSON.stringify(a) === JSON.stringify(b);
383};
384
385coffeelint.trimConfig = function(userConfig) {
386 var config, dConfig, dValue, key, newConfig, ref, rule, value;
387 newConfig = {};
388 userConfig = mergeDefaultConfig(userConfig);
389 for (rule in userConfig) {
390 config = userConfig[rule];
391 dConfig = RULES[rule];
392 if (rule === 'coffeelint') {
393 config.transforms = config._transforms;
394 delete config._transforms;
395 config.coffeescript = config._coffeescript;
396 delete config._coffeescript;
397 newConfig[rule] = config;
398 } else if ((config.level === (ref = dConfig.level) && ref === 'ignore')) {
399 void 0;
400 } else if (config.level === 'ignore') {
401 newConfig[rule] = {
402 level: 'ignore'
403 };
404 } else {
405 config.module = config._module;
406 delete config._module;
407 for (key in config) {
408 value = config[key];
409 if (key === 'message' || key === 'description' || key === 'name') {
410 continue;
411 }
412 dValue = dConfig[key];
413 if (value !== dValue && !sameJSON(value, dValue)) {
414 if (newConfig[rule] == null) {
415 newConfig[rule] = {};
416 }
417 newConfig[rule][key] = value;
418 }
419 }
420 }
421 }
422 return newConfig;
423};
424
425coffeelint.invertLiterate = function(source) {
426 var j, len, line, newSource, ref;
427 source = CoffeeScript.helpers.invertLiterate(source);
428 newSource = '';
429 ref = source.split('\n');
430 for (j = 0, len = ref.length; j < len; j++) {
431 line = ref[j];
432 if (line.match(/^#/)) {
433 line = line.replace(/\s*$/, '');
434 }
435 line = line.replace(/^[ ]{4}|^\t/g, '');
436 newSource += line + "\n";
437 }
438 return newSource;
439};
440
441_rules = {};
442
443coffeelint.registerRule = function(RuleConstructor, ruleName) {
444 var e, name, p, ref, ref1;
445 if (ruleName == null) {
446 ruleName = void 0;
447 }
448 p = new RuleConstructor;
449 name = (p != null ? (ref = p.rule) != null ? ref.name : void 0 : void 0) || '(unknown)';
450 e = function(msg) {
451 throw new Error("Invalid rule: " + name + " " + msg);
452 };
453 if (p.rule == null) {
454 e('Rules must provide rule attribute with a default configuration.');
455 }
456 if (p.rule.name == null) {
457 e('Rule defaults require a name');
458 }
459 if ((ruleName != null) && ruleName !== p.rule.name) {
460 e("Mismatched rule name: " + ruleName);
461 }
462 if (p.rule.message == null) {
463 e('Rule defaults require a message');
464 }
465 if (p.rule.description == null) {
466 e('Rule defaults require a description');
467 }
468 if ((ref1 = p.rule.level) !== 'ignore' && ref1 !== 'warn' && ref1 !== 'error') {
469 e("Default level must be 'ignore', 'warn', or 'error'");
470 }
471 if (typeof p.lintToken === 'function') {
472 if (!p.tokens) {
473 e("'tokens' is required for 'lintToken'");
474 }
475 } else if (typeof p.lintLine !== 'function' && typeof p.lintAST !== 'function') {
476 e('Rules must implement lintToken, lintLine, or lintAST');
477 }
478 RULES[p.rule.name] = p.rule;
479 return _rules[p.rule.name] = RuleConstructor;
480};
481
482coffeelint.getRules = function() {
483 var j, key, len, output, ref;
484 output = {};
485 ref = Object.keys(RULES).sort();
486 for (j = 0, len = ref.length; j < len; j++) {
487 key = ref[j];
488 output[key] = RULES[key];
489 }
490 return output;
491};
492
493coffeelint.registerRule(require('./rules/arrow_spacing.coffee'));
494
495coffeelint.registerRule(require('./rules/braces_spacing.coffee'));
496
497coffeelint.registerRule(require('./rules/no_tabs.coffee'));
498
499coffeelint.registerRule(require('./rules/no_trailing_whitespace.coffee'));
500
501coffeelint.registerRule(require('./rules/max_line_length.coffee'));
502
503coffeelint.registerRule(require('./rules/line_endings.coffee'));
504
505coffeelint.registerRule(require('./rules/no_trailing_semicolons.coffee'));
506
507coffeelint.registerRule(require('./rules/indentation.coffee'));
508
509coffeelint.registerRule(require('./rules/camel_case_classes.coffee'));
510
511coffeelint.registerRule(require('./rules/colon_assignment_spacing.coffee'));
512
513coffeelint.registerRule(require('./rules/no_implicit_braces.coffee'));
514
515coffeelint.registerRule(require('./rules/no_nested_string_interpolation.coffee'));
516
517coffeelint.registerRule(require('./rules/no_plusplus.coffee'));
518
519coffeelint.registerRule(require('./rules/no_throwing_strings.coffee'));
520
521coffeelint.registerRule(require('./rules/no_backticks.coffee'));
522
523coffeelint.registerRule(require('./rules/no_implicit_parens.coffee'));
524
525coffeelint.registerRule(require('./rules/no_empty_param_list.coffee'));
526
527coffeelint.registerRule(require('./rules/no_stand_alone_at.coffee'));
528
529coffeelint.registerRule(require('./rules/space_operators.coffee'));
530
531coffeelint.registerRule(require('./rules/duplicate_key.coffee'));
532
533coffeelint.registerRule(require('./rules/empty_constructor_needs_parens.coffee'));
534
535coffeelint.registerRule(require('./rules/cyclomatic_complexity.coffee'));
536
537coffeelint.registerRule(require('./rules/newlines_after_classes.coffee'));
538
539coffeelint.registerRule(require('./rules/no_unnecessary_fat_arrows.coffee'));
540
541coffeelint.registerRule(require('./rules/missing_fat_arrows.coffee'));
542
543coffeelint.registerRule(require('./rules/non_empty_constructor_needs_parens.coffee'));
544
545coffeelint.registerRule(require('./rules/no_unnecessary_double_quotes.coffee'));
546
547coffeelint.registerRule(require('./rules/no_debugger.coffee'));
548
549coffeelint.registerRule(require('./rules/no_interpolation_in_single_quotes.coffee'));
550
551coffeelint.registerRule(require('./rules/no_empty_functions.coffee'));
552
553coffeelint.registerRule(require('./rules/prefer_english_operator.coffee'));
554
555coffeelint.registerRule(require('./rules/spacing_after_comma.coffee'));
556
557coffeelint.registerRule(require('./rules/transform_messes_up_line_numbers.coffee'));
558
559coffeelint.registerRule(require('./rules/ensure_comprehensions.coffee'));
560
561coffeelint.registerRule(require('./rules/no_this.coffee'));
562
563coffeelint.registerRule(require('./rules/eol_last.coffee'));
564
565coffeelint.registerRule(require('./rules/no_private_function_fat_arrows.coffee'));
566
567hasSyntaxError = function(source) {
568 try {
569 CoffeeScript.tokens(source);
570 return false;
571 } catch (error) {}
572 return true;
573};
574
575ErrorReport = require('./error_report.coffee');
576
577coffeelint.getErrorReport = function() {
578 return new ErrorReport(coffeelint);
579};
580
581coffeelint.lint = function(source, userConfig, literate) {
582 var allErrors, astErrors, cmd, config, disabled, disabledEntirely, disabledInitially, disabledLine, e, errors, i, inlineConfig, j, l, len, len1, lexErrors, lexicalLinter, lineErrors, lineLinter, m, n, name, nextLine, o, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ref8, regex, rule, ruleLoader, rules, set, sourceLength, tokensByLine, transform;
583 if (userConfig == null) {
584 userConfig = {};
585 }
586 if (literate == null) {
587 literate = false;
588 }
589 errors = [];
590 if (cache != null) {
591 cache.setConfig(userConfig);
592 }
593 if (cache != null ? cache.has(source) : void 0) {
594 return cache != null ? cache.get(source) : void 0;
595 }
596 config = mergeDefaultConfig(userConfig);
597 if (literate) {
598 source = this.invertLiterate(source);
599 }
600 if ((userConfig != null ? (ref = userConfig.coffeelint) != null ? ref.transforms : void 0 : void 0) != null) {
601 sourceLength = source.split('\n').length;
602 ref2 = userConfig != null ? (ref1 = userConfig.coffeelint) != null ? ref1.transforms : void 0 : void 0;
603 for (j = 0, len = ref2.length; j < len; j++) {
604 m = ref2[j];
605 try {
606 ruleLoader = nodeRequire('./ruleLoader');
607 transform = ruleLoader.require(m);
608 source = transform(source);
609 } catch (error) {}
610 }
611 if (sourceLength !== source.split('\n').length && config.transform_messes_up_line_numbers.level !== 'ignore') {
612 errors.push(extend({
613 lineNumber: 1,
614 context: "File was transformed from " + sourceLength + " lines to " + (source.split("\n").length) + " lines"
615 }, config.transform_messes_up_line_numbers));
616 }
617 }
618 if ((userConfig != null ? (ref3 = userConfig.coffeelint) != null ? ref3.coffeescript : void 0 : void 0) != null) {
619 CoffeeScript = ruleLoader.require(userConfig.coffeelint.coffeescript);
620 }
621 for (name in userConfig) {
622 if (name !== 'coffeescript_error' && name !== '_comment') {
623 if (_rules[name] == null) {
624 void 0;
625 }
626 }
627 }
628 disabledInitially = [];
629 ref4 = source.split('\n');
630 for (n = 0, len1 = ref4.length; n < len1; n++) {
631 l = ref4[n];
632 ref5 = LineLinter.getDirective(l) || [], regex = ref5[0], set = ref5[1], rule = ref5[ref5.length - 1];
633 if ((set === 'enable' || set === 'enable-line') && ((ref6 = config[rule]) != null ? ref6.level : void 0) === 'ignore') {
634 disabledInitially.push(rule);
635 config[rule].level = 'error';
636 }
637 }
638 astErrors = new ASTLinter(source, config, _rules, CoffeeScript).lint();
639 errors = errors.concat(astErrors);
640 if (!hasSyntaxError(source)) {
641 lexicalLinter = new LexicalLinter(source, config, _rules, CoffeeScript);
642 lexErrors = lexicalLinter.lint();
643 errors = errors.concat(lexErrors);
644 tokensByLine = lexicalLinter.tokensByLine;
645 lineLinter = new LineLinter(source, config, _rules, tokensByLine, literate);
646 lineErrors = lineLinter.lint();
647 errors = errors.concat(lineErrors);
648 inlineConfig = lineLinter.inlineConfig;
649 } else {
650 inlineConfig = {
651 enable: {},
652 disable: {},
653 'enable-line': {},
654 'disable-line': {}
655 };
656 }
657 errors.sort(function(a, b) {
658 return a.lineNumber - b.lineNumber;
659 });
660 disabledEntirely = (function() {
661 var len2, map, o, ref7, result;
662 result = [];
663 map = {};
664 ref7 = errors || [];
665 for (o = 0, len2 = ref7.length; o < len2; o++) {
666 name = ref7[o].name;
667 if (!map[name]) {
668 result.push(name);
669 map[name] = true;
670 }
671 }
672 return result;
673 })();
674 allErrors = errors;
675 errors = [];
676 disabled = disabledInitially;
677 nextLine = 0;
678 for (i = o = 0, ref7 = source.split('\n').length; 0 <= ref7 ? o < ref7 : o > ref7; i = 0 <= ref7 ? ++o : --o) {
679 disabledLine = disabled;
680 for (cmd in inlineConfig) {
681 rules = inlineConfig[cmd][i];
682 if (rules != null) {
683 ({
684 'disable': function() {
685 if (rules.length) {
686 disabled = union(disabled, rules);
687 return disabledLine = union(disabledLine, rules);
688 } else {
689 return disabled = disabledLine = disabledEntirely;
690 }
691 },
692 'disable-line': function() {
693 if (rules.length) {
694 return disabledLine = union(disabledLine, rules);
695 } else {
696 return disabledLine = disabledEntirely;
697 }
698 },
699 'enable': function() {
700 if (rules.length) {
701 disabled = difference(disabled, rules);
702 return disabledLine = difference(disabledLine, rules);
703 } else {
704 return disabled = disabledLine = disabledInitially;
705 }
706 },
707 'enable-line': function() {
708 if (rules.length) {
709 return disabledLine = difference(disabledLine, rules);
710 } else {
711 return disabledLine = disabledInitially;
712 }
713 }
714 })[cmd]();
715 }
716 }
717 while (nextLine === i && allErrors.length > 0) {
718 nextLine = allErrors[0].lineNumber - 1;
719 e = allErrors[0];
720 if (e.lineNumber === i + 1 || (e.lineNumber == null)) {
721 e = allErrors.shift();
722 if (ref8 = e.rule, indexOf.call(disabledLine, ref8) < 0) {
723 errors.push(e);
724 }
725 }
726 }
727 }
728 if (cache != null) {
729 cache.set(source, errors);
730 }
731 return errors;
732};
733
734coffeelint.setCache = function(obj) {
735 return cache = obj;
736};
737
738
739},{"./../package.json":1,"./ast_linter.coffee":2,"./error_report.coffee":5,"./lexical_linter.coffee":6,"./line_linter.coffee":7,"./rules.coffee":8,"./rules/arrow_spacing.coffee":9,"./rules/braces_spacing.coffee":10,"./rules/camel_case_classes.coffee":11,"./rules/colon_assignment_spacing.coffee":12,"./rules/cyclomatic_complexity.coffee":13,"./rules/duplicate_key.coffee":14,"./rules/empty_constructor_needs_parens.coffee":15,"./rules/ensure_comprehensions.coffee":16,"./rules/eol_last.coffee":17,"./rules/indentation.coffee":18,"./rules/line_endings.coffee":19,"./rules/max_line_length.coffee":20,"./rules/missing_fat_arrows.coffee":21,"./rules/newlines_after_classes.coffee":22,"./rules/no_backticks.coffee":23,"./rules/no_debugger.coffee":24,"./rules/no_empty_functions.coffee":25,"./rules/no_empty_param_list.coffee":26,"./rules/no_implicit_braces.coffee":27,"./rules/no_implicit_parens.coffee":28,"./rules/no_interpolation_in_single_quotes.coffee":29,"./rules/no_nested_string_interpolation.coffee":30,"./rules/no_plusplus.coffee":31,"./rules/no_private_function_fat_arrows.coffee":32,"./rules/no_stand_alone_at.coffee":33,"./rules/no_tabs.coffee":34,"./rules/no_this.coffee":35,"./rules/no_throwing_strings.coffee":36,"./rules/no_trailing_semicolons.coffee":37,"./rules/no_trailing_whitespace.coffee":38,"./rules/no_unnecessary_double_quotes.coffee":39,"./rules/no_unnecessary_fat_arrows.coffee":40,"./rules/non_empty_constructor_needs_parens.coffee":41,"./rules/prefer_english_operator.coffee":42,"./rules/space_operators.coffee":43,"./rules/spacing_after_comma.coffee":44,"./rules/transform_messes_up_line_numbers.coffee":45}],5:[function(require,module,exports){
740var ErrorReport;
741
742module.exports = ErrorReport = (function() {
743 function ErrorReport(coffeelint) {
744 this.coffeelint = coffeelint;
745 this.paths = {};
746 }
747
748 ErrorReport.prototype.lint = function(filename, source, config, literate) {
749 if (config == null) {
750 config = {};
751 }
752 if (literate == null) {
753 literate = false;
754 }
755 return this.paths[filename] = this.coffeelint.lint(source, config, literate);
756 };
757
758 ErrorReport.prototype.getExitCode = function() {
759 var path;
760 for (path in this.paths) {
761 if (this.pathHasError(path)) {
762 return 1;
763 }
764 }
765 return 0;
766 };
767
768 ErrorReport.prototype.getSummary = function() {
769 var error, errorCount, errors, i, len, path, pathCount, ref, warningCount;
770 pathCount = errorCount = warningCount = 0;
771 ref = this.paths;
772 for (path in ref) {
773 errors = ref[path];
774 pathCount++;
775 for (i = 0, len = errors.length; i < len; i++) {
776 error = errors[i];
777 if (error.level === 'error') {
778 errorCount++;
779 }
780 if (error.level === 'warn') {
781 warningCount++;
782 }
783 }
784 }
785 return {
786 errorCount: errorCount,
787 warningCount: warningCount,
788 pathCount: pathCount
789 };
790 };
791
792 ErrorReport.prototype.getErrors = function(path) {
793 return this.paths[path];
794 };
795
796 ErrorReport.prototype.pathHasWarning = function(path) {
797 return this._hasLevel(path, 'warn');
798 };
799
800 ErrorReport.prototype.pathHasError = function(path) {
801 return this._hasLevel(path, 'error');
802 };
803
804 ErrorReport.prototype.hasError = function() {
805 var path;
806 for (path in this.paths) {
807 if (this.pathHasError(path)) {
808 return true;
809 }
810 }
811 return false;
812 };
813
814 ErrorReport.prototype._hasLevel = function(path, level) {
815 var error, i, len, ref;
816 ref = this.paths[path];
817 for (i = 0, len = ref.length; i < len; i++) {
818 error = ref[i];
819 if (error.level === level) {
820 return true;
821 }
822 }
823 return false;
824 };
825
826 return ErrorReport;
827
828})();
829
830
831},{}],6:[function(require,module,exports){
832var BaseLinter, LexicalLinter, TokenApi,
833 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
834 hasProp = {}.hasOwnProperty,
835 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
836
837TokenApi = (function() {
838 function TokenApi(CoffeeScript, source, config1, tokensByLine) {
839 this.config = config1;
840 this.tokensByLine = tokensByLine;
841 this.tokens = CoffeeScript.tokens(source);
842 this.lines = source.split('\n');
843 this.tokensByLine = {};
844 }
845
846 TokenApi.prototype.i = 0;
847
848 TokenApi.prototype.peek = function(n) {
849 if (n == null) {
850 n = 1;
851 }
852 return this.tokens[this.i + n] || null;
853 };
854
855 return TokenApi;
856
857})();
858
859BaseLinter = require('./base_linter.coffee');
860
861module.exports = LexicalLinter = (function(superClass) {
862 extend(LexicalLinter, superClass);
863
864 function LexicalLinter(source, config, rules, CoffeeScript) {
865 LexicalLinter.__super__.constructor.call(this, source, config, rules);
866 this.tokenApi = new TokenApi(CoffeeScript, source, this.config, this.tokensByLine);
867 this.tokensByLine = this.tokenApi.tokensByLine;
868 }
869
870 LexicalLinter.prototype.acceptRule = function(rule) {
871 return typeof rule.lintToken === 'function';
872 };
873
874 LexicalLinter.prototype.lint = function() {
875 var error, errors, i, j, k, len, len1, ref, ref1, token;
876 errors = [];
877 ref = this.tokenApi.tokens;
878 for (i = j = 0, len = ref.length; j < len; i = ++j) {
879 token = ref[i];
880 this.tokenApi.i = i;
881 ref1 = this.lintToken(token);
882 for (k = 0, len1 = ref1.length; k < len1; k++) {
883 error = ref1[k];
884 errors.push(error);
885 }
886 }
887 return errors;
888 };
889
890 LexicalLinter.prototype.lintToken = function(token) {
891 var base, errors, j, len, lineNumber, ref, ref1, ref2, rule, type, v, value;
892 type = token[0], value = token[1], (ref = token[2], lineNumber = ref.first_line);
893 if ((base = this.tokensByLine)[lineNumber] == null) {
894 base[lineNumber] = [];
895 }
896 this.tokensByLine[lineNumber].push(token);
897 this.lineNumber = lineNumber || this.lineNumber || 0;
898 this.tokenApi.lineNumber = this.lineNumber;
899 errors = [];
900 ref1 = this.rules;
901 for (j = 0, len = ref1.length; j < len; j++) {
902 rule = ref1[j];
903 if (!(ref2 = token[0], indexOf.call(rule.tokens, ref2) >= 0)) {
904 continue;
905 }
906 v = this.normalizeResult(rule, rule.lintToken(token, this.tokenApi));
907 if (v != null) {
908 errors.push(v);
909 }
910 }
911 return errors;
912 };
913
914 LexicalLinter.prototype.createError = function(ruleName, attrs) {
915 if (attrs == null) {
916 attrs = {};
917 }
918 if (attrs.lineNumber == null) {
919 attrs.lineNumber = this.lineNumber;
920 }
921 attrs.lineNumber += 1;
922 attrs.line = this.tokenApi.lines[attrs.lineNumber - 1];
923 return LexicalLinter.__super__.createError.call(this, ruleName, attrs);
924 };
925
926 return LexicalLinter;
927
928})(BaseLinter);
929
930
931},{"./base_linter.coffee":3}],7:[function(require,module,exports){
932var BaseLinter, LineApi, LineLinter, configShortcuts, configStatement,
933 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
934 hasProp = {}.hasOwnProperty;
935
936LineApi = (function() {
937 function LineApi(source, config1, tokensByLine1, literate1) {
938 this.config = config1;
939 this.tokensByLine = tokensByLine1;
940 this.literate = literate1;
941 this.line = null;
942 this.lines = source.split('\n');
943 this.lineCount = this.lines.length;
944 this.context = {
945 "class": {
946 inClass: false,
947 lastUnemptyLineInClass: null,
948 classIndents: null
949 }
950 };
951 }
952
953 LineApi.prototype.lineNumber = 0;
954
955 LineApi.prototype.isLiterate = function() {
956 return this.literate;
957 };
958
959 LineApi.prototype.maintainClassContext = function(line) {
960 if (this.context["class"].inClass) {
961 if (this.lineHasToken('INDENT')) {
962 this.context["class"].classIndents++;
963 } else if (this.lineHasToken('OUTDENT')) {
964 this.context["class"].classIndents--;
965 if (this.context["class"].classIndents === 0) {
966 this.context["class"].inClass = false;
967 this.context["class"].classIndents = null;
968 }
969 }
970 if (!line.match(/^\s*$/)) {
971 this.context["class"].lastUnemptyLineInClass = this.lineNumber;
972 }
973 } else {
974 if (!line.match(/\\s*/)) {
975 this.context["class"].lastUnemptyLineInClass = null;
976 }
977 if (this.lineHasToken('CLASS')) {
978 this.context["class"].inClass = true;
979 this.context["class"].lastUnemptyLineInClass = this.lineNumber;
980 this.context["class"].classIndents = 0;
981 }
982 }
983 return null;
984 };
985
986 LineApi.prototype.isLastLine = function() {
987 return this.lineNumber === this.lineCount - 1;
988 };
989
990 LineApi.prototype.lineHasToken = function(tokenType, lineNumber) {
991 var i, len, token, tokens;
992 if (tokenType == null) {
993 tokenType = null;
994 }
995 if (lineNumber == null) {
996 lineNumber = null;
997 }
998 lineNumber = lineNumber != null ? lineNumber : this.lineNumber;
999 if (tokenType == null) {
1000 return this.tokensByLine[lineNumber] != null;
1001 } else {
1002 tokens = this.tokensByLine[lineNumber];
1003 if (tokens == null) {
1004 return null;
1005 }
1006 for (i = 0, len = tokens.length; i < len; i++) {
1007 token = tokens[i];
1008 if (token[0] === tokenType) {
1009 return true;
1010 }
1011 }
1012 return false;
1013 }
1014 };
1015
1016 LineApi.prototype.getLineTokens = function() {
1017 return this.tokensByLine[this.lineNumber] || [];
1018 };
1019
1020 return LineApi;
1021
1022})();
1023
1024BaseLinter = require('./base_linter.coffee');
1025
1026configStatement = /coffeelint:\s*((disable|enable)(-line)?)(?:=([\w\s,]*))?/;
1027
1028configShortcuts = [[/\#.*noqa/, 'coffeelint: disable-line']];
1029
1030module.exports = LineLinter = (function(superClass) {
1031 extend(LineLinter, superClass);
1032
1033 LineLinter.getDirective = function(line) {
1034 var i, len, ref, replacement, shortcut;
1035 for (i = 0, len = configShortcuts.length; i < len; i++) {
1036 ref = configShortcuts[i], shortcut = ref[0], replacement = ref[1];
1037 if (line.match(shortcut)) {
1038 return configStatement.exec(replacement);
1039 }
1040 }
1041 return configStatement.exec(line);
1042 };
1043
1044 function LineLinter(source, config, rules, tokensByLine, literate) {
1045 if (literate == null) {
1046 literate = false;
1047 }
1048 LineLinter.__super__.constructor.call(this, source, config, rules);
1049 this.lineApi = new LineApi(source, config, tokensByLine, literate);
1050 this.inlineConfig = {
1051 enable: {},
1052 disable: {},
1053 'enable-line': {},
1054 'disable-line': {}
1055 };
1056 }
1057
1058 LineLinter.prototype.acceptRule = function(rule) {
1059 return typeof rule.lintLine === 'function';
1060 };
1061
1062 LineLinter.prototype.lint = function() {
1063 var error, errors, i, j, len, len1, line, lineNumber, ref, ref1;
1064 errors = [];
1065 ref = this.lineApi.lines;
1066 for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
1067 line = ref[lineNumber];
1068 this.lineApi.lineNumber = this.lineNumber = lineNumber;
1069 this.lineApi.line = this.lineApi.lines[lineNumber];
1070 this.lineApi.maintainClassContext(line);
1071 this.collectInlineConfig(line);
1072 ref1 = this.lintLine(line);
1073 for (j = 0, len1 = ref1.length; j < len1; j++) {
1074 error = ref1[j];
1075 errors.push(error);
1076 }
1077 }
1078 return errors;
1079 };
1080
1081 LineLinter.prototype.lintLine = function(line) {
1082 var errors, i, len, ref, rule, v;
1083 errors = [];
1084 ref = this.rules;
1085 for (i = 0, len = ref.length; i < len; i++) {
1086 rule = ref[i];
1087 v = this.normalizeResult(rule, rule.lintLine(line, this.lineApi));
1088 if (v != null) {
1089 errors.push(v);
1090 }
1091 }
1092 return errors;
1093 };
1094
1095 LineLinter.prototype.collectInlineConfig = function(line) {
1096 var cmd, i, len, r, ref, result, rules;
1097 result = this.constructor.getDirective(line);
1098 if (result != null) {
1099 cmd = result[1];
1100 rules = [];
1101 if (result[4] != null) {
1102 ref = result[4].split(',');
1103 for (i = 0, len = ref.length; i < len; i++) {
1104 r = ref[i];
1105 rules.push(r.replace(/^\s+|\s+$/g, ''));
1106 }
1107 }
1108 this.inlineConfig[cmd][this.lineNumber] = rules;
1109 }
1110 return null;
1111 };
1112
1113 LineLinter.prototype.createError = function(rule, attrs) {
1114 var ref;
1115 if (attrs == null) {
1116 attrs = {};
1117 }
1118 attrs.lineNumber = this.lineNumber + 1;
1119 attrs.level = (ref = this.config[rule]) != null ? ref.level : void 0;
1120 return LineLinter.__super__.createError.call(this, rule, attrs);
1121 };
1122
1123 return LineLinter;
1124
1125})(BaseLinter);
1126
1127
1128},{"./base_linter.coffee":3}],8:[function(require,module,exports){
1129var ERROR, IGNORE, WARN;
1130
1131ERROR = 'error';
1132
1133WARN = 'warn';
1134
1135IGNORE = 'ignore';
1136
1137module.exports = {
1138 coffeescript_error: {
1139 level: ERROR,
1140 message: ''
1141 }
1142};
1143
1144
1145},{}],9:[function(require,module,exports){
1146var ArrowSpacing;
1147
1148module.exports = ArrowSpacing = (function() {
1149 function ArrowSpacing() {}
1150
1151 ArrowSpacing.prototype.rule = {
1152 name: 'arrow_spacing',
1153 level: 'ignore',
1154 message: 'Function arrows (-> and =>) must be spaced properly',
1155 description: '<p>This rule checks to see that there is spacing before and after\nthe arrow operator that declares a function. This rule is disabled\nby default.</p> <p>Note that if arrow_spacing is enabled, and you\npass an empty function as a parameter, arrow_spacing will accept\neither a space or no space in-between the arrow operator and the\nparenthesis</p>\n<pre><code># Both of this will not trigger an error,\n# even with arrow_spacing enabled.\nx(-> 3)\nx( -> 3)\n\n# However, this will trigger an error\nx((a,b)-> 3)\n</code>\n</pre>'
1156 };
1157
1158 ArrowSpacing.prototype.tokens = ['->', '=>'];
1159
1160 ArrowSpacing.prototype.lintToken = function(token, tokenApi) {
1161 var pp;
1162 pp = tokenApi.peek(-1);
1163 if (!pp) {
1164 return;
1165 }
1166 if (!token.spaced && tokenApi.peek(1)[0] === 'INDENT' && tokenApi.peek(2)[0] === 'OUTDENT') {
1167 return null;
1168 } else if (!(((token.spaced != null) || (token.newLine != null)) && (((pp.spaced != null) || pp[0] === 'TERMINATOR') || (pp.generated != null) || pp[0] === 'INDENT' || (pp[1] === '(' && (pp.generated == null))))) {
1169 return true;
1170 } else {
1171 return null;
1172 }
1173 };
1174
1175 return ArrowSpacing;
1176
1177})();
1178
1179
1180},{}],10:[function(require,module,exports){
1181var BracesSpacing;
1182
1183module.exports = BracesSpacing = (function() {
1184 function BracesSpacing() {}
1185
1186 BracesSpacing.prototype.rule = {
1187 name: 'braces_spacing',
1188 level: 'ignore',
1189 spaces: 0,
1190 empty_object_spaces: 0,
1191 message: 'Curly braces must have the proper spacing',
1192 description: 'This rule checks to see that there is the proper spacing inside\ncurly braces. The spacing amount is specified by "spaces".\nThe spacing amount for empty objects is specified by\n"empty_object_spaces".\n\n<pre><code>\n# Spaces is 0\n{a: b} # Good\n{a: b } # Bad\n{ a: b} # Bad\n{ a: b } # Bad\n\n# Spaces is 1\n{a: b} # Bad\n{a: b } # Bad\n{ a: b} # Bad\n{ a: b } # Good\n{ a: b } # Bad\n{ a: b } # Bad\n{ a: b } # Bad\n\n# Empty Object Spaces is 0\n{} # Good\n{ } # Bad\n\n# Empty Object Spaces is 1\n{} # Bad\n{ } # Good\n</code></pre>\n\nThis rule is disabled by default.'
1193 };
1194
1195 BracesSpacing.prototype.tokens = ['{', '}'];
1196
1197 BracesSpacing.prototype.distanceBetweenTokens = function(firstToken, secondToken) {
1198 return secondToken[2].first_column - firstToken[2].last_column - 1;
1199 };
1200
1201 BracesSpacing.prototype.findNearestToken = function(token, tokenApi, difference) {
1202 var nearestToken, totalDifference;
1203 totalDifference = 0;
1204 while (true) {
1205 totalDifference += difference;
1206 nearestToken = tokenApi.peek(totalDifference);
1207 if (nearestToken[0] === 'OUTDENT' || (nearestToken.generated != null)) {
1208 continue;
1209 }
1210 return nearestToken;
1211 }
1212 };
1213
1214 BracesSpacing.prototype.tokensOnSameLine = function(firstToken, secondToken) {
1215 return firstToken[2].first_line === secondToken[2].first_line;
1216 };
1217
1218 BracesSpacing.prototype.getExpectedSpaces = function(tokenApi, firstToken, secondToken) {
1219 var config, ref;
1220 config = tokenApi.config[this.rule.name];
1221 if (firstToken[0] === '{' && secondToken[0] === '}') {
1222 return (ref = config.empty_object_spaces) != null ? ref : config.spaces;
1223 } else {
1224 return config.spaces;
1225 }
1226 };
1227
1228 BracesSpacing.prototype.lintToken = function(token, tokenApi) {
1229 var actual, expected, firstToken, msg, ref, secondToken;
1230 if (token.generated) {
1231 return null;
1232 }
1233 ref = token[0] === '{' ? [token, this.findNearestToken(token, tokenApi, 1)] : [this.findNearestToken(token, tokenApi, -1), token], firstToken = ref[0], secondToken = ref[1];
1234 if (!this.tokensOnSameLine(firstToken, secondToken)) {
1235 return null;
1236 }
1237 expected = this.getExpectedSpaces(tokenApi, firstToken, secondToken);
1238 actual = this.distanceBetweenTokens(firstToken, secondToken);
1239 if (actual === expected) {
1240 return null;
1241 } else {
1242 msg = "There should be " + expected + " space";
1243 if (expected !== 1) {
1244 msg += 's';
1245 }
1246 msg += " inside \"" + token[0] + "\"";
1247 return {
1248 context: msg
1249 };
1250 }
1251 };
1252
1253 return BracesSpacing;
1254
1255})();
1256
1257
1258},{}],11:[function(require,module,exports){
1259var CamelCaseClasses, regexes;
1260
1261regexes = {
1262 camelCase: /^[A-Z_][a-zA-Z\d]*$/
1263};
1264
1265module.exports = CamelCaseClasses = (function() {
1266 function CamelCaseClasses() {}
1267
1268 CamelCaseClasses.prototype.rule = {
1269 name: 'camel_case_classes',
1270 level: 'error',
1271 message: 'Class name should be UpperCamelCased',
1272 description: 'This rule mandates that all class names are UpperCamelCased.\nCamel casing class names is a generally accepted way of\ndistinguishing constructor functions - which require the \'new\'\nprefix to behave properly - from plain old functions.\n<pre>\n<code># Good!\nclass BoaConstrictor\n\n# Bad!\nclass boaConstrictor\n</code>\n</pre>\nThis rule is enabled by default.'
1273 };
1274
1275 CamelCaseClasses.prototype.tokens = ['CLASS'];
1276
1277 CamelCaseClasses.prototype.lintToken = function(token, tokenApi) {
1278 var className, offset, ref, ref1, ref2;
1279 if ((token.newLine != null) || ((ref = tokenApi.peek()[0]) === 'INDENT' || ref === 'EXTENDS')) {
1280 return null;
1281 }
1282 className = null;
1283 offset = 1;
1284 while (!className) {
1285 if (((ref1 = tokenApi.peek(offset + 1)) != null ? ref1[0] : void 0) === '.') {
1286 offset += 2;
1287 } else if (((ref2 = tokenApi.peek(offset)) != null ? ref2[0] : void 0) === '@') {
1288 offset += 1;
1289 } else {
1290 className = tokenApi.peek(offset)[1];
1291 }
1292 }
1293 if (!regexes.camelCase.test(className)) {
1294 return {
1295 context: "class name: " + className
1296 };
1297 }
1298 };
1299
1300 return CamelCaseClasses;
1301
1302})();
1303
1304
1305},{}],12:[function(require,module,exports){
1306var ColonAssignmentSpacing;
1307
1308module.exports = ColonAssignmentSpacing = (function() {
1309 function ColonAssignmentSpacing() {}
1310
1311 ColonAssignmentSpacing.prototype.rule = {
1312 name: 'colon_assignment_spacing',
1313 level: 'ignore',
1314 message: 'Colon assignment without proper spacing',
1315 spacing: {
1316 left: 0,
1317 right: 0
1318 },
1319 description: '<p>This rule checks to see that there is spacing before and\nafter the colon in a colon assignment (i.e., classes, objects).\nThe spacing amount is specified by\nspacing.left and spacing.right, respectively.\nA zero value means no spacing required.\n</p>\n<pre><code>\n#\n# If spacing.left and spacing.right is 1\n#\n\n# Doesn\'t throw an error\nobject = {spacing : true}\nclass Dog\n canBark : true\n\n# Throws an error\nobject = {spacing: true}\nclass Cat\n canBark: false\n</code></pre>'
1320 };
1321
1322 ColonAssignmentSpacing.prototype.tokens = [':'];
1323
1324 ColonAssignmentSpacing.prototype.lintToken = function(token, tokenApi) {
1325 var checkSpacing, getSpaceFromToken, isLeftSpaced, isRightSpaced, leftSpacing, nextToken, previousToken, ref, ref1, rightSpacing, spaceRules;
1326 spaceRules = tokenApi.config[this.rule.name].spacing;
1327 previousToken = tokenApi.peek(-1);
1328 nextToken = tokenApi.peek(1);
1329 getSpaceFromToken = function(direction) {
1330 switch (direction) {
1331 case 'left':
1332 return token[2].first_column - previousToken[2].last_column - 1;
1333 case 'right':
1334 return nextToken[2].first_column - token[2].first_column - 1;
1335 }
1336 };
1337 checkSpacing = function(direction) {
1338 var isSpaced, spacing;
1339 spacing = getSpaceFromToken(direction);
1340 isSpaced = spacing < 0 ? true : spacing === parseInt(spaceRules[direction]);
1341 return [isSpaced, spacing];
1342 };
1343 ref = checkSpacing('left'), isLeftSpaced = ref[0], leftSpacing = ref[1];
1344 ref1 = checkSpacing('right'), isRightSpaced = ref1[0], rightSpacing = ref1[1];
1345 if (isLeftSpaced && isRightSpaced) {
1346 return null;
1347 } else {
1348 return {
1349 context: "Incorrect spacing around column " + token[2].first_column
1350 };
1351 }
1352 };
1353
1354 return ColonAssignmentSpacing;
1355
1356})();
1357
1358
1359},{}],13:[function(require,module,exports){
1360var CyclomaticComplexity;
1361
1362module.exports = CyclomaticComplexity = (function() {
1363 function CyclomaticComplexity() {}
1364
1365 CyclomaticComplexity.prototype.rule = {
1366 name: 'cyclomatic_complexity',
1367 level: 'ignore',
1368 message: 'The cyclomatic complexity is too damn high',
1369 value: 10,
1370 description: 'Examine the complexity of your function.'
1371 };
1372
1373 CyclomaticComplexity.prototype.getComplexity = function(node) {
1374 var complexity, name, ref;
1375 name = this.astApi.getNodeName(node);
1376 complexity = name === 'If' || name === 'While' || name === 'For' || name === 'Try' ? 1 : name === 'Op' && ((ref = node.operator) === '&&' || ref === '||') ? 1 : name === 'Switch' ? node.cases.length : 0;
1377 return complexity;
1378 };
1379
1380 CyclomaticComplexity.prototype.lintAST = function(node, astApi) {
1381 this.astApi = astApi;
1382 this.lintNode(node);
1383 return void 0;
1384 };
1385
1386 CyclomaticComplexity.prototype.lintNode = function(node) {
1387 var complexity, error, name, ref, rule;
1388 name = (ref = this.astApi) != null ? ref.getNodeName(node) : void 0;
1389 complexity = this.getComplexity(node);
1390 node.eachChild((function(_this) {
1391 return function(childNode) {
1392 var childComplexity, ref1;
1393 childComplexity = _this.lintNode(childNode);
1394 if (((ref1 = _this.astApi) != null ? ref1.getNodeName(childNode) : void 0) !== 'Code') {
1395 return complexity += childComplexity;
1396 }
1397 };
1398 })(this));
1399 rule = this.astApi.config[this.rule.name];
1400 if (name === 'Code' && complexity >= rule.value) {
1401 error = this.astApi.createError({
1402 context: complexity + 1,
1403 lineNumber: node.locationData.first_line + 1,
1404 lineNumberEnd: node.locationData.last_line + 1
1405 });
1406 if (error) {
1407 this.errors.push(error);
1408 }
1409 }
1410 return complexity;
1411 };
1412
1413 return CyclomaticComplexity;
1414
1415})();
1416
1417
1418},{}],14:[function(require,module,exports){
1419var DuplicateKey;
1420
1421module.exports = DuplicateKey = (function() {
1422 DuplicateKey.prototype.rule = {
1423 name: 'duplicate_key',
1424 level: 'error',
1425 message: 'Duplicate key defined in object or class',
1426 description: 'Prevents defining duplicate keys in object literals and classes'
1427 };
1428
1429 DuplicateKey.prototype.tokens = ['IDENTIFIER', 'PROPERTY', '{', '}'];
1430
1431 function DuplicateKey() {
1432 this.braceScopes = [];
1433 }
1434
1435 DuplicateKey.prototype.lintToken = function(arg, tokenApi) {
1436 var type;
1437 type = arg[0];
1438 if (type === '{' || type === '}') {
1439 this.lintBrace.apply(this, arguments);
1440 return void 0;
1441 }
1442 if (type === 'IDENTIFIER' || type === 'PROPERTY') {
1443 return this.lintIdentifier.apply(this, arguments);
1444 }
1445 };
1446
1447 DuplicateKey.prototype.lintIdentifier = function(token, tokenApi) {
1448 var key, nextToken, previousToken;
1449 key = token[1];
1450 if (this.currentScope == null) {
1451 return null;
1452 }
1453 nextToken = tokenApi.peek(1);
1454 if (nextToken[1] !== ':') {
1455 return null;
1456 }
1457 previousToken = tokenApi.peek(-1);
1458 if (previousToken[0] === '@') {
1459 key = "@" + key;
1460 }
1461 key = "identifier-" + key;
1462 if (this.currentScope[key]) {
1463 return true;
1464 } else {
1465 this.currentScope[key] = token;
1466 return null;
1467 }
1468 };
1469
1470 DuplicateKey.prototype.lintBrace = function(token) {
1471 if (token[0] === '{') {
1472 if (this.currentScope != null) {
1473 this.braceScopes.push(this.currentScope);
1474 }
1475 this.currentScope = {};
1476 } else {
1477 this.currentScope = this.braceScopes.pop();
1478 }
1479 return null;
1480 };
1481
1482 return DuplicateKey;
1483
1484})();
1485
1486
1487},{}],15:[function(require,module,exports){
1488var EmptyConstructorNeedsParens;
1489
1490module.exports = EmptyConstructorNeedsParens = (function() {
1491 function EmptyConstructorNeedsParens() {}
1492
1493 EmptyConstructorNeedsParens.prototype.rule = {
1494 name: 'empty_constructor_needs_parens',
1495 level: 'ignore',
1496 message: 'Invoking a constructor without parens and without arguments',
1497 description: 'Requires constructors with no parameters to include the parens'
1498 };
1499
1500 EmptyConstructorNeedsParens.prototype.tokens = ['UNARY'];
1501
1502 EmptyConstructorNeedsParens.prototype.lintToken = function(token, tokenApi) {
1503 var identIndex, isIdent, nextToken, peek, ref, ref1, ref2;
1504 if (token[1] === 'new') {
1505 peek = tokenApi.peek.bind(tokenApi);
1506 identIndex = 1;
1507 while (true) {
1508 isIdent = (ref = (ref1 = peek(identIndex)) != null ? ref1[0] : void 0) === 'IDENTIFIER' || ref === 'PROPERTY';
1509 nextToken = peek(identIndex + 1);
1510 if (isIdent) {
1511 if ((nextToken != null ? nextToken[0] : void 0) === '.') {
1512 identIndex += 2;
1513 continue;
1514 }
1515 if ((nextToken != null ? nextToken[0] : void 0) === 'INDEX_START') {
1516 while (((ref2 = peek(identIndex)) != null ? ref2[0] : void 0) !== 'INDEX_END') {
1517 identIndex++;
1518 }
1519 continue;
1520 }
1521 }
1522 break;
1523 }
1524 if (isIdent && (nextToken != null)) {
1525 return this.handleExpectedCallStart(nextToken);
1526 }
1527 }
1528 };
1529
1530 EmptyConstructorNeedsParens.prototype.handleExpectedCallStart = function(isCallStart) {
1531 if (isCallStart[0] !== 'CALL_START') {
1532 return true;
1533 }
1534 };
1535
1536 return EmptyConstructorNeedsParens;
1537
1538})();
1539
1540
1541},{}],16:[function(require,module,exports){
1542var EnsureComprehensions,
1543 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
1544
1545module.exports = EnsureComprehensions = (function() {
1546 function EnsureComprehensions() {}
1547
1548 EnsureComprehensions.prototype.rule = {
1549 name: 'ensure_comprehensions',
1550 level: 'warn',
1551 message: 'Comprehensions must have parentheses around them',
1552 description: 'This rule makes sure that parentheses are around comprehensions.'
1553 };
1554
1555 EnsureComprehensions.prototype.tokens = ['FOR'];
1556
1557 EnsureComprehensions.prototype.forBlock = false;
1558
1559 EnsureComprehensions.prototype.lintToken = function(token, tokenApi) {
1560 var atEqual, idents, numCallEnds, numCallStarts, numParenEnds, numParenStarts, peeker, prevIdents, prevToken, ref, ref1;
1561 idents = this.findIdents(tokenApi);
1562 if (this.forBlock) {
1563 this.forBlock = false;
1564 return;
1565 }
1566 peeker = -1;
1567 atEqual = false;
1568 numCallEnds = 0;
1569 numCallStarts = 0;
1570 numParenStarts = 0;
1571 numParenEnds = 0;
1572 prevIdents = [];
1573 while ((prevToken = tokenApi.peek(peeker))) {
1574 if (prevToken[0] === 'CALL_END') {
1575 numCallEnds++;
1576 }
1577 if (prevToken[0] === 'CALL_START') {
1578 numCallStarts++;
1579 }
1580 if (prevToken[0] === '(') {
1581 numParenStarts++;
1582 }
1583 if (prevToken[0] === ')') {
1584 numParenEnds++;
1585 }
1586 if (prevToken[0] === 'IDENTIFIER') {
1587 if (!atEqual) {
1588 prevIdents.push(prevToken[1]);
1589 } else if (ref = prevToken[1], indexOf.call(idents, ref) >= 0) {
1590 return;
1591 }
1592 }
1593 if (((ref1 = prevToken[0]) === '(' || ref1 === '->' || ref1 === 'TERMINATOR') || (prevToken.newLine != null)) {
1594 break;
1595 }
1596 if (prevToken[0] === '=' && numParenEnds === numParenStarts) {
1597 atEqual = true;
1598 }
1599 peeker--;
1600 }
1601 if (atEqual && numCallStarts === numCallEnds) {
1602 return {
1603 context: ''
1604 };
1605 }
1606 };
1607
1608 EnsureComprehensions.prototype.findIdents = function(tokenApi) {
1609 var idents, nextToken, peeker, ref;
1610 peeker = 1;
1611 idents = [];
1612 while ((nextToken = tokenApi.peek(peeker))) {
1613 if (nextToken[0] === 'IDENTIFIER') {
1614 idents.push(nextToken[1]);
1615 }
1616 if ((ref = nextToken[0]) === 'FORIN' || ref === 'FOROF') {
1617 break;
1618 }
1619 peeker++;
1620 }
1621 while ((nextToken = tokenApi.peek(peeker))) {
1622 if (nextToken[0] === 'TERMINATOR') {
1623 break;
1624 }
1625 if (nextToken[0] === 'INDENT') {
1626 this.forBlock = true;
1627 break;
1628 }
1629 peeker++;
1630 }
1631 return idents;
1632 };
1633
1634 return EnsureComprehensions;
1635
1636})();
1637
1638
1639},{}],17:[function(require,module,exports){
1640var EOLLast;
1641
1642module.exports = EOLLast = (function() {
1643 function EOLLast() {}
1644
1645 EOLLast.prototype.rule = {
1646 name: 'eol_last',
1647 level: 'ignore',
1648 message: 'File does not end with a single newline',
1649 description: 'Checks that the file ends with a single newline'
1650 };
1651
1652 EOLLast.prototype.lintLine = function(line, lineApi) {
1653 var isNewline, previousIsNewline;
1654 if (!lineApi.isLastLine()) {
1655 return null;
1656 }
1657 isNewline = line.length === 0;
1658 previousIsNewline = lineApi.lineCount > 1 ? lineApi.lines[lineApi.lineNumber - 1].length === 0 : false;
1659 if (!(isNewline && !previousIsNewline)) {
1660 return true;
1661 }
1662 };
1663
1664 return EOLLast;
1665
1666})();
1667
1668
1669},{}],18:[function(require,module,exports){
1670var Indentation,
1671 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
1672
1673module.exports = Indentation = (function() {
1674 Indentation.prototype.rule = {
1675 name: 'indentation',
1676 value: 2,
1677 level: 'error',
1678 message: 'Line contains inconsistent indentation',
1679 description: 'This rule imposes a standard number of spaces to be used for\nindentation. Since whitespace is significant in CoffeeScript, it\'s\ncritical that a project chooses a standard indentation format and\nstays consistent. Other roads lead to darkness. <pre> <code>#\nEnabling this option will prevent this ugly\n# but otherwise valid CoffeeScript.\ntwoSpaces = () ->\n fourSpaces = () ->\n eightSpaces = () ->\n \'this is valid CoffeeScript\'\n\n</code>\n</pre>\nTwo space indentation is enabled by default.'
1680 };
1681
1682 Indentation.prototype.tokens = ['INDENT', '[', ']', '.'];
1683
1684 Indentation.prototype.keywords = ['->', '=>', '@', 'CATCH', 'CLASS', 'DEFAULT', 'ELSE', 'EXPORT', 'FINALLY', 'FOR', 'FORIN', 'FOROF', 'IDENTIFIER', 'IF', 'IMPORT', 'LEADING_WHEN', 'LOOP', 'PROPERTY', 'RETURN', 'SWITCH', 'THROW', 'TRY', 'UNTIL', 'WHEN', 'WHILE', 'YIELD'];
1685
1686 function Indentation() {
1687 this.arrayTokens = [];
1688 }
1689
1690 Indentation.prototype.lintToken = function(token, tokenApi) {
1691 var chain, currentLine, dotIndent, expected, got, ignoreIndent, isArrayIndent, isMultiline, lineNumber, lines, next, numIndents, previous, previousSymbol, ref, ref1, regExRes, startsWith, type;
1692 type = token[0], numIndents = token[1];
1693 dotIndent = token[2].first_column;
1694 lines = tokenApi.lines, lineNumber = tokenApi.lineNumber;
1695 expected = tokenApi.config[this.rule.name].value;
1696 if (type === '.') {
1697 currentLine = lines[lineNumber];
1698 if (((ref = currentLine.match(/\S/)) != null ? ref[0] : void 0) === '.') {
1699 next = tokenApi.peek(1);
1700 if (next[0] === 'PROPERTY') {
1701 chain = '.' + next[1];
1702 startsWith = new RegExp('^(\\s*)(\\' + chain + ')');
1703 regExRes = currentLine.match(startsWith);
1704 if ((regExRes != null ? regExRes.index : void 0) === 0) {
1705 got = dotIndent;
1706 if (dotIndent - expected > expected) {
1707 got %= expected;
1708 }
1709 if (dotIndent % expected !== 0) {
1710 return {
1711 context: "Expected " + expected + " got " + got
1712 };
1713 }
1714 }
1715 }
1716 }
1717 return void 0;
1718 }
1719 if (type === '[' || type === ']') {
1720 this.lintArray(token);
1721 return void 0;
1722 }
1723 if ((token.generated != null) || (token.explicit != null)) {
1724 return null;
1725 }
1726 previous = tokenApi.peek(-1);
1727 isArrayIndent = this.inArray() && (previous != null ? previous.newLine : void 0);
1728 previousSymbol = (ref1 = tokenApi.peek(-1)) != null ? ref1[0] : void 0;
1729 isMultiline = previousSymbol === '=' || previousSymbol === ',';
1730 ignoreIndent = isArrayIndent || isMultiline;
1731 numIndents = this.getCorrectIndent(tokenApi);
1732 if (!ignoreIndent && !(indexOf.call(numIndents, expected) >= 0)) {
1733 return {
1734 context: "Expected " + expected + " got " + numIndents[0]
1735 };
1736 }
1737 };
1738
1739 Indentation.prototype.inArray = function() {
1740 return this.arrayTokens.length > 0;
1741 };
1742
1743 Indentation.prototype.lintArray = function(token) {
1744 if (token[0] === '[') {
1745 this.arrayTokens.push(token);
1746 } else if (token[0] === ']') {
1747 this.arrayTokens.pop();
1748 }
1749 return null;
1750 };
1751
1752 Indentation.prototype.grabLineTokens = function(tokenApi, lineNumber, all) {
1753 var i, k, len, len1, ref, ref1, results, results1, tok, tokensByLine;
1754 if (all == null) {
1755 all = false;
1756 }
1757 tokensByLine = tokenApi.tokensByLine;
1758 while (!((tokensByLine[lineNumber] != null) || lineNumber === 0)) {
1759 lineNumber--;
1760 }
1761 if (all) {
1762 ref = tokensByLine[lineNumber];
1763 results = [];
1764 for (i = 0, len = ref.length; i < len; i++) {
1765 tok = ref[i];
1766 results.push(tok);
1767 }
1768 return results;
1769 } else {
1770 ref1 = tokensByLine[lineNumber];
1771 results1 = [];
1772 for (k = 0, len1 = ref1.length; k < len1; k++) {
1773 tok = ref1[k];
1774 if ((tok.generated == null) && tok[0] !== 'OUTDENT') {
1775 results1.push(tok);
1776 }
1777 }
1778 return results1;
1779 }
1780 };
1781
1782 Indentation.prototype.getCorrectIndent = function(tokenApi) {
1783 var _, curIndent, i, j, len, lineNumber, lines, prevIndent, prevNum, prevTokens, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ret, skipAssign, t, tokens, tryLine;
1784 lineNumber = tokenApi.lineNumber, lines = tokenApi.lines, tokens = tokenApi.tokens;
1785 curIndent = (ref = lines[lineNumber].match(/\S/)) != null ? ref.index : void 0;
1786 prevNum = 1;
1787 while (/^\s*(#|$)/.test(lines[lineNumber - prevNum])) {
1788 prevNum += 1;
1789 }
1790 prevTokens = this.grabLineTokens(tokenApi, lineNumber - prevNum);
1791 if (((ref1 = prevTokens[0]) != null ? ref1[0] : void 0) === 'INDENT') {
1792 return [curIndent - ((ref2 = prevTokens[1]) != null ? ref2[2].first_column : void 0), curIndent - prevTokens[0][1]];
1793 } else {
1794 prevIndent = (ref3 = prevTokens[0]) != null ? ref3[2].first_column : void 0;
1795 for (j = i = 0, len = prevTokens.length; i < len; j = ++i) {
1796 _ = prevTokens[j];
1797 if (!(prevTokens[j][0] === '=' && ((ref4 = prevTokens[j + 1]) != null ? ref4[0] : void 0) === 'IF')) {
1798 continue;
1799 }
1800 skipAssign = curIndent - prevTokens[j + 1][2].first_column;
1801 ret = curIndent - prevIndent;
1802 if (skipAssign < 0) {
1803 return [ret];
1804 }
1805 return [skipAssign, ret];
1806 }
1807 while (prevIndent > curIndent) {
1808 tryLine = lineNumber - prevNum;
1809 prevTokens = this.grabLineTokens(tokenApi, tryLine, true);
1810 if (((ref5 = prevTokens[0]) != null ? ref5[0] : void 0) === 'INDENT') {
1811 prevIndent = prevTokens[0][1];
1812 prevTokens = prevTokens.slice(1);
1813 }
1814 t = 0;
1815 while (!((prevTokens[t] == null) || (ref6 = prevTokens[t][0], indexOf.call(this.keywords, ref6) >= 0))) {
1816 t++;
1817 }
1818 prevTokens = prevTokens.slice(t);
1819 prevNum++;
1820 if (prevTokens[0] == null) {
1821 continue;
1822 }
1823 prevIndent = (ref7 = prevTokens[0]) != null ? ref7[2].first_column : void 0;
1824 }
1825 }
1826 return [curIndent - prevIndent];
1827 };
1828
1829 return Indentation;
1830
1831})();
1832
1833
1834},{}],19:[function(require,module,exports){
1835var LineEndings;
1836
1837module.exports = LineEndings = (function() {
1838 function LineEndings() {}
1839
1840 LineEndings.prototype.rule = {
1841 name: 'line_endings',
1842 level: 'ignore',
1843 value: 'unix',
1844 message: 'Line contains incorrect line endings',
1845 description: 'This rule ensures your project uses only <tt>windows</tt> or\n<tt>unix</tt> line endings. This rule is disabled by default.'
1846 };
1847
1848 LineEndings.prototype.lintLine = function(line, lineApi) {
1849 var ending, lastChar, ref, valid;
1850 ending = (ref = lineApi.config[this.rule.name]) != null ? ref.value : void 0;
1851 if (!ending || lineApi.isLastLine() || !line) {
1852 return null;
1853 }
1854 lastChar = line[line.length - 1];
1855 valid = (function() {
1856 if (ending === 'windows') {
1857 return lastChar === '\r';
1858 } else if (ending === 'unix') {
1859 return lastChar !== '\r';
1860 } else {
1861 throw new Error("unknown line ending type: " + ending);
1862 }
1863 })();
1864 if (!valid) {
1865 return {
1866 context: "Expected " + ending
1867 };
1868 } else {
1869 return null;
1870 }
1871 };
1872
1873 return LineEndings;
1874
1875})();
1876
1877
1878},{}],20:[function(require,module,exports){
1879var MaxLineLength, regexes;
1880
1881regexes = {
1882 literateComment: /^\#\s/,
1883 longUrlComment: /^\s*\#\s*http[^\s]+$/
1884};
1885
1886module.exports = MaxLineLength = (function() {
1887 function MaxLineLength() {}
1888
1889 MaxLineLength.prototype.rule = {
1890 name: 'max_line_length',
1891 value: 80,
1892 level: 'error',
1893 limitComments: true,
1894 message: 'Line exceeds maximum allowed length',
1895 description: 'This rule imposes a maximum line length on your code. <a\nhref="http://www.python.org/dev/peps/pep-0008/">Python\'s style\nguide</a> does a good job explaining why you might want to limit the\nlength of your lines, though this is a matter of taste.\n\nLines can be no longer than eighty characters by default.'
1896 };
1897
1898 MaxLineLength.prototype.lintLine = function(line, lineApi) {
1899 var limitComments, lineLength, max, ref, ref1;
1900 max = (ref = lineApi.config[this.rule.name]) != null ? ref.value : void 0;
1901 limitComments = (ref1 = lineApi.config[this.rule.name]) != null ? ref1.limitComments : void 0;
1902 lineLength = line.replace(/\s+$/, '').length;
1903 if (lineApi.isLiterate() && regexes.literateComment.test(line)) {
1904 lineLength -= 2;
1905 }
1906 if (max && max < lineLength && !regexes.longUrlComment.test(line)) {
1907 if (!limitComments) {
1908 if (lineApi.getLineTokens().length === 0) {
1909 return;
1910 }
1911 }
1912 return {
1913 context: "Length is " + lineLength + ", max is " + max
1914 };
1915 }
1916 };
1917
1918 return MaxLineLength;
1919
1920})();
1921
1922
1923},{}],21:[function(require,module,exports){
1924var MissingFatArrows, any, containsButIsnt,
1925 bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
1926 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
1927
1928any = function(arr, test) {
1929 return arr.reduce((function(res, elt) {
1930 return res || test(elt);
1931 }), false);
1932};
1933
1934containsButIsnt = function(node, nIsThis, nIsClass) {
1935 var target;
1936 target = void 0;
1937 node.traverseChildren(false, function(n) {
1938 if (nIsClass(n)) {
1939 return false;
1940 }
1941 if (nIsThis(n)) {
1942 target = n;
1943 return false;
1944 }
1945 });
1946 return target;
1947};
1948
1949module.exports = MissingFatArrows = (function() {
1950 function MissingFatArrows() {
1951 this.isFatArrowCode = bind(this.isFatArrowCode, this);
1952 this.isThis = bind(this.isThis, this);
1953 this.isObject = bind(this.isObject, this);
1954 this.isValue = bind(this.isValue, this);
1955 this.isClass = bind(this.isClass, this);
1956 this.isCode = bind(this.isCode, this);
1957 }
1958
1959 MissingFatArrows.prototype.rule = {
1960 name: 'missing_fat_arrows',
1961 level: 'ignore',
1962 is_strict: false,
1963 message: 'Used `this` in a function without a fat arrow',
1964 description: 'Warns when you use `this` inside a function that wasn\'t defined\nwith a fat arrow. This rule does not apply to methods defined in a\nclass, since they have `this` bound to the class instance (or the\nclass itself, for class methods). The option `is_strict` is\navailable for checking bindings of class methods.\n\nIt is impossible to statically determine whether a function using\n`this` will be bound with the correct `this` value due to language\nfeatures like `Function.prototype.call` and\n`Function.prototype.bind`, so this rule may produce false positives.'
1965 };
1966
1967 MissingFatArrows.prototype.lintAST = function(node, astApi) {
1968 this.astApi = astApi;
1969 this.lintNode(node);
1970 return void 0;
1971 };
1972
1973 MissingFatArrows.prototype.lintNode = function(node, methods) {
1974 var error, isStrict, ref;
1975 if (methods == null) {
1976 methods = [];
1977 }
1978 isStrict = (ref = this.astApi.config[this.rule.name]) != null ? ref.is_strict : void 0;
1979 if (this.isPrototype(node)) {
1980 return;
1981 }
1982 if (this.isConstructor(node)) {
1983 return;
1984 }
1985 if ((!this.isFatArrowCode(node)) && (isStrict ? true : indexOf.call(methods, node) < 0) && (this.needsFatArrow(node))) {
1986 error = this.astApi.createError({
1987 lineNumber: node.locationData.first_line + 1
1988 });
1989 this.errors.push(error);
1990 }
1991 return node.eachChild((function(_this) {
1992 return function(child) {
1993 return _this.lintNode(child, (function() {
1994 switch (false) {
1995 case !this.isClass(node):
1996 return this.methodsOfClass(node);
1997 case !this.isCode(node):
1998 return [];
1999 default:
2000 return methods;
2001 }
2002 }).call(_this));
2003 };
2004 })(this));
2005 };
2006
2007 MissingFatArrows.prototype.isCode = function(node) {
2008 return this.astApi.getNodeName(node) === 'Code';
2009 };
2010
2011 MissingFatArrows.prototype.isClass = function(node) {
2012 return this.astApi.getNodeName(node) === 'Class';
2013 };
2014
2015 MissingFatArrows.prototype.isValue = function(node) {
2016 return this.astApi.getNodeName(node) === 'Value';
2017 };
2018
2019 MissingFatArrows.prototype.isObject = function(node) {
2020 return this.astApi.getNodeName(node) === 'Obj';
2021 };
2022
2023 MissingFatArrows.prototype.isPrototype = function(node) {
2024 var i, ident, len, props, ref, ref1;
2025 props = (node != null ? (ref = node.variable) != null ? ref.properties : void 0 : void 0) || [];
2026 for (i = 0, len = props.length; i < len; i++) {
2027 ident = props[i];
2028 if (((ref1 = ident.name) != null ? ref1.value : void 0) === 'prototype') {
2029 return true;
2030 }
2031 }
2032 return false;
2033 };
2034
2035 MissingFatArrows.prototype.isThis = function(node) {
2036 return this.isValue(node) && node.base.value === 'this';
2037 };
2038
2039 MissingFatArrows.prototype.isFatArrowCode = function(node) {
2040 return this.isCode(node) && node.bound;
2041 };
2042
2043 MissingFatArrows.prototype.isConstructor = function(node) {
2044 var ref, ref1;
2045 return ((ref = node.variable) != null ? (ref1 = ref.base) != null ? ref1.value : void 0 : void 0) === 'constructor';
2046 };
2047
2048 MissingFatArrows.prototype.needsFatArrow = function(node) {
2049 return this.isCode(node) && (any(node.params, (function(_this) {
2050 return function(param) {
2051 return param.contains(_this.isThis) != null;
2052 };
2053 })(this)) || containsButIsnt(node.body, this.isThis, this.isClass));
2054 };
2055
2056 MissingFatArrows.prototype.methodsOfClass = function(classNode) {
2057 var bodyNodes, returnNode;
2058 bodyNodes = classNode.body.expressions;
2059 returnNode = bodyNodes[bodyNodes.length - 1];
2060 if ((returnNode != null) && this.isValue(returnNode) && this.isObject(returnNode.base)) {
2061 return returnNode.base.properties.map(function(assignNode) {
2062 return assignNode.value;
2063 }).filter(this.isCode);
2064 } else {
2065 return [];
2066 }
2067 };
2068
2069 return MissingFatArrows;
2070
2071})();
2072
2073
2074},{}],22:[function(require,module,exports){
2075var NewlinesAfterClasses;
2076
2077module.exports = NewlinesAfterClasses = (function() {
2078 function NewlinesAfterClasses() {}
2079
2080 NewlinesAfterClasses.prototype.rule = {
2081 name: 'newlines_after_classes',
2082 value: 3,
2083 level: 'ignore',
2084 message: 'Wrong count of newlines between a class and other code',
2085 description: '<p>Checks the number of newlines between classes and other code.</p>\n\nOptions:\n- <pre><code>value</code></pre> - The number of required newlines\nafter class definitions. Defaults to 3.'
2086 };
2087
2088 NewlinesAfterClasses.prototype.tokens = ['CLASS', '}', '{'];
2089
2090 NewlinesAfterClasses.prototype.classBracesCount = 0;
2091
2092 NewlinesAfterClasses.prototype.classCount = 0;
2093
2094 NewlinesAfterClasses.prototype.lintToken = function(token, tokenApi) {
2095 var afters, befores, comment, ending, got, lineNumber, lines, numIndents, outdent, ref, ref1, ref2, start, trueLine, type;
2096 type = token[0], numIndents = token[1], (ref = token[2], lineNumber = ref.first_line);
2097 lines = tokenApi.lines;
2098 ending = tokenApi.config[this.rule.name].value;
2099 if (type === 'CLASS') {
2100 this.classCount++;
2101 }
2102 if (this.classCount > 0 && (token.generated != null)) {
2103 if (type === '{' && ((ref1 = token.origin) != null ? ref1[0] : void 0) === ':') {
2104 this.classBracesCount++;
2105 }
2106 if (type === '}' && ((ref2 = token.origin) != null ? ref2[0] : void 0) === 'OUTDENT') {
2107 this.classBracesCount--;
2108 this.classCount--;
2109 if (this.classCount === 0 && this.classBracesCount === 0) {
2110 befores = 1;
2111 afters = 1;
2112 comment = 0;
2113 outdent = token.origin[2].first_line;
2114 start = Math.min(lineNumber, outdent);
2115 trueLine = 2e308;
2116 while (/^\s*(#|$)/.test(lines[start + afters])) {
2117 if (/^\s*#/.test(lines[start + afters])) {
2118 comment += 1;
2119 } else {
2120 trueLine = Math.min(trueLine, start + afters);
2121 }
2122 afters += 1;
2123 }
2124 while (/^\s*(#|$)/.test(lines[start - befores])) {
2125 if (/^\s*#/.test(lines[start - befores])) {
2126 comment += 1;
2127 } else {
2128 trueLine = Math.min(trueLine, start - befores);
2129 }
2130 befores += 1;
2131 }
2132 got = afters + befores - comment - 2;
2133 if (got !== ending && trueLine + ending <= lines.length) {
2134 return {
2135 context: "Expected " + ending + " got " + got,
2136 lineNumber: trueLine
2137 };
2138 }
2139 }
2140 }
2141 }
2142 };
2143
2144 return NewlinesAfterClasses;
2145
2146})();
2147
2148
2149},{}],23:[function(require,module,exports){
2150var NoBackticks;
2151
2152module.exports = NoBackticks = (function() {
2153 function NoBackticks() {}
2154
2155 NoBackticks.prototype.rule = {
2156 name: 'no_backticks',
2157 level: 'error',
2158 message: 'Backticks are forbidden',
2159 description: 'Backticks allow snippets of JavaScript to be embedded in\nCoffeeScript. While some folks consider backticks useful in a few\nniche circumstances, they should be avoided because so none of\nJavaScript\'s "bad parts", like <tt>with</tt> and <tt>eval</tt>,\nsneak into CoffeeScript.\nThis rule is enabled by default.'
2160 };
2161
2162 NoBackticks.prototype.tokens = ['JS'];
2163
2164 NoBackticks.prototype.lintToken = function(token, tokenApi) {
2165 return token.comments == null;
2166 };
2167
2168 return NoBackticks;
2169
2170})();
2171
2172
2173},{}],24:[function(require,module,exports){
2174var NoDebugger;
2175
2176module.exports = NoDebugger = (function() {
2177 function NoDebugger() {}
2178
2179 NoDebugger.prototype.rule = {
2180 name: 'no_debugger',
2181 level: 'warn',
2182 message: 'Found debugging code',
2183 console: false,
2184 description: 'This rule detects `debugger` and optionally `console` calls\nThis rule is `warn` by default.'
2185 };
2186
2187 NoDebugger.prototype.tokens = ['STATEMENT', 'DEBUGGER', 'IDENTIFIER'];
2188
2189 NoDebugger.prototype.lintToken = function(token, tokenApi) {
2190 var method, ref, ref1, ref2;
2191 if (((ref = token[0]) === 'DEBUGGER' || ref === 'STATEMENT') && token[1] === 'debugger') {
2192 return {
2193 context: "found '" + token[0] + "'"
2194 };
2195 }
2196 if ((ref1 = tokenApi.config[this.rule.name]) != null ? ref1.console : void 0) {
2197 if (token[1] === 'console' && ((ref2 = tokenApi.peek(1)) != null ? ref2[0] : void 0) === '.') {
2198 method = tokenApi.peek(2);
2199 return {
2200 context: "found 'console." + method[1] + "'"
2201 };
2202 }
2203 }
2204 };
2205
2206 return NoDebugger;
2207
2208})();
2209
2210
2211},{}],25:[function(require,module,exports){
2212var NoEmptyFunctions, isEmptyCode;
2213
2214isEmptyCode = function(node, astApi) {
2215 var nodeName;
2216 nodeName = astApi.getNodeName(node);
2217 return nodeName === 'Code' && node.body.isEmpty();
2218};
2219
2220module.exports = NoEmptyFunctions = (function() {
2221 function NoEmptyFunctions() {}
2222
2223 NoEmptyFunctions.prototype.rule = {
2224 name: 'no_empty_functions',
2225 level: 'ignore',
2226 message: 'Empty function',
2227 description: 'Disallows declaring empty functions. The goal of this rule is that\nunintentional empty callbacks can be detected:\n<pre>\n<code>someFunctionWithCallback ->\ndoSomethingSignificant()\n</code>\n</pre>\nThe problem is that the call to\n<tt>doSomethingSignificant</tt> will be made regardless\nof <tt>someFunctionWithCallback</tt>\'s execution. It can\nbe because you did not indent the call to\n<tt>doSomethingSignificant</tt> properly.\n\nIf you really meant that <tt>someFunctionWithCallback</tt>\nshould call a callback that does nothing, you can write your code\nthis way:\n<pre>\n<code>someFunctionWithCallback ->\n undefined\ndoSomethingSignificant()\n</code>\n</pre>'
2228 };
2229
2230 NoEmptyFunctions.prototype.lintAST = function(node, astApi) {
2231 this.lintNode(node, astApi);
2232 return void 0;
2233 };
2234
2235 NoEmptyFunctions.prototype.lintNode = function(node, astApi) {
2236 var error;
2237 if (isEmptyCode(node, astApi)) {
2238 error = astApi.createError({
2239 lineNumber: node.locationData.first_line + 1
2240 });
2241 this.errors.push(error);
2242 }
2243 return node.eachChild((function(_this) {
2244 return function(child) {
2245 return _this.lintNode(child, astApi);
2246 };
2247 })(this));
2248 };
2249
2250 return NoEmptyFunctions;
2251
2252})();
2253
2254
2255},{}],26:[function(require,module,exports){
2256var NoEmptyParamList;
2257
2258module.exports = NoEmptyParamList = (function() {
2259 function NoEmptyParamList() {}
2260
2261 NoEmptyParamList.prototype.rule = {
2262 name: 'no_empty_param_list',
2263 level: 'ignore',
2264 message: 'Empty parameter list is forbidden',
2265 description: 'This rule prohibits empty parameter lists in function definitions.\n<pre>\n<code># The empty parameter list in here is unnecessary:\nmyFunction = () -&gt;\n\n# We might favor this instead:\nmyFunction = -&gt;\n</code>\n</pre>\nEmpty parameter lists are permitted by default.'
2266 };
2267
2268 NoEmptyParamList.prototype.tokens = ['PARAM_START'];
2269
2270 NoEmptyParamList.prototype.lintToken = function(token, tokenApi) {
2271 var nextType;
2272 nextType = tokenApi.peek()[0];
2273 return nextType === 'PARAM_END';
2274 };
2275
2276 return NoEmptyParamList;
2277
2278})();
2279
2280
2281},{}],27:[function(require,module,exports){
2282var NoImplicitBraces;
2283
2284module.exports = NoImplicitBraces = (function() {
2285 NoImplicitBraces.prototype.rule = {
2286 name: 'no_implicit_braces',
2287 level: 'ignore',
2288 message: 'Implicit braces are forbidden',
2289 strict: true,
2290 description: 'This rule prohibits implicit braces when declaring object literals.\nImplicit braces can make code more difficult to understand,\nespecially when used in combination with optional parenthesis.\n<pre>\n<code># Do you find this code ambiguous? Is it a\n# function call with three arguments or four?\nmyFunction a, b, 1:2, 3:4\n\n# While the same code written in a more\n# explicit manner has no ambiguity.\nmyFunction(a, b, {1:2, 3:4})\n</code>\n</pre>\nImplicit braces are permitted by default, since their use is\nidiomatic CoffeeScript.'
2291 };
2292
2293 NoImplicitBraces.prototype.tokens = ['{', 'OUTDENT', 'INDENT', 'CLASS', 'IDENTIFIER', 'PROPERTY', 'EXTENDS'];
2294
2295 NoImplicitBraces.prototype.dent = 0;
2296
2297 function NoImplicitBraces() {
2298 this.isClass = false;
2299 this.className = '';
2300 }
2301
2302 NoImplicitBraces.prototype.lintToken = function(token, tokenApi) {
2303 var _type, _val, c, lineNum, peekIdent, prevToken, ref, ref1, type, val;
2304 type = token[0], val = token[1], lineNum = token[2];
2305 if (type === 'OUTDENT' || type === 'INDENT' || type === 'CLASS') {
2306 return this.trackClass.apply(this, arguments);
2307 }
2308 if (type === 'EXTENDS') {
2309 this.className = '';
2310 return;
2311 }
2312 if ((type === 'IDENTIFIER' || type === 'PROPERTY') && this.isClass && this.className === '') {
2313 c = 0;
2314 while ((ref = tokenApi.peek(c)[0]) === 'IDENTIFIER' || ref === 'PROPERTY' || ref === '.') {
2315 this.className += tokenApi.peek(c)[1];
2316 c++;
2317 }
2318 }
2319 if (token.generated && type === '{') {
2320 if (!tokenApi.config[this.rule.name].strict) {
2321 prevToken = tokenApi.peek(-1)[0];
2322 if (prevToken === 'INDENT' || prevToken === 'TERMINATOR') {
2323 return;
2324 }
2325 }
2326 if (this.isClass) {
2327 prevToken = tokenApi.peek(-1)[0];
2328 if (prevToken === 'TERMINATOR') {
2329 return;
2330 }
2331 peekIdent = '';
2332 c = -2;
2333 while ((ref1 = tokenApi.peek(c), _type = ref1[0], _val = ref1[1], ref1)) {
2334 if (_type !== 'IDENTIFIER' && _type !== 'PROPERTY' && _type !== '.') {
2335 break;
2336 }
2337 peekIdent = _val + peekIdent;
2338 c--;
2339 }
2340 if (peekIdent === this.className) {
2341 return;
2342 }
2343 }
2344 return true;
2345 }
2346 };
2347
2348 NoImplicitBraces.prototype.trackClass = function(token, tokenApi) {
2349 var ln, n0, n1, ref, ref1, ref2;
2350 ref = [token, tokenApi.peek()], (ref1 = ref[0], n0 = ref1[0], ln = ref1[ref1.length - 1]), (ref2 = ref[1], n1 = ref2[0]);
2351 if (n0 === 'INDENT') {
2352 this.dent++;
2353 }
2354 if (n0 === 'OUTDENT') {
2355 this.dent--;
2356 }
2357 if (this.dent === 0 && n0 === 'OUTDENT' && n1 === 'TERMINATOR') {
2358 this.isClass = false;
2359 }
2360 if (n0 === 'CLASS') {
2361 this.isClass = true;
2362 this.className = '';
2363 }
2364 return null;
2365 };
2366
2367 return NoImplicitBraces;
2368
2369})();
2370
2371
2372},{}],28:[function(require,module,exports){
2373var NoImplicitParens;
2374
2375module.exports = NoImplicitParens = (function() {
2376 function NoImplicitParens() {}
2377
2378 NoImplicitParens.prototype.rule = {
2379 name: 'no_implicit_parens',
2380 level: 'ignore',
2381 message: 'Implicit parens are forbidden',
2382 strict: true,
2383 description: 'This rule prohibits implicit parens on function calls.\n<pre>\n<code># Some folks don\'t like this style of coding.\nmyFunction a, b, c\n\n# And would rather it always be written like this:\nmyFunction(a, b, c)\n</code>\n</pre>\nImplicit parens are permitted by default, since their use is\nidiomatic CoffeeScript.'
2384 };
2385
2386 NoImplicitParens.prototype.tokens = ['CALL_END'];
2387
2388 NoImplicitParens.prototype.lintToken = function(token, tokenApi) {
2389 var genCallStart, i, sameLine, t;
2390 if (token.generated) {
2391 if (tokenApi.config[this.rule.name].strict !== false) {
2392 return true;
2393 } else {
2394 i = -1;
2395 while (true) {
2396 t = tokenApi.peek(i);
2397 sameLine = t[2].first_line === token[2].first_line;
2398 genCallStart = t[0] === 'CALL_START' && t.generated;
2399 if ((t == null) || genCallStart && sameLine) {
2400 return true;
2401 }
2402 if (!sameLine) {
2403 return null;
2404 }
2405 i -= 1;
2406 }
2407 }
2408 }
2409 };
2410
2411 return NoImplicitParens;
2412
2413})();
2414
2415
2416},{}],29:[function(require,module,exports){
2417var NoInterpolationInSingleQuotes;
2418
2419module.exports = NoInterpolationInSingleQuotes = (function() {
2420 function NoInterpolationInSingleQuotes() {}
2421
2422 NoInterpolationInSingleQuotes.prototype.rule = {
2423 name: 'no_interpolation_in_single_quotes',
2424 level: 'ignore',
2425 message: 'Interpolation in single quoted strings is forbidden',
2426 description: 'This rule prohibits string interpolation in a single quoted string.\n<pre>\n<code># String interpolation in single quotes is not allowed:\nfoo = \'#{bar}\'\n\n# Double quotes is OK of course\nfoo = "#{bar}"\n</code>\n</pre>\nString interpolation in single quoted strings is permitted by\ndefault.'
2427 };
2428
2429 NoInterpolationInSingleQuotes.prototype.tokens = ['STRING'];
2430
2431 NoInterpolationInSingleQuotes.prototype.lintToken = function(token, tokenApi) {
2432 var hasInterpolation, tokenValue;
2433 tokenValue = token[1];
2434 hasInterpolation = tokenValue.match(/^\'.*#\{[^}]+\}.*\'$/);
2435 return hasInterpolation;
2436 };
2437
2438 return NoInterpolationInSingleQuotes;
2439
2440})();
2441
2442
2443},{}],30:[function(require,module,exports){
2444var NoNestedStringInterpolation;
2445
2446module.exports = NoNestedStringInterpolation = (function() {
2447 NoNestedStringInterpolation.prototype.rule = {
2448 name: 'no_nested_string_interpolation',
2449 level: 'warn',
2450 message: 'Nested string interpolation is forbidden',
2451 description: 'This rule warns about nested string interpolation,\nas it tends to make code harder to read and understand.\n<pre>\n<code># Good!\nstr = "Book by #{firstName.toUpperCase()} #{lastName.toUpperCase()}"\n\n# Bad!\nstr = "Book by #{"#{firstName} #{lastName}".toUpperCase()}"\n</code>\n</pre>'
2452 };
2453
2454 NoNestedStringInterpolation.prototype.tokens = ['STRING_START', 'STRING_END'];
2455
2456 function NoNestedStringInterpolation() {
2457 this.startedStrings = 0;
2458 this.generatedError = false;
2459 }
2460
2461 NoNestedStringInterpolation.prototype.lintToken = function(arg, tokenApi) {
2462 var type;
2463 type = arg[0];
2464 if (type === 'STRING_START') {
2465 return this.trackStringStart();
2466 } else {
2467 return this.trackStringEnd();
2468 }
2469 };
2470
2471 NoNestedStringInterpolation.prototype.trackStringStart = function() {
2472 this.startedStrings += 1;
2473 if (this.startedStrings <= 1 || this.generatedError) {
2474 return;
2475 }
2476 this.generatedError = true;
2477 return true;
2478 };
2479
2480 NoNestedStringInterpolation.prototype.trackStringEnd = function() {
2481 this.startedStrings -= 1;
2482 if (this.startedStrings === 1) {
2483 return this.generatedError = false;
2484 }
2485 };
2486
2487 return NoNestedStringInterpolation;
2488
2489})();
2490
2491
2492},{}],31:[function(require,module,exports){
2493var NoPlusPlus;
2494
2495module.exports = NoPlusPlus = (function() {
2496 function NoPlusPlus() {}
2497
2498 NoPlusPlus.prototype.rule = {
2499 name: 'no_plusplus',
2500 level: 'ignore',
2501 message: 'The increment and decrement operators are forbidden',
2502 description: 'This rule forbids the increment and decrement arithmetic operators.\nSome people believe the <tt>++</tt> and <tt>--</tt> to be cryptic\nand the cause of bugs due to misunderstandings of their precedence\nrules.\nThis rule is disabled by default.'
2503 };
2504
2505 NoPlusPlus.prototype.tokens = ['++', '--'];
2506
2507 NoPlusPlus.prototype.lintToken = function(token, tokenApi) {
2508 return {
2509 context: "found '" + token[0] + "'"
2510 };
2511 };
2512
2513 return NoPlusPlus;
2514
2515})();
2516
2517
2518},{}],32:[function(require,module,exports){
2519var NoPrivateFunctionFatArrows,
2520 bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
2521 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
2522
2523module.exports = NoPrivateFunctionFatArrows = (function() {
2524 function NoPrivateFunctionFatArrows() {
2525 this.isFatArrowCode = bind(this.isFatArrowCode, this);
2526 this.isObject = bind(this.isObject, this);
2527 this.isValue = bind(this.isValue, this);
2528 this.isClass = bind(this.isClass, this);
2529 this.isCode = bind(this.isCode, this);
2530 }
2531
2532 NoPrivateFunctionFatArrows.prototype.rule = {
2533 name: 'no_private_function_fat_arrows',
2534 level: 'warn',
2535 message: 'Used the fat arrow for a private function',
2536 description: 'Warns when you use the fat arrow for a private function\ninside a class definition scope. It is not necessary and\nit does not do anything.'
2537 };
2538
2539 NoPrivateFunctionFatArrows.prototype.lintAST = function(node, astApi) {
2540 this.astApi = astApi;
2541 this.lintNode(node);
2542 return void 0;
2543 };
2544
2545 NoPrivateFunctionFatArrows.prototype.lintNode = function(node, functions) {
2546 var error;
2547 if (functions == null) {
2548 functions = [];
2549 }
2550 if (this.isFatArrowCode(node) && indexOf.call(functions, node) >= 0) {
2551 error = this.astApi.createError({
2552 lineNumber: node.locationData.first_line + 1
2553 });
2554 this.errors.push(error);
2555 }
2556 return node.eachChild((function(_this) {
2557 return function(child) {
2558 return _this.lintNode(child, (function() {
2559 switch (false) {
2560 case !this.isClass(node):
2561 return this.functionsOfClass(node);
2562 case !this.isCode(node):
2563 return [];
2564 default:
2565 return functions;
2566 }
2567 }).call(_this));
2568 };
2569 })(this));
2570 };
2571
2572 NoPrivateFunctionFatArrows.prototype.isCode = function(node) {
2573 return this.astApi.getNodeName(node) === 'Code';
2574 };
2575
2576 NoPrivateFunctionFatArrows.prototype.isClass = function(node) {
2577 return this.astApi.getNodeName(node) === 'Class';
2578 };
2579
2580 NoPrivateFunctionFatArrows.prototype.isValue = function(node) {
2581 return this.astApi.getNodeName(node) === 'Value';
2582 };
2583
2584 NoPrivateFunctionFatArrows.prototype.isObject = function(node) {
2585 return this.astApi.getNodeName(node) === 'Obj';
2586 };
2587
2588 NoPrivateFunctionFatArrows.prototype.isFatArrowCode = function(node) {
2589 return this.isCode(node) && node.bound;
2590 };
2591
2592 NoPrivateFunctionFatArrows.prototype.functionsOfClass = function(classNode) {
2593 var bodyNode, bodyValues;
2594 bodyValues = (function() {
2595 var i, len, ref, results;
2596 ref = classNode.body.expressions;
2597 results = [];
2598 for (i = 0, len = ref.length; i < len; i++) {
2599 bodyNode = ref[i];
2600 if (this.isValue(bodyNode) && this.isObject(bodyNode.base)) {
2601 continue;
2602 }
2603 results.push(bodyNode.value);
2604 }
2605 return results;
2606 }).call(this);
2607 return bodyValues.filter(this.isCode);
2608 };
2609
2610 return NoPrivateFunctionFatArrows;
2611
2612})();
2613
2614
2615},{}],33:[function(require,module,exports){
2616var NoStandAloneAt;
2617
2618module.exports = NoStandAloneAt = (function() {
2619 function NoStandAloneAt() {}
2620
2621 NoStandAloneAt.prototype.rule = {
2622 name: 'no_stand_alone_at',
2623 level: 'ignore',
2624 message: '@ must not be used stand alone',
2625 description: 'This rule checks that no stand alone @ are in use, they are\ndiscouraged. Further information in CoffeeScript issue <a\nhref="https://github.com/jashkenas/coffee-script/issues/1601">\n#1601</a>'
2626 };
2627
2628 NoStandAloneAt.prototype.tokens = ['@'];
2629
2630 NoStandAloneAt.prototype.lintToken = function(token, tokenApi) {
2631 var isAStart, isDot, isProp, isProtoProp, nextToken, noSpace, ref, ref1;
2632 nextToken = tokenApi.peek()[0];
2633 noSpace = !token.spaced;
2634 isProp = nextToken === 'IDENTIFIER' || nextToken === 'PROPERTY';
2635 isAStart = nextToken === 'INDEX_START' || nextToken === 'CALL_START';
2636 isDot = nextToken === '.';
2637 isProtoProp = nextToken === '::' && ((ref = (ref1 = tokenApi.peek(2)) != null ? ref1[0] : void 0) === 'IDENTIFIER' || ref === 'PROPERTY');
2638 if (!(isDot || (noSpace && (isProp || isAStart || isProtoProp)))) {
2639 return true;
2640 }
2641 };
2642
2643 return NoStandAloneAt;
2644
2645})();
2646
2647
2648},{}],34:[function(require,module,exports){
2649var NoTabs, indentationRegex,
2650 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
2651
2652indentationRegex = /\S/;
2653
2654module.exports = NoTabs = (function() {
2655 function NoTabs() {}
2656
2657 NoTabs.prototype.rule = {
2658 name: 'no_tabs',
2659 level: 'error',
2660 message: 'Line contains tab indentation',
2661 description: 'This rule forbids tabs in indentation. Enough said. It is enabled by\ndefault.'
2662 };
2663
2664 NoTabs.prototype.lintLine = function(line, lineApi) {
2665 var indentation;
2666 indentation = line.split(indentationRegex)[0];
2667 if (lineApi.lineHasToken() && indexOf.call(indentation, '\t') >= 0) {
2668 return true;
2669 } else {
2670 return null;
2671 }
2672 };
2673
2674 return NoTabs;
2675
2676})();
2677
2678
2679},{}],35:[function(require,module,exports){
2680var NoThis;
2681
2682module.exports = NoThis = (function() {
2683 function NoThis() {}
2684
2685 NoThis.prototype.rule = {
2686 name: 'no_this',
2687 level: 'ignore',
2688 message: "Don't use 'this', use '@' instead",
2689 description: 'This rule prohibits \'this\'.\nUse \'@\' instead.'
2690 };
2691
2692 NoThis.prototype.tokens = ['THIS'];
2693
2694 NoThis.prototype.lintToken = function(token, tokenApi) {
2695 var level, nextToken, ref;
2696 level = tokenApi.config.no_stand_alone_at.level;
2697 nextToken = (ref = tokenApi.peek(1)) != null ? ref[0] : void 0;
2698 if (!(level !== 'ignore' && nextToken !== '.')) {
2699 return true;
2700 }
2701 };
2702
2703 return NoThis;
2704
2705})();
2706
2707
2708},{}],36:[function(require,module,exports){
2709var NoThrowingStrings;
2710
2711module.exports = NoThrowingStrings = (function() {
2712 function NoThrowingStrings() {}
2713
2714 NoThrowingStrings.prototype.rule = {
2715 name: 'no_throwing_strings',
2716 level: 'error',
2717 message: 'Throwing strings is forbidden',
2718 description: 'This rule forbids throwing string literals or interpolations. While\nJavaScript (and CoffeeScript by extension) allow any expression to\nbe thrown, it is best to only throw <a\nhref="https://developer.mozilla.org\n/en/JavaScript/Reference/Global_Objects/Error"> Error</a> objects,\nbecause they contain valuable debugging information like the stack\ntrace. Because of JavaScript\'s dynamic nature, CoffeeLint cannot\nensure you are always throwing instances of <tt>Error</tt>. It will\nonly catch the simple but real case of throwing literal strings.\n<pre>\n<code># CoffeeLint will catch this:\nthrow "i made a boo boo"\n\n# ... but not this:\nthrow getSomeString()\n</code>\n</pre>\nThis rule is enabled by default.'
2719 };
2720
2721 NoThrowingStrings.prototype.tokens = ['THROW'];
2722
2723 NoThrowingStrings.prototype.lintToken = function(token, tokenApi) {
2724 var n1, nextIsString, ref;
2725 ref = tokenApi.peek(), n1 = ref[0];
2726 nextIsString = n1 === 'STRING' || n1 === 'STRING_START';
2727 return nextIsString;
2728 };
2729
2730 return NoThrowingStrings;
2731
2732})();
2733
2734
2735},{}],37:[function(require,module,exports){
2736var NoTrailingSemicolons, regexes,
2737 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; },
2738 slice = [].slice;
2739
2740regexes = {
2741 trailingSemicolon: /;\r?$/
2742};
2743
2744module.exports = NoTrailingSemicolons = (function() {
2745 function NoTrailingSemicolons() {}
2746
2747 NoTrailingSemicolons.prototype.rule = {
2748 name: 'no_trailing_semicolons',
2749 level: 'error',
2750 message: 'Line contains a trailing semicolon',
2751 description: 'This rule prohibits trailing semicolons, since they are needless\ncruft in CoffeeScript.\n<pre>\n<code># This semicolon is meaningful.\nx = \'1234\'; console.log(x)\n\n# This semicolon is redundant.\nalert(\'end of line\');\n</code>\n</pre>\nTrailing semicolons are forbidden by default.'
2752 };
2753
2754 NoTrailingSemicolons.prototype.lintLine = function(line, lineApi) {
2755 var endPos, first, hasNewLine, hasSemicolon, i, last, lineTokens, newLine, ref, ref1, startCounter, startPos, stopTokens, tokenLen;
2756 lineTokens = lineApi.getLineTokens();
2757 tokenLen = lineTokens.length;
2758 stopTokens = ['TERMINATOR', 'HERECOMMENT'];
2759 if (tokenLen === 1 && (ref = lineTokens[0][0], indexOf.call(stopTokens, ref) >= 0)) {
2760 return;
2761 }
2762 newLine = line;
2763 if (tokenLen > 1 && lineTokens[tokenLen - 1][0] === 'TERMINATOR') {
2764 startPos = lineTokens[tokenLen - 2][2].last_column + 1;
2765 endPos = lineTokens[tokenLen - 1][2].first_column;
2766 if (startPos !== endPos) {
2767 startCounter = startPos;
2768 while (line[startCounter] !== '#' && startCounter < line.length) {
2769 startCounter++;
2770 }
2771 newLine = line.substring(0, startCounter).replace(/\s*$/, '');
2772 }
2773 }
2774 hasSemicolon = regexes.trailingSemicolon.test(newLine);
2775 first = 2 <= lineTokens.length ? slice.call(lineTokens, 0, i = lineTokens.length - 1) : (i = 0, []), last = lineTokens[i++];
2776 hasNewLine = last && (last.newLine != null);
2777 if (hasSemicolon && !hasNewLine && lineApi.lineHasToken() && !((ref1 = last[0]) === 'STRING' || ref1 === 'IDENTIFIER' || ref1 === 'STRING_END')) {
2778 return true;
2779 }
2780 };
2781
2782 return NoTrailingSemicolons;
2783
2784})();
2785
2786
2787},{}],38:[function(require,module,exports){
2788var NoTrailingWhitespace, regexes;
2789
2790regexes = {
2791 trailingWhitespace: /[^\s]+[\t ]+\r?$/,
2792 onlySpaces: /^[\t ]+\r?$/,
2793 lineHasComment: /^\s*[^\#]*\#/
2794};
2795
2796module.exports = NoTrailingWhitespace = (function() {
2797 function NoTrailingWhitespace() {}
2798
2799 NoTrailingWhitespace.prototype.rule = {
2800 name: 'no_trailing_whitespace',
2801 level: 'error',
2802 message: 'Line ends with trailing whitespace',
2803 allowed_in_comments: false,
2804 allowed_in_empty_lines: true,
2805 description: 'This rule forbids trailing whitespace in your code, since it is\nneedless cruft. It is enabled by default.'
2806 };
2807
2808 NoTrailingWhitespace.prototype.lintLine = function(line, lineApi) {
2809 var i, len, ref, ref1, ref2, str, token, tokens;
2810 if (!((ref = lineApi.config['no_trailing_whitespace']) != null ? ref.allowed_in_empty_lines : void 0)) {
2811 if (regexes.onlySpaces.test(line)) {
2812 return true;
2813 }
2814 }
2815 if (regexes.trailingWhitespace.test(line)) {
2816 if (!((ref1 = lineApi.config['no_trailing_whitespace']) != null ? ref1.allowed_in_comments : void 0)) {
2817 return true;
2818 }
2819 line = line;
2820 tokens = lineApi.tokensByLine[lineApi.lineNumber];
2821 if (!tokens) {
2822 return null;
2823 }
2824 ref2 = (function() {
2825 var j, len, results;
2826 results = [];
2827 for (j = 0, len = tokens.length; j < len; j++) {
2828 token = tokens[j];
2829 if (token[0] === 'STRING') {
2830 results.push(token[1]);
2831 }
2832 }
2833 return results;
2834 })();
2835 for (i = 0, len = ref2.length; i < len; i++) {
2836 str = ref2[i];
2837 line = line.replace(str, 'STRING');
2838 }
2839 if (!regexes.lineHasComment.test(line)) {
2840 return true;
2841 }
2842 }
2843 };
2844
2845 return NoTrailingWhitespace;
2846
2847})();
2848
2849
2850},{}],39:[function(require,module,exports){
2851var NoUnnecessaryDoubleQuotes;
2852
2853module.exports = NoUnnecessaryDoubleQuotes = (function() {
2854 NoUnnecessaryDoubleQuotes.prototype.rule = {
2855 name: 'no_unnecessary_double_quotes',
2856 level: 'ignore',
2857 message: 'Unnecessary double quotes are forbidden',
2858 description: 'This rule prohibits double quotes unless string interpolation is\nused or the string contains single quotes.\n<pre>\n<code># Double quotes are discouraged:\nfoo = "bar"\n\n# Unless string interpolation is used:\nfoo = "#{bar}baz"\n\n# Or they prevent cumbersome escaping:\nfoo = "I\'m just following the \'rules\'"\n</code>\n</pre>\nDouble quotes are permitted by default.'
2859 };
2860
2861 function NoUnnecessaryDoubleQuotes() {
2862 this.regexps = [];
2863 this.interpolationLevel = 0;
2864 }
2865
2866 NoUnnecessaryDoubleQuotes.prototype.tokens = ['STRING', 'STRING_START', 'STRING_END'];
2867
2868 NoUnnecessaryDoubleQuotes.prototype.lintToken = function(token, tokenApi) {
2869 var hasLegalConstructs, ref, stringValue, tokenValue, type;
2870 type = token[0], tokenValue = token[1];
2871 if (type === 'STRING_START' || type === 'STRING_END') {
2872 return this.trackParens.apply(this, arguments);
2873 }
2874 stringValue = tokenValue.match(/^\"(.*)\"$/);
2875 if (!stringValue) {
2876 return false;
2877 }
2878 if (((ref = tokenApi.peek(2)) != null ? ref[0] : void 0) === 'REGEX_END') {
2879 return false;
2880 }
2881 hasLegalConstructs = this.isInInterpolation() || this.hasSingleQuote(tokenValue);
2882 return !hasLegalConstructs;
2883 };
2884
2885 NoUnnecessaryDoubleQuotes.prototype.isInInterpolation = function() {
2886 return this.interpolationLevel > 0;
2887 };
2888
2889 NoUnnecessaryDoubleQuotes.prototype.trackParens = function(token, tokenApi) {
2890 if (token[0] === 'STRING_START') {
2891 this.interpolationLevel += 1;
2892 } else if (token[0] === 'STRING_END') {
2893 this.interpolationLevel -= 1;
2894 }
2895 return null;
2896 };
2897
2898 NoUnnecessaryDoubleQuotes.prototype.hasSingleQuote = function(tokenValue) {
2899 return tokenValue.indexOf("'") !== -1;
2900 };
2901
2902 return NoUnnecessaryDoubleQuotes;
2903
2904})();
2905
2906
2907},{}],40:[function(require,module,exports){
2908var NoUnnecessaryFatArrows, any,
2909 bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
2910
2911any = function(arr, test) {
2912 return arr.reduce((function(res, elt) {
2913 return res || test(elt);
2914 }), false);
2915};
2916
2917module.exports = NoUnnecessaryFatArrows = (function() {
2918 function NoUnnecessaryFatArrows() {
2919 this.needsFatArrow = bind(this.needsFatArrow, this);
2920 this.isThis = bind(this.isThis, this);
2921 }
2922
2923 NoUnnecessaryFatArrows.prototype.rule = {
2924 name: 'no_unnecessary_fat_arrows',
2925 level: 'warn',
2926 message: 'Unnecessary fat arrow',
2927 description: 'Disallows defining functions with fat arrows when `this`\nis not used within the function.'
2928 };
2929
2930 NoUnnecessaryFatArrows.prototype.lintAST = function(node, astApi) {
2931 this.astApi = astApi;
2932 this.lintNode(node);
2933 return void 0;
2934 };
2935
2936 NoUnnecessaryFatArrows.prototype.lintNode = function(node) {
2937 var error;
2938 if ((this.isFatArrowCode(node)) && (!this.needsFatArrow(node))) {
2939 error = this.astApi.createError({
2940 lineNumber: node.locationData.first_line + 1
2941 });
2942 this.errors.push(error);
2943 }
2944 return node.eachChild((function(_this) {
2945 return function(child) {
2946 return _this.lintNode(child);
2947 };
2948 })(this));
2949 };
2950
2951 NoUnnecessaryFatArrows.prototype.isCode = function(node) {
2952 return this.astApi.getNodeName(node) === 'Code';
2953 };
2954
2955 NoUnnecessaryFatArrows.prototype.isFatArrowCode = function(node) {
2956 return this.isCode(node) && node.bound;
2957 };
2958
2959 NoUnnecessaryFatArrows.prototype.isValue = function(node) {
2960 return this.astApi.getNodeName(node) === 'Value';
2961 };
2962
2963 NoUnnecessaryFatArrows.prototype.isThis = function(node) {
2964 var ref;
2965 return ((ref = node.constructor) != null ? ref.name : void 0) === 'ThisLiteral' || this.isValue(node) && node.base.value === 'this';
2966 };
2967
2968 NoUnnecessaryFatArrows.prototype.needsFatArrow = function(node) {
2969 return this.isCode(node) && (any(node.params, (function(_this) {
2970 return function(param) {
2971 return param.contains(_this.isThis) != null;
2972 };
2973 })(this)) || (node.body.contains(this.isThis) != null) || (node.body.contains((function(_this) {
2974 return function(child) {
2975 var ref;
2976 if (!_this.astApi.getNodeName(child)) {
2977 return ((ref = child.constructor) != null ? ref.name : void 0) === 'SuperCall' || ((child.isSuper != null) && child.isSuper);
2978 } else {
2979 return _this.isFatArrowCode(child) && _this.needsFatArrow(child);
2980 }
2981 };
2982 })(this)) != null));
2983 };
2984
2985 return NoUnnecessaryFatArrows;
2986
2987})();
2988
2989
2990},{}],41:[function(require,module,exports){
2991var NonEmptyConstructorNeedsParens, ParentClass,
2992 extend = function(child, parent) { for (var key in parent) { if (hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
2993 hasProp = {}.hasOwnProperty;
2994
2995ParentClass = require('./empty_constructor_needs_parens.coffee');
2996
2997module.exports = NonEmptyConstructorNeedsParens = (function(superClass) {
2998 extend(NonEmptyConstructorNeedsParens, superClass);
2999
3000 function NonEmptyConstructorNeedsParens() {
3001 return NonEmptyConstructorNeedsParens.__super__.constructor.apply(this, arguments);
3002 }
3003
3004 NonEmptyConstructorNeedsParens.prototype.rule = {
3005 name: 'non_empty_constructor_needs_parens',
3006 level: 'ignore',
3007 message: 'Invoking a constructor without parens and with arguments',
3008 description: 'Requires constructors with parameters to include the parens'
3009 };
3010
3011 NonEmptyConstructorNeedsParens.prototype.handleExpectedCallStart = function(isCallStart) {
3012 if (isCallStart[0] === 'CALL_START' && isCallStart.generated) {
3013 return true;
3014 }
3015 };
3016
3017 return NonEmptyConstructorNeedsParens;
3018
3019})(ParentClass);
3020
3021
3022},{"./empty_constructor_needs_parens.coffee":15}],42:[function(require,module,exports){
3023var PreferEnglishOperator;
3024
3025module.exports = PreferEnglishOperator = (function() {
3026 function PreferEnglishOperator() {}
3027
3028 PreferEnglishOperator.prototype.rule = {
3029 name: 'prefer_english_operator',
3030 level: 'ignore',
3031 message: 'Don\'t use &&, ||, ==, !=, or !',
3032 doubleNotLevel: 'ignore',
3033 description: 'This rule prohibits &&, ||, ==, != and !.\nUse and, or, is, isnt, and not instead.\n!! for converting to a boolean is ignored.'
3034 };
3035
3036 PreferEnglishOperator.prototype.tokens = ['COMPARE', 'UNARY_MATH', '&&', '||'];
3037
3038 PreferEnglishOperator.prototype.lintToken = function(token, tokenApi) {
3039 var actual_token, config, context, first_column, last_column, level, line, ref;
3040 config = tokenApi.config[this.rule.name];
3041 level = config.level;
3042 ref = token[2], first_column = ref.first_column, last_column = ref.last_column;
3043 line = tokenApi.lines[tokenApi.lineNumber];
3044 actual_token = line.slice(first_column, +last_column + 1 || 9e9);
3045 context = (function() {
3046 var ref1, ref2;
3047 switch (actual_token) {
3048 case '==':
3049 return 'Replace "==" with "is"';
3050 case '!=':
3051 return 'Replace "!=" with "isnt"';
3052 case '||':
3053 return 'Replace "||" with "or"';
3054 case '&&':
3055 return 'Replace "&&" with "and"';
3056 case '!':
3057 if (((ref1 = tokenApi.peek(1)) != null ? ref1[0] : void 0) === 'UNARY_MATH') {
3058 level = config.doubleNotLevel;
3059 return '"?" is usually better than "!!"';
3060 } else if (((ref2 = tokenApi.peek(-1)) != null ? ref2[0] : void 0) === 'UNARY_MATH') {
3061 return void 0;
3062 } else {
3063 return 'Replace "!" with "not"';
3064 }
3065 break;
3066 default:
3067 return void 0;
3068 }
3069 })();
3070 if (context != null) {
3071 return {
3072 level: level,
3073 context: context
3074 };
3075 }
3076 };
3077
3078 return PreferEnglishOperator;
3079
3080})();
3081
3082
3083},{}],43:[function(require,module,exports){
3084var SpaceOperators,
3085 slice = [].slice,
3086 indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
3087
3088module.exports = SpaceOperators = (function() {
3089 SpaceOperators.prototype.rule = {
3090 name: 'space_operators',
3091 level: 'ignore',
3092 message: 'Operators must be spaced properly',
3093 description: 'This rule enforces that operators have spaces around them.'
3094 };
3095
3096 SpaceOperators.prototype.tokens = ['+', '-', '=', '**', 'MATH', 'COMPARE', '&', '^', '|', '&&', '||', 'COMPOUND_ASSIGN', 'STRING_START', 'STRING_END', 'CALL_START', 'CALL_END'];
3097
3098 function SpaceOperators() {
3099 this.callTokens = [];
3100 this.parenTokens = [];
3101 this.interpolationLevel = 0;
3102 }
3103
3104 SpaceOperators.prototype.lintToken = function(token, tokenApi) {
3105 var rest, type;
3106 type = token[0], rest = 2 <= token.length ? slice.call(token, 1) : [];
3107 if (type === 'CALL_START' || type === 'CALL_END') {
3108 this.trackCall(token, tokenApi);
3109 return;
3110 }
3111 if (type === 'STRING_START' || type === 'STRING_END') {
3112 return this.trackParens(token, tokenApi);
3113 }
3114 if (type === '+' || type === '-') {
3115 return this.lintPlus(token, tokenApi);
3116 } else {
3117 return this.lintMath(token, tokenApi);
3118 }
3119 };
3120
3121 SpaceOperators.prototype.lintPlus = function(token, tokenApi) {
3122 var isUnary, notFirstToken, p, ref, unaries;
3123 if (this.isInInterpolation() || this.isInExtendedRegex()) {
3124 return null;
3125 }
3126 p = tokenApi.peek(-1);
3127 unaries = ['TERMINATOR', '(', '=', '-', '+', ',', 'CALL_START', 'INDEX_START', '..', '...', 'COMPARE', 'IF', 'THROW', '&', '^', '|', '&&', '||', 'POST_IF', ':', '[', 'INDENT', 'COMPOUND_ASSIGN', 'RETURN', 'MATH', 'BY', 'LEADING_WHEN'];
3128 isUnary = !p ? false : (ref = p[0], indexOf.call(unaries, ref) >= 0);
3129 notFirstToken = p || (token.spaced != null) || token.newLine;
3130 if (notFirstToken && ((isUnary && (token.spaced != null)) || (!isUnary && !token.newLine && (!token.spaced || (p && !p.spaced))))) {
3131 return {
3132 context: token[1]
3133 };
3134 } else {
3135 return null;
3136 }
3137 };
3138
3139 SpaceOperators.prototype.lintMath = function(token, tokenApi) {
3140 var p;
3141 p = tokenApi.peek(-1);
3142 if (!token.newLine && (!token.spaced || (p && !p.spaced))) {
3143 return {
3144 context: token[1]
3145 };
3146 } else {
3147 return null;
3148 }
3149 };
3150
3151 SpaceOperators.prototype.isInExtendedRegex = function() {
3152 var i, len, ref, t;
3153 ref = this.callTokens;
3154 for (i = 0, len = ref.length; i < len; i++) {
3155 t = ref[i];
3156 if (t.isRegex) {
3157 return true;
3158 }
3159 }
3160 return false;
3161 };
3162
3163 SpaceOperators.prototype.isInInterpolation = function() {
3164 return this.interpolationLevel > 0;
3165 };
3166
3167 SpaceOperators.prototype.trackCall = function(token, tokenApi) {
3168 var p;
3169 if (token[0] === 'CALL_START') {
3170 p = tokenApi.peek(-1);
3171 token.isRegex = p && p[0] === 'IDENTIFIER' && p[1] === 'RegExp';
3172 this.callTokens.push(token);
3173 } else {
3174 this.callTokens.pop();
3175 }
3176 return null;
3177 };
3178
3179 SpaceOperators.prototype.trackParens = function(token, tokenApi) {
3180 if (token[0] === 'STRING_START') {
3181 this.interpolationLevel += 1;
3182 } else if (token[0] === 'STRING_END') {
3183 this.interpolationLevel -= 1;
3184 }
3185 return null;
3186 };
3187
3188 return SpaceOperators;
3189
3190})();
3191
3192
3193},{}],44:[function(require,module,exports){
3194var SpacingAfterComma;
3195
3196module.exports = SpacingAfterComma = (function() {
3197 SpacingAfterComma.prototype.rule = {
3198 name: 'spacing_after_comma',
3199 level: 'ignore',
3200 message: 'a space is required after commas',
3201 description: 'This rule checks to make sure you have a space after commas.'
3202 };
3203
3204 SpacingAfterComma.prototype.tokens = [',', 'REGEX_START', 'REGEX_END'];
3205
3206 function SpacingAfterComma() {
3207 this.inRegex = false;
3208 }
3209
3210 SpacingAfterComma.prototype.lintToken = function(token, tokenApi) {
3211 var type;
3212 type = token[0];
3213 if (type === 'REGEX_START') {
3214 this.inRegex = true;
3215 return;
3216 }
3217 if (type === 'REGEX_END') {
3218 this.inRegex = false;
3219 return;
3220 }
3221 if (!(token.spaced || token.newLine || token.generated || this.isRegexFlag(token, tokenApi))) {
3222 return true;
3223 }
3224 };
3225
3226 SpacingAfterComma.prototype.isRegexFlag = function(token, tokenApi) {
3227 var maybeEnd;
3228 if (!this.inRegex) {
3229 return false;
3230 }
3231 maybeEnd = tokenApi.peek(3);
3232 return (maybeEnd != null ? maybeEnd[0] : void 0) === 'REGEX_END';
3233 };
3234
3235 return SpacingAfterComma;
3236
3237})();
3238
3239
3240},{}],45:[function(require,module,exports){
3241var TransformMessesUpLineNumbers;
3242
3243module.exports = TransformMessesUpLineNumbers = (function() {
3244 function TransformMessesUpLineNumbers() {}
3245
3246 TransformMessesUpLineNumbers.prototype.rule = {
3247 name: 'transform_messes_up_line_numbers',
3248 level: 'warn',
3249 message: 'Transforming source messes up line numbers',
3250 description: 'This rule detects when changes are made by transform function,\nand warns that line numbers are probably incorrect.'
3251 };
3252
3253 TransformMessesUpLineNumbers.prototype.tokens = [];
3254
3255 TransformMessesUpLineNumbers.prototype.lintToken = function(token, tokenApi) {};
3256
3257 return TransformMessesUpLineNumbers;
3258
3259})();
3260
3261
3262},{}]},{},[4])(4)
3263});
\No newline at end of file