microsoft/vscode-react-native

Public

mirrored from https://github.com/microsoft/vscode-react-nativeAvailable

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.11.2

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/debuggingConfiguration/reactNativeDebugConfigProvider.ts

280lines · 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 * as nls from "vscode-nls";
6import { TelemetryHelper } from "../../common/telemetryHelper";
7import { Telemetry } from "../../common/telemetry";
8import { ILaunchRequestArgs } from "../../debugger/debugSessionBase";
9import {
10 debugConfigurations,
11 DEBUG_CONFIGURATION_NAMES,
12 DEBUG_TYPES,
13 DebugScenarioType,
14 DebugConfigurationQuickPickItem,
15 DebugConfigurationState,
16} from "./debugConfigTypesAndConstants";
17import { DebugScenarioNameGenerator } from "./debugScenarioNameGenerator";
18
19import { MultiStepInput, IMultiStepInput, InputStep, IQuickPickParameters } from "./multiStepInput";
20import { ConfigProviderFactory } from "./configurationProviders/configProviderFactory";
21
22nls.config({
23 messageFormat: nls.MessageFormat.bundle,
24 bundleFormat: nls.BundleFormat.standalone,
25})();
26const localize = nls.loadMessageBundle();
27
28export class ReactNativeDebugConfigProvider implements vscode.DebugConfigurationProvider {
29 private initialPickConfig: ReadonlyArray<vscode.QuickPickItem> = [
30 {
31 label: DEBUG_CONFIGURATION_NAMES.DEBUG_ANDROID,
32 description: localize("DebugAndroidConfigDesc", "Run and debug Android application"),
33 },
34 {
35 label: DEBUG_CONFIGURATION_NAMES.RUN_ANDROID,
36 description: localize("RunAndroidConfigDesc", "Run Android application"),
37 },
38 {
39 label: DEBUG_CONFIGURATION_NAMES.DEBUG_IOS,
40 description: localize("DebugiOSConfigDesc", "Run and debug iOS application"),
41 },
42 {
43 label: DEBUG_CONFIGURATION_NAMES.RUN_IOS,
44 description: localize("RuniOSConfigDesc", "Run iOS application"),
45 },
46 {
47 label: DEBUG_CONFIGURATION_NAMES.DEBUG_WINDOWS,
48 description: localize("DebugWindowsConfigDesc", "Run and debug Windows application"),
49 },
50 {
51 label: DEBUG_CONFIGURATION_NAMES.DEBUG_MACOS,
52 description: localize("DebugmacOSConfigDesc", "Run and debug macOS application"),
53 },
54 {
55 label: DEBUG_CONFIGURATION_NAMES.ATTACH_TO_PACKAGER,
56 description: localize(
57 "AttachToPackagerConfigDesc",
58 "Attach to already working application packager",
59 ),
60 },
61 {
62 label: DEBUG_CONFIGURATION_NAMES.DEBUG_IN_EXPONENT,
63 description: localize(
64 "DebugExpoConfigDesc",
65 "Debug Expo application or React Native application in Expo",
66 ),
67 },
68 {
69 label: DEBUG_CONFIGURATION_NAMES.DEBUG_IN_EXPONENT_HERMES_EXPERIMENTAL,
70 description: localize(
71 "DebugHermesExpoConfigDesc",
72 "Debug Hermes Expo application or React Native application in Expo",
73 ),
74 },
75 {
76 label: DEBUG_CONFIGURATION_NAMES.DEBUG_ANDROID_HERMES,
77 description: localize(
78 "DebugAndroidHermesConfigDesc",
79 "Run and debug Android Hermes application",
80 ),
81 },
82 {
83 label: DEBUG_CONFIGURATION_NAMES.RUN_ANDROID_HERMES,
84 description: localize("RunAndroidHermesConfigDesc", "Run Android Hermes application"),
85 },
86 {
87 label: DEBUG_CONFIGURATION_NAMES.DEBUG_IOS_HERMES,
88 description: localize(
89 "DebugIosHermesConfigDesc",
90 "Run and debug iOS Hermes application",
91 ),
92 },
93 {
94 label: DEBUG_CONFIGURATION_NAMES.RUN_IOS_HERMES,
95 description: localize("RunIosHermesConfigDesc", "Run iOS Hermes application"),
96 },
97 {
98 label: DEBUG_CONFIGURATION_NAMES.DEBUG_MACOS_HERMES_EXPERIMENTAL,
99 description: localize(
100 "DebugMacOSHermesConfigDesc",
101 "Run and debug macOS Hermes application",
102 ),
103 },
104 {
105 label: DEBUG_CONFIGURATION_NAMES.DEBUG_WINDOWS_HERMES_EXPERIMENTAL,
106 description: localize(
107 "DebugWindowsHermesConfigDesc",
108 "Run and debug Windows Hermes application",
109 ),
110 },
111 {
112 label: DEBUG_CONFIGURATION_NAMES.ATTACH_TO_HERMES_APPLICATION,
113 description: localize(
114 "AttachToPackagerHermesConfigDesc",
115 "Attach to already working React Native Hermes application on Android directly",
116 ),
117 },
118 {
119 label: DEBUG_CONFIGURATION_NAMES.DEBUG_DIRECT_IOS_EXPERIMENTAL,
120 description: localize(
121 "DebugDirectiOSConfigDesc",
122 "Run and debug iOS application directly",
123 ),
124 },
125 {
126 label: DEBUG_CONFIGURATION_NAMES.RUN_DIRECT_IOS_EXPERIMENTAL,
127 description: localize(
128 "RunDirectiOSConfigDesc",
129 "Run iOS application with direct debugging support",
130 ),
131 },
132 {
133 label: DEBUG_CONFIGURATION_NAMES.ATTACH_TO_DIRECT_IOS_EXPERIMENTAL,
134 description: localize(
135 "AttachToPackageriOSConfigDesc",
136 "Attach to already working React Native iOS application directly",
137 ),
138 },
139 ];
140
141 private sequentialPickConfig: ReadonlyArray<DebugConfigurationQuickPickItem> = [
142 {
143 label: "Run application",
144 description: localize(
145 "RunApplicationScenario",
146 "Run React Native application without debugging",
147 ),
148 type: DebugScenarioType.RunApp,
149 },
150 {
151 label: "Debug application",
152 description: localize("DebugApplicationScenario", "Debug React Native application"),
153 type: DebugScenarioType.DebugApp,
154 },
155 {
156 label: "Attach to application",
157 description: localize(
158 "AttachApplicationScenario",
159 "Attach to running React Native application",
160 ),
161 type: DebugScenarioType.AttachApp,
162 },
163 ];
164
165 public async provideDebugConfigurations(
166 folder: vscode.WorkspaceFolder | undefined, // eslint-disable-line @typescript-eslint/no-unused-vars
167 token?: vscode.CancellationToken, // eslint-disable-line @typescript-eslint/no-unused-vars
168 ): Promise<vscode.DebugConfiguration[]> {
169 return new Promise<vscode.DebugConfiguration[]>(resolve => {
170 const configPicker = this.prepareDebugConfigPicker();
171 const disposables: vscode.Disposable[] = [];
172 const pickHandler = () => {
173 const chosenConfigsEvent = TelemetryHelper.createTelemetryEvent(
174 "chosenDebugConfigurations",
175 );
176 const selected: string[] = configPicker.selectedItems.map(element => element.label);
177 chosenConfigsEvent.properties.selectedItems = selected;
178 Telemetry.send(chosenConfigsEvent);
179 const launchConfig = this.gatherDebugScenarios(selected);
180 disposables.forEach(d => d.dispose());
181 resolve(launchConfig);
182 };
183
184 disposables.push(
185 configPicker.onDidAccept(pickHandler),
186 configPicker.onDidHide(pickHandler),
187 configPicker,
188 );
189
190 configPicker.show();
191 });
192 }
193
194 public async provideDebugConfigurationSequentially(
195 folder: vscode.WorkspaceFolder | undefined,
196 token?: vscode.CancellationToken,
197 ): Promise<vscode.DebugConfiguration | undefined> {
198 const config: Partial<ILaunchRequestArgs> = {};
199 const state = { config, scenarioType: DebugScenarioType.DebugApp, folder, token };
200
201 const multiStep = new MultiStepInput<DebugConfigurationState>();
202 await multiStep.run((input, s) => this.pickDebugConfiguration(input, s), state);
203
204 if (Object.keys(state.config).length === 0) {
205 return;
206 }
207 if (state.config.type === DEBUG_TYPES.REACT_NATIVE_DIRECT) {
208 if (
209 state.config.platform === "android" ||
210 (state.config.platform === "ios" &&
211 state.config.target !== "device" &&
212 state.config.request !== "attach")
213 ) {
214 state.config.name = DebugScenarioNameGenerator.createScenarioName(
215 state.scenarioType,
216 state.config.type,
217 state.config.platform,
218 state.config.useHermesEngine !== false,
219 );
220 } else {
221 state.config.name = DebugScenarioNameGenerator.createScenarioName(
222 state.scenarioType,
223 state.config.type,
224 state.config.platform,
225 state.config.useHermesEngine !== false,
226 true,
227 );
228 }
229 } else {
230 state.config.name = DebugScenarioNameGenerator.createScenarioName(
231 state.scenarioType,
232 state.config.type || DEBUG_TYPES.REACT_NATIVE,
233 state.config.platform,
234 );
235 }
236 return state.config as vscode.DebugConfiguration;
237 }
238
239 private async pickDebugConfiguration(
240 input: IMultiStepInput<DebugConfigurationState>,
241 state: DebugConfigurationState,
242 ): Promise<InputStep<DebugConfigurationState> | void> {
243 state.config = {};
244 const pick = await input.showQuickPick<
245 DebugConfigurationQuickPickItem,
246 IQuickPickParameters<DebugConfigurationQuickPickItem>
247 >({
248 title: localize("DebugConfigQuickPickSequentialLabel", "Select a debug configuration"),
249 placeholder: "Debug Configuration",
250 activeItem: this.sequentialPickConfig[0],
251 items: this.sequentialPickConfig,
252 });
253 if (pick) {
254 const provider = ConfigProviderFactory.create(pick.type);
255 return provider.buildConfiguration.bind(provider);
256 }
257 }
258
259 private gatherDebugScenarios(selectedItems: string[]): vscode.DebugConfiguration[] {
260 const launchConfig: vscode.DebugConfiguration[] = selectedItems.map(
261 element => debugConfigurations[element],
262 );
263 return launchConfig;
264 }
265
266 private prepareDebugConfigPicker(): vscode.QuickPick<vscode.QuickPickItem> {
267 const debugConfigPicker = vscode.window.createQuickPick();
268 debugConfigPicker.canSelectMany = true;
269 debugConfigPicker.ignoreFocusOut = true;
270 debugConfigPicker.title = localize(
271 "DebugConfigQuickPickLabel",
272 "Pick debug configurations",
273 );
274 debugConfigPicker.items = this.initialPickConfig;
275 // QuickPickItem property `picked` doesn't work, so this line will check first item in the list
276 // which is supposed to be Debug Android
277 debugConfigPicker.selectedItems = [this.initialPickConfig[0]];
278 return debugConfigPicker;
279 }
280}
281