coffeelint 1.11.0 → 1.14.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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 [](https://travis-ci.org/zmbush/coffeelint-ruby) [](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 = [];
|