microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
e3706a1c594018c079d800618749f03e6b169667

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/debugger/direct/directDebugAdapter.ts

208lines · 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 path from "path";
5import { ProjectVersionHelper } from "../../common/projectVersionHelper";
6import { ReactNativeProjectHelper } from "../../common/reactNativeProjectHelper";
7import { ErrorHelper } from "../../common/error/errorHelper";
8import { getExtensionVersion } from "../../common/extensionHelper";
9import { ILaunchArgs } from "../../extension/launchArgs";
10import { getProjectRoot } from "../nodeDebugWrapper";
11import { Telemetry } from "../../common/telemetry";
12import { OutputEvent, Logger } from "vscode-debugadapter";
13import { TelemetryHelper } from "../../common/telemetryHelper";
14import { RemoteTelemetryReporter } from "../../common/telemetryReporters";
15import { ChromeDebugAdapter, ChromeDebugSession, IChromeDebugSessionOpts, IAttachRequestArgs, logger } from "vscode-chrome-debug-core";
16import { InternalErrorCode } from "../../common/error/internalErrorCode";
17import { RemoteExtension } from "../../common/remoteExtension";
18import { DebugProtocol } from "vscode-debugprotocol";
19import { getLoggingDirectory } from "../../extension/log/LogHelper";
20import * as nls from "vscode-nls";
21import * as Q from "q";
22const localize = nls.loadMessageBundle();
23
24export interface IDirectAttachRequestArgs extends IAttachRequestArgs, ILaunchArgs {
25 cwd: string; /* Automatically set by VS Code to the currently opened folder */
26}
27
28export interface IDirectLaunchRequestArgs extends DebugProtocol.LaunchRequestArguments, IDirectAttachRequestArgs { }
29
30export class DirectDebugAdapter extends ChromeDebugAdapter {
31
32 private outputLogger: (message: string, error?: boolean | string) => void;
33 private projectRootPath: string;
34 private remoteExtension: RemoteExtension;
35 private isSettingsInitialized: boolean; // used to prevent parameters reinitialization when attach is called from launch function
36 private previousAttachArgs: IDirectAttachRequestArgs;
37
38 public constructor(opts: IChromeDebugSessionOpts, debugSession: ChromeDebugSession) {
39 super(opts, debugSession);
40 this.outputLogger = (message: string, error?: boolean | string) => {
41 let category = "console";
42 if (error === true) {
43 category = "stderr";
44 }
45 if (typeof error === "string") {
46 category = error;
47 }
48
49 let newLine = "\n";
50 if (category === "stdout" || category === "stderr") {
51 newLine = "";
52 }
53 debugSession.sendEvent(new OutputEvent(message + newLine, category));
54 };
55
56 this.isSettingsInitialized = false;
57 }
58
59 public launch(launchArgs: IDirectLaunchRequestArgs): Promise<void> {
60 let extProps = {
61 platform: {
62 value: launchArgs.platform,
63 isPii: false,
64 },
65 isDirect: {
66 value: true,
67 isPii: false,
68 },
69 };
70
71 return new Promise<void>((resolve, reject) => this.initializeSettings(launchArgs)
72 .then(() => {
73 this.outputLogger("Launching the application");
74 logger.verbose(`Launching the application: ${JSON.stringify(launchArgs, null , 2)}`);
75 return ProjectVersionHelper.getReactNativeVersions(launchArgs.cwd, launchArgs.platform === "windows")
76 .then(versions => {
77 extProps = TelemetryHelper.addPropertyToTelemetryProperties(versions.reactNativeVersion, "reactNativeVersion", extProps);
78 if (launchArgs.platform === "windows") {
79 extProps = TelemetryHelper.addPropertyToTelemetryProperties(versions.reactNativeWindowsVersion, "reactNativeWindowsVersion", extProps);
80 }
81 return TelemetryHelper.generate("launch", extProps, (generator) => {
82 return this.remoteExtension.launch({ "arguments": launchArgs })
83 .then(() => {
84 return this.remoteExtension.getPackagerPort(launchArgs.cwd);
85 })
86 .then((packagerPort: number) => {
87 launchArgs.port = launchArgs.port || packagerPort;
88 this.attach(launchArgs).then(() => {
89 resolve();
90 }).catch((e) => reject(e));
91 }).catch((e) => reject(e));
92 })
93 .catch((err) => {
94 this.outputLogger("An error occurred while launching the application. " + err.message || err, true);
95 this.cleanUp();
96 reject(err);
97 });
98 });
99 }));
100 }
101
102 public attach(attachArgs: IDirectAttachRequestArgs): Promise<void> {
103 let extProps = {
104 platform: {
105 value: attachArgs.platform,
106 isPii: false,
107 },
108 isDirect: {
109 value: true,
110 isPii: false,
111 },
112 };
113
114 this.previousAttachArgs = attachArgs;
115
116 return new Promise<void>((resolve, reject) => this.initializeSettings(attachArgs)
117 .then(() => {
118 this.outputLogger("Attaching to the application");
119 logger.verbose(`Attaching to the application: ${JSON.stringify(attachArgs, null , 2)}`);
120 return ProjectVersionHelper.getReactNativeVersions(attachArgs.cwd, true)
121 .then(versions => {
122 extProps = TelemetryHelper.addPropertyToTelemetryProperties(versions.reactNativeVersion, "reactNativeVersion", extProps);
123 if (!ProjectVersionHelper.isVersionError(versions.reactNativeWindowsVersion)) {
124 extProps = TelemetryHelper.addPropertyToTelemetryProperties(versions.reactNativeWindowsVersion, "reactNativeWindowsVersion", extProps);
125 }
126 return TelemetryHelper.generate("attach", extProps, (generator) => {
127 return this.remoteExtension.getPackagerPort(attachArgs.cwd)
128 .then((packagerPort: number) => {
129 attachArgs.port = attachArgs.port || packagerPort;
130 this.outputLogger(`Connecting to ${attachArgs.port} port`);
131 const attachArguments = Object.assign({}, attachArgs, {
132 address: "localhost",
133 port: attachArgs.port,
134 restart: true,
135 request: "attach",
136 remoteRoot: undefined,
137 localRoot: undefined,
138 });
139 super.attach(attachArguments).then(() => {
140 this.outputLogger("The debugger attached successfully");
141 resolve();
142 }).catch((e) => reject(e));
143 }).catch((e) => reject(e));
144 })
145 .catch((err) => {
146 this.outputLogger("An error occurred while attaching to the debugger. " + err.message || err, true);
147 this.cleanUp();
148 reject(err);
149 });
150 });
151 }));
152 }
153
154 public disconnect(args: DebugProtocol.DisconnectArguments): void {
155 this.cleanUp();
156 super.disconnect(args);
157 }
158
159 private initializeSettings(args: any): Q.Promise<any> {
160 if (!this.isSettingsInitialized) {
161 let chromeDebugCoreLogs = getLoggingDirectory();
162 if (chromeDebugCoreLogs) {
163 chromeDebugCoreLogs = path.join(chromeDebugCoreLogs, "ChromeDebugCoreLogs.txt");
164 }
165 let logLevel: string = args.trace;
166 if (logLevel) {
167 logLevel = logLevel.replace(logLevel[0], logLevel[0].toUpperCase());
168 logger.setup(Logger.LogLevel[logLevel], chromeDebugCoreLogs || false);
169 } else {
170 logger.setup(Logger.LogLevel.Log, chromeDebugCoreLogs || false);
171 }
172
173 if (!args.sourceMaps) {
174 args.sourceMaps = true;
175 }
176
177 const projectRootPath = getProjectRoot(args);
178 return ReactNativeProjectHelper.isReactNativeProject(projectRootPath)
179 .then((result) => {
180 if (!result) {
181 throw ErrorHelper.getInternalError(InternalErrorCode.NotInReactNativeFolderError);
182 }
183 this.projectRootPath = projectRootPath;
184 this.remoteExtension = RemoteExtension.atProjectRootPath(this.projectRootPath);
185 const version = getExtensionVersion();
186
187 // Start to send telemetry
188 (this._session as any).getTelemetryReporter().reassignTo(new RemoteTelemetryReporter(
189 "react-native-tools", version, Telemetry.APPINSIGHTS_INSTRUMENTATIONKEY, this.projectRootPath));
190
191 this.isSettingsInitialized = true;
192
193 return void 0;
194 });
195 } else {
196 return Q.resolve<void>(void 0);
197 }
198 }
199
200 private cleanUp() {
201 if (this.previousAttachArgs.platform === "android") {
202 this.remoteExtension.stopMonitoringLogcat()
203 .catch(reason => logger.warn(localize("CouldNotStopMonitoringLogcat", "Couldn't stop monitoring logcat: {0}", reason.message || reason)))
204 .finally(() => super.disconnect({terminateDebuggee: true}));
205 }
206 }
207
208}
209