Permalink
Browse files

Add no_implicit_return option

  • Loading branch information...
1 parent c7da6b3 commit dd52a204433c0b31ff5b14984df375da4dc6d93e Omar Khan committed Jun 15, 2012
Showing with 108 additions and 22 deletions.
  1. +6 −13 bin/coffeelint
  2. +30 −9 lib/coffeelint.js
  3. +22 −0 src/coffeelint.coffee
  4. +50 −0 test/test_no_implicit_return.coffee
View
@@ -1,5 +1,5 @@
#!/usr/bin/env node
-// Generated by CoffeeScript 1.3.1
+// Generated by CoffeeScript 1.3.3
/*
CoffeeLint
@@ -13,7 +13,7 @@ CoffeeLint is freely distributable under the MIT license.
var CSVReporter, ErrorReport, Reporter, coffeelint, config, configPath, data, errorReport, findCoffeeScripts, fs, glob, lintFiles, lintSource, optimist, options, path, paths, read, reportAndExit, scripts, stdin, thisdir,
__slice = [].slice,
__hasProp = {}.hasOwnProperty,
- __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; };
+ __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; };
path = require("path");
@@ -49,14 +49,11 @@ CoffeeLint is freely distributable under the MIT license.
ErrorReport = (function() {
- ErrorReport.name = 'ErrorReport';
-
function ErrorReport() {
this.paths = {};
}
ErrorReport.prototype.getExitCode = function() {
- var path;
for (path in this.paths) {
if (this.pathHasError(path)) {
return 1;
@@ -66,7 +63,7 @@ CoffeeLint is freely distributable under the MIT license.
};
ErrorReport.prototype.getSummary = function() {
- var error, errorCount, errors, path, pathCount, warningCount, _i, _len, _ref;
+ var error, errorCount, errors, pathCount, warningCount, _i, _len, _ref;
pathCount = errorCount = warningCount = 0;
_ref = this.paths;
for (path in _ref) {
@@ -119,8 +116,6 @@ CoffeeLint is freely distributable under the MIT license.
Reporter = (function() {
- Reporter.name = 'Reporter';
-
function Reporter(errorReport) {
this.errorReport = errorReport;
this.ok = '';
@@ -143,7 +138,7 @@ CoffeeLint is freely distributable under the MIT license.
};
Reporter.prototype.publish = function() {
- var errors, path, summary, _ref;
+ var errors, summary, _ref;
this.print("");
_ref = this.errorReport.paths;
for (path in _ref) {
@@ -206,14 +201,12 @@ CoffeeLint is freely distributable under the MIT license.
__extends(CSVReporter, _super);
- CSVReporter.name = 'CSVReporter';
-
function CSVReporter() {
return CSVReporter.__super__.constructor.apply(this, arguments);
}
CSVReporter.prototype.publish = function() {
- var e, errors, f, path, _ref, _results;
+ var e, errors, f, _ref, _results;
_ref = this.errorReport.paths;
_results = [];
for (path in _ref) {
@@ -237,7 +230,7 @@ CoffeeLint is freely distributable under the MIT license.
})(Reporter);
lintFiles = function(paths, config) {
- var errorReport, path, source, _i, _len;
+ var errorReport, source, _i, _len;
errorReport = new ErrorReport();
for (_i = 0, _len = paths.length; _i < _len; _i++) {
path = paths[_i];
View

Some generated files are not rendered by default. Learn more.

Oops, something went wrong.
View
@@ -95,6 +95,10 @@ RULES =
level : IGNORE
message : 'Operators must be spaced properly'
+ no_implicit_return :
+ level : IGNORE
+ message : 'Implicit returns are forbidden'
+
# Some repeatedly used regular expressions.
regexes =
@@ -528,9 +532,27 @@ class ASTLinter
error = createError 'cyclomatic_complexity', attrs
@errors.push error if error
+ if name == 'Assign' and node.value.constructor.name == 'Code'
+ @lintImplicitReturn(node)
+
# Return the complexity for the benefit of parent nodes.
return complexity
+ # Check for an implicit return, but only if it's not a constructor.
+ lintImplicitReturn : (node) ->
+ rule = @config.no_implicit_return
+ funcname = node.variable?.base?.value
+ if node.context == 'object' and funcname == 'constructor'
+ return
+ func = node.value.body.expressions
+ if func.length and not func[func.length - 1].expression?
+ attrs = {
+ context: funcname
+ level: rule.level
+ }
+ error = createError 'no_implicit_return', attrs
+ @errors.push error if error
+
# Merge default and user configuration.
mergeDefaultConfig = (userConfig) ->
@@ -0,0 +1,50 @@
+path = require 'path'
+vows = require 'vows'
+assert = require 'assert'
+coffeelint = require path.join('..', 'lib', 'coffeelint')
+
+vows.describe('return').addBatch({
+
+ 'Implicit returns' :
+
+ topic : () ->
+ '''
+ double = (x) ->
+ x*2
+
+ triple = (x) ->
+ return x*3
+
+ noop = ->
+
+ complex = (x) ->
+ x += 2
+ x -= 5
+ x = x * 4
+ x / 2
+
+ class Cat
+ constructor: ->
+ @howhigh = 5
+ roar: -> return 'meow'
+ jump: => @howhigh
+ '''
+
+ 'are allowed by default' : (source) ->
+ errors = coffeelint.lint(source)
+ assert.isArray(errors)
+ assert.isEmpty(errors)
+
+ 'can be forbidden' : (source) ->
+ config = {no_implicit_return : {level:'error'}}
+ errors = coffeelint.lint(source, config)
+ assert.isArray(errors)
+ assert.lengthOf(errors, 3)
+ for error in errors
+ assert.equal(error.message, 'Implicit returns are forbidden')
+ assert.equal(error.rule, 'no_implicit_return')
+
+ assert.deepEqual(errors.map((e) -> e.context),
+ ['double', 'complex', 'jump'])
+
+}).export(module)

0 comments on commit dd52a20

Please sign in to comment.