diff --git a/package-lock.json b/package-lock.json index eda6c623..5871ad4f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,6 +11,7 @@ "dependencies": { "@zero-plusplus/autohotkey-utilities": "github:zero-plusplus/node-autohotkey-utilities#develop", "async-lock": "^1.2.8", + "command-exists": "^1.2.9", "convert-hrtime": "^3.0.0", "fast-glob": "^3.2.7", "fast-xml-parser": "^3.16.0", @@ -1644,6 +1645,11 @@ "color-support": "bin.js" } }, + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, "node_modules/commander": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", @@ -10748,6 +10754,11 @@ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", "dev": true }, + "command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==" + }, "commander": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", diff --git a/package.json b/package.json index 955e5f44..59949713 100644 --- a/package.json +++ b/package.json @@ -959,6 +959,7 @@ "dependencies": { "@zero-plusplus/autohotkey-utilities": "github:zero-plusplus/node-autohotkey-utilities#develop", "async-lock": "^1.2.8", + "command-exists": "^1.2.9", "convert-hrtime": "^3.0.0", "fast-glob": "^3.2.7", "fast-xml-parser": "^3.16.0", diff --git a/src/extension.ts b/src/extension.ts index 55336d02..7ed6af0f 100644 --- a/src/extension.ts +++ b/src/extension.ts @@ -1,5 +1,5 @@ /* eslint-disable require-atomic-updates */ -import { existsSync, readFileSync } from 'fs'; +import { existsSync, lstatSync, readFileSync } from 'fs'; import * as path from 'path'; import * as vscode from 'vscode'; import { isArray, isBoolean, isPlainObject } from 'ts-predicates'; @@ -27,6 +27,16 @@ const ahkPathResolve = (filePath: string, cwd?: string): string => { return _filePath; }; const normalizePath = (filePath: string): string => (filePath ? path.normalize(filePath) : filePath); // If pass in an empty string, path.normalize returns '.' +const commandExistsSync = require('command-exists').sync; +const existsSyncEx = (path: string): boolean => { + try { + lstatSync(path); + } + catch (err) { + if ((err as any)?.code === 'ENOENT') return false; + } + return true; +}; export type ScopeName = 'Local' | 'Static' | 'Global'; export type ScopeSelector = '*' | ScopeName; @@ -208,7 +218,7 @@ class AhkConfigurationProvider implements vscode.DebugConfigurationProvider { config.runtime = ahkPathResolve(config.runtime); } - if (!existsSync(config.runtime)) { + if (!existsSyncEx(config.runtime) && !commandExistsSync(config.runtime)) { throw Error(`\`runtime\` must be a file path that exists.\nSpecified: "${String(normalizePath(config.runtime))}"`); } })(); @@ -356,7 +366,7 @@ class AhkConfigurationProvider implements vscode.DebugConfigurationProvider { if (!isString(config.program)) { throw Error('`program` must be a string.'); } - if (config.request === 'launch' && !existsSync(config.program)) { + if (config.request === 'launch' && !existsSyncEx(config.program) && !commandExistsSync(config.program)) { throw Error(`\`program\` must be a file path that exists.\nSpecified: "${String(normalizePath(config.program))}"`); } if (config.program) { @@ -424,7 +434,7 @@ class AhkConfigurationProvider implements vscode.DebugConfigurationProvider { if (!isString(config.openFileOnExit)) { throw Error('`openFileOnExit` must be a string.'); } - if (!existsSync(config.openFileOnExit)) { + if (!existsSyncEx(config.openFileOnExit) && !commandExistsSync(config.openFileOnExit)) { throw Error(`\`openFileOnExit\` must be a file path that exists.\nSpecified: "${String(normalizePath(config.openFileOnExit))}"`); } })();