Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
microsoft
GitHub Repository: microsoft/vscode
Path: blob/main/build/gulpfile.extensions.ts
4770 views
1
/*---------------------------------------------------------------------------------------------
2
* Copyright (c) Microsoft Corporation. All rights reserved.
3
* Licensed under the MIT License. See License.txt in the project root for license information.
4
*--------------------------------------------------------------------------------------------*/
5
6
// Increase max listeners for event emitters
7
import { EventEmitter } from 'events';
8
EventEmitter.defaultMaxListeners = 100;
9
10
import gulp from 'gulp';
11
import * as path from 'path';
12
import * as nodeUtil from 'util';
13
import es from 'event-stream';
14
import filter from 'gulp-filter';
15
import * as util from './lib/util.ts';
16
import { getVersion } from './lib/getVersion.ts';
17
import * as task from './lib/task.ts';
18
import watcher from './lib/watch/index.ts';
19
import { createReporter } from './lib/reporter.ts';
20
import glob from 'glob';
21
import plumber from 'gulp-plumber';
22
import * as ext from './lib/extensions.ts';
23
import * as tsb from './lib/tsb/index.ts';
24
import sourcemaps from 'gulp-sourcemaps';
25
26
const root = path.dirname(import.meta.dirname);
27
const commit = getVersion(root);
28
29
// To save 250ms for each gulp startup, we are caching the result here
30
// const compilations = glob.sync('**/tsconfig.json', {
31
// cwd: extensionsPath,
32
// ignore: ['**/out/**', '**/node_modules/**']
33
// });
34
const compilations = [
35
'extensions/configuration-editing/tsconfig.json',
36
'extensions/css-language-features/client/tsconfig.json',
37
'extensions/css-language-features/server/tsconfig.json',
38
'extensions/debug-auto-launch/tsconfig.json',
39
'extensions/debug-server-ready/tsconfig.json',
40
'extensions/emmet/tsconfig.json',
41
'extensions/extension-editing/tsconfig.json',
42
'extensions/git/tsconfig.json',
43
'extensions/git-base/tsconfig.json',
44
'extensions/github/tsconfig.json',
45
'extensions/github-authentication/tsconfig.json',
46
'extensions/grunt/tsconfig.json',
47
'extensions/gulp/tsconfig.json',
48
'extensions/html-language-features/client/tsconfig.json',
49
'extensions/html-language-features/server/tsconfig.json',
50
'extensions/ipynb/tsconfig.json',
51
'extensions/jake/tsconfig.json',
52
'extensions/json-language-features/client/tsconfig.json',
53
'extensions/json-language-features/server/tsconfig.json',
54
'extensions/markdown-language-features/tsconfig.json',
55
'extensions/markdown-math/tsconfig.json',
56
'extensions/media-preview/tsconfig.json',
57
'extensions/merge-conflict/tsconfig.json',
58
'extensions/mermaid-chat-features/tsconfig.json',
59
'extensions/terminal-suggest/tsconfig.json',
60
'extensions/microsoft-authentication/tsconfig.json',
61
'extensions/notebook-renderers/tsconfig.json',
62
'extensions/npm/tsconfig.json',
63
'extensions/php-language-features/tsconfig.json',
64
'extensions/references-view/tsconfig.json',
65
'extensions/search-result/tsconfig.json',
66
'extensions/simple-browser/tsconfig.json',
67
'extensions/tunnel-forwarding/tsconfig.json',
68
'extensions/typescript-language-features/web/tsconfig.json',
69
'extensions/typescript-language-features/tsconfig.json',
70
'extensions/vscode-api-tests/tsconfig.json',
71
'extensions/vscode-colorize-tests/tsconfig.json',
72
'extensions/vscode-colorize-perf-tests/tsconfig.json',
73
'extensions/vscode-test-resolver/tsconfig.json',
74
75
'.vscode/extensions/vscode-selfhost-test-provider/tsconfig.json',
76
'.vscode/extensions/vscode-selfhost-import-aid/tsconfig.json',
77
];
78
79
const getBaseUrl = (out: string) => `https://main.vscode-cdn.net/sourcemaps/${commit}/${out}`;
80
81
const tasks = compilations.map(function (tsconfigFile) {
82
const absolutePath = path.join(root, tsconfigFile);
83
const relativeDirname = path.dirname(tsconfigFile.replace(/^(.*\/)?extensions\//i, ''));
84
85
const overrideOptions: { sourceMap?: boolean; inlineSources?: boolean; base?: string } = {};
86
overrideOptions.sourceMap = true;
87
88
const name = relativeDirname.replace(/\//g, '-');
89
90
const srcRoot = path.dirname(tsconfigFile);
91
const srcBase = path.join(srcRoot, 'src');
92
const src = path.join(srcBase, '**');
93
const srcOpts = { cwd: root, base: srcBase, dot: true };
94
95
const out = path.join(srcRoot, 'out');
96
const baseUrl = getBaseUrl(out);
97
98
function createPipeline(build: boolean, emitError?: boolean, transpileOnly?: boolean) {
99
const reporter = createReporter('extensions');
100
101
overrideOptions.inlineSources = Boolean(build);
102
overrideOptions.base = path.dirname(absolutePath);
103
104
const compilation = tsb.create(absolutePath, overrideOptions, { verbose: false, transpileOnly, transpileOnlyIncludesDts: transpileOnly, transpileWithEsbuild: true }, err => reporter(err.toString()));
105
106
const pipeline = function () {
107
const input = es.through();
108
const tsFilter = filter(['**/*.ts', '!**/lib/lib*.d.ts', '!**/node_modules/**'], { restore: true, dot: true });
109
const output = input
110
.pipe(plumber({
111
errorHandler: function (err) {
112
if (err && !err.__reporter__) {
113
reporter(err);
114
}
115
}
116
}))
117
.pipe(tsFilter)
118
.pipe(util.loadSourcemaps())
119
.pipe(compilation())
120
.pipe(build ? util.stripSourceMappingURL() : es.through())
121
.pipe(sourcemaps.write('.', {
122
sourceMappingURL: !build ? undefined : f => `${baseUrl}/${f.relative}.map`,
123
addComment: !!build,
124
includeContent: !!build,
125
// note: trailing slash is important, else the source URLs in V8's file coverage are incorrect
126
sourceRoot: '../src/',
127
}))
128
.pipe(tsFilter.restore)
129
.pipe(reporter.end(!!emitError));
130
131
return es.duplex(input, output);
132
};
133
134
// add src-stream for project files
135
pipeline.tsProjectSrc = () => {
136
return compilation.src(srcOpts);
137
};
138
return pipeline;
139
}
140
141
const cleanTask = task.define(`clean-extension-${name}`, util.rimraf(out));
142
143
const transpileTask = task.define(`transpile-extension:${name}`, task.series(cleanTask, () => {
144
const pipeline = createPipeline(false, true, true);
145
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
146
const input = es.merge(nonts, pipeline.tsProjectSrc());
147
148
return input
149
.pipe(pipeline())
150
.pipe(gulp.dest(out));
151
}));
152
153
const compileTask = task.define(`compile-extension:${name}`, task.series(cleanTask, () => {
154
const pipeline = createPipeline(false, true);
155
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
156
const input = es.merge(nonts, pipeline.tsProjectSrc());
157
158
return input
159
.pipe(pipeline())
160
.pipe(gulp.dest(out));
161
}));
162
163
const watchTask = task.define(`watch-extension:${name}`, task.series(cleanTask, () => {
164
const pipeline = createPipeline(false);
165
const nonts = gulp.src(src, srcOpts).pipe(filter(['**', '!**/*.ts']));
166
const input = es.merge(nonts, pipeline.tsProjectSrc());
167
const watchInput = watcher(src, { ...srcOpts, ...{ readDelay: 200 } });
168
169
return watchInput
170
.pipe(util.incremental(pipeline, input))
171
.pipe(gulp.dest(out));
172
}));
173
174
// Tasks
175
gulp.task(transpileTask);
176
gulp.task(compileTask);
177
gulp.task(watchTask);
178
179
return { transpileTask, compileTask, watchTask };
180
});
181
182
const transpileExtensionsTask = task.define('transpile-extensions', task.parallel(...tasks.map(t => t.transpileTask)));
183
gulp.task(transpileExtensionsTask);
184
185
export const compileExtensionsTask = task.define('compile-extensions', task.parallel(...tasks.map(t => t.compileTask)));
186
gulp.task(compileExtensionsTask);
187
188
export const watchExtensionsTask = task.define('watch-extensions', task.parallel(...tasks.map(t => t.watchTask)));
189
gulp.task(watchExtensionsTask);
190
191
//#region Extension media
192
193
export const compileExtensionMediaTask = task.define('compile-extension-media', () => ext.buildExtensionMedia(false));
194
gulp.task(compileExtensionMediaTask);
195
196
export const watchExtensionMedia = task.define('watch-extension-media', () => ext.buildExtensionMedia(true));
197
gulp.task(watchExtensionMedia);
198
199
export const compileExtensionMediaBuildTask = task.define('compile-extension-media-build', () => ext.buildExtensionMedia(false, '.build/extensions'));
200
gulp.task(compileExtensionMediaBuildTask);
201
202
//#endregion
203
204
//#region Azure Pipelines
205
206
/**
207
* Cleans the build directory for extensions
208
*/
209
export const cleanExtensionsBuildTask = task.define('clean-extensions-build', util.rimraf('.build/extensions'));
210
211
/**
212
* brings in the marketplace extensions for the build
213
*/
214
const bundleMarketplaceExtensionsBuildTask = task.define('bundle-marketplace-extensions-build', () => ext.packageMarketplaceExtensionsStream(false).pipe(gulp.dest('.build')));
215
216
/**
217
* Compiles the non-native extensions for the build
218
* @note this does not clean the directory ahead of it. See {@link cleanExtensionsBuildTask} for that.
219
*/
220
export const compileNonNativeExtensionsBuildTask = task.define('compile-non-native-extensions-build', task.series(
221
bundleMarketplaceExtensionsBuildTask,
222
task.define('bundle-non-native-extensions-build', () => ext.packageNonNativeLocalExtensionsStream(false, false).pipe(gulp.dest('.build')))
223
));
224
gulp.task(compileNonNativeExtensionsBuildTask);
225
226
/**
227
* Compiles the native extensions for the build
228
* @note this does not clean the directory ahead of it. See {@link cleanExtensionsBuildTask} for that.
229
*/
230
export const compileNativeExtensionsBuildTask = task.define('compile-native-extensions-build', () => ext.packageNativeLocalExtensionsStream(false, false).pipe(gulp.dest('.build')));
231
gulp.task(compileNativeExtensionsBuildTask);
232
233
/**
234
* Compiles the extensions for the build.
235
* This is essentially a helper task that combines {@link cleanExtensionsBuildTask}, {@link compileNonNativeExtensionsBuildTask} and {@link compileNativeExtensionsBuildTask}
236
*/
237
export const compileAllExtensionsBuildTask = task.define('compile-extensions-build', task.series(
238
cleanExtensionsBuildTask,
239
bundleMarketplaceExtensionsBuildTask,
240
task.define('bundle-extensions-build', () => ext.packageAllLocalExtensionsStream(false, false).pipe(gulp.dest('.build'))),
241
));
242
gulp.task(compileAllExtensionsBuildTask);
243
244
// This task is run in the compilation stage of the CI pipeline. We only compile the non-native extensions since those can be fully built regardless of platform.
245
// This defers the native extensions to the platform specific stage of the CI pipeline.
246
gulp.task(task.define('extensions-ci', task.series(compileNonNativeExtensionsBuildTask, compileExtensionMediaBuildTask)));
247
248
const compileExtensionsBuildPullRequestTask = task.define('compile-extensions-build-pr', task.series(
249
cleanExtensionsBuildTask,
250
bundleMarketplaceExtensionsBuildTask,
251
task.define('bundle-extensions-build-pr', () => ext.packageAllLocalExtensionsStream(false, true).pipe(gulp.dest('.build'))),
252
));
253
gulp.task(compileExtensionsBuildPullRequestTask);
254
255
// This task is run in the compilation stage of the PR pipeline. We compile all extensions in it to verify compilation.
256
gulp.task(task.define('extensions-ci-pr', task.series(compileExtensionsBuildPullRequestTask, compileExtensionMediaBuildTask)));
257
258
//#endregion
259
260
export const compileWebExtensionsTask = task.define('compile-web', () => buildWebExtensions(false));
261
gulp.task(compileWebExtensionsTask);
262
263
export const watchWebExtensionsTask = task.define('watch-web', () => buildWebExtensions(true));
264
gulp.task(watchWebExtensionsTask);
265
266
async function buildWebExtensions(isWatch: boolean) {
267
const extensionsPath = path.join(root, 'extensions');
268
const webpackConfigLocations = await nodeUtil.promisify(glob)(
269
path.join(extensionsPath, '**', 'extension-browser.webpack.config.js'),
270
{ ignore: ['**/node_modules'] }
271
);
272
return ext.webpackExtensions('packaging web extension', isWatch, webpackConfigLocations.map(configPath => ({ configPath })));
273
}
274
275