Skip to content

Commit

Permalink
Fix argument passed to lilconfig.search() (#15363)
Browse files Browse the repository at this point in the history
  • Loading branch information
fisker authored Nov 15, 2023
1 parent 83b9f62 commit e4a74c0
Show file tree
Hide file tree
Showing 11 changed files with 79 additions and 14 deletions.
19 changes: 19 additions & 0 deletions changelog_unreleased/api/15363.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
#### Fix config file search (#15363 by @fisker)

Previously, we start search for config files from the filePath as a directory, if it happened to be a directory and contains config file, it will be used by mistake.

```text
├─ .prettierrc
└─ test.js (A directory)
└─ index.min.js
```

```js
// Prettier stable
await prettier.resolveConfigFile(new URL("./test.js", import.meta.url));
// <CWD>/test.js/.prettierrc

// Prettier main
await prettier.resolveConfigFile(new URL("./test.js", import.meta.url));
// <CWD>/.prettierrc
```
4 changes: 3 additions & 1 deletion src/cli/format.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,8 @@ async function formatStdin(context) {

try {
const input = await getStdin();
// TODO[@fisker]: Exit if no input.
// `prettier --config-precedence cli-override`

let isFileIgnored = false;
if (filepath) {
Expand All @@ -262,7 +264,7 @@ async function formatStdin(context) {

const options = await getOptionsForFile(
context,
filepath ? path.resolve(process.cwd(), filepath) : process.cwd(),
filepath ? path.resolve(filepath) : undefined,
);

if (await listDifferent(context, input, options, "(stdin)")) {
Expand Down
4 changes: 2 additions & 2 deletions src/cli/options/get-options-for-file.js
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,8 @@ async function getOptionsOrDie(context, filePath) {
return options;
} catch (error) {
context.logger.error(
`Invalid configuration for file "${filePath}":\n` + error.message,
`Invalid configuration${filePath ? ` for file "${filePath}"` : ""}:\n` +
error.message,
);
process.exit(2);
}
Expand All @@ -103,7 +104,6 @@ function applyConfigPrecedence(context, options) {

async function getOptionsForFile(context, filepath) {
const options = await getOptionsOrDie(context, filepath);

const hasPlugins = options?.plugins;
if (hasPlugins) {
await context.pushContextPlugins(options.plugins);
Expand Down
23 changes: 16 additions & 7 deletions src/config/resolve-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,9 +30,17 @@ function loadPrettierConfig(filePath, options) {
const { load, search } = getPrettierConfigExplorer({
cache: Boolean(useCache),
});
return configPath
? load(configPath)
: search(filePath ? path.resolve(filePath) : undefined);

if (configPath) {
return load(configPath);
}

if (!filePath) {
return search();
}

const dirname = path.dirname(path.resolve(filePath));
return search(dirname);
}

async function resolveConfig(fileUrlOrPath, options) {
Expand Down Expand Up @@ -65,10 +73,11 @@ async function resolveConfig(fileUrlOrPath, options) {
}

async function resolveConfigFile(fileUrlOrPath) {
const { search } = getPrettierConfigExplorer({ cache: false });
const result = await search(
fileUrlOrPath ? path.resolve(toPath(fileUrlOrPath)) : undefined,
);
const { search } = getPrettierConfigExplorerWithoutCache();
const dirname = fileUrlOrPath
? path.dirname(path.resolve(toPath(fileUrlOrPath)))
: undefined;
const result = await search(dirname);
return result?.filepath ?? null;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ exports[`show warning with unknown option (stdout) 1`] = `""`;
exports[`show warning with unknown option (write) 1`] = `[]`;
exports[`throw error for unsupported extension (stderr) 1`] = `
"[error] Invalid configuration for file "<cli>/config/invalid":
"[error] Invalid configuration:
[error] No loader specified for extension ".unsupported""
`;
Expand Down Expand Up @@ -62,7 +62,7 @@ exports[`throw error with invalid config precedence option (configPrecedence) (s
exports[`throw error with invalid config precedence option (configPrecedence) (write) 1`] = `[]`;
exports[`throw error with invalid config target (directory) (stderr) 1`] = `
"[error] Invalid configuration for file "<cli>/config/invalid":
"[error] Invalid configuration:
[error] EISDIR: illegal operation on a directory, read"
`;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ exports[`accepts configuration from --config (stdout) 1`] = `

exports[`accepts configuration from --config (write) 1`] = `[]`;

exports[`prints error message when no file found with --find-config-path (stderr) 1`] = `"[error] Can not find configure file for ".."."`;
exports[`prints error message when no file found with --find-config-path (stderr) 1`] = `"[error] Can not find configure file for "../--non-exits-filename--"."`;

exports[`prints error message when no file found with --find-config-path (write) 1`] = `[]`;

Expand Down
31 changes: 30 additions & 1 deletion tests/integration/__tests__/config-resolution.js
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ describe("prints error message when no file found with --find-config-path", () =
"--end-of-line",
"lf",
"--find-config-path",
"..",
"../--non-exits-filename--",
]).test({
stdout: "",
status: 1,
Expand Down Expand Up @@ -389,3 +389,32 @@ test("API resolveConfig accepts path or URL", async () => {
expect(resultByPath).toMatchObject(expectedResult);
expect(resultByRelativePath).toMatchObject(expectedResult);
});

test("Search from directory, not treat file as directory", async () => {
// CLI
const getConfigFileByCli = async (file) => {
const { stdout: configFile } = await runCli("cli/config/config-position/", [
"--find-config-path",
file,
]);
return configFile;
};

expect(await getConfigFileByCli("file.js")).toBe(".prettierrc");
expect(await getConfigFileByCli("directory/file-in-child-directory.js")).toBe(
"directory/.prettierrc",
);

// Api
const directory = new URL("../cli/config/config-position/", import.meta.url);
const getConfigFileByApi = async (file) => {
const configFile = await prettier.resolveConfigFile(
new URL(file, directory),
);
return url.pathToFileURL(configFile).href.slice(directory.href.length);
};
expect(await getConfigFileByApi("file.js")).toBe(".prettierrc");
expect(await getConfigFileByApi("directory/file-in-child-directory.js")).toBe(
"directory/.prettierrc",
);
});
1 change: 1 addition & 0 deletions tests/integration/cli/config/config-position/.prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
{}
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Hello
.prettier()
2 changes: 2 additions & 0 deletions tests/integration/cli/config/config-position/file.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Hello
.prettier()

0 comments on commit e4a74c0

Please sign in to comment.