microsoft/vscode-react-native

Public

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

CodeCommitsIssuesPull requestsActionsInsightsSecurity
1.9.1

Branches

Tags

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

Clone

HTTPS

Download ZIP

gulpfile.js

579lines · modeblame

b8ecee4ddigeff10 years ago1// Copyright (c) Microsoft Corporation. All rights reserved.
2// Licensed under the MIT license. See LICENSE file in the project root for details.
8ba55f4cJimmy Thomson10 years ago3
74dba829Yuri Skorokhodov7 years ago4const gulp = require("gulp");
5fd423caYuri Skorokhodov7 years ago5const log = require("fancy-log");
74dba829Yuri Skorokhodov7 years ago6const sourcemaps = require("gulp-sourcemaps");
7const path = require("path");
8const preprocess = require("gulp-preprocess");
9const ts = require("gulp-typescript");
10const mocha = require("gulp-mocha");
11const GulpExtras = require("./tools/gulp-extras");
12const minimist = require("minimist");
13const os = require("os");
14const fs = require("fs");
5fd423caYuri Skorokhodov7 years ago15const es = require("event-stream");
16const nls = require("vscode-nls-dev");
2d8af448Yuri Skorokhodov6 years ago17const webpack = require("webpack");
4bb0956eRedMickey5 years ago18const TerserPlugin = require("terser-webpack-plugin");
d55f3c22Yuri Skorokhodov5 years ago19const filter = require("gulp-filter");
2d8af448Yuri Skorokhodov6 years ago20const del = require("del");
de838bbfJiglioNero6 years ago21const vscodeTest = require("vscode-test");
4f8669f9JiglioNero6 years ago22const cp = require("child_process");
09f6024fHeniker4 years ago23const { promisify } = require("util");
24const assert = require("assert");
25const through2 = require("through2");
26const { Transform } = require("readable-stream");
8ba55f4cJimmy Thomson10 years ago27
74dba829Yuri Skorokhodov7 years ago28const copyright = GulpExtras.checkCopyright;
29const executeCommand = GulpExtras.executeCommand;
2d8af448Yuri Skorokhodov6 years ago30const tsProject = ts.createProject("tsconfig.json");
74dba829Yuri Skorokhodov7 years ago31
17bf2e64Yuri Skorokhodov6 years ago32/**
33* Whether we're running a nightly build.
34*/
2d8af448Yuri Skorokhodov6 years ago35const isNightly = process.argv.includes("--nightly");
17bf2e64Yuri Skorokhodov6 years ago36
7a2f6ad6RedMickey4 years ago37const vscodeVersionForTests = "stable";
f311755cRedMickey5 years ago38
9928222cYuri Skorokhodov5 years ago39const fullExtensionName = isNightly
34472878RedMickey5 years ago40? "msjsdiag.vscode-react-native-preview"
41: "msjsdiag.vscode-react-native";
9928222cYuri Skorokhodov5 years ago42
34472878RedMickey5 years ago43const extensionName = isNightly ? "vscode-react-native-preview" : "vscode-react-native";
9928222cYuri Skorokhodov5 years ago44
d55f3c22Yuri Skorokhodov5 years ago45const translationProjectName = "vscode-extensions";
74dba829Yuri Skorokhodov7 years ago46const defaultLanguages = [
34472878RedMickey5 years ago47{ id: "zh-tw", folderName: "cht", transifexId: "zh-hant" },
48{ id: "zh-cn", folderName: "chs", transifexId: "zh-hans" },
49{ id: "ja", folderName: "jpn" },
50{ id: "ko", folderName: "kor" },
51{ id: "de", folderName: "deu" },
52{ id: "fr", folderName: "fra" },
53{ id: "es", folderName: "esn" },
54{ id: "ru", folderName: "rus" },
55{ id: "it", folderName: "ita" },
56
57// These language-pack languages are included for VS but excluded from the vscode package
58{ id: "cs", folderName: "csy" },
59{ id: "tr", folderName: "trk" },
60{ id: "pt-br", folderName: "ptb", transifexId: "pt-BR" },
61{ id: "pl", folderName: "plk" },
74dba829Yuri Skorokhodov7 years ago62];
936ae21cmax-mironov8 years ago63
f6ac01ceRuslan Bikkinin7 years ago64const srcPath = "src";
65const testPath = "test";
2d8af448Yuri Skorokhodov6 years ago66const distDir = "dist";
67const distSrcDir = `${distDir}/src`;
89973b41dlebu10 years ago68
34472878RedMickey5 years ago69const sources = [srcPath, testPath].map(tsFolder => tsFolder + "/**/*.ts");
8ba55f4cJimmy Thomson10 years ago70
f6ac01ceRuslan Bikkinin7 years ago71const knownOptions = {
34472878RedMickey5 years ago72string: "env",
73default: { env: "production" },
572cd3badigeff10 years ago74};
75
f6ac01ceRuslan Bikkinin7 years ago76const options = minimist(process.argv.slice(2), knownOptions);
3aa3017bDmitry Zinovyev9 years ago77
34472878RedMickey5 years ago78let lintSources = [srcPath, testPath].map(tsFolder => tsFolder + "/**/*.ts");
f6ac01ceRuslan Bikkinin7 years ago79lintSources = lintSources.concat([
34472878RedMickey5 years ago80"!src/typings/**",
3c116e19RedMickey4 years ago81"!test/resources/sampleReactNativeProject/**",
34472878RedMickey5 years ago82"!test/smoke/**",
83"!/SmokeTestLogs/**",
f6ac01ceRuslan Bikkinin7 years ago84]);
5fd423caYuri Skorokhodov7 years ago85
2d8af448Yuri Skorokhodov6 years ago86async function runWebpack({
34472878RedMickey5 years ago87packages = [],
88devtool = false,
89compileInPlace = false,
90mode = process.argv.includes("watch") ? "development" : "production",
d55f3c22Yuri Skorokhodov5 years ago91} = options) {
34472878RedMickey5 years ago92let configs = [];
93for (const { entry, library, filename } of packages) {
94const config = {
95mode,
96target: "node",
97entry: path.resolve(entry),
98output: {
99path: compileInPlace ? path.resolve(path.dirname(entry)) : path.resolve(distDir),
100filename: filename || path.basename(entry).replace(".js", ".bundle.js"),
101devtoolModuleFilenameTemplate: "../[resource-path]",
102},
103devtool: devtool,
104resolve: {
105extensions: [".js", ".ts", ".json"],
106},
107module: {
108rules: [
109{
110test: /\.ts$/,
111exclude: /node_modules/,
112use: [
113{
114// vscode-nls-dev loader:
115// * rewrite nls-calls
116loader: "vscode-nls-dev/lib/webpack-loader",
117options: {
118base: path.join(__dirname),
119},
120},
121{
122// configure TypeScript loader:
123// * enable sources maps for end-to-end source maps
124loader: "ts-loader",
125options: {
126compilerOptions: {
127sourceMap: true,
128},
129},
130},
131],
132},
133],
134},
4bb0956eRedMickey5 years ago135optimization: {
136minimize: true,
137minimizer: [
138new TerserPlugin({
139terserOptions: {
140format: {
141comments: /^\**!|@preserve/i,
142},
143},
144extractComments: false,
145}),
146],
147},
34472878RedMickey5 years ago148node: {
149__dirname: false,
150__filename: false,
151},
152externals: {
153vscode: "commonjs vscode",
154},
155};
156
157if (library) {
158config.output.libraryTarget = "commonjs2";
159}
160
161if (process.argv.includes("--analyze-size")) {
162config.plugins = [
163new (require("webpack-bundle-analyzer").BundleAnalyzerPlugin)({
164analyzerMode: "static",
165reportFilename: path.resolve(distSrcDir, path.basename(entry) + ".html"),
166}),
167];
168}
169
170configs.push(config);
d55f3c22Yuri Skorokhodov5 years ago171}
2d8af448Yuri Skorokhodov6 years ago172
34472878RedMickey5 years ago173await new Promise((resolve, reject) =>
174webpack(configs, (err, stats) => {
175if (err) {
176reject(err);
177} else if (stats.hasErrors()) {
178reject(stats);
179} else {
180resolve();
181}
d55f3c22Yuri Skorokhodov5 years ago182}),
34472878RedMickey5 years ago183);
2d8af448Yuri Skorokhodov6 years ago184}
185
186// Generates ./dist/nls.bundle.<language_id>.json from files in ./i18n/** *//<src_path>/<filename>.i18n.json
187// Localized strings are read from these files at runtime.
188const generateSrcLocBundle = () => {
34472878RedMickey5 years ago189// Transpile the TS to JS, and let vscode-nls-dev scan the files for calls to localize.
190return tsProject
191.src()
192.pipe(sourcemaps.init())
193.pipe(tsProject())
194.js.pipe(nls.createMetaDataFiles())
195.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, "i18n"))
196.pipe(nls.bundleMetaDataFiles(fullExtensionName, "dist"))
197.pipe(nls.bundleLanguageFiles())
198.pipe(
199filter([
200"**/nls.bundle.*.json",
201"**/nls.metadata.header.json",
202"**/nls.metadata.json",
203"!src/**",
204]),
205)
206.pipe(gulp.dest("dist"));
2d8af448Yuri Skorokhodov6 years ago207};
208
5fd423caYuri Skorokhodov7 years ago209function build(failOnError, buildNls) {
34472878RedMickey5 years ago210const isProd = options.env === "production";
211const preprocessorContext = isProd ? { PROD: true } : { DEBUG: true };
212let gotError = false;
213log(`Building with preprocessor context: ${JSON.stringify(preprocessorContext)}`);
214const tsResult = tsProject
215.src()
216.pipe(preprocess({ context: preprocessorContext })) //To set environment variables in-line
217.pipe(sourcemaps.init())
218.pipe(tsProject());
219
220return tsResult.js
221.pipe(buildNls ? nls.rewriteLocalizeCalls() : es.through())
222.pipe(
223buildNls
224? nls.createAdditionalLanguageFiles(defaultLanguages, "i18n", ".")
225: es.through(),
226)
227.pipe(buildNls ? nls.bundleMetaDataFiles(fullExtensionName, ".") : es.through())
228.pipe(buildNls ? nls.bundleLanguageFiles() : es.through())
229.pipe(sourcemaps.write(".", { includeContent: false, sourceRoot: "." }))
230.pipe(gulp.dest(file => file.cwd))
231.once("error", () => {
232gotError = true;
233})
234.once("finish", () => {
235if (failOnError && gotError) {
236process.exit(1);
237}
238});
3aa3017bDmitry Zinovyev9 years ago239}
8ba55f4cJimmy Thomson10 years ago240
f311755cRedMickey5 years ago241async function test(inspectCodeCoverage = false) {
34472878RedMickey5 years ago242// Check if arguments were passed
243if (options.pattern) {
244log(`\nTesting cases that match pattern: ${options.pattern}`);
245} else {
246log(`\nTesting cases that don't match pattern: extensionContext|localizationContext`);
247}
248
249try {
250// The folder containing the Extension Manifest package.json
251// Passed to `--extensionDevelopmentPath`
252const extensionDevelopmentPath = __dirname;
253
254// The path to the extension test runner script
255// Passed to --extensionTestsPath
256const extensionTestsPath = path.resolve(__dirname, "test", "index");
257console.log(extensionTestsPath);
258// Download VS Code, unzip it and run the integration test
f311755cRedMickey5 years ago259
260const testOptions = {
34472878RedMickey5 years ago261extensionDevelopmentPath,
262extensionTestsPath,
f311755cRedMickey5 years ago263version: vscodeVersionForTests,
264};
265
266// Activate inspection of code coverage with unit tests
267if (inspectCodeCoverage) {
268testOptions.extensionTestsEnv = {
269COVERAGE: "true",
270};
271}
272
273await vscodeTest.runTests(testOptions);
34472878RedMickey5 years ago274} catch (err) {
275console.error(err);
276console.error("Failed to run tests");
277process.exit(1);
278}
f6ac01ceRuslan Bikkinin7 years ago279}
280
09f6024fHeniker4 years ago281const runPrettier = async fix => {
34472878RedMickey5 years ago282const child = cp.fork(
283"./node_modules/@mixer/parallel-prettier/dist/index.js",
284[
285fix ? "--write" : "--list-different",
286"test/**/*.ts",
287"gulpfile.js",
288"*.md",
289"!CHANGELOG.md",
290"!test/smoke/**",
291"!src/**/*.d.ts",
292],
293{
294stdio: "inherit",
295},
296);
297
09f6024fHeniker4 years ago298await new Promise((resolve, reject) => {
299child.on("exit", code => {
300code ? reject(`Prettier exited with code ${code}`) : resolve();
301});
302});
303};
304
305/**
519795a9Heniker4 years ago306* @typedef {{color: boolean, fix: boolean}} OptionsT
09f6024fHeniker4 years ago307*/
308
309/**
310* @param {OptionsT} options_
311*/
312const runEslint = async options_ => {
313/** @type {OptionsT} */
519795a9Heniker4 years ago314const options = Object.assign({ color: true, fix: false }, options_);
09f6024fHeniker4 years ago315
519795a9Heniker4 years ago316const files = ["src/**/*.ts"];
09f6024fHeniker4 years ago317
318const args = [
319...(options.color ? ["--color"] : ["--no-color"]),
320...(options.fix ? ["--fix"] : []),
321...files,
322];
323
41d17648RedMickey5 years ago324const child = cp.fork("./node_modules/eslint/bin/eslint.js", args, {
325stdio: "inherit",
326cwd: __dirname,
327});
34472878RedMickey5 years ago328
09f6024fHeniker4 years ago329await new Promise((resolve, reject) => {
330child.on("exit", code => {
331code ? reject(`Eslint exited with code ${code}`) : resolve();
332});
333});
d55f3c22Yuri Skorokhodov5 years ago334};
4f8669f9JiglioNero6 years ago335
09f6024fHeniker4 years ago336gulp.task("format:prettier", () => runPrettier(true));
337gulp.task("format:eslint", () => runEslint({ fix: true }));
34472878RedMickey5 years ago338gulp.task("format", gulp.series("format:prettier", "format:eslint"));
339
09f6024fHeniker4 years ago340gulp.task("lint:prettier", () => runPrettier(false));
341gulp.task("lint:eslint", () => runEslint({ fix: false }));
342gulp.task("lint", gulp.series("lint:prettier", "lint:eslint"));
fc602bb6Yuri Skorokhodov7 years ago343
2d8af448Yuri Skorokhodov6 years ago344/** Run webpack to bundle the extension output files */
345gulp.task("webpack-bundle", async () => {
34472878RedMickey5 years ago346const packages = [
347{
09f6024fHeniker4 years ago348entry: `${srcPath}/extension/rn-extension.ts`,
34472878RedMickey5 years ago349filename: "rn-extension.js",
350library: true,
351},
352];
353return runWebpack({ packages });
2d8af448Yuri Skorokhodov6 years ago354});
355
356gulp.task("clean", () => {
34472878RedMickey5 years ago357const pathsToDelete = [
358"src/**/*.js",
359"src/**/*.js.map",
360"test/**/*.js",
361"test/**/*.js.map",
362"out/",
363"dist",
3c116e19RedMickey4 years ago364"!test/resources/sampleReactNativeProject/**/*.js",
34472878RedMickey5 years ago365".vscode-test/",
366"nls.*.json",
367"!test/smoke/**/*",
368];
369return del(pathsToDelete, { force: true });
2d8af448Yuri Skorokhodov6 years ago370});
371
5fd423caYuri Skorokhodov7 years ago372// TODO: The file property should point to the generated source (this implementation adds an extra folder to the path)
373// We should also make sure that we always generate urls in all the path properties (We shouldn"t have \\s. This seems to
374// be an issue on Windows platforms)
d55f3c22Yuri Skorokhodov5 years ago375gulp.task(
34472878RedMickey5 years ago376"build",
09f6024fHeniker4 years ago377gulp.series("lint", function runBuild(done) {
34472878RedMickey5 years ago378build(true, true).once("finish", () => {
379done();
380});
381}),
d55f3c22Yuri Skorokhodov5 years ago382);
383
716c1b85RedMickey4 years ago384gulp.task("build-dev", function runDevBuild(done) {
09f6024fHeniker4 years ago385build(true, false).once("finish", () => {
386done();
387});
388});
5fd423caYuri Skorokhodov7 years ago389
fc602bb6Yuri Skorokhodov7 years ago390gulp.task("quick-build", gulp.series("build-dev"));
5fd423caYuri Skorokhodov7 years ago391
d55f3c22Yuri Skorokhodov5 years ago392gulp.task(
34472878RedMickey5 years ago393"watch",
394gulp.series("build", function runWatch() {
395log("Watching build sources...");
396return gulp.watch(sources, gulp.series("build"));
397}),
d55f3c22Yuri Skorokhodov5 years ago398);
8ba55f4cJimmy Thomson10 years ago399
34472878RedMickey5 years ago400gulp.task("prod-build", gulp.series("clean", "webpack-bundle", generateSrcLocBundle));
8ba55f4cJimmy Thomson10 years ago401
2d8af448Yuri Skorokhodov6 years ago402gulp.task("default", gulp.series("prod-build"));
5fd423caYuri Skorokhodov7 years ago403
34472878RedMickey5 years ago404gulp.task("test", gulp.series("build", "lint", test));
28d84585Vladimir Kotikov8 years ago405
62b110e3Dmitry Zinovyev9 years ago406gulp.task("test-no-build", test);
8ba55f4cJimmy Thomson10 years ago407
d55f3c22Yuri Skorokhodov5 years ago408gulp.task(
34472878RedMickey5 years ago409"test:coverage",
f311755cRedMickey5 years ago410gulp.series("quick-build", async function () {
411await test(true);
412}),
d55f3c22Yuri Skorokhodov5 years ago413);
414
415gulp.task(
34472878RedMickey5 years ago416"watch-build-test",
417gulp.series("build", "test", function runWatch() {
418return gulp.watch(sources, gulp.series("build", "test"));
419}),
d55f3c22Yuri Skorokhodov5 years ago420);
7212311dDaniel Lebu10 years ago421
34472878RedMickey5 years ago422gulp.task("package", callback => {
423const command = path.join(__dirname, "node_modules", ".bin", "vsce");
424const args = ["package"];
425executeCommand(command, args, callback);
92f13422Jimmy Thomson9 years ago426});
427
17bf2e64Yuri Skorokhodov6 years ago428function readJson(file) {
34472878RedMickey5 years ago429const contents = fs.readFileSync(path.join(__dirname, file), "utf-8").toString();
430return JSON.parse(contents);
17bf2e64Yuri Skorokhodov6 years ago431}
432
433function writeJson(file, jsonObj) {
34472878RedMickey5 years ago434const content = JSON.stringify(jsonObj, null, 2);
435fs.writeFileSync(path.join(__dirname, file), content);
17bf2e64Yuri Skorokhodov6 years ago436}
437
2d8af448Yuri Skorokhodov6 years ago438/**
439* Generate version number for a nightly build.
440*/
17bf2e64Yuri Skorokhodov6 years ago441const getVersionNumber = () => {
34472878RedMickey5 years ago442const date = new Date(new Date().toLocaleString("en-US", { timeZone: "America/Los_Angeles" }));
443
444return [
445// YY
446date.getFullYear(),
447// MM,
448date.getMonth() + 1,
449//DDHH
450`${date.getDate()}${String(date.getHours()).padStart(2, "0")}`,
451].join(".");
17bf2e64Yuri Skorokhodov6 years ago452};
453
2d8af448Yuri Skorokhodov6 years ago454gulp.task("release", function prepareLicenses() {
34472878RedMickey5 years ago455const backupFiles = [
456"LICENSE.txt",
d55f3c22Yuri Skorokhodov5 years ago457"ThirdPartyNotices.txt",
34472878RedMickey5 years ago458"package.json",
459"package-lock.json",
460];
461const backupFolder = path.resolve(path.join(os.tmpdir(), "vscode-react-native"));
462if (!fs.existsSync(backupFolder)) {
463fs.mkdirSync(backupFolder);
464}
465
466return Promise.resolve()
467.then(() => {
468/* back up LICENSE.txt, ThirdPartyNotices.txt, README.md */
469log("Backing up license files to " + backupFolder + "...");
470backupFiles.forEach(fileName => {
471fs.writeFileSync(path.join(backupFolder, fileName), fs.readFileSync(fileName));
472});
473
474/* copy over the release package license files */
475log("Preparing license files for release...");
476fs.writeFileSync("LICENSE.txt", fs.readFileSync("release/LICENSE.txt"));
477fs.writeFileSync(
478"ThirdPartyNotices.txt",
479fs.readFileSync("release/ThirdPartyNotices.txt"),
480);
481})
482.then(() => {
483let packageJson = readJson("package.json");
484packageJson.main = "./dist/rn-extension";
485if (isNightly) {
486log("Performing nightly release...");
487packageJson.version = getVersionNumber();
488packageJson.name = extensionName;
489packageJson.preview = true;
490packageJson.displayName += " (Preview)";
17bf2e64Yuri Skorokhodov6 years ago491}
34472878RedMickey5 years ago492writeJson("package.json", packageJson);
493log("Creating release package...");
494return new Promise((resolve, reject) => {
495// NOTE: vsce must see npm 3.X otherwise it will not correctly strip out dev dependencies.
496executeCommand(
497"vsce",
498["package"],
499arg => {
500if (arg) {
501reject(arg);
502}
503resolve();
504},
505{ cwd: path.resolve(__dirname) },
506);
507});
508})
509.finally(() => {
510/* restore backed up files */
511log("Restoring modified files...");
512backupFiles.forEach(fileName => {
513fs.writeFileSync(
514path.join(__dirname, fileName),
515fs.readFileSync(path.join(backupFolder, fileName)),
516);
517});
518});
2d8af448Yuri Skorokhodov6 years ago519});
74dba829Yuri Skorokhodov7 years ago520
fc602bb6Yuri Skorokhodov7 years ago521// Creates package.i18n.json files for all languages from {workspaceRoot}/i18n folder into project root
f6ac01ceRuslan Bikkinin7 years ago522gulp.task("add-i18n", () => {
34472878RedMickey5 years ago523return gulp
524.src(["package.nls.json"])
525.pipe(nls.createAdditionalLanguageFiles(defaultLanguages, "i18n"))
526.pipe(gulp.dest("."));
74dba829Yuri Skorokhodov7 years ago527});
528
b6c68212Yuri Skorokhodov7 years ago529// Creates MLCP readable .xliff file and saves it locally
d55f3c22Yuri Skorokhodov5 years ago530gulp.task(
34472878RedMickey5 years ago531"translations-export",
532gulp.series("build", function runTranslationExport() {
533return gulp
534.src(["package.nls.json", "nls.metadata.header.json", "nls.metadata.json"])
535.pipe(nls.createXlfFiles(translationProjectName, fullExtensionName))
536.pipe(gulp.dest(path.join("..", `${translationProjectName}-localization-export`)));
537}),
d55f3c22Yuri Skorokhodov5 years ago538);
74dba829Yuri Skorokhodov7 years ago539
b6c68212Yuri Skorokhodov7 years ago540// Imports localization from raw localized MLCP strings to VS Code .i18n.json files
d55f3c22Yuri Skorokhodov5 years ago541gulp.task(
34472878RedMickey5 years ago542"translations-import",
543gulp.series(done => {
544var options = minimist(process.argv.slice(2), {
545string: "location",
546default: {
547location: "../vscode-translations-import",
548},
549});
550es.merge(
551defaultLanguages.map(language => {
552let id = language.transifexId || language.id;
553log(
554path.join(
555options.location,
556id,
557"vscode-extensions",
558`${fullExtensionName}.xlf`,
559),
560);
561return gulp
562.src(
563path.join(
564options.location,
565id,
566"vscode-extensions",
567`${fullExtensionName}.xlf`,
568),
569)
570.pipe(nls.prepareJsonFiles())
571.pipe(gulp.dest(path.join("./i18n", language.folderName)));
572}),
573).pipe(
574es.wait(() => {
575done();
576}),
d55f3c22Yuri Skorokhodov5 years ago577);
34472878RedMickey5 years ago578}, "add-i18n"),
d55f3c22Yuri Skorokhodov5 years ago579);