coffeelint 0.2.3 → 0.2.5

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 12213463c6912beabd247d01c967b81a52e1ba65
4
- data.tar.gz: 440bdcd9141c0acdb17b6bae17fee664bd561ee8
3
+ metadata.gz: 52e26570cb6aeb608b13718ee0643a3587799f5b
4
+ data.tar.gz: 87ca1b9e93e502ab77443fd76ab7f8b227c098cd
5
5
  SHA512:
6
- metadata.gz: 1b65aaf5269d62114576b8543bdcaec783e7d1cb9e7d634340dfe5cc4781ff270e0ba2a1fff7e8a65c9fdaf74e6782d1ab550b4139311ddbad97d378630e4e22
7
- data.tar.gz: 75cf7d50c532da9d6e57d8dd2066389d5e0d6f572d532d7488bc160dcac7d6046206b8246691cbc6b955e740aa6a84021e039db48749107d576b91b252204f3a
6
+ metadata.gz: 4bb4389a7e90c880e22ffb9a11f4e881a70225749c410a707d37c8e59d7e0c028c2386d979659804eaa4d612054c93bc817cba2f382ac42640f085a9ce6c5e26
7
+ data.tar.gz: 0dda5a52009fe77364cc10812362b249dd48368410d3796700e2d0c521a44ecfb53bd17419d66a4b836e9fe8bdccd5b82edd4b1fedb6199f6328254e6c55c40e
@@ -1,3 +1,3 @@
1
1
  [submodule "coffeelint"]
2
2
  path = coffeelint
3
- url = git://github.com/clutchski/coffeelint.git
3
+ url = git://github.com/zmbush/coffeelint.git
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.1.0
3
+ Using coffeelint version: v1.1.0-21-g5dc0408-20-gc896693
4
4
 
5
5
  Coffeelint is a set of simple ruby bindings for [coffeelint](https://github.com/clutchski/coffeelint).
6
6
 
@@ -21,6 +21,7 @@ Gem::Specification.new do |gem|
21
21
 
22
22
  gem.add_dependency "coffee-script"
23
23
  gem.add_dependency "json"
24
+ gem.add_dependency "execjs"
24
25
 
25
26
  gem.add_development_dependency 'rspec'
26
27
  gem.add_development_dependency 'rake'
@@ -25,7 +25,7 @@ module.exports={
25
25
  "optimist": ">=0.2.8",
26
26
  "coffee-script": "~1.7",
27
27
  "glob": ">=3.1.9",
28
- "browserify": "~3.x",
28
+ "browserify": "~3.37",
29
29
  "coffeeify": "~0.6.0"
30
30
  },
31
31
  "devDependencies": {
@@ -53,17 +53,61 @@ module.exports={
53
53
  }
54
54
 
55
55
  },{}],2:[function(_dereq_,module,exports){
56
- var ASTApi, ASTLinter, BaseLinter,
56
+ var ASTApi, ASTLinter, BaseLinter, hasChildren, node_children,
57
57
  __hasProp = {}.hasOwnProperty,
58
58
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
59
59
 
60
60
  BaseLinter = _dereq_('./base_linter.coffee');
61
61
 
62
+ node_children = {
63
+ Class: ['variable', 'parent', 'body'],
64
+ Code: ['params', 'body'],
65
+ For: ['body', 'source', 'guard', 'step'],
66
+ If: ['condition', 'body', 'elseBody'],
67
+ Obj: ['properties'],
68
+ Op: ['first', 'second'],
69
+ Switch: ['subject', 'cases', 'otherwise'],
70
+ Try: ['attempt', 'recovery', 'ensure'],
71
+ Value: ['base', 'properties'],
72
+ While: ['condition', 'guard', 'body']
73
+ };
74
+
75
+ hasChildren = function(node, children) {
76
+ var _ref;
77
+ return (node != null ? (_ref = node.children) != null ? _ref.length : void 0 : void 0) === children.length && (node != null ? node.children.every(function(elem, i) {
78
+ return elem === children[i];
79
+ }) : void 0);
80
+ };
81
+
62
82
  ASTApi = (function() {
63
83
  function ASTApi(config) {
64
84
  this.config = config;
65
85
  }
66
86
 
87
+ ASTApi.prototype.getNodeName = function(node) {
88
+ var children, name, _ref;
89
+ name = node != null ? (_ref = node.constructor) != null ? _ref.name : void 0 : void 0;
90
+ if (name === (function() {
91
+ var _results;
92
+ _results = [];
93
+ for (name in node_children) {
94
+ if (!__hasProp.call(node_children, name)) continue;
95
+ _results.push(name);
96
+ }
97
+ return _results;
98
+ })()) {
99
+ return name;
100
+ } else {
101
+ for (name in node_children) {
102
+ if (!__hasProp.call(node_children, name)) continue;
103
+ children = node_children[name];
104
+ if (hasChildren(node, children)) {
105
+ return name;
106
+ }
107
+ }
108
+ }
109
+ };
110
+
67
111
  return ASTApi;
68
112
 
69
113
  })();
@@ -418,6 +462,12 @@ coffeelint.registerRule(_dereq_('./rules/missing_fat_arrows.coffee'));
418
462
 
419
463
  coffeelint.registerRule(_dereq_('./rules/non_empty_constructor_needs_parens.coffee'));
420
464
 
465
+ coffeelint.registerRule(_dereq_('./rules/no_unnecessary_double_quotes.coffee'));
466
+
467
+ coffeelint.registerRule(_dereq_('./rules/no_debugger.coffee'));
468
+
469
+ coffeelint.registerRule(_dereq_('./rules/no_interpolation_in_single_quotes.coffee'));
470
+
421
471
  hasSyntaxError = function(source) {
422
472
  try {
423
473
  CoffeeScript.tokens(source);
@@ -514,7 +564,7 @@ coffeelint.lint = function(source, userConfig, literate) {
514
564
  };
515
565
 
516
566
 
517
- },{"./../package.json":1,"./ast_linter.coffee":2,"./lexical_linter.coffee":5,"./line_linter.coffee":6,"./rules.coffee":7,"./rules/arrow_spacing.coffee":8,"./rules/camel_case_classes.coffee":9,"./rules/colon_assignment_spacing.coffee":10,"./rules/cyclomatic_complexity.coffee":11,"./rules/duplicate_key.coffee":12,"./rules/empty_constructor_needs_parens.coffee":13,"./rules/indentation.coffee":14,"./rules/line_endings.coffee":15,"./rules/max_line_length.coffee":16,"./rules/missing_fat_arrows.coffee":17,"./rules/newlines_after_classes.coffee":18,"./rules/no_backticks.coffee":19,"./rules/no_empty_param_list.coffee":20,"./rules/no_implicit_braces.coffee":21,"./rules/no_implicit_parens.coffee":22,"./rules/no_plusplus.coffee":23,"./rules/no_stand_alone_at.coffee":24,"./rules/no_tabs.coffee":25,"./rules/no_throwing_strings.coffee":26,"./rules/no_trailing_semicolons.coffee":27,"./rules/no_trailing_whitespace.coffee":28,"./rules/no_unnecessary_fat_arrows.coffee":29,"./rules/non_empty_constructor_needs_parens.coffee":30,"./rules/space_operators.coffee":31}],5:[function(_dereq_,module,exports){
567
+ },{"./../package.json":1,"./ast_linter.coffee":2,"./lexical_linter.coffee":5,"./line_linter.coffee":6,"./rules.coffee":7,"./rules/arrow_spacing.coffee":8,"./rules/camel_case_classes.coffee":9,"./rules/colon_assignment_spacing.coffee":10,"./rules/cyclomatic_complexity.coffee":11,"./rules/duplicate_key.coffee":12,"./rules/empty_constructor_needs_parens.coffee":13,"./rules/indentation.coffee":14,"./rules/line_endings.coffee":15,"./rules/max_line_length.coffee":16,"./rules/missing_fat_arrows.coffee":17,"./rules/newlines_after_classes.coffee":18,"./rules/no_backticks.coffee":19,"./rules/no_debugger.coffee":20,"./rules/no_empty_param_list.coffee":21,"./rules/no_implicit_braces.coffee":22,"./rules/no_implicit_parens.coffee":23,"./rules/no_interpolation_in_single_quotes.coffee":24,"./rules/no_plusplus.coffee":25,"./rules/no_stand_alone_at.coffee":26,"./rules/no_tabs.coffee":27,"./rules/no_throwing_strings.coffee":28,"./rules/no_trailing_semicolons.coffee":29,"./rules/no_trailing_whitespace.coffee":30,"./rules/no_unnecessary_double_quotes.coffee":31,"./rules/no_unnecessary_fat_arrows.coffee":32,"./rules/non_empty_constructor_needs_parens.coffee":33,"./rules/space_operators.coffee":34}],5:[function(_dereq_,module,exports){
518
568
  var BaseLinter, LexicalLinter, TokenApi,
519
569
  __hasProp = {}.hasOwnProperty,
520
570
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
@@ -978,7 +1028,7 @@ module.exports = NoTabs = (function() {
978
1028
 
979
1029
  NoTabs.prototype.getComplexity = function(node) {
980
1030
  var complexity, name, _ref;
981
- name = node.constructor.name;
1031
+ name = this.astApi.getNodeName(node);
982
1032
  complexity = name === 'If' || name === 'While' || name === 'For' || name === 'Try' ? 1 : name === 'Op' && ((_ref = node.operator) === '&&' || _ref === '||') ? 1 : name === 'Switch' ? node.cases.length : 0;
983
1033
  return complexity;
984
1034
  };
@@ -990,8 +1040,8 @@ module.exports = NoTabs = (function() {
990
1040
  };
991
1041
 
992
1042
  NoTabs.prototype.lintNode = function(node, line) {
993
- var complexity, error, name, rule;
994
- name = node.constructor.name;
1043
+ var complexity, error, name, rule, _ref;
1044
+ name = (_ref = this.astApi) != null ? _ref.getNodeName(node) : void 0;
995
1045
  complexity = this.getComplexity(node);
996
1046
  node.eachChild((function(_this) {
997
1047
  return function(childNode) {
@@ -1333,60 +1383,25 @@ module.exports = MaxLineLength = (function() {
1333
1383
 
1334
1384
 
1335
1385
  },{}],17:[function(_dereq_,module,exports){
1336
- var MissingFatArrows, any, isClass, isCode, isFatArrowCode, isObject, isThis, isValue, methodsOfClass, needsFatArrow,
1386
+ var MissingFatArrows, any,
1387
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; },
1337
1388
  __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; };
1338
1389
 
1339
- isCode = function(node) {
1340
- return (node != null ? node.constructor.name : void 0) === 'Code';
1341
- };
1342
-
1343
- isClass = function(node) {
1344
- return node.constructor.name === 'Class';
1345
- };
1346
-
1347
- isValue = function(node) {
1348
- return node.constructor.name === 'Value';
1349
- };
1350
-
1351
- isObject = function(node) {
1352
- return node.constructor.name === 'Obj';
1353
- };
1354
-
1355
- isThis = function(node) {
1356
- return isValue(node) && node.base.value === 'this';
1357
- };
1358
-
1359
- isFatArrowCode = function(node) {
1360
- return isCode(node) && node.bound;
1361
- };
1362
-
1363
1390
  any = function(arr, test) {
1364
1391
  return arr.reduce((function(res, elt) {
1365
1392
  return res || test(elt);
1366
1393
  }), false);
1367
1394
  };
1368
1395
 
1369
- needsFatArrow = function(node) {
1370
- return isCode(node) && (any(node.params, function(param) {
1371
- return param.contains(isThis) != null;
1372
- }) || (node.body.contains(isThis) != null));
1373
- };
1374
-
1375
- methodsOfClass = function(classNode) {
1376
- var bodyNodes, returnNode;
1377
- bodyNodes = classNode.body.expressions;
1378
- returnNode = bodyNodes[bodyNodes.length - 1];
1379
- if ((returnNode != null) && isValue(returnNode) && isObject(returnNode.base)) {
1380
- return returnNode.base.properties.map(function(assignNode) {
1381
- return assignNode.value;
1382
- }).filter(isCode);
1383
- } else {
1384
- return [];
1385
- }
1386
- };
1387
-
1388
1396
  module.exports = MissingFatArrows = (function() {
1389
- function MissingFatArrows() {}
1397
+ function MissingFatArrows() {
1398
+ this.isFatArrowCode = __bind(this.isFatArrowCode, this);
1399
+ this.isThis = __bind(this.isThis, this);
1400
+ this.isObject = __bind(this.isObject, this);
1401
+ this.isValue = __bind(this.isValue, this);
1402
+ this.isClass = __bind(this.isClass, this);
1403
+ this.isCode = __bind(this.isCode, this);
1404
+ }
1390
1405
 
1391
1406
  MissingFatArrows.prototype.rule = {
1392
1407
  name: 'missing_fat_arrows',
@@ -1396,37 +1411,83 @@ module.exports = MissingFatArrows = (function() {
1396
1411
  };
1397
1412
 
1398
1413
  MissingFatArrows.prototype.lintAST = function(node, astApi) {
1399
- this.lintNode(node, astApi);
1414
+ this.astApi = astApi;
1415
+ this.lintNode(node);
1400
1416
  return void 0;
1401
1417
  };
1402
1418
 
1403
- MissingFatArrows.prototype.lintNode = function(node, astApi, methods) {
1419
+ MissingFatArrows.prototype.lintNode = function(node, methods) {
1404
1420
  var error;
1405
1421
  if (methods == null) {
1406
1422
  methods = [];
1407
1423
  }
1408
- if ((!isFatArrowCode(node)) && (__indexOf.call(methods, node) < 0) && (needsFatArrow(node))) {
1409
- error = astApi.createError({
1424
+ if ((!this.isFatArrowCode(node)) && (__indexOf.call(methods, node) < 0) && (this.needsFatArrow(node))) {
1425
+ error = this.astApi.createError({
1410
1426
  lineNumber: node.locationData.first_line + 1
1411
1427
  });
1412
1428
  this.errors.push(error);
1413
1429
  }
1414
1430
  return node.eachChild((function(_this) {
1415
1431
  return function(child) {
1416
- return _this.lintNode(child, astApi, (function() {
1432
+ return _this.lintNode(child, (function() {
1417
1433
  switch (false) {
1418
- case !isClass(node):
1419
- return methodsOfClass(node);
1420
- case !isCode(node):
1434
+ case !this.isClass(node):
1435
+ return this.methodsOfClass(node);
1436
+ case !this.isCode(node):
1421
1437
  return [];
1422
1438
  default:
1423
1439
  return methods;
1424
1440
  }
1425
- })());
1441
+ }).call(_this));
1426
1442
  };
1427
1443
  })(this));
1428
1444
  };
1429
1445
 
1446
+ MissingFatArrows.prototype.isCode = function(node) {
1447
+ return this.astApi.getNodeName(node) === 'Code';
1448
+ };
1449
+
1450
+ MissingFatArrows.prototype.isClass = function(node) {
1451
+ return this.astApi.getNodeName(node) === 'Class';
1452
+ };
1453
+
1454
+ MissingFatArrows.prototype.isValue = function(node) {
1455
+ return this.astApi.getNodeName(node) === 'Value';
1456
+ };
1457
+
1458
+ MissingFatArrows.prototype.isObject = function(node) {
1459
+ return this.astApi.getNodeName(node) === 'Obj';
1460
+ };
1461
+
1462
+ MissingFatArrows.prototype.isThis = function(node) {
1463
+ return this.isValue(node) && node.base.value === 'this';
1464
+ };
1465
+
1466
+ MissingFatArrows.prototype.isFatArrowCode = function(node) {
1467
+ return this.isCode(node) && node.bound;
1468
+ };
1469
+
1470
+ MissingFatArrows.prototype.needsFatArrow = function(node) {
1471
+ return this.isCode(node) && (any(node.params, (function(_this) {
1472
+ return function(param) {
1473
+ return param.contains(_this.isThis) != null;
1474
+ };
1475
+ })(this)) || (node.body.contains(this.isThis) != null));
1476
+ };
1477
+
1478
+ MissingFatArrows.prototype.methodsOfClass = function(classNode) {
1479
+ var bodyNodes, returnNode;
1480
+ bodyNodes = classNode.body.expressions;
1481
+ returnNode = bodyNodes[bodyNodes.length - 1];
1482
+ if ((returnNode != null) && this.isValue(returnNode) && this.isObject(returnNode.base)) {
1483
+ return returnNode.base.properties.map(function(assignNode) {
1484
+ return assignNode.value;
1485
+ }).filter(this.isCode);
1486
+ } else {
1487
+ return [];
1488
+ }
1489
+ };
1490
+
1430
1491
  return MissingFatArrows;
1431
1492
 
1432
1493
  })();
@@ -1492,6 +1553,32 @@ module.exports = NoBackticks = (function() {
1492
1553
 
1493
1554
 
1494
1555
  },{}],20:[function(_dereq_,module,exports){
1556
+ var NoDebugger;
1557
+
1558
+ module.exports = NoDebugger = (function() {
1559
+ function NoDebugger() {}
1560
+
1561
+ NoDebugger.prototype.rule = {
1562
+ name: 'no_debugger',
1563
+ level: 'warn',
1564
+ message: 'Debugger statements will cause warnings',
1565
+ description: "This rule detects the `debugger` statement.\nThis rule is `warn` by default."
1566
+ };
1567
+
1568
+ NoDebugger.prototype.tokens = ["DEBUGGER"];
1569
+
1570
+ NoDebugger.prototype.lintToken = function(token, tokenApi) {
1571
+ return {
1572
+ context: "found '" + token[0] + "'"
1573
+ };
1574
+ };
1575
+
1576
+ return NoDebugger;
1577
+
1578
+ })();
1579
+
1580
+
1581
+ },{}],21:[function(_dereq_,module,exports){
1495
1582
  var NoEmptyParamList;
1496
1583
 
1497
1584
  module.exports = NoEmptyParamList = (function() {
@@ -1517,7 +1604,7 @@ module.exports = NoEmptyParamList = (function() {
1517
1604
  })();
1518
1605
 
1519
1606
 
1520
- },{}],21:[function(_dereq_,module,exports){
1607
+ },{}],22:[function(_dereq_,module,exports){
1521
1608
  var NoImplicitBraces;
1522
1609
 
1523
1610
  module.exports = NoImplicitBraces = (function() {
@@ -1566,7 +1653,7 @@ module.exports = NoImplicitBraces = (function() {
1566
1653
  })();
1567
1654
 
1568
1655
 
1569
- },{}],22:[function(_dereq_,module,exports){
1656
+ },{}],23:[function(_dereq_,module,exports){
1570
1657
  var NoImplicitParens;
1571
1658
 
1572
1659
  module.exports = NoImplicitParens = (function() {
@@ -1574,15 +1661,33 @@ module.exports = NoImplicitParens = (function() {
1574
1661
 
1575
1662
  NoImplicitParens.prototype.rule = {
1576
1663
  name: 'no_implicit_parens',
1664
+ strict: true,
1577
1665
  level: 'ignore',
1578
1666
  message: 'Implicit parens are forbidden',
1579
1667
  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."
1580
1668
  };
1581
1669
 
1582
- NoImplicitParens.prototype.tokens = ["CALL_START"];
1670
+ NoImplicitParens.prototype.tokens = ["CALL_END"];
1583
1671
 
1584
1672
  NoImplicitParens.prototype.lintToken = function(token, tokenApi) {
1585
- return token.generated;
1673
+ var i, t;
1674
+ if (token.generated) {
1675
+ if (tokenApi.config[this.rule.name].strict !== false) {
1676
+ return true;
1677
+ } else {
1678
+ i = -1;
1679
+ while (true) {
1680
+ t = tokenApi.peek(i);
1681
+ if ((t == null) || t[0] === 'CALL_START') {
1682
+ return true;
1683
+ }
1684
+ if (t.newLine) {
1685
+ return null;
1686
+ }
1687
+ i -= 1;
1688
+ }
1689
+ }
1690
+ }
1586
1691
  };
1587
1692
 
1588
1693
  return NoImplicitParens;
@@ -1590,7 +1695,34 @@ module.exports = NoImplicitParens = (function() {
1590
1695
  })();
1591
1696
 
1592
1697
 
1593
- },{}],23:[function(_dereq_,module,exports){
1698
+ },{}],24:[function(_dereq_,module,exports){
1699
+ var NoInterpolationInSingleQuotes;
1700
+
1701
+ module.exports = NoInterpolationInSingleQuotes = (function() {
1702
+ function NoInterpolationInSingleQuotes() {}
1703
+
1704
+ NoInterpolationInSingleQuotes.prototype.rule = {
1705
+ name: 'no_interpolation_in_single_quotes',
1706
+ level: 'ignore',
1707
+ message: 'Interpolation in single quoted strings is forbidden',
1708
+ description: 'This rule prohibits string interpolation in a single quoted string.\n<pre>\n<code># String interpolation in single quotes is not allowed:\nfoo = \'#{bar}\'\n\n# Double quotes is OK of course\nfoo = "#{bar}"\n</code>\n</pre>\nString interpolation in single quoted strings is permitted by \ndefault.'
1709
+ };
1710
+
1711
+ NoInterpolationInSingleQuotes.prototype.tokens = ['STRING'];
1712
+
1713
+ NoInterpolationInSingleQuotes.prototype.lintToken = function(token, tokenApi) {
1714
+ var hasInterpolation, tokenValue;
1715
+ tokenValue = token[1];
1716
+ hasInterpolation = tokenValue.match(/#\{[^}]+\}/);
1717
+ return hasInterpolation;
1718
+ };
1719
+
1720
+ return NoInterpolationInSingleQuotes;
1721
+
1722
+ })();
1723
+
1724
+
1725
+ },{}],25:[function(_dereq_,module,exports){
1594
1726
  var NoPlusPlus;
1595
1727
 
1596
1728
  module.exports = NoPlusPlus = (function() {
@@ -1616,7 +1748,7 @@ module.exports = NoPlusPlus = (function() {
1616
1748
  })();
1617
1749
 
1618
1750
 
1619
- },{}],24:[function(_dereq_,module,exports){
1751
+ },{}],26:[function(_dereq_,module,exports){
1620
1752
  var NoStandAloneAt;
1621
1753
 
1622
1754
  module.exports = NoStandAloneAt = (function() {
@@ -1652,7 +1784,7 @@ module.exports = NoStandAloneAt = (function() {
1652
1784
  })();
1653
1785
 
1654
1786
 
1655
- },{}],25:[function(_dereq_,module,exports){
1787
+ },{}],27:[function(_dereq_,module,exports){
1656
1788
  var NoTabs, indentationRegex,
1657
1789
  __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; };
1658
1790
 
@@ -1683,7 +1815,7 @@ module.exports = NoTabs = (function() {
1683
1815
  })();
1684
1816
 
1685
1817
 
1686
- },{}],26:[function(_dereq_,module,exports){
1818
+ },{}],28:[function(_dereq_,module,exports){
1687
1819
  var NoThrowingStrings;
1688
1820
 
1689
1821
  module.exports = NoThrowingStrings = (function() {
@@ -1710,7 +1842,7 @@ module.exports = NoThrowingStrings = (function() {
1710
1842
  })();
1711
1843
 
1712
1844
 
1713
- },{}],27:[function(_dereq_,module,exports){
1845
+ },{}],29:[function(_dereq_,module,exports){
1714
1846
  var NoTrailingSemicolons, regexes,
1715
1847
  __slice = [].slice;
1716
1848
 
@@ -1759,7 +1891,7 @@ module.exports = NoTrailingSemicolons = (function() {
1759
1891
  })();
1760
1892
 
1761
1893
 
1762
- },{}],28:[function(_dereq_,module,exports){
1894
+ },{}],30:[function(_dereq_,module,exports){
1763
1895
  var NoTrailingWhitespace, regexes;
1764
1896
 
1765
1897
  regexes = {
@@ -1822,20 +1954,62 @@ module.exports = NoTrailingWhitespace = (function() {
1822
1954
  })();
1823
1955
 
1824
1956
 
1825
- },{}],29:[function(_dereq_,module,exports){
1826
- var NoUnnecessaryFatArrows, any, isCode, isFatArrowCode, isThis, needsFatArrow;
1957
+ },{}],31:[function(_dereq_,module,exports){
1958
+ var NoUnnecessaryDoubleQuotes;
1827
1959
 
1828
- isCode = function(node) {
1829
- return node.constructor.name === 'Code';
1830
- };
1960
+ module.exports = NoUnnecessaryDoubleQuotes = (function() {
1961
+ function NoUnnecessaryDoubleQuotes() {}
1831
1962
 
1832
- isFatArrowCode = function(node) {
1833
- return isCode(node) && node.bound;
1834
- };
1963
+ NoUnnecessaryDoubleQuotes.prototype.rule = {
1964
+ name: 'no_unnecessary_double_quotes',
1965
+ level: 'ignore',
1966
+ message: 'Unnecessary double quotes are forbidden',
1967
+ description: 'This rule prohibits double quotes unless string interpolation is \nused or the string contains single quotes.\n<pre>\n<code># Double quotes are discouraged:\nfoo = "bar"\n\n# Unless string interpolation is used:\nfoo = "#{bar}baz"\n\n# Or they prevent cumbersome escaping:\nfoo = "I\'m just following the \'rules\'"\n</code>\n</pre>\nDouble quotes are permitted by default.'
1968
+ };
1835
1969
 
1836
- isThis = function(node) {
1837
- return node.constructor.name === 'Value' && node.base.value === 'this';
1838
- };
1970
+ NoUnnecessaryDoubleQuotes.prototype.tokens = ['STRING'];
1971
+
1972
+ NoUnnecessaryDoubleQuotes.prototype.lintToken = function(token, tokenApi) {
1973
+ var hasLegalConstructs, stringValue, tokenValue;
1974
+ tokenValue = token[1];
1975
+ stringValue = tokenValue.match(/^\"(.*)\"$/);
1976
+ if (!stringValue) {
1977
+ return false;
1978
+ }
1979
+ hasLegalConstructs = this.isInterpolated(tokenApi) || this.containsSingleQuote(tokenValue);
1980
+ return !hasLegalConstructs;
1981
+ };
1982
+
1983
+ NoUnnecessaryDoubleQuotes.prototype.isInterpolated = function(tokenApi) {
1984
+ var currentIndex, i, isInterpolated, lineTokens, token, tokenName, _i, _ref;
1985
+ currentIndex = tokenApi.i;
1986
+ isInterpolated = false;
1987
+ lineTokens = tokenApi.tokensByLine[tokenApi.lineNumber];
1988
+ for (i = _i = 1; 1 <= currentIndex ? _i <= currentIndex : _i >= currentIndex; i = 1 <= currentIndex ? ++_i : --_i) {
1989
+ token = tokenApi.peek(-i);
1990
+ tokenName = token[0];
1991
+ if (tokenName === ')' && token.stringEnd) {
1992
+ break;
1993
+ } else if (tokenName === '(' && ((_ref = token.origin) != null ? _ref[1] : void 0) === "string interpolation") {
1994
+ isInterpolated = true;
1995
+ break;
1996
+ }
1997
+ }
1998
+ return isInterpolated;
1999
+ };
2000
+
2001
+ NoUnnecessaryDoubleQuotes.prototype.containsSingleQuote = function(tokenValue) {
2002
+ return tokenValue.indexOf("'") !== -1;
2003
+ };
2004
+
2005
+ return NoUnnecessaryDoubleQuotes;
2006
+
2007
+ })();
2008
+
2009
+
2010
+ },{}],32:[function(_dereq_,module,exports){
2011
+ var NoUnnecessaryFatArrows, any,
2012
+ __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; };
1839
2013
 
1840
2014
  any = function(arr, test) {
1841
2015
  return arr.reduce((function(res, elt) {
@@ -1843,16 +2017,11 @@ any = function(arr, test) {
1843
2017
  }), false);
1844
2018
  };
1845
2019
 
1846
- needsFatArrow = function(node) {
1847
- return isCode(node) && (any(node.params, function(param) {
1848
- return param.contains(isThis) != null;
1849
- }) || (node.body.contains(isThis) != null) || (node.body.contains(function(child) {
1850
- return isFatArrowCode(child) && needsFatArrow(child);
1851
- }) != null));
1852
- };
1853
-
1854
2020
  module.exports = NoUnnecessaryFatArrows = (function() {
1855
- function NoUnnecessaryFatArrows() {}
2021
+ function NoUnnecessaryFatArrows() {
2022
+ this.needsFatArrow = __bind(this.needsFatArrow, this);
2023
+ this.isThis = __bind(this.isThis, this);
2024
+ }
1856
2025
 
1857
2026
  NoUnnecessaryFatArrows.prototype.rule = {
1858
2027
  name: 'no_unnecessary_fat_arrows',
@@ -1862,31 +2031,60 @@ module.exports = NoUnnecessaryFatArrows = (function() {
1862
2031
  };
1863
2032
 
1864
2033
  NoUnnecessaryFatArrows.prototype.lintAST = function(node, astApi) {
1865
- this.lintNode(node, astApi);
2034
+ this.astApi = astApi;
2035
+ this.lintNode(node);
1866
2036
  return void 0;
1867
2037
  };
1868
2038
 
1869
- NoUnnecessaryFatArrows.prototype.lintNode = function(node, astApi) {
2039
+ NoUnnecessaryFatArrows.prototype.lintNode = function(node) {
1870
2040
  var error;
1871
- if ((isFatArrowCode(node)) && (!needsFatArrow(node))) {
1872
- error = astApi.createError({
2041
+ if ((this.isFatArrowCode(node)) && (!this.needsFatArrow(node))) {
2042
+ error = this.astApi.createError({
1873
2043
  lineNumber: node.locationData.first_line + 1
1874
2044
  });
1875
2045
  this.errors.push(error);
1876
2046
  }
1877
2047
  return node.eachChild((function(_this) {
1878
2048
  return function(child) {
1879
- return _this.lintNode(child, astApi);
2049
+ return _this.lintNode(child);
1880
2050
  };
1881
2051
  })(this));
1882
2052
  };
1883
2053
 
2054
+ NoUnnecessaryFatArrows.prototype.isCode = function(node) {
2055
+ return this.astApi.getNodeName(node) === 'Code';
2056
+ };
2057
+
2058
+ NoUnnecessaryFatArrows.prototype.isFatArrowCode = function(node) {
2059
+ return this.isCode(node) && node.bound;
2060
+ };
2061
+
2062
+ NoUnnecessaryFatArrows.prototype.isValue = function(node) {
2063
+ return this.astApi.getNodeName(node) === 'Value';
2064
+ };
2065
+
2066
+ NoUnnecessaryFatArrows.prototype.isThis = function(node) {
2067
+ return this.isValue(node) && node.base.value === 'this';
2068
+ };
2069
+
2070
+ NoUnnecessaryFatArrows.prototype.needsFatArrow = function(node) {
2071
+ return this.isCode(node) && (any(node.params, (function(_this) {
2072
+ return function(param) {
2073
+ return param.contains(_this.isThis) != null;
2074
+ };
2075
+ })(this)) || (node.body.contains(this.isThis) != null) || (node.body.contains((function(_this) {
2076
+ return function(child) {
2077
+ return _this.isFatArrowCode(child) && _this.needsFatArrow(child);
2078
+ };
2079
+ })(this)) != null));
2080
+ };
2081
+
1884
2082
  return NoUnnecessaryFatArrows;
1885
2083
 
1886
2084
  })();
1887
2085
 
1888
2086
 
1889
- },{}],30:[function(_dereq_,module,exports){
2087
+ },{}],33:[function(_dereq_,module,exports){
1890
2088
  var NonEmptyConstructorNeedsParens, ParentClass,
1891
2089
  __hasProp = {}.hasOwnProperty,
1892
2090
  __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };
@@ -1918,7 +2116,7 @@ module.exports = NonEmptyConstructorNeedsParens = (function(_super) {
1918
2116
  })(ParentClass);
1919
2117
 
1920
2118
 
1921
- },{"./empty_constructor_needs_parens.coffee":13}],31:[function(_dereq_,module,exports){
2119
+ },{"./empty_constructor_needs_parens.coffee":13}],34:[function(_dereq_,module,exports){
1922
2120
  var SpaceOperators,
1923
2121
  __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; };
1924
2122
 
@@ -1,3 +1,3 @@
1
1
  module Coffeelint
2
- VERSION = "0.2.3"
2
+ VERSION = "0.2.5"
3
3
  end
@@ -18,4 +18,26 @@ describe Coffeelint do
18
18
  results = Coffeelint.lint('apple;', :config_file => "/tmp/coffeelint.json")
19
19
  results.length.should == 0
20
20
  end
21
+
22
+ it 'should report missing fat arrow' do
23
+ results = Coffeelint.lint "hey: ->\n @bort()\n", :missing_fat_arrows => { :level => "error" }
24
+ results.length.should == 1
25
+ end
26
+
27
+ it 'should report unnecessary fat arrow' do
28
+ results = Coffeelint.lint "hey: =>\n bort()\n", :no_unnecessary_fat_arrows => { :level => "error" }
29
+ results.length.should == 1
30
+ end
31
+
32
+ it 'should report cyclomatic complexity' do
33
+ results = Coffeelint.lint(<<-EOF, :cyclomatic_complexity => { :level => "error" })
34
+ x = ->
35
+ 1 and 2 and 3 and
36
+ 4 and 5 and 6 and
37
+ 7 and 8 and 9 and
38
+ 10 and 11
39
+ EOF
40
+ results.length.should == 1
41
+ results[0]['name'].should == 'cyclomatic_complexity'
42
+ end
21
43
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coffeelint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.3
4
+ version: 0.2.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Zachary Bush
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-03-31 00:00:00.000000000 Z
11
+ date: 2014-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: coffee-script
@@ -38,6 +38,20 @@ dependencies:
38
38
  - - '>='
39
39
  - !ruby/object:Gem::Version
40
40
  version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: execjs
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
41
55
  - !ruby/object:Gem::Dependency
42
56
  name: rspec
43
57
  requirement: !ruby/object:Gem::Requirement