Repository: eslint/eslint
Pull request #12452 (2019-10-17 14:56:25)

Fix: report full dot location in dot-location
<!--
    ESLint adheres to the [JS Foundation Code of Conduct](https://js.foundation/community/code-of-conduct).
-->

**What is the purpose of this pull request? (put an "X" next to item)**

[X] Other, please explain:

Fixes `dot-location` to report the full location of the dot token instead of just its start. This can improve highlighting behavior in editors.

For example, [Online Demo](https://eslint.org/demo#eyJ0ZXh0IjoiLyogZXNsaW50IGRvdC1sb2NhdGlvbjogZXJyb3IgKi9cblxuYVxuICAgIC5iO1xuIiwib3B0aW9ucyI6eyJwYXJzZXJPcHRpb25zIjp7ImVjbWFWZXJzaW9uIjo1LCJzb3VyY2VUeXBlIjoic2NyaXB0IiwiZWNtYUZlYXR1cmVzIjp7fX0sInJ1bGVzIjp7fSwiZW52Ijp7fX19) at the moment doesn't highlight anything. 

<!--
    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)**

`dot.loc.start` -> `dot.loc`

**Is there anything you'd like reviewers to focus on?**





Patch:
diff --git a/lib/rules/dot-location.js b/lib/rules/dot-location.js
index c2e734a1a..812988efa 100644
--- a/lib/rules/dot-location.js
+++ b/lib/rules/dot-location.js
@@ -67,7 +67,7 @@ module.exports = {
 
                     context.report({
                         node,
-                        loc: dot.loc.start,
+                        loc: dot.loc,
                         messageId: "expectedDotAfterObject",
                         fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${neededTextAfterToken}.${textBeforeDot}${textAfterDot}`)
                     });
@@ -75,7 +75,7 @@ module.exports = {
             } else if (!astUtils.isTokenOnSameLine(dot, prop)) {
                 context.report({
                     node,
-                    loc: dot.loc.start,
+                    loc: dot.loc,
                     messageId: "expectedDotBeforeProperty",
                     fix: fixer => fixer.replaceTextRange([tokenBeforeDot.range[1], prop.range[0]], `${textBeforeDot}${textAfterDot}.`)
                 });
diff --git a/lib/rules/keyword-spacing.js b/lib/rules/keyword-spacing.js
index ef619aa77..2b3fef33b 100644
--- a/lib/rules/keyword-spacing.js
+++ b/lib/rules/keyword-spacing.js
@@ -86,8 +86,8 @@ module.exports = {
                             retv[key] = {
                                 type: "object",
                                 properties: {
-                                    before: { type: "boolean", default: true },
-                                    after: { type: "boolean", default: true }
+                                    before: { type: "boolean" },
+                                    after: { type: "boolean" }
                                 },
                                 additionalProperties: false
                             };
diff --git a/lib/rules/no-multi-spaces.js b/lib/rules/no-multi-spaces.js
index 64a04c5cc..403d04da9 100644
--- a/lib/rules/no-multi-spaces.js
+++ b/lib/rules/no-multi-spaces.js
@@ -121,7 +121,7 @@ module.exports = {
 
                     context.report({
                         node: rightToken,
-                        loc: rightToken.loc.start,
+                        loc: { start: leftToken.loc.end, end: rightToken.loc.start },
                         message: "Multiple spaces found before '{{displayValue}}'.",
                         data: { displayValue },
                         fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
diff --git a/lib/rules/space-in-parens.js b/lib/rules/space-in-parens.js
index 35ded5e78..85ee74210 100644
--- a/lib/rules/space-in-parens.js
+++ b/lib/rules/space-in-parens.js
@@ -232,7 +232,7 @@ module.exports = {
                     if (token.value === "(" && openerMissingSpace(token, nextToken)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: token.loc,
                             messageId: "missingOpeningSpace",
                             fix(fixer) {
                                 return fixer.insertTextAfter(token, " ");
@@ -244,7 +244,7 @@ module.exports = {
                     if (token.value === "(" && openerRejectsSpace(token, nextToken)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: { start: token.loc.end, end: nextToken.loc.start },
                             messageId: "rejectedOpeningSpace",
                             fix(fixer) {
                                 return fixer.removeRange([token.range[1], nextToken.range[0]]);
@@ -256,7 +256,7 @@ module.exports = {
                     if (token.value === ")" && closerMissingSpace(prevToken, token)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: token.loc,
                             messageId: "missingClosingSpace",
                             fix(fixer) {
                                 return fixer.insertTextBefore(token, " ");
@@ -268,7 +268,7 @@ module.exports = {
                     if (token.value === ")" && closerRejectsSpace(prevToken, token)) {
                         context.report({
                             node,
-                            loc: token.loc.start,
+                            loc: { start: prevToken.loc.end, end: token.loc.start },
                             messageId: "rejectedClosingSpace",
                             fix(fixer) {
                                 return fixer.removeRange([prevToken.range[1], token.range[0]]);
diff --git a/lib/source-code/source-code.js b/lib/source-code/source-code.js
index 450dc24a1..86a56803e 100644
--- a/lib/source-code/source-code.js
+++ b/lib/source-code/source-code.js
@@ -423,7 +423,7 @@ class SourceCode extends TokenStore {
     isSpaceBetweenTokens(first, second) {
         const text = this.text.slice(first.range[1], second.range[0]);
 
-        return /\s/u.test(text.replace(/\/\*.*?\*\//gu, ""));
+        return /\s/u.test(text.replace(/\/\*.*?\*\//gus, ""));
     }
 
     /**


Test patch:
diff --git a/tests/lib/rules/dot-location.js b/tests/lib/rules/dot-location.js
index 3f6caea60..1a6ea37a7 100644
--- a/tests/lib/rules/dot-location.js
+++ b/tests/lib/rules/dot-location.js
@@ -143,13 +143,13 @@ ruleTester.run("dot-location", rule, {
             code: "obj\n.property",
             output: "obj.\nproperty",
             options: ["object"],
-            errors: [{ messageId: "expectedDotAfterObject", type: "MemberExpression", line: 2, column: 1 }]
+            errors: [{ messageId: "expectedDotAfterObject", type: "MemberExpression", line: 2, column: 1, endLine: 2, endColumn: 2 }]
         },
         {
             code: "obj.\nproperty",
             output: "obj\n.property",
             options: ["property"],
-            errors: [{ messageId: "expectedDotBeforeProperty", type: "MemberExpression", line: 1, column: 4 }]
+            errors: [{ messageId: "expectedDotBeforeProperty", type: "MemberExpression", line: 1, column: 4, endLine: 1, endColumn: 5 }]
         },
         {
             code: "(obj).\nproperty",
diff --git a/tests/lib/rules/keyword-spacing.js b/tests/lib/rules/keyword-spacing.js
index 9c0bf8d0a..9971facf1 100644
--- a/tests/lib/rules/keyword-spacing.js
+++ b/tests/lib/rules/keyword-spacing.js
@@ -545,6 +545,8 @@ ruleTester.run("keyword-spacing", rule, {
         { code: "if (a) {}else{}", options: [override("else", NEITHER)] },
         "if (a) {}\nelse\n{}",
         { code: "if(a) {}\nelse\n{}", options: [NEITHER] },
+        { code: "if(a){ }else{ }", options: [{ before: false, after: true, overrides: { else: { after: false }, if: { after: false } } }] },
+        { code: "if(a){ }else{ }", options: [{ before: true, after: false, overrides: { else: { before: false }, if: { before: false } } }] },
 
         // not conflict with `semi-spacing`
         "if (a);else;",
diff --git a/tests/lib/rules/no-multi-spaces.js b/tests/lib/rules/no-multi-spaces.js
index db77ff391..4a8e6034e 100644
--- a/tests/lib/rules/no-multi-spaces.js
+++ b/tests/lib/rules/no-multi-spaces.js
@@ -112,7 +112,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "function foo(a, b) {}",
             errors: [{
                 message: "Multiple spaces found before 'b'.",
-                type: "Identifier"
+                type: "Identifier",
+                column: 16,
+                endColumn: 18
             }]
         },
         {
@@ -121,7 +123,9 @@ ruleTester.run("no-multi-spaces", rule, {
             parserOptions: { ecmaVersion: 6 },
             errors: [{
                 message: "Multiple spaces found before 'b'.",
-                type: "Identifier"
+                type: "Identifier",
+                column: 14,
+                endColumn: 16
             }]
         },
         {
@@ -129,7 +133,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var a = 1",
             errors: [{
                 message: "Multiple spaces found before '1'.",
-                type: "Numeric"
+                type: "Numeric",
+                column: 8,
+                endColumn: 10
             }]
         },
         {
@@ -153,7 +159,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var arr = {'a': 1, 'b': 2};",
             errors: [{
                 message: "Multiple spaces found before ''b''.",
-                type: "String"
+                type: "String",
+                column: 19,
+                endColumn: 21
             }]
         },
         {
@@ -213,16 +221,24 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "[ , 1, , 3, , ]",
             errors: [{
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 2,
+                endColumn: 4
             }, {
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 8,
+                endColumn: 10
             }, {
                 message: "Multiple spaces found before ','.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 14,
+                endColumn: 16
             }, {
                 message: "Multiple spaces found before ']'.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 17,
+                endColumn: 19
             }]
         },
         {
@@ -273,7 +289,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "function foo () {}",
             errors: [{
                 message: "Multiple spaces found before '('.",
-                type: "Punctuator"
+                type: "Punctuator",
+                column: 13,
+                endColumn: 19
             }]
         },
         {
@@ -389,7 +407,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var x = 5;",
             errors: [{
                 message: "Multiple spaces found before '5'.",
-                type: "Numeric"
+                type: "Numeric",
+                column: 8,
+                endColumn: 11
             }]
         },
 
@@ -415,7 +435,9 @@ ruleTester.run("no-multi-spaces", rule, {
             output: "var x = 5; // comment",
             errors: [{
                 message: "Multiple spaces found before '// comment'.",
-                type: "Line"
+                type: "Line",
+                column: 11,
+                endColumn: 13
             }]
         },
         {
@@ -582,7 +604,9 @@ ruleTester.run("no-multi-spaces", rule, {
             options: [{ ignoreEOLComments: false }],
             errors: [{
                 message: "Multiple spaces found before '/*comment...*/'.",
-                type: "Block"
+                type: "Block",
+                column: 11,
+                endColumn: 13
             }]
         },
         {
diff --git a/tests/lib/rules/space-in-parens.js b/tests/lib/rules/space-in-parens.js
index 6f90da52b..a68c6bae7 100644
--- a/tests/lib/rules/space-in-parens.js
+++ b/tests/lib/rules/space-in-parens.js
@@ -128,8 +128,17 @@ ruleTester.run("space-in-parens", rule, {
             output: "bar(baz)",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 10 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 6 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 9, endColumn: 10 }
+            ]
+        },
+        {
+            code: "bar(  baz  )",
+            output: "bar(baz)",
+            options: ["never"],
+            errors: [
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 7 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 10, endColumn: 12 }
             ]
         },
         {
@@ -137,8 +146,17 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 6 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5, endColumn: 6 }
+            ]
+        },
+        {
+            code: "foo(  )",
+            output: "foo()",
+            options: ["never"],
+            errors: [
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5, endColumn: 7 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5, endColumn: 7 }
             ]
         },
         {
@@ -151,7 +169,7 @@ ruleTester.run("space-in-parens", rule, {
             code: "foo\n(\nbar )",
             output: "foo\n(\nbar)",
             options: ["never"],
-            errors: [{ messageId: "rejectedClosingSpace", line: 3, column: 5 }]
+            errors: [{ messageId: "rejectedClosingSpace", line: 3, column: 4 }]
         },
         {
             code: "foo\n(bar\n)\n",
@@ -170,8 +188,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo( bar )",
             options: ["always"],
             errors: [
-                { messageId: "missingOpeningSpace", line: 1, column: 4 },
-                { messageId: "missingClosingSpace", line: 1, column: 8 }
+                { messageId: "missingOpeningSpace", line: 1, column: 4, endColumn: 5 },
+                { messageId: "missingClosingSpace", line: 1, column: 8, endColumn: 9 }
             ]
         },
 
@@ -248,7 +266,7 @@ ruleTester.run("space-in-parens", rule, {
             code: "foo( /* bar */ baz)",
             output: "foo(/* bar */ baz)",
             options: ["never"],
-            errors: [{ messageId: "rejectedOpeningSpace", line: 1, column: 4 }]
+            errors: [{ messageId: "rejectedOpeningSpace", line: 1, column: 5 }]
         },
 
         // exceptions
@@ -266,8 +284,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["always", { exceptions: ["()", "empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5 }
             ]
         },
         {
@@ -275,8 +293,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo()",
             options: ["always", { exceptions: ["empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 6 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 5 }
             ]
         },
         {
@@ -284,7 +302,7 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo( bar())",
             options: ["always", { exceptions: ["()", "empty"] }],
             errors: [
-                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 11 }
             ]
         },
         {
@@ -300,10 +318,10 @@ ruleTester.run("space-in-parens", rule, {
             output: "foo(bar( ))",
             options: ["never", { exceptions: ["empty"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
+                { messageId: "rejectedOpeningSpace", line: 1, column: 5 },
                 { messageId: "missingOpeningSpace", line: 1, column: 9 },
                 { messageId: "missingClosingSpace", line: 1, column: 10 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 11 }
             ]
         },
         {
@@ -312,7 +330,7 @@ ruleTester.run("space-in-parens", rule, {
             options: ["never", { exceptions: ["[]"] }],
             errors: [
                 { messageId: "missingOpeningSpace", line: 1, column: 4 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 18 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 17 }
             ]
         },
         {
@@ -449,8 +467,8 @@ ruleTester.run("space-in-parens", rule, {
             output: "(( 1 + 2 ))",
             options: ["always", { exceptions: ["()"] }],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 1 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 13 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 2 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
             ]
         },
         {
@@ -458,10 +476,10 @@ ruleTester.run("space-in-parens", rule, {
             output: "((1 + 2))",
             options: ["never"],
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 1 },
-                { messageId: "rejectedOpeningSpace", line: 1, column: 3 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 11 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 13 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 2 },
+                { messageId: "rejectedOpeningSpace", line: 1, column: 4 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 10 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 12 }
             ]
         },
         {
@@ -506,7 +524,7 @@ ruleTester.run("space-in-parens", rule, {
             output: "var result = ( 1 / ( 1 + 2 )) + 3",
             options: ["always", { exceptions: ["()"] }],
             errors: [
-                { messageId: "rejectedClosingSpace", line: 1, column: 30 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 29 }
             ]
         },
         {
@@ -524,7 +542,7 @@ ruleTester.run("space-in-parens", rule, {
             errors: [
                 { messageId: "missingOpeningSpace", line: 1, column: 14 },
                 { messageId: "missingClosingSpace", line: 1, column: 26 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 28 }
+                { messageId: "rejectedClosingSpace", line: 1, column: 27 }
             ]
         },
 
@@ -535,8 +553,8 @@ ruleTester.run("space-in-parens", rule, {
             options: ["never"],
             parserOptions: { ecmaVersion: 6 },
             errors: [
-                { messageId: "rejectedOpeningSpace", line: 1, column: 19 },
-                { messageId: "rejectedClosingSpace", line: 1, column: 27 }
+                { messageId: "rejectedOpeningSpace", line: 1, column: 20 },
+                { messageId: "rejectedClosingSpace", line: 1, column: 26 }
             ]
         },
         {
diff --git a/tests/lib/source-code/source-code.js b/tests/lib/source-code/source-code.js
index 57cc960d2..9e8da4844 100644
--- a/tests/lib/source-code/source-code.js
+++ b/tests/lib/source-code/source-code.js
@@ -1796,6 +1796,7 @@ describe("SourceCode", () => {
             ["let  foo = bar;", true],
             ["let /**/ foo = bar;", true],
             ["let/**/foo = bar;", false],
+            ["let/*\n*/foo = bar", false],
             ["a+b", false],
             ["a/**/+b", false],
             ["a/* */+b", false],