diff --git a/eslint/babel-eslint-parser/src/configuration.js b/eslint/babel-eslint-parser/src/configuration.js index cffab4f884ab..cef371cf526b 100644 --- a/eslint/babel-eslint-parser/src/configuration.js +++ b/eslint/babel-eslint-parser/src/configuration.js @@ -21,6 +21,26 @@ export function normalizeESLintConfig(options) { }; } +/** + * Merge user supplied estree plugin options to default estree plugin options + * + * @param {*} babelOptions + * @returns {Array} Merged parser plugin descriptors + */ +function getParserPlugins(babelOptions) { + const babelParserPlugins = babelOptions.parserOpts?.plugins ?? []; + // todo: enable classFeatures when it is supported by ESLint + const estreeOptions = { classFeatures: false }; + for (const plugin of babelParserPlugins) { + if (Array.isArray(plugin) && plugin[0] === "estree") { + Object.assign(estreeOptions, plugin[1]); + break; + } + } + // estree must be the first parser plugin to work with other parser plugins + return [["estree", estreeOptions], ...babelParserPlugins]; +} + export function normalizeBabelParseConfig(options) { const parseOptions = { sourceType: options.sourceType, @@ -31,10 +51,7 @@ export function normalizeBabelParseConfig(options) { allowReturnOutsideFunction: true, allowSuperOutsideMethod: true, ...options.babelOptions.parserOpts, - plugins: [ - ["estree", { classFeatures: false }], - ...(options.babelOptions.parserOpts?.plugins ?? []), - ], + plugins: getParserPlugins(options.babelOptions), ranges: true, tokens: true, }, diff --git a/eslint/babel-eslint-parser/test/index.js b/eslint/babel-eslint-parser/test/index.js index 60868edf3003..350e17ea2e58 100644 --- a/eslint/babel-eslint-parser/test/index.js +++ b/eslint/babel-eslint-parser/test/index.js @@ -327,6 +327,26 @@ describe("Babel and Espree", () => { expect(babylonAST.tokens[3].value).toEqual("#"); }); + it("parse to PropertyDeclaration when `classFeatures: true`", () => { + const code = "class A { #x }"; + const babylonAST = parseForESLint(code, { + eslintVisitorKeys: true, + eslintScopeManager: true, + babelOptions: { + filename: "test.js", + parserOpts: { + plugins: [ + ["estree", { classFeatures: true }], + "classPrivateProperties", + "classProperties", + ], + }, + }, + }).ast; + const classDeclaration = babylonAST.body[0]; + expect(classDeclaration.body.body[0].type).toEqual("PropertyDefinition"); + }); + it("empty program with line comment", () => { parseAndAssertSame("// single comment"); });