Repository: eslint/eslint
Pull request #12174 (2019-08-27 11:30:07)

Fix: reset to the default color
<!--
    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)**

When we issue a warning on webpack, every warning is yellow and bold.
With `eslint-loader` and the` stylish` formatter the first line is different from the others.

https://github.com/webpack-contrib/eslint-loader/issues/292

**Is there anything you'd like reviewers to focus on?**




Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 000000000..0667729f8
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,63 @@
+name: CI
+on:
+  push:
+    branches: [master]
+  pull_request:
+    branches: [master]
+
+jobs:
+  verify_files:
+    name: Verify Files
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v1
+    - uses: actions/setup-node@v1
+    - name: Install Packages
+      run: npm install
+    - name: Lint Files
+      run: node Makefile lint
+    - name: Check Rule Files
+      run: node Makefile checkRuleFiles
+    - name: Check Licenses
+      run: node Makefile checkLicenses
+
+  test_on_node:
+    name: Test
+    strategy:
+      matrix:
+        os: [ubuntu-latest, windows-latest, macOS-latest]
+        node: [8.x, 10.x, 12.x]
+        exclude:
+        - os: windows-latest
+          node: 8.x
+        - os: windows-latest
+          node: 10.x
+        - os: macOS-latest
+          node: 8.x
+        - os: macOS-latest
+          node: 10.x
+    runs-on: ${{ matrix.os }}
+    steps:
+    - uses: actions/checkout@v1
+    - uses: actions/setup-node@v1
+      with:
+        version: ${{ matrix.node }}
+    - name: Install Packages
+      run: npm install
+    - name: Test
+      run: node Makefile mocha
+    - name: Fuzz Test
+      run: node Makefile fuzz
+
+  test_on_browser:
+    name: Browser Test
+    runs-on: ubuntu-latest
+    steps:
+    - uses: actions/checkout@v1
+    - uses: actions/setup-node@v1
+    - name: Install Packages
+      run: npm install
+    - name: Test
+      run: node Makefile karma
+    - name: Fuzz Test
+      run: node Makefile fuzz
diff --git a/Makefile.js b/Makefile.js
index 02386d2f4..a01d13bde 100644
--- a/Makefile.js
+++ b/Makefile.js
@@ -497,7 +497,7 @@ target.lint = function() {
     }
 };
 
-target.fuzz = function({ amount = process.env.CI ? 1000 : 300, fuzzBrokenAutofixes = true } = {}) {
+target.fuzz = function({ amount = 1000, fuzzBrokenAutofixes = false } = {}) {
     const fuzzerRunner = require("./tools/fuzzer-runner");
     const fuzzResults = fuzzerRunner.run({ amount, fuzzBrokenAutofixes });
 
@@ -536,18 +536,13 @@ target.fuzz = function({ amount = process.env.CI ? 1000 : 300, fuzzBrokenAutofix
     }
 };
 
-target.test = function() {
-    target.lint();
-    target.checkRuleFiles();
+target.mocha = () => {
     let errors = 0,
         lastReturn;
 
     echo("Running unit tests");
 
-    // In CI (Azure Pipelines), use JUnit reporter.
-    const reporter = process.env.TF_BUILD ? "mocha-junit-reporter" : "progress";
-
-    lastReturn = exec(`${getBinFile("nyc")} -- ${MOCHA} -R ${reporter} -t ${MOCHA_TIMEOUT} -c ${TEST_FILES}`);
+    lastReturn = exec(`${getBinFile("nyc")} -- ${MOCHA} -R progress -t ${MOCHA_TIMEOUT} -c ${TEST_FILES}`);
     if (lastReturn.code !== 0) {
         errors++;
     }
@@ -557,6 +552,14 @@ target.test = function() {
         errors++;
     }
 
+    if (errors) {
+        exit(1);
+    }
+};
+
+target.karma = () => {
+    echo("Running unit tests on browsers");
+
     target.webpack();
 
     const browserFileLintOutput = new CLIEngine({
@@ -569,20 +572,22 @@ target.test = function() {
     if (browserFileLintOutput.errorCount > 0) {
         echo(`error: Failed to lint ${BUILD_DIR}/eslint.js as ES5 code`);
         echo(CLIEngine.getFormatter("stylish")(browserFileLintOutput.results));
-        errors++;
+        exit(1);
     }
 
-    lastReturn = exec(`${getBinFile("karma")} start karma.conf.js`);
-    if (lastReturn.code !== 0) {
-        errors++;
-    }
+    const lastReturn = exec(`${getBinFile("karma")} start karma.conf.js`);
 
-    if (errors) {
+    if (lastReturn.code !== 0) {
         exit(1);
     }
+};
 
+target.test = function() {
+    target.lint();
+    target.checkRuleFiles();
+    target.mocha();
+    target.karma();
     target.fuzz({ amount: 150, fuzzBrokenAutofixes: false });
-
     target.checkLicenses();
 };
 
diff --git a/README.md b/README.md
index 7ed0416c3..134c991d8 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,6 @@
 [![NPM version][npm-image]][npm-url]
 [![Build Status](https://dev.azure.com/eslint/eslint/_apis/build/status/eslint.eslint?branchName=master)](https://dev.azure.com/eslint/eslint/_build/latest?definitionId=1&branchName=master)
+[![Build Status](https://github.com/eslint/eslint/workflows/CI/badge.svg)](https://github.com/eslint/eslint/actions)
 [![Downloads][downloads-image]][downloads-url]
 [![Bountysource](https://www.bountysource.com/badge/tracker?tracker_id=282608)](https://www.bountysource.com/trackers/282608-eslint?utm_source=282608&utm_medium=shield&utm_campaign=TRACKER_BADGE)
 [![Join the chat at https://gitter.im/eslint/eslint](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/eslint/eslint?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
diff --git a/lib/cli-engine/formatters/stylish.js b/lib/cli-engine/formatters/stylish.js
index ca132ffa8..a808448b6 100644
--- a/lib/cli-engine/formatters/stylish.js
+++ b/lib/cli-engine/formatters/stylish.js
@@ -96,5 +96,6 @@ module.exports = function(results) {
         }
     }
 
-    return total > 0 ? output : "";
+    // Resets output color, for prevent change on top level
+    return total > 0 ? chalk.reset(output) : "";
 };
diff --git a/lib/init/config-initializer.js b/lib/init/config-initializer.js
index 17aa96505..2e47e902c 100644
--- a/lib/init/config-initializer.js
+++ b/lib/init/config-initializer.js
@@ -120,6 +120,12 @@ function getModulesList(config, installESLint) {
         }
     }
 
+    const parser = config.parser || (config.parserOptions && config.parserOptions.parser);
+
+    if (parser) {
+        modules[parser] = "latest";
+    }
+
     if (installESLint === false) {
         delete modules.eslint;
     } else {
@@ -291,6 +297,20 @@ function processAnswers(answers) {
         config.extends.push("plugin:vue/essential");
     }
 
+    if (answers.typescript) {
+        if (answers.framework === "vue") {
+            config.parserOptions.parser = "@typescript-eslint/parser";
+        } else {
+            config.parser = "@typescript-eslint/parser";
+        }
+
+        if (Array.isArray(config.plugins)) {
+            config.plugins.push("@typescript-eslint");
+        } else {
+            config.plugins = ["@typescript-eslint"];
+        }
+    }
+
     // setup rules based on problems/style enforcement preferences
     if (answers.purpose === "problems") {
         config.extends.unshift("eslint:recommended");
@@ -306,6 +326,9 @@ function processAnswers(answers) {
             config = autoconfig.extendFromRecommended(config);
         }
     }
+    if (answers.typescript && config.extends.includes("eslint:recommended")) {
+        config.extends.push("plugin:@typescript-eslint/eslint-recommended");
+    }
 
     // normalize extends
     if (config.extends.length === 0) {
@@ -465,6 +488,12 @@ function promptUser() {
                 { name: "None of these", value: "none" }
             ]
         },
+        {
+            type: "confirm",
+            name: "typescript",
+            message: "Does your project use TypeScript?",
+            default: false
+        },
         {
             type: "checkbox",
             name: "env",
diff --git a/lib/rules/no-extra-boolean-cast.js b/lib/rules/no-extra-boolean-cast.js
index 9ae9b5be6..9bbd5546e 100644
--- a/lib/rules/no-extra-boolean-cast.js
+++ b/lib/rules/no-extra-boolean-cast.js
@@ -102,7 +102,17 @@ module.exports = {
                             if (hasCommentsInside(parent)) {
                                 return null;
                             }
-                            return fixer.replaceText(parent, sourceCode.getText(node.argument));
+
+                            let prefix = "";
+                            const tokenBefore = sourceCode.getTokenBefore(parent);
+                            const firstReplacementToken = sourceCode.getFirstToken(node.argument);
+
+                            if (tokenBefore && tokenBefore.range[1] === parent.range[0] &&
+                                    !astUtils.canTokensBeAdjacent(tokenBefore, firstReplacementToken)) {
+                                prefix = " ";
+                            }
+
+                            return fixer.replaceText(parent, prefix + sourceCode.getText(node.argument));
                         }
                     });
                 }
diff --git a/lib/rules/yoda.js b/lib/rules/yoda.js
index 89c4a8afd..b00acf82c 100644
--- a/lib/rules/yoda.js
+++ b/lib/rules/yoda.js
@@ -274,13 +274,22 @@ module.exports = {
          * @returns {string} A string representation of the node with the sides and operator flipped
          */
         function getFlippedString(node) {
+            const tokenBefore = sourceCode.getTokenBefore(node);
             const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
             const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
             const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]);
             const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
-            const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], node.range[1]);
+            const firstRightToken = sourceCode.getTokenAfter(operatorToken);
+            const rightText = sourceCode.getText().slice(firstRightToken.range[0], node.range[1]);
 
-            return rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
+            let prefix = "";
+
+            if (tokenBefore && tokenBefore.range[1] === node.range[0] &&
+                    !astUtils.canTokensBeAdjacent(tokenBefore, firstRightToken)) {
+                prefix = " ";
+            }
+
+            return prefix + rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
         }
 
         //--------------------------------------------------------------------------
diff --git a/tools/eslint-fuzzer.js b/tools/eslint-fuzzer.js
index dce2b2352..dc0a65a8e 100644
--- a/tools/eslint-fuzzer.js
+++ b/tools/eslint-fuzzer.js
@@ -129,7 +129,7 @@ function fuzz(options) {
         const text = codeGenerator({ sourceType });
         const config = {
             rules: lodash.mapValues(ruleConfigs, lodash.sample),
-            parserOptions: { sourceType, ecmaVersion: 2018 }
+            parserOptions: { sourceType, ecmaVersion: 2020 }
         };
 
         let autofixResult;


Test patch:
diff --git a/tests/lib/cli-engine/formatters/stylish.js b/tests/lib/cli-engine/formatters/stylish.js
index b336df54b..54e66fbc1 100644
--- a/tests/lib/cli-engine/formatters/stylish.js
+++ b/tests/lib/cli-engine/formatters/stylish.js
@@ -19,6 +19,12 @@ const assert = require("chai").assert,
  * for Sinon to work.
  */
 const chalkStub = Object.create(chalk, {
+    reset: {
+        value(str) {
+            return chalk.reset(str);
+        },
+        writable: true
+    },
     yellow: {
         value(str) {
             return chalk.yellow(str);
@@ -47,6 +53,7 @@ describe("formatter:stylish", () => {
 
     beforeEach(() => {
         chalk.enabled = false;
+        sinon.spy(chalkStub, "reset");
         sinon.spy(chalkStub.yellow, "bold");
         sinon.spy(chalkStub.red, "bold");
     });
@@ -68,6 +75,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "");
+            assert.strictEqual(chalkStub.reset.callCount, 0);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 0);
         });
@@ -93,8 +101,10 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
+
         });
 
         describe("when the error is fixable", () => {
@@ -106,6 +116,7 @@ describe("formatter:stylish", () => {
                 const result = formatter(code);
 
                 assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n  1 error and 0 warnings potentially fixable with the `--fix` option.\n");
+                assert.strictEqual(chalkStub.reset.callCount, 1);
                 assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
                 assert.strictEqual(chalkStub.red.bold.callCount, 2);
             });
@@ -132,6 +143,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected foo  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 1);
             assert.strictEqual(chalkStub.red.bold.callCount, 0);
         });
@@ -145,6 +157,7 @@ describe("formatter:stylish", () => {
                 const result = formatter(code);
 
                 assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected foo  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n  0 errors and 1 warning potentially fixable with the `--fix` option.\n");
+                assert.strictEqual(chalkStub.reset.callCount, 1);
                 assert.strictEqual(chalkStub.yellow.bold.callCount, 2);
                 assert.strictEqual(chalkStub.red.bold.callCount, 0);
             });
@@ -172,6 +185,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  warning  Unexpected .  foo\n\n\u2716 1 problem (0 errors, 1 warning)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 1);
             assert.strictEqual(chalkStub.red.bold.callCount, 0);
         });
@@ -195,6 +209,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\n\u2716 1 problem (1 error, 0 warnings)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
@@ -224,6 +239,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error    Unexpected foo  foo\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (1 error, 1 warning)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
@@ -258,6 +274,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (1 error, 1 warning)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
@@ -271,6 +288,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (2 errors, 0 warnings)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
@@ -284,6 +302,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  5:10  error  Unexpected foo  foo\n\nbar.js\n  6:11  warning  Unexpected bar  bar\n\n\u2716 2 problems (0 errors, 2 warnings)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
@@ -304,6 +323,7 @@ describe("formatter:stylish", () => {
             const result = formatter(code);
 
             assert.strictEqual(result, "\nfoo.js\n  0:0  error  Couldn't find foo.js\n\n\u2716 1 problem (1 error, 0 warnings)\n");
+            assert.strictEqual(chalkStub.reset.callCount, 1);
             assert.strictEqual(chalkStub.yellow.bold.callCount, 0);
             assert.strictEqual(chalkStub.red.bold.callCount, 1);
         });
diff --git a/tests/lib/init/config-initializer.js b/tests/lib/init/config-initializer.js
index 4ee6ff6b7..ed2388fd5 100644
--- a/tests/lib/init/config-initializer.js
+++ b/tests/lib/init/config-initializer.js
@@ -168,6 +168,24 @@ describe("configInitializer", () => {
                 assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:vue/essential"]);
             });
 
+            it("should enable typescript parser and plugin", () => {
+                answers.typescript = true;
+                const config = init.processAnswers(answers);
+
+                assert.strictEqual(config.parser, "@typescript-eslint/parser");
+                assert.deepStrictEqual(config.plugins, ["@typescript-eslint"]);
+                assert.deepStrictEqual(config.extends, ["eslint:recommended", "plugin:@typescript-eslint/eslint-recommended"]);
+            });
+
+            it("should enable typescript parser and plugin with vue", () => {
+                answers.framework = "vue";
+                answers.typescript = true;
+                const config = init.processAnswers(answers);
+
+                assert.strictEqual(config.parserOptions.parser, "@typescript-eslint/parser");
+                assert.deepStrictEqual(config.plugins, ["vue", "@typescript-eslint"]);
+            });
+
             it("should extend eslint:recommended", () => {
                 const config = init.processAnswers(answers);
 
@@ -317,6 +335,28 @@ describe("configInitializer", () => {
                 assert.include(modules, "eslint-plugin-vue@latest");
                 assert.include(modules, "eslint-config-standard@latest");
             });
+
+            it("should support custom parser", () => {
+                const config = {
+                    parser: "@typescript-eslint/parser"
+                };
+                const modules = init.getModulesList(config);
+
+                assert.include(modules, "@typescript-eslint/parser@latest");
+            });
+
+            it("should support custom parser with Vue.js", () => {
+                const config = {
+
+                    // We should declare the parser at `parserOptions` when using with `eslint-plugin-vue`.
+                    parserOptions: {
+                        parser: "@typescript-eslint/parser"
+                    }
+                };
+                const modules = init.getModulesList(config);
+
+                assert.include(modules, "@typescript-eslint/parser@latest");
+            });
         });
 
         describe("auto", () => {
diff --git a/tests/lib/rules/no-extra-boolean-cast.js b/tests/lib/rules/no-extra-boolean-cast.js
index 129329ff0..1de914ca5 100644
--- a/tests/lib/rules/no-extra-boolean-cast.js
+++ b/tests/lib/rules/no-extra-boolean-cast.js
@@ -270,6 +270,68 @@ ruleTester.run("no-extra-boolean-cast", rule, {
         },
 
         // Adjacent tokens tests
+        {
+            code: "function *foo() { yield!!a ? b : c }",
+            output: "function *foo() { yield a ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "function *foo() { yield!! a ? b : c }",
+            output: "function *foo() { yield a ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "function *foo() { yield! !a ? b : c }",
+            output: "function *foo() { yield a ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "function *foo() { yield !!a ? b : c }",
+            output: "function *foo() { yield a ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "function *foo() { yield(!!a) ? b : c }",
+            output: "function *foo() { yield(a) ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "function *foo() { yield/**/!!a ? b : c }",
+            output: "function *foo() { yield/**/a ? b : c }",
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
+        {
+            code: "x=!!a ? b : c ",
+            output: "x=a ? b : c ",
+            errors: [{
+                messageId: "unexpectedNegation",
+                type: "UnaryExpression"
+            }]
+        },
         {
             code: "void!Boolean()",
             output: "void true",
diff --git a/tests/lib/rules/yoda.js b/tests/lib/rules/yoda.js
index d2c183477..7908499d8 100644
--- a/tests/lib/rules/yoda.js
+++ b/tests/lib/rules/yoda.js
@@ -568,6 +568,175 @@ ruleTester.run("yoda", rule, {
                     type: "BinaryExpression"
                 }
             ]
+        },
+
+        // Adjacent tokens tests
+        {
+            code: "function *foo() { yield(1) < a }",
+            output: "function *foo() { yield a > (1) }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield((1)) < a }",
+            output: "function *foo() { yield a > ((1)) }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield 1 < a }",
+            output: "function *foo() { yield a > 1 }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield/**/1 < a }",
+            output: "function *foo() { yield/**/a > 1 }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield(1) < ++a }",
+            output: "function *foo() { yield++a > (1) }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield(1) < (a) }",
+            output: "function *foo() { yield(a) > (1) }",
+            options: ["never"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "x=1 < a",
+            output: "x=a > 1",
+            options: ["never"],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "right", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield++a < 1 }",
+            output: "function *foo() { yield 1 > ++a }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield(a) < 1 }",
+            output: "function *foo() { yield 1 > (a) }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield a < 1 }",
+            output: "function *foo() { yield 1 > a }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield/**/a < 1 }",
+            output: "function *foo() { yield/**/1 > a }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "function *foo() { yield++a < (1) }",
+            output: "function *foo() { yield(1) > ++a }",
+            options: ["always"],
+            parserOptions: { ecmaVersion: 2015 },
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
+        },
+        {
+            code: "x=a < 1",
+            output: "x=1 > a",
+            options: ["always"],
+            errors: [
+                {
+                    messageId: "expected",
+                    data: { expectedSide: "left", operator: "<" },
+                    type: "BinaryExpression"
+                }
+            ]
         }
     ]
 });