Repository: eslint/eslint
Pull request #12524 (2019-11-03 07:57:19)

Docs: add notice about `function` keyword in keyword-spacing
<!--
    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

<!--
    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 notice about `function` keyword to reduce confusion.



Patch:
diff --git a/docs/rules/keyword-spacing.md b/docs/rules/keyword-spacing.md
index becc9ef32..ecc6bb0a4 100644
--- a/docs/rules/keyword-spacing.md
+++ b/docs/rules/keyword-spacing.md
@@ -1,7 +1,7 @@
 # enforce consistent spacing before and after keywords (keyword-spacing)
 
-Keywords are syntax elements of JavaScript, such as `function` and `if`.
-These identifiers have special meaning to the language and so often appear in a different color in code editors.
+Keywords are syntax elements of JavaScript, such as `try` and `if`.
+These keywords have special meaning to the language and so often appear in a different color in code editors.
 As an important part of the language, style guides often refer to the spacing that should be used around keywords.
 For example, you might have a style guide that says keywords should be always surrounded by spaces, which would mean `if-else` statements must look like this:
 
@@ -15,6 +15,8 @@ if (foo) {
 
 Of course, you could also have a style guide that disallows spaces around keywords.
 
+However, if you want to enforce the style of spacing between the `function` keyword and the following opening parenthesis, please refer to [space-before-function-paren](space-before-function-paren.md).
+
 ## Rule Details
 
 This rule enforces consistent spacing around keywords and keyword-like tokens: `as` (in module declarations), `async` (of async functions), `await` (of await expressions), `break`, `case`, `catch`, `class`, `const`, `continue`, `debugger`, `default`, `delete`, `do`, `else`, `export`, `extends`, `finally`, `for`, `from` (in module declarations), `function`, `get` (of getters), `if`, `import`, `in`, `instanceof`, `let`, `new`, `of` (in for-of statements), `return`, `set` (of setters), `static`, `super`, `switch`, `this`, `throw`, `try`, `typeof`, `var`, `void`, `while`, `with`, and `yield`. This rule is designed carefully not to conflict with other spacing rules: it does not apply to spacing where other rules report problems.
diff --git a/lib/rules/curly.js b/lib/rules/curly.js
index c62acdfe9..ee2fe4dce 100644
--- a/lib/rules/curly.js
+++ b/lib/rules/curly.js
@@ -245,7 +245,7 @@ module.exports = {
             if (node.type === "IfStatement" && node.consequent === body && requiresBraceOfConsequent(node)) {
                 expected = true;
             } else if (multiOnly) {
-                if (hasBlock && body.body.length === 1) {
+                if (hasBlock && body.body.length === 1 && !isLexicalDeclaration(body.body[0])) {
                     expected = false;
                 }
             } else if (multiLine) {
diff --git a/lib/rules/prefer-const.js b/lib/rules/prefer-const.js
index 87f838921..439a4db3c 100644
--- a/lib/rules/prefer-const.js
+++ b/lib/rules/prefer-const.js
@@ -356,7 +356,9 @@ module.exports = {
         const ignoreReadBeforeAssign = options.ignoreReadBeforeAssign === true;
         const variables = [];
         let reportCount = 0;
-        let name = "";
+        let checkedId = null;
+        let checkedName = "";
+
 
         /**
          * Reports given identifier nodes if all of the nodes should be declared
@@ -387,25 +389,30 @@ module.exports = {
                         /*
                          * First we check the declaration type and then depending on
                          * if the type is a "VariableDeclarator" or its an "ObjectPattern"
-                         * we compare the name from the first identifier, if the names are different
-                         * we assign the new name and reset the count of reportCount and nodeCount in
+                         * we compare the name and id from the first identifier, if the names are different
+                         * we assign the new name, id and reset the count of reportCount and nodeCount in
                          * order to check each block for the number of reported errors and base our fix
                          * based on comparing nodes.length and nodesToReport.length.
                          */
 
                         if (firstDecParent.type === "VariableDeclarator") {
 
-                            if (firstDecParent.id.name !== name) {
-                                name = firstDecParent.id.name;
+                            if (firstDecParent.id.name !== checkedName) {
+                                checkedName = firstDecParent.id.name;
                                 reportCount = 0;
                             }
 
                             if (firstDecParent.id.type === "ObjectPattern") {
-                                if (firstDecParent.init.name !== name) {
-                                    name = firstDecParent.init.name;
+                                if (firstDecParent.init.name !== checkedName) {
+                                    checkedName = firstDecParent.init.name;
                                     reportCount = 0;
                                 }
                             }
+
+                            if (firstDecParent.id !== checkedId) {
+                                checkedId = firstDecParent.id;
+                                reportCount = 0;
+                            }
                         }
                     }
                 }


Test patch:
diff --git a/tests/lib/rules/curly.js b/tests/lib/rules/curly.js
index 57987a344..457e55f49 100644
--- a/tests/lib/rules/curly.js
+++ b/tests/lib/rules/curly.js
@@ -164,6 +164,35 @@ ruleTester.run("curly", rule, {
             options: ["multi-or-nest"],
             parserOptions: { ecmaVersion: 6 }
         },
+        {
+            code: "if (foo) { const bar = 'baz'; }",
+            options: ["multi"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "while (foo) { let bar = 'baz'; }",
+            options: ["multi"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "for(;;) { function foo() {} }",
+            options: ["multi"]
+        },
+        {
+            code: "for (foo in bar) { class Baz {} }",
+            options: ["multi"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "if (foo) { let bar; } else { baz(); }",
+            options: ["multi", "consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
+        {
+            code: "if (foo) { bar(); } else { const baz = 'quux'; }",
+            options: ["multi", "consistent"],
+            parserOptions: { ecmaVersion: 6 }
+        },
         {
             code: "if (foo) { \n const bar = 'baz'; \n }",
             options: ["multi-or-nest"],
@@ -692,6 +721,44 @@ ruleTester.run("curly", rule, {
                 }
             ]
         },
+        {
+            code: "if (foo) { var bar = 'baz'; }",
+            output: "if (foo)  var bar = 'baz'; ",
+            options: ["multi"],
+            errors: [
+                {
+                    messageId: "unexpectedCurlyAfterCondition",
+                    data: { name: "if" },
+                    type: "IfStatement"
+                }
+            ]
+        },
+        {
+            code: "if (foo) { let bar; } else baz();",
+            output: "if (foo) { let bar; } else {baz();}",
+            options: ["multi", "consistent"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingCurlyAfter",
+                    data: { name: "else" },
+                    type: "IfStatement"
+                }
+            ]
+        },
+        {
+            code: "if (foo) bar(); else { const baz = 'quux' }",
+            output: "if (foo) {bar();} else { const baz = 'quux' }",
+            options: ["multi", "consistent"],
+            parserOptions: { ecmaVersion: 6 },
+            errors: [
+                {
+                    messageId: "missingCurlyAfterCondition",
+                    data: { name: "if" },
+                    type: "IfStatement"
+                }
+            ]
+        },
         {
             code: "if (foo) { \n var bar = 'baz'; \n }",
             output: "if (foo)  \n var bar = 'baz'; \n ",
diff --git a/tests/lib/rules/prefer-const.js b/tests/lib/rules/prefer-const.js
index d92398533..ad25f5f48 100644
--- a/tests/lib/rules/prefer-const.js
+++ b/tests/lib/rules/prefer-const.js
@@ -527,6 +527,25 @@ ruleTester.run("prefer-const", rule, {
                 { messageId: "useConst", data: { name: "b" }, type: "Identifier" },
                 { messageId: "useConst", data: { name: "c" }, type: "Identifier" }
             ]
+        },
+        {
+            code: [
+                "function a() {",
+                "let foo = 0,",
+                "  bar = 1;",
+                "foo = 1;",
+                "}",
+                "function b() {",
+                "let foo = 0,",
+                "  bar = 2;",
+                "foo = 2;",
+                "}"
+            ].join("\n"),
+            output: null,
+            errors: [
+                { message: "'bar' is never reassigned. Use 'const' instead.", type: "Identifier" },
+                { message: "'bar' is never reassigned. Use 'const' instead.", type: "Identifier" }
+            ]
         }
     ]
 });