diff --git a/eslint/babel-eslint-parser/package.json b/eslint/babel-eslint-parser/package.json index 0205facb646d..b64d7a051af3 100644 --- a/eslint/babel-eslint-parser/package.json +++ b/eslint/babel-eslint-parser/package.json @@ -34,6 +34,7 @@ "@babel/plugin-proposal-nullish-coalescing-operator": "^7.0.0", "@babel/plugin-proposal-optional-chaining": "^7.0.0", "@babel/plugin-proposal-pipeline-operator": "^7.0.0", + "@babel/plugin-proposal-private-methods": "^7.7.4", "@babel/plugin-syntax-bigint": "^7.7.4", "@babel/plugin-syntax-dynamic-import": "^7.0.0", "@babel/plugin-syntax-export-default-from": "^7.0.0", diff --git a/eslint/babel-eslint-parser/src/analyze-scope.js b/eslint/babel-eslint-parser/src/analyze-scope.js index 24a1b5491c12..ffb9eb95ba82 100644 --- a/eslint/babel-eslint-parser/src/analyze-scope.js +++ b/eslint/babel-eslint-parser/src/analyze-scope.js @@ -16,16 +16,16 @@ const flowFlippedAliasKeys = t.FLIPPED_ALIAS_KEYS.Flow.concat([ "ObjectPattern", "RestElement", ]); -const visitorKeysMap = Object.entries(t.VISITOR_KEYS).reduce(function( - acc, - [key, value], -) { - if (flowFlippedAliasKeys.indexOf(value) === -1) { - acc[key] = value; - } - return acc; -}, -{}); + +const visitorKeysMap = Object.entries(t.VISITOR_KEYS).reduce( + (acc, [key, value]) => { + if (!flowFlippedAliasKeys.includes(value)) { + acc[key] = value; + } + return acc; + }, + {}, +); const propertyTypes = { // loops @@ -166,6 +166,11 @@ class Referencer extends OriginalReferencer { this._visitClassProperty(node); } + // TODO: Update to visit type annotations when TypeScript/Flow support this syntax. + ClassPrivateMethod(node) { + super.MethodDefinition(node); + } + DeclareModule(node) { this._visitDeclareX(node); } diff --git a/eslint/babel-eslint-parser/test/babel-eslint-parser.js b/eslint/babel-eslint-parser/test/babel-eslint-parser.js index fb75112dc966..3924875d38d5 100644 --- a/eslint/babel-eslint-parser/test/babel-eslint-parser.js +++ b/eslint/babel-eslint-parser/test/babel-eslint-parser.js @@ -270,7 +270,7 @@ describe("babylon-to-espree", () => { assert.strictEqual(babylonAST.tokens[1].type, "Punctuator"); }); - // Espree doesn't support the private fields yet + // Espree doesn't support private fields yet it("hash (token)", () => { const code = "class A { #x }"; const babylonAST = parseForESLint(code, { diff --git a/eslint/babel-eslint-parser/test/fixtures/config/babel.config.js b/eslint/babel-eslint-parser/test/fixtures/config/babel.config.js index 56a2f07d9707..b84b8d0b3cca 100644 --- a/eslint/babel-eslint-parser/test/fixtures/config/babel.config.js +++ b/eslint/babel-eslint-parser/test/fixtures/config/babel.config.js @@ -18,5 +18,6 @@ module.exports = { ["@babel/plugin-proposal-decorators", { decoratorsBeforeExport: false }], ["@babel/plugin-proposal-pipeline-operator", { proposal: "minimal" }], "@babel/plugin-syntax-bigint", + "@babel/plugin-proposal-private-methods", ], }; diff --git a/eslint/babel-eslint-parser/test/non-regression.js b/eslint/babel-eslint-parser/test/non-regression.js index dca0b489d9ec..418c651d1640 100644 --- a/eslint/babel-eslint-parser/test/non-regression.js +++ b/eslint/babel-eslint-parser/test/non-regression.js @@ -1763,27 +1763,77 @@ describe("verify", () => { ); }); - describe("private class properties", () => { - it("should not be undefined", () => { - verifyAndAssertMessages( - ` - class C { - #d = 1; - } - `, - { "no-undef": 1 }, - ); + describe("class field declarations", () => { + describe("field declarations", () => { + it("should not be undefined", () => { + verifyAndAssertMessages( + ` + class C { + d = 1; + } + `, + { "no-undef": 1 }, + ); + }); + + it("should not be unused", () => { + verifyAndAssertMessages( + ` + export class C { + d = 1; + } + `, + { "no-unused-vars": 1 }, + ); + }); }); - it("should not be unused", () => { - verifyAndAssertMessages( - ` - export class C { - #d = 1; - } - `, - { "no-unused-vars": 1 }, - ); + describe("private field declarations", () => { + it("should not be undefined", () => { + verifyAndAssertMessages( + ` + class C { + #d = 1; + } + `, + { "no-undef": 1 }, + ); + }); + + it("should not be unused", () => { + verifyAndAssertMessages( + ` + export class C { + #d = 1; + } + `, + { "no-unused-vars": 1 }, + ); + }); + }); + + describe("private methods", () => { + it("should not be undefined", () => { + verifyAndAssertMessages( + ` + class C { + #d() {}; + } + `, + { "no-undef": 1 }, + ); + }); + + it("should not be unused", () => { + verifyAndAssertMessages( + ` + export class C { + #d() {}; + } + `, + { "no-unused-vars": 1 }, + ); + }); }); }); @@ -1853,6 +1903,22 @@ describe("verify", () => { ); }); + it("works with classPrivateMethods", () => { + verifyAndAssertMessages( + ` + class A { #a(b, c) {} } + `, + ); + }); + + it("works with arrow function classPrivateProperties", () => { + verifyAndAssertMessages( + ` + class A { #a = (a, b) => {}; } + `, + ); + }); + it("works with optionalCatchBinding", () => { verifyAndAssertMessages( `