diff --git a/editors/vscode/client/ConfigService.ts b/editors/vscode/client/ConfigService.ts index 3a9280fa5ec37..c0f32813fd193 100644 --- a/editors/vscode/client/ConfigService.ts +++ b/editors/vscode/client/ConfigService.ts @@ -90,45 +90,62 @@ export class ConfigService implements IDisposable { return this.searchBinaryPath(this.vsCodeConfig.binPathOxfmt, "oxfmt"); } + public getTsGoLintBinPath(): string | undefined { + return this.resolveBinaryPath(this.vsCodeConfig.binPathTsGoLint); + } + private async searchBinaryPath( settingsBinary: string | undefined, defaultPattern: string, ): Promise { + if (settingsBinary) { + return this.resolveBinaryPath(settingsBinary); + } + + // try to find the binary in node_modules/.bin, resolve to the first workspace folder const cwd = this.workspaceConfigs.keys().next().value; if (!cwd) { return undefined; } - if (!settingsBinary) { - // try to find the binary in node_modules/.bin, resolve to the first workspace folder - const files = await workspace.findFiles( - new RelativePattern(cwd, `**/node_modules/.bin/${defaultPattern}`), - null, - 1, - ); + const files = await workspace.findFiles( + new RelativePattern(cwd, `**/node_modules/.bin/${defaultPattern}`), + null, + 1, + ); + + return files.length > 0 ? files[0].fsPath : undefined; + } + + private resolveBinaryPath(settingsPath: string | undefined): string | undefined { + if (!settingsPath) { + return undefined; + } - return files.length > 0 ? files[0].fsPath : undefined; + const cwd = this.workspaceConfigs.keys().next().value; + if (!cwd) { + return undefined; } if (!workspace.isTrusted) { - return; + return undefined; } // validates the given path is safe to use - if (validateSafeBinaryPath(settingsBinary) === false) { + if (validateSafeBinaryPath(settingsPath) === false) { return undefined; } - if (!path.isAbsolute(settingsBinary)) { + if (!path.isAbsolute(settingsPath)) { // if the path is not absolute, resolve it to the first workspace folder - settingsBinary = path.normalize(path.join(cwd, settingsBinary)); + settingsPath = path.normalize(path.join(cwd, settingsPath)); // strip the leading slash on Windows - if (process.platform === "win32" && settingsBinary.startsWith("\\")) { - settingsBinary = settingsBinary.slice(1); + if (process.platform === "win32" && settingsPath.startsWith("\\")) { + settingsPath = settingsPath.slice(1); } } - return settingsBinary; + return settingsPath; } private async onVscodeConfigChange(event: ConfigurationChangeEvent): Promise { diff --git a/editors/vscode/client/tools/linter.ts b/editors/vscode/client/tools/linter.ts index 2db0bbbd0aefa..061cc04e53b1c 100644 --- a/editors/vscode/client/tools/linter.ts +++ b/editors/vscode/client/tools/linter.ts @@ -110,7 +110,7 @@ export default class LinterTool implements ToolInterface { const run: Executable = runExecutable( binaryPath, configService.vsCodeConfig.nodePath, - configService.vsCodeConfig.binPathTsGoLint, + configService.getTsGoLintBinPath(), ); const serverOptions: ServerOptions = { run, diff --git a/editors/vscode/tests/ConfigService.spec.ts b/editors/vscode/tests/ConfigService.spec.ts index 53f960adfacbd..acd6d9f241152 100644 --- a/editors/vscode/tests/ConfigService.spec.ts +++ b/editors/vscode/tests/ConfigService.spec.ts @@ -110,4 +110,49 @@ suite('ConfigService', () => { strictEqual(relativeServerPath, `${workspace_path}\\relative\\oxlint`); }); }); + + suite('getTsGoLintBinPath', () => { + testSingleFolderMode('resolves relative tsgolint path with workspace folder', async () => { + const service = new ConfigService(); + const nonDefinedPath = service.getTsGoLintBinPath(); + + strictEqual(nonDefinedPath, undefined); + + await conf.update('path.tsgolint', '/absolute/tsgolint'); + service.vsCodeConfig.refresh(); + const absolutePath = service.getTsGoLintBinPath(); + + strictEqual(absolutePath, '/absolute/tsgolint'); + + await conf.update('path.tsgolint', './relative/tsgolint'); + service.vsCodeConfig.refresh(); + const relativePath = service.getTsGoLintBinPath(); + + const workspace_path = getWorkspaceFolderPlatformSafe(); + strictEqual(relativePath, `${workspace_path}/relative/tsgolint`); + }); + + testSingleFolderMode('returns undefined for unsafe tsgolint path', async () => { + const service = new ConfigService(); + await conf.update('path.tsgolint', '../unsafe/tsgolint'); + service.vsCodeConfig.refresh(); + const unsafePath = service.getTsGoLintBinPath(); + + strictEqual(unsafePath, undefined); + }); + + testSingleFolderMode('returns backslashes path on Windows', async () => { + if (process.platform !== 'win32') { + return; + } + const service = new ConfigService(); + await conf.update('path.tsgolint', './relative/tsgolint'); + service.vsCodeConfig.refresh(); + const relativePath = service.getTsGoLintBinPath(); + const workspace_path = getWorkspaceFolderPlatformSafe(); + + strictEqual(workspace_path[1], ':', 'The test workspace folder must be an absolute path with a drive letter on Windows'); + strictEqual(relativePath, `${workspace_path}\\relative\\tsgolint`); + }); + }); });