diff --git a/docs/rules/README.md b/docs/rules/README.md index 0a3ac392195..3a17f174e2d 100644 --- a/docs/rules/README.md +++ b/docs/rules/README.md @@ -161,7 +161,7 @@ These rules relate to style guidelines, and are therefore quite subjective: * [computed-property-spacing](computed-property-spacing.md): enforce consistent spacing inside computed property brackets (fixable) * [consistent-this](consistent-this.md): enforce consistent naming when capturing the current execution context * [eol-last](eol-last.md): enforce at least one newline at the end of files (fixable) -* [func-names](func-names.md): enforce named `function` expressions +* [func-names](func-names.md): require or disallow named `function` expressions * [func-style](func-style.md): enforce the consistent use of either `function` declarations or expressions * [id-blacklist](id-blacklist.md): disallow specified identifiers * [id-length](id-length.md): enforce minimum and maximum identifier lengths diff --git a/docs/rules/func-names.md b/docs/rules/func-names.md index f18fd1f2718..d8754833da9 100644 --- a/docs/rules/func-names.md +++ b/docs/rules/func-names.md @@ -1,4 +1,4 @@ -# Require Function Expressions to have a Name (func-names) +# Require or disallow named `function` expressions (func-names) A pattern that's becoming more common is to give function expressions names to aid in debugging. For example: @@ -10,7 +10,17 @@ Adding the second `bar` in the above example is optional. If you leave off the ## Rule Details -Examples of **incorrect** code for this rule: +This rule can enforce or disallow the use of named function expressions. + +## Options + +This rule has a string option: + +* `"always"` (default) requires function expressions to have a name +* `"never"` disallows named function expressions + + +Examples of **incorrect** code for this rule with the default `"always"` option: ```js /*eslint func-names: "error"*/ @@ -22,7 +32,7 @@ Foo.prototype.bar = function() {}; }()) ``` -Examples of **correct** code for this rule: +Examples of **correct** code for this rule with the default `"always"` option: ```js /*eslint func-names: "error"*/ @@ -34,6 +44,35 @@ Foo.prototype.bar = function bar() {}; }()) ``` +Examples of **incorrect** code for this rule with the `"never"` option: + +```js +/*eslint func-names: "error"*/ + +Foo.prototype.bar = function bar() {}; + +(function bar() { + // ... +}()) +``` + +Examples of **correct** code for this rule with the `"never"` option: + +```js +/*eslint func-names: "error"*/ + +Foo.prototype.bar = function() {}; + +(function() { + // ... +}()) +``` + ## Further Reading * [Functions Explained](http://markdaggett.com/blog/2013/02/15/functions-explained/) + +## Compatibility + +* **JSCS**: [requireAnonymousFunctions](http://jscs.info/rule/requireAnonymousFunctions) +* **JSCS**: [disallowAnonymousFunctions](http://jscs.info/rule/disallowAnonymousFunctions) diff --git a/lib/rules/func-names.js b/lib/rules/func-names.js index 51a1ffe0468..44b989b2c47 100644 --- a/lib/rules/func-names.js +++ b/lib/rules/func-names.js @@ -12,15 +12,20 @@ module.exports = { meta: { docs: { - description: "enforce named `function` expressions", + description: "require or disallow named `function` expressions", category: "Stylistic Issues", recommended: false }, - schema: [] + schema: [ + { + enum: ["always", "never"] + } + ] }, create: function(context) { + var never = context.options[0] === "never"; /** * Determines whether the current FunctionExpression node is a get, set, or @@ -44,8 +49,14 @@ module.exports = { var name = node.id && node.id.name; - if (!name && !isObjectOrClassMethod()) { - context.report(node, "Missing function expression name."); + if (never) { + if (name) { + context.report(node, "Unexpected function expression name."); + } + } else { + if (!name && !isObjectOrClassMethod()) { + context.report(node, "Missing function expression name."); + } } } }; diff --git a/tests/lib/rules/func-names.js b/tests/lib/rules/func-names.js index b936303c905..1def7b18888 100644 --- a/tests/lib/rules/func-names.js +++ b/tests/lib/rules/func-names.js @@ -33,6 +33,44 @@ ruleTester.run("func-names", rule, { { code: "class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}}", parserOptions: { ecmaVersion: 6 } + }, + { + code: "function foo() {}", + options: ["always"] + }, + { + code: "var a = function foo() {};", + options: ["always"] + }, + { + code: "function foo() {}", + options: ["never"] + }, + { + code: "var a = function() {};", + options: ["never"] + }, + { + code: "var foo = {bar: function() {}};", + options: ["never"] + }, + { + code: "$('#foo').click(function() {});", + options: ["never"] + }, + { + code: "Foo.prototype.bar = function() {};", + options: ["never"] + }, + { + code: "class A { constructor(){} foo(){} get bar(){} set baz(value){} static qux(){}}", + options: ["never"], + parserOptions: { ecmaVersion: 6 } + }, + { + code: "({ foo() {} });", + options: ["never"], + parserOptions: { ecmaVersion: 6 } } ], invalid: [ @@ -41,6 +79,21 @@ ruleTester.run("func-names", rule, { { code: "f(function(){})", errors: [{ message: "Missing function expression name.", type: "FunctionExpression"}] }, { code: "var a = new Date(function() {});", errors: [{ message: "Missing function expression name.", type: "FunctionExpression"}] }, { code: "var test = function(d, e, f) {};", errors: [{ message: "Missing function expression name.", type: "FunctionExpression"}] }, - { code: "new function() {}", errors: [{ message: "Missing function expression name.", type: "FunctionExpression"}] } + { code: "new function() {}", errors: [{ message: "Missing function expression name.", type: "FunctionExpression"}] }, + { + code: "var x = function named() {};", + options: ["never"], + errors: [{ message: "Unexpected function expression name.", type: "FunctionExpression"}] + }, + { + code: "Foo.prototype.bar = function named() {};", + options: ["never"], + errors: [{ message: "Unexpected function expression name.", type: "FunctionExpression"}] + }, + { + code: "({foo: function named() {}})", + options: ["never"], + errors: [{ message: "Unexpected function expression name.", type: "FunctionExpression"}] + } ] });