| 21 | import { getGlobalFlutterArgs, getToolEnv, runToolProcess, safeToolSpawn } from "../utils/processes"; |
| 22 | |
| 23 | export class FlutterDaemon extends StdIOService<UnknownNotification> implements IFlutterDaemon { |
| 24 | private startTime: Date | undefined; |
| 25 | private get hasStarted() { return !!this.startTime; }; |
| 26 | private hasShownTerminatedError = false; |
| 27 | private hasLoggedDaemonTimeout = false; |
| 28 | private isShuttingDown = false; |
| 29 | private startupReporter: vs.Progress<{ message?: string; increment?: number }> | undefined; |
| 30 | private daemonResponsiveCompleter = new PromiseCompleter<void>(); |
| 31 | private daemonResponsive = this.daemonResponsiveCompleter.promise; |
| 32 | private daemonInitializedCompleter = new PromiseCompleter<void>(); |
| 33 | private daemonInitialized = this.daemonInitializedCompleter.promise; |
| 34 | private pingIntervalId?: NodeJS.Timeout; |
| 35 | public capabilities: DaemonCapabilities = DaemonCapabilities.empty; |
| 36 | private didSpawnWithAdditionalArgs = false; |
| 37 | |
| 38 | constructor(logger: Logger, private readonly analytics: Analytics, private readonly workspaceContext: FlutterWorkspaceContext, flutterCapabilities: FlutterCapabilities, private readonly runIfNoDevices?: () => void, portFromLocalExtension?: number) { |
| 39 | super(new CategoryLogger(logger, LogCategory.FlutterDaemon), config.maxLogLineLength, true, true); |
| 40 | |
| 41 | const folder = workspaceContext.sdks.flutter; |
| 42 | |
| 43 | this.registerForDaemonConnected((e) => { |
| 44 | this.additionalPidsToTerminate.push(e.pid); |
| 45 | this.capabilities.version = e.version; |
| 46 | void vs.commands.executeCommand("setContext", FLUTTER_SUPPORTS_ATTACH, this.capabilities.canFlutterAttach); |
| 47 | |
| 48 | // Delay marking as initialized for a few seconds to see whether it helps prevent |
| 49 | // the first emulator requests from hanging. |
| 50 | // https://github.com/Dart-Code/Dart-Code/issues/5793 |
| 51 | const completer = this.daemonInitializedCompleter; |
| 52 | const markInitializedAfterDelay = () => setTimeout(() => completer.resolve(), 2000); |
| 53 | void this.deviceEnable().then(markInitializedAfterDelay, markInitializedAfterDelay); |
| 54 | }); |
| 55 | |
| 56 | const daemonArgs = []; |
| 57 | |
| 58 | const showWebServer = config.flutterShowWebServerDevice === "always" || !isRunningLocally; |
| 59 | if (showWebServer) |
| 60 | daemonArgs.push("--show-web-server-device"); |
| 61 | |
| 62 | if (isDartCodeTestRun) |
| 63 | daemonArgs.push("--show-test-device"); |
| 64 | |
| 65 | if (portFromLocalExtension) { |
| 66 | this.createNcProcess(portFromLocalExtension); |
| 67 | this.startPing(); |
| 68 | } else if (workspaceContext.config.forceFlutterWorkspace && config.daemonPort) { |
| 69 | this.createNcProcess(config.daemonPort); |
| 70 | this.startPing(workspaceContext.config.restartMacDaemonMessage); |
| 71 | } else { |
| 72 | const execution = usingCustomScript( |
| 73 | path.join(workspaceContext.sdks.flutter, flutterPath), |
| 74 | ["daemon"].concat(daemonArgs), |
| 75 | workspaceContext.config?.flutterDaemonScript, |
| 76 | ); |
| 77 | |
| 78 | const flutterAdditionalArgs = config.for(vs.Uri.file(folder)).flutterAdditionalArgs; |
| 79 | this.didSpawnWithAdditionalArgs = !!flutterAdditionalArgs.length; |
| 80 | const args = getGlobalFlutterArgs().concat(flutterAdditionalArgs).concat(execution.args); |
nothing calls this directly
no outgoing calls
no test coverage detected