Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Commit

Permalink
New rules: (disallow|require)FunctionDeclarations
Browse files Browse the repository at this point in the history
Closes gh-569
  • Loading branch information
benesch authored and mikesherov committed Sep 23, 2014
1 parent bce7eda commit d735899
Show file tree
Hide file tree
Showing 6 changed files with 229 additions and 0 deletions.
91 changes: 91 additions & 0 deletions README.md
Expand Up @@ -2536,6 +2536,97 @@ $('#foo').click(function bar(){
};)
```

### disallowFunctionDeclarations

Disallows function declarations.

Type: `Boolean`

Values: `true`

#### Example

```js
"disallowFunctionDeclarations": true
```

##### Valid

```js
var expressed = function() {

};

var expressed = function deeply() {

};

$('#foo').click(function bar() {

};)
```

##### Invalid

```js
function stated() {

}
```

### requireFunctionDeclarations

Requires function declarations by disallowing assignment of functions
expressions to variables. Function expressions are allowed in all other
contexts, including when passed as function arguments or immediately invoked.

Assignment of function expressions to object members is also permitted, since
these can't be declared.

Type: `Boolean`

Values: `true`

#### Example

```js
"requireFunctionDeclarations": true
```

##### Valid

```js
function declared() {

};

(function iife() {
void 0;
})();

var obj = {
a: function () {}
};

obj.b = function () { };

$('#foo').click(function bar() {

};)
```

##### Invalid

```js
var expressed = function() {

};

var expressed = function deeply() {

};
```

### disallowNewlineBeforeBlockStatements

Disallows newline before opening curly brace of all block statements.
Expand Down
22 changes: 22 additions & 0 deletions lib/rules/disallow-function-declarations.js
@@ -0,0 +1,22 @@
var assert = require('assert');

module.exports = function() {};

module.exports.prototype = {
configure: function(disallowFunctionDeclarations) {
assert(
disallowFunctionDeclarations === true,
'disallowFunctionDeclarations option requires true value or should be removed'
);
},

getOptionName: function() {
return 'disallowFunctionDeclarations';
},

check: function(file, errors) {
file.iterateNodesByType('FunctionDeclaration', function(node) {
errors.add('Illegal function declaration', node.loc.start);
});
}
};
37 changes: 37 additions & 0 deletions lib/rules/require-function-declarations.js
@@ -0,0 +1,37 @@
var assert = require('assert');

module.exports = function() {};

module.exports.prototype = {
configure: function(requireFunctionDeclarations) {
assert(
requireFunctionDeclarations === true,
'requireFunctionDeclarations option requires true value or should be removed'
);
},

getOptionName: function() {
return 'requireFunctionDeclarations';
},

check: function(file, errors) {
file.iterateNodesByType(
'VariableDeclarator',
function(node) {
if (node.init && node.init.type === 'FunctionExpression') {
errors.add('Use a function declaration instead', node.loc.start);
}
}
);

file.iterateNodesByType(
'AssignmentExpression',
function(node) {
if (node.left.type !== 'MemberExpression' &&
node.right.type === 'FunctionExpression') {
errors.add('Use a function declaration instead', node.loc.start);
}
}
);
}
};
3 changes: 3 additions & 0 deletions lib/string-checker.js
Expand Up @@ -131,6 +131,9 @@ StringChecker.prototype = {

this.registerRule(new (require('./rules/require-anonymous-functions'))());
this.registerRule(new (require('./rules/disallow-anonymous-functions'))());

this.registerRule(new (require('./rules/require-function-declarations'))());
this.registerRule(new (require('./rules/disallow-function-declarations'))());
},

/**
Expand Down
29 changes: 29 additions & 0 deletions test/rules/disallow-function-declarations.js
@@ -0,0 +1,29 @@
var Checker = require('../../lib/checker');
var assert = require('assert');

describe('rules/disallow-function-declarations', function() {
var checker;

beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();

checker.configure({
disallowFunctionDeclarations: true
});
});

it('should report on function declarations', function() {
assert(checker.checkString('function declared() { }').getErrorCount() === 1);
});

it('should not report on anonymous function expressions', function() {
assert(checker.checkString('var expressed = function (){};').isEmpty());
assert(checker.checkString('var foo = {bar: function() {}};').isEmpty());
});

it('should not report on named function expressions', function() {
assert(checker.checkString('$("hi").click(function named(){});').isEmpty());
assert(checker.checkString('var x = function named(){};').isEmpty());
});
});
47 changes: 47 additions & 0 deletions test/rules/require-function-declarations.js
@@ -0,0 +1,47 @@
var Checker = require('../../lib/checker');
var assert = require('assert');

describe('rules/require-function-declarations', function() {
var checker;

beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();

checker.configure({
requireFunctionDeclarations: true
});
});

it('should report on anonymous function expression declarations', function() {
assert(checker.checkString('var anon = function() {};').getErrorCount() === 1);
});

it('should report on named function expression declarations', function() {
assert(checker.checkString('var named = function named() {};').getErrorCount() === 1);
});

it('should report on anonymous function expression assignments', function() {
assert(checker.checkString('var anon; anon = function() {};').getErrorCount() === 1);
});

it('should report on named function expression assignments', function() {
assert(checker.checkString('var named; named = function named() {};').getErrorCount() === 1);
});

it('should ignore member expression assignments', function() {
assert(checker.checkString('obj.a = function() {};').isEmpty());
});

it('should ignore IIFEs', function() {
assert(checker.checkString('(function() { void 0; })();').isEmpty());
});

it('should ignore function expressions in object literals', function() {
assert(checker.checkString('var foo = {bar: function() {}};').isEmpty());
});

it('should ignore function expressions in function calls', function() {
assert(checker.checkString('onclick(function() {})').isEmpty());
});
});

0 comments on commit d735899

Please sign in to comment.