forked from jscs-dev/node-jscs
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
requireMatchingFunctionName: requires member and property names to ma…
…tch 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 jscs-dev#846 Closes jscs-dev#850
- Loading branch information
Showing
4 changed files
with
188 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
var assert = require('assert'); | ||
|
||
module.exports = function() {}; | ||
|
||
module.exports.prototype = { | ||
configure: function(requireMatchingFunctionName) { | ||
assert( | ||
requireMatchingFunctionName === true, | ||
'requireMatchingFunctionName option requires true value or should be removed' | ||
); | ||
}, | ||
|
||
getOptionName: function() { | ||
return 'requireMatchingFunctionName'; | ||
}, | ||
|
||
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) { | ||
// We don't care about anonymous functions as | ||
// those should be enforced by separate rule | ||
if (isAnonymousFunction(assignment.right)) { | ||
return; | ||
} | ||
|
||
if (assignment.left.property.name !== assignment.right.id.name) { | ||
errors.add( | ||
'Function name does not match member name', | ||
assignment.loc.start | ||
); | ||
} | ||
} | ||
|
||
function checkForProperty(property, errors) { | ||
// We don't care about anonymous functions as | ||
// those should be enforced by separate rule | ||
if (isAnonymousFunction(property.value)) { | ||
return; | ||
} | ||
|
||
if (property.key.name !== property.value.id.name) { | ||
errors.add( | ||
'Function name does not match property name', | ||
property.loc.start | ||
); | ||
} | ||
} | ||
|
||
function isAnonymousFunction(node) { | ||
return !node.id; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
var Checker = require('../../lib/checker'); | ||
var assert = require('assert'); | ||
|
||
describe('rules/require-matching-function-name', function() { | ||
var checker; | ||
|
||
beforeEach(function() { | ||
checker = new Checker(); | ||
checker.registerDefaultRules(); | ||
}); | ||
|
||
describe('option value true', function() { | ||
beforeEach(function() { | ||
checker.configure({ requireMatchingFunctionName: true }); | ||
}); | ||
|
||
// TODO: | ||
// - assigning function to variable (both names should match) | ||
// - 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 | ||
|
||
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 NOT report function name mismatch when assign anonymous to member', function() { | ||
assertNoError('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 NOT report function name mismatch when assign anonymous to property', function() { | ||
assertNoError('var test = {foo: function() {}};'); | ||
}); | ||
|
||
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, 'requireMatchingFunctionName'); | ||
assert.equal(errors[0].message, message); | ||
} | ||
|
||
function assertNoError(js) { | ||
var errors = checker.checkString(js).getErrorList(); | ||
assert.equal(errors.length, 0); | ||
} | ||
}); | ||
}); |