diff --git a/changelog_unreleased/api/13268.md b/changelog_unreleased/api/13268.md index 29ea1d14b..64c94612d 100644 --- a/changelog_unreleased/api/13268.md +++ b/changelog_unreleased/api/13268.md @@ -14,7 +14,7 @@ function parse(text: string, options: object): Promise | AST; The second argument `parsers` has been removed, if you still need other parser during parse process, you can: -1. Import the plugin yourself +1. Import the plugin yourself (recommended) ```js import pluginBabel from "prettier/plugins/babel"; @@ -37,8 +37,8 @@ The second argument `parsers` has been removed, if you still need other parser d ```js function getParserFromOptions(options, parserName) { - const parserOrParserInitFunction = options.plugins.find((plugin) => - Object.hasOwn(plugin.parsers, parserName) + const parserOrParserInitFunction = options.plugins.find( + (plugin) => plugin.parsers && Object.hasOwn(plugin.parsers, parserName) )?.parsers[parserName]; return typeof parserOrParserInitFunction === "function" ? parserOrParserInitFunction() diff --git a/package.json b/package.json index a8f94ce4a..1305d5e86 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,7 @@ "flow-parser": "0.204.0", "get-stdin": "9.0.0", "graphql": "16.6.0", - "hermes-eslint": "0.10.1", + "hermes-parser": "0.10.1", "html-element-attributes": "3.2.0", "html-styles": "1.0.0", "html-tag-names": "2.1.0", diff --git a/scripts/benchmark/bench.js b/scripts/benchmark/bench.js index 6b600d6b9..62b3e8f3f 100644 --- a/scripts/benchmark/bench.js +++ b/scripts/benchmark/bench.js @@ -4,7 +4,7 @@ const [, , version, method, groupCountString = 100, groupSizeString = 10] = process.argv; const groupCount = Number(groupCountString); const groupSize = Number(groupSizeString); -const { format } = await import(`./${version}/dist/index.js`); +const { format } = await import(`./${version}/dist/index.mjs`); const sourceText = readFileSync( process.env.PRETTIER_PERF_FILENAME || "../../src/language-js/utils/index.js", diff --git a/src/index.d.ts b/src/index.d.ts index 058839972..c459048e4 100644 --- a/src/index.d.ts +++ b/src/index.d.ts @@ -449,9 +449,7 @@ export interface ParserOptions extends RequiredOptions { export interface Plugin { languages?: SupportLanguage[] | undefined; - parsers?: - | { [parserName: string]: Parser | (() => Promise>) } - | undefined; + parsers?: { [parserName: string]: Parser } | undefined; printers?: { [astFormat: string]: Printer } | undefined; options?: SupportOptions | undefined; defaultOptions?: Partial | undefined; diff --git a/src/language-css/index.js b/src/language-css/index.js index 75a42ae38..45136ffec 100644 --- a/src/language-css/index.js +++ b/src/language-css/index.js @@ -1,17 +1,8 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-postcss.js"; export const printers = { postcss: printer, }; -export const parsers = createParsers( - // TODO: switch these to just `postcss` and use `language` instead. - [ - { - importParsers: () => import("./parser-postcss.js"), - parserNames: ["css", "less", "scss"], - }, - ] -); +export * as parsers from "./parser-postcss.js"; export { default as languages } from "./languages.evaluate.js"; export { default as options } from "./options.js"; diff --git a/src/language-graphql/index.js b/src/language-graphql/index.js index de7b6379a..47acfd323 100644 --- a/src/language-graphql/index.js +++ b/src/language-graphql/index.js @@ -1,14 +1,8 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-graphql.js"; export const printers = { graphql: printer, }; -export const parsers = createParsers([ - { - importParsers: () => import("./parser-graphql.js"), - parserNames: ["graphql"], - }, -]); +export * as parsers from "./parser-graphql.js"; export { default as languages } from "./languages.evaluate.js"; export { default as options } from "./options.js"; diff --git a/src/language-handlebars/index.js b/src/language-handlebars/index.js index daafefe10..201380172 100644 --- a/src/language-handlebars/index.js +++ b/src/language-handlebars/index.js @@ -1,13 +1,7 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-glimmer.js"; export const printers = { glimmer: printer, }; -export const parsers = createParsers([ - { - importParsers: () => import("./parser-glimmer.js"), - parserNames: ["glimmer"], - }, -]); +export * as parsers from "./parser-glimmer.js"; export { default as languages } from "./languages.evaluate.js"; diff --git a/src/language-html/index.js b/src/language-html/index.js index a76a25a9e..62b714a10 100644 --- a/src/language-html/index.js +++ b/src/language-html/index.js @@ -1,14 +1,8 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-html.js"; export const printers = { html: printer, }; -export const parsers = createParsers([ - { - importParsers: () => import("./parser-html.js"), - parserNames: ["html", "vue", "angular", "lwc"], - }, -]); +export * as parsers from "./parser-html.js"; export { default as languages } from "./languages.evaluate.js"; export { default as options } from "./options.js"; diff --git a/src/language-js/traverse/visitor-keys.evaluate.js b/src/language-js/traverse/visitor-keys.evaluate.js index 820f1e693..3ef3a9034 100644 --- a/src/language-js/traverse/visitor-keys.evaluate.js +++ b/src/language-js/traverse/visitor-keys.evaluate.js @@ -1,6 +1,6 @@ import { VISITOR_KEYS as babelVisitorKeys } from "@babel/types"; import { visitorKeys as tsVisitorKeys } from "@typescript-eslint/visitor-keys"; -import { VisitorKeys as flowVisitorKeys } from "hermes-eslint"; +import flowVisitorKeys from "hermes-parser/dist/generated/ESTreeVisitorKeys.js"; import unionVisitorKeys from "./union-visitor-keys.js"; const angularVisitorKeys = { diff --git a/src/language-markdown/index.js b/src/language-markdown/index.js index cf1492d0a..0e513c036 100644 --- a/src/language-markdown/index.js +++ b/src/language-markdown/index.js @@ -1,14 +1,8 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-markdown.js"; export const printers = { mdast: printer, }; -export const parsers = createParsers([ - { - importParsers: () => import("./parser-markdown.js"), - parserNames: ["remark", "markdown", "mdx"], - }, -]); +export * as parsers from "./parser-markdown.js"; export { default as languages } from "./languages.evaluate.js"; export { default as options } from "./options.js"; diff --git a/src/language-yaml/index.js b/src/language-yaml/index.js index 6f96ee690..d298a799b 100644 --- a/src/language-yaml/index.js +++ b/src/language-yaml/index.js @@ -1,14 +1,8 @@ -import createParsers from "../utils/create-parsers.js"; import printer from "./printer-yaml.js"; export const printers = { yaml: printer, }; -export const parsers = createParsers([ - { - importParsers: () => import("./parser-yaml.js"), - parserNames: ["yaml"], - }, -]); +export * as parsers from "./parser-yaml.js"; export { default as languages } from "./languages.evaluate.js"; export { default as options } from "./options.js"; diff --git a/src/main/normalize-format-options.js b/src/main/normalize-format-options.js index d64e7bb31..94ee6a433 100644 --- a/src/main/normalize-format-options.js +++ b/src/main/normalize-format-options.js @@ -6,6 +6,7 @@ import { getParserPluginByParserName, getPrinterPluginByAstFormat, initParser, + initPrinter, } from "./parser-and-printer.js"; const formatOptionsHiddenDefaults = { @@ -64,7 +65,7 @@ async function normalizeFormatOptions(options, opts = {}) { const printerPlugin = parserPlugin.printers?.[parser.astFormat] ? parserPlugin : getPrinterPluginByAstFormat(rawOptions.plugins, parser.astFormat); - const printer = printerPlugin.printers[parser.astFormat]; + const printer = await initPrinter(printerPlugin, parser.astFormat); rawOptions.printer = printer; diff --git a/src/main/parser-and-printer.js b/src/main/parser-and-printer.js index f0ee98c21..01c70bbc6 100644 --- a/src/main/parser-and-printer.js +++ b/src/main/parser-and-printer.js @@ -68,9 +68,17 @@ function initParser(plugin, parserName) { : parserOrParserInitFunction; } +function initPrinter(plugin, astFormat) { + const printerOrPrinterInitFunction = plugin.printers[astFormat]; + return typeof printerOrPrinterInitFunction === "function" + ? printerOrPrinterInitFunction() + : printerOrPrinterInitFunction; +} + export { getParserPluginByParserName, getPrinterPluginByAstFormat, - initParser, resolveParser, + initParser, + initPrinter, }; diff --git a/src/main/plugins/load-builtin-plugins.js b/src/main/plugins/load-builtin-plugins.js index 79f778fee..43b924f33 100644 --- a/src/main/plugins/load-builtin-plugins.js +++ b/src/main/plugins/load-builtin-plugins.js @@ -1,23 +1,7 @@ -let builtinPlugins; +import * as builtinPluginsProxy from "../../plugins/builtin-plugins-proxy.js"; -async function loadBuiltinPlugins() { - builtinPlugins ??= await Promise.all([ - import("../../plugins/estree.js"), - import("../../plugins/babel.js"), - import("../../plugins/flow.js"), - import("../../plugins/typescript.js"), - import("../../plugins/acorn.js"), - import("../../plugins/meriyah.js"), - import("../../plugins/angular.js"), - import("../../plugins/postcss.js"), - import("../../plugins/graphql.js"), - import("../../plugins/markdown.js"), - import("../../plugins/glimmer.js"), - import("../../plugins/html.js"), - import("../../plugins/yaml.js"), - ]); - - return builtinPlugins; +function loadBuiltinPlugins() { + return [builtinPluginsProxy]; } export default loadBuiltinPlugins; diff --git a/src/plugins/acorn.js b/src/plugins/acorn.js index 9dbab7295..fff470190 100644 --- a/src/plugins/acorn.js +++ b/src/plugins/acorn.js @@ -1,13 +1,5 @@ -import createParsers from "../utils/create-parsers.js"; +import { acorn } from "../language-js/parse/acorn.js"; +import { espree } from "../language-js/parse/espree.js"; -export const parsers = createParsers([ - { - importParsers: () => import("../language-js/parse/acorn.js"), - parserNames: ["acorn"], - }, - { - importParsers: () => import("../language-js/parse/espree.js"), - parserNames: ["espree"], - }, -]); +export const parsers = { acorn, espree }; export default { parsers }; diff --git a/src/plugins/angular.js b/src/plugins/angular.js index d71875b8d..17e250188 100644 --- a/src/plugins/angular.js +++ b/src/plugins/angular.js @@ -1,14 +1,4 @@ -import createParsers from "../utils/create-parsers.js"; +import * as parsers from "../language-js/parse/angular.js"; -export const parsers = createParsers([ - { - importParsers: () => import("../language-js/parse/angular.js"), - parserNames: [ - "__ng_action", - "__ng_binding", - "__ng_interpolation", - "__ng_directive", - ], - }, -]); +export { parsers }; export default { parsers }; diff --git a/src/plugins/babel.js b/src/plugins/babel.js index 10d5b429e..6bc1571a4 100644 --- a/src/plugins/babel.js +++ b/src/plugins/babel.js @@ -1,27 +1,6 @@ -import createParsers from "../utils/create-parsers.js"; +import babelParsers from "../language-js/parse/babel.js"; +// JSON parsers are based on babel, bundle together to reduce package size +import jsonParsers from "../language-json/parser-json.js"; -export const parsers = createParsers([ - { - importParsers: async () => - (await import("../language-js/parse/babel.js")).default, - parserNames: [ - "babel", - "babel-flow", - "babel-ts", - "__js_expression", - "__ts_expression", - "__vue_expression", - "__vue_ts_expression", - "__vue_event_binding", - "__vue_ts_event_binding", - "__babel_estree", - ], - }, - // JSON parsers are based on babel, bundle together to reduce package size - { - importParsers: async () => - (await import("../language-json/parser-json.js")).default, - parserNames: ["json", "json5", "json-stringify"], - }, -]); +export const parsers = { ...babelParsers, ...jsonParsers }; export default { parsers }; diff --git a/src/plugins/builtin-plugins-proxy.js b/src/plugins/builtin-plugins-proxy.js new file mode 100644 index 000000000..af3147fde --- /dev/null +++ b/src/plugins/builtin-plugins-proxy.js @@ -0,0 +1,152 @@ +import cssOptions from "../language-css/options.js"; +import cssLanguages from "../language-css/languages.evaluate.js"; + +import graphqlOptions from "../language-graphql/options.js"; +import graphqlLanguages from "../language-graphql/languages.evaluate.js"; + +import handlebarsLanguages from "../language-handlebars/languages.evaluate.js"; + +import htmlOptions from "../language-html/options.js"; +import htmlLanguages from "../language-html/languages.evaluate.js"; + +import jsOptions from "../language-js/options.js"; +import jsLanguages from "../language-js/languages.evaluate.js"; + +import jsonLanguages from "../language-json/languages.evaluate.js"; + +import markdownOptions from "../language-markdown/options.js"; +import markdownLanguages from "../language-markdown/languages.evaluate.js"; + +import yamlOptions from "../language-yaml/options.js"; +import yamlLanguages from "../language-yaml/languages.evaluate.js"; + +function createParsersAndParsers(modules) { + const parsers = Object.create(null); + const printers = Object.create(null); + + for (const { + importPlugin, + parsers: parserNames = [], + printers: printerNames = [], + } of modules) { + const loadPlugin = async () => { + const plugin = await importPlugin(); + Object.assign(parsers, plugin.parsers); + Object.assign(printers, plugin.printers); + return plugin; + }; + + for (const parserName of parserNames) { + parsers[parserName] = async () => + (await loadPlugin()).parsers[parserName]; + } + + for (const printerName of printerNames) { + printers[printerName] = async () => + (await loadPlugin()).printers[printerName]; + } + } + + return { parsers, printers }; +} + +export const options = { + ...cssOptions, + ...graphqlOptions, + ...htmlOptions, + ...jsOptions, + ...markdownOptions, + ...yamlOptions, +}; + +export const languages = [ + ...cssLanguages, + ...graphqlLanguages, + ...handlebarsLanguages, + ...htmlLanguages, + ...jsLanguages, + ...jsonLanguages, + ...markdownLanguages, + ...yamlLanguages, +]; + +// Lazy load the plugins +export const { parsers, printers } = createParsersAndParsers([ + { + importPlugin: () => import("./acorn.js"), + parsers: ["acorn", "espree"], + }, + { + importPlugin: () => import("./angular.js"), + parsers: [ + "__ng_action", + "__ng_binding", + "__ng_interpolation", + "__ng_directive", + ], + }, + { + importPlugin: () => import("./babel.js"), + parsers: [ + "babel", + "babel-flow", + "babel-ts", + "__js_expression", + "__ts_expression", + "__vue_expression", + "__vue_ts_expression", + "__vue_event_binding", + "__vue_ts_event_binding", + "__babel_estree", + "json", + "json5", + "json-stringify", + ], + }, + { + importPlugin: () => import("./estree.js"), + printers: ["estree", "estree-json"], + }, + { + importPlugin: () => import("./flow.js"), + parsers: ["flow"], + }, + { + importPlugin: () => import("./glimmer.js"), + parsers: ["glimmer"], + printers: ["glimmer"], + }, + { + importPlugin: () => import("./graphql.js"), + parsers: ["graphql"], + printers: ["graphql"], + }, + { + importPlugin: () => import("./html.js"), + parsers: ["html", "angular", "vue", "lwc"], + printers: ["html"], + }, + { + importPlugin: () => import("./markdown.js"), + parsers: ["markdown", "mdx", "remark"], + printers: ["mdast"], + }, + { + importPlugin: () => import("./meriyah.js"), + parsers: ["meriyah"], + }, + { + importPlugin: () => import("./postcss.js"), + parsers: ["css", "less", "scss"], + printers: ["postcss"], + }, + { + importPlugin: () => import("./typescript.js"), + parsers: ["typescript"], + }, + { + importPlugin: () => import("./yaml.js"), + parsers: ["yaml"], + printers: ["yaml"], + }, +]); diff --git a/src/plugins/flow.js b/src/plugins/flow.js index 6de6b1a1d..cdc6099f8 100644 --- a/src/plugins/flow.js +++ b/src/plugins/flow.js @@ -1,9 +1,4 @@ -import createParsers from "../utils/create-parsers.js"; +import * as parsers from "../language-js/parse/flow.js"; -export const parsers = createParsers([ - { - importParsers: () => import("../language-js/parse/flow.js"), - parserNames: ["flow"], - }, -]); +export { parsers }; export default { parsers }; diff --git a/src/plugins/meriyah.js b/src/plugins/meriyah.js index 1d054a8d0..b46568fbc 100644 --- a/src/plugins/meriyah.js +++ b/src/plugins/meriyah.js @@ -1,9 +1,4 @@ -import createParsers from "../utils/create-parsers.js"; +import * as parsers from "../language-js/parse/meriyah.js"; -export const parsers = createParsers([ - { - importParsers: () => import("../language-js/parse/meriyah.js"), - parserNames: ["meriyah"], - }, -]); +export { parsers }; export default { parsers }; diff --git a/src/plugins/typescript.js b/src/plugins/typescript.js index 6180a7e2a..0876cb729 100644 --- a/src/plugins/typescript.js +++ b/src/plugins/typescript.js @@ -1,9 +1,4 @@ -import createParsers from "../utils/create-parsers.js"; +import * as parsers from "../language-js/parse/typescript.js"; -export const parsers = createParsers([ - { - importParsers: () => import("../language-js/parse/typescript.js"), - parserNames: ["typescript"], - }, -]); +export { parsers }; export default { parsers }; diff --git a/src/utils/create-parsers.js b/src/utils/create-parsers.js deleted file mode 100644 index fad8d484a..000000000 --- a/src/utils/create-parsers.js +++ /dev/null @@ -1,14 +0,0 @@ -function createParsers(modules) { - const parsers = Object.create(null); - - for (const { importParsers, parserNames } of modules) { - for (const parserName of parserNames) { - parsers[parserName] = async () => - Object.assign(parsers, await importParsers())[parserName]; - } - } - - return parsers; -} - -export default createParsers; diff --git a/yarn.lock b/yarn.lock index d164e9463..3c8e22a94 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4354,17 +4354,6 @@ __metadata: languageName: node linkType: hard -"hermes-eslint@npm:0.10.1": - version: 0.10.1 - resolution: "hermes-eslint@npm:0.10.1" - dependencies: - esrecurse: ^4.3.0 - hermes-estree: 0.10.1 - hermes-parser: 0.10.1 - checksum: e22b3937e53e4b605fa964ec7576dcd242787a4599ee749ccdb05569950cfd4d36962a80291c927d5fd6c662ad9b0657b580a04a45b10246cfd0349469083eb7 - languageName: node - linkType: hard - "hermes-estree@npm:0.10.1": version: 0.10.1 resolution: "hermes-estree@npm:0.10.1" @@ -6776,7 +6765,7 @@ __metadata: flow-parser: 0.204.0 get-stdin: 9.0.0 graphql: 16.6.0 - hermes-eslint: 0.10.1 + hermes-parser: 0.10.1 html-element-attributes: 3.2.0 html-styles: 1.0.0 html-tag-names: 2.1.0