coffeelint 1.11.0 → 1.14.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/coffeelint/lib/coffeelint.js +278 -155
- data/lib/coffeelint.rb +29 -19
- data/lib/coffeelint/cmd.rb +4 -2
- data/lib/coffeelint/version.rb +1 -1
- data/spec/coffeelint_spec.rb +55 -0
- metadata +34 -22
- checksums.yaml +0 -7
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Coffeelint [![Build Status](https://travis-ci.org/zmbush/coffeelint-ruby.svg?branch=master)](https://travis-ci.org/zmbush/coffeelint-ruby) [![Gem Version](https://badge.fury.io/rb/coffeelint.png)](http://badge.fury.io/rb/coffeelint)
|
2
2
|
|
3
|
-
Using coffeelint version: v1.
|
3
|
+
Using coffeelint version: v1.14.0
|
4
4
|
|
5
5
|
Coffeelint is a set of simple ruby bindings for [coffeelint](https://github.com/clutchski/coffeelint).
|
6
6
|
|
@@ -82,7 +82,7 @@ mergeDefaultConfig = function(userConfig) {
|
|
82
82
|
try {
|
83
83
|
ruleLoader = nodeRequire('./ruleLoader');
|
84
84
|
ruleLoader.loadFromConfig(coffeelint, userConfig);
|
85
|
-
} catch (
|
85
|
+
} catch (undefined) {}
|
86
86
|
config = {};
|
87
87
|
if (userConfig.coffeelint) {
|
88
88
|
config.coffeelint = userConfig.coffeelint;
|
@@ -141,8 +141,8 @@ coffeelint.trimConfig = function(userConfig) {
|
|
141
141
|
coffeelint.invertLiterate = function(source) {
|
142
142
|
var len, line, n, newSource, ref;
|
143
143
|
source = CoffeeScript.helpers.invertLiterate(source);
|
144
|
-
newSource =
|
145
|
-
ref = source.split(
|
144
|
+
newSource = '';
|
145
|
+
ref = source.split('\n');
|
146
146
|
for (n = 0, len = ref.length; n < len; n++) {
|
147
147
|
line = ref[n];
|
148
148
|
if (line.match(/^#/)) {
|
@@ -162,24 +162,24 @@ coffeelint.registerRule = function(RuleConstructor, ruleName) {
|
|
162
162
|
ruleName = void 0;
|
163
163
|
}
|
164
164
|
p = new RuleConstructor;
|
165
|
-
name = (p != null ? (ref = p.rule) != null ? ref.name : void 0 : void 0) ||
|
165
|
+
name = (p != null ? (ref = p.rule) != null ? ref.name : void 0 : void 0) || '(unknown)';
|
166
166
|
e = function(msg) {
|
167
167
|
throw new Error("Invalid rule: " + name + " " + msg);
|
168
168
|
};
|
169
169
|
if (p.rule == null) {
|
170
|
-
e(
|
170
|
+
e('Rules must provide rule attribute with a default configuration.');
|
171
171
|
}
|
172
172
|
if (p.rule.name == null) {
|
173
|
-
e(
|
173
|
+
e('Rule defaults require a name');
|
174
174
|
}
|
175
175
|
if ((ruleName != null) && ruleName !== p.rule.name) {
|
176
176
|
e("Mismatched rule name: " + ruleName);
|
177
177
|
}
|
178
178
|
if (p.rule.message == null) {
|
179
|
-
e(
|
179
|
+
e('Rule defaults require a message');
|
180
180
|
}
|
181
181
|
if (p.rule.description == null) {
|
182
|
-
e(
|
182
|
+
e('Rule defaults require a description');
|
183
183
|
}
|
184
184
|
if ((ref1 = p.rule.level) !== 'ignore' && ref1 !== 'warn' && ref1 !== 'error') {
|
185
185
|
e("Default level must be 'ignore', 'warn', or 'error'");
|
@@ -189,7 +189,7 @@ coffeelint.registerRule = function(RuleConstructor, ruleName) {
|
|
189
189
|
e("'tokens' is required for 'lintToken'");
|
190
190
|
}
|
191
191
|
} else if (typeof p.lintLine !== 'function' && typeof p.lintAST !== 'function') {
|
192
|
-
e(
|
192
|
+
e('Rules must implement lintToken, lintLine, or lintAST');
|
193
193
|
}
|
194
194
|
RULES[p.rule.name] = p.rule;
|
195
195
|
return _rules[p.rule.name] = RuleConstructor;
|
@@ -284,7 +284,7 @@ hasSyntaxError = function(source) {
|
|
284
284
|
try {
|
285
285
|
CoffeeScript.tokens(source);
|
286
286
|
return false;
|
287
|
-
} catch (
|
287
|
+
} catch (undefined) {}
|
288
288
|
return true;
|
289
289
|
};
|
290
290
|
|
@@ -314,7 +314,7 @@ coffeelint.lint = function(source, userConfig, literate) {
|
|
314
314
|
source = this.invertLiterate(source);
|
315
315
|
}
|
316
316
|
if ((userConfig != null ? (ref = userConfig.coffeelint) != null ? ref.transforms : void 0 : void 0) != null) {
|
317
|
-
sourceLength = source.split(
|
317
|
+
sourceLength = source.split('\n').length;
|
318
318
|
ref2 = userConfig != null ? (ref1 = userConfig.coffeelint) != null ? ref1.transforms : void 0 : void 0;
|
319
319
|
for (n = 0, len = ref2.length; n < len; n++) {
|
320
320
|
m = ref2[n];
|
@@ -322,9 +322,9 @@ coffeelint.lint = function(source, userConfig, literate) {
|
|
322
322
|
ruleLoader = nodeRequire('./ruleLoader');
|
323
323
|
transform = ruleLoader.require(m);
|
324
324
|
source = transform(source);
|
325
|
-
} catch (
|
325
|
+
} catch (undefined) {}
|
326
326
|
}
|
327
|
-
if (sourceLength !== source.split(
|
327
|
+
if (sourceLength !== source.split('\n').length && config.transform_messes_up_line_numbers.level !== 'ignore') {
|
328
328
|
errors.push(extend({
|
329
329
|
lineNumber: 1,
|
330
330
|
context: "File was transformed from " + sourceLength + " lines to " + (source.split("\n").length) + " lines"
|
@@ -429,7 +429,7 @@ coffeelint.setCache = function(obj) {
|
|
429
429
|
module.exports={
|
430
430
|
"name": "coffeelint",
|
431
431
|
"description": "Lint your CoffeeScript",
|
432
|
-
"version": "1.
|
432
|
+
"version": "1.14.0",
|
433
433
|
"homepage": "http://www.coffeelint.org",
|
434
434
|
"keywords": [
|
435
435
|
"lint",
|
@@ -470,6 +470,7 @@ module.exports={
|
|
470
470
|
"testrule": "npm run compile && ./vowsrunner.js --spec",
|
471
471
|
"posttest": "npm run lint",
|
472
472
|
"prepublish": "cake prepublish",
|
473
|
+
"postpublish": "cake postpublish",
|
473
474
|
"publish": "cake publish",
|
474
475
|
"install": "cake install",
|
475
476
|
"lint": "cake compile && ./bin/coffeelint .",
|
@@ -545,12 +546,12 @@ module.exports = ASTLinter = (function(superClass) {
|
|
545
546
|
};
|
546
547
|
|
547
548
|
ASTLinter.prototype.lint = function() {
|
548
|
-
var coffeeError, err, errors, j, len, ref, rule, v;
|
549
|
+
var coffeeError, err, error, errors, j, len, ref, rule, v;
|
549
550
|
errors = [];
|
550
551
|
try {
|
551
552
|
this.node = this.CoffeeScript.nodes(this.source);
|
552
|
-
} catch (
|
553
|
-
coffeeError =
|
553
|
+
} catch (error) {
|
554
|
+
coffeeError = error;
|
554
555
|
err = this._parseCoffeeScriptError(coffeeError);
|
555
556
|
if (err != null) {
|
556
557
|
errors.push(err);
|
@@ -646,7 +647,7 @@ module.exports = BaseLinter = (function() {
|
|
646
647
|
}
|
647
648
|
level = attrs.level;
|
648
649
|
if (level !== 'ignore' && level !== 'warn' && level !== 'error') {
|
649
|
-
throw new Error("unknown level " + level);
|
650
|
+
throw new Error("unknown level " + level + " for rule: " + ruleName);
|
650
651
|
}
|
651
652
|
if (level === 'error' || level === 'warn') {
|
652
653
|
attrs.rule = ruleName;
|
@@ -657,7 +658,7 @@ module.exports = BaseLinter = (function() {
|
|
657
658
|
};
|
658
659
|
|
659
660
|
BaseLinter.prototype.acceptRule = function(rule) {
|
660
|
-
throw new Error(
|
661
|
+
throw new Error('acceptRule needs to be overridden in the subclass');
|
661
662
|
};
|
662
663
|
|
663
664
|
BaseLinter.prototype.setupRules = function(rules) {
|
@@ -675,7 +676,7 @@ module.exports = BaseLinter = (function() {
|
|
675
676
|
results.push(void 0);
|
676
677
|
}
|
677
678
|
} else if (level !== 'ignore') {
|
678
|
-
throw new Error("unknown level " + level);
|
679
|
+
throw new Error("unknown level " + level + " for rule: " + rule);
|
679
680
|
} else {
|
680
681
|
results.push(void 0);
|
681
682
|
}
|
@@ -851,15 +852,8 @@ module.exports = LexicalLinter = (function(superClass) {
|
|
851
852
|
};
|
852
853
|
|
853
854
|
LexicalLinter.prototype.lintToken = function(token) {
|
854
|
-
var base, errors, j, len, lineNumber, ref, ref1, rule, type, v, value;
|
855
|
-
type = token[0], value = token[1],
|
856
|
-
if (typeof lineNumber === "object") {
|
857
|
-
if (type === 'OUTDENT' || type === 'INDENT') {
|
858
|
-
lineNumber = lineNumber.last_line;
|
859
|
-
} else {
|
860
|
-
lineNumber = lineNumber.first_line;
|
861
|
-
}
|
862
|
-
}
|
855
|
+
var base, errors, j, len, lineNumber, ref, ref1, ref2, rule, type, v, value;
|
856
|
+
type = token[0], value = token[1], (ref = token[2], lineNumber = ref.first_line);
|
863
857
|
if ((base = this.tokensByLine)[lineNumber] == null) {
|
864
858
|
base[lineNumber] = [];
|
865
859
|
}
|
@@ -867,10 +861,10 @@ module.exports = LexicalLinter = (function(superClass) {
|
|
867
861
|
this.lineNumber = lineNumber || this.lineNumber || 0;
|
868
862
|
this.tokenApi.lineNumber = this.lineNumber;
|
869
863
|
errors = [];
|
870
|
-
|
871
|
-
for (j = 0, len =
|
872
|
-
rule =
|
873
|
-
if (!(
|
864
|
+
ref1 = this.rules;
|
865
|
+
for (j = 0, len = ref1.length; j < len; j++) {
|
866
|
+
rule = ref1[j];
|
867
|
+
if (!(ref2 = token[0], indexOf.call(rule.tokens, ref2) >= 0)) {
|
874
868
|
continue;
|
875
869
|
}
|
876
870
|
v = this.normalizeResult(rule, rule.lintToken(token, this.tokenApi));
|
@@ -885,8 +879,11 @@ module.exports = LexicalLinter = (function(superClass) {
|
|
885
879
|
if (attrs == null) {
|
886
880
|
attrs = {};
|
887
881
|
}
|
888
|
-
attrs.lineNumber
|
889
|
-
|
882
|
+
if (attrs.lineNumber == null) {
|
883
|
+
attrs.lineNumber = this.lineNumber;
|
884
|
+
}
|
885
|
+
attrs.lineNumber += 1;
|
886
|
+
attrs.line = this.tokenApi.lines[attrs.lineNumber - 1];
|
890
887
|
return LexicalLinter.__super__.createError.call(this, ruleName, attrs);
|
891
888
|
};
|
892
889
|
|
@@ -935,7 +932,7 @@ LineApi = (function() {
|
|
935
932
|
this.context["class"].classIndents = null;
|
936
933
|
}
|
937
934
|
}
|
938
|
-
if (
|
935
|
+
if (!line.match(/^\s*$/)) {
|
939
936
|
this.context["class"].lastUnemptyLineInClass = this.lineNumber;
|
940
937
|
}
|
941
938
|
} else {
|
@@ -1021,6 +1018,7 @@ module.exports = LineLinter = (function(superClass) {
|
|
1021
1018
|
for (lineNumber = i = 0, len = ref.length; i < len; lineNumber = ++i) {
|
1022
1019
|
line = ref[lineNumber];
|
1023
1020
|
this.lineApi.lineNumber = this.lineNumber = lineNumber;
|
1021
|
+
this.lineApi.line = this.lineApi.lines[lineNumber];
|
1024
1022
|
this.lineApi.maintainClassContext(line);
|
1025
1023
|
this.collectInlineConfig(line);
|
1026
1024
|
ref1 = this.lintLine(line);
|
@@ -1056,7 +1054,7 @@ module.exports = LineLinter = (function(superClass) {
|
|
1056
1054
|
ref = result[2].split(',');
|
1057
1055
|
for (i = 0, len = ref.length; i < len; i++) {
|
1058
1056
|
r = ref[i];
|
1059
|
-
rules.push(r.replace(/^\s+|\s+$/g,
|
1057
|
+
rules.push(r.replace(/^\s+|\s+$/g, ''));
|
1060
1058
|
}
|
1061
1059
|
}
|
1062
1060
|
this.block_config[cmd][this.lineNumber] = rules;
|
@@ -1108,7 +1106,7 @@ module.exports = ArrowSpacing = (function() {
|
|
1108
1106
|
name: 'arrow_spacing',
|
1109
1107
|
level: 'ignore',
|
1110
1108
|
message: 'Function arrows (-> and =>) must be spaced properly',
|
1111
|
-
description:
|
1109
|
+
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>'
|
1112
1110
|
};
|
1113
1111
|
|
1114
1112
|
ArrowSpacing.prototype.tokens = ['->', '=>'];
|
@@ -1119,28 +1117,15 @@ module.exports = ArrowSpacing = (function() {
|
|
1119
1117
|
if (!pp) {
|
1120
1118
|
return;
|
1121
1119
|
}
|
1122
|
-
if (!token.spaced &&
|
1120
|
+
if (!token.spaced && tokenApi.peek(1)[0] === 'INDENT' && tokenApi.peek(2)[0] === 'OUTDENT') {
|
1123
1121
|
return null;
|
1124
|
-
} else if (!(((token.spaced != null) || (token.newLine != null)
|
1122
|
+
} 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))))) {
|
1125
1123
|
return true;
|
1126
1124
|
} else {
|
1127
1125
|
return null;
|
1128
1126
|
}
|
1129
1127
|
};
|
1130
1128
|
|
1131
|
-
ArrowSpacing.prototype.atEof = function(tokenApi) {
|
1132
|
-
var i, j, len, ref, ref1, token, tokens;
|
1133
|
-
tokens = tokenApi.tokens, i = tokenApi.i;
|
1134
|
-
ref = tokens.slice(i + 1);
|
1135
|
-
for (j = 0, len = ref.length; j < len; j++) {
|
1136
|
-
token = ref[j];
|
1137
|
-
if (!(token.generated || ((ref1 = token[0]) === 'OUTDENT' || ref1 === 'TERMINATOR'))) {
|
1138
|
-
return false;
|
1139
|
-
}
|
1140
|
-
}
|
1141
|
-
return true;
|
1142
|
-
};
|
1143
|
-
|
1144
1129
|
return ArrowSpacing;
|
1145
1130
|
|
1146
1131
|
})();
|
@@ -1174,7 +1159,7 @@ module.exports = BracesSpacing = (function() {
|
|
1174
1159
|
while (true) {
|
1175
1160
|
totalDifference += difference;
|
1176
1161
|
nearestToken = tokenApi.peek(totalDifference);
|
1177
|
-
if (nearestToken[0] === 'OUTDENT') {
|
1162
|
+
if (nearestToken[0] === 'OUTDENT' || (nearestToken.generated != null)) {
|
1178
1163
|
continue;
|
1179
1164
|
}
|
1180
1165
|
return nearestToken;
|
@@ -1240,7 +1225,7 @@ module.exports = CamelCaseClasses = (function() {
|
|
1240
1225
|
name: 'camel_case_classes',
|
1241
1226
|
level: 'error',
|
1242
1227
|
message: 'Class name should be UpperCamelCased',
|
1243
|
-
description:
|
1228
|
+
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.'
|
1244
1229
|
};
|
1245
1230
|
|
1246
1231
|
CamelCaseClasses.prototype.tokens = ['CLASS'];
|
@@ -1288,7 +1273,7 @@ module.exports = ColonAssignmentSpacing = (function() {
|
|
1288
1273
|
left: 0,
|
1289
1274
|
right: 0
|
1290
1275
|
},
|
1291
|
-
description:
|
1276
|
+
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>'
|
1292
1277
|
};
|
1293
1278
|
|
1294
1279
|
ColonAssignmentSpacing.prototype.tokens = [':'];
|
@@ -1318,7 +1303,7 @@ module.exports = ColonAssignmentSpacing = (function() {
|
|
1318
1303
|
return null;
|
1319
1304
|
} else {
|
1320
1305
|
return {
|
1321
|
-
context: "Incorrect spacing around column " + token[2].first_column
|
1306
|
+
context: "Incorrect spacing around column " + token[2].first_column
|
1322
1307
|
};
|
1323
1308
|
}
|
1324
1309
|
};
|
@@ -1337,10 +1322,10 @@ module.exports = CyclomaticComplexity = (function() {
|
|
1337
1322
|
|
1338
1323
|
CyclomaticComplexity.prototype.rule = {
|
1339
1324
|
name: 'cyclomatic_complexity',
|
1340
|
-
value: 10,
|
1341
1325
|
level: 'ignore',
|
1342
1326
|
message: 'The cyclomatic complexity is too damn high',
|
1343
|
-
|
1327
|
+
value: 10,
|
1328
|
+
description: 'Examine the complexity of your function.'
|
1344
1329
|
};
|
1345
1330
|
|
1346
1331
|
CyclomaticComplexity.prototype.getComplexity = function(node) {
|
@@ -1356,16 +1341,16 @@ module.exports = CyclomaticComplexity = (function() {
|
|
1356
1341
|
return void 0;
|
1357
1342
|
};
|
1358
1343
|
|
1359
|
-
CyclomaticComplexity.prototype.lintNode = function(node
|
1344
|
+
CyclomaticComplexity.prototype.lintNode = function(node) {
|
1360
1345
|
var complexity, error, name, ref, rule;
|
1361
1346
|
name = (ref = this.astApi) != null ? ref.getNodeName(node) : void 0;
|
1362
1347
|
complexity = this.getComplexity(node);
|
1363
1348
|
node.eachChild((function(_this) {
|
1364
1349
|
return function(childNode) {
|
1365
|
-
var
|
1366
|
-
|
1367
|
-
if (childNode) {
|
1368
|
-
return complexity +=
|
1350
|
+
var childComplexity, ref1;
|
1351
|
+
childComplexity = _this.lintNode(childNode);
|
1352
|
+
if (((ref1 = _this.astApi) != null ? ref1.getNodeName(childNode) : void 0) !== 'Code') {
|
1353
|
+
return complexity += childComplexity;
|
1369
1354
|
}
|
1370
1355
|
};
|
1371
1356
|
})(this));
|
@@ -1373,7 +1358,7 @@ module.exports = CyclomaticComplexity = (function() {
|
|
1373
1358
|
if (name === 'Code' && complexity >= rule.value) {
|
1374
1359
|
error = this.astApi.createError({
|
1375
1360
|
context: complexity + 1,
|
1376
|
-
lineNumber:
|
1361
|
+
lineNumber: node.locationData.first_line + 1,
|
1377
1362
|
lineNumberEnd: node.locationData.last_line + 1
|
1378
1363
|
});
|
1379
1364
|
if (error) {
|
@@ -1397,7 +1382,7 @@ module.exports = DuplicateKey = (function() {
|
|
1397
1382
|
name: 'duplicate_key',
|
1398
1383
|
level: 'error',
|
1399
1384
|
message: 'Duplicate key defined in object or class',
|
1400
|
-
description:
|
1385
|
+
description: 'Prevents defining duplicate keys in object literals and classes'
|
1401
1386
|
};
|
1402
1387
|
|
1403
1388
|
DuplicateKey.prototype.tokens = ['IDENTIFIER', '{', '}'];
|
@@ -1469,7 +1454,7 @@ module.exports = EmptyConstructorNeedsParens = (function() {
|
|
1469
1454
|
name: 'empty_constructor_needs_parens',
|
1470
1455
|
level: 'ignore',
|
1471
1456
|
message: 'Invoking a constructor without parens and without arguments',
|
1472
|
-
description:
|
1457
|
+
description: 'Requires constructors with no parameters to include the parens'
|
1473
1458
|
};
|
1474
1459
|
|
1475
1460
|
EmptyConstructorNeedsParens.prototype.tokens = ['UNARY'];
|
@@ -1533,7 +1518,7 @@ module.exports = EnsureComprehensions = (function() {
|
|
1533
1518
|
EnsureComprehensions.prototype.forBlock = false;
|
1534
1519
|
|
1535
1520
|
EnsureComprehensions.prototype.lintToken = function(token, tokenApi) {
|
1536
|
-
var atEqual, idents, numCallEnds, numCallStarts, peeker, prevIdents, prevToken, ref, ref1;
|
1521
|
+
var atEqual, idents, numCallEnds, numCallStarts, numParenEnds, numParenStarts, peeker, prevIdents, prevToken, ref, ref1;
|
1537
1522
|
idents = this.findIdents(tokenApi);
|
1538
1523
|
if (this.forBlock) {
|
1539
1524
|
this.forBlock = false;
|
@@ -1543,6 +1528,8 @@ module.exports = EnsureComprehensions = (function() {
|
|
1543
1528
|
atEqual = false;
|
1544
1529
|
numCallEnds = 0;
|
1545
1530
|
numCallStarts = 0;
|
1531
|
+
numParenStarts = 0;
|
1532
|
+
numParenEnds = 0;
|
1546
1533
|
prevIdents = [];
|
1547
1534
|
while ((prevToken = tokenApi.peek(peeker))) {
|
1548
1535
|
if (prevToken[0] === 'CALL_END') {
|
@@ -1551,6 +1538,12 @@ module.exports = EnsureComprehensions = (function() {
|
|
1551
1538
|
if (prevToken[0] === 'CALL_START') {
|
1552
1539
|
numCallStarts++;
|
1553
1540
|
}
|
1541
|
+
if (prevToken[0] === '(') {
|
1542
|
+
numParenStarts++;
|
1543
|
+
}
|
1544
|
+
if (prevToken[0] === ')') {
|
1545
|
+
numParenEnds++;
|
1546
|
+
}
|
1554
1547
|
if (prevToken[0] === 'IDENTIFIER') {
|
1555
1548
|
if (!atEqual) {
|
1556
1549
|
prevIdents.push(prevToken[1]);
|
@@ -1561,12 +1554,12 @@ module.exports = EnsureComprehensions = (function() {
|
|
1561
1554
|
if (((ref1 = prevToken[0]) === '(' || ref1 === '->' || ref1 === 'TERMINATOR') || (prevToken.newLine != null)) {
|
1562
1555
|
break;
|
1563
1556
|
}
|
1564
|
-
if (prevToken[0] === '=') {
|
1557
|
+
if (prevToken[0] === '=' && numParenEnds === numParenStarts) {
|
1565
1558
|
atEqual = true;
|
1566
1559
|
}
|
1567
1560
|
peeker--;
|
1568
1561
|
}
|
1569
|
-
if (atEqual &&
|
1562
|
+
if (atEqual && numCallStarts === numCallEnds) {
|
1570
1563
|
return {
|
1571
1564
|
context: ''
|
1572
1565
|
};
|
@@ -1615,14 +1608,17 @@ module.exports = EOLLast = (function() {
|
|
1615
1608
|
name: 'eol_last',
|
1616
1609
|
level: 'ignore',
|
1617
1610
|
message: 'File does not end with a single newline',
|
1618
|
-
description:
|
1611
|
+
description: 'Checks that the file ends with a single newline'
|
1619
1612
|
};
|
1620
1613
|
|
1621
1614
|
EOLLast.prototype.lintLine = function(line, lineApi) {
|
1615
|
+
var isNewline, previousIsNewline;
|
1622
1616
|
if (!lineApi.isLastLine()) {
|
1623
1617
|
return null;
|
1624
1618
|
}
|
1625
|
-
|
1619
|
+
isNewline = line.length === 0;
|
1620
|
+
previousIsNewline = lineApi.lineCount > 1 ? lineApi.lines[lineApi.lineNumber - 1].length === 0 : false;
|
1621
|
+
if (!(isNewline && !previousIsNewline)) {
|
1626
1622
|
return true;
|
1627
1623
|
}
|
1628
1624
|
};
|
@@ -1634,7 +1630,8 @@ module.exports = EOLLast = (function() {
|
|
1634
1630
|
|
1635
1631
|
|
1636
1632
|
},{}],18:[function(require,module,exports){
|
1637
|
-
var Indentation
|
1633
|
+
var Indentation,
|
1634
|
+
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; };
|
1638
1635
|
|
1639
1636
|
module.exports = Indentation = (function() {
|
1640
1637
|
Indentation.prototype.rule = {
|
@@ -1642,23 +1639,25 @@ module.exports = Indentation = (function() {
|
|
1642
1639
|
value: 2,
|
1643
1640
|
level: 'error',
|
1644
1641
|
message: 'Line contains inconsistent indentation',
|
1645
|
-
description:
|
1642
|
+
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.'
|
1646
1643
|
};
|
1647
1644
|
|
1648
1645
|
Indentation.prototype.tokens = ['INDENT', '[', ']', '.'];
|
1649
1646
|
|
1647
|
+
Indentation.prototype.keywords = ['->', '=>', '@', 'CATCH', 'CLASS', 'ELSE', 'FINALLY', 'FOR', 'FORIN', 'FOROF', 'IDENTIFIER', 'IF', 'LEADING_WHEN', 'LOOP', 'RETURN', 'SWITCH', 'THROW', 'TRY', 'UNTIL', 'WHEN', 'WHILE', 'YIELD'];
|
1648
|
+
|
1650
1649
|
function Indentation() {
|
1651
1650
|
this.arrayTokens = [];
|
1652
1651
|
}
|
1653
1652
|
|
1654
1653
|
Indentation.prototype.lintToken = function(token, tokenApi) {
|
1655
|
-
var currentLine, expected, ignoreIndent, isArrayIndent,
|
1654
|
+
var currentLine, expected, ignoreIndent, isArrayIndent, isMultiline, lineNumber, lines, numIndents, previous, previousSymbol, ref, ref1, ref2, type;
|
1656
1655
|
type = token[0], numIndents = token[1], (ref = token[2], lineNumber = ref.first_line);
|
1657
1656
|
lines = tokenApi.lines, lineNumber = tokenApi.lineNumber;
|
1658
1657
|
expected = tokenApi.config[this.rule.name].value;
|
1659
1658
|
if (type === '.') {
|
1660
1659
|
currentLine = lines[lineNumber];
|
1661
|
-
if (((ref1 = currentLine.match(/\S/
|
1660
|
+
if (((ref1 = currentLine.match(/\S/)) != null ? ref1[0] : void 0) === '.') {
|
1662
1661
|
return this.handleChain(tokenApi, expected);
|
1663
1662
|
}
|
1664
1663
|
return void 0;
|
@@ -1667,20 +1666,18 @@ module.exports = Indentation = (function() {
|
|
1667
1666
|
this.lintArray(token);
|
1668
1667
|
return void 0;
|
1669
1668
|
}
|
1670
|
-
if (token.generated != null) {
|
1669
|
+
if ((token.generated != null) || (token.explicit != null)) {
|
1671
1670
|
return null;
|
1672
1671
|
}
|
1673
|
-
previous = tokenApi.peek(-2);
|
1674
|
-
isInterpIndent = previous && previous[0] === '+';
|
1675
1672
|
previous = tokenApi.peek(-1);
|
1676
1673
|
isArrayIndent = this.inArray() && (previous != null ? previous.newLine : void 0);
|
1677
1674
|
previousSymbol = (ref2 = tokenApi.peek(-1)) != null ? ref2[0] : void 0;
|
1678
1675
|
isMultiline = previousSymbol === '=' || previousSymbol === ',';
|
1679
|
-
ignoreIndent =
|
1676
|
+
ignoreIndent = isArrayIndent || isMultiline;
|
1680
1677
|
numIndents = this.getCorrectIndent(tokenApi);
|
1681
|
-
if (!ignoreIndent && numIndents
|
1678
|
+
if (!ignoreIndent && !(indexOf.call(numIndents, expected) >= 0)) {
|
1682
1679
|
return {
|
1683
|
-
context: "Expected " + expected + " got " + numIndents
|
1680
|
+
context: "Expected " + expected + " got " + numIndents[0]
|
1684
1681
|
};
|
1685
1682
|
}
|
1686
1683
|
};
|
@@ -1717,9 +1714,9 @@ module.exports = Indentation = (function() {
|
|
1717
1714
|
checkNum = lineNumber - prevNum;
|
1718
1715
|
if (checkNum >= 0) {
|
1719
1716
|
prevLine = lines[checkNum];
|
1720
|
-
if (prevLine.match(/\S/
|
1721
|
-
currentSpaces = (ref = currentLine.match(/\S/
|
1722
|
-
prevSpaces = (ref1 = prevLine.match(/\S/
|
1717
|
+
if (prevLine.match(/\S/)[0] === '.' || checkNum === lastCheck) {
|
1718
|
+
currentSpaces = (ref = currentLine.match(/\S/)) != null ? ref.index : void 0;
|
1719
|
+
prevSpaces = (ref1 = prevLine.match(/\S/)) != null ? ref1.index : void 0;
|
1723
1720
|
numIndents = currentSpaces - prevSpaces;
|
1724
1721
|
prevIsIndent = prevSpaces % expected !== 0;
|
1725
1722
|
currIsIndent = currentSpaces % expected !== 0;
|
@@ -1735,21 +1732,81 @@ module.exports = Indentation = (function() {
|
|
1735
1732
|
}
|
1736
1733
|
};
|
1737
1734
|
|
1735
|
+
Indentation.prototype.grabLineTokens = function(tokenApi, lineNumber, all) {
|
1736
|
+
var i, k, len, len1, ref, ref1, results, results1, tok, tokensByLine;
|
1737
|
+
if (all == null) {
|
1738
|
+
all = false;
|
1739
|
+
}
|
1740
|
+
tokensByLine = tokenApi.tokensByLine;
|
1741
|
+
while (!((tokensByLine[lineNumber] != null) || lineNumber === 0)) {
|
1742
|
+
lineNumber--;
|
1743
|
+
}
|
1744
|
+
if (all) {
|
1745
|
+
ref = tokensByLine[lineNumber];
|
1746
|
+
results = [];
|
1747
|
+
for (i = 0, len = ref.length; i < len; i++) {
|
1748
|
+
tok = ref[i];
|
1749
|
+
results.push(tok);
|
1750
|
+
}
|
1751
|
+
return results;
|
1752
|
+
} else {
|
1753
|
+
ref1 = tokensByLine[lineNumber];
|
1754
|
+
results1 = [];
|
1755
|
+
for (k = 0, len1 = ref1.length; k < len1; k++) {
|
1756
|
+
tok = ref1[k];
|
1757
|
+
if ((tok.generated == null) && tok[0] !== 'OUTDENT') {
|
1758
|
+
results1.push(tok);
|
1759
|
+
}
|
1760
|
+
}
|
1761
|
+
return results1;
|
1762
|
+
}
|
1763
|
+
};
|
1764
|
+
|
1738
1765
|
Indentation.prototype.getCorrectIndent = function(tokenApi) {
|
1739
|
-
var curIndent, i, lineNumber, lines, prevIndent,
|
1740
|
-
lineNumber = tokenApi.lineNumber, lines = tokenApi.lines, tokens = tokenApi.tokens
|
1766
|
+
var _, curIndent, i, j, len, lineNumber, lines, prevIndent, prevNum, prevTokens, ref, ref1, ref2, ref3, ref4, ref5, ref6, ref7, ret, skipAssign, t, tokens, tryLine;
|
1767
|
+
lineNumber = tokenApi.lineNumber, lines = tokenApi.lines, tokens = tokenApi.tokens;
|
1741
1768
|
curIndent = (ref = lines[lineNumber].match(/\S/)) != null ? ref.index : void 0;
|
1742
1769
|
prevNum = 1;
|
1743
1770
|
while (/^\s*(#|$)/.test(lines[lineNumber - prevNum])) {
|
1744
1771
|
prevNum += 1;
|
1745
1772
|
}
|
1746
|
-
|
1747
|
-
|
1748
|
-
|
1749
|
-
return curIndent - ((ref2 = prevLine.match(/\S/)) != null ? ref2.index : void 0);
|
1773
|
+
prevTokens = this.grabLineTokens(tokenApi, lineNumber - prevNum);
|
1774
|
+
if (((ref1 = prevTokens[0]) != null ? ref1[0] : void 0) === 'INDENT') {
|
1775
|
+
return [curIndent - ((ref2 = prevTokens[1]) != null ? ref2[2].first_column : void 0), curIndent - prevTokens[0][1]];
|
1750
1776
|
} else {
|
1751
|
-
|
1777
|
+
prevIndent = (ref3 = prevTokens[0]) != null ? ref3[2].first_column : void 0;
|
1778
|
+
for (j = i = 0, len = prevTokens.length; i < len; j = ++i) {
|
1779
|
+
_ = prevTokens[j];
|
1780
|
+
if (!(prevTokens[j][0] === '=' && ((ref4 = prevTokens[j + 1]) != null ? ref4[0] : void 0) === 'IF')) {
|
1781
|
+
continue;
|
1782
|
+
}
|
1783
|
+
skipAssign = curIndent - prevTokens[j + 1][2].first_column;
|
1784
|
+
ret = curIndent - prevIndent;
|
1785
|
+
if (skipAssign < 0) {
|
1786
|
+
return [ret];
|
1787
|
+
}
|
1788
|
+
return [skipAssign, ret];
|
1789
|
+
}
|
1790
|
+
while (prevIndent > curIndent) {
|
1791
|
+
tryLine = lineNumber - prevNum;
|
1792
|
+
prevTokens = this.grabLineTokens(tokenApi, tryLine, true);
|
1793
|
+
if (((ref5 = prevTokens[0]) != null ? ref5[0] : void 0) === 'INDENT') {
|
1794
|
+
prevIndent = prevTokens[0][1];
|
1795
|
+
prevTokens = prevTokens.slice(1);
|
1796
|
+
}
|
1797
|
+
t = 0;
|
1798
|
+
while (!((prevTokens[t] == null) || (ref6 = prevTokens[t][0], indexOf.call(this.keywords, ref6) >= 0))) {
|
1799
|
+
t++;
|
1800
|
+
}
|
1801
|
+
prevTokens = prevTokens.slice(t);
|
1802
|
+
prevNum++;
|
1803
|
+
if (prevTokens[0] == null) {
|
1804
|
+
continue;
|
1805
|
+
}
|
1806
|
+
prevIndent = (ref7 = prevTokens[0]) != null ? ref7[2].first_column : void 0;
|
1807
|
+
}
|
1752
1808
|
}
|
1809
|
+
return [curIndent - prevIndent];
|
1753
1810
|
};
|
1754
1811
|
|
1755
1812
|
return Indentation;
|
@@ -1769,7 +1826,7 @@ module.exports = LineEndings = (function() {
|
|
1769
1826
|
level: 'ignore',
|
1770
1827
|
value: 'unix',
|
1771
1828
|
message: 'Line contains incorrect line endings',
|
1772
|
-
description:
|
1829
|
+
description: 'This rule ensures your project uses only <tt>windows</tt> or\n<tt>unix</tt> line endings. This rule is disabled by default.'
|
1773
1830
|
};
|
1774
1831
|
|
1775
1832
|
LineEndings.prototype.lintLine = function(line, lineApi) {
|
@@ -1820,7 +1877,7 @@ module.exports = MaxLineLength = (function() {
|
|
1820
1877
|
level: 'error',
|
1821
1878
|
limitComments: true,
|
1822
1879
|
message: 'Line exceeds maximum allowed length',
|
1823
|
-
description:
|
1880
|
+
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.'
|
1824
1881
|
};
|
1825
1882
|
|
1826
1883
|
MaxLineLength.prototype.lintLine = function(line, lineApi) {
|
@@ -1890,7 +1947,7 @@ module.exports = MissingFatArrows = (function() {
|
|
1890
1947
|
level: 'ignore',
|
1891
1948
|
is_strict: false,
|
1892
1949
|
message: 'Used `this` in a function without a fat arrow',
|
1893
|
-
description:
|
1950
|
+
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.'
|
1894
1951
|
};
|
1895
1952
|
|
1896
1953
|
MissingFatArrows.prototype.lintAST = function(node, astApi) {
|
@@ -1900,15 +1957,18 @@ module.exports = MissingFatArrows = (function() {
|
|
1900
1957
|
};
|
1901
1958
|
|
1902
1959
|
MissingFatArrows.prototype.lintNode = function(node, methods) {
|
1903
|
-
var error,
|
1960
|
+
var error, isStrict, ref;
|
1904
1961
|
if (methods == null) {
|
1905
1962
|
methods = [];
|
1906
1963
|
}
|
1907
|
-
|
1964
|
+
isStrict = (ref = this.astApi.config[this.rule.name]) != null ? ref.is_strict : void 0;
|
1965
|
+
if (this.isPrototype(node)) {
|
1966
|
+
return;
|
1967
|
+
}
|
1908
1968
|
if (this.isConstructor(node)) {
|
1909
1969
|
return;
|
1910
1970
|
}
|
1911
|
-
if ((!this.isFatArrowCode(node)) && (
|
1971
|
+
if ((!this.isFatArrowCode(node)) && (isStrict ? true : indexOf.call(methods, node) < 0) && (this.needsFatArrow(node))) {
|
1912
1972
|
error = this.astApi.createError({
|
1913
1973
|
lineNumber: node.locationData.first_line + 1
|
1914
1974
|
});
|
@@ -1946,6 +2006,18 @@ module.exports = MissingFatArrows = (function() {
|
|
1946
2006
|
return this.astApi.getNodeName(node) === 'Obj';
|
1947
2007
|
};
|
1948
2008
|
|
2009
|
+
MissingFatArrows.prototype.isPrototype = function(node) {
|
2010
|
+
var i, ident, len, props, ref, ref1;
|
2011
|
+
props = (node != null ? (ref = node.variable) != null ? ref.properties : void 0 : void 0) || [];
|
2012
|
+
for (i = 0, len = props.length; i < len; i++) {
|
2013
|
+
ident = props[i];
|
2014
|
+
if (((ref1 = ident.name) != null ? ref1.value : void 0) === 'prototype') {
|
2015
|
+
return true;
|
2016
|
+
}
|
2017
|
+
}
|
2018
|
+
return false;
|
2019
|
+
};
|
2020
|
+
|
1949
2021
|
MissingFatArrows.prototype.isThis = function(node) {
|
1950
2022
|
return this.isValue(node) && node.base.value === 'this';
|
1951
2023
|
};
|
@@ -1997,23 +2069,63 @@ module.exports = NewlinesAfterClasses = (function() {
|
|
1997
2069
|
value: 3,
|
1998
2070
|
level: 'ignore',
|
1999
2071
|
message: 'Wrong count of newlines between a class and other code',
|
2000
|
-
description:
|
2072
|
+
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.'
|
2001
2073
|
};
|
2002
2074
|
|
2003
|
-
NewlinesAfterClasses.prototype.
|
2004
|
-
|
2005
|
-
|
2006
|
-
|
2007
|
-
|
2008
|
-
|
2009
|
-
|
2010
|
-
|
2011
|
-
|
2012
|
-
|
2013
|
-
|
2014
|
-
|
2075
|
+
NewlinesAfterClasses.prototype.tokens = ['CLASS', '}', '{'];
|
2076
|
+
|
2077
|
+
NewlinesAfterClasses.prototype.classBracesCount = 0;
|
2078
|
+
|
2079
|
+
NewlinesAfterClasses.prototype.classCount = 0;
|
2080
|
+
|
2081
|
+
NewlinesAfterClasses.prototype.lintToken = function(token, tokenApi) {
|
2082
|
+
var afters, befores, comment, ending, got, lineNumber, lines, numIndents, outdent, ref, ref1, ref2, start, trueLine, type;
|
2083
|
+
type = token[0], numIndents = token[1], (ref = token[2], lineNumber = ref.first_line);
|
2084
|
+
lines = tokenApi.lines;
|
2085
|
+
ending = tokenApi.config[this.rule.name].value;
|
2086
|
+
if (type === 'CLASS') {
|
2087
|
+
this.classCount++;
|
2088
|
+
}
|
2089
|
+
if (this.classCount > 0 && (token.generated != null)) {
|
2090
|
+
if (type === '{' && ((ref1 = token.origin) != null ? ref1[0] : void 0) === ':') {
|
2091
|
+
this.classBracesCount++;
|
2092
|
+
}
|
2093
|
+
if (type === '}' && ((ref2 = token.origin) != null ? ref2[0] : void 0) === 'OUTDENT') {
|
2094
|
+
this.classBracesCount--;
|
2095
|
+
this.classCount--;
|
2096
|
+
if (this.classCount === 0 && this.classBracesCount === 0) {
|
2097
|
+
befores = 1;
|
2098
|
+
afters = 1;
|
2099
|
+
comment = 0;
|
2100
|
+
outdent = token.origin[2].first_line;
|
2101
|
+
start = Math.min(lineNumber, outdent);
|
2102
|
+
trueLine = Infinity;
|
2103
|
+
while (/^\s*(#|$)/.test(lines[start + afters])) {
|
2104
|
+
if (/^\s*#/.test(lines[start + afters])) {
|
2105
|
+
comment += 1;
|
2106
|
+
} else {
|
2107
|
+
trueLine = Math.min(trueLine, start + afters);
|
2108
|
+
}
|
2109
|
+
afters += 1;
|
2110
|
+
}
|
2111
|
+
while (/^\s*(#|$)/.test(lines[start - befores])) {
|
2112
|
+
if (/^\s*#/.test(lines[start - befores])) {
|
2113
|
+
comment += 1;
|
2114
|
+
} else {
|
2115
|
+
trueLine = Math.min(trueLine, start - befores);
|
2116
|
+
}
|
2117
|
+
befores += 1;
|
2118
|
+
}
|
2119
|
+
got = afters + befores - comment - 2;
|
2120
|
+
if (got !== ending && trueLine + ending <= lines.length) {
|
2121
|
+
return {
|
2122
|
+
context: "Expected " + ending + " got " + got,
|
2123
|
+
lineNumber: trueLine
|
2124
|
+
};
|
2125
|
+
}
|
2126
|
+
}
|
2127
|
+
}
|
2015
2128
|
}
|
2016
|
-
return null;
|
2017
2129
|
};
|
2018
2130
|
|
2019
2131
|
return NewlinesAfterClasses;
|
@@ -2032,10 +2144,10 @@ module.exports = NoBackticks = (function() {
|
|
2032
2144
|
name: 'no_backticks',
|
2033
2145
|
level: 'error',
|
2034
2146
|
message: 'Backticks are forbidden',
|
2035
|
-
description:
|
2147
|
+
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.'
|
2036
2148
|
};
|
2037
2149
|
|
2038
|
-
NoBackticks.prototype.tokens = [
|
2150
|
+
NoBackticks.prototype.tokens = ['JS'];
|
2039
2151
|
|
2040
2152
|
NoBackticks.prototype.lintToken = function(token, tokenApi) {
|
2041
2153
|
return true;
|
@@ -2058,10 +2170,10 @@ module.exports = NoDebugger = (function() {
|
|
2058
2170
|
level: 'warn',
|
2059
2171
|
message: 'Found debugging code',
|
2060
2172
|
console: false,
|
2061
|
-
description:
|
2173
|
+
description: 'This rule detects `debugger` and optionally `console` calls\nThis rule is `warn` by default.'
|
2062
2174
|
};
|
2063
2175
|
|
2064
|
-
NoDebugger.prototype.tokens = [
|
2176
|
+
NoDebugger.prototype.tokens = ['DEBUGGER', 'IDENTIFIER'];
|
2065
2177
|
|
2066
2178
|
NoDebugger.prototype.lintToken = function(token, tokenApi) {
|
2067
2179
|
var method, ref, ref1;
|
@@ -2102,7 +2214,7 @@ module.exports = NoEmptyFunctions = (function() {
|
|
2102
2214
|
name: 'no_empty_functions',
|
2103
2215
|
level: 'ignore',
|
2104
2216
|
message: 'Empty function',
|
2105
|
-
description:
|
2217
|
+
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>'
|
2106
2218
|
};
|
2107
2219
|
|
2108
2220
|
NoEmptyFunctions.prototype.lintAST = function(node, astApi) {
|
@@ -2141,10 +2253,10 @@ module.exports = NoEmptyParamList = (function() {
|
|
2141
2253
|
name: 'no_empty_param_list',
|
2142
2254
|
level: 'ignore',
|
2143
2255
|
message: 'Empty parameter list is forbidden',
|
2144
|
-
description:
|
2256
|
+
description: 'This rule prohibits empty parameter lists in function definitions.\n<pre>\n<code># The empty parameter list in here is unnecessary:\nmyFunction = () ->\n\n# We might favor this instead:\nmyFunction = ->\n</code>\n</pre>\nEmpty parameter lists are permitted by default.'
|
2145
2257
|
};
|
2146
2258
|
|
2147
|
-
NoEmptyParamList.prototype.tokens = [
|
2259
|
+
NoEmptyParamList.prototype.tokens = ['PARAM_START'];
|
2148
2260
|
|
2149
2261
|
NoEmptyParamList.prototype.lintToken = function(token, tokenApi) {
|
2150
2262
|
var nextType;
|
@@ -2170,27 +2282,36 @@ module.exports = NoImplicitBraces = (function() {
|
|
2170
2282
|
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.'
|
2171
2283
|
};
|
2172
2284
|
|
2173
|
-
NoImplicitBraces.prototype.tokens = ['{', 'OUTDENT', 'CLASS'];
|
2285
|
+
NoImplicitBraces.prototype.tokens = ['{', 'OUTDENT', 'CLASS', 'IDENTIFIER'];
|
2174
2286
|
|
2175
2287
|
function NoImplicitBraces() {
|
2176
2288
|
this.isClass = false;
|
2177
|
-
this.
|
2289
|
+
this.className = void 0;
|
2178
2290
|
}
|
2179
2291
|
|
2180
2292
|
NoImplicitBraces.prototype.lintToken = function(token, tokenApi) {
|
2181
|
-
var lineNum,
|
2293
|
+
var lineNum, peekTwo, prevToken, type, val;
|
2182
2294
|
type = token[0], val = token[1], lineNum = token[2];
|
2183
2295
|
if (type === 'OUTDENT' || type === 'CLASS') {
|
2184
2296
|
return this.trackClass.apply(this, arguments);
|
2185
2297
|
}
|
2186
|
-
if (
|
2187
|
-
|
2188
|
-
|
2189
|
-
|
2190
|
-
}
|
2298
|
+
if (type === 'IDENTIFIER' && this.isClass && ((this.className == null) || tokenApi.peek(-1)[0] === 'EXTENDS')) {
|
2299
|
+
this.className = val;
|
2300
|
+
}
|
2301
|
+
if (token.generated && type === '{') {
|
2191
2302
|
if (!tokenApi.config[this.rule.name].strict) {
|
2192
|
-
|
2193
|
-
if (
|
2303
|
+
prevToken = tokenApi.peek(-1)[0];
|
2304
|
+
if (prevToken === 'INDENT' || prevToken === 'TERMINATOR') {
|
2305
|
+
return;
|
2306
|
+
}
|
2307
|
+
}
|
2308
|
+
if (this.isClass) {
|
2309
|
+
prevToken = tokenApi.peek(-1)[0];
|
2310
|
+
if (prevToken === 'TERMINATOR') {
|
2311
|
+
return;
|
2312
|
+
}
|
2313
|
+
peekTwo = tokenApi.peek(-2);
|
2314
|
+
if (peekTwo[0] === 'IDENTIFIER' && peekTwo[1] === this.className) {
|
2194
2315
|
return;
|
2195
2316
|
}
|
2196
2317
|
}
|
@@ -2203,11 +2324,10 @@ module.exports = NoImplicitBraces = (function() {
|
|
2203
2324
|
ref = [token, tokenApi.peek()], (ref1 = ref[0], n0 = ref1[0], ln = ref1[ref1.length - 1]), (ref2 = ref[1], n1 = ref2[0]);
|
2204
2325
|
if (n0 === 'OUTDENT' && n1 === 'TERMINATOR') {
|
2205
2326
|
this.isClass = false;
|
2206
|
-
this.classBrace = false;
|
2207
2327
|
}
|
2208
2328
|
if (n0 === 'CLASS') {
|
2209
2329
|
this.isClass = true;
|
2210
|
-
this.
|
2330
|
+
this.className = void 0;
|
2211
2331
|
}
|
2212
2332
|
return null;
|
2213
2333
|
};
|
@@ -2226,10 +2346,10 @@ module.exports = NoImplicitParens = (function() {
|
|
2226
2346
|
|
2227
2347
|
NoImplicitParens.prototype.rule = {
|
2228
2348
|
name: 'no_implicit_parens',
|
2229
|
-
strict: true,
|
2230
2349
|
level: 'ignore',
|
2231
2350
|
message: 'Implicit parens are forbidden',
|
2232
|
-
|
2351
|
+
strict: true,
|
2352
|
+
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.'
|
2233
2353
|
};
|
2234
2354
|
|
2235
2355
|
NoImplicitParens.prototype.tokens = ['CALL_END'];
|
@@ -2349,10 +2469,10 @@ module.exports = NoPlusPlus = (function() {
|
|
2349
2469
|
name: 'no_plusplus',
|
2350
2470
|
level: 'ignore',
|
2351
2471
|
message: 'The increment and decrement operators are forbidden',
|
2352
|
-
description:
|
2472
|
+
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.'
|
2353
2473
|
};
|
2354
2474
|
|
2355
|
-
NoPlusPlus.prototype.tokens = [
|
2475
|
+
NoPlusPlus.prototype.tokens = ['++', '--'];
|
2356
2476
|
|
2357
2477
|
NoPlusPlus.prototype.lintToken = function(token, tokenApi) {
|
2358
2478
|
return {
|
@@ -2384,7 +2504,7 @@ module.exports = NoPrivateFunctionFatArrows = (function() {
|
|
2384
2504
|
name: 'no_private_function_fat_arrows',
|
2385
2505
|
level: 'warn',
|
2386
2506
|
message: 'Used the fat arrow for a private function',
|
2387
|
-
description:
|
2507
|
+
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.'
|
2388
2508
|
};
|
2389
2509
|
|
2390
2510
|
NoPrivateFunctionFatArrows.prototype.lintAST = function(node, astApi) {
|
@@ -2474,7 +2594,7 @@ module.exports = NoStandAloneAt = (function() {
|
|
2474
2594
|
name: 'no_stand_alone_at',
|
2475
2595
|
level: 'ignore',
|
2476
2596
|
message: '@ must not be used stand alone',
|
2477
|
-
description:
|
2597
|
+
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>'
|
2478
2598
|
};
|
2479
2599
|
|
2480
2600
|
NoStandAloneAt.prototype.tokens = ['@'];
|
@@ -2514,7 +2634,7 @@ module.exports = NoTabs = (function() {
|
|
2514
2634
|
name: 'no_tabs',
|
2515
2635
|
level: 'error',
|
2516
2636
|
message: 'Line contains tab indentation',
|
2517
|
-
description:
|
2637
|
+
description: 'This rule forbids tabs in indentation. Enough said. It is enabled by\ndefault.'
|
2518
2638
|
};
|
2519
2639
|
|
2520
2640
|
NoTabs.prototype.lintLine = function(line, lineApi) {
|
@@ -2541,15 +2661,20 @@ module.exports = NoThis = (function() {
|
|
2541
2661
|
|
2542
2662
|
NoThis.prototype.rule = {
|
2543
2663
|
name: 'no_this',
|
2544
|
-
description: 'This rule prohibits \'this\'.\nUse \'@\' instead.',
|
2545
2664
|
level: 'ignore',
|
2546
|
-
message: "Don't use 'this', use '@' instead"
|
2665
|
+
message: "Don't use 'this', use '@' instead",
|
2666
|
+
description: 'This rule prohibits \'this\'.\nUse \'@\' instead.'
|
2547
2667
|
};
|
2548
2668
|
|
2549
2669
|
NoThis.prototype.tokens = ['THIS'];
|
2550
2670
|
|
2551
2671
|
NoThis.prototype.lintToken = function(token, tokenApi) {
|
2552
|
-
|
2672
|
+
var level, nextToken, ref;
|
2673
|
+
level = tokenApi.config.no_stand_alone_at.level;
|
2674
|
+
nextToken = (ref = tokenApi.peek(1)) != null ? ref[0] : void 0;
|
2675
|
+
if (!(level !== 'ignore' && nextToken !== '.')) {
|
2676
|
+
return true;
|
2677
|
+
}
|
2553
2678
|
};
|
2554
2679
|
|
2555
2680
|
return NoThis;
|
@@ -2568,7 +2693,7 @@ module.exports = NoThrowingStrings = (function() {
|
|
2568
2693
|
name: 'no_throwing_strings',
|
2569
2694
|
level: 'error',
|
2570
2695
|
message: 'Throwing strings is forbidden',
|
2571
|
-
description:
|
2696
|
+
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.'
|
2572
2697
|
};
|
2573
2698
|
|
2574
2699
|
NoThrowingStrings.prototype.tokens = ['THROW'];
|
@@ -2602,7 +2727,7 @@ module.exports = NoTrailingSemicolons = (function() {
|
|
2602
2727
|
name: 'no_trailing_semicolons',
|
2603
2728
|
level: 'error',
|
2604
2729
|
message: 'Line contains a trailing semicolon',
|
2605
|
-
description:
|
2730
|
+
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.'
|
2606
2731
|
};
|
2607
2732
|
|
2608
2733
|
NoTrailingSemicolons.prototype.lintLine = function(line, lineApi) {
|
@@ -2657,7 +2782,7 @@ module.exports = NoTrailingWhitespace = (function() {
|
|
2657
2782
|
message: 'Line ends with trailing whitespace',
|
2658
2783
|
allowed_in_comments: false,
|
2659
2784
|
allowed_in_empty_lines: true,
|
2660
|
-
description:
|
2785
|
+
description: 'This rule forbids trailing whitespace in your code, since it is\nneedless cruft. It is enabled by default.'
|
2661
2786
|
};
|
2662
2787
|
|
2663
2788
|
NoTrailingWhitespace.prototype.lintLine = function(line, lineApi) {
|
@@ -2781,7 +2906,7 @@ module.exports = NoUnnecessaryFatArrows = (function() {
|
|
2781
2906
|
name: 'no_unnecessary_fat_arrows',
|
2782
2907
|
level: 'warn',
|
2783
2908
|
message: 'Unnecessary fat arrow',
|
2784
|
-
description:
|
2909
|
+
description: 'Disallows defining functions with fat arrows when `this`\nis not used within the function.'
|
2785
2910
|
};
|
2786
2911
|
|
2787
2912
|
NoUnnecessaryFatArrows.prototype.lintAST = function(node, astApi) {
|
@@ -2861,7 +2986,7 @@ module.exports = NonEmptyConstructorNeedsParens = (function(superClass) {
|
|
2861
2986
|
name: 'non_empty_constructor_needs_parens',
|
2862
2987
|
level: 'ignore',
|
2863
2988
|
message: 'Invoking a constructor without parens and with arguments',
|
2864
|
-
description:
|
2989
|
+
description: 'Requires constructors with parameters to include the parens'
|
2865
2990
|
};
|
2866
2991
|
|
2867
2992
|
NonEmptyConstructorNeedsParens.prototype.handleExpectedCallStart = function(expectedCallStart) {
|
@@ -2884,10 +3009,10 @@ module.exports = PreferEnglishOperator = (function() {
|
|
2884
3009
|
|
2885
3010
|
PreferEnglishOperator.prototype.rule = {
|
2886
3011
|
name: 'prefer_english_operator',
|
2887
|
-
description: 'This rule prohibits &&, ||, ==, != and !.\nUse and, or, is, isnt, and not instead.\n!! for converting to a boolean is ignored.',
|
2888
3012
|
level: 'ignore',
|
3013
|
+
message: 'Don\'t use &&, ||, ==, !=, or !',
|
2889
3014
|
doubleNotLevel: 'ignore',
|
2890
|
-
|
3015
|
+
description: 'This rule prohibits &&, ||, ==, != and !.\nUse and, or, is, isnt, and not instead.\n!! for converting to a boolean is ignored.'
|
2891
3016
|
};
|
2892
3017
|
|
2893
3018
|
PreferEnglishOperator.prototype.tokens = ['COMPARE', 'UNARY_MATH', 'LOGIC'];
|
@@ -2947,7 +3072,7 @@ module.exports = SpaceOperators = (function() {
|
|
2947
3072
|
name: 'space_operators',
|
2948
3073
|
level: 'ignore',
|
2949
3074
|
message: 'Operators must be spaced properly',
|
2950
|
-
description:
|
3075
|
+
description: 'This rule enforces that operators have spaces around them.'
|
2951
3076
|
};
|
2952
3077
|
|
2953
3078
|
SpaceOperators.prototype.tokens = ['+', '-', '=', '**', 'MATH', 'COMPARE', 'LOGIC', 'COMPOUND_ASSIGN', 'STRING_START', 'STRING_END', 'CALL_START', 'CALL_END'];
|
@@ -3053,9 +3178,9 @@ var SpacingAfterComma;
|
|
3053
3178
|
module.exports = SpacingAfterComma = (function() {
|
3054
3179
|
SpacingAfterComma.prototype.rule = {
|
3055
3180
|
name: 'spacing_after_comma',
|
3056
|
-
description: 'This rule requires a space after commas.',
|
3057
3181
|
level: 'ignore',
|
3058
|
-
message: '
|
3182
|
+
message: 'a space is required after commas',
|
3183
|
+
description: 'This rule checks to make sure you have a space after commas.'
|
3059
3184
|
};
|
3060
3185
|
|
3061
3186
|
SpacingAfterComma.prototype.tokens = [',', 'REGEX_START', 'REGEX_END'];
|
@@ -3076,9 +3201,7 @@ module.exports = SpacingAfterComma = (function() {
|
|
3076
3201
|
return;
|
3077
3202
|
}
|
3078
3203
|
if (!(token.spaced || token.newLine || token.generated || this.isRegexFlag(token, tokenApi))) {
|
3079
|
-
return
|
3080
|
-
context: token[1]
|
3081
|
-
};
|
3204
|
+
return true;
|
3082
3205
|
}
|
3083
3206
|
};
|
3084
3207
|
|
@@ -3107,7 +3230,7 @@ module.exports = TransformMessesUpLineNumbers = (function() {
|
|
3107
3230
|
name: 'transform_messes_up_line_numbers',
|
3108
3231
|
level: 'warn',
|
3109
3232
|
message: 'Transforming source messes up line numbers',
|
3110
|
-
description:
|
3233
|
+
description: 'This rule detects when changes are made by transform function,\nand warns that line numbers are probably incorrect.'
|
3111
3234
|
};
|
3112
3235
|
|
3113
3236
|
TransformMessesUpLineNumbers.prototype.tokens = [];
|