From de3427b5f8a36c88df6ae4045182a8e9b6625805 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 14 Apr 2017 22:46:22 +0800 Subject: [PATCH 01/24] New: getter-return (#8449) --- conf/eslint-recommended.js | 1 + docs/rules/getter-return.md | 5 ++ lib/rules/getter-return.js | 143 +++++++++++++++++++++++++++++++ tests/lib/rules/getter-return.js | 48 +++++++++++ 4 files changed, 197 insertions(+) create mode 100644 docs/rules/getter-return.md create mode 100644 lib/rules/getter-return.js create mode 100644 tests/lib/rules/getter-return.js diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js index 0d8d19e447d..1a2e2f8e7ff 100755 --- a/conf/eslint-recommended.js +++ b/conf/eslint-recommended.js @@ -48,6 +48,7 @@ module.exports = { "func-names": "off", "func-style": "off", "generator-star-spacing": "off", + "getter-return": "off", "global-require": "off", "guard-for-in": "off", "handle-callback-err": "off", diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md new file mode 100644 index 00000000000..e71ad4c9903 --- /dev/null +++ b/docs/rules/getter-return.md @@ -0,0 +1,5 @@ +# Enforces that a return statement is present in property getters (getter-return) + +## Rule Details + +## When Not To Use It diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js new file mode 100644 index 00000000000..e708997cd79 --- /dev/null +++ b/lib/rules/getter-return.js @@ -0,0 +1,143 @@ +/** + * @fileoverview Enforces that a return statement is present in property getters. + * @author Aladdin-ADD(hh_2013@foxmail.com) + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const astUtils = require("../ast-utils"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; + +/** + * Checks a given code path segment is reachable. + * + * @param {CodePathSegment} segment - A segment to check. + * @returns {boolean} `true` if the segment is reachable. + */ +function isReachable(segment) { + return segment.reachable; +} + +/** + * Gets a readable location. + * + * - FunctionExpression -> the function name or `function` keyword. + * - ArrowFunctionExpression -> `=>` token. + * + * @param {ASTNode} node - A function node to get. + * @param {SourceCode} sourceCode - A source code to get tokens. + * @returns {ASTNode|Token} The node or the token of a location. + */ +function getLocation(node, sourceCode) { + if (node.type === "ArrowFunctionExpression") { + return sourceCode.getTokenBefore(node.body); + } + return node.id || node; +} + +//------------------------------------------------------------------------------ +// Rule Definition +//------------------------------------------------------------------------------ + +module.exports = { + meta: { + docs: { + description: "enforce `return` statements in getters", + category: "Best Practices", + recommended: false + }, + + schema: [] + }, + + create(context) { + let funcInfo = { + upper: null, + codePath: null, + hasReturn: false, + shouldCheck: false, + node: null + }; + + /** + * Checks whether or not the last code path segment is reachable. + * Then reports this function if the segment is reachable. + * + * If the last code path segment is reachable, there are paths which are not + * returned or thrown. + * + * @param {ASTNode} node - A node to check. + * @returns {void} + */ + function checkLastSegment(node) { + if (funcInfo.shouldCheck && + funcInfo.codePath.currentSegments.some(isReachable) + ) { + context.report({ + node, + loc: getLocation(node, context.getSourceCode()).loc.start, + message: funcInfo.hasReturn + ? "Expected to return a value at the end of {{name}}." + : "Expected to return a value in {{name}}.", + data: { + name: astUtils.getFunctionNameWithKind(funcInfo.node) + } + }); + } + } + + return { + + // Stacks this function's information. + onCodePathStart(codePath, node) { + funcInfo = { + upper: funcInfo, + codePath, + hasReturn: false, + shouldCheck: + TARGET_NODE_TYPE.test(node.type) && + node.body.type === "BlockStatement" && + node.parent.kind === "get" && + !node.async && + !node.generator, + node + }; + }, + + // Pops this function's information. + onCodePathEnd() { + funcInfo = funcInfo.upper; + }, + + // Checks the return statement is valid. + ReturnStatement(node) { + if (funcInfo.shouldCheck) { + funcInfo.hasReturn = true; + + if (!node.argument) { + context.report({ + node, + message: "Expected to return a value in {{name}}.", + data: { + name: astUtils.getFunctionNameWithKind(funcInfo.node) + } + }); + } + } + }, + + // Reports a given function if the last path is reachable. + "FunctionExpression:exit": checkLastSegment, + "ArrowFunctionExpression:exit": checkLastSegment + }; + } +}; diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js new file mode 100644 index 00000000000..19ab85fcc5f --- /dev/null +++ b/tests/lib/rules/getter-return.js @@ -0,0 +1,48 @@ +/** + * @fileoverview Enforces that a return statement is present in property getters. + * @author Aladdin-ADD(hh_2013@foxmail.com) + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const rule = require("../../../lib/rules/getter-return"); +const RuleTester = require("../../../lib/testers/rule-tester"); + +//------------------------------------------------------------------------------ +// Tests +//------------------------------------------------------------------------------ + +const ruleTester = new RuleTester(); + +// TODO: data is not working, so specify a name: "getter 'bar'" +const noReturnMessage = "Expected to return a value in getter 'bar'."; +const noLastReturnMessage = "Expected to return a value at the end of getter 'bar'."; + +ruleTester.run("enforce-return-in-getter", rule, { + + valid: [ + { code: "var foo = { get: function(){} };" }, + { code: "var foo = { get bar(){return true;} };" }, + { code: "var foo = { bar(){return true;} };", env: { es6: true } }, + { code: "var foo = { bar(){} };", env: { es6: true } }, + + { code: "class foo { get bar(){return true;} }", env: { es6: true } }, + { code: "class foo { get(){} }", env: { es6: true } }, + { code: "class foo { get(){return true;} }", env: { es6: true } }, + + { code: "var get = function(){};" } + ], + + invalid: [ + + // TODO: why data: { name: "getter 'bar'"} is not working? + { code: "var foo = { get bar() {return;} }", env: { es6: true }, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return true;}} }", env: { es6: true }, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} }", env: { es6: true }, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] } + + ] +}); From 9723ee00c581de30c9dfbeea5de27cfd5855196e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 2 May 2017 06:10:31 +0800 Subject: [PATCH 02/24] add more test --- lib/rules/getter-return.js | 20 ++++++------- tests/lib/rules/getter-return.js | 48 ++++++++++++++++++++++++-------- 2 files changed, 45 insertions(+), 23 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index e708997cd79..3e31b9320b3 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -15,7 +15,7 @@ const astUtils = require("../ast-utils"); // Helpers //------------------------------------------------------------------------------ -const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/; +const TARGET_NODE_TYPE = /^FunctionExpression$/; /** * Checks a given code path segment is reachable. @@ -31,16 +31,11 @@ function isReachable(segment) { * Gets a readable location. * * - FunctionExpression -> the function name or `function` keyword. - * - ArrowFunctionExpression -> `=>` token. * * @param {ASTNode} node - A function node to get. - * @param {SourceCode} sourceCode - A source code to get tokens. * @returns {ASTNode|Token} The node or the token of a location. */ -function getLocation(node, sourceCode) { - if (node.type === "ArrowFunctionExpression") { - return sourceCode.getTokenBefore(node.body); - } +function getLocation(node) { return node.id || node; } @@ -99,6 +94,8 @@ module.exports = { // Stacks this function's information. onCodePathStart(codePath, node) { + const parent = node.parent; + funcInfo = { upper: funcInfo, codePath, @@ -106,9 +103,9 @@ module.exports = { shouldCheck: TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement" && - node.parent.kind === "get" && - !node.async && - !node.generator, + + // check if it is a "getter", or a method named "get". + (parent.kind === "get" || astUtils.getStaticPropertyName(parent) === "get"), node }; }, @@ -136,8 +133,7 @@ module.exports = { }, // Reports a given function if the last path is reachable. - "FunctionExpression:exit": checkLastSegment, - "ArrowFunctionExpression:exit": checkLastSegment + "FunctionExpression:exit": checkLastSegment }; } }; diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 19ab85fcc5f..0b9d34856bc 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -19,30 +19,56 @@ const RuleTester = require("../../../lib/testers/rule-tester"); const ruleTester = new RuleTester(); // TODO: data is not working, so specify a name: "getter 'bar'" -const noReturnMessage = "Expected to return a value in getter 'bar'."; -const noLastReturnMessage = "Expected to return a value at the end of getter 'bar'."; +const name = "getter 'bar'"; +const noReturnMessage = `Expected to return a value in ${name}.`; +const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; +const parserOptions = { ecmaVersion: 6 }; ruleTester.run("enforce-return-in-getter", rule, { valid: [ - { code: "var foo = { get: function(){} };" }, + + // test obj: get { code: "var foo = { get bar(){return true;} };" }, - { code: "var foo = { bar(){return true;} };", env: { es6: true } }, - { code: "var foo = { bar(){} };", env: { es6: true } }, + { code: "var foo = { bar: function(){return true;} };" }, + { code: "var foo = { bar(){return true;} };", parserOptions }, + { code: "var foo = { bar: function(){} };" }, + { code: "var foo = { bar(){} };", parserOptions }, + + // test class: get + { code: "class foo { get bar(){return true;} }", parserOptions }, + { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }", parserOptions }, + { code: "class foo { get(){return true;} }", parserOptions }, - { code: "class foo { get bar(){return true;} }", env: { es6: true } }, - { code: "class foo { get(){} }", env: { es6: true } }, - { code: "class foo { get(){return true;} }", env: { es6: true } }, + // add object.defineProperty + { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, + // not getter. { code: "var get = function(){};" } ], invalid: [ // TODO: why data: { name: "getter 'bar'"} is not working? - { code: "var foo = { get bar() {return;} }", env: { es6: true }, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return true;}} }", env: { es6: true }, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} }", env: { es6: true }, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] } + // test obj: get + { code: "var foo = { get bar() {return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar() {return; ;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar() {return 1; return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar() {return; return 1;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return true;} return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + + // test class: get + { code: "class foo { get bar(){return;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "class foo { get bar(){if(bar) {return true;}} }", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "class foo { get bar(){if(bar) {return;} return true;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + + // add object.defineProperty + { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", errors: [{ message: "Expected to return a value in method 'get'.", data: { name: "getter 'bar'" } }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'.", data: { name: "getter 'bar'" } }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", errors: [{ message: "Expected to return a value in method 'get'.", data: { name: "getter 'bar'" } }] } ] }); From 98f9e7cd478c7f571b6d141ca6f2aa10899654d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 2 May 2017 19:14:52 +0800 Subject: [PATCH 03/24] add test --- tests/lib/rules/getter-return.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 0b9d34856bc..a489b636663 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -51,6 +51,7 @@ ruleTester.run("enforce-return-in-getter", rule, { // TODO: why data: { name: "getter 'bar'"} is not working? // test obj: get + { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "var foo = { get bar() {return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "var foo = { get bar() {return; ;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "var foo = { get bar() {return 1; return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, @@ -61,6 +62,7 @@ ruleTester.run("enforce-return-in-getter", rule, { { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, // test class: get + { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "class foo { get bar(){return;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "class foo { get bar(){if(bar) {return true;}} }", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, { code: "class foo { get bar(){if(bar) {return;} return true;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, From 8983a8350906c934d2288d94e30d120aee5eff6c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 2 May 2017 20:08:37 +0800 Subject: [PATCH 04/24] Docs: for rule getter-return --- docs/rules/getter-return.md | 75 +++++++++++++++++++++++++++++++++++++ 1 file changed, 75 insertions(+) diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md index e71ad4c9903..bda0524dfd9 100644 --- a/docs/rules/getter-return.md +++ b/docs/rules/getter-return.md @@ -1,5 +1,80 @@ # Enforces that a return statement is present in property getters (getter-return) +The get syntax binds an object property to a function that will be called when that property is looked up. It is firstly introduced in ECMAScript 5: + +```js + var p = { + get name(){ + return "nicholas"; + } + }; + + Object.defineProperty(p, "age", { + get: function (){ + return 17; + } + }); +``` + +Note that every `getter` is expected to return a value. + ## Rule Details +This rule enforces that a return statement is present in property getters. + +Examples of **incorrect** code for this rule: + +```js +/*eslint getter-return: "error"*/ + +p = { + get name(){ + // no returns. + } +}; + +Object.defineProperty(p, "age", { + get: function (){ + // no returns. + } +}); + +class P{ + get name(){ + // no returns. + } +} +``` + +Examples of **correct** code for this rule: + +```js +/*eslint getter-return: "error"*/ + +p = { + get name(){ + return "nicholas"; + } +}; + +Object.defineProperty(p, "age", { + get: function (){ + return 18; + } +}); + +class P{ + get name(){ + return "nicholas"; + } +} +``` + ## When Not To Use It + +If your project will not be using getter you do not need this rule. + +## Further Reading + +* [MDN: Functions getter](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/get) +* [Understanding ES6: Accessor Properties](https://leanpub.com/understandinges6/read/#leanpub-auto-accessor-properties) From b622d920b446db8b77f1acc38824716efe5aa945 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 9 May 2017 04:46:21 +0800 Subject: [PATCH 05/24] add option: noImplicit --- lib/rules/getter-return.js | 19 +++++++-- tests/lib/rules/getter-return.js | 70 ++++++++++++++++++++------------ 2 files changed, 61 insertions(+), 28 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 3e31b9320b3..ba081853f63 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -50,11 +50,23 @@ module.exports = { category: "Best Practices", recommended: false }, - - schema: [] + fixable: null, + schema: [ + { + type: "object", + properties: { + noImplicit: { + type: "boolean" + } + } + } + ] }, create(context) { + + const options = context.options[0] || {}; + let funcInfo = { upper: null, codePath: null, @@ -120,7 +132,8 @@ module.exports = { if (funcInfo.shouldCheck) { funcInfo.hasReturn = true; - if (!node.argument) { + // if noImplicit: true, should also check node.argument + if (options.noImplicit && !node.argument) { context.report({ node, message: "Expected to return a value in {{name}}.", diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index a489b636663..fab0a9a2030 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -23,54 +23,74 @@ const name = "getter 'bar'"; const noReturnMessage = `Expected to return a value in ${name}.`; const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; const parserOptions = { ecmaVersion: 6 }; +const options = [{ noImplicit: true }]; ruleTester.run("enforce-return-in-getter", rule, { valid: [ - // test obj: get + // test obj: get, option: {noImplicit: false} { code: "var foo = { get bar(){return true;} };" }, + { code: "var foo = { get bar(){return;} };" }, { code: "var foo = { bar: function(){return true;} };" }, + { code: "var foo = { bar: function(){return;} };" }, { code: "var foo = { bar(){return true;} };", parserOptions }, - { code: "var foo = { bar: function(){} };" }, - { code: "var foo = { bar(){} };", parserOptions }, + { code: "var foo = { bar(){return;} };", parserOptions }, - // test class: get + // test class: get, option: {noImplicit: false} { code: "class foo { get bar(){return true;} }", parserOptions }, { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }", parserOptions }, + { code: "class foo { get bar(){if(baz){return;} else {return false;} } }", parserOptions }, { code: "class foo { get(){return true;} }", parserOptions }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [] }, - // add object.defineProperty + // test object.defineProperty(s), option: {noImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, + { code: "Object.defineProperty(foo, \"bar\", { get: function () {return;}});" }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });" }, + + // test option: {noImplicit: true} + { code: "var foo = { get bar(){return true;} };", options }, + { code: "class foo { get bar(){return true;} }", options, parserOptions }, + { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, // not getter. - { code: "var get = function(){};" } + { code: "var get = function(){};" }, + { code: "var get = function(){ return true; };" }, + { code: "var foo = { bar: function(){} };" }, + { code: "var foo = { bar: function(){ return true; } };" }, + { code: "var foo = { bar(){} };", parserOptions }, + { code: "var foo = { bar(){ return true; } };", parserOptions } ], invalid: [ - // TODO: why data: { name: "getter 'bar'"} is not working? // test obj: get - { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar() {return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar() {return; ;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar() {return 1; return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar() {return; return 1;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return true;} return;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, + { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {return; ;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {return; return 1;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;} return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, // test class: get - { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "class foo { get bar(){return;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "class foo { get bar(){if(bar) {return true;}} }", parserOptions, errors: [{ message: noLastReturnMessage, data: { name: "getter 'bar'" } }] }, - { code: "class foo { get bar(){if(bar) {return;} return true;} }", parserOptions, errors: [{ message: noReturnMessage, data: { name: "getter 'bar'" } }] }, - - // add object.defineProperty - { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", errors: [{ message: "Expected to return a value in method 'get'.", data: { name: "getter 'bar'" } }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'.", data: { name: "getter 'bar'" } }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", errors: [{ message: "Expected to return a value in method 'get'.", data: { name: "getter 'bar'" } }] } + { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){return;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){if(bar) {return true;}} }", options, parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "class foo { get bar(){if(bar) {return;} return true;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, + + // test object.defineProperty + { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", options: [{ noImplicit: true }], errors: [{ message: "Expected to return a value in method 'get'." }] }, + + // test option: {noImplicit: true} + { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] } ] }); From 6c25dbe9cb1c85b7cbbeb0036177195ad9ab3eb1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 9 May 2017 04:47:41 +0800 Subject: [PATCH 06/24] 1.update category. 2.update comments. --- lib/rules/getter-return.js | 2 +- tests/lib/rules/getter-return.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index ba081853f63..84fd2ae67f9 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -47,7 +47,7 @@ module.exports = { meta: { docs: { description: "enforce `return` statements in getters", - category: "Best Practices", + category: "Possible Errors", recommended: false }, fixable: null, diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index fab0a9a2030..d2a9d4d3eda 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -18,14 +18,14 @@ const RuleTester = require("../../../lib/testers/rule-tester"); const ruleTester = new RuleTester(); -// TODO: data is not working, so specify a name: "getter 'bar'" +// data is not working, so specify a name: "getter 'bar'" const name = "getter 'bar'"; const noReturnMessage = `Expected to return a value in ${name}.`; const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; const parserOptions = { ecmaVersion: 6 }; const options = [{ noImplicit: true }]; -ruleTester.run("enforce-return-in-getter", rule, { +ruleTester.run("getter-return", rule, { valid: [ From 6bc00fdcea587024aac4b001a6f5b7d28105aa06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Tue, 9 May 2017 05:24:09 +0800 Subject: [PATCH 07/24] add more tests: IIFE... --- tests/lib/rules/getter-return.js | 35 ++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 13 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index d2a9d4d3eda..366d8a6e9a6 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -36,6 +36,8 @@ ruleTester.run("getter-return", rule, { { code: "var foo = { bar: function(){return;} };" }, { code: "var foo = { bar(){return true;} };", parserOptions }, { code: "var foo = { bar(){return;} };", parserOptions }, + { code: "var foo = { bar(){~function (){}();return;} };", parserOptions }, + { code: "var foo = { bar(){~function (){return true;}();return;} };", parserOptions }, // test class: get, option: {noImplicit: false} { code: "class foo { get bar(){return true;} }", parserOptions }, @@ -43,12 +45,18 @@ ruleTester.run("getter-return", rule, { { code: "class foo { get bar(){if(baz){return;} else {return false;} } }", parserOptions }, { code: "class foo { get(){return true;} }", parserOptions }, { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [] }, + { code: "var foo = { get bar(){ ~function (){ return true; }(); return; } };", parserOptions, errors: [] }, + { code: "var foo = { get bar(){ ~function (){}(); return; } };", parserOptions, errors: [] }, // test object.defineProperty(s), option: {noImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });" }, + { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){ return true; }();return true;}});" }, + { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){}();return;}});" }, + { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" }, + { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){}(); return;}} });" }, // test option: {noImplicit: true} { code: "var foo = { get bar(){return true;} };", options }, @@ -67,30 +75,31 @@ ruleTester.run("getter-return", rule, { invalid: [ - // test obj: get + // test obj: get, option: {noImplicit: false} { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, + + // test class: get, option: {noImplicit: false} + { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, + + // test object.defineProperty, option: {noImplicit: false} + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + + // test option: {noImplicit: true} { code: "var foo = { get bar() {return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {return; ;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {return; return 1;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, { code: "var foo = { get bar(){if(bar) {return true;} return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - - // test class: get - { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "class foo { get bar(){return;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "class foo { get bar(){if(bar) {return true;}} }", options, parserOptions, errors: [{ message: noLastReturnMessage }] }, { code: "class foo { get bar(){if(bar) {return;} return true;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, - - // test object.defineProperty { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", options: [{ noImplicit: true }], errors: [{ message: "Expected to return a value in method 'get'." }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, - // test option: {noImplicit: true} - { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] } + { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] } ] }); From 40b1c8f6a5ae0d911884b3063d9077d5edbb6e6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 4 Jun 2017 14:23:59 +0800 Subject: [PATCH 08/24] update: change option name & default val --- lib/rules/getter-return.js | 8 ++++---- tests/lib/rules/getter-return.js | 19 ++++++++++--------- 2 files changed, 14 insertions(+), 13 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 84fd2ae67f9..10a276617f7 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -55,7 +55,7 @@ module.exports = { { type: "object", properties: { - noImplicit: { + allowImplicit: { type: "boolean" } } @@ -65,7 +65,7 @@ module.exports = { create(context) { - const options = context.options[0] || {}; + const options = context.options[0] || { allowImplicit: false }; let funcInfo = { upper: null, @@ -132,8 +132,8 @@ module.exports = { if (funcInfo.shouldCheck) { funcInfo.hasReturn = true; - // if noImplicit: true, should also check node.argument - if (options.noImplicit && !node.argument) { + // if allowImplicit: true, should also check node.argument + if (options.allowImplicit && !node.argument) { context.report({ node, message: "Expected to return a value in {{name}}.", diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 366d8a6e9a6..e79e5ace5c5 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -23,13 +23,13 @@ const name = "getter 'bar'"; const noReturnMessage = `Expected to return a value in ${name}.`; const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; const parserOptions = { ecmaVersion: 6 }; -const options = [{ noImplicit: true }]; +const options = [{ allowImplicit: true }]; ruleTester.run("getter-return", rule, { valid: [ - // test obj: get, option: {noImplicit: false} + // test obj: get, option: {allowImplicit: false} { code: "var foo = { get bar(){return true;} };" }, { code: "var foo = { get bar(){return;} };" }, { code: "var foo = { bar: function(){return true;} };" }, @@ -39,7 +39,7 @@ ruleTester.run("getter-return", rule, { { code: "var foo = { bar(){~function (){}();return;} };", parserOptions }, { code: "var foo = { bar(){~function (){return true;}();return;} };", parserOptions }, - // test class: get, option: {noImplicit: false} + // test class: get, option: {allowImplicit: false} { code: "class foo { get bar(){return true;} }", parserOptions }, { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }", parserOptions }, { code: "class foo { get bar(){if(baz){return;} else {return false;} } }", parserOptions }, @@ -48,7 +48,7 @@ ruleTester.run("getter-return", rule, { { code: "var foo = { get bar(){ ~function (){ return true; }(); return; } };", parserOptions, errors: [] }, { code: "var foo = { get bar(){ ~function (){}(); return; } };", parserOptions, errors: [] }, - // test object.defineProperty(s), option: {noImplicit: false} + // test object.defineProperty(s), option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, @@ -58,7 +58,8 @@ ruleTester.run("getter-return", rule, { { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" }, { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){}(); return;}} });" }, - // test option: {noImplicit: true} + + // test option: {allowImplicit: true} { code: "var foo = { get bar(){return true;} };", options }, { code: "class foo { get bar(){return true;} }", options, parserOptions }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, @@ -75,18 +76,18 @@ ruleTester.run("getter-return", rule, { invalid: [ - // test obj: get, option: {noImplicit: false} + // test obj: get, option: {allowImplicit: false} { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, - // test class: get, option: {noImplicit: false} + // test class: get, option: {allowImplicit: false} { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, - // test object.defineProperty, option: {noImplicit: false} + // test object.defineProperty, option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, - // test option: {noImplicit: true} + // test option: {allowImplicit: true} { code: "var foo = { get bar() {return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {return; ;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {return; return 1;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, From c53493a99e215615507beeef9a06b4e4a9addc6a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 4 Jun 2017 14:29:17 +0800 Subject: [PATCH 09/24] docs: fix typo. --- docs/rules/getter-return.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md index bda0524dfd9..bab4cd8666f 100644 --- a/docs/rules/getter-return.md +++ b/docs/rules/getter-return.md @@ -1,6 +1,6 @@ # Enforces that a return statement is present in property getters (getter-return) -The get syntax binds an object property to a function that will be called when that property is looked up. It is firstly introduced in ECMAScript 5: +The get syntax binds an object property to a function that will be called when that property is looked up. It was first introduced in ECMAScript 5: ```js var p = { From fec1d29cdd3b155a2eb45b156067f3b8365a41c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 4 Jun 2017 15:13:11 +0800 Subject: [PATCH 10/24] update: additionalProperties & docs option --- docs/rules/getter-return.md | 6 ++++++ lib/rules/getter-return.js | 3 ++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md index bab4cd8666f..81f379309ad 100644 --- a/docs/rules/getter-return.md +++ b/docs/rules/getter-return.md @@ -70,6 +70,12 @@ class P{ } ``` +## Options + +This rule has an object option: + +* `"allowImplicit": false` (default) disallows implicitly return a value. + ## When Not To Use It If your project will not be using getter you do not need this rule. diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 10a276617f7..fa08d989470 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -58,7 +58,8 @@ module.exports = { allowImplicit: { type: "boolean" } - } + }, + additionalProperties: false } ] }, From 926356c82cd7c5e3a6465b186d00eb95af405b1b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Thu, 15 Jun 2017 16:48:24 +0100 Subject: [PATCH 11/24] fix: wrong option behavior & update tests --- lib/rules/getter-return.js | 2 +- tests/lib/rules/getter-return.js | 35 +++++++++----------------------- 2 files changed, 11 insertions(+), 26 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index fa08d989470..6ec0ff38c12 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -134,7 +134,7 @@ module.exports = { funcInfo.hasReturn = true; // if allowImplicit: true, should also check node.argument - if (options.allowImplicit && !node.argument) { + if (!options.allowImplicit && !node.argument) { context.report({ node, message: "Expected to return a value in {{name}}.", diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index e79e5ace5c5..5024b976d5e 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -31,39 +31,33 @@ ruleTester.run("getter-return", rule, { // test obj: get, option: {allowImplicit: false} { code: "var foo = { get bar(){return true;} };" }, - { code: "var foo = { get bar(){return;} };" }, { code: "var foo = { bar: function(){return true;} };" }, { code: "var foo = { bar: function(){return;} };" }, { code: "var foo = { bar(){return true;} };", parserOptions }, - { code: "var foo = { bar(){return;} };", parserOptions }, - { code: "var foo = { bar(){~function (){}();return;} };", parserOptions }, - { code: "var foo = { bar(){~function (){return true;}();return;} };", parserOptions }, // test class: get, option: {allowImplicit: false} { code: "class foo { get bar(){return true;} }", parserOptions }, { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }", parserOptions }, - { code: "class foo { get bar(){if(baz){return;} else {return false;} } }", parserOptions }, { code: "class foo { get(){return true;} }", parserOptions }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} };", parserOptions, errors: [] }, - { code: "var foo = { get bar(){ ~function (){ return true; }(); return; } };", parserOptions, errors: [] }, - { code: "var foo = { get bar(){ ~function (){}(); return; } };", parserOptions, errors: [] }, // test object.defineProperty(s), option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, - { code: "Object.defineProperty(foo, \"bar\", { get: function () {return;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, - { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });" }, { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){ return true; }();return true;}});" }, - { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){}();return;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" }, - { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){}(); return;}} });" }, - // test option: {allowImplicit: true} + { code: "var foo = { get bar() {return;} };", options }, { code: "var foo = { get bar(){return true;} };", options }, { code: "class foo { get bar(){return true;} }", options, parserOptions }, + { code: "class foo { get bar(){return;} }", options, parserOptions }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, + { code: "var foo = { get bar() {return;} };", options, parserOptions }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options, parserOptions }, + { code: "class foo { get bar(){return;} }", options, parserOptions }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options }, // not getter. { code: "var get = function(){};" }, @@ -88,18 +82,9 @@ ruleTester.run("getter-return", rule, { { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, // test option: {allowImplicit: true} - { code: "var foo = { get bar() {return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar() {return; ;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar() {return; return 1;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;} return;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){return;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){if(bar) {return true;}} }", options, parserOptions, errors: [{ message: noLastReturnMessage }] }, - { code: "class foo { get bar(){if(bar) {return;} return true;} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return;} return true;}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, - { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, - + { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] }, { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] } ] From b2ec492eb99ac78ffd832fde225049d28b10a74f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Thu, 15 Jun 2017 17:59:27 +0100 Subject: [PATCH 12/24] fix comment. --- lib/rules/getter-return.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 6ec0ff38c12..bced965f1b7 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -133,7 +133,7 @@ module.exports = { if (funcInfo.shouldCheck) { funcInfo.hasReturn = true; - // if allowImplicit: true, should also check node.argument + // if allowImplicit: false, should also check node.argument if (!options.allowImplicit && !node.argument) { context.report({ node, From b6bbdb8d473d3ece91e615767f31a7449b0169bc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 16 Jun 2017 02:36:26 +0800 Subject: [PATCH 13/24] del dulp test. --- tests/lib/rules/getter-return.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 5024b976d5e..e60d88f1e11 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -49,13 +49,11 @@ ruleTester.run("getter-return", rule, { // test option: {allowImplicit: true} { code: "var foo = { get bar() {return;} };", options }, { code: "var foo = { get bar(){return true;} };", options }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options }, { code: "class foo { get bar(){return true;} }", options, parserOptions }, { code: "class foo { get bar(){return;} }", options, parserOptions }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, - { code: "var foo = { get bar() {return;} };", options, parserOptions }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options, parserOptions }, - { code: "class foo { get bar(){return;} }", options, parserOptions }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options }, From dd4781129ce386e2841219ce44928d3b54e41716 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 16 Jun 2017 02:49:57 +0800 Subject: [PATCH 14/24] add more invalid tests. --- tests/lib/rules/getter-return.js | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index e60d88f1e11..809b7637250 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -71,19 +71,24 @@ ruleTester.run("getter-return", rule, { // test obj: get, option: {allowImplicit: false} { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;} ;} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar() { ~function () {return true;}} };", parserOptions, errors: [{ message: noReturnMessage }] }, // test class: get, option: {allowImplicit: false} { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){ if (baz) { return true; }}}", parserOptions, errors: [{ noLastReturnMessage }] }, + { code: "class foo { get bar(){ ~function () { return true; }}}", parserOptions, errors: [{ noLastReturnMessage }] }, - // test object.defineProperty, option: {allowImplicit: false} + // test object.defineProperty(s), option: {allowImplicit: false} + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage}] }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage}] }, + { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, // test option: {allowImplicit: true} { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] }, - { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] } + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] } ] }); From 5aa8c5bc47c3548af1c3f7128af0b0e95aff9e21 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 16 Jun 2017 02:56:32 +0800 Subject: [PATCH 15/24] add more tests. --- tests/lib/rules/getter-return.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 809b7637250..12d3e94354f 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -76,19 +76,21 @@ ruleTester.run("getter-return", rule, { // test class: get, option: {allowImplicit: false} { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, { code: "class foo { get bar(){ if (baz) { return true; }}}", parserOptions, errors: [{ noLastReturnMessage }] }, - { code: "class foo { get bar(){ ~function () { return true; }}}", parserOptions, errors: [{ noLastReturnMessage }] }, + { code: "class foo { get bar(){ ~function () { return true; }()}}", parserOptions, errors: [{ noLastReturnMessage }] }, // test object.defineProperty(s), option: {allowImplicit: false} - { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage}] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ noReturnMessage }] }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, - { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage}] }, + { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] }, { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, // test option: {allowImplicit: true} { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] } - + { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){if (baz) {return true;} } }", options, parserOptions, errors: [{ message: noLastReturnMessage }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] }, + { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] } ] }); From 8fbaa746a2627818c7c17a33f30a5585e129f06e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Fri, 16 Jun 2017 03:15:35 +0800 Subject: [PATCH 16/24] and more. --- tests/lib/rules/getter-return.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 12d3e94354f..ba5ac45d1c0 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -80,10 +80,11 @@ ruleTester.run("getter-return", rule, { // test object.defineProperty(s), option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ noReturnMessage }] }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ noReturnMessage }] }, { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] }, { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperies(foo, { bar: { get: function () {~function () { return true; }()}} });", options, errors: [{ noReturnMessage }] }, // test option: {allowImplicit: true} { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, From cbffeff53610dc683d04176104d15ee6d3596889 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sat, 24 Jun 2017 23:58:16 +0800 Subject: [PATCH 17/24] update: reg => string. --- lib/rules/getter-return.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index bced965f1b7..d077c2b62bc 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -15,7 +15,7 @@ const astUtils = require("../ast-utils"); // Helpers //------------------------------------------------------------------------------ -const TARGET_NODE_TYPE = /^FunctionExpression$/; +const TARGET_NODE_TYPE = "FunctionExpression"; /** * Checks a given code path segment is reachable. @@ -114,7 +114,7 @@ module.exports = { codePath, hasReturn: false, shouldCheck: - TARGET_NODE_TYPE.test(node.type) && + node.type === TARGET_NODE_TYPE && node.body.type === "BlockStatement" && // check if it is a "getter", or a method named "get". From 64847d3b1012395b0041bd526f660e0ea5593fbd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 25 Jun 2017 00:05:38 +0800 Subject: [PATCH 18/24] docs. --- docs/rules/getter-return.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md index 81f379309ad..018f09c4561 100644 --- a/docs/rules/getter-return.md +++ b/docs/rules/getter-return.md @@ -74,11 +74,11 @@ class P{ This rule has an object option: -* `"allowImplicit": false` (default) disallows implicitly return a value. +* `"allowImplicit": false` (default) disallows implicitly returning undefined with a return; statement. ## When Not To Use It -If your project will not be using getter you do not need this rule. +If your project will not be using ES5 property getters you do not need this rule. ## Further Reading From fbf2702b8e9833d778ce152f310c20971b7d1adc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 25 Jun 2017 00:13:49 +0800 Subject: [PATCH 19/24] rename func name. --- lib/rules/getter-return.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index d077c2b62bc..604d8e3016c 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -35,7 +35,7 @@ function isReachable(segment) { * @param {ASTNode} node - A function node to get. * @returns {ASTNode|Token} The node or the token of a location. */ -function getLocation(node) { +function getId(node) { return node.id || node; } @@ -92,7 +92,7 @@ module.exports = { ) { context.report({ node, - loc: getLocation(node, context.getSourceCode()).loc.start, + loc: getId(node, context.getSourceCode()).loc.start, message: funcInfo.hasReturn ? "Expected to return a value at the end of {{name}}." : "Expected to return a value in {{name}}.", From 396625a27fbdbfb9343193b7cec1269123a2d916 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 25 Jun 2017 00:14:42 +0800 Subject: [PATCH 20/24] set default parser option: ecmaVersion 6 --- tests/lib/rules/getter-return.js | 37 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index ba5ac45d1c0..f3008dd9cec 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -16,13 +16,12 @@ const RuleTester = require("../../../lib/testers/rule-tester"); // Tests //------------------------------------------------------------------------------ -const ruleTester = new RuleTester(); +const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); // data is not working, so specify a name: "getter 'bar'" const name = "getter 'bar'"; const noReturnMessage = `Expected to return a value in ${name}.`; const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; -const parserOptions = { ecmaVersion: 6 }; const options = [{ allowImplicit: true }]; ruleTester.run("getter-return", rule, { @@ -33,12 +32,12 @@ ruleTester.run("getter-return", rule, { { code: "var foo = { get bar(){return true;} };" }, { code: "var foo = { bar: function(){return true;} };" }, { code: "var foo = { bar: function(){return;} };" }, - { code: "var foo = { bar(){return true;} };", parserOptions }, + { code: "var foo = { bar(){return true;} };" }, // test class: get, option: {allowImplicit: false} - { code: "class foo { get bar(){return true;} }", parserOptions }, - { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }", parserOptions }, - { code: "class foo { get(){return true;} }", parserOptions }, + { code: "class foo { get bar(){return true;} }" }, + { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }" }, + { code: "class foo { get(){return true;} }" }, // test object.defineProperty(s), option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, @@ -50,8 +49,8 @@ ruleTester.run("getter-return", rule, { { code: "var foo = { get bar() {return;} };", options }, { code: "var foo = { get bar(){return true;} };", options }, { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options }, - { code: "class foo { get bar(){return true;} }", options, parserOptions }, - { code: "class foo { get bar(){return;} }", options, parserOptions }, + { code: "class foo { get bar(){return true;} }", options }, + { code: "class foo { get bar(){return;} }", options }, { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options }, @@ -62,21 +61,21 @@ ruleTester.run("getter-return", rule, { { code: "var get = function(){ return true; };" }, { code: "var foo = { bar: function(){} };" }, { code: "var foo = { bar: function(){ return true; } };" }, - { code: "var foo = { bar(){} };", parserOptions }, - { code: "var foo = { bar(){ return true; } };", parserOptions } + { code: "var foo = { bar(){} };" }, + { code: "var foo = { bar(){ return true; } };" } ], invalid: [ // test obj: get, option: {allowImplicit: false} - { code: "var foo = { get bar() {} };", parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;}} };", parserOptions, errors: [{ message: noLastReturnMessage }] }, - { code: "var foo = { get bar() { ~function () {return true;}} };", parserOptions, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {} };", errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar(){if(bar) {return true;}} };", errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar() { ~function () {return true;}} };", errors: [{ message: noReturnMessage }] }, // test class: get, option: {allowImplicit: false} - { code: "class foo { get bar(){} }", parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){ if (baz) { return true; }}}", parserOptions, errors: [{ noLastReturnMessage }] }, - { code: "class foo { get bar(){ ~function () { return true; }()}}", parserOptions, errors: [{ noLastReturnMessage }] }, + { code: "class foo { get bar(){} }", errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){ if (baz) { return true; }}}", errors: [{ noLastReturnMessage }] }, + { code: "class foo { get bar(){ ~function () { return true; }()}}", errors: [{ noLastReturnMessage }] }, // test object.defineProperty(s), option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage }] }, @@ -89,9 +88,9 @@ ruleTester.run("getter-return", rule, { // test option: {allowImplicit: true} { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, - { code: "class foo { get bar(){} }", options, parserOptions, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){if (baz) {return true;} } }", options, parserOptions, errors: [{ message: noLastReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, parserOptions, errors: [{ message: "Expected to return a value in method 'get'." }] }, + { code: "class foo { get bar(){} }", options, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){if (baz) {return true;} } }", options, errors: [{ message: noLastReturnMessage }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] } ] }); From a170476a514299f6277ae2fa254c0a061ebd8ca4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 25 Jun 2017 01:11:09 +0800 Subject: [PATCH 21/24] update --- lib/rules/getter-return.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 604d8e3016c..4048a56d185 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -15,8 +15,6 @@ const astUtils = require("../ast-utils"); // Helpers //------------------------------------------------------------------------------ -const TARGET_NODE_TYPE = "FunctionExpression"; - /** * Checks a given code path segment is reachable. * @@ -114,7 +112,7 @@ module.exports = { codePath, hasReturn: false, shouldCheck: - node.type === TARGET_NODE_TYPE && + node.type === "FunctionExpression" && node.body.type === "BlockStatement" && // check if it is a "getter", or a method named "get". From 9da8b401b73cb57513f8b3075b3264cd9e2efb6f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Sun, 25 Jun 2017 01:11:50 +0800 Subject: [PATCH 22/24] docs: add option example. --- docs/rules/getter-return.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/rules/getter-return.md b/docs/rules/getter-return.md index 018f09c4561..57f92065d42 100644 --- a/docs/rules/getter-return.md +++ b/docs/rules/getter-return.md @@ -76,6 +76,17 @@ This rule has an object option: * `"allowImplicit": false` (default) disallows implicitly returning undefined with a return; statement. +Examples of **correct** code for the `{ "allowImplicit": true }` option: + +```js +/*eslint getter-return: ["error", { allowImplicit: true }]*/ +p = { + get name(){ + return; // return undefined implicitly. + } +}; +``` + ## When Not To Use It If your project will not be using ES5 property getters you do not need this rule. From 17d35f85dc99850064186af79d74063fb6b886a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Wed, 28 Jun 2017 04:55:16 +0800 Subject: [PATCH 23/24] update msg. & tests. --- lib/rules/getter-return.js | 4 +- tests/lib/rules/getter-return.js | 67 +++++++++++++++++++------------- 2 files changed, 42 insertions(+), 29 deletions(-) diff --git a/lib/rules/getter-return.js b/lib/rules/getter-return.js index 4048a56d185..8a095ad296f 100644 --- a/lib/rules/getter-return.js +++ b/lib/rules/getter-return.js @@ -90,9 +90,9 @@ module.exports = { ) { context.report({ node, - loc: getId(node, context.getSourceCode()).loc.start, + loc: getId(node).loc.start, message: funcInfo.hasReturn - ? "Expected to return a value at the end of {{name}}." + ? "Expected {{name}} to always return a value." : "Expected to return a value in {{name}}.", data: { name: astUtils.getFunctionNameWithKind(funcInfo.node) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index f3008dd9cec..14eab2a1a96 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -21,36 +21,40 @@ const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } }); // data is not working, so specify a name: "getter 'bar'" const name = "getter 'bar'"; const noReturnMessage = `Expected to return a value in ${name}.`; -const noLastReturnMessage = `Expected to return a value at the end of ${name}.`; +const noLastReturnMessage = `Expected ${name} to always return a value.`; const options = [{ allowImplicit: true }]; ruleTester.run("getter-return", rule, { valid: [ - // test obj: get, option: {allowImplicit: false} + // test obj: get + // option: {allowImplicit: false} { code: "var foo = { get bar(){return true;} };" }, - { code: "var foo = { bar: function(){return true;} };" }, - { code: "var foo = { bar: function(){return;} };" }, - { code: "var foo = { bar(){return true;} };" }, - // test class: get, option: {allowImplicit: false} + // option: {allowImplicit: true} + { code: "var foo = { get bar() {return;} };", options }, + { code: "var foo = { get bar(){return true;} };", options }, + { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options }, + + // test class: get + // option: {allowImplicit: false} { code: "class foo { get bar(){return true;} }" }, { code: "class foo { get bar(){if(baz){return true;} else {return false;} } }" }, { code: "class foo { get(){return true;} }" }, - // test object.defineProperty(s), option: {allowImplicit: false} + // option: {allowImplicit: true} + { code: "class foo { get bar(){return true;} }", options }, + { code: "class foo { get bar(){return;} }", options }, + + // test object.defineProperty(s) + // option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){ return true; }();return true;}});" }, { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" }, - // test option: {allowImplicit: true} - { code: "var foo = { get bar() {return;} };", options }, - { code: "var foo = { get bar(){return true;} };", options }, - { code: "var foo = { get bar(){if(bar) {return;} return true;} };", options }, - { code: "class foo { get bar(){return true;} }", options }, - { code: "class foo { get bar(){return;} }", options }, + // option: {allowImplicit: true} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options }, @@ -59,37 +63,46 @@ ruleTester.run("getter-return", rule, { // not getter. { code: "var get = function(){};" }, { code: "var get = function(){ return true; };" }, - { code: "var foo = { bar: function(){} };" }, - { code: "var foo = { bar: function(){ return true; } };" }, { code: "var foo = { bar(){} };" }, - { code: "var foo = { bar(){ return true; } };" } + { code: "var foo = { bar(){ return true; } };" }, + { code: "var foo = { bar: function(){} };" }, + { code: "var foo = { bar(){ return true; } };" }, + { code: "var foo = { bar: function(){return;} };" }, + { code: "var foo = { bar: function(){return true;} };" } ], invalid: [ - // test obj: get, option: {allowImplicit: false} + // test obj: get + // option: {allowImplicit: false} { code: "var foo = { get bar() {} };", errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar(){if(bar) {return true;}} };", errors: [{ message: noLastReturnMessage }] }, + { code: "var foo = { get bar(){if(baz) {return true;}} };", errors: [{ message: noLastReturnMessage }] }, { code: "var foo = { get bar() { ~function () {return true;}} };", errors: [{ message: noReturnMessage }] }, - // test class: get, option: {allowImplicit: false} + // option: {allowImplicit: true} + { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, + { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, + + // test class: get + // option: {allowImplicit: false} { code: "class foo { get bar(){} }", errors: [{ message: noReturnMessage }] }, { code: "class foo { get bar(){ if (baz) { return true; }}}", errors: [{ noLastReturnMessage }] }, { code: "class foo { get bar(){ ~function () { return true; }()}}", errors: [{ noLastReturnMessage }] }, - // test object.defineProperty(s), option: {allowImplicit: false} + // option: {allowImplicit: true} + { code: "class foo { get bar(){} }", options, errors: [{ message: noReturnMessage }] }, + { code: "class foo { get bar(){if (baz) {return true;} } }", options, errors: [{ message: noLastReturnMessage }] }, + + // test object.defineProperty(s) + // option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", errors: [{ noReturnMessage }] }, - { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperty(foo, \"bar\", { get: function (){if(bar) {return true;}}});", errors: [{ message: "Expected method 'get' to always return a value." }] }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){ ~function () { return true; }()}});", errors: [{ noReturnMessage }] }, { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] }, - { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected to return a value at the end of method 'get'." }] }, + { code: "Object.defineProperies(foo, { bar: { get: function (){if(bar) {return true;}}}});", options, errors: [{ message: "Expected method 'get' to always return a value." }] }, { code: "Object.defineProperies(foo, { bar: { get: function () {~function () { return true; }()}} });", options, errors: [{ noReturnMessage }] }, - // test option: {allowImplicit: true} - { code: "var foo = { get bar() {} };", options, errors: [{ message: noReturnMessage }] }, - { code: "var foo = { get bar() {if (baz) {return;}} };", options, errors: [{ message: noLastReturnMessage }] }, - { code: "class foo { get bar(){} }", options, errors: [{ message: noReturnMessage }] }, - { code: "class foo { get bar(){if (baz) {return true;} } }", options, errors: [{ message: noLastReturnMessage }] }, + // option: {allowImplicit: true} { code: "Object.defineProperty(foo, \"bar\", { get: function (){}});", options, errors: [{ message: "Expected to return a value in method 'get'." }] }, { code: "Object.defineProperies(foo, { bar: { get: function () {}} });", options, errors: [{ noReturnMessage }] } ] From d5b172e14be3f22f8aae6f268194271d7744a697 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=96=9B=E5=AE=9A=E8=B0=94=E7=9A=84=E7=8C=AB?= Date: Wed, 28 Jun 2017 05:31:43 +0800 Subject: [PATCH 24/24] update --- tests/lib/rules/getter-return.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/lib/rules/getter-return.js b/tests/lib/rules/getter-return.js index 14eab2a1a96..646d4489389 100644 --- a/tests/lib/rules/getter-return.js +++ b/tests/lib/rules/getter-return.js @@ -50,14 +50,14 @@ ruleTester.run("getter-return", rule, { // test object.defineProperty(s) // option: {allowImplicit: false} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});" }, - { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, { code: "Object.defineProperty(foo, \"bar\", { get: function () { ~function (){ return true; }();return true;}});" }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });" }, { code: "Object.defineProperies(foo, { bar: { get: function () { ~function (){ return true; }(); return true;}} });" }, // option: {allowImplicit: true} { code: "Object.defineProperty(foo, \"bar\", { get: function () {return true;}});", options }, - { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, { code: "Object.defineProperty(foo, \"bar\", { get: function (){return;}});", options }, + { code: "Object.defineProperies(foo, { bar: { get: function () {return true;}} });", options }, { code: "Object.defineProperies(foo, { bar: { get: function () {return;}} });", options }, // not getter.