Repository: eslint/eslint
Pull request #9467 (2017-10-17 18:00:44)

Docs: Add FAQ for when ESLint cannot find plugin
<!--
    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] Documentation update
[ ] 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)**

Added an FAQ for the most common install/runtime problem we have :smile:

Note: I'm trying to keep this a high-level answer rather than going into a lot of detail.

**Is there anything you'd like reviewers to focus on?**

Anything else to add?

eslintbot: LGTM

Patch:
diff --git a/README.md b/README.md
index 915291d65..9da7d9cce 100644
--- a/README.md
+++ b/README.md
@@ -206,11 +206,23 @@ Maybe, depending on how much you need it. [JSCS has reached end of life](https:/
 
 If you are having issues with JSCS, you can try to move to ESLint. We are focusing our time and energy on JSCS compatibility issues.
 
-
 ### Is ESLint just linting or does it also check style?
 
 ESLint does both traditional linting (looking for problematic patterns) and style checking (enforcement of conventions). You can use it for both.
 
+### Why can't ESLint find my plugins?
+
+ESLint can be [globally or locally installed](#installation-and-usage). If you install ESLint globally, your plugins must also be installed globally; if you install ESLint locally, your plugins must also be installed locally.
+
+If you are trying to run globally, make sure your plugins are installed globally (use `npm ls -g`).
+
+If you are trying to run locally:
+
+* Make sure your plugins (and ESLint) are both in your project's `package.json` as devDependencies (or dependencies, if your project uses ESLint at runtime).
+* Make sure you have run `npm install` and all your dependencies are installed.
+
+In all cases, make sure your plugins' peerDependencies have been installed as well. You can use `npm view eslint-plugin-myplugin peerDepencies` to see what peer dependencies `eslint-plugin-myplugin` has.
+
 ### Does ESLint support JSX?
 
 Yes, ESLint natively supports parsing JSX syntax (this must be enabled in [configuration](https://eslint.org/docs/user-guide/configuring).). Please note that supporting JSX syntax *is not* the same as supporting React. React applies specific semantics to JSX syntax that ESLint doesn't recognize. We recommend using [eslint-plugin-react](https://www.npmjs.com/package/eslint-plugin-react) if you are using React and want React semantics.
diff --git a/docs/user-guide/README.md b/docs/user-guide/README.md
index 50d33e149..36e059a48 100644
--- a/docs/user-guide/README.md
+++ b/docs/user-guide/README.md
@@ -2,7 +2,7 @@
 
 This guide is intended for those who wish to use ESLint as an end-user. If you're looking for how to extend ESLint or work with the ESLint source code, please see the [Developer Guide](../developer-guide).
 
-## [Getting Started](getting-started)
+## [Getting Started](getting-started.md)
 
 Want to skip ahead and just start using ESLint? This section gives a high-level overview of installation, setup, and configuration options.
 
@@ -10,22 +10,27 @@ Want to skip ahead and just start using ESLint? This section gives a high-level
 
 ESLint has a lot of rules that you can configure to fine-tune it to your project. This section is an exhaustive list of every rule and link to each rule's documentation.
 
-## [Configuring](configuring)
+## [Configuring](configuring.md)
 
 Once you've got ESLint running, you'll probably want to adjust the configuration to better suit your project. This section explains all the different ways you can configure ESLint.
 
-## [Command Line Interface](command-line-interface)
+## [Command Line Interface](command-line-interface.md)
 
 There are a lot of command line flags for ESLint and this section explains what they do.
 
-## [Integrations](integrations)
+## [Integrations](integrations.md)
 
 Wondering if ESLint will work with your favorite editor or build system? This section has a list of all known integrations (submitted by their authors).
 
-## [Rule Deprecation](rule-deprecation)
+## [Rule Deprecation](rule-deprecation.md)
 
 The ESLint team is committed to making upgrading as easy and painless as possible. This section outlines the guidelines the team has set in place for the deprecation of rules in future releases.
 
-## [Migrating to 1.0.0](migrating-to-1.0.0)
+## Migrating
 
-If you were using a version of ESLint prior to v1.0.0, this section helps you with the transition.
+If you were using a prior version of ESLint, you can get help with the transition by reading:
+
+- [migrating-to-1.0.0](migrating-to-1.0.0.md)
+- [migrating-to-2.0.0](migrating-to-2.0.0.md)
+- [migrating-to-3.0.0](migrating-to-3.0.0.md)
+- [migrating-to-4.0.0](migrating-to-4.0.0.md)
diff --git a/docs/user-guide/configuring.md b/docs/user-guide/configuring.md
index ed1f573fa..3561502d0 100644
--- a/docs/user-guide/configuring.md
+++ b/docs/user-guide/configuring.md
@@ -3,7 +3,9 @@
 ESLint is designed to be completely configurable, meaning you can turn off every rule and run only with basic syntax validation, or mix and match the bundled rules and your custom rules to make ESLint perfect for your project. There are two primary ways to configure ESLint:
 
 1. **Configuration Comments** - use JavaScript comments to embed configuration information directly into a file.
-1. **Configuration Files** - use a JavaScript, JSON or YAML file to specify configuration information for an entire directory and all of its subdirectories. This can be in the form of an [.eslintrc.*](#configuration-file-formats) file or an `eslintConfig` field in a [`package.json`](https://docs.npmjs.com/files/package.json) file, both of which ESLint will look for and read automatically, or you can specify a configuration file on the [command line](command-line-interface).
+1. **Configuration Files** - use a JavaScript, JSON or YAML file to specify configuration information for an entire directory (other than your home directory) and all of its subdirectories. This can be in the form of an [.eslintrc.*](#configuration-file-formats) file or an `eslintConfig` field in a [`package.json`](https://docs.npmjs.com/files/package.json) file, both of which ESLint will look for and read automatically, or you can specify a configuration file on the [command line](command-line-interface).
+
+    If you have a configuration file in your home directory (generally `~/`), ESLint uses it **only** if ESLint cannot find any other configuration file.
 
 There are several pieces of information that can be configured:
 
diff --git a/lib/rules/multiline-comment-style.js b/lib/rules/multiline-comment-style.js
index d323d882a..0972b7cc7 100644
--- a/lib/rules/multiline-comment-style.js
+++ b/lib/rules/multiline-comment-style.js
@@ -174,8 +174,12 @@ module.exports = {
                                     : MISSING_STAR_ERROR,
                                 fix(fixer) {
                                     const lineStartIndex = sourceCode.getIndexFromLoc({ line: lineNumber, column: 0 });
-                                    const commentStartIndex = lineStartIndex + lineText.match(/^\s*\*? ?/)[0].length;
-                                    const replacementText = lineNumber === block.loc.end.line ? expectedLinePrefix : `${expectedLinePrefix} `;
+                                    const linePrefixLength = lineText.match(/^\s*\*? ?/)[0].length;
+                                    const commentStartIndex = lineStartIndex + linePrefixLength;
+
+                                    const replacementText = lineNumber === block.loc.end.line || lineText.length === linePrefixLength
+                                        ? expectedLinePrefix
+                                        : `${expectedLinePrefix} `;
 
                                     return fixer.replaceTextRange([lineStartIndex, commentStartIndex], replacementText);
                                 }
@@ -188,6 +192,11 @@ module.exports = {
                 if (!isJSDoc(commentGroup) && commentGroup[0].type === "Block") {
                     const commentLines = getCommentLines(commentGroup);
                     const block = commentGroup[0];
+                    const tokenAfter = sourceCode.getTokenAfter(block, { includeComments: true });
+
+                    if (tokenAfter && block.loc.end.line === tokenAfter.loc.start.line) {
+                        return;
+                    }
 
                     context.report({
                         loc: {
diff --git a/lib/rules/no-constant-condition.js b/lib/rules/no-constant-condition.js
index 31e5b372c..0cd445dfd 100644
--- a/lib/rules/no-constant-condition.js
+++ b/lib/rules/no-constant-condition.js
@@ -138,7 +138,7 @@ module.exports = {
         function checkConstantConditionLoopInSet(node) {
             if (loopsInCurrentScope.has(node)) {
                 loopsInCurrentScope.delete(node);
-                context.report({ node, message: "Unexpected constant condition." });
+                context.report({ node: node.test, message: "Unexpected constant condition." });
             }
         }
 
@@ -150,7 +150,7 @@ module.exports = {
          */
         function reportIfConstant(node) {
             if (node.test && isConstant(node.test, true)) {
-                context.report({ node, message: "Unexpected constant condition." });
+                context.report({ node: node.test, message: "Unexpected constant condition." });
             }
         }
 


Test patch:
diff --git a/tests/lib/rules/multiline-comment-style.js b/tests/lib/rules/multiline-comment-style.js
index f5c23bad1..9da55a995 100644
--- a/tests/lib/rules/multiline-comment-style.js
+++ b/tests/lib/rules/multiline-comment-style.js
@@ -144,6 +144,13 @@ ruleTester.run("multiline-comment-style", rule, {
             `,
             options: ["separate-lines"]
         },
+        {
+            code: `
+                /* this is
+                   a comment */ foo;
+            `,
+            options: ["separate-lines"]
+        },
         {
             code: `
                 /* eslint semi: "error" */
@@ -325,6 +332,55 @@ ruleTester.run("multiline-comment-style", rule, {
             `,
             errors: [{ message: ALIGNMENT_ERROR, line: 5 }]
         },
+        {
+            code: `
+                /*
+                 * the following line
+                *
+                 * is blank
+                 */
+            `,
+            output: `
+                /*
+                 * the following line
+                 *
+                 * is blank
+                 */
+            `,
+            errors: [{ message: ALIGNMENT_ERROR, line: 4 }]
+        },
+        {
+            code: `
+                /*
+                 * the following line
+                  *
+                 * is blank
+                 */
+            `,
+            output: `
+                /*
+                 * the following line
+                 *
+                 * is blank
+                 */
+            `,
+            errors: [{ message: ALIGNMENT_ERROR, line: 4 }]
+        },
+        {
+            code: `
+                /*
+                 * the last line of this comment
+                 * is misaligned
+                   */ foo
+            `,
+            output: `
+                /*
+                 * the last line of this comment
+                 * is misaligned
+                 */ foo
+            `,
+            errors: [{ message: ALIGNMENT_ERROR, line: 5 }]
+        },
         {
             code: `
                 /*
diff --git a/tests/lib/rules/no-constant-condition.js b/tests/lib/rules/no-constant-condition.js
index b113ebb09..9f7bc4c0d 100644
--- a/tests/lib/rules/no-constant-condition.js
+++ b/tests/lib/rules/no-constant-condition.js
@@ -71,90 +71,90 @@ ruleTester.run("no-constant-condition", rule, {
         "function* foo() { for (let x = yield; ; x++) { yield; }}"
     ],
     invalid: [
-        { code: "for(;true;);", errors: [{ message: "Unexpected constant condition.", type: "ForStatement" }] },
-        { code: "do{}while(true)", errors: [{ message: "Unexpected constant condition.", type: "DoWhileStatement" }] },
-        { code: "do{}while(t = -2)", errors: [{ message: "Unexpected constant condition.", type: "DoWhileStatement" }] },
-        { code: "true ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "ConditionalExpression" }] },
-        { code: "q = 0 ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "ConditionalExpression" }] },
-        { code: "(q = 0) ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "ConditionalExpression" }] },
-        { code: "if(-2);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(true);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if({});", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(0 < 1);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(0 || 1);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(a, 1);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-
-        { code: "while([]);", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
-        { code: "while(~!0);", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
-        { code: "while(x = 1);", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
-        { code: "while(function(){});", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
-        { code: "while(true);", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
-        { code: "while(() => {});", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
+        { code: "for(;true;);", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "do{}while(true)", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "do{}while(t = -2)", errors: [{ message: "Unexpected constant condition.", type: "AssignmentExpression" }] },
+        { code: "true ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "q = 0 ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "(q = 0) ? 1 : 2;", errors: [{ message: "Unexpected constant condition.", type: "AssignmentExpression" }] },
+        { code: "if(-2);", errors: [{ message: "Unexpected constant condition.", type: "UnaryExpression" }] },
+        { code: "if(true);", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "if({});", errors: [{ message: "Unexpected constant condition.", type: "ObjectExpression" }] },
+        { code: "if(0 < 1);", errors: [{ message: "Unexpected constant condition.", type: "BinaryExpression" }] },
+        { code: "if(0 || 1);", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(a, 1);", errors: [{ message: "Unexpected constant condition.", type: "SequenceExpression" }] },
+
+        { code: "while([]);", errors: [{ message: "Unexpected constant condition.", type: "ArrayExpression" }] },
+        { code: "while(~!0);", errors: [{ message: "Unexpected constant condition.", type: "UnaryExpression" }] },
+        { code: "while(x = 1);", errors: [{ message: "Unexpected constant condition.", type: "AssignmentExpression" }] },
+        { code: "while(function(){});", errors: [{ message: "Unexpected constant condition.", type: "FunctionExpression" }] },
+        { code: "while(true);", errors: [{ message: "Unexpected constant condition.", type: "Literal" }] },
+        { code: "while(() => {});", errors: [{ message: "Unexpected constant condition.", type: "ArrowFunctionExpression" }] },
 
         // #5228 , typeof conditions
-        { code: "if(typeof x){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(typeof 'abc' === 'string'){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(a = typeof b){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(a, typeof b){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(typeof 'a' == 'string' || typeof 'b' == 'string'){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "while(typeof x){}", errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }] },
+        { code: "if(typeof x){}", errors: [{ message: "Unexpected constant condition.", type: "UnaryExpression" }] },
+        { code: "if(typeof 'abc' === 'string'){}", errors: [{ message: "Unexpected constant condition.", type: "BinaryExpression" }] },
+        { code: "if(a = typeof b){}", errors: [{ message: "Unexpected constant condition.", type: "AssignmentExpression" }] },
+        { code: "if(a, typeof b){}", errors: [{ message: "Unexpected constant condition.", type: "SequenceExpression" }] },
+        { code: "if(typeof 'a' == 'string' || typeof 'b' == 'string'){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "while(typeof x){}", errors: [{ message: "Unexpected constant condition.", type: "UnaryExpression" }] },
 
         // #5726, void conditions
-        { code: "if(1 || void x);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(void x);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(y = void x);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(x, void x);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(void x === void y);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(void x && a);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(a && void x);", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
+        { code: "if(1 || void x);", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(void x);", errors: [{ message: "Unexpected constant condition.", type: "UnaryExpression" }] },
+        { code: "if(y = void x);", errors: [{ message: "Unexpected constant condition.", type: "AssignmentExpression" }] },
+        { code: "if(x, void x);", errors: [{ message: "Unexpected constant condition.", type: "SequenceExpression" }] },
+        { code: "if(void x === void y);", errors: [{ message: "Unexpected constant condition.", type: "BinaryExpression" }] },
+        { code: "if(void x && a);", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(a && void x);", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
 
         // #5693
-        { code: "if(false && abc==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(true || abc==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(abc==='str' || true){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(abc==='str' || true || def ==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(false || true){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
-        { code: "if(typeof abc==='str' || true){}", errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }] },
+        { code: "if(false && abc==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(true || abc==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(abc==='str' || true){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(abc==='str' || true || def ==='str'){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(false || true){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
+        { code: "if(typeof abc==='str' || true){}", errors: [{ message: "Unexpected constant condition.", type: "LogicalExpression" }] },
 
         {
             code: "function* foo(){while(true){} yield 'foo';}",
-            errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo(){while(true){if (true) {yield 'foo';}}}",
-            errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo(){while(true){yield 'foo';} while(true) {}}",
-            errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "var a = function* foo(){while(true){} yield 'foo';}",
-            errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "while (true) { function* foo() {yield;}}",
-            errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo(){if (true) {yield 'foo';}}",
-            errors: [{ message: "Unexpected constant condition.", type: "IfStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo() {for (let foo = yield; true;) {}}",
-            errors: [{ message: "Unexpected constant condition.", type: "ForStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo() {for (foo = yield; true;) {}}",
-            errors: [{ message: "Unexpected constant condition.", type: "ForStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function foo() {while (true) {function* bar() {while (true) {yield;}}}}",
-            errors: [{ message: "Unexpected constant condition.", type: "WhileStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         },
         {
             code: "function* foo() { for (let foo = 1 + 2 + 3 + (yield); true; baz) {}}",
-            errors: [{ message: "Unexpected constant condition.", type: "ForStatement" }]
+            errors: [{ message: "Unexpected constant condition.", type: "Literal" }]
         }
     ]
 });