From cc734753fc8dd43afdf128d08bf6c2a5fbb4fd69 Mon Sep 17 00:00:00 2001 From: Alexander Kachkaev Date: Wed, 9 May 2018 17:53:44 +0100 Subject: [PATCH] Implement prettier.getFileInfo() method and --file-info CLI option (#4341) * Implement prettier.getFileInfo() method and --file-info CLI option * Add empty line between functions in index.js * Support --plugin-search-dirs / pluginSearchDirs() in --file-info / getFileInfo() * Address review comments by @ikatyang --- docs/api.md | 17 ++ index.js | 12 +- src/cli/constant.js | 8 + src/cli/index.js | 12 +- src/cli/util.js | 53 ++-- src/common/create-ignorer.js | 30 +++ src/common/get-file-info.js | 40 +++ src/main/options.js | 4 +- .../__snapshots__/early-exit.js.snap | 28 +++ .../__tests__/__snapshots__/file-info.js.snap | 121 +++++++++ tests_integration/__tests__/early-exit.js | 6 + tests_integration/__tests__/file-info.js | 231 ++++++++++++++++++ .../@prettier/plugin-foo/index.js | 3 +- 13 files changed, 538 insertions(+), 27 deletions(-) create mode 100644 src/common/create-ignorer.js create mode 100644 src/common/get-file-info.js create mode 100644 tests_integration/__tests__/__snapshots__/file-info.js.snap create mode 100644 tests_integration/__tests__/file-info.js diff --git a/docs/api.md b/docs/api.md index 6329d739..b8bafe55 100644 --- a/docs/api.md +++ b/docs/api.md @@ -72,6 +72,23 @@ If `options.useCache` is `false`, all caching will be bypassed. As you repeatedly call `resolveConfig`, the file system structure will be cached for performance. This function will clear the cache. Generally this is only needed for editor integrations that know that the file system has changed since the last format took place. +## `prettier.getFileInfo(filePath [, options])` + +`getFileInfo` can be used by editor extensions to decide if a particular file needs to be formatted. This method returns a promise, which resolves to an object with the following properties: + +```typescript +{ + ignored: boolean, + inferredParser: string | null, +} +``` + +Setting `options.ignorePath` (`string`) and `options.withNodeModules` (`boolean`) influence the value of `ignored` (`false` by default). + +Providing [plugin](./plugins.md) paths in `options.plugins` (`string[]`) helps extract `inferredParser` for files that are not supported by Prettier core. + +Use `prettier.getFileInfo.sync(filePath [, options])` if you'd like to use sync version. + ## `prettier.getSupportInfo([version])` Returns an object representing the parsers, languages and file types Prettier supports. diff --git a/index.js b/index.js index 736146e4..a7c361d0 100644 --- a/index.js +++ b/index.js @@ -4,6 +4,7 @@ const version = require("./package.json").version; const core = require("./src/main/core"); const getSupportInfo = require("./src/main/support").getSupportInfo; +const getFileInfo = require("./src/common/get-file-info"); const sharedUtil = require("./src/common/util-shared"); const loadPlugins = require("./src/common/load-plugins"); @@ -12,7 +13,7 @@ const config = require("./src/config/resolve-config"); const doc = require("./src/doc"); // Luckily `opts` is always the 2nd argument -function withPlugins(fn) { +function _withPlugins(fn) { return function() { const args = Array.from(arguments); const opts = args[1] || {}; @@ -23,6 +24,14 @@ function withPlugins(fn) { }; } +function withPlugins(fn) { + const resultingFn = _withPlugins(fn); + if (fn.sync) { + resultingFn.sync = _withPlugins(fn.sync); + } + return resultingFn; +} + const formatWithCursor = withPlugins(core.formatWithCursor); module.exports = { @@ -47,6 +56,7 @@ module.exports = { resolveConfigFile: config.resolveConfigFile, clearConfigCache: config.clearCache, + getFileInfo: withPlugins(getFileInfo), getSupportInfo: withPlugins(getSupportInfo), version, diff --git a/src/cli/constant.js b/src/cli/constant.js index aafb8f6c..43867335 100644 --- a/src/cli/constant.js +++ b/src/cli/constant.js @@ -131,6 +131,14 @@ const options = { description: "Find and print the path to a configuration file for the given input file." }, + "file-info": { + type: "path", + description: dedent` + Extract the following info (as JSON) for a given file path. Reported fields: + * ignored (boolean) - true if file path is filtered by --ignore-path + * inferredParser (string | null) - name of parser inferred from file path + ` + }, help: { type: "flag", alias: "h", diff --git a/src/cli/index.js b/src/cli/index.js index 2ab8ac5d..7edb6062 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -22,6 +22,11 @@ function run(args) { process.exit(1); } + if (context.argv["file-info"] && context.filePatterns.length) { + context.logger.error("Cannot use --file-info with multiple files"); + process.exit(1); + } + if (context.argv["version"]) { context.logger.log(prettier.version); process.exit(0); @@ -50,10 +55,9 @@ function run(args) { context.argv["stdin"] || (!hasFilePatterns && !process.stdin.isTTY); if (context.argv["find-config-path"]) { - util.logResolvedConfigPathOrDie( - context, - context.argv["find-config-path"] - ); + util.logResolvedConfigPathOrDie(context); + } else if (context.argv["file-info"]) { + util.logFileInfoOrDie(context); } else if (useStdin) { util.formatStdin(context); } else if (hasFilePatterns) { diff --git a/src/cli/util.js b/src/cli/util.js index a25f0621..36f9d0f2 100644 --- a/src/cli/util.js +++ b/src/cli/util.js @@ -5,13 +5,14 @@ const camelCase = require("camelcase"); const dashify = require("dashify"); const fs = require("fs"); const globby = require("globby"); -const ignore = require("ignore"); const chalk = require("chalk"); const readline = require("readline"); const leven = require("leven"); +const stringify = require("json-stable-stringify"); const minimist = require("./minimist"); const prettier = require("../../index"); +const createIgnorer = require("../common/create-ignorer"); const errors = require("../common/errors"); const constant = require("./constant"); const coreOptions = require("../main/core-options"); @@ -76,8 +77,10 @@ function handleError(context, filename, error) { process.exitCode = 2; } -function logResolvedConfigPathOrDie(context, filePath) { - const configFile = prettier.resolveConfigFile.sync(filePath); +function logResolvedConfigPathOrDie(context) { + const configFile = prettier.resolveConfigFile.sync( + context.argv["find-config-path"] + ); if (configFile) { context.logger.log(path.relative(process.cwd(), configFile)); } else { @@ -85,6 +88,23 @@ function logResolvedConfigPathOrDie(context, filePath) { } } +function logFileInfoOrDie(context) { + const options = { + ignorePath: context.argv["ignore-path"], + withNodeModules: context.argv["with-node-modules"], + plugins: context.argv["plugin"], + pluginSearchDirs: context.argv["plugin-search-dir"] + }; + context.logger.log( + prettier.format( + stringify(prettier.getFileInfo.sync(context.argv["file-info"], options)), + { + parser: "json" + } + ) + ); +} + function writeOutput(result, options) { // Don't use `console.log` here since it adds an extra newline at the end. process.stdout.write(result.formatted); @@ -255,7 +275,7 @@ function formatStdin(context) { ? path.resolve(process.cwd(), context.argv["stdin-filepath"]) : process.cwd(); - const ignorer = createIgnorer(context); + const ignorer = createIgnorerFromContextOrDie(context); const relativeFilepath = path.relative(process.cwd(), filepath); thirdParty.getStream(process.stdin).then(input => { @@ -278,22 +298,16 @@ function formatStdin(context) { }); } -function createIgnorer(context) { - const ignoreFilePath = path.resolve(context.argv["ignore-path"]); - let ignoreText = ""; - +function createIgnorerFromContextOrDie(context) { try { - ignoreText = fs.readFileSync(ignoreFilePath, "utf8"); - } catch (readError) { - if (readError.code !== "ENOENT") { - context.logger.error( - `Unable to read ${ignoreFilePath}: ` + readError.message - ); - process.exit(2); - } + return createIgnorer( + context.argv["ignore-path"], + context.argv["with-node-modules"] + ); + } catch (e) { + context.logger.error(e.message); + process.exit(2); } - - return ignore().add(ignoreText); } function eachFilename(context, patterns, callback) { @@ -329,7 +343,7 @@ function eachFilename(context, patterns, callback) { function formatFiles(context) { // The ignorer will be used to filter file paths after the glob is checked, // before any files are actually written - const ignorer = createIgnorer(context); + const ignorer = createIgnorerFromContextOrDie(context); eachFilename(context, context.filePatterns, (filename, options) => { const fileIgnored = ignorer.filter([filename]).length === 0; @@ -910,5 +924,6 @@ module.exports = { formatStdin, initContext, logResolvedConfigPathOrDie, + logFileInfoOrDie, normalizeDetailedOptionMap }; diff --git a/src/common/create-ignorer.js b/src/common/create-ignorer.js new file mode 100644 index 00000000..b63f47f5 --- /dev/null +++ b/src/common/create-ignorer.js @@ -0,0 +1,30 @@ +"use strict"; + +const ignore = require("ignore"); +const fs = require("fs"); +const path = require("path"); + +function createIgnorer(ignorePath, withNodeModules) { + let ignoreText = ""; + + if (ignorePath) { + const resolvedIgnorePath = path.resolve(ignorePath); + try { + ignoreText = fs.readFileSync(resolvedIgnorePath, "utf8"); + } catch (readError) { + if (readError.code !== "ENOENT") { + throw new Error( + `Unable to read ${resolvedIgnorePath}: ${readError.message}` + ); + } + } + } + + const ignorer = ignore().add(ignoreText); + if (!withNodeModules) { + ignorer.add("node_modules"); + } + return ignorer; +} + +module.exports = createIgnorer; diff --git a/src/common/get-file-info.js b/src/common/get-file-info.js new file mode 100644 index 00000000..9bcb25de --- /dev/null +++ b/src/common/get-file-info.js @@ -0,0 +1,40 @@ +"use strict"; + +const createIgnorer = require("./create-ignorer"); +const options = require("../main/options"); + +/** + * @param {string} filePath + * @param {{ ignorePath?: string, withNodeModules?: boolean, plugins: object }} opts + * + * Please note that prettier.getFileInfo() expects opts.plugins to be an array of paths, + * not an object. A transformation from this array to an object is automatically done + * internally by the method wrapper. See withPlugins() in index.js. + */ +function _getFileInfo(filePath, opts) { + let ignored = false; + const ignorer = createIgnorer(opts.ignorePath, opts.withNodeModules); + ignored = ignorer.ignores(filePath); + + const inferredParser = options.inferParser(filePath, opts.plugins) || null; + + return { + ignored, + inferredParser + }; +} + +// the method has been implemented as asynchronous to avoid possible breaking changes in future +function getFileInfo(filePath, opts) { + return new Promise((resolve, reject) => { + try { + resolve(_getFileInfo(filePath, opts)); + } catch (e) { + reject(e); + } + }); +} + +getFileInfo.sync = _getFileInfo; + +module.exports = getFileInfo; diff --git a/src/main/options.js b/src/main/options.js index 39a91738..5a7d5752 100644 --- a/src/main/options.js +++ b/src/main/options.js @@ -118,7 +118,7 @@ function inferParser(filepath, plugins) { }).languages.find( language => language.since !== null && - (language.extensions.indexOf(extension) > -1 || + ((language.extensions && language.extensions.indexOf(extension) > -1) || (language.filenames && language.filenames.find(name => name.toLowerCase() === filename))) ); @@ -126,4 +126,4 @@ function inferParser(filepath, plugins) { return language && language.parsers[0]; } -module.exports = { normalize, hiddenDefaults }; +module.exports = { normalize, hiddenDefaults, inferParser }; diff --git a/tests_integration/__tests__/__snapshots__/early-exit.js.snap b/tests_integration/__tests__/__snapshots__/early-exit.js.snap index ac67f38f..483d4880 100644 --- a/tests_integration/__tests__/__snapshots__/early-exit.js.snap +++ b/tests_integration/__tests__/__snapshots__/early-exit.js.snap @@ -102,6 +102,19 @@ Default: true exports[`show detailed usage with --help editorconfig (write) 1`] = `Array []`; +exports[`show detailed usage with --help file-info (stderr) 1`] = `""`; + +exports[`show detailed usage with --help file-info (stdout) 1`] = ` +"--file-info + + Extract the following info (as JSON) for a given file path. Reported fields: + * ignored (boolean) - true if file path is filtered by --ignore-path + * inferredParser (string | null) - name of parser inferred from file path +" +`; + +exports[`show detailed usage with --help file-info (write) 1`] = `Array []`; + exports[`show detailed usage with --help find-config-path (stderr) 1`] = `""`; exports[`show detailed usage with --help find-config-path (stdout) 1`] = ` @@ -638,6 +651,9 @@ Editor options: Other options: --no-color Do not colorize error messages. + --file-info Extract the following info (as JSON) for a given file path. Reported fields: + * ignored (boolean) - true if file path is filtered by --ignore-path + * inferredParser (string | null) - name of parser inferred from file path -h, --help Show CLI usage, or details about the given flag. Example: --help write --insert-pragma Insert @format pragma into file's first docblock comment. @@ -786,6 +802,9 @@ Editor options: Other options: --no-color Do not colorize error messages. + --file-info Extract the following info (as JSON) for a given file path. Reported fields: + * ignored (boolean) - true if file path is filtered by --ignore-path + * inferredParser (string | null) - name of parser inferred from file path -h, --help Show CLI usage, or details about the given flag. Example: --help write --insert-pragma Insert @format pragma into file's first docblock comment. @@ -807,6 +826,15 @@ Other options: exports[`throw error and show usage with something unexpected (write) 1`] = `Array []`; +exports[`throw error with --file-info + multiple files (stderr) 1`] = ` +"[error] Cannot use --file-info with multiple files +" +`; + +exports[`throw error with --file-info + multiple files (stdout) 1`] = `""`; + +exports[`throw error with --file-info + multiple files (write) 1`] = `Array []`; + exports[`throw error with --find-config-path + multiple files (stderr) 1`] = ` "[error] Cannot use --find-config-path with multiple files " diff --git a/tests_integration/__tests__/__snapshots__/file-info.js.snap b/tests_integration/__tests__/__snapshots__/file-info.js.snap new file mode 100644 index 00000000..b1946701 --- /dev/null +++ b/tests_integration/__tests__/__snapshots__/file-info.js.snap @@ -0,0 +1,121 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`extracts file-info for a file in not_node_modules (stderr) 1`] = `""`; + +exports[`extracts file-info for a file in not_node_modules (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info for a file in not_node_modules (write) 1`] = `Array []`; + +exports[`extracts file-info for a js file (stderr) 1`] = `""`; + +exports[`extracts file-info for a js file (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info for a js file (write) 1`] = `Array []`; + +exports[`extracts file-info for a known markdown file with no extension (stderr) 1`] = `""`; + +exports[`extracts file-info for a known markdown file with no extension (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"markdown\\" } + +" +`; + +exports[`extracts file-info for a known markdown file with no extension (write) 1`] = `Array []`; + +exports[`extracts file-info for a markdown file (stderr) 1`] = `""`; + +exports[`extracts file-info for a markdown file (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"markdown\\" } + +" +`; + +exports[`extracts file-info for a markdown file (write) 1`] = `Array []`; + +exports[`extracts file-info with ignored=false for a file in node_modules when --with-node-modules provided (stderr) 1`] = `""`; + +exports[`extracts file-info with ignored=false for a file in node_modules when --with-node-modules provided (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info with ignored=false for a file in node_modules when --with-node-modules provided (write) 1`] = `Array []`; + +exports[`extracts file-info with ignored=true for a file in .prettierignore (stderr) 1`] = `""`; + +exports[`extracts file-info with ignored=true for a file in .prettierignore (stdout) 1`] = ` +"{ \\"ignored\\": true, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info with ignored=true for a file in .prettierignore (write) 1`] = `Array []`; + +exports[`extracts file-info with ignored=true for a file in a hand-picked .prettierignore (stderr) 1`] = `""`; + +exports[`extracts file-info with ignored=true for a file in a hand-picked .prettierignore (stdout) 1`] = ` +"{ \\"ignored\\": true, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info with ignored=true for a file in a hand-picked .prettierignore (write) 1`] = `Array []`; + +exports[`extracts file-info with inferredParser=foo when a plugin is hand-picked (stderr) 1`] = `""`; + +exports[`extracts file-info with inferredParser=foo when a plugin is hand-picked (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"foo\\" } + +" +`; + +exports[`extracts file-info with inferredParser=foo when a plugin is hand-picked (write) 1`] = `Array []`; + +exports[`extracts file-info with inferredParser=foo when plugins are autoloaded (stderr) 1`] = `""`; + +exports[`extracts file-info with inferredParser=foo when plugins are autoloaded (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"foo\\" } + +" +`; + +exports[`extracts file-info with inferredParser=foo when plugins are autoloaded (write) 1`] = `Array []`; + +exports[`extracts file-info with inferredParser=foo when plugins are loaded with --plugin-search-dir (stderr) 1`] = `""`; + +exports[`extracts file-info with inferredParser=foo when plugins are loaded with --plugin-search-dir (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": \\"foo\\" } + +" +`; + +exports[`extracts file-info with inferredParser=foo when plugins are loaded with --plugin-search-dir (write) 1`] = `Array []`; + +exports[`extracts file-info with inferredParser=null for file.foo (stderr) 1`] = `""`; + +exports[`extracts file-info with inferredParser=null for file.foo (stdout) 1`] = ` +"{ \\"ignored\\": false, \\"inferredParser\\": null } + +" +`; + +exports[`extracts file-info with inferredParser=null for file.foo (write) 1`] = `Array []`; + +exports[`extracts file-info with with ignored=true for a file in node_modules (stderr) 1`] = `""`; + +exports[`extracts file-info with with ignored=true for a file in node_modules (stdout) 1`] = ` +"{ \\"ignored\\": true, \\"inferredParser\\": \\"babylon\\" } + +" +`; + +exports[`extracts file-info with with ignored=true for a file in node_modules (write) 1`] = `Array []`; diff --git a/tests_integration/__tests__/early-exit.js b/tests_integration/__tests__/early-exit.js index f4b2f4dc..bb740d63 100644 --- a/tests_integration/__tests__/early-exit.js +++ b/tests_integration/__tests__/early-exit.js @@ -99,6 +99,12 @@ describe("throw error with --find-config-path + multiple files", () => { }); }); +describe("throw error with --file-info + multiple files", () => { + runPrettier("cli", ["--file-info", "abc.js", "def.js"]).test({ + status: 1 + }); +}); + describe("throw error and show usage with something unexpected", () => { runPrettier("cli", [], { isTTY: true }).test({ status: "non-zero" diff --git a/tests_integration/__tests__/file-info.js b/tests_integration/__tests__/file-info.js new file mode 100644 index 00000000..7c49a905 --- /dev/null +++ b/tests_integration/__tests__/file-info.js @@ -0,0 +1,231 @@ +"use strict"; + +const path = require("path"); + +const runPrettier = require("../runPrettier"); +const prettier = require("../../tests_config/require_prettier"); + +expect.addSnapshotSerializer(require("../path-serializer")); + +describe("extracts file-info for a js file", () => { + runPrettier("cli/", ["--file-info", "something.js"]).test({ + status: 0 + }); +}); + +describe("extracts file-info for a markdown file", () => { + runPrettier("cli/", ["--file-info", "README.md"]).test({ + status: 0 + }); +}); + +describe("extracts file-info for a known markdown file with no extension", () => { + runPrettier("cli/", ["--file-info", "README"]).test({ + status: 0 + }); +}); + +describe("extracts file-info with ignored=true for a file in .prettierignore", () => { + runPrettier("cli/ignore-path/", ["--file-info", "regular-module.js"]).test({ + status: 0 + }); +}); + +describe("extracts file-info with ignored=true for a file in a hand-picked .prettierignore", () => { + runPrettier("cli/", [ + "--file-info", + "regular-module.js", + "--ignore-path=ignore-path/.prettierignore" + ]).test({ + status: 0 + }); +}); + +describe("extracts file-info for a file in not_node_modules", () => { + runPrettier("cli/with-node-modules/", [ + "--file-info", + "not_node_modules/file.js" + ]).test({ + status: 0 + }); +}); + +describe("extracts file-info with with ignored=true for a file in node_modules", () => { + runPrettier("cli/with-node-modules/", [ + "--file-info", + "node_modules/file.js" + ]).test({ + status: 0 + }); +}); + +describe("extracts file-info with ignored=false for a file in node_modules when --with-node-modules provided", () => { + runPrettier("cli/with-node-modules/", [ + "--file-info", + "node_modules/file.js", + "--with-node-modules" + ]).test({ + status: 0 + }); +}); + +describe("extracts file-info with inferredParser=null for file.foo", () => { + runPrettier("cli/", ["--file-info", "file.foo"]).test({ + status: 0 + }); +}); + +describe("extracts file-info with inferredParser=foo when plugins are autoloaded", () => { + runPrettier("plugins/automatic/", ["--file-info", "file.foo"]).test({ + status: 0 + }); +}); + +describe("extracts file-info with inferredParser=foo when plugins are loaded with --plugin-search-dir", () => { + runPrettier("cli/", [ + "--file-info", + "file.foo", + "--plugin-search-dir", + "../plugins/automatic" + ]).test({ + status: 0 + }); +}); + +describe("extracts file-info with inferredParser=foo when a plugin is hand-picked", () => { + runPrettier("cli/", [ + "--file-info", + "file.foo", + "--plugin", + "../plugins/automatic/node_modules/@prettier/plugin-foo" + ]).test({ + status: 0 + }); +}); + +test("API getFileInfo with no args", () => { + expect(prettier.getFileInfo()).rejects.toThrow(); +}); + +test("API getFileInfo.sync with no args", () => { + expect(() => prettier.getFileInfo.sync()).toThrow(); +}); + +test("API getFileInfo with filepath only", () => { + expect(prettier.getFileInfo("README")).resolves.toMatchObject({ + ignored: false, + inferredParser: "markdown" + }); +}); + +test("API getFileInfo.sync with filepath only", () => { + expect(prettier.getFileInfo.sync("README")).toMatchObject({ + ignored: false, + inferredParser: "markdown" + }); +}); + +test("API getFileInfo with ignorePath", () => { + const file = path.resolve( + path.join(__dirname, "../cli/ignore-path/regular-module.js") + ); + const ignorePath = path.resolve( + path.join(__dirname, "../cli/ignore-path/.prettierignore") + ); + + expect(prettier.getFileInfo(file)).resolves.toMatchObject({ + ignored: false, + inferredParser: "babylon" + }); + + expect( + prettier.getFileInfo(file, { + ignorePath + }) + ).resolves.toMatchObject({ + ignored: true, + inferredParser: "babylon" + }); +}); + +test("API getFileInfo.sync with ignorePath", () => { + const file = path.resolve( + path.join(__dirname, "../cli/ignore-path/regular-module.js") + ); + const ignorePath = path.resolve( + path.join(__dirname, "../cli/ignore-path/.prettierignore") + ); + + expect(prettier.getFileInfo.sync(file)).toMatchObject({ + ignored: false, + inferredParser: "babylon" + }); + + expect( + prettier.getFileInfo.sync(file, { + ignorePath + }) + ).toMatchObject({ + ignored: true, + inferredParser: "babylon" + }); +}); + +test("API getFileInfo with withNodeModules", () => { + const file = path.resolve( + path.join(__dirname, "../cli/with-node-modules/node_modules/file.js") + ); + expect(prettier.getFileInfo(file)).resolves.toMatchObject({ + ignored: true, + inferredParser: "babylon" + }); + expect( + prettier.getFileInfo(file, { + withNodeModules: true + }) + ).resolves.toMatchObject({ + ignored: false, + inferredParser: "babylon" + }); +}); + +test("API getFileInfo with plugins loaded using pluginSearchDir", () => { + const file = "file.foo"; + const pluginsPath = path.resolve( + path.join(__dirname, "../plugins/automatic") + ); + expect(prettier.getFileInfo(file)).resolves.toMatchObject({ + ignored: false, + inferredParser: null + }); + expect( + prettier.getFileInfo(file, { + pluginSearchDirs: [pluginsPath] + }) + ).resolves.toMatchObject({ + ignored: false, + inferredParser: "foo" + }); +}); + +test("API getFileInfo with hand-picked plugins", () => { + const file = "file.foo"; + const pluginPath = path.resolve( + path.join( + __dirname, + "../plugins/automatic/node_modules/@prettier/plugin-foo" + ) + ); + expect(prettier.getFileInfo(file)).resolves.toMatchObject({ + ignored: false, + inferredParser: null + }); + expect( + prettier.getFileInfo(file, { + plugins: [pluginPath] + }) + ).resolves.toMatchObject({ + ignored: false, + inferredParser: "foo" + }); +}); diff --git a/tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js b/tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js index 080b0e6c..577cee25 100644 --- a/tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js +++ b/tests_integration/plugins/automatic/node_modules/@prettier/plugin-foo/index.js @@ -6,7 +6,8 @@ module.exports = { languages: [ { name: "foo", - parsers: ["foo"] + parsers: ["foo"], + extensions: [".foo"] } ], parsers: {