microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.4.3

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/intellisenseHelper.ts

295lines · modeblame

bfd09d23Joshua Skelton10 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 {FileSystem} from "../common/node/fileSystem";
5import * as path from "path";
76176919Joshua Skelton10 years ago6import * as Q from "q";
bfd09d23Joshua Skelton10 years ago7import * as vscode from "vscode";
8a9925eeEric Hamilton10 years ago8import * as semver from "semver";
88e05f1bJoshua Skelton10 years ago9import {Telemetry} from "../common/telemetry";
10import {TelemetryHelper} from "../common/telemetryHelper";
b1df983eEric Hamilton10 years ago11import {CommandExecutor} from "../common/commandExecutor";
8bde1c02Vladimir Kotikov9 years ago12import {JsConfigHelper} from "./tsconfigHelper";
bfd09d23Joshua Skelton10 years ago13import {SettingsHelper} from "./settingsHelper";
a1005420dlebu10 years ago14import {HostPlatform} from "../common/hostPlatform";
0a68f8dbArtem Egorov8 years ago15import {ConsoleLogger} from "./log/ConsoleLogger";
b1df983eEric Hamilton10 years ago16
9948de5dEric Hamilton10 years ago17interface IInstallProps {
8a9925eeEric Hamilton10 years ago18installed: boolean;
19version: string;
20}
bfd09d23Joshua Skelton10 years ago21
22export class IntellisenseHelper {
0a68f8dbArtem Egorov8 years ago23private static logger: ConsoleLogger = new ConsoleLogger();
8a9925eeEric Hamilton10 years ago24
25private static s_typeScriptVersion = "1.8.2"; // preferred version of TypeScript for legacy VSCode installs
26private static s_vsCodeVersion = "0.10.10-insider"; // preferred version of VSCode (current is 0.10.9, 0.10.10-insider+ will include native TypeScript support)
b1df983eEric Hamilton10 years ago27// note: semver considers "x.x.x-<string>" to be < "x.x.x"" - so we include insider here as the
28// insider build is less than the release build of 0.10.10 and we will support it.
8bde1c02Vladimir Kotikov9 years ago29private static VSCODE_SUPPORTS_ATA_SINCE = "1.7.2-insider";
8a9925eeEric Hamilton10 years ago30
5e53b45aJoshua Skelton10 years ago31/**
9dc82fe8Joshua Skelton10 years ago32* Helper method that configures the workspace for Salsa intellisense.
5e53b45aJoshua Skelton10 years ago33*/
10873e11digeff10 years ago34public static setupReactNativeIntellisense(): Q.Promise<void> {
88e05f1bJoshua Skelton10 years ago35// Telemetry - Send Salsa Environment setup information
10873e11digeff10 years ago36const tsSalsaEnvSetup = TelemetryHelper.createTelemetryEvent("RNIntellisense");
88e05f1bJoshua Skelton10 years ago37TelemetryHelper.addTelemetryEventProperty(tsSalsaEnvSetup, "TsSalsaEnvSetup", !!process.env.VSCODE_TSJS, false);
38Telemetry.send(tsSalsaEnvSetup);
39
8bde1c02Vladimir Kotikov9 years ago40const configureWorkspace = JsConfigHelper.createJsConfigIfNotPresent()
41.then(() => {
42// VSCode versions >= 1.7.2-insider support ATA and will not require copying
43// typings into workspace for intellisense
44if (semver.lt(vscode.version, IntellisenseHelper.VSCODE_SUPPORTS_ATA_SINCE)) {
45return IntellisenseHelper.installReactNativeTypings();
46}
5c8365a6Artem Egorov8 years ago47return void 0;
8bde1c02Vladimir Kotikov9 years ago48});
bfd09d23Joshua Skelton10 years ago49
cdbc4389Joshua Skelton10 years ago50// The actions taken in the promise chain below may result in requring a restart.
10873e11digeff10 years ago51const configureTypescript = Q(false)
cdbc4389Joshua Skelton10 years ago52.then((isRestartRequired: boolean) => IntellisenseHelper.enableSalsa(isRestartRequired))
8a9925eeEric Hamilton10 years ago53.then((isRestartRequired: boolean) => IntellisenseHelper.verifyInstallTypeScript(isRestartRequired))
bed90dbdJoshua Skelton10 years ago54.then((isRestartRequired: boolean) => IntellisenseHelper.configureWorkspaceSettings(isRestartRequired))
8a9925eeEric Hamilton10 years ago55.then((isRestartRequired: boolean) => IntellisenseHelper.warnIfRestartIsRequired(isRestartRequired))
b1df983eEric Hamilton10 years ago56.catch((err: any) => {
0a68f8dbArtem Egorov8 years ago57IntellisenseHelper.logger.error("Error while setting up IntelliSense: " + err);
b1df983eEric Hamilton10 years ago58return Q.reject<void>(err);
8a9925eeEric Hamilton10 years ago59});
10873e11digeff10 years ago60
65fd8e85digeff10 years ago61/* TODO #83: Refactor this code to
98bdec43digeff10 years ago62Q.all([enableSalsa(), installTypescript(), configureWorkspace()])
63.then((result) => warnIfRestartIsRequired(result.any((x) => x)))
64*/
65return Q.all([configureWorkspace, configureTypescript]).then(() => { });
5e53b45aJoshua Skelton10 years ago66}
67
68/**
69* Helper method that install typings for React Native.
70*/
cdbc4389Joshua Skelton10 years ago71public static installReactNativeTypings(): Q.Promise<void> {
986196e7Patricio Beltran10 years ago72const typingsSource = path.resolve(__dirname, "..", "..", "ReactTypings");
73const reactTypings = path.resolve(typingsSource, "react");
74const reactNativeTypings = path.resolve(typingsSource, "react-native");
274b561cVladimir Kotikov9 years ago75const typingsIndex = path.resolve(typingsSource, "react-native.d.ts.index");
986196e7Patricio Beltran10 years ago76
77const typingsDestination = path.resolve(vscode.workspace.rootPath, ".vscode", "typings");
78const reactTypingsDestination = path.resolve(typingsDestination, "react");
79const reactNativeTypingsDestination = path.resolve(typingsDestination, "react-native");
274b561cVladimir Kotikov9 years ago80const typingsIndexDestination = path.resolve(vscode.workspace.rootPath, "typings");
81const typingIndexFinalPath = path.resolve(typingsIndexDestination, "react-native.d.ts");
986196e7Patricio Beltran10 years ago82
bfd09d23Joshua Skelton10 years ago83let fileSystem = new FileSystem();
84
81f88231Patricio Beltran9 years ago85const createTypingsDirectoryIfNeeded = fileSystem.directoryExists(typingsDestination).
86then((exists) => {
87if (!exists) {
88return fileSystem.makeDirectoryRecursiveSync(typingsDestination);
89}
90});
986196e7Patricio Beltran10 years ago91const copyReactTypingsIfNeeded = fileSystem.directoryExists(reactTypingsDestination)
92.then((exists) => {
5c8365a6Artem Egorov8 years ago93return exists ? void 0 : fileSystem.copyRecursive(reactTypings, reactTypingsDestination);
986196e7Patricio Beltran10 years ago94});
95const copyReactNativeTypingsIfNeeded = fileSystem.directoryExists(reactNativeTypingsDestination)
96.then((exists) => {
5c8365a6Artem Egorov8 years ago97return exists ? void 0 : fileSystem.copyRecursive(reactNativeTypings, reactNativeTypingsDestination);
986196e7Patricio Beltran10 years ago98});
274b561cVladimir Kotikov9 years ago99
100const copyTypingsIndexIfNeeded = fileSystem.directoryExists(typingsIndexDestination)
101.then((exists) => {
5c8365a6Artem Egorov8 years ago102return exists ? null : fileSystem.makeDirectoryRecursiveSync(typingsIndexDestination);
274b561cVladimir Kotikov9 years ago103})
104.then(() => fileSystem.exists(typingIndexFinalPath))
ae278043Vladimir Kotikov9 years ago105.then((exists) => {
5c8365a6Artem Egorov8 years ago106return exists ? void 0 : fileSystem.copyFile(typingsIndex, typingIndexFinalPath);
ae278043Vladimir Kotikov9 years ago107});
108
109return Q.all([
110createTypingsDirectoryIfNeeded,
111copyReactTypingsIfNeeded,
112copyReactNativeTypingsIfNeeded,
113copyTypingsIndexIfNeeded,
114]).then(() => { });
bfd09d23Joshua Skelton10 years ago115}
116
5e53b45aJoshua Skelton10 years ago117/**
8a9925eeEric Hamilton10 years ago118* Helper method that verifies the correct version of TypeScript is installed.
119* If using a newer version of VSCode TypeScript is installed by default and no
120* action is needed. If using an older version, verify that the correct TS version is
121* installed, if not install it.
5e53b45aJoshua Skelton10 years ago122*/
8a9925eeEric Hamilton10 years ago123public static verifyInstallTypeScript(isRestartRequired: boolean): Q.Promise<boolean> {
bed90dbdJoshua Skelton10 years ago124
8a9925eeEric Hamilton10 years ago125if (IntellisenseHelper.isSalsaSupported()) {
126// this is the correct version of vscode, which includes TypeScript (Salsa) support, nothing to do here
127return Q.resolve<boolean>(isRestartRequired);
128}
129
130return IntellisenseHelper.getInstalledTypeScriptVersion()
9948de5dEric Hamilton10 years ago131.then(function(installProps: IInstallProps) {
8a9925eeEric Hamilton10 years ago132
b1df983eEric Hamilton10 years ago133if (installProps.installed === true) {
8a9925eeEric Hamilton10 years ago134
b1df983eEric Hamilton10 years ago135if (semver.neq(IntellisenseHelper.s_typeScriptVersion, installProps.version)) {
0a68f8dbArtem Egorov8 years ago136IntellisenseHelper.logger.debug("TypeScript is installed with the wrong version: " + installProps.version);
b1df983eEric Hamilton10 years ago137return true;
138} else {
0a68f8dbArtem Egorov8 years ago139IntellisenseHelper.logger.debug("Installed TypeScript version is correct");
b1df983eEric Hamilton10 years ago140return false;
8a9925eeEric Hamilton10 years ago141}
b1df983eEric Hamilton10 years ago142} else {
0a68f8dbArtem Egorov8 years ago143IntellisenseHelper.logger.debug("TypeScript is not installed");
b1df983eEric Hamilton10 years ago144return true;
bed90dbdJoshua Skelton10 years ago145}
8a9925eeEric Hamilton10 years ago146})
b1df983eEric Hamilton10 years ago147.then((install: boolean) => {
8a9925eeEric Hamilton10 years ago148
b1df983eEric Hamilton10 years ago149if (install) {
a1005420dlebu10 years ago150let installPath: string = path.resolve(HostPlatform.getUserHomePath(), ".vscode");
b1df983eEric Hamilton10 years ago151let runArguments: string[] = [];
a1005420dlebu10 years ago152let npmCommand: string = HostPlatform.getNpmCliCommand("npm");
b1df983eEric Hamilton10 years ago153runArguments.push("install");
154runArguments.push("--prefix " + installPath);
155runArguments.push("typescript@" + IntellisenseHelper.s_typeScriptVersion);
156
323a3cc0Meena Kunnathur Balakrishnan10 years ago157return new CommandExecutor(installPath).spawn(npmCommand, runArguments)
8a9925eeEric Hamilton10 years ago158.then(() => {
b1df983eEric Hamilton10 years ago159return true;
8a9925eeEric Hamilton10 years ago160})
b1df983eEric Hamilton10 years ago161.catch((err: any) => {
0a68f8dbArtem Egorov8 years ago162IntellisenseHelper.logger.error("Error attempting to install TypeScript: " + err);
b1df983eEric Hamilton10 years ago163return Q.reject<boolean>(err);
8a9925eeEric Hamilton10 years ago164});
b1df983eEric Hamilton10 years ago165
166} else {
167return isRestartRequired;
8a9925eeEric Hamilton10 years ago168}
bed90dbdJoshua Skelton10 years ago169});
170}
171
172
173
9e81e40fPatricio Beltran10 years ago174public static configureWorkspaceSettings(isRestartRequired: boolean): boolean {
8a9925eeEric Hamilton10 years ago175let typeScriptLibPath: string = path.resolve(IntellisenseHelper.getTypeScriptInstallPath(), "lib");
9e81e40fPatricio Beltran10 years ago176const tsdkPath = SettingsHelper.getTypeScriptTsdk();
bfd09d23Joshua Skelton10 years ago177
9e81e40fPatricio Beltran10 years ago178if (IntellisenseHelper.isSalsaSupported()) {
179if (tsdkPath === typeScriptLibPath) {
180// Note: In previous releases of VSCode (< 0.10.10) the Salsa TypeScript
181// IntelliSense was not enabled by default, this extension would install
182// Salsa itself, and update the settings to point at that. Here we
183// attempt to reset that value to null if it still points to the previous
184// installed (and no longer valid) version of TypeScript.
185SettingsHelper.notifyUserToRemoveTSDKFromSettingsJson(tsdkPath);
186// We are already telling the user to restart. No need to show another message.
187return false;
188}
189} else {
190if (tsdkPath === null) {
191SettingsHelper.notifyUserToAddTSDKInSettingsJson(typeScriptLibPath);
192// We are already telling the user to restart. No need to show another message.
193return false;
194}
195}
196return isRestartRequired;
bfd09d23Joshua Skelton10 years ago197}
198
bed90dbdJoshua Skelton10 years ago199public static warnIfRestartIsRequired(isRestartRequired: boolean): Q.Promise<void> {
200if (isRestartRequired) {
88e05f1bJoshua Skelton10 years ago201vscode.window.showInformationMessage("React Native intellisense was successfully configured for this project. Restart to enable it.");
bed90dbdJoshua Skelton10 years ago202}
203
5c8365a6Artem Egorov8 years ago204return Q.resolve(void 0);
bed90dbdJoshua Skelton10 years ago205}
206
5e53b45aJoshua Skelton10 years ago207/**
208* Helper method that sets the environment variable and informs the user they need to restart
209* in order to enable the Salsa intellisense.
210*/
9dc82fe8Joshua Skelton10 years ago211public static enableSalsa(isRestartRequired: boolean): Q.Promise<boolean> {
e2216684Patricio Beltran10 years ago212if (!IntellisenseHelper.isSalsaSupported() && !process.env.VSCODE_TSJS) {
9dc82fe8Joshua Skelton10 years ago213return Q({})
a1005420dlebu10 years ago214.then(() => HostPlatform.setEnvironmentVariable("VSCODE_TSJS", "1"))
02cbb151Joshua Skelton10 years ago215.then(() => { return true; });
bfd09d23Joshua Skelton10 years ago216}
9dc82fe8Joshua Skelton10 years ago217
218return Q(isRestartRequired);
bfd09d23Joshua Skelton10 years ago219}
8a9925eeEric Hamilton10 years ago220
221/**
222* Simple check to see if the TypeScript package is in the expected location (where we installed it)
223*/
b1df983eEric Hamilton10 years ago224private static isTypeScriptInstalled(): Q.Promise<boolean> {
8a9925eeEric Hamilton10 years ago225let fileSystem: FileSystem = new FileSystem();
226let installPath: string = path.join(IntellisenseHelper.getTypeScriptInstallPath(), "lib");
b1df983eEric Hamilton10 years ago227return fileSystem.exists(installPath);
8a9925eeEric Hamilton10 years ago228}
229
230/**
231* Checks for the existance of our installed TypeScript package, if it exists also determine its version
232*/
9948de5dEric Hamilton10 years ago233private static getInstalledTypeScriptVersion(): Q.Promise<IInstallProps> {
8a9925eeEric Hamilton10 years ago234return IntellisenseHelper.isTypeScriptInstalled()
b1df983eEric Hamilton10 years ago235.then((installed: boolean) => {
9948de5dEric Hamilton10 years ago236let installProps: IInstallProps = {
b1df983eEric Hamilton10 years ago237installed: installed,
cdf34447digeff10 years ago238version: "",
b1df983eEric Hamilton10 years ago239};
8a9925eeEric Hamilton10 years ago240
241if (installed === true) {
0a68f8dbArtem Egorov8 years ago242IntellisenseHelper.logger.debug("TypeScript is installed - checking version");
8a9925eeEric Hamilton10 years ago243return IntellisenseHelper.readPackageJson()
b1df983eEric Hamilton10 years ago244.then((version: string) => {
245installProps.version = version;
246return installProps;
247});
248} else {
249return installProps;
8a9925eeEric Hamilton10 years ago250}
251});
252}
253
254/**
255* Read the package.json from the TypeScript install path and return the version if it's available
256*/
b1df983eEric Hamilton10 years ago257private static readPackageJson(): Q.Promise<string> {
8a9925eeEric Hamilton10 years ago258let packageFilePath: string = path.join(IntellisenseHelper.getTypeScriptInstallPath(), "package.json");
259let fileSystem = new FileSystem();
260
261return fileSystem.exists(packageFilePath)
262.then(function(exists: boolean): Q.Promise<string> {
263if (!exists) {
264return Q.reject<string>("package.json not found at:" + packageFilePath);
265}
266
267return fileSystem.readFile(packageFilePath, "utf-8");
268})
269.then(function(jsonContents: string): Q.Promise<any> {
b1df983eEric Hamilton10 years ago270let data = JSON.parse(jsonContents);
8a9925eeEric Hamilton10 years ago271return data.version;
272})
b1df983eEric Hamilton10 years ago273.catch((err: any) => {
0a68f8dbArtem Egorov8 years ago274IntellisenseHelper.logger.error("Error while processing package.json: " + err);
b1df983eEric Hamilton10 years ago275return "0.0.0";
8a9925eeEric Hamilton10 years ago276});
277}
278
279/**
280* Simple helper to get the TypeScript install path
281*/
b1df983eEric Hamilton10 years ago282private static getTypeScriptInstallPath(): string {
8a9925eeEric Hamilton10 years ago283
a1005420dlebu10 years ago284let codePath: string = path.resolve(HostPlatform.getUserHomePath(), ".vscode");
8a9925eeEric Hamilton10 years ago285let typeScriptLibPath: string = path.join(codePath, "node_modules", "typescript");
286return typeScriptLibPath;
287}
288
289/**
290* Simple helper to determine if the current version of VSCode supports TypeScript (Salsa) or better
291*/
292private static isSalsaSupported(): boolean {
293return semver.gte(vscode.version, IntellisenseHelper.s_vsCodeVersion, true);
294}
f16656e9frogcjn10 years ago295}