@@ -38,48 +38,60 @@ export class DebugAdapterDescriptorFactory implements IDebugAdapterDescriptorFac
3838 const configuration = session . configuration as LaunchRequestArguments | AttachRequestArguments ;
3939
4040 if ( this . experimentsManager . inExperiment ( DebugAdapterNewPtvsd . experiment ) ) {
41- const isAttach = configuration . request === 'attach' ;
42- const port = configuration . port ?? 0 ;
43- // When processId is provided we may have to inject the debugger into the process.
44- // This is done by the debug adapter, so we need to start it. The adapter will handle injecting the debugger when it receives the attach request.
45- const processId = configuration . processId ?? 0 ;
46-
47- if ( isAttach && processId === 0 ) {
48- if ( port === 0 ) {
49- throw new Error ( 'Port or processId must be specified for request type attach' ) ;
50- } else {
51- return new DebugAdapterServer ( port , configuration . host ) ;
41+ // There are four distinct scenarios here:
42+ //
43+ // 1. "launch";
44+ // 2. "attach" with "processId";
45+ // 3. "attach" with "listen";
46+ // 4. "attach" with "connect" (or legacy "host"/"port");
47+ //
48+ // For the first three, we want to spawn the debug adapter directly.
49+ // For the last one, the adapter is already listening on the specified socket.
50+ // When "debugServer" is used, the standard adapter factory takes care of it - no need to check here.
51+
52+ if ( configuration . request === 'attach' ) {
53+ if ( configuration . connect !== undefined ) {
54+ return new DebugAdapterServer (
55+ configuration . connect . port ,
56+ configuration . connect . host ?? '127.0.0.1'
57+ ) ;
58+ } else if ( configuration . port !== undefined ) {
59+ return new DebugAdapterServer ( configuration . port , configuration . host ?? '127.0.0.1' ) ;
60+ } else if ( configuration . listen === undefined && configuration . processId === undefined ) {
61+ throw new Error ( '"request":"attach" requires either "connect", "listen", or "processId"' ) ;
5262 }
53- } else {
54- const pythonPath = await this . getPythonPath ( configuration , session . workspaceFolder ) ;
55- // If logToFile is set in the debug config then pass --log-dir <path-to-extension-dir> when launching the debug adapter.
63+ }
64+
65+ const pythonPath = await this . getPythonPath ( configuration , session . workspaceFolder ) ;
66+ if ( pythonPath . length !== 0 ) {
67+ if ( configuration . request === 'attach' && configuration . processId !== undefined ) {
68+ sendTelemetryEvent ( EventName . DEBUGGER_ATTACH_TO_LOCAL_PROCESS ) ;
69+ }
70+
71+ // "logToFile" is not handled directly by the adapter - instead, we need to pass
72+ // the corresponding CLI switch when spawning it.
5673 const logArgs = configuration . logToFile ? [ '--log-dir' , EXTENSION_ROOT_DIR ] : [ ] ;
74+
75+ if ( configuration . debugAdapterPath !== undefined ) {
76+ return new DebugAdapterExecutable ( pythonPath , [ configuration . debugAdapterPath , ...logArgs ] ) ;
77+ }
78+
5779 const debuggerPathToUse = path . join ( EXTENSION_ROOT_DIR , 'pythonFiles' , 'lib' , 'python' , 'debugpy' ) ;
5880
59- if ( pythonPath . length !== 0 ) {
60- if ( processId ) {
61- sendTelemetryEvent ( EventName . DEBUGGER_ATTACH_TO_LOCAL_PROCESS ) ;
62- }
63-
64- if ( configuration . debugAdapterPath ) {
65- return new DebugAdapterExecutable ( pythonPath , [ configuration . debugAdapterPath , ...logArgs ] ) ;
66- }
67-
68- if ( await this . useNewDebugger ( pythonPath ) ) {
69- sendTelemetryEvent ( EventName . DEBUG_ADAPTER_USING_WHEELS_PATH , undefined , { usingWheels : true } ) ;
70- return new DebugAdapterExecutable ( pythonPath , [
71- path . join ( debuggerPathToUse , 'wheels' , 'debugpy' , 'adapter' ) ,
72- ...logArgs
73- ] ) ;
74- } else {
75- sendTelemetryEvent ( EventName . DEBUG_ADAPTER_USING_WHEELS_PATH , undefined , {
76- usingWheels : false
77- } ) ;
78- return new DebugAdapterExecutable ( pythonPath , [
79- path . join ( debuggerPathToUse , 'no_wheels' , 'debugpy' , 'adapter' ) ,
80- ...logArgs
81- ] ) ;
82- }
81+ if ( await this . useNewDebugger ( pythonPath ) ) {
82+ sendTelemetryEvent ( EventName . DEBUG_ADAPTER_USING_WHEELS_PATH , undefined , { usingWheels : true } ) ;
83+ return new DebugAdapterExecutable ( pythonPath , [
84+ path . join ( debuggerPathToUse , 'wheels' , 'debugpy' , 'adapter' ) ,
85+ ...logArgs
86+ ] ) ;
87+ } else {
88+ sendTelemetryEvent ( EventName . DEBUG_ADAPTER_USING_WHEELS_PATH , undefined , {
89+ usingWheels : false
90+ } ) ;
91+ return new DebugAdapterExecutable ( pythonPath , [
92+ path . join ( debuggerPathToUse , 'no_wheels' , 'debugpy' , 'adapter' ) ,
93+ ...logArgs
94+ ] ) ;
8395 }
8496 }
8597 } else {
0 commit comments