microsoft/vscode-react-native

Public

mirrored fromhttps://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
866e020b2c664db8b8c5bf972901bc2fc25ddd93

Branches

Tags

  • No tags available.
0Branches0Tags
Go to file
Add file
Code

Clone

HTTPS

Download ZIP

src/extension/debuggingConfiguration/reactNativeDebugDynamicConfigProvider.ts

175lines · modecode

1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import * as vscode from "vscode";
5import {
6 debugConfigurations,
7 DEBUG_CONFIGURATION_NAMES,
8 DebugScenarioType,
9 DebugConfigurationState,
10} from "./debugConfigTypesAndConstants";
11import { SettingsHelper } from "../settingsHelper";
12import { TelemetryHelper } from "../../common/telemetryHelper";
13import { Telemetry } from "../../common/telemetry";
14import { ProjectVersionHelper } from "../../common/projectVersionHelper";
15import { ReactNativeProjectHelper } from "../../common/reactNativeProjectHelper";
16import { PlatformType } from "../launchArgs";
17import { MultiStepInput, InputStep } from "./multiStepInput";
18import { ILaunchRequestArgs } from "../../debugger/debugSessionBase";
19import { ConfigurationProviderHelper } from "../../common/configurationProviderHelper";
20
21export class ReactNativeDebugDynamicConfigProvider implements vscode.DebugConfigurationProvider {
22 public async provideDebugConfigurations(
23 folder: vscode.WorkspaceFolder | undefined,
24 token?: vscode.CancellationToken, // eslint-disable-line @typescript-eslint/no-unused-vars
25 ): Promise<vscode.DebugConfiguration[]> {
26 let debugConfigurationsToShow = Object.assign({}, debugConfigurations);
27
28 if (folder) {
29 let rootPath = folder.uri.fsPath;
30 let projectRootPath = SettingsHelper.getReactNativeProjectRoot(rootPath);
31 const versions = await ProjectVersionHelper.tryToGetRNSemverValidVersionsFromProjectPackage(
32 projectRootPath,
33 ProjectVersionHelper.generateAllAdditionalPackages(),
34 projectRootPath,
35 );
36
37 let macOSHermesEnabled = false;
38 let windowsHermesEnabled = false;
39 let androidHermesEnabled = ReactNativeProjectHelper.isAndroidHermesEnabled(rootPath);
40 let iOSHermesEnabled = ReactNativeProjectHelper.isIOSHermesEnabled(rootPath);
41
42 if (ProjectVersionHelper.isVersionError(versions.reactNativeWindowsVersion)) {
43 delete debugConfigurationsToShow[DEBUG_CONFIGURATION_NAMES.DEBUG_WINDOWS];
44 delete debugConfigurationsToShow[
45 DEBUG_CONFIGURATION_NAMES.DEBUG_WINDOWS_HERMES_EXPERIMENTAL
46 ];
47 } else {
48 windowsHermesEnabled = ReactNativeProjectHelper.isWindowsHermesEnabled(rootPath);
49 if (!windowsHermesEnabled) {
50 delete debugConfigurationsToShow[
51 DEBUG_CONFIGURATION_NAMES.DEBUG_WINDOWS_HERMES_EXPERIMENTAL
52 ];
53 }
54 }
55
56 if (ProjectVersionHelper.isVersionError(versions.reactNativeMacOSVersion)) {
57 delete debugConfigurationsToShow[DEBUG_CONFIGURATION_NAMES.DEBUG_MACOS];
58 delete debugConfigurationsToShow[
59 DEBUG_CONFIGURATION_NAMES.DEBUG_MACOS_HERMES_EXPERIMENTAL
60 ];
61 } else {
62 macOSHermesEnabled = ReactNativeProjectHelper.isMacOSHermesEnabled(rootPath);
63 if (!macOSHermesEnabled) {
64 delete debugConfigurationsToShow[
65 DEBUG_CONFIGURATION_NAMES.DEBUG_MACOS_HERMES_EXPERIMENTAL
66 ];
67 }
68 }
69
70 if (!androidHermesEnabled) {
71 delete debugConfigurationsToShow[
72 DEBUG_CONFIGURATION_NAMES.DEBUG_ANDROID_HERMES_EXPERIMENTAL
73 ];
74 delete debugConfigurationsToShow[
75 DEBUG_CONFIGURATION_NAMES.RUN_ANDROID_HERMES_EXPERIMENTAL
76 ];
77 }
78
79 if (!iOSHermesEnabled) {
80 delete debugConfigurationsToShow[
81 DEBUG_CONFIGURATION_NAMES.DEBUG_IOS_HERMES_EXPERIMENTAL
82 ];
83 delete debugConfigurationsToShow[
84 DEBUG_CONFIGURATION_NAMES.RUN_IOS_HERMES_EXPERIMENTAL
85 ];
86 }
87
88 if (
89 !androidHermesEnabled &&
90 !iOSHermesEnabled &&
91 !macOSHermesEnabled &&
92 !windowsHermesEnabled
93 ) {
94 delete debugConfigurationsToShow[
95 DEBUG_CONFIGURATION_NAMES.ATTACH_TO_HERMES_APPLICATION_EXPERIMENTAL
96 ];
97 }
98 }
99
100 const debugConfigurationsToShowList = Object.values(debugConfigurationsToShow);
101 debugConfigurationsToShowList.forEach(config => {
102 config.isDynamic = true;
103 });
104
105 return debugConfigurationsToShowList;
106 }
107
108 public async resolveDebugConfiguration(
109 folder: vscode.WorkspaceFolder | undefined,
110 config: vscode.DebugConfiguration,
111 token?: vscode.CancellationToken,
112 ): Promise<vscode.ProviderResult<vscode.DebugConfiguration>> {
113 if (config.isDynamic) {
114 const chosenConfigsEvent = TelemetryHelper.createTelemetryEvent(
115 "chosenDynamicDebugConfiguration",
116 {
117 selectedConfiguration: config.name,
118 },
119 );
120 Telemetry.send(chosenConfigsEvent);
121 if (config.request === "attach") {
122 await this.configureAttachScenario(folder, config, token);
123 }
124 if (config.platform === PlatformType.Exponent) {
125 await this.configureExpoScenario(folder, config, token);
126 }
127 }
128
129 return config;
130 }
131
132 private async configureExpoScenario(
133 folder: vscode.WorkspaceFolder | undefined,
134 config: vscode.DebugConfiguration,
135 token?: vscode.CancellationToken,
136 ): Promise<vscode.DebugConfiguration> {
137 const state = { config, scenarioType: DebugScenarioType.DebugApp, folder, token };
138 const picker = new MultiStepInput<DebugConfigurationState>();
139 const configurationProviderHelper = new ConfigurationProviderHelper();
140 await picker.run(async (input, s) => {
141 await configurationProviderHelper.selectExpoHostType(input, s.config, 1, 1);
142 }, state);
143
144 return config;
145 }
146
147 private async configureAttachScenario(
148 folder: vscode.WorkspaceFolder | undefined,
149 config: vscode.DebugConfiguration,
150 token?: vscode.CancellationToken,
151 ): Promise<vscode.DebugConfiguration> {
152 const state = { config, scenarioType: DebugScenarioType.AttachApp, folder, token };
153 const picker = new MultiStepInput<DebugConfigurationState>();
154 const configurationProviderHelper = new ConfigurationProviderHelper();
155
156 const configurePort = async (
157 input: MultiStepInput<DebugConfigurationState>,
158 config: Partial<ILaunchRequestArgs>,
159 ): Promise<InputStep<DebugConfigurationState> | void> => {
160 await configurationProviderHelper.configurePort(input, config, 2, 2);
161 };
162
163 const configureAddress = async (
164 input: MultiStepInput<DebugConfigurationState>,
165 config: Partial<ILaunchRequestArgs>,
166 ): Promise<InputStep<DebugConfigurationState> | void> => {
167 await configurationProviderHelper.configureAddress(input, config, 1, 2, "localhost");
168 return () => configurePort(input, config);
169 };
170
171 await picker.run((input, s) => configureAddress(input, s.config), state);
172
173 return config;
174 }
175}
176