Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 24 additions & 17 deletions editors/vscode/client/ConfigService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,25 +184,32 @@ export class ConfigService implements IDisposable {
*/
private async searchNodeModulesBin(binaryName: string): Promise<string | undefined> {
const cts = new CancellationTokenSource();
setTimeout(() => cts.cancel(), 10000); // cancel after 10 seconds
setTimeout(() => cts.cancel(), 20000); // cancel after 20 seconds

try {
// bun package manager uses `.exe` extension on Windows
// search for both with and without `.exe` extension
const extension = process.platform === "win32" ? "{,.exe}" : "";
// maybe use `tinyglobby` later for better performance, VSCode can be slow on globbing large projects.
const files = await workspace.findFiles(
// search workspace root plus up to 3 subdirectory levels for the binary path
`{,*/,*/*,*/*/*}/node_modules/.bin/${binaryName}${extension}`,
undefined,
1,
cts.token,
);

return files.length > 0 ? files[0].fsPath : undefined;
} catch {
return undefined;
}
// search workspace root plus up to 3 subdirectory levels for the binary path
let patterns = [
`node_modules/.bin/${binaryName}`,
`*/node_modules/.bin/${binaryName}`,
`*/*/node_modules/.bin/${binaryName}`,
`*/*/*/node_modules/.bin/${binaryName}`,
];

if (process.platform === "win32") {
// bun package manager uses `.exe` extension on Windows
// search for both with and without `.exe` extension
patterns = patterns.flatMap((pattern) => [`${pattern}`, `${pattern}.exe`]);
}

for (const pattern of patterns) {
// maybe use `tinyglobby` later for better performance, VSCode can be slow on globbing large projects.
// oxlint-disable-next-line no-await-in-loop -- search sequentially up the directories
const files = await workspace.findFiles(pattern, null, 1, cts.token);
if (files.length > 0) {
return files[0].fsPath;
}
}
} catch {}
}

private async onVscodeConfigChange(event: ConfigurationChangeEvent): Promise<void> {
Expand Down
4 changes: 1 addition & 3 deletions editors/vscode/tests/unit/ConfigService.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -154,16 +154,14 @@ suite("ConfigService", () => {
strictEqual(relativeServerPath, `${workspace_path}\\relative\\oxlint`);
});

// Skipped due to Test API limitation?
test.skip("resolves binary path in multi-folder workspace", async () => {
test("resolves binary path in multi-folder workspace", async () => {
const service = new ConfigService();
const workspace_path = getWorkspaceFolderPlatformSafe();

await createWorkspaceFolderFileUri("node_modules/.bin/oxlint");
await createWorkspaceFolderFileUri("node_modules/.bin/oxlint", WORKSPACE_SECOND_FOLDER);
const absoluteServerPath = await service.getOxlintServerBinPath();

// returns undefined, but it should search with glob and return the first found binary
strictEqual(absoluteServerPath, `${workspace_path}/node_modules/.bin/oxlint`);

await deleteWorkspaceFolderFileUri("node_modules/.bin/oxlint");
Expand Down
Loading