Skip to content

Commit 2ad7e14

Browse files
committed
refactor(vscode)!: use node_module/.bin/oxlint by default, fallback to internal language server
1 parent daa3866 commit 2ad7e14

File tree

4 files changed

+35
-49
lines changed

4 files changed

+35
-49
lines changed

editors/vscode/client/ConfigService.ts

Lines changed: 17 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -91,45 +91,27 @@ export class ConfigService implements IDisposable {
9191
return false;
9292
}
9393

94-
public getUserServerBinPath(): string | undefined {
95-
let bin = this.vsCodeConfig.binPathOxlint;
96-
if (!bin) {
97-
return;
98-
}
99-
100-
// validates the given path is safe to use
101-
if (validateSafeBinaryPath(bin) === false) {
102-
return;
103-
}
104-
105-
if (!path.isAbsolute(bin)) {
106-
// if the path is not absolute, resolve it to the first workspace folder
107-
const cwd = this.workspaceConfigs.keys().next().value;
108-
if (!cwd) {
109-
return;
110-
}
111-
bin = path.normalize(path.join(cwd, bin));
112-
// strip the leading slash on Windows
113-
if (process.platform === "win32" && bin.startsWith("\\")) {
114-
bin = bin.slice(1);
115-
}
116-
}
117-
118-
return bin;
94+
public async getOxlintServerBinPath(): Promise<string | undefined> {
95+
return this.searchBinaryPath(this.vsCodeConfig.binPathOxlint, "oxlint");
11996
}
12097

12198
public async getOxfmtServerBinPath(): Promise<string | undefined> {
122-
let bin = this.vsCodeConfig.binPathOxfmt;
99+
return this.searchBinaryPath(this.vsCodeConfig.binPathOxfmt, "oxfmt");
100+
}
123101

102+
private async searchBinaryPath(
103+
settingsBinary: string | undefined,
104+
defaultPattern: string,
105+
): Promise<string | undefined> {
124106
const cwd = this.workspaceConfigs.keys().next().value;
125107
if (!cwd) {
126108
return undefined;
127109
}
128110

129-
if (!bin) {
130-
// try to find oxfmt in node_modules/.bin, resolve to the first workspace folder
111+
if (!settingsBinary) {
112+
// try to find the binary in node_modules/.bin, resolve to the first workspace folder
131113
const files = await workspace.findFiles(
132-
new RelativePattern(cwd, "**/node_modules/.bin/oxfmt"),
114+
new RelativePattern(cwd, `**/node_modules/.bin/${defaultPattern}`),
133115
null,
134116
1,
135117
);
@@ -138,20 +120,20 @@ export class ConfigService implements IDisposable {
138120
}
139121

140122
// validates the given path is safe to use
141-
if (validateSafeBinaryPath(bin) === false) {
123+
if (validateSafeBinaryPath(settingsBinary) === false) {
142124
return undefined;
143125
}
144126

145-
if (!path.isAbsolute(bin)) {
127+
if (!path.isAbsolute(settingsBinary)) {
146128
// if the path is not absolute, resolve it to the first workspace folder
147-
bin = path.normalize(path.join(cwd, bin));
129+
settingsBinary = path.normalize(path.join(cwd, settingsBinary));
148130
// strip the leading slash on Windows
149-
if (process.platform === "win32" && bin.startsWith("\\")) {
150-
bin = bin.slice(1);
131+
if (process.platform === "win32" && settingsBinary.startsWith("\\")) {
132+
settingsBinary = settingsBinary.slice(1);
151133
}
152134
}
153135

154-
return bin;
136+
return settingsBinary;
155137
}
156138

157139
private async onVscodeConfigChange(event: ConfigurationChangeEvent): Promise<void> {

editors/vscode/client/extension.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { commands, ExtensionContext, window, workspace } from "vscode";
22

3+
import { join } from "node:path";
34
import { OxcCommands } from "./commands";
45
import { ConfigService } from "./ConfigService";
56
import StatusBarItemHandler from "./StatusBarItemHandler";
@@ -75,6 +76,15 @@ export async function activate(context: ExtensionContext) {
7576
),
7677
);
7778

79+
// when no oxlint binary path are provided, fallback to internal oxc_language_server
80+
if (!binaryPaths[0]) {
81+
const ext = process.platform === "win32" ? ".exe" : "";
82+
// NOTE: The `./target/release` path is aligned with the path defined in .github/workflows/release_vscode.yml
83+
binaryPaths[0] =
84+
process.env.SERVER_PATH_DEV ??
85+
join(context.extensionPath, `./target/release/oxc_language_server${ext}`);
86+
}
87+
7888
// remove this block, when `oxfmt` binary is always required. This will be a breaking change.
7989
if (
8090
binaryPaths.some((path) => path?.includes("oxc_language_server")) &&

editors/vscode/client/tools/linter.ts

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@ import {
2424
ServerOptions,
2525
} from "vscode-languageclient/node";
2626

27-
import { join } from "node:path";
2827
import { OxcCommands } from "../commands";
2928
import { ConfigService } from "../ConfigService";
3029
import StatusBarItemHandler from "../StatusBarItemHandler";
@@ -61,7 +60,7 @@ export default class LinterTool implements ToolInterface {
6160
outputChannel: LogOutputChannel,
6261
configService: ConfigService,
6362
): Promise<string | undefined> {
64-
const bin = configService.getUserServerBinPath();
63+
const bin = await configService.getOxlintServerBinPath();
6564
if (workspace.isTrusted && bin) {
6665
try {
6766
await fsPromises.access(bin);
@@ -70,12 +69,7 @@ export default class LinterTool implements ToolInterface {
7069
outputChannel.error(`Invalid bin path: ${bin}`, e);
7170
}
7271
}
73-
const ext = process.platform === "win32" ? ".exe" : "";
74-
// NOTE: The `./target/release` path is aligned with the path defined in .github/workflows/release_vscode.yml
75-
return (
76-
process.env.SERVER_PATH_DEV ??
77-
join(context.extensionPath, `./target/release/oxc_language_server${ext}`)
78-
);
72+
return process.env.SERVER_PATH_DEV;
7973
}
8074

8175
async activate(

editors/vscode/tests/ConfigService.spec.ts

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,20 +70,20 @@ suite('ConfigService', () => {
7070
});
7171
});
7272

73-
suite('getUserServerBinPath', () => {
73+
suite('getOxlintServerBinPath', () => {
7474
testSingleFolderMode('resolves relative server path with workspace folder', async () => {
7575
const service = new ConfigService();
76-
const nonDefinedServerPath = service.getUserServerBinPath();
76+
const nonDefinedServerPath = await service.getOxlintServerBinPath();
7777

7878
strictEqual(nonDefinedServerPath, undefined);
7979

8080
await conf.update('path.oxlint', '/absolute/oxlint');
81-
const absoluteServerPath = service.getUserServerBinPath();
81+
const absoluteServerPath = await service.getOxlintServerBinPath();
8282

8383
strictEqual(absoluteServerPath, '/absolute/oxlint');
8484

8585
await conf.update('path.oxlint', './relative/oxlint');
86-
const relativeServerPath = service.getUserServerBinPath();
86+
const relativeServerPath = await service.getOxlintServerBinPath();
8787

8888
const workspace_path = getWorkspaceFolderPlatformSafe();
8989
strictEqual(relativeServerPath, `${workspace_path}/relative/oxlint`);
@@ -92,7 +92,7 @@ suite('ConfigService', () => {
9292
testSingleFolderMode('returns undefined for unsafe server path', async () => {
9393
const service = new ConfigService();
9494
await conf.update('path.oxlint', '../unsafe/oxlint');
95-
const unsafeServerPath = service.getUserServerBinPath();
95+
const unsafeServerPath = await service.getOxlintServerBinPath();
9696

9797
strictEqual(unsafeServerPath, undefined);
9898
});
@@ -103,7 +103,7 @@ suite('ConfigService', () => {
103103
}
104104
const service = new ConfigService();
105105
await conf.update('path.oxlint', './relative/oxlint');
106-
const relativeServerPath = service.getUserServerBinPath();
106+
const relativeServerPath = service.getOxlintServerBinPath();
107107
const workspace_path = getWorkspaceFolderPlatformSafe();
108108

109109
strictEqual(workspace_path[1], ':', 'The test workspace folder must be an absolute path with a drive letter on Windows');

0 commit comments

Comments
 (0)