diff --git a/lib/rules/block-scoped-var.js b/lib/rules/block-scoped-var.js index 5a951276c59..ec597d5661e 100644 --- a/lib/rules/block-scoped-var.js +++ b/lib/rules/block-scoped-var.js @@ -22,7 +22,7 @@ module.exports = { schema: [], messages: { - outOfScope: "'{{name}}' used outside of binding context." + outOfScope: "'{{name}}' declared on line {{definitionLine}} column {{definitionColumn}} is used outside of binding context." } }, @@ -50,12 +50,22 @@ module.exports = { /** * Reports a given reference. * @param {eslint-scope.Reference} reference A reference to report. + * @param {eslint-scope.Definition} definition A definition for which to report reference. * @returns {void} */ - function report(reference) { + function report(reference, definition) { const identifier = reference.identifier; - - context.report({ node: identifier, messageId: "outOfScope", data: { name: identifier.name } }); + const definitionPosition = definition.name.loc.start; + + context.report({ + node: identifier, + messageId: "outOfScope", + data: { + name: identifier.name, + definitionLine: definitionPosition.line, + definitionColumn: definitionPosition.column + 1 + } + }); } /** @@ -92,7 +102,7 @@ module.exports = { variables[i] .references .filter(isOutsideOfScope) - .forEach(report); + .forEach(ref => report(ref, variables[i].defs.find(def => def.parent === node))); } } diff --git a/tests/lib/rules/block-scoped-var.js b/tests/lib/rules/block-scoped-var.js index f401332b116..175676b3a58 100644 --- a/tests/lib/rules/block-scoped-var.js +++ b/tests/lib/rules/block-scoped-var.js @@ -121,63 +121,345 @@ ruleTester.run("block-scoped-var", rule, { { code: "foo; class C { static {} } var foo; ", parserOptions: { ecmaVersion: 2022 } } ], invalid: [ - { code: "function f(){ x; { var x; } }", errors: [{ messageId: "outOfScope", data: { name: "x" }, type: "Identifier" }] }, - { code: "function f(){ { var x; } x; }", errors: [{ messageId: "outOfScope", data: { name: "x" }, type: "Identifier" }] }, - { code: "function f() { var a; { var b = 0; } a = b; }", errors: [{ messageId: "outOfScope", data: { name: "b" }, type: "Identifier" }] }, - { code: "function f() { try { var a = 0; } catch (e) { var b = a; } }", errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] }, + { + code: "function f(){ x; { var x; } }", + errors: [{ + messageId: "outOfScope", + data: { + name: "x", + definitionLine: 1, + definitionColumn: 24 + }, + line: 1, + column: 15, + type: "Identifier" + }] + }, + { + code: "function f(){ { var x; } x; }", + errors: [{ + messageId: "outOfScope", + data: { + name: "x", + definitionLine: 1, + definitionColumn: 21 + }, + line: 1, + column: 26, + type: "Identifier" + }] + }, + { + code: "function f() { var a; { var b = 0; } a = b; }", + errors: [{ + messageId: "outOfScope", + data: { + name: "b", + definitionLine: 1, + definitionColumn: 29 + }, + line: 1, + column: 42, + type: "Identifier" + }] + }, + { + code: "function f() { try { var a = 0; } catch (e) { var b = a; } }", + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 26 + }, + line: 1, + column: 55, + type: "Identifier" + }] + }, { code: "function a() { for(var b in {}) { var c = b; } c; }", - errors: [{ messageId: "outOfScope", data: { name: "c" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "c", + definitionLine: 1, + definitionColumn: 39 + }, + line: 1, + column: 48, + type: "Identifier" + }] }, { code: "function a() { for(var b of {}) { var c = b; } c; }", parserOptions: { ecmaVersion: 6 }, - errors: [{ messageId: "outOfScope", data: { name: "c" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "c", + definitionLine: 1, + definitionColumn: 39 + }, + line: 1, + column: 48, + type: "Identifier" + }] }, { code: "function f(){ switch(2) { case 1: var b = 2; b; break; default: b; break;} b; }", - errors: [{ messageId: "outOfScope", data: { name: "b" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "b", + definitionLine: 1, + definitionColumn: 39 + }, + line: 1, + column: 76, + type: "Identifier" + }] }, { code: "for (var a = 0;;) {} a;", - errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 10 + }, + line: 1, + column: 22, + type: "Identifier" + }] }, { code: "for (var a in []) {} a;", - errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 10 + }, + line: 1, + column: 22, + type: "Identifier" + }] }, { code: "for (var a of []) {} a;", parserOptions: { ecmaVersion: 6 }, - errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 10 + }, + line: 1, + column: 22, + type: "Identifier" + }] }, { code: "{ var a = 0; } a;", parserOptions: { ecmaVersion: 6, sourceType: "module" }, - errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 7 + }, + line: 1, + column: 16, + type: "Identifier" + }] }, { code: "if (true) { var a; } a;", - errors: [{ messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 17 + }, + line: 1, + column: 22, + type: "Identifier" + }] }, { code: "if (true) { var a = 1; } else { var a = 2; }", errors: [ - { messageId: "outOfScope", data: { name: "a" }, type: "Identifier" }, - { messageId: "outOfScope", data: { name: "a" }, type: "Identifier" } + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 37 + }, + line: 1, + column: 17, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 17 + }, + line: 1, + column: 37, + type: "Identifier" + } ] }, { code: "for (var i = 0;;) {} for(var i = 0;;) {}", errors: [ - { messageId: "outOfScope", data: { name: "i" }, type: "Identifier" }, - { messageId: "outOfScope", data: { name: "i" }, type: "Identifier" } + { + messageId: "outOfScope", + data: { + name: "i", + definitionLine: 1, + definitionColumn: 30 + }, + line: 1, + column: 10, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "i", + definitionLine: 1, + definitionColumn: 10 + }, + line: 1, + column: 30, + type: "Identifier" + } ] }, { code: "class C { static { if (bar) { var foo; } foo; } }", parserOptions: { ecmaVersion: 2022 }, - errors: [{ messageId: "outOfScope", data: { name: "foo" }, type: "Identifier" }] + errors: [{ + messageId: "outOfScope", + data: { + name: "foo", + definitionLine: 1, + definitionColumn: 35 + }, + line: 1, + column: 42, + type: "Identifier" + }] + }, + { + code: "{ var foo,\n bar; } bar;", + errors: [{ + messageId: "outOfScope", + data: { + name: "bar", + definitionLine: 2, + definitionColumn: 3 + }, + line: 2, + column: 10, + type: "Identifier" + }] + }, + { + code: "{ var { foo,\n bar } = baz; } bar;", + parserOptions: { ecmaVersion: 6 }, + errors: [{ + messageId: "outOfScope", + data: { + name: "bar", + definitionLine: 2, + definitionColumn: 3 + }, + line: 2, + column: 18, + type: "Identifier" + }] + }, + { + code: "if (foo) { var a = 1; } else if (bar) { var a = 2; } else { var a = 3; }", + errors: [ + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 45 + }, + line: 1, + column: 16, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 65 + }, + line: 1, + column: 16, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 16 + }, + line: 1, + column: 45, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 65 + }, + line: 1, + column: 45, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 16 + }, + line: 1, + column: 65, + type: "Identifier" + }, + { + messageId: "outOfScope", + data: { + name: "a", + definitionLine: 1, + definitionColumn: 45 + }, + line: 1, + column: 65, + type: "Identifier" + } + ] } ] });