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

Commit

Permalink
requireFunctionNameMatch: requires member and property names to match…
Browse files Browse the repository at this point in the history
… function names

Example of member name mismatch:

```js
function Test() {};
Test.prototype.foo = function bar() {};
```

Example of property name mismatch:

```js
var test = {foo: function bar() {}};
```

Fixes #846
Closes #850
  • Loading branch information
xaka committed Dec 22, 2014
1 parent 9aae17e commit 6c57462
Show file tree
Hide file tree
Showing 4 changed files with 168 additions and 0 deletions.
50 changes: 50 additions & 0 deletions README.md
Expand Up @@ -3697,6 +3697,56 @@ var a = 1;
[b].forEach(c);
```

### requireFunctionNameMatch

Requires member and property names to match function names, including anonymous.

Type: `Boolean`

Value: `true`

#### Example

```js
"requireFunctionNameMatch": true
```

##### Valid

```js
function Test() {};
Test.prototype.foo = function foo() {};
```

```js
var test = {foo: function foo() {}};
```

```js
var test = {};
test['foo'] = function foo() {};
```

##### Invalid

```js
function Test() {};
Test.prototype.foo = function bar() {};
```

```js
var test = {foo: function bar() {}};
```

```js
var test = {foo: function() {}};
```

```js
var test = {};
test['foo'] = function bar() {};
```

### ~~validateJSDoc~~

Please use the [JSCS-JSDoc](https://github.com/jscs-dev/jscs-jsdoc) plugin instead.
Expand Down
2 changes: 2 additions & 0 deletions lib/config/configuration.js
Expand Up @@ -595,6 +595,8 @@ Configuration.prototype.registerDefaultRules = function() {
this.registerRule(require('../rules/require-line-break-after-variable-assignment'));

this.registerRule(require('../rules/disallow-semicolons'));

this.registerRule(require('../rules/require-function-name-match'));
};

/**
Expand Down
58 changes: 58 additions & 0 deletions lib/rules/require-function-name-match.js
@@ -0,0 +1,58 @@
var assert = require('assert');

module.exports = function() {};

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

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

check: function(file, errors) {
file.iterateNodesByType(['FunctionExpression'], function(node) {
var checker;
switch (node.parentNode.type) {
// object.foo = function bar() {}
// object['foo'] = function bar() {}
case 'AssignmentExpression':
checker = checkForMember;
break;

// object = {foo: function bar() {}}
case 'Property':
checker = checkForProperty;
break;
}

if (checker) {
checker(node.parentNode, errors);
}
});
}
};

function checkForMember(assignment, errors) {
// anonymous function OR names mismatch
if (!assignment.right.id || (assignment.left.property.name !== assignment.right.id.name)) {
errors.add(
'Function name does not match member name',
assignment.loc.start
);
}
}

function checkForProperty(property, errors) {
// anonymous function OR names mismatch
if (!property.value.id || (property.key.name !== property.value.id.name)) {
errors.add(
'Function name does not match property name',
property.loc.start
);
}
}
58 changes: 58 additions & 0 deletions test/rules/require-function-name-match.js
@@ -0,0 +1,58 @@
var Checker = require('../../lib/checker');
var assert = require('assert');

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

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

describe('option value true', function() {
beforeEach(function() {
checker.configure({ requireFunctionNameMatch: true });
});

it('should report function name mismatch when assigning to member', function() {
assertErrorForMemberNameMismatch('function Test() {}; Test.prototype.foo = function bar() {};');
});

it('should report function name mismatch when assigning to member via ["..."]', function() {
assertErrorForMemberNameMismatch('var test = {}; test["foo"] = function bar() {};');
});

it('should report function name mismatch when assign anonymous to member', function() {
assertErrorForMemberNameMismatch('function Test() {}; Test.prototype.foo = function() {};');
});

it('should report function name mismatch when assigning to property', function() {
assertErrorForPropertyNameMismatch('var test = {foo: function bar() {}};');
});

it('should report function name mismatch when assign anonymous to property', function() {
assertErrorForPropertyNameMismatch('var test = {foo: function() {}};');
});

// TODO:
// - assigning function declaration to member
// - assigning function declaration to property
// For both cases we should track identifier back, check whether
// it's a function and if so, compare the names

function assertErrorForMemberNameMismatch(js) {
assertError(js, 'Function name does not match member name');
}

function assertErrorForPropertyNameMismatch(js) {
assertError(js, 'Function name does not match property name');
}

function assertError(js, message) {
var errors = checker.checkString(js).getErrorList();
assert(errors.length);
assert.equal(errors[0].rule, 'requireFunctionNameMatch');
assert.equal(errors[0].message, message);
}
});
});

0 comments on commit 6c57462

Please sign in to comment.