Repository: eslint/eslint (js)

Issue:
False positive on rule `lines-between-class-memebers` if a comment occurs between class members
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).

    This template is for bug reports. If you are reporting a bug, please continue on. If you are here for another reason, please see below:

    1. To propose a new rule: https://eslint.org/docs/developer-guide/contributing/new-rules
    2. To request a change: https://eslint.org/docs/developer-guide/contributing/changes
    3. If you have any questions, please stop by our chatroom: https://gitter.im/eslint/eslint

    Note that leaving sections blank will make it difficult for us to troubleshoot and we may have to close the issue.
-->

**Tell us about your environment**

* **ESLint Version:** 4.12
* **Node Version:** 8.9.1
* **npm Version:** 5.5.1

**What parser (default, Babel-ESLint, etc.) are you using?**
n/a

**Please show your full configuration:**

<details>
<summary>Configuration</summary>

<!-- Paste your configuration below: -->
```json
{
    "parserOptions": {
        "ecmaVersion": 6,
        "sourceType": "script",
        "ecmaFeatures": {}
    },
    "rules": {
        "lines-between-class-members": 2
    },
    "env": {}
}
```
(generated by [ESLint Demo](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuICAvKipcbiAgICogQHJldHVybnMge0FycmF5fVxuICAgKi9cbiAgZ2V0Rm9vKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2hpbGQgY2xhc3Mgc2hvdWxkIHJlaW1wbGVtZW50IHRoaXMgbWV0aG9kJyk7XG4gIH1cbiAgLyogZXNsaW50LWVuYWJsZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzICovXG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gICAqL1xuICBkb1NvbWV0aGluZygpIHt9XG59Iiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo2LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7ImxpbmVzLWJldHdlZW4tY2xhc3MtbWVtYmVycyI6Mn0sImVudiI6e319fQ==))

</details>

**What did you do? Please include the actual source code causing the issue, as well as the command that you used to run ESLint.**

I have a class which purpose is to be extended by other classes in order to provide actual implementation of some methods.
The class has placeholder methods that only throw, but don't use context (the subclass implementation will)

Since this is an exception i wrapped the method with `/* eslint-disable class-methods-use-this */` just before the doc block and `/* eslint-enable class-methods-use-this */` just after the method body like that:

<!-- Paste the source code below: -->
```js
class Foo {
  /* eslint-disable class-methods-use-this */
  /**
   * @returns {Array}
   */
  getFoo() {
    throw new Error('Child class should reimplement this method');
  }
  /* eslint-enable class-methods-use-this */

  /**
   * @returns {undefined}
   */
  doSomething() {}
}
```

<!-- Paste the command you used to run ESLint: -->
[Demo showing false positive (demo1)](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuICAvKipcbiAgICogQHJldHVybnMge0FycmF5fVxuICAgKi9cbiAgZ2V0Rm9vKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2hpbGQgY2xhc3Mgc2hvdWxkIHJlaW1wbGVtZW50IHRoaXMgbWV0aG9kJyk7XG4gIH1cbiAgLyogZXNsaW50LWVuYWJsZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzICovXG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gICAqL1xuICBkb1NvbWV0aGluZygpIHt9XG59Iiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo2LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7ImxpbmVzLWJldHdlZW4tY2xhc3MtbWVtYmVycyI6Mn0sImVudiI6e319fQ==)

[Demo reduced to bare minimum showing false positive (demo2)](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgZm9vKCkge31cbiAgLyogZm9vICovXG5cbiAgYmFyKCkge31cbn0iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjYsInNvdXJjZVR5cGUiOiJzY3JpcHQiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnsibGluZXMtYmV0d2Vlbi1jbGFzcy1tZW1iZXJzIjoyfSwiZW52Ijp7fX19). This one proves that any block comment between class members break the rule

What's interesting: Moving the `/* eslint-enable class-methods-use-this */` from line 9 to line 10 (so that the padding line is above the `/* eslint-enable */` directive) solves the problem (another demo with no error: [demo1-no-error](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuICAvKipcbiAgICogQHJldHVybnMge0FycmF5fVxuICAgKi9cbiAgZ2V0Rm9vKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2hpbGQgY2xhc3Mgc2hvdWxkIHJlaW1wbGVtZW50IHRoaXMgbWV0aG9kJyk7XG4gIH1cblxuICAvKiBlc2xpbnQtZW5hYmxlIGNsYXNzLW1ldGhvZHMtdXNlLXRoaXMgKi9cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gICAqL1xuICBkb1NvbWV0aGluZygpIHt9XG59Iiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo2LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7ImxpbmVzLWJldHdlZW4tY2xhc3MtbWVtYmVycyI6Mn0sImVudiI6e319fQ==), and [demo2-no-error](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgZm9vKCkge31cblxuICAvKiBmb28gKi9cbiAgYmFyKCkge31cbn0iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjYsInNvdXJjZVR5cGUiOiJzY3JpcHQiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnsibGluZXMtYmV0d2Vlbi1jbGFzcy1tZW1iZXJzIjoyfSwiZW52Ijp7fX19))

**What did you expect to happen?**
I think the rule should not report an error on line 14, especially since there's a blank line 10 which logically meets rule requirements.
Placement of `/* eslint-* */` directives should not affect whether the rule reports error or not if there's  one empty line between members.

**What actually happened? Please include the actual, raw output from ESLint.**
Rule reports error in line 14, column 3 (see [demo1](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgLyogZXNsaW50LWRpc2FibGUgY2xhc3MtbWV0aG9kcy11c2UtdGhpcyAqL1xuICAvKipcbiAgICogQHJldHVybnMge0FycmF5fVxuICAgKi9cbiAgZ2V0Rm9vKCkge1xuICAgIHRocm93IG5ldyBFcnJvcignQ2hpbGQgY2xhc3Mgc2hvdWxkIHJlaW1wbGVtZW50IHRoaXMgbWV0aG9kJyk7XG4gIH1cbiAgLyogZXNsaW50LWVuYWJsZSBjbGFzcy1tZXRob2RzLXVzZS10aGlzICovXG5cbiAgLyoqXG4gICAqIEByZXR1cm5zIHt1bmRlZmluZWR9XG4gICAqL1xuICBkb1NvbWV0aGluZygpIHt9XG59Iiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo2LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7ImxpbmVzLWJldHdlZW4tY2xhc3MtbWVtYmVycyI6Mn0sImVudiI6e319fQ==) and [demo2](https://eslint.org/demo/#eyJ0ZXh0IjoiY2xhc3MgRm9vIHtcbiAgZm9vKCkge31cbiAgLyogZm9vICovXG5cbiAgYmFyKCkge31cbn0iLCJvcHRpb25zIjp7InBhcnNlck9wdGlvbnMiOnsiZWNtYVZlcnNpb24iOjYsInNvdXJjZVR5cGUiOiJzY3JpcHQiLCJlY21hRmVhdHVyZXMiOnt9fSwicnVsZXMiOnsibGluZXMtYmV0d2Vlbi1jbGFzcy1tZW1iZXJzIjoyfSwiZW52Ijp7fX19)).



Pull request description:
Fix: `lines-between-class-members` (fixes #9665)
<!--
    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)**

[ ] Documentation update
[X] Bug fix ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/bug-report.md))
[ ] New rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-proposal.md))
[ ] Changes an existing rule ([template](https://raw.githubusercontent.com/eslint/eslint/master/templates/rule-change-proposal.md))
[ ] Add autofixing to a rule
[ ] Add a CLI option
[ ] Add something to the core
[ ] 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)**
I fixed the bug of issue #9665 

**Is there anything you'd like reviewers to focus on?**




Patch:
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 93e1f4a09..10be6ca53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+v4.13.1 - December 11, 2017
+
+* b72dc83 Fix: eol-last allow empty-string to always pass (refs #9534) (#9696) (Kevin Partington)
+* d80aa7c Fix: camelcase destructure leading/trailing underscore (fixes #9700) (#9701) (Kevin Partington)
+* d49d9d0 Docs: Add missing period to the README (#9702) (Kevin Partington)
+* 4564fe0 Chore: no-invalid-meta crash if no export assignment (refs #9534) (#9698) (Kevin Partington)
+
+v4.13.0 - December 8, 2017
+
+* 256481b Update: update handling of destructuring in camelcase (fixes #8511) (#9468) (Erin)
+* d067ae1 Docs: Don’t use undocumented array-style configuration for max-len (#9690) (Jed Fox)
+* 1ad3091 Chore: fix test-suite to work with node master (#9688) (Myles Borins)
+* cdb1488 Docs: Adds an example with try/catch. (#9672) (Jaap Taal)
+
 v4.12.1 - November 30, 2017
 
 * 1e362a0 Revert "Fix: Use XML 1.1 on XML formatters (fixes #9607) (#9608)" (#9667) (Kevin Partington)
diff --git a/README.md b/README.md
index 5a23d6295..160e72e10 100644
--- a/README.md
+++ b/README.md
@@ -239,7 +239,7 @@ Once a language feature has been adopted into the ECMAScript standard (stage 4 a
 
 ### Where to ask for help?
 
-Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://gitter.im/eslint/eslint)
+Join our [Mailing List](https://groups.google.com/group/eslint) or [Chatroom](https://gitter.im/eslint/eslint).
 
 
 [npm-image]: https://img.shields.io/npm/v/eslint.svg?style=flat-square
diff --git a/docs/rules/camelcase.md b/docs/rules/camelcase.md
index 66abcccf8..db660bcee 100644
--- a/docs/rules/camelcase.md
+++ b/docs/rules/camelcase.md
@@ -32,9 +32,27 @@ obj.do_something = function() {
     // ...
 };
 
+function foo({ no_camelcased }) {
+    // ...
+};
+
+function foo({ isCamelcased: no_camelcased }) {
+    // ...
+}
+
+function foo({ no_camelcased = 'default value' }) {
+    // ...
+};
+
 var obj = {
     my_pref: 1
 };
+
+var { category_id = 1 } = query;
+
+var { foo: no_camelcased } = bar;
+
+var { foo: bar_baz = 1 } = quz;
 ```
 
 Examples of **correct** code for this rule with the default `{ "properties": "always" }` option:
@@ -56,6 +74,25 @@ do_something();
 new do_something();
 
 var { category_id: category } = query;
+
+function foo({ isCamelCased }) {
+    // ...
+};
+
+function foo({ isCamelCased: isAlsoCamelCased }) {
+    // ...
+}
+
+function foo({ isCamelCased = 'default value' }) {
+    // ...
+};
+
+var { categoryId = 1 } = query;
+
+var { foo: isCamelCased } = bar;
+
+var { foo: isCamelCased = 1 } = quz;
+
 ```
 
 ### never
diff --git a/docs/rules/max-len.md b/docs/rules/max-len.md
index 55a41fcfa..71339f01c 100644
--- a/docs/rules/max-len.md
+++ b/docs/rules/max-len.md
@@ -30,7 +30,7 @@ This rule has a number or object option:
 Examples of **incorrect** code for this rule with the default `{ "code": 80 }` option:
 
 ```js
-/*eslint max-len: ["error", 80]*/
+/*eslint max-len: ["error", { "code": 80 }]*/
 
 var foo = { "bar": "This is a bar.", "baz": { "qux": "This is a qux" }, "difficult": "to read" };
 ```
@@ -38,7 +38,7 @@ var foo = { "bar": "This is a bar.", "baz": { "qux": "This is a qux" }, "difficu
 Examples of **correct** code for this rule with the default `{ "code": 80 }` option:
 
 ```js
-/*eslint max-len: ["error", 80]*/
+/*eslint max-len: ["error", { "code": 80 }]*/
 
 var foo = {
   "bar": "This is a bar.",
@@ -52,7 +52,7 @@ var foo = {
 Examples of **incorrect** code for this rule with the default `{ "tabWidth": 4 }` option:
 
 ```js
-/*eslint max-len: ["error", 80, 4]*/
+/*eslint max-len: ["error", { "code": 80, "tabWidth": 4 }]*/
 
 \t  \t  var foo = { "bar": "This is a bar.", "baz": { "qux": "This is a qux" } };
 ```
@@ -60,7 +60,7 @@ Examples of **incorrect** code for this rule with the default `{ "tabWidth": 4 }
 Examples of **correct** code for this rule with the default `{ "tabWidth": 4 }` option:
 
 ```js
-/*eslint max-len: ["error", 80, 4]*/
+/*eslint max-len: ["error", { "code": 80, "tabWidth": 4 }]*/
 
 \t  \t  var foo = {
 \t  \t  \t  \t  "bar": "This is a bar.",
diff --git a/lib/rules/camelcase.js b/lib/rules/camelcase.js
index 6fb1475b2..e3b764f7c 100644
--- a/lib/rules/camelcase.js
+++ b/lib/rules/camelcase.js
@@ -92,34 +92,45 @@ module.exports = {
                     }
 
                     // Always report underscored object names
-                    if (node.parent.object.type === "Identifier" &&
-                            node.parent.object.name === node.name &&
-                            isUnderscored(name)) {
+                    if (node.parent.object.type === "Identifier" && node.parent.object.name === node.name && isUnderscored(name)) {
                         report(node);
 
                     // Report AssignmentExpressions only if they are the left side of the assignment
-                    } else if (effectiveParent.type === "AssignmentExpression" &&
-                            isUnderscored(name) &&
-                            (effectiveParent.right.type !== "MemberExpression" ||
-                            effectiveParent.left.type === "MemberExpression" &&
-                            effectiveParent.left.property.name === node.name)) {
+                    } else if (effectiveParent.type === "AssignmentExpression" && isUnderscored(name) && (effectiveParent.right.type !== "MemberExpression" || effectiveParent.left.type === "MemberExpression" && effectiveParent.left.property.name === node.name)) {
                         report(node);
                     }
 
-                // Properties have their own rules
-                } else if (node.parent.type === "Property") {
+                /*
+                 * Properties have their own rules, and
+                 * AssignmentPattern nodes can be treated like Properties:
+                 * e.g.: const { no_camelcased = false } = bar;
+                 */
+                } else if (node.parent.type === "Property" || node.parent.type === "AssignmentPattern") {
 
-                    // "never" check properties
-                    if (properties === "never") {
-                        return;
+                    if (node.parent.parent && node.parent.parent.type === "ObjectPattern") {
+
+                        if (node.parent.shorthand && node.parent.value.left && isUnderscored(name)) {
+
+                            report(node);
+                        }
+
+                        // prevent checking righthand side of destructured object
+                        if (node.parent.key === node && node.parent.value !== node) {
+                            return;
+                        }
+
+                        if (node.parent.value.name && isUnderscored(name)) {
+                            report(node);
+                        }
                     }
 
-                    if (node.parent.parent && node.parent.parent.type === "ObjectPattern" &&
-                            node.parent.key === node && node.parent.value !== node) {
+                    // "never" check properties
+                    if (properties === "never") {
                         return;
                     }
 
-                    if (isUnderscored(name) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type)) {
+                    // don't check right hand side of AssignmentExpression to prevent duplicate warnings
+                    if (isUnderscored(name) && !ALLOWED_PARENT_TYPES.has(effectiveParent.type) && !(node.parent.right === node)) {
                         report(node);
                     }
 
diff --git a/lib/rules/eol-last.js b/lib/rules/eol-last.js
index 1f3676b0e..3933bc346 100644
--- a/lib/rules/eol-last.js
+++ b/lib/rules/eol-last.js
@@ -46,6 +46,14 @@ module.exports = {
                     CRLF = `\r${LF}`,
                     endsWithNewline = lodash.endsWith(src, LF);
 
+                /*
+                 * Empty source is always valid: No content in file so we don't
+                 * need to lint for a newline on the last line of content.
+                 */
+                if (!src.length) {
+                    return;
+                }
+
                 let mode = context.options[0] || "always",
                     appendCRLF = false;
 
diff --git a/lib/rules/lines-between-class-members.js b/lib/rules/lines-between-class-members.js
index 85e8c6935..ab87f5e84 100644
--- a/lib/rules/lines-between-class-members.js
+++ b/lib/rules/lines-between-class-members.js
@@ -55,7 +55,56 @@ module.exports = {
          * @returns {boolean} True if there is at least a line between the tokens
          */
         function isPaddingBetweenTokens(first, second) {
-            return second.loc.start.line - first.loc.end.line >= 2;
+            const comments = sourceCode.getCommentsBefore(second);
+            const len = comments.length;
+
+            // If there is no comments
+            if (len === 0) {
+                const linesBetweenFstAndSnd = second.loc.start.line - first.loc.end.line - 1;
+
+                return linesBetweenFstAndSnd >= 1;
+            }
+
+
+            // If there are comments
+            let sumOfCommentLines = 0; // the numbers of lines of comments
+            let prevCommentLineNum = -1; // line number of the end of the previous comment
+
+            for (let i = 0; i < len; i++) {
+                const commentLinesOfThisComment = comments[i].loc.end.line - comments[i].loc.start.line + 1;
+
+                sumOfCommentLines += commentLinesOfThisComment;
+
+                /*
+                 * If this comment and the previous comment are in the same line,
+                 * the count of comment lines is duplicated. So decrement sumOfCommentLines.
+                 */
+                if (prevCommentLineNum === comments[i].loc.start.line) {
+                    sumOfCommentLines -= 1;
+                }
+
+                prevCommentLineNum = comments[i].loc.end.line;
+            }
+
+            /*
+             * If the first block and the first comment are in the same line,
+             * the count of comment lines is duplicated. So decrement sumOfCommentLines.
+             */
+            if (first.loc.end.line === comments[0].loc.start.line) {
+                sumOfCommentLines -= 1;
+            }
+
+            /*
+             * If the last comment and the second block are in the same line,
+             * the count of comment lines is duplicated. So decrement sumOfCommentLines.
+             */
+            if (comments[len - 1].loc.end.line === second.loc.start.line) {
+                sumOfCommentLines -= 1;
+            }
+
+            const linesBetweenFstAndSnd = second.loc.start.line - first.loc.end.line - 1;
+
+            return linesBetweenFstAndSnd - sumOfCommentLines >= 1;
         }
 
         return {
@@ -65,8 +114,7 @@ module.exports = {
                 for (let i = 0; i < body.length - 1; i++) {
                     const curFirst = sourceCode.getFirstToken(body[i]);
                     const curLast = sourceCode.getLastToken(body[i]);
-                    const comments = sourceCode.getCommentsBefore(body[i + 1]);
-                    const nextFirst = comments.length ? comments[0] : sourceCode.getFirstToken(body[i + 1]);
+                    const nextFirst = sourceCode.getFirstToken(body[i + 1]);
                     const isPadded = isPaddingBetweenTokens(curLast, nextFirst);
                     const isMulti = !astUtils.isTokenOnSameLine(curFirst, curLast);
                     const skip = !isMulti && options[1].exceptAfterSingleLine;
diff --git a/package.json b/package.json
index ca1e8bfe4..2ac5e8fc9 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
 {
   "name": "eslint",
-  "version": "4.12.1",
+  "version": "4.13.1",
   "author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
   "description": "An AST-based pattern checker for JavaScript.",
   "bin": {
diff --git a/tools/internal-rules/no-invalid-meta.js b/tools/internal-rules/no-invalid-meta.js
index d13df358b..8082d1000 100644
--- a/tools/internal-rules/no-invalid-meta.js
+++ b/tools/internal-rules/no-invalid-meta.js
@@ -175,13 +175,20 @@ module.exports = {
                 }
             },
 
-            "Program:exit"() {
-                if (!isCorrectExportsFormat(exportsNode)) {
-                    context.report({ node: exportsNode, message: "Rule does not export an Object. Make sure the rule follows the new rule format." });
-                    return;
+            "Program:exit"(node) {
+                if (!exportsNode) {
+                    context.report({
+                        node,
+                        message: "Rule does not export anything. Make sure rule exports an object according to new rule format."
+                    });
+                } else if (!isCorrectExportsFormat(exportsNode)) {
+                    context.report({
+                        node: exportsNode,
+                        message: "Rule does not export an Object. Make sure the rule follows the new rule format."
+                    });
+                } else {
+                    checkMetaValidity(context, exportsNode);
                 }
-
-                checkMetaValidity(context, exportsNode);
             }
         };
     }


Test patch:
diff --git a/tests/lib/rules/camelcase.js b/tests/lib/rules/camelcase.js
index 5983fb1c6..81251ff2c 100644
--- a/tests/lib/rules/camelcase.js
+++ b/tests/lib/rules/camelcase.js
@@ -43,14 +43,46 @@ ruleTester.run("camelcase", rule, {
             code: "var o = {key: 1}",
             options: [{ properties: "always" }]
         },
+        {
+            code: "var o = {_leading: 1}",
+            options: [{ properties: "always" }]
+        },
+        {
+            code: "var o = {trailing_: 1}",
+            options: [{ properties: "always" }]
+        },
         {
             code: "var o = {bar_baz: 1}",
             options: [{ properties: "never" }]
         },
+        {
+            code: "var o = {_leading: 1}",
+            options: [{ properties: "never" }]
+        },
+        {
+            code: "var o = {trailing_: 1}",
+            options: [{ properties: "never" }]
+        },
         {
             code: "obj.a_b = 2;",
             options: [{ properties: "never" }]
         },
+        {
+            code: "obj._a = 2;",
+            options: [{ properties: "always" }]
+        },
+        {
+            code: "obj.a_ = 2;",
+            options: [{ properties: "always" }]
+        },
+        {
+            code: "obj._a = 2;",
+            options: [{ properties: "never" }]
+        },
+        {
+            code: "obj.a_ = 2;",
+            options: [{ properties: "never" }]
+        },
         {
             code: "var obj = {\n a_a: 1 \n};\n obj.a_b = 2;",
             options: [{ properties: "never" }]
@@ -64,21 +96,76 @@ ruleTester.run("camelcase", rule, {
             parserOptions: { ecmaVersion: 6 }
         },
         {
-            code: "var { category_id: category } = query;",
-            options: [{ properties: "never" }],
+            code: "var { _leading } = query;",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "var { trailing_ } = query;",
             parserOptions: { ecmaVersion: 6 }
         },
         {
             code: "import { camelCased } from \"external module\";",
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
         },
+        {
+            code: "import { _leading } from \"external module\";",
+            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        },
+        {
+            code: "import { trailing_ } from \"external module\";",
+            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        },
         {
             code: "import { no_camelcased as camelCased } from \"external-module\";",
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
         },
+        {
+            code: "import { no_camelcased as _leading } from \"external-module\";",
+            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        },
+        {
+            code: "import { no_camelcased as trailing_ } from \"external-module\";",
+            parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        },
         {
             code: "import { no_camelcased as camelCased, anoterCamelCased } from \"external-module\";",
             parserOptions: { ecmaVersion: 6, sourceType: "module" }
+        },
+        {
+            code: "function foo({ no_camelcased: camelCased }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ no_camelcased: _leading }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ no_camelcased: trailing_ }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ camelCased = 'default value' }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ _leading = 'default value' }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ trailing_ = 'default value' }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ camelCased }) {};",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ _leading }) {}",
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "function foo({ trailing_ }) {}",
+            parserOptions: { ecmaVersion: 6 }
         }
     ],
     invalid: [
@@ -212,6 +299,16 @@ ruleTester.run("camelcase", rule, {
                 }
             ]
         },
+        {
+            code: "var { category_id = 1 } = query;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'category_id' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
         {
             code: "import no_camelcased from \"external-module\";",
             parserOptions: { ecmaVersion: 6, sourceType: "module" },
@@ -301,6 +398,90 @@ ruleTester.run("camelcase", rule, {
                     type: "Identifier"
                 }
             ]
+        },
+        {
+            code: "function foo({ no_camelcased }) {};",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "function foo({ no_camelcased = 'default value' }) {};",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "const no_camelcased = 0; function foo({ camelcased_value = no_camelcased}) {}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                },
+                {
+                    message: "Identifier 'camelcased_value' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "const { bar: no_camelcased } = foo;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "function foo({ value_1: my_default }) {}",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'my_default' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "function foo({ isCamelcased: no_camelcased }) {};",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "var { foo: bar_baz = 1 } = quz;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'bar_baz' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
+        },
+        {
+            code: "const { no_camelcased = false } = bar;",
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    message: "Identifier 'no_camelcased' is not in camel case.",
+                    type: "Identifier"
+                }
+            ]
         }
     ]
 });
diff --git a/tests/lib/rules/lines-between-class-members.js b/tests/lib/rules/lines-between-class-members.js
index 1304d719a..443a41f2f 100644
--- a/tests/lib/rules/lines-between-class-members.js
+++ b/tests/lib/rules/lines-between-class-members.js
@@ -36,6 +36,10 @@ ruleTester.run("lines-between-class-members", rule, {
         "class foo{ bar(){}\n\nbaz(){}}",
         "class foo{ bar(){}\n\n/*comments*/baz(){}}",
         "class foo{ bar(){}\n\n//comments\nbaz(){}}",
+        "class foo{ bar(){}\n//comments\n\nbaz(){}}",
+        "class A{ foo() {} // a comment\n\nbar() {}}",
+        "class A{ foo() {}\n/* a */ /* b */\n\nbar() {}}",
+        "class A{ foo() {}/* a */ \n\n /* b */bar() {}}",
 
         "class foo{ bar(){}\n\n;;baz(){}}",
         "class foo{ bar(){};\n\nbaz(){}}",
@@ -43,6 +47,9 @@ ruleTester.run("lines-between-class-members", rule, {
         { code: "class foo{ bar(){}\nbaz(){}}", options: ["never"] },
         { code: "class foo{ bar(){}\n/*comments*/baz(){}}", options: ["never"] },
         { code: "class foo{ bar(){}\n//comments\nbaz(){}}", options: ["never"] },
+        { code: "class foo{ bar(){}/* comments\n\n*/baz(){}}", options: ["never"] },
+        { code: "class foo{ bar(){}/* \ncomments\n*/baz(){}}", options: ["never"] },
+        { code: "class foo{ bar(){}\n/* \ncomments\n*/\nbaz(){}}", options: ["never"] },
 
         { code: "class foo{ bar(){}\n\nbaz(){}}", options: ["always"] },
         { code: "class foo{ bar(){}\n\n/*comments*/baz(){}}", options: ["always"] },
diff --git a/tests/lib/testers/rule-tester.js b/tests/lib/testers/rule-tester.js
index 195a616d4..d7a4bd51c 100644
--- a/tests/lib/testers/rule-tester.js
+++ b/tests/lib/testers/rule-tester.js
@@ -126,7 +126,7 @@ describe("RuleTester", () => {
                     { code: "var foo = bar;", errors: [{ message: "Bad error message." }] }
                 ]
             });
-        }, /Bad var\..*==.*Bad error message/);
+        }, /Bad var\.((.*==)|(.*strictEqual)).*Bad error message/);
     });
 
     it("should throw an error when the error message regex does not match", () => {
@@ -167,7 +167,7 @@ describe("RuleTester", () => {
                     { code: "var foo = bar;", errors: ["Bad error message."] }
                 ]
             });
-        }, /Bad var\..*==.*Bad error message/);
+        }, /Bad var\.((.*==)|(.*strictEqual)).*Bad error message/);
     });
 
     it("should throw an error when the error is a string and it does not match error message", () => {
diff --git a/tests/tools/internal-rules/no-invalid-meta.js b/tests/tools/internal-rules/no-invalid-meta.js
index 54b2c9628..5d675e1e3 100644
--- a/tests/tools/internal-rules/no-invalid-meta.js
+++ b/tests/tools/internal-rules/no-invalid-meta.js
@@ -241,6 +241,40 @@ ruleTester.run("no-invalid-meta", rule, {
                 line: 2,
                 column: 5
             }]
+        },
+
+        /*
+         * Rule doesn't export anything: Should warn on the Program node.
+         * See https://github.com/eslint/eslint/issues/9534
+         */
+
+        /*
+         * Should be invalid, but will currently show as valid due to #9534.
+         * FIXME: Uncomment when #9534 is fixed in major release.
+         * {
+         *     code: "",
+         *     errors: [{
+         *         message: "Rule does not export anything. Make sure rule exports an object according to new rule format.",
+         *         line: 1,
+         *         column: 1
+         *     }]
+         * },
+         */
+        {
+            code: "foo();",
+            errors: [{
+                message: "Rule does not export anything. Make sure rule exports an object according to new rule format.",
+                line: 1,
+                column: 1
+            }]
+        },
+        {
+            code: "foo = bar;",
+            errors: [{
+                message: "Rule does not export anything. Make sure rule exports an object according to new rule format.",
+                line: 1,
+                column: 1
+            }]
         }
     ]
 });