microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
indexed-sourcemap-null-section-issue

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/commands/util/command.ts

155lines · modeblame

36a21645Heniker4 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
3
4import assert = require("assert");
5import * as vscode from "vscode";
6import { EntryPointHandler } from "../../../common/entryPointHandler";
7import { ErrorHelper } from "../../../common/error/errorHelper";
8import { InternalError } from "../../../common/error/internalError";
9import { InternalErrorCode } from "../../../common/error/internalErrorCode";
10import { AppLauncher } from "../../appLauncher";
11import { PlatformType } from "../../launchArgs";
12import { OutputChannelLogger } from "../../log/OutputChannelLogger";
13import { TelemetryGenerator } from "../../../common/telemetryGenerators";
14import { selectProject } from ".";
15
16export abstract class Command<ArgT extends unknown[] = never[]> {
17private static instances = new Map<Command, unknown>();
18
19static formInstance<T extends { prototype: unknown }>(this: T): T["prototype"] {
20// 'any' because TypeScript is wrong
21// workaround from https://github.com/microsoft/TypeScript/issues/5863
22const that = this as any;
23const result = Command.instances.get(that) || new that();
24Command.instances.set(that, result);
25return result;
26}
27
28abstract readonly codeName: string;
29abstract readonly label: string;
30abstract readonly error: InternalError;
31
32get platform(): string {
33return (
34[
35PlatformType.Android,
36PlatformType.iOS,
37PlatformType.Exponent,
38PlatformType.macOS,
39PlatformType.Windows,
40].find(it => this.codeName.toLowerCase().includes(it.toLowerCase())) || ""
41);
42}
43
44private entryPointHandler?: EntryPointHandler;
45
46/** Initialize project property before executing command */
47protected requiresProject = true;
48
49/** Throw an Error if workspace is not trusted before executing command */
50protected requiresTrust = true;
51
52protected project?: AppLauncher;
53
54protected constructor() {}
55
56protected createHandler(fn = this.baseFn.bind(this)): (...args: ArgT) => Promise<void> {
57return async (...args: ArgT): Promise<void> => {
58assert(this.entryPointHandler, "this.entryPointHandler is not defined");
59
60const resultFn = async (generator: TelemetryGenerator) => {
61try {
62await this.onBeforeExecute(...args);
63await fn.bind(this)(...args);
64} catch (error) {
fff0cefdConnorQi014 months ago65if (
66error instanceof InternalError &&
67error.errorCode === InternalErrorCode.CommandCanceled
68) {
69generator.addError(error);
70return;
36a21645Heniker4 years ago71}
fff0cefdConnorQi014 months ago72throw error;
36a21645Heniker4 years ago73}
74};
75
76OutputChannelLogger.getMainChannel().debug(`Run command: ${this.codeName}`);
77
78await this.entryPointHandler.runFunctionWExtProps(
79`commandPalette.${this.codeName}`,
80{
81platform: {
82value: this.platform,
83isPii: false,
84},
85},
86this.error,
87resultFn.bind(this),
88);
89};
90}
91
92// eslint-disable-next-line @typescript-eslint/no-unused-vars
93protected async onBeforeExecute(...args: ArgT): Promise<void> {
94if (this.requiresProject) {
95this.project = await this.selectProject();
96}
97
98if (this.requiresTrust && !isWorkspaceTrusted()) {
99throw ErrorHelper.getInternalError(
100InternalErrorCode.WorkspaceIsNotTrusted,
101this.project?.getPackager().getProjectPath() || undefined,
102this.label,
103);
104}
105
106function isWorkspaceTrusted() {
107// Remove after updating supported VS Code engine version to 1.57.0
108if (typeof (vscode.workspace as any).isTrusted === "boolean") {
109return (vscode.workspace as any).isTrusted;
110}
111
112return true;
113}
114}
115
116protected async selectProject(): Promise<AppLauncher> {
117try {
118return await selectProject();
119} catch (error) {
fff0cefdConnorQi014 months ago120if (
121error instanceof InternalError &&
122error.errorCode === InternalErrorCode.UserInputCanceled
123) {
124throw ErrorHelper.getNestedError(
125error,
126InternalErrorCode.CommandCanceled,
127this.label,
128);
36a21645Heniker4 years ago129}
fff0cefdConnorQi014 months ago130throw error;
36a21645Heniker4 years ago131}
132}
133
134abstract baseFn(...args: ArgT): Promise<void>;
135
136/** Execute base command without telemetry */
137async executeLocally(...args: ArgT): Promise<void> {
138await this.onBeforeExecute(...args);
139await this.baseFn(...args);
140}
141
142public register = (() => {
143let isCalled = false;
144return (entryPointHandler: EntryPointHandler) => {
145this.entryPointHandler = entryPointHandler;
146
147assert(!isCalled, "Command can only be registered once");
148isCalled = true;
149return vscode.commands.registerCommand(
150`reactNative.${this.codeName}`,
151this.createHandler(),
152);
153};
154})();
155}