diff --git a/changelog_unreleased/api/pr-8390.md b/changelog_unreleased/api/pr-8390.md new file mode 100644 index 000000000..fead47a13 --- /dev/null +++ b/changelog_unreleased/api/pr-8390.md @@ -0,0 +1,16 @@ +#### Add plugins' parsers to the `parser` option ([#8390](https://github.com/prettier/prettier/pull/8390) by [@thorn0](https://github.com/thorn0)) + +When a plugin defines a language, the parsers specified for this language are now automatically added to the list of valid values of the `parser` option. +This might be useful for editor integrations or other applications that need a list of available parsers. + +```console +> yarn add prettier @prettier/plugin-php +``` + +```js +const hasPhpParser = prettier + .getSupportInfo() + .options.find((option) => option.name === "parser") + .choices.map((choice) => choice.value) + .includes("php"); // false in Prettier stable, true in Prettier master +``` diff --git a/src/main/support.js b/src/main/support.js index f1d0e54d2..8bff0cf03 100644 --- a/src/main/support.js +++ b/src/main/support.js @@ -29,6 +29,10 @@ function getSupportInfo({ // we need to treat it as the normal one so as to test new features. const version = currentVersion.split("-", 1)[0]; + const languages = plugins + .reduce((all, plugin) => all.concat(plugin.languages || []), []) + .filter(filterSince); + const options = arrayify( Object.assign({}, ...plugins.map(({ options }) => options), coreOptions), "name" @@ -54,26 +58,26 @@ function getSupportInfo({ option.choices = option.choices.filter( (option) => filterSince(option) && filterDeprecated(option) ); + + if (option.name === "parser") { + collectParsersFromLanguages(option, languages, plugins); + } } - const filteredPlugins = plugins.filter( - (plugin) => - plugin.defaultOptions && - plugin.defaultOptions[option.name] !== undefined - ); - - const pluginDefaults = filteredPlugins.reduce((reduced, plugin) => { - reduced[plugin.name] = plugin.defaultOptions[option.name]; - return reduced; - }, {}); + const pluginDefaults = plugins + .filter( + (plugin) => + plugin.defaultOptions && + plugin.defaultOptions[option.name] !== undefined + ) + .reduce((reduced, plugin) => { + reduced[plugin.name] = plugin.defaultOptions[option.name]; + return reduced; + }, {}); return { ...option, pluginDefaults }; }); - const languages = plugins - .reduce((all, plugin) => all.concat(plugin.languages || []), []) - .filter(filterSince); - return { languages, options }; function filterSince(object) { @@ -101,6 +105,27 @@ function getSupportInfo({ } } +function collectParsersFromLanguages(option, languages, plugins) { + const existingValues = new Set(option.choices.map((choice) => choice.value)); + for (const language of languages) { + if (language.parsers) { + for (const value of language.parsers) { + if (!existingValues.has(value)) { + existingValues.add(value); + const plugin = plugins.find( + (plugin) => plugin.parsers && plugin.parsers[value] + ); + let description = language.name; + if (plugin && plugin.name) { + description += ` (plugin: ${plugin.name})`; + } + option.choices.push({ value, description }); + } + } + } + } +} + module.exports = { getSupportInfo, }; diff --git a/tests_integration/__tests__/__snapshots__/plugin-options-string.js.snap b/tests_integration/__tests__/__snapshots__/plugin-options-string.js.snap index cf0d60aa1..656238849 100644 --- a/tests_integration/__tests__/__snapshots__/plugin-options-string.js.snap +++ b/tests_integration/__tests__/__snapshots__/plugin-options-string.js.snap @@ -5,7 +5,7 @@ exports[` 1`] = ` - First value + Second value -@@ -20,10 +20,12 @@ +@@ -20,18 +20,20 @@ Control how Prettier formats quoted code embedded in the file. Defaults to auto. --end-of-line @@ -17,7 +17,16 @@ exports[` 1`] = ` How to handle whitespaces in HTML. Defaults to css. --jsx-bracket-same-line Put > on the last line instead of at a new line. - Defaults to false." + Defaults to false. + --jsx-single-quote Use single quotes in JSX. + Defaults to false. +- --parser ++ --parser + Which parser to use. + --print-width The line length where Prettier will try wrap. + Defaults to 80. + --prose-wrap + How to wrap prose." `; exports[`show detailed external option with \`--help foo-string\` (stderr) 1`] = `""`; diff --git a/tests_integration/__tests__/__snapshots__/plugin-options.js.snap b/tests_integration/__tests__/__snapshots__/plugin-options.js.snap index 9176e067a..4160962f1 100644 --- a/tests_integration/__tests__/__snapshots__/plugin-options.js.snap +++ b/tests_integration/__tests__/__snapshots__/plugin-options.js.snap @@ -5,7 +5,7 @@ exports[` 1`] = ` - First value + Second value -@@ -20,10 +20,12 @@ +@@ -20,18 +20,20 @@ Control how Prettier formats quoted code embedded in the file. Defaults to auto. --end-of-line @@ -17,9 +17,52 @@ exports[` 1`] = ` How to handle whitespaces in HTML. Defaults to css. --jsx-bracket-same-line Put > on the last line instead of at a new line. - Defaults to false." + Defaults to false. + --jsx-single-quote Use single quotes in JSX. + Defaults to false. +- --parser ++ --parser + Which parser to use. + --print-width The line length where Prettier will try wrap. + Defaults to 80. + --prose-wrap + How to wrap prose." `; +exports[`include plugin's parsers to the values of the \`parser\` option\` (stderr) 1`] = `""`; + +exports[`include plugin's parsers to the values of the \`parser\` option\` (stdout) 1`] = ` +"--parser + + Which parser to use. + +Valid options: + + flow Flow + babel JavaScript + babel-flow Flow + babel-ts TypeScript + typescript TypeScript + css CSS + less Less + scss SCSS + json JSON + json5 JSON5 + json-stringify JSON.stringify + graphql GraphQL + markdown Markdown + mdx MDX + vue Vue + yaml YAML + html HTML + angular Angular + lwc Lightning Web Components + foo-parser foo (plugin: ./plugin) +" +`; + +exports[`include plugin's parsers to the values of the \`parser\` option\` (write) 1`] = `Array []`; + exports[`show detailed external option with \`--help foo-option\` (stderr) 1`] = `""`; exports[`show detailed external option with \`--help foo-option\` (stdout) 1`] = ` diff --git a/tests_integration/__tests__/plugin-options.js b/tests_integration/__tests__/plugin-options.js index bb6ddfe9c..1d47987c2 100644 --- a/tests_integration/__tests__/plugin-options.js +++ b/tests_integration/__tests__/plugin-options.js @@ -22,6 +22,16 @@ describe("show detailed external option with `--help foo-option`", () => { }); }); +describe("include plugin's parsers to the values of the `parser` option`", () => { + runPrettier("plugins/options", [ + "--plugin=./plugin", + "--help", + "parser", + ]).test({ + status: 0, + }); +}); + describe("external options from CLI should work", () => { runPrettier( "plugins/options",