11import * as path from "path" ;
22import * as util from "util" ;
33import * as vscode from "vscode" ;
4+ import * as child_process from "child_process" ;
5+ import * as fs from "node:fs/promises" ;
46
5- import { LLDBDapOptions } from "./types" ;
7+ export async function isExecutable ( path : string ) : Promise < Boolean > {
8+ try {
9+ await fs . access ( path , fs . constants . X_OK ) ;
10+ } catch {
11+ return false ;
12+ }
13+ return true ;
14+ }
615
7- /**
8- * This class defines a factory used to find the lldb-dap binary to use
9- * depending on the session configuration.
10- */
11- export class LLDBDapDescriptorFactory
12- implements vscode . DebugAdapterDescriptorFactory
13- {
14- static async isValidFile ( pathUri : vscode . Uri ) : Promise < Boolean > {
16+ async function findWithXcrun ( executable : string ) : Promise < string | undefined > {
17+ if ( process . platform === "darwin" ) {
1518 try {
16- const fileStats = await vscode . workspace . fs . stat ( pathUri ) ;
17- if ( ! ( fileStats . type & vscode . FileType . File ) ) {
18- return false ;
19+ const exec = util . promisify ( child_process . execFile ) ;
20+ let { stdout, stderr } = await exec ( "/usr/bin/xcrun" , [
21+ "-find" ,
22+ executable ,
23+ ] ) ;
24+ if ( stdout ) {
25+ return stdout . toString ( ) . trimEnd ( ) ;
1926 }
20- } catch ( err ) {
21- return false ;
22- }
23- return true ;
27+ } catch ( error ) { }
2428 }
29+ return undefined ;
30+ }
2531
26- static async findDAPExecutable ( ) : Promise < string | undefined > {
27- let executable = "lldb-dap" ;
28- if ( process . platform === "win32" ) {
29- executable = "lldb-dap.exe" ;
30- }
32+ async function findInPath ( executable : string ) : Promise < string | undefined > {
33+ const env_path =
34+ process . platform === "win32" ? process . env [ "Path" ] : process . env [ "PATH" ] ;
35+ if ( ! env_path ) {
36+ return undefined ;
37+ }
3138
32- // Prefer lldb-dap from Xcode on Darwin.
33- if ( process . platform === "darwin" ) {
34- try {
35- const exec = util . promisify ( require ( "child_process" ) . execFile ) ;
36- let { stdout, stderr } = await exec ( "/usr/bin/xcrun" , [
37- "-find" ,
38- executable ,
39- ] ) ;
40- if ( stdout ) {
41- return stdout . toString ( ) . trimEnd ( ) ;
42- }
43- } catch ( error ) { }
39+ const paths = env_path . split ( path . delimiter ) ;
40+ for ( const p of paths ) {
41+ const exe_path = path . join ( p , executable ) ;
42+ if ( await isExecutable ( exe_path ) ) {
43+ return exe_path ;
4444 }
45+ }
46+ return undefined ;
47+ }
4548
46- // Find lldb-dap in the user's path.
47- let env_path =
48- process . env [ "PATH" ] ||
49- ( process . platform === "win32" ? process . env [ "Path" ] : null ) ;
50- if ( ! env_path ) {
51- return undefined ;
52- }
49+ async function findDAPExecutable ( ) : Promise < string | undefined > {
50+ const executable = process . platform === "win32" ? "lldb-dap.exe" : "lldb-dap" ;
5351
54- const paths = env_path . split ( path . delimiter ) ;
55- for ( const p of paths ) {
56- const exe_path = path . join ( p , executable ) ;
57- if (
58- await LLDBDapDescriptorFactory . isValidFile ( vscode . Uri . file ( exe_path ) )
59- ) {
60- return exe_path ;
61- }
62- }
52+ // Prefer lldb-dap from Xcode on Darwin.
53+ const xcrun_dap = findWithXcrun ( executable ) ;
54+ if ( xcrun_dap ) {
55+ return xcrun_dap ;
56+ }
6357
64- return undefined ;
58+ // Find lldb-dap in the user's path.
59+ const path_dap = findInPath ( executable ) ;
60+ if ( path_dap ) {
61+ return path_dap ;
6562 }
6663
67- static async getDAPExecutable (
68- session : vscode . DebugSession ,
69- ) : Promise < string | undefined > {
70- const config = vscode . workspace . getConfiguration (
71- "lldb-dap" ,
72- session . workspaceFolder ,
73- ) ;
64+ return undefined ;
65+ }
7466
75- // Prefer the explicitly specified path in the extension's configuration.
76- const configPath = config . get < string > ( "executable-path" ) ;
77- if ( configPath && configPath . length !== 0 ) {
78- return configPath ;
79- }
67+ async function getDAPExecutable (
68+ session : vscode . DebugSession ,
69+ ) : Promise < string | undefined > {
70+ const config = vscode . workspace . getConfiguration (
71+ "lldb-dap" ,
72+ session . workspaceFolder ,
73+ ) ;
8074
81- // Try finding the lldb-dap binary .
82- const foundPath = await LLDBDapDescriptorFactory . findDAPExecutable ( ) ;
83- if ( foundPath ) {
84- return foundPath ;
85- }
75+ // Prefer the explicitly specified path in the extension's configuration .
76+ const configPath = config . get < string > ( "executable-path" ) ;
77+ if ( configPath && configPath . length !== 0 ) {
78+ return configPath ;
79+ }
8680
87- return undefined ;
81+ // Try finding the lldb-dap binary.
82+ const foundPath = await findDAPExecutable ( ) ;
83+ if ( foundPath ) {
84+ return foundPath ;
8885 }
8986
87+ return undefined ;
88+ }
89+
90+ /**
91+ * This class defines a factory used to find the lldb-dap binary to use
92+ * depending on the session configuration.
93+ */
94+ export class LLDBDapDescriptorFactory
95+ implements vscode . DebugAdapterDescriptorFactory
96+ {
9097 async createDebugAdapterDescriptor (
9198 session : vscode . DebugSession ,
9299 executable : vscode . DebugAdapterExecutable | undefined ,
@@ -103,7 +110,7 @@ export class LLDBDapDescriptorFactory
103110 }
104111 const configEnvironment =
105112 config . get < { [ key : string ] : string } > ( "environment" ) || { } ;
106- const dapPath = await LLDBDapDescriptorFactory . getDAPExecutable ( session ) ;
113+ const dapPath = await getDAPExecutable ( session ) ;
107114 const dbgOptions = {
108115 env : {
109116 ...executable ?. options ?. env ,
@@ -112,16 +119,14 @@ export class LLDBDapDescriptorFactory
112119 } ,
113120 } ;
114121 if ( dapPath ) {
115- const fileUri = vscode . Uri . file ( dapPath ) ;
116- if ( ! ( await LLDBDapDescriptorFactory . isValidFile ( fileUri ) ) ) {
117- LLDBDapDescriptorFactory . showLLDBDapNotFoundMessage ( fileUri . path ) ;
122+ if ( ! ( await isExecutable ( dapPath ) ) ) {
123+ LLDBDapDescriptorFactory . showLLDBDapNotFoundMessage ( dapPath ) ;
118124 return undefined ;
119125 }
120126 return new vscode . DebugAdapterExecutable ( dapPath , [ ] , dbgOptions ) ;
121127 } else if ( executable ) {
122- const fileUri = vscode . Uri . file ( executable . command ) ;
123- if ( ! ( await LLDBDapDescriptorFactory . isValidFile ( fileUri ) ) ) {
124- LLDBDapDescriptorFactory . showLLDBDapNotFoundMessage ( fileUri . path ) ;
128+ if ( ! ( await isExecutable ( executable . command ) ) ) {
129+ LLDBDapDescriptorFactory . showLLDBDapNotFoundMessage ( executable . command ) ;
125130 return undefined ;
126131 }
127132 return new vscode . DebugAdapterExecutable (
0 commit comments