microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
0.4.0

Branches

Tags

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

Clone

HTTPS

Download ZIP

src/extension/intellisenseHelper.ts

304lines · 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";
f1a07677Meena Kunnathur Balakrishnan10 years ago15import {Log} from "../common/log/log";
16import {LogLevel} from "../common/log/logHelper";
8a9925eeEric Hamilton10 years ago17
18
b1df983eEric Hamilton10 years ago19
9948de5dEric Hamilton10 years ago20interface IInstallProps {
8a9925eeEric Hamilton10 years ago21installed: boolean;
22version: string;
23}
bfd09d23Joshua Skelton10 years ago24
25export class IntellisenseHelper {
8a9925eeEric Hamilton10 years ago26
27private static s_typeScriptVersion = "1.8.2"; // preferred version of TypeScript for legacy VSCode installs
28private 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 ago29// note: semver considers "x.x.x-<string>" to be < "x.x.x"" - so we include insider here as the
30// insider build is less than the release build of 0.10.10 and we will support it.
8bde1c02Vladimir Kotikov9 years ago31private static VSCODE_SUPPORTS_ATA_SINCE = "1.7.2-insider";
8a9925eeEric Hamilton10 years ago32
5e53b45aJoshua Skelton10 years ago33/**
9dc82fe8Joshua Skelton10 years ago34* Helper method that configures the workspace for Salsa intellisense.
5e53b45aJoshua Skelton10 years ago35*/
10873e11digeff10 years ago36public static setupReactNativeIntellisense(): Q.Promise<void> {
88e05f1bJoshua Skelton10 years ago37// Telemetry - Send Salsa Environment setup information
10873e11digeff10 years ago38const tsSalsaEnvSetup = TelemetryHelper.createTelemetryEvent("RNIntellisense");
88e05f1bJoshua Skelton10 years ago39TelemetryHelper.addTelemetryEventProperty(tsSalsaEnvSetup, "TsSalsaEnvSetup", !!process.env.VSCODE_TSJS, false);
40Telemetry.send(tsSalsaEnvSetup);
41
8bde1c02Vladimir Kotikov9 years ago42const configureWorkspace = JsConfigHelper.createJsConfigIfNotPresent()
43.then(() => {
44// VSCode versions >= 1.7.2-insider support ATA and will not require copying
45// typings into workspace for intellisense
46if (semver.lt(vscode.version, IntellisenseHelper.VSCODE_SUPPORTS_ATA_SINCE)) {
47return IntellisenseHelper.installReactNativeTypings();
48}
49});
bfd09d23Joshua Skelton10 years ago50
cdbc4389Joshua Skelton10 years ago51// The actions taken in the promise chain below may result in requring a restart.
10873e11digeff10 years ago52const configureTypescript = Q(false)
cdbc4389Joshua Skelton10 years ago53.then((isRestartRequired: boolean) => IntellisenseHelper.enableSalsa(isRestartRequired))
8a9925eeEric Hamilton10 years ago54.then((isRestartRequired: boolean) => IntellisenseHelper.verifyInstallTypeScript(isRestartRequired))
bed90dbdJoshua Skelton10 years ago55.then((isRestartRequired: boolean) => IntellisenseHelper.configureWorkspaceSettings(isRestartRequired))
8a9925eeEric Hamilton10 years ago56.then((isRestartRequired: boolean) => IntellisenseHelper.warnIfRestartIsRequired(isRestartRequired))
b1df983eEric Hamilton10 years ago57.catch((err: any) => {
58Log.logError("Error while setting up IntelliSense: " + err);
59return Q.reject<void>(err);
8a9925eeEric Hamilton10 years ago60});
10873e11digeff10 years ago61
65fd8e85digeff10 years ago62/* TODO #83: Refactor this code to
98bdec43digeff10 years ago63Q.all([enableSalsa(), installTypescript(), configureWorkspace()])
64.then((result) => warnIfRestartIsRequired(result.any((x) => x)))
65*/
66return Q.all([configureWorkspace, configureTypescript]).then(() => { });
5e53b45aJoshua Skelton10 years ago67}
68
69/**
70* Helper method that install typings for React Native.
71*/
cdbc4389Joshua Skelton10 years ago72public static installReactNativeTypings(): Q.Promise<void> {
986196e7Patricio Beltran9 years ago73const typingsSource = path.resolve(__dirname, "..", "..", "ReactTypings");
74const reactTypings = path.resolve(typingsSource, "react");
75const reactNativeTypings = path.resolve(typingsSource, "react-native");
274b561cVladimir Kotikov9 years ago76const typingsIndex = path.resolve(typingsSource, "react-native.d.ts.index");
986196e7Patricio Beltran9 years ago77
78const typingsDestination = path.resolve(vscode.workspace.rootPath, ".vscode", "typings");
79const reactTypingsDestination = path.resolve(typingsDestination, "react");
80const reactNativeTypingsDestination = path.resolve(typingsDestination, "react-native");
274b561cVladimir Kotikov9 years ago81const typingsIndexDestination = path.resolve(vscode.workspace.rootPath, "typings");
82const typingIndexFinalPath = path.resolve(typingsIndexDestination, "react-native.d.ts");
986196e7Patricio Beltran9 years ago83
bfd09d23Joshua Skelton10 years ago84let fileSystem = new FileSystem();
85
81f88231Patricio Beltran9 years ago86const createTypingsDirectoryIfNeeded = fileSystem.directoryExists(typingsDestination).
87then((exists) => {
88if (!exists) {
89return fileSystem.makeDirectoryRecursiveSync(typingsDestination);
90}
91});
986196e7Patricio Beltran9 years ago92const copyReactTypingsIfNeeded = fileSystem.directoryExists(reactTypingsDestination)
93.then((exists) => {
94if (!exists) {
95return fileSystem.copyRecursive(reactTypings, reactTypingsDestination);
96}
97});
98const copyReactNativeTypingsIfNeeded = fileSystem.directoryExists(reactNativeTypingsDestination)
99.then((exists) => {
100if (!exists) {
101return fileSystem.copyRecursive(reactNativeTypings, reactNativeTypingsDestination);
102}
103});
274b561cVladimir Kotikov9 years ago104
105const copyTypingsIndexIfNeeded = fileSystem.directoryExists(typingsIndexDestination)
106.then((exists) => {
107if (!exists) {
108return fileSystem.makeDirectoryRecursiveSync(typingsIndexDestination);
109}
110})
111.then(() => fileSystem.exists(typingIndexFinalPath))
ae278043Vladimir Kotikov9 years ago112.then((exists) => {
113if (!exists) {
274b561cVladimir Kotikov9 years ago114return fileSystem.copyFile(typingsIndex, typingIndexFinalPath);
ae278043Vladimir Kotikov9 years ago115}
116});
117
118return Q.all([
119createTypingsDirectoryIfNeeded,
120copyReactTypingsIfNeeded,
121copyReactNativeTypingsIfNeeded,
122copyTypingsIndexIfNeeded,
123]).then(() => { });
bfd09d23Joshua Skelton10 years ago124}
125
5e53b45aJoshua Skelton10 years ago126/**
8a9925eeEric Hamilton10 years ago127* Helper method that verifies the correct version of TypeScript is installed.
128* If using a newer version of VSCode TypeScript is installed by default and no
129* action is needed. If using an older version, verify that the correct TS version is
130* installed, if not install it.
5e53b45aJoshua Skelton10 years ago131*/
8a9925eeEric Hamilton10 years ago132public static verifyInstallTypeScript(isRestartRequired: boolean): Q.Promise<boolean> {
bed90dbdJoshua Skelton10 years ago133
8a9925eeEric Hamilton10 years ago134if (IntellisenseHelper.isSalsaSupported()) {
135// this is the correct version of vscode, which includes TypeScript (Salsa) support, nothing to do here
136return Q.resolve<boolean>(isRestartRequired);
137}
138
139return IntellisenseHelper.getInstalledTypeScriptVersion()
9948de5dEric Hamilton10 years ago140.then(function(installProps: IInstallProps) {
8a9925eeEric Hamilton10 years ago141
b1df983eEric Hamilton10 years ago142if (installProps.installed === true) {
8a9925eeEric Hamilton10 years ago143
b1df983eEric Hamilton10 years ago144if (semver.neq(IntellisenseHelper.s_typeScriptVersion, installProps.version)) {
8a9925eeEric Hamilton10 years ago145Log.logInternalMessage(LogLevel.Debug, "TypeScript is installed with the wrong version: " + installProps.version);
b1df983eEric Hamilton10 years ago146return true;
147} else {
148Log.logInternalMessage(LogLevel.Debug, "Installed TypeScript version is correct");
149return false;
8a9925eeEric Hamilton10 years ago150}
b1df983eEric Hamilton10 years ago151} else {
152Log.logInternalMessage(LogLevel.Debug, "TypeScript is not installed");
153return true;
bed90dbdJoshua Skelton10 years ago154}
8a9925eeEric Hamilton10 years ago155})
b1df983eEric Hamilton10 years ago156.then((install: boolean) => {
8a9925eeEric Hamilton10 years ago157
b1df983eEric Hamilton10 years ago158if (install) {
a1005420dlebu10 years ago159let installPath: string = path.resolve(HostPlatform.getUserHomePath(), ".vscode");
b1df983eEric Hamilton10 years ago160let runArguments: string[] = [];
a1005420dlebu10 years ago161let npmCommand: string = HostPlatform.getNpmCliCommand("npm");
b1df983eEric Hamilton10 years ago162runArguments.push("install");
163runArguments.push("--prefix " + installPath);
164runArguments.push("typescript@" + IntellisenseHelper.s_typeScriptVersion);
165
323a3cc0Meena Kunnathur Balakrishnan10 years ago166return new CommandExecutor(installPath).spawn(npmCommand, runArguments)
8a9925eeEric Hamilton10 years ago167.then(() => {
b1df983eEric Hamilton10 years ago168return true;
8a9925eeEric Hamilton10 years ago169})
b1df983eEric Hamilton10 years ago170.catch((err: any) => {
8a9925eeEric Hamilton10 years ago171Log.logError("Error attempting to install TypeScript: " + err);
b1df983eEric Hamilton10 years ago172return Q.reject<boolean>(err);
8a9925eeEric Hamilton10 years ago173});
b1df983eEric Hamilton10 years ago174
175} else {
176return isRestartRequired;
8a9925eeEric Hamilton10 years ago177}
bed90dbdJoshua Skelton10 years ago178});
179}
180
181
182
9e81e40fPatricio Beltran10 years ago183public static configureWorkspaceSettings(isRestartRequired: boolean): boolean {
8a9925eeEric Hamilton10 years ago184let typeScriptLibPath: string = path.resolve(IntellisenseHelper.getTypeScriptInstallPath(), "lib");
9e81e40fPatricio Beltran10 years ago185const tsdkPath = SettingsHelper.getTypeScriptTsdk();
bfd09d23Joshua Skelton10 years ago186
9e81e40fPatricio Beltran10 years ago187if (IntellisenseHelper.isSalsaSupported()) {
188if (tsdkPath === typeScriptLibPath) {
189// Note: In previous releases of VSCode (< 0.10.10) the Salsa TypeScript
190// IntelliSense was not enabled by default, this extension would install
191// Salsa itself, and update the settings to point at that. Here we
192// attempt to reset that value to null if it still points to the previous
193// installed (and no longer valid) version of TypeScript.
194SettingsHelper.notifyUserToRemoveTSDKFromSettingsJson(tsdkPath);
195// We are already telling the user to restart. No need to show another message.
196return false;
197}
198} else {
199if (tsdkPath === null) {
200SettingsHelper.notifyUserToAddTSDKInSettingsJson(typeScriptLibPath);
201// We are already telling the user to restart. No need to show another message.
202return false;
203}
204}
205return isRestartRequired;
bfd09d23Joshua Skelton10 years ago206}
207
bed90dbdJoshua Skelton10 years ago208public static warnIfRestartIsRequired(isRestartRequired: boolean): Q.Promise<void> {
209if (isRestartRequired) {
88e05f1bJoshua Skelton10 years ago210vscode.window.showInformationMessage("React Native intellisense was successfully configured for this project. Restart to enable it.");
bed90dbdJoshua Skelton10 years ago211}
212
213return;
214}
215
5e53b45aJoshua Skelton10 years ago216/**
217* Helper method that sets the environment variable and informs the user they need to restart
218* in order to enable the Salsa intellisense.
219*/
9dc82fe8Joshua Skelton10 years ago220public static enableSalsa(isRestartRequired: boolean): Q.Promise<boolean> {
e2216684Patricio Beltran10 years ago221if (!IntellisenseHelper.isSalsaSupported() && !process.env.VSCODE_TSJS) {
9dc82fe8Joshua Skelton10 years ago222return Q({})
a1005420dlebu10 years ago223.then(() => HostPlatform.setEnvironmentVariable("VSCODE_TSJS", "1"))
02cbb151Joshua Skelton10 years ago224.then(() => { return true; });
bfd09d23Joshua Skelton10 years ago225}
9dc82fe8Joshua Skelton10 years ago226
227return Q(isRestartRequired);
bfd09d23Joshua Skelton10 years ago228}
8a9925eeEric Hamilton10 years ago229
230/**
231* Simple check to see if the TypeScript package is in the expected location (where we installed it)
232*/
b1df983eEric Hamilton10 years ago233private static isTypeScriptInstalled(): Q.Promise<boolean> {
8a9925eeEric Hamilton10 years ago234let fileSystem: FileSystem = new FileSystem();
235let installPath: string = path.join(IntellisenseHelper.getTypeScriptInstallPath(), "lib");
b1df983eEric Hamilton10 years ago236return fileSystem.exists(installPath);
8a9925eeEric Hamilton10 years ago237}
238
239/**
240* Checks for the existance of our installed TypeScript package, if it exists also determine its version
241*/
9948de5dEric Hamilton10 years ago242private static getInstalledTypeScriptVersion(): Q.Promise<IInstallProps> {
8a9925eeEric Hamilton10 years ago243return IntellisenseHelper.isTypeScriptInstalled()
b1df983eEric Hamilton10 years ago244.then((installed: boolean) => {
9948de5dEric Hamilton10 years ago245let installProps: IInstallProps = {
b1df983eEric Hamilton10 years ago246installed: installed,
cdf34447digeff10 years ago247version: "",
b1df983eEric Hamilton10 years ago248};
8a9925eeEric Hamilton10 years ago249
250if (installed === true) {
251Log.logInternalMessage(LogLevel.Debug, "TypeScript is installed - checking version");
252return IntellisenseHelper.readPackageJson()
b1df983eEric Hamilton10 years ago253.then((version: string) => {
254installProps.version = version;
255return installProps;
256});
257} else {
258return installProps;
8a9925eeEric Hamilton10 years ago259}
260});
261}
262
263/**
264* Read the package.json from the TypeScript install path and return the version if it's available
265*/
b1df983eEric Hamilton10 years ago266private static readPackageJson(): Q.Promise<string> {
8a9925eeEric Hamilton10 years ago267let packageFilePath: string = path.join(IntellisenseHelper.getTypeScriptInstallPath(), "package.json");
268let fileSystem = new FileSystem();
269
270return fileSystem.exists(packageFilePath)
271.then(function(exists: boolean): Q.Promise<string> {
272if (!exists) {
273return Q.reject<string>("package.json not found at:" + packageFilePath);
274}
275
276return fileSystem.readFile(packageFilePath, "utf-8");
277})
278.then(function(jsonContents: string): Q.Promise<any> {
b1df983eEric Hamilton10 years ago279let data = JSON.parse(jsonContents);
8a9925eeEric Hamilton10 years ago280return data.version;
281})
b1df983eEric Hamilton10 years ago282.catch((err: any) => {
ccce3f36Joshua Skelton10 years ago283Log.logError("Error while processing package.json: " + err);
b1df983eEric Hamilton10 years ago284return "0.0.0";
8a9925eeEric Hamilton10 years ago285});
286}
287
288/**
289* Simple helper to get the TypeScript install path
290*/
b1df983eEric Hamilton10 years ago291private static getTypeScriptInstallPath(): string {
8a9925eeEric Hamilton10 years ago292
a1005420dlebu10 years ago293let codePath: string = path.resolve(HostPlatform.getUserHomePath(), ".vscode");
8a9925eeEric Hamilton10 years ago294let typeScriptLibPath: string = path.join(codePath, "node_modules", "typescript");
295return typeScriptLibPath;
296}
297
298/**
299* Simple helper to determine if the current version of VSCode supports TypeScript (Salsa) or better
300*/
301private static isSalsaSupported(): boolean {
302return semver.gte(vscode.version, IntellisenseHelper.s_vsCodeVersion, true);
303}
f16656e9frogcjn10 years ago304}