Skip to content

Commit 0b65a03

Browse files
committed
Switch debug adapters to run back out-of-process
Fixes #1876.
1 parent 9a83f1c commit 0b65a03

3 files changed

Lines changed: 38 additions & 70 deletions

File tree

‎src/extension/extension.ts‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,7 @@ import { DartReferenceProvider } from "./providers/dart_reference_provider";
7272
import { DartRenameProvider } from "./providers/dart_rename_provider";
7373
import { DartSignatureHelpProvider } from "./providers/dart_signature_help_provider";
7474
import { DartWorkspaceSymbolProvider } from "./providers/dart_workspace_symbol_provider";
75+
import { DartDebugAdapterDescriptorFactory } from "./providers/debug_adapter_descriptor_factory";
7576
import { DebugConfigProvider, DynamicDebugConfigProvider, InitialLaunchJsonDebugConfigProvider } from "./providers/debug_config_provider";
7677
import { FixCodeActionProvider } from "./providers/fix_code_action_provider";
7778
import { IgnoreLintCodeActionProvider } from "./providers/ignore_lint_code_action_provider";
@@ -403,7 +404,7 @@ export async function activate(context: vs.ExtensionContext, isRestart: boolean
403404
// Set up debug stuff.
404405
const debugProvider = new DebugConfigProvider(logger, workspaceContext, analytics, pubGlobal, flutterDaemon, deviceManager, dartCapabilities, flutterCapabilities);
405406
context.subscriptions.push(vs.debug.registerDebugConfigurationProvider("dart", debugProvider));
406-
context.subscriptions.push(debugProvider);
407+
context.subscriptions.push(vs.debug.registerDebugAdapterDescriptorFactory("dart", new DartDebugAdapterDescriptorFactory(context)));
407408
// Also the providers for the initial configs.
408409
context.subscriptions.push(vs.debug.registerDebugConfigurationProvider("dart", new InitialLaunchJsonDebugConfigProvider(), vs.DebugConfigurationProviderTriggerKind.Initial));
409410
context.subscriptions.push(vs.debug.registerDebugConfigurationProvider("dart", new DynamicDebugConfigProvider(), vs.DebugConfigurationProviderTriggerKind.Dynamic));
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
import { DebugAdapterDescriptor, DebugAdapterDescriptorFactory, DebugAdapterExecutable, DebugSession, ExtensionContext } from "vscode";
2+
import { DebuggerType } from "../../shared/enums";
3+
4+
export class DartDebugAdapterDescriptorFactory implements DebugAdapterDescriptorFactory {
5+
constructor(private readonly extensionContext: ExtensionContext) { }
6+
7+
public createDebugAdapterDescriptor(session: DebugSession, executable: DebugAdapterExecutable | undefined): DebugAdapterDescriptor {
8+
let debuggerScript: string;
9+
switch (session.configuration.debuggerType) {
10+
case DebuggerType.Flutter:
11+
debuggerScript = "flutter_debug_entry";
12+
break;
13+
case DebuggerType.FlutterTest:
14+
debuggerScript = "flutter_test_debug_entry";
15+
break;
16+
case DebuggerType.Web:
17+
debuggerScript = "web_debug_entry";
18+
break;
19+
case DebuggerType.WebTest:
20+
debuggerScript = "web_test_debug_entry"
21+
break;
22+
case DebuggerType.Dart:
23+
debuggerScript = "dart_debug_entry";
24+
break;
25+
case DebuggerType.PubTest:
26+
debuggerScript = "dart_test_debug_entry";
27+
break;
28+
default:
29+
throw new Error("Unknown debugger type");
30+
}
31+
32+
const scriptPath = this.extensionContext.asAbsolutePath(`./out/src/debug/${debuggerScript}.js`);
33+
const args = [scriptPath];
34+
return new DebugAdapterExecutable("node", args);
35+
}
36+
}

‎src/extension/providers/debug_config_provider.ts‎

Lines changed: 0 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,8 @@
11
import * as fs from "fs";
2-
import * as net from "net";
32
import * as path from "path";
43
import * as vs from "vscode";
54
import { CancellationToken, DebugConfiguration, DebugConfigurationProvider, ProviderResult, Uri, window, workspace, WorkspaceFolder } from "vscode";
6-
import { DebugSession } from "vscode-debugadapter";
7-
import { DartDebugSession } from "../../debug/dart_debug_impl";
8-
import { DartTestDebugSession } from "../../debug/dart_test_debug_impl";
9-
import { FlutterDebugSession } from "../../debug/flutter_debug_impl";
10-
import { FlutterTestDebugSession } from "../../debug/flutter_test_debug_impl";
115
import { FlutterLaunchRequestArguments } from "../../debug/utils";
12-
import { WebDebugSession } from "../../debug/web_debug_impl";
13-
import { WebTestDebugSession } from "../../debug/web_test_debug_impl";
146
import { DartCapabilities } from "../../shared/capabilities/dart";
157
import { FlutterCapabilities } from "../../shared/capabilities/flutter";
168
import { CHROME_OS_VM_SERVICE_PORT, dartVMPath, debugAnywayAction, flutterPath, HAS_LAST_DEBUG_CONFIG, HAS_LAST_TEST_DEBUG_CONFIG, isChromeOS, pubPath, pubSnapshotPath, showErrorsAction } from "../../shared/constants";
@@ -36,8 +28,6 @@ import { TestResultsProvider } from "../views/test_view";
3628
const isCI = !!process.env.CI;
3729

3830
export class DebugConfigProvider implements DebugConfigurationProvider {
39-
private debugServers: { [index: string]: net.Server } = {};
40-
4131
constructor(private readonly logger: Logger, private readonly wsContext: WorkspaceContext, private readonly analytics: Analytics, private readonly pubGlobal: PubGlobal, private readonly daemon: IFlutterDaemon, private readonly deviceManager: FlutterDeviceManager, private dartCapabilities: DartCapabilities, private readonly flutterCapabilities: FlutterCapabilities) { }
4232

4333
public resolveDebugConfiguration(folder: WorkspaceFolder | undefined, debugConfig: DebugConfiguration, token?: CancellationToken): ProviderResult<DebugConfiguration> {
@@ -349,22 +339,6 @@ export class DebugConfigProvider implements DebugConfigurationProvider {
349339
if (!didWarnAboutCwd && debugConfig.program && path.isAbsolute(debugConfig.program))
350340
warnIfPathCaseMismatch(logger, debugConfig.program, "the launch script", "check the 'program' field in your launch configuration file (.vscode/launch.json)");
351341

352-
// Start port listener on launch of first debug session.
353-
const debugServer = this.getDebugServer(debugType, debugConfig.debugServer);
354-
const serverAddress = debugServer.address();
355-
356-
// Updated node bindings say address can be a string (used for pipes) but
357-
// this should never be the case here. This check is to keep the types happy.
358-
if (!serverAddress || typeof serverAddress === "string") {
359-
logger.info("Debug server does not have a valid address");
360-
window.showErrorMessage("Debug server does not have a valid address");
361-
return undefined;
362-
}
363-
364-
// Make VS Code connect to debug server instead of launching debug adapter.
365-
// TODO: Why do we need this cast? The node-mock-debug does not?
366-
(debugConfig as any).debugServer = serverAddress.port;
367-
368342
this.analytics.logDebuggerStart(folder && folder.uri, DebuggerType[debugType], debugConfig.noDebug ? "Run" : "Debug");
369343
if (debugType === DebuggerType.FlutterTest /*|| debugType === DebuggerType.WebTest*/ || debugType === DebuggerType.PubTest) {
370344
TestResultsProvider.flagSuiteStart(debugConfig.program, !argsHaveTestNameFilter);
@@ -444,40 +418,6 @@ export class DebugConfigProvider implements DebugConfigurationProvider {
444418
return vmServiceUriOrPort;
445419
}
446420

447-
private getDebugServer(debugType: DebuggerType, port?: number) {
448-
switch (debugType) {
449-
case DebuggerType.Flutter:
450-
return this.spawnOrGetServer("flutter", port, () => new FlutterDebugSession());
451-
case DebuggerType.FlutterTest:
452-
return this.spawnOrGetServer("flutterTest", port, () => new FlutterTestDebugSession());
453-
case DebuggerType.Web:
454-
return this.spawnOrGetServer("web", port, () => new WebDebugSession());
455-
case DebuggerType.WebTest:
456-
return this.spawnOrGetServer("pubTest", port, () => new WebTestDebugSession());
457-
case DebuggerType.Dart:
458-
return this.spawnOrGetServer("dart", port, () => new DartDebugSession());
459-
case DebuggerType.PubTest:
460-
return this.spawnOrGetServer("pubTest", port, () => new DartTestDebugSession());
461-
default:
462-
throw new Error("Unknown debugger type");
463-
}
464-
}
465-
466-
private spawnOrGetServer(type: string, port: number = 0, create: () => DebugSession): net.Server {
467-
// Start port listener on launch of first debug session.
468-
if (!this.debugServers[type]) {
469-
this.logger.info(`Spawning a new ${type} debugger`);
470-
// Start listening on a random port.
471-
this.debugServers[type] = net.createServer((socket) => {
472-
const session = create();
473-
session.setRunAsServer(true);
474-
session.start(socket as NodeJS.ReadableStream, socket);
475-
}).listen(port);
476-
}
477-
478-
return this.debugServers[type];
479-
}
480-
481421
private setupDebugConfig(folder: WorkspaceFolder | undefined, debugConfig: FlutterLaunchRequestArguments, isFlutter: boolean, device: Device | undefined, deviceManager: FlutterDeviceManager) {
482422
const conf = config.for(folder && folder.uri);
483423

@@ -551,15 +491,6 @@ export class DebugConfigProvider implements DebugConfigurationProvider {
551491
? logPath.replace(/\${name}/, filenameSafe(args.name || "unnamed-session"))
552492
: logPath;
553493
}
554-
555-
public dispose() {
556-
if (this.debugServers) {
557-
for (const type of Object.keys(this.debugServers)) {
558-
this.debugServers[type].close();
559-
delete this.debugServers[type];
560-
}
561-
}
562-
}
563494
}
564495

565496
export class InitialLaunchJsonDebugConfigProvider implements DebugConfigurationProvider {

0 commit comments

Comments
 (0)