Repository: eslint/eslint
Pull request #10497 (2018-06-21 16:48:19)

Upgrade: globals@11.7.0
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**


[x] Other, please explain:

<!--
    If the item you've checked above has a template, please paste the template questions below and answer them. (If this pull request is addressing an issue, you can just paste a link to the issue here instead.)
-->

<!--
    Please ensure your pull request is ready:

    - Read the pull request guide (https://eslint.org/docs/developer-guide/contributing/pull-requests)
    - Include tests for this change
    - Update documentation for this change (if appropriate)
-->

<!--
    The following is required for all pull requests:
-->

**What changes did you make? (Give an overview)**
upgrade globals@11.7.0, added bigint.

**Is there anything you'd like reviewers to focus on?**
no~


platinumazure: I'm okay with merging this in, but I'll ask: Do we want to wait until bigint is stage 4? (Not sure if the globals are included as part of the proposal or not.)

Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 97fa0bcb9..97bca968c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,22 @@
+v5.0.1 - June 25, 2018
+
+* 196c102 Fix: valid-jsdoc should allow optional returns for async (fixes #10386) (#10480) (Mark Banner)
+* 4c823bd Docs: Fix max-lines-per-function correct code's max value (#10513) (Rhys Bower)
+
+v5.0.0 - June 22, 2018
+
+* 0feedfd New: Added max-lines-per-function rule (fixes #9842) (#10188) (peteward44)
+* daefbdb Upgrade: eslint-scope and espree to 4.0.0 (refs #10458) (#10500) (Brandon Mills)
+* 077358b Docs: no-process-exit: recommend process.exitCode (#10478) (Andres Kalle)
+* f93d6ff Fix: do not fail on unknown operators from custom parsers (fixes #10475) (#10476) (Rubén Norte)
+* 05343fd Fix: add parens for yield statement (fixes #10432) (#10468) (Pig Fang)
+* d477c5e Fix: check destructuring for "no-shadow-restricted-names" (fixes #10467) (#10470) (Pig Fang)
+* 7a7580b Update: Add considerPropertyDescriptor option to func-name-matching (#9078) (Dieter Luypaert)
+* e0a0418 Fix: crash on optional catch binding (#10429) (Toru Nagashima)
+* de4dba9 Docs: styling team members (#10460) (薛定谔的猫)
+* 5e453a3 Docs: display team members in tables. (#10433) (薛定谔的猫)
+* b1895eb Docs: Restore intentional spelling mistake (#10459) (Wilfred Hughes)
+
 v5.0.0-rc.0 - June 9, 2018
 
 * abf400d Update: Add ignoreDestructing option to camelcase rule (fixes #9807) (#10373) (Andrew Lunny)
diff --git a/conf/eslint-recommended.js b/conf/eslint-recommended.js
index 4b4ed0ae8..28d7aa4f9 100644
--- a/conf/eslint-recommended.js
+++ b/conf/eslint-recommended.js
@@ -69,6 +69,7 @@ module.exports = {
         "max-depth": "off",
         "max-len": "off",
         "max-lines": "off",
+        "max-lines-per-function": "off",
         "max-nested-callbacks": "off",
         "max-params": "off",
         "max-statements": "off",
diff --git a/docs/developer-guide/README.md b/docs/developer-guide/README.md
index 406568c1c..2070b2da1 100644
--- a/docs/developer-guide/README.md
+++ b/docs/developer-guide/README.md
@@ -34,10 +34,14 @@ You're finally ready to start working with rules. You may want to fix an existin
 
 You've developed library-specific rules for ESLint and you want to share it with the community. You can publish an ESLint plugin on npm.
 
-## Section 6: [Node.js API](nodejs-api.md)
+## Section 6: [Working with Parsers](working-with-parsers.md)
+
+If you aren't going to use the default parser of ESLint, this section explains about using custom parsers.
+
+## Section 7: [Node.js API](nodejs-api.md)
 
 If you're interested in writing a tool that uses ESLint, then you can use the Node.js API to get programmatic access to functionality.
 
-## Section 7: [Contributing](contributing/)
+## Section 8: [Contributing](contributing/)
 
 Once you've made changes that you want to share with the community, the next step is to submit those changes back via a pull request.
diff --git a/docs/rules/complexity.md b/docs/rules/complexity.md
index 4f4654b9d..e70a8989a 100644
--- a/docs/rules/complexity.md
+++ b/docs/rules/complexity.md
@@ -80,6 +80,8 @@ If you can't determine an appropriate complexity limit for your code, then it's
 
 * [max-depth](max-depth.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-depth.md b/docs/rules/max-depth.md
index 32f2a4a6d..8eed0912f 100644
--- a/docs/rules/max-depth.md
+++ b/docs/rules/max-depth.md
@@ -58,6 +58,8 @@ function foo() {
 
 * [complexity](complexity.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-lines-per-function.md b/docs/rules/max-lines-per-function.md
new file mode 100644
index 000000000..8ce0e313e
--- /dev/null
+++ b/docs/rules/max-lines-per-function.md
@@ -0,0 +1,191 @@
+# enforce a maximum function length (max-lines-per-function)
+
+Some people consider large functions a code smell. Large functions tend to do a lot of things and can make it hard following what's going on. Many coding style guides dictate a limit of the number of lines that a function can comprise of. This rule can help enforce that style.
+
+## Rule Details
+
+This rule enforces a maximum number of lines per function, in order to aid in maintainability and reduce complexity.
+
+## Why not use `max-statements` or other complexity measurement rules instead?
+
+Nested long method chains like the below example are often broken onto separate lines for readability:
+
+```
+function() {
+    return m("div", [
+        m("table", {className: "table table-striped latest-data"}, [
+            m("tbody",
+                data.map(function(db) {
+                    return m("tr", {key: db.dbname}, [
+                        m("td", {className: "dbname"}, db.dbname),
+                        m("td", {className: "query-count"},  [
+                            m("span", {className: db.lastSample.countClassName}, db.lastSample.nbQueries)
+                        ])
+                    ])
+                })
+            )
+        ])
+    ])
+}
+```
+
+* `max-statements` will only report this as 1 statement, despite being 16 lines of code.
+* `complexity` will only report a complexity of 1
+* `max-nested-callbacks` will only report 1
+* `max-depth` will report a depth of 0
+
+## Options
+
+This rule has the following options that can be specified using an object:
+
+* `"max"` (default `50`) enforces a maximum number of lines in a function.
+
+* `"skipBlankLines": true` ignore lines made up purely of whitespace.
+
+* `"skipComments": true` ignore lines containing just comments.
+
+* `"IIFEs": true` include any code included in IIFEs.
+
+Alternatively, you may specify a single integer for the `max` option:
+
+```json
+"max-lines-per-function": ["error", 20]
+```
+
+is equivalent to
+
+```json
+"max-lines-per-function": ["error", { "max": 20 }]
+```
+
+### code
+
+Examples of **incorrect** code for this rule with a max value of `2`:
+
+```js
+/*eslint max-lines-per-function: ["error", 2]*/
+function foo() {
+    var x = 0;
+}
+```
+
+```js
+/*eslint max-lines-per-function: ["error", 2]*/
+function foo() {
+    // a comment
+    var x = 0;
+}
+```
+
+```js
+/*eslint max-lines-per-function: ["error", 2]*/
+function foo() {
+    // a comment followed by a blank line
+
+    var x = 0;
+}
+```
+
+Examples of **correct** code for this rule with a max value of `3`:
+
+```js
+/*eslint max-lines-per-function: ["error", 3]*/
+function foo() {
+    var x = 0;
+}
+```
+
+```js
+/*eslint max-lines-per-function: ["error", 3]*/
+function foo() {
+    // a comment
+    var x = 0;
+}
+```
+
+```js
+/*eslint max-lines-per-function: ["error", 3]*/
+function foo() {
+    // a comment followed by a blank line
+
+    var x = 0;
+}
+```
+
+### skipBlankLines
+
+Examples of **incorrect** code for this rule with the `{ "skipBlankLines": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 2, "skipBlankLines": true}]*/
+function foo() {
+
+    var x = 0;
+}
+```
+
+Examples of **correct** code for this rule with the `{ "skipBlankLines": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 3, "skipBlankLines": true}]*/
+function foo() {
+
+    var x = 0;
+}
+```
+
+### skipComments
+
+Examples of **incorrect** code for this rule with the `{ "skipComments": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 2, "skipComments": true}]*/
+function foo() {
+    // a comment
+    var x = 0;
+}
+```
+
+Examples of **correct** code for this rule with the `{ "skipComments": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 3, "skipComments": true}]*/
+function foo() {
+    // a comment
+    var x = 0;
+}
+```
+
+### IIFEs
+
+Examples of **incorrect** code for this rule with the `{ "IIFEs": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 2, "IIFEs": true}]*/
+(function(){
+    var x = 0;
+}());
+```
+
+Examples of **correct** code for this rule with the `{ "IIFEs": true }` option:
+
+```js
+/*eslint max-lines-per-function: ["error", {"max": 3, "IIFEs": true}]*/
+(function(){
+    var x = 0;
+}());
+```
+
+## When Not To Use It
+
+You can turn this rule off if you are not concerned with the number of lines in your functions.
+
+## Related Rules
+
+* [complexity](complexity.md)
+* [max-depth](max-depth.md)
+* [max-lines](max-lines.md)
+* [max-nested-callbacks](max-nested-callbacks.md)
+* [max-params](max-params.md)
+* [max-statements](max-statements.md)
+* [max-statements-per-line](max-statements-per-line.md)
diff --git a/docs/rules/max-lines.md b/docs/rules/max-lines.md
index d0a6f2ffb..097804570 100644
--- a/docs/rules/max-lines.md
+++ b/docs/rules/max-lines.md
@@ -116,6 +116,7 @@ You can turn this rule off if you are not concerned with the number of lines in
 
 * [complexity](complexity.md)
 * [max-depth](max-depth.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-nested-callbacks.md b/docs/rules/max-nested-callbacks.md
index 8c1f9c230..24e4b907f 100644
--- a/docs/rules/max-nested-callbacks.md
+++ b/docs/rules/max-nested-callbacks.md
@@ -79,5 +79,7 @@ function handleFoo4() {
 * [complexity](complexity.md)
 * [max-depth](max-depth.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-params.md b/docs/rules/max-params.md
index 5c12b9d7d..050d2a348 100644
--- a/docs/rules/max-params.md
+++ b/docs/rules/max-params.md
@@ -57,5 +57,7 @@ let foo = (bar, baz, qux) => {
 * [complexity](complexity.md)
 * [max-depth](max-depth.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-statements-per-line.md b/docs/rules/max-statements-per-line.md
index d7f51ec53..e8462b664 100644
--- a/docs/rules/max-statements-per-line.md
+++ b/docs/rules/max-statements-per-line.md
@@ -80,6 +80,8 @@ You can turn this rule off if you are not concerned with the number of statement
 
 * [max-depth](max-depth.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
 * [max-statements](max-statements.md)
diff --git a/docs/rules/max-statements.md b/docs/rules/max-statements.md
index 3d03e1d57..6ef87c2f8 100644
--- a/docs/rules/max-statements.md
+++ b/docs/rules/max-statements.md
@@ -139,5 +139,7 @@ function foo() {
 * [complexity](complexity.md)
 * [max-depth](max-depth.md)
 * [max-len](max-len.md)
+* [max-lines](max-lines.md)
+* [max-lines-per-function](max-lines-per-function.md)
 * [max-nested-callbacks](max-nested-callbacks.md)
 * [max-params](max-params.md)
diff --git a/docs/rules/no-catch-shadow.md b/docs/rules/no-catch-shadow.md
index 0cc449b51..cd57ac8f7 100644
--- a/docs/rules/no-catch-shadow.md
+++ b/docs/rules/no-catch-shadow.md
@@ -1,5 +1,7 @@
 # Disallow Shadowing of Variables Inside of catch (no-catch-shadow)
 
+This rule was **deprecated** in ESLint v5.1.0.
+
 In IE 8 and earlier, the catch clause parameter can overwrite the value of a variable in the outer scope, if that variable has the same name as the catch clause parameter.
 
 ```js
diff --git a/docs/rules/no-implied-eval.md b/docs/rules/no-implied-eval.md
index a8e007a32..d300ff61d 100644
--- a/docs/rules/no-implied-eval.md
+++ b/docs/rules/no-implied-eval.md
@@ -2,7 +2,7 @@
 
 It's considered a good practice to avoid using `eval()` in JavaScript. There are security and performance implications involved with doing so, which is why many linters (including ESLint) recommend disallowing `eval()`. However, there are some other ways to pass a string and have it interpreted as JavaScript code that have similar concerns.
 
-The first is using `setTimeout()`, `setInterval()` or `execScript()` (Internet Explorer only), both of which can accept a string of JavaScript code as their first argument. For example:
+The first is using `setTimeout()`, `setInterval()` or `execScript()` (Internet Explorer only), all of which can accept a string of JavaScript code as their first argument. For example:
 
 ```js
 setTimeout("alert('Hi!');", 100);
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index 8ee985689..b1284f92a 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -448,6 +448,25 @@ foo(); /* eslint-disable-line example/rule-name */
 
 **Note:** Comments that disable warnings for a portion of a file tell ESLint not to report rule violations for the disabled code. ESLint still parses the entire file, however, so disabled code still needs to be syntactically valid JavaScript.
 
+
+### Disabling Rules Only for a Group of Files
+
+To disable rules inside of a configuration file for a group of files, use the `overrides` key along with a `files` key. For example:
+
+```json
+{
+  "rules": {...},
+  "overrides": [
+    {
+      "files": ["*-test.js","*.spec.js"],
+      "rules": {
+        "no-unused-expressions": "off"
+      }
+    }
+  ]
+}
+```
+
 ## Adding Shared Settings
 
 ESLint supports adding shared settings into configuration file. You can add `settings` object to ESLint configuration file and it will be supplied to every rule that will be executed. This may be useful if you are adding custom rules and want them to have access to the same information and be easily configurable.
diff --git a/lib/rules/max-lines-per-function.js b/lib/rules/max-lines-per-function.js
new file mode 100644
index 000000000..b40c7ee88
--- /dev/null
+++ b/lib/rules/max-lines-per-function.js
@@ -0,0 +1,218 @@
+/**
+ * @fileoverview A rule to set the maximum number of line of code in a function.
+ * @author Pete Ward <peteward44@gmail.com>
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+
+const astUtils = require("../ast-utils");
+
+//------------------------------------------------------------------------------
+// Constants
+//------------------------------------------------------------------------------
+
+const OPTIONS_SCHEMA = {
+    type: "object",
+    properties: {
+        max: {
+            type: "integer",
+            minimum: 0
+        },
+        skipComments: {
+            type: "boolean"
+        },
+        skipBlankLines: {
+            type: "boolean"
+        },
+        IIFEs: {
+            type: "boolean"
+        }
+    },
+    additionalProperties: false
+};
+
+const OPTIONS_OR_INTEGER_SCHEMA = {
+    oneOf: [
+        OPTIONS_SCHEMA,
+        {
+            type: "integer",
+            minimum: 1
+        }
+    ]
+};
+
+/**
+ * Given a list of comment nodes, return a map with numeric keys (source code line numbers) and comment token values.
+ * @param {Array} comments An array of comment nodes.
+ * @returns {Map.<string,Node>} A map with numeric keys (source code line numbers) and comment token values.
+ */
+function getCommentLineNumbers(comments) {
+    const map = new Map();
+
+    if (!comments) {
+        return map;
+    }
+    comments.forEach(comment => {
+        for (let i = comment.loc.start.line; i <= comment.loc.end.line; i++) {
+            map.set(i, comment);
+        }
+    });
+    return map;
+}
+
+//------------------------------------------------------------------------------
+// Rule Definition
+//------------------------------------------------------------------------------
+
+module.exports = {
+    meta: {
+        docs: {
+            description: "enforce a maximum number of line of code in a function",
+            category: "Stylistic Issues",
+            recommended: false,
+            url: "https://eslint.org/docs/rules/max-lines-per-function"
+        },
+
+        schema: [
+            OPTIONS_OR_INTEGER_SCHEMA
+        ]
+    },
+
+    create(context) {
+        const sourceCode = context.getSourceCode();
+        const lines = sourceCode.lines;
+
+        const option = context.options[0];
+        let maxLines = 50;
+        let skipComments = false;
+        let skipBlankLines = false;
+        let IIFEs = false;
+
+        if (typeof option === "object") {
+            if (typeof option.max === "number") {
+                maxLines = option.max;
+            }
+            if (typeof option.skipComments === "boolean") {
+                skipComments = option.skipComments;
+            }
+            if (typeof option.skipBlankLines === "boolean") {
+                skipBlankLines = option.skipBlankLines;
+            }
+            if (typeof option.IIFEs === "boolean") {
+                IIFEs = option.IIFEs;
+            }
+        } else if (typeof option === "number") {
+            maxLines = option;
+        }
+
+        const commentLineNumbers = getCommentLineNumbers(sourceCode.getAllComments());
+
+        //--------------------------------------------------------------------------
+        // Helpers
+        //--------------------------------------------------------------------------
+
+        /**
+         * Tells if a comment encompasses the entire line.
+         * @param {string} line The source line with a trailing comment
+         * @param {number} lineNumber The one-indexed line number this is on
+         * @param {ASTNode} comment The comment to remove
+         * @returns {boolean} If the comment covers the entire line
+         */
+        function isFullLineComment(line, lineNumber, comment) {
+            const start = comment.loc.start,
+                end = comment.loc.end,
+                isFirstTokenOnLine = start.line === lineNumber && !line.slice(0, start.column).trim(),
+                isLastTokenOnLine = end.line === lineNumber && !line.slice(end.column).trim();
+
+            return comment &&
+                (start.line < lineNumber || isFirstTokenOnLine) &&
+                (end.line > lineNumber || isLastTokenOnLine);
+        }
+
+        /**
+         * Identifies is a node is a FunctionExpression which is part of an IIFE
+         * @param {ASTNode} node Node to test
+         * @returns {boolean} True if it's an IIFE
+         */
+        function isIIFE(node) {
+            return node.type === "FunctionExpression" && node.parent && node.parent.type === "CallExpression" && node.parent.callee === node;
+        }
+
+        /**
+         * Identifies is a node is a FunctionExpression which is embedded within a MethodDefinition or Property
+         * @param {ASTNode} node Node to test
+         * @returns {boolean} True if it's a FunctionExpression embedded within a MethodDefinition or Property
+         */
+        function isEmbedded(node) {
+            if (!node.parent) {
+                return false;
+            }
+            if (node !== node.parent.value) {
+                return false;
+            }
+            if (node.parent.type === "MethodDefinition") {
+                return true;
+            }
+            if (node.parent.type === "Property") {
+                return node.parent.method === true || node.parent.kind === "get" || node.parent.kind === "set";
+            }
+            return false;
+        }
+
+        /**
+         * Count the lines in the function
+         * @param {ASTNode} funcNode Function AST node
+         * @returns {void}
+         * @private
+         */
+        function processFunction(funcNode) {
+            const node = isEmbedded(funcNode) ? funcNode.parent : funcNode;
+
+            if (!IIFEs && isIIFE(node)) {
+                return;
+            }
+            let lineCount = 0;
+
+            for (let i = node.loc.start.line - 1; i < node.loc.end.line; ++i) {
+                const line = lines[i];
+
+                if (skipComments) {
+                    if (commentLineNumbers.has(i + 1) && isFullLineComment(line, i + 1, commentLineNumbers.get(i + 1))) {
+                        continue;
+                    }
+                }
+
+                if (skipBlankLines) {
+                    if (line.match(/^\s*$/)) {
+                        continue;
+                    }
+                }
+
+                lineCount++;
+            }
+
+            if (lineCount > maxLines) {
+                const name = astUtils.getFunctionNameWithKind(funcNode);
+
+                context.report({
+                    node,
+                    message: "{{name}} has too many lines ({{lineCount}}). Maximum allowed is {{maxLines}}.",
+                    data: { name, lineCount, maxLines }
+                });
+            }
+        }
+
+        //--------------------------------------------------------------------------
+        // Public API
+        //--------------------------------------------------------------------------
+
+        return {
+            FunctionDeclaration: processFunction,
+            FunctionExpression: processFunction,
+            ArrowFunctionExpression: processFunction
+        };
+    }
+};
diff --git a/lib/rules/no-catch-shadow.js b/lib/rules/no-catch-shadow.js
index f7abc931c..e1e24e0ef 100644
--- a/lib/rules/no-catch-shadow.js
+++ b/lib/rules/no-catch-shadow.js
@@ -1,6 +1,7 @@
 /**
  * @fileoverview Rule to flag variable leak in CatchClauses in IE 8 and earlier
  * @author Ian Christian Myers
+ * @deprecated in ESLint v5.1.0
  */
 
 "use strict";
@@ -21,8 +22,10 @@ module.exports = {
             description: "disallow `catch` clause parameters from shadowing variables in the outer scope",
             category: "Variables",
             recommended: false,
-            url: "https://eslint.org/docs/rules/no-catch-shadow"
+            url: "https://eslint.org/docs/rules/no-catch-shadow",
+            replacedBy: ["no-shadow"]
         },
+        deprecated: true,
 
         schema: [],
 
diff --git a/lib/rules/no-debugger.js b/lib/rules/no-debugger.js
index f00e819df..5d63bb7e1 100644
--- a/lib/rules/no-debugger.js
+++ b/lib/rules/no-debugger.js
@@ -5,8 +5,6 @@
 
 "use strict";
 
-const astUtils = require("../ast-utils");
-
 //------------------------------------------------------------------------------
 // Rule Definition
 //------------------------------------------------------------------------------
@@ -19,7 +17,7 @@ module.exports = {
             recommended: true,
             url: "https://eslint.org/docs/rules/no-debugger"
         },
-        fixable: "code",
+        fixable: null,
         schema: [],
         messages: {
             unexpected: "Unexpected 'debugger' statement."
@@ -32,13 +30,7 @@ module.exports = {
             DebuggerStatement(node) {
                 context.report({
                     node,
-                    messageId: "unexpected",
-                    fix(fixer) {
-                        if (astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) {
-                            return fixer.remove(node);
-                        }
-                        return null;
-                    }
+                    messageId: "unexpected"
                 });
             }
         };
diff --git a/lib/rules/valid-jsdoc.js b/lib/rules/valid-jsdoc.js
index a8466135b..44c0f9999 100644
--- a/lib/rules/valid-jsdoc.js
+++ b/lib/rules/valid-jsdoc.js
@@ -408,7 +408,7 @@ module.exports = {
                 if (!isOverride && !hasReturns && !hasConstructor && !isInterface &&
                     node.parent.kind !== "get" && node.parent.kind !== "constructor" &&
                     node.parent.kind !== "set" && !isTypeClass(node)) {
-                    if (requireReturn || functionData.returnPresent) {
+                    if (requireReturn || (functionData.returnPresent && !node.async)) {
                         context.report({
                             node: jsdocNode,
                             message: "Missing JSDoc @{{returns}} for function.",
diff --git a/package.json b/package.json
index 5344f25fd..40a8b7229 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "5.0.0-rc.0",
+  "version": "5.0.1",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
@@ -41,15 +41,15 @@
     "cross-spawn": "^6.0.5",
     "debug": "^3.1.0",
     "doctrine": "^2.1.0",
-    "eslint-scope": "^4.0.0-rc.0",
+    "eslint-scope": "^4.0.0",
     "eslint-visitor-keys": "^1.0.0",
-    "espree": "^4.0.0-rc.0",
+    "espree": "^4.0.0",
     "esquery": "^1.0.1",
     "esutils": "^2.0.2",
     "file-entry-cache": "^2.0.0",
     "functional-red-black-tree": "^1.0.1",
     "glob": "^7.1.2",
-    "globals": "^11.5.0",
+    "globals": "^11.7.0",
     "ignore": "^3.3.3",
     "imurmurhash": "^0.1.4",
     "inquirer": "^5.2.0",


Test patch:
diff --git a/tests/lib/rules/max-lines-per-function.js b/tests/lib/rules/max-lines-per-function.js
new file mode 100644
index 000000000..8bf8250f3
--- /dev/null
+++ b/tests/lib/rules/max-lines-per-function.js
@@ -0,0 +1,431 @@
+/**
+ * @fileoverview Tests for max-lines-per-function rule.
+ * @author Pete Ward <peteward44@gmail.com>
+ */
+"use strict";
+
+//------------------------------------------------------------------------------
+// Requirements
+//------------------------------------------------------------------------------
+const rule = require("../../../lib/rules/max-lines-per-function");
+const RuleTester = require("../../../lib/testers/rule-tester");
+
+//------------------------------------------------------------------------------
+// Tests
+//------------------------------------------------------------------------------
+
+const ruleTester = new RuleTester({ parserOptions: { ecmaVersion: 6 } });
+
+ruleTester.run("max-lines-per-function", rule, {
+    valid: [
+
+        // Test code in global scope doesn't count
+        {
+            code: "var x = 5;\nvar x = 2;\n",
+            options: [1]
+        },
+
+        // Test single line standlone function
+        {
+            code: "function name() {}",
+            options: [1]
+        },
+
+        // Test standalone function with lines of code
+        {
+            code: "function name() {\nvar x = 5;\nvar x = 2;\n}",
+            options: [4]
+        },
+
+        // Test inline arrow function
+        {
+            code: "const bar = () => 2",
+            options: [1]
+        },
+
+        // Test arrow function
+        {
+            code: "const bar = () => {\nconst x = 2 + 1;\nreturn x;\n}",
+            options: [4]
+        },
+
+        // skipBlankLines: false with simple standalone function
+        {
+            code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 7, skipComments: false, skipBlankLines: false }]
+        },
+
+        // skipBlankLines: true with simple standalone function
+        {
+            code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 4, skipComments: false, skipBlankLines: true }]
+        },
+
+        // skipComments: true with an individual single line comment
+        {
+            code: "function name() {\nvar x = 5;\nvar x = 2; // end of line comment\n}",
+            options: [{ max: 4, skipComments: true, skipBlankLines: false }]
+        },
+
+        // skipComments: true with an individual single line comment
+        {
+            code: "function name() {\nvar x = 5;\n// a comment on it's own line\nvar x = 2; // end of line comment\n}",
+            options: [{ max: 4, skipComments: true, skipBlankLines: false }]
+        },
+
+        // skipComments: true with single line comments
+        {
+            code: "function name() {\nvar x = 5;\n// a comment on it's own line\n// and another line comment\nvar x = 2; // end of line comment\n}",
+            options: [{ max: 4, skipComments: true, skipBlankLines: false }]
+        },
+
+        // skipComments: true test with multiple different comment types
+        {
+            code: "function name() {\nvar x = 5;\n/* a \n multi \n line \n comment \n*/\n\nvar x = 2; // end of line comment\n}",
+            options: [{ max: 5, skipComments: true, skipBlankLines: false }]
+        },
+
+        // skipComments: true with multiple different comment types, including trailing and leading whitespace
+        {
+            code: "function name() {\nvar x = 5;\n\t/* a comment with leading whitespace */\n/* a comment with trailing whitespace */\t\t\n\t/* a comment with trailing and leading whitespace */\t\t\n/* a \n multi \n line \n comment \n*/\t\t\n\nvar x = 2; // end of line comment\n}",
+            options: [{ max: 5, skipComments: true, skipBlankLines: false }]
+        },
+
+        // Multiple params on seperate lines test
+        {
+            code: `function foo(
+    aaa = 1,
+    bbb = 2,
+    ccc = 3
+) {
+    return aaa + bbb + ccc
+}`,
+            options: [{ max: 7, skipComments: true, skipBlankLines: false }]
+        },
+
+        // IIFE validity test
+        {
+            code: `(
+function
+()
+{
+}
+)
+()`,
+            options: [{ max: 4, skipComments: true, skipBlankLines: false, IIFEs: true }]
+        },
+
+        // Nested function validity test
+        {
+            code: `function parent() {
+var x = 0;
+function nested() {
+    var y = 0;
+    x = 2;
+}
+if ( x === y ) {
+    x++;
+}
+}`,
+            options: [{ max: 10, skipComments: true, skipBlankLines: false }]
+        },
+
+        // Class method validity test
+        {
+            code: `class foo {
+    method() {
+        let y = 10;
+        let x = 20;
+        return y + x;
+    }
+}`,
+            options: [{ max: 5, skipComments: true, skipBlankLines: false }]
+        },
+
+        // IIFEs should be recognised if IIFEs: true
+        {
+            code: `(function(){
+    let x = 0;
+    let y = 0;
+    let z = x + y;
+    let foo = {};
+    return bar;
+}());`,
+            options: [{ max: 7, skipComments: true, skipBlankLines: false, IIFEs: true }]
+        },
+
+        // IIFEs should not be recognised if IIFEs: false
+        {
+            code: `(function(){
+    let x = 0;
+    let y = 0;
+    let z = x + y;
+    let foo = {};
+    return bar;
+}());`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: false }]
+        }
+    ],
+
+    invalid: [
+
+        // Test simple standalone function is recognised
+        {
+            code: "function name() {\n}",
+            options: [1],
+            errors: [
+                "function 'name' has too many lines (2). Maximum allowed is 1."
+            ]
+        },
+
+        // Test anonymous function assigned to variable is recognised
+        {
+            code: "var func = function() {\n}",
+            options: [1],
+            errors: [
+                "function has too many lines (2). Maximum allowed is 1."
+            ]
+        },
+
+        // Test arrow functions are recognised
+        {
+            code: "const bar = () => {\nconst x = 2 + 1;\nreturn x;\n}",
+            options: [3],
+            errors: [
+                "arrow function has too many lines (4). Maximum allowed is 3."
+            ]
+        },
+
+        // Test inline arrow functions are recognised
+        {
+            code: "const bar = () =>\n 2",
+            options: [1],
+            errors: [
+                "arrow function has too many lines (2). Maximum allowed is 1."
+            ]
+        },
+
+        // Test skipBlankLines: false
+        {
+            code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 6, skipComments: false, skipBlankLines: false }],
+            errors: [
+                "function 'name' has too many lines (7). Maximum allowed is 6."
+            ]
+        },
+
+        // Test skipBlankLines: false with CRLF line endings
+        {
+            code: "function name() {\r\nvar x = 5;\r\n\t\r\n \r\n\r\nvar x = 2;\r\n}",
+            options: [{ max: 6, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "function 'name' has too many lines (7). Maximum allowed is 6."
+            ]
+        },
+
+        // Test skipBlankLines: true
+        {
+            code: "function name() {\nvar x = 5;\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 2, skipComments: true, skipBlankLines: true }],
+            errors: [
+                "function 'name' has too many lines (4). Maximum allowed is 2."
+            ]
+        },
+
+        // Test skipBlankLines: true with CRLF line endings
+        {
+            code: "function name() {\r\nvar x = 5;\r\n\t\r\n \r\n\r\nvar x = 2;\r\n}",
+            options: [{ max: 2, skipComments: true, skipBlankLines: true }],
+            errors: [
+                "function 'name' has too many lines (4). Maximum allowed is 2."
+            ]
+        },
+
+        // Test skipComments: true and skipBlankLines: false for multiple types of comment
+        {
+            code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 6, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "function 'name' has too many lines (7). Maximum allowed is 6."
+            ]
+        },
+
+        // Test skipComments: true and skipBlankLines: true for multiple types of comment
+        {
+            code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 1, skipComments: true, skipBlankLines: true }],
+            errors: [
+                "function 'name' has too many lines (4). Maximum allowed is 1."
+            ]
+        },
+
+        // Test skipComments: false and skipBlankLines: true for multiple types of comment
+        {
+            code: "function name() { // end of line comment\nvar x = 5; /* mid line comment */\n\t// single line comment taking up whole line\n\t\n \n\nvar x = 2;\n}",
+            options: [{ max: 1, skipComments: false, skipBlankLines: true }],
+            errors: [
+                "function 'name' has too many lines (5). Maximum allowed is 1."
+            ]
+        },
+
+        // Test simple standalone function with params on separate lines
+        {
+            code: `function foo(
+    aaa = 1,
+    bbb = 2,
+    ccc = 3
+) {
+    return aaa + bbb + ccc
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "function 'foo' has too many lines (7). Maximum allowed is 2."
+            ]
+        },
+
+        // Test IIFE "function" keyword is included in the count
+        {
+            code: `(
+function
+()
+{
+}
+)
+()`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: true }],
+            errors: [
+                "function has too many lines (4). Maximum allowed is 2."
+            ]
+        },
+
+        // Test nested functions are included in it's parent's function count.
+        {
+            code: `function parent() {
+var x = 0;
+function nested() {
+    var y = 0;
+    x = 2;
+}
+if ( x === y ) {
+    x++;
+}
+}`,
+            options: [{ max: 9, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "function 'parent' has too many lines (10). Maximum allowed is 9."
+            ]
+        },
+
+        // Test nested functions are included in it's parent's function count.
+        {
+            code: `function parent() {
+var x = 0;
+function nested() {
+    var y = 0;
+    x = 2;
+}
+if ( x === y ) {
+    x++;
+}
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "function 'parent' has too many lines (10). Maximum allowed is 2.",
+                "function 'nested' has too many lines (4). Maximum allowed is 2."
+            ]
+        },
+
+        // Test regular methods are recognised
+        {
+            code: `class foo {
+    method() {
+        let y = 10;
+        let x = 20;
+        return y + x;
+    }
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "method 'method' has too many lines (5). Maximum allowed is 2."
+            ]
+        },
+
+        // Test static methods are recognised
+        {
+            code: `class A {
+    static
+    foo
+    (a) {
+        return a
+    }
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "static method 'foo' has too many lines (5). Maximum allowed is 2."
+            ]
+        },
+
+        // Test getters are recognised as properties
+        {
+            code: `var obj = {
+    get
+    foo
+    () {
+        return 1
+    }
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "getter 'foo' has too many lines (5). Maximum allowed is 2."
+            ]
+        },
+
+        // Test setters are recognised as properties
+        {
+            code: `var obj = {
+    set
+    foo
+    ( val ) {
+        this._foo = val;
+    }
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "setter 'foo' has too many lines (5). Maximum allowed is 2."
+            ]
+        },
+
+        // Test computed property names
+        {
+            code: `class A {
+    static
+    [
+        foo +
+            bar
+    ]
+    (a) {
+        return a
+    }
+}`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false }],
+            errors: [
+                "static method has too many lines (8). Maximum allowed is 2."
+            ]
+        },
+
+        // Test the IIFEs option includes IIFEs
+        {
+            code: `(function(){
+    let x = 0;
+    let y = 0;
+    let z = x + y;
+    let foo = {};
+    return bar;
+}());`,
+            options: [{ max: 2, skipComments: true, skipBlankLines: false, IIFEs: true }],
+            errors: [
+                "function has too many lines (7). Maximum allowed is 2."
+            ]
+        }
+    ]
+});
diff --git a/tests/lib/rules/no-debugger.js b/tests/lib/rules/no-debugger.js
index d97750599..3d991fc3e 100644
--- a/tests/lib/rules/no-debugger.js
+++ b/tests/lib/rules/no-debugger.js
@@ -23,11 +23,6 @@ ruleTester.run("no-debugger", rule, {
         "var test = { debugger: 1 }; test.debugger;"
     ],
     invalid: [
-        {
-            code: "debugger",
-            output: "",
-            errors: [{ messageId: "unexpected", type: "DebuggerStatement" }]
-        },
         {
             code: "if (foo) debugger",
             output: null,
diff --git a/tests/lib/rules/valid-jsdoc.js b/tests/lib/rules/valid-jsdoc.js
index 6962598ab..c300d08ea 100644
--- a/tests/lib/rules/valid-jsdoc.js
+++ b/tests/lib/rules/valid-jsdoc.js
@@ -296,6 +296,17 @@ ruleTester.run("valid-jsdoc", rule, {
                 ecmaVersion: 2017
             }
         },
+        {
+            code:
+              "/**\n" +
+              " * An async function. Options do not require return.\n" +
+              " */\n" +
+              "async function a() {}",
+            options: [{ requireReturn: false }],
+            parserOptions: {
+                ecmaVersion: 2017
+            }
+        },
 
         // type validations
         {
@@ -1677,6 +1688,24 @@ ruleTester.run("valid-jsdoc", rule, {
             }]
         },
 
+        // async function
+        {
+            code:
+              "/**\n" +
+              " * An async function. Options requires return.\n" +
+              " */\n" +
+              "async function a() {}",
+            output: null,
+            options: [{ requireReturn: true }],
+            parserOptions: {
+                ecmaVersion: 2017
+            },
+            errors: [{
+                message: "Missing JSDoc @returns for function.",
+                type: "Block"
+            }]
+        },
+
         // type validations
         {
             code: