mirror of
https://github.com/Microsoft/vscode
synced 2024-10-06 03:17:00 +00:00
remove build compilation output
This commit is contained in:
parent
0ca320561a
commit
2469bf6832
|
@ -1,61 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const codesign = require("electron-osx-sign");
|
||||
const path = require("path");
|
||||
const util = require("../lib/util");
|
||||
const product = require("../../product.json");
|
||||
async function main() {
|
||||
const buildDir = process.env['AGENT_BUILDDIRECTORY'];
|
||||
const tempDir = process.env['AGENT_TEMPDIRECTORY'];
|
||||
if (!buildDir) {
|
||||
throw new Error('$AGENT_BUILDDIRECTORY not set');
|
||||
}
|
||||
if (!tempDir) {
|
||||
throw new Error('$AGENT_TEMPDIRECTORY not set');
|
||||
}
|
||||
const baseDir = path.dirname(__dirname);
|
||||
const appRoot = path.join(buildDir, 'VSCode-darwin');
|
||||
const appName = product.nameLong + '.app';
|
||||
const appFrameworkPath = path.join(appRoot, appName, 'Contents', 'Frameworks');
|
||||
const helperAppBaseName = product.nameShort;
|
||||
const gpuHelperAppName = helperAppBaseName + ' Helper (GPU).app';
|
||||
const pluginHelperAppName = helperAppBaseName + ' Helper (Plugin).app';
|
||||
const rendererHelperAppName = helperAppBaseName + ' Helper (Renderer).app';
|
||||
const defaultOpts = {
|
||||
app: path.join(appRoot, appName),
|
||||
platform: 'darwin',
|
||||
entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
|
||||
'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'app-entitlements.plist'),
|
||||
hardenedRuntime: true,
|
||||
'pre-auto-entitlements': false,
|
||||
'pre-embed-provisioning-profile': false,
|
||||
keychain: path.join(tempDir, 'buildagent.keychain'),
|
||||
version: util.getElectronVersion(),
|
||||
identity: '99FM488X57',
|
||||
'gatekeeper-assess': false
|
||||
};
|
||||
const appOpts = Object.assign(Object.assign({}, defaultOpts), {
|
||||
// TODO(deepak1556): Incorrectly declared type in electron-osx-sign
|
||||
ignore: (filePath) => {
|
||||
return filePath.includes(gpuHelperAppName) ||
|
||||
filePath.includes(pluginHelperAppName) ||
|
||||
filePath.includes(rendererHelperAppName);
|
||||
} });
|
||||
const gpuHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, gpuHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-gpu-entitlements.plist') });
|
||||
const pluginHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, pluginHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-plugin-entitlements.plist') });
|
||||
const rendererHelperOpts = Object.assign(Object.assign({}, defaultOpts), { app: path.join(appFrameworkPath, rendererHelperAppName), entitlements: path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist'), 'entitlements-inherit': path.join(baseDir, 'azure-pipelines', 'darwin', 'helper-renderer-entitlements.plist') });
|
||||
await codesign.signAsync(gpuHelperOpts);
|
||||
await codesign.signAsync(pluginHelperOpts);
|
||||
await codesign.signAsync(rendererHelperOpts);
|
||||
await codesign.signAsync(appOpts);
|
||||
}
|
||||
if (require.main === module) {
|
||||
main().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createAsar = void 0;
|
||||
const path = require("path");
|
||||
const es = require("event-stream");
|
||||
const pickle = require('chromium-pickle-js');
|
||||
const Filesystem = require('asar/lib/filesystem');
|
||||
const VinylFile = require("vinyl");
|
||||
const minimatch = require("minimatch");
|
||||
function createAsar(folderPath, unpackGlobs, destFilename) {
|
||||
const shouldUnpackFile = (file) => {
|
||||
for (let i = 0; i < unpackGlobs.length; i++) {
|
||||
if (minimatch(file.relative, unpackGlobs[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
};
|
||||
const filesystem = new Filesystem(folderPath);
|
||||
const out = [];
|
||||
// Keep track of pending inserts
|
||||
let pendingInserts = 0;
|
||||
let onFileInserted = () => { pendingInserts--; };
|
||||
// Do not insert twice the same directory
|
||||
const seenDir = {};
|
||||
const insertDirectoryRecursive = (dir) => {
|
||||
if (seenDir[dir]) {
|
||||
return;
|
||||
}
|
||||
let lastSlash = dir.lastIndexOf('/');
|
||||
if (lastSlash === -1) {
|
||||
lastSlash = dir.lastIndexOf('\\');
|
||||
}
|
||||
if (lastSlash !== -1) {
|
||||
insertDirectoryRecursive(dir.substring(0, lastSlash));
|
||||
}
|
||||
seenDir[dir] = true;
|
||||
filesystem.insertDirectory(dir);
|
||||
};
|
||||
const insertDirectoryForFile = (file) => {
|
||||
let lastSlash = file.lastIndexOf('/');
|
||||
if (lastSlash === -1) {
|
||||
lastSlash = file.lastIndexOf('\\');
|
||||
}
|
||||
if (lastSlash !== -1) {
|
||||
insertDirectoryRecursive(file.substring(0, lastSlash));
|
||||
}
|
||||
};
|
||||
const insertFile = (relativePath, stat, shouldUnpack) => {
|
||||
insertDirectoryForFile(relativePath);
|
||||
pendingInserts++;
|
||||
// Do not pass `onFileInserted` directly because it gets overwritten below.
|
||||
// Create a closure capturing `onFileInserted`.
|
||||
filesystem.insertFile(relativePath, shouldUnpack, { stat: stat }, {}).then(() => onFileInserted(), () => onFileInserted());
|
||||
};
|
||||
return es.through(function (file) {
|
||||
if (file.stat.isDirectory()) {
|
||||
return;
|
||||
}
|
||||
if (!file.stat.isFile()) {
|
||||
throw new Error(`unknown item in stream!`);
|
||||
}
|
||||
const shouldUnpack = shouldUnpackFile(file);
|
||||
insertFile(file.relative, { size: file.contents.length, mode: file.stat.mode }, shouldUnpack);
|
||||
if (shouldUnpack) {
|
||||
// The file goes outside of xx.asar, in a folder xx.asar.unpacked
|
||||
const relative = path.relative(folderPath, file.path);
|
||||
this.queue(new VinylFile({
|
||||
cwd: folderPath,
|
||||
base: folderPath,
|
||||
path: path.join(destFilename + '.unpacked', relative),
|
||||
stat: file.stat,
|
||||
contents: file.contents
|
||||
}));
|
||||
}
|
||||
else {
|
||||
// The file goes inside of xx.asar
|
||||
out.push(file.contents);
|
||||
}
|
||||
}, function () {
|
||||
let finish = () => {
|
||||
{
|
||||
const headerPickle = pickle.createEmpty();
|
||||
headerPickle.writeString(JSON.stringify(filesystem.header));
|
||||
const headerBuf = headerPickle.toBuffer();
|
||||
const sizePickle = pickle.createEmpty();
|
||||
sizePickle.writeUInt32(headerBuf.length);
|
||||
const sizeBuf = sizePickle.toBuffer();
|
||||
out.unshift(headerBuf);
|
||||
out.unshift(sizeBuf);
|
||||
}
|
||||
const contents = Buffer.concat(out);
|
||||
out.length = 0;
|
||||
this.queue(new VinylFile({
|
||||
cwd: folderPath,
|
||||
base: folderPath,
|
||||
path: destFilename,
|
||||
contents: contents
|
||||
}));
|
||||
this.queue(null);
|
||||
};
|
||||
// Call finish() only when all file inserts have finished...
|
||||
if (pendingInserts === 0) {
|
||||
finish();
|
||||
}
|
||||
else {
|
||||
onFileInserted = () => {
|
||||
pendingInserts--;
|
||||
if (pendingInserts === 0) {
|
||||
finish();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.createAsar = createAsar;
|
|
@ -1,464 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.bundle = void 0;
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vm = require("vm");
|
||||
/**
|
||||
* Bundle `entryPoints` given config `config`.
|
||||
*/
|
||||
function bundle(entryPoints, config, callback) {
|
||||
const entryPointsMap = {};
|
||||
entryPoints.forEach((module) => {
|
||||
entryPointsMap[module.name] = module;
|
||||
});
|
||||
const allMentionedModulesMap = {};
|
||||
entryPoints.forEach((module) => {
|
||||
allMentionedModulesMap[module.name] = true;
|
||||
(module.include || []).forEach(function (includedModule) {
|
||||
allMentionedModulesMap[includedModule] = true;
|
||||
});
|
||||
(module.exclude || []).forEach(function (excludedModule) {
|
||||
allMentionedModulesMap[excludedModule] = true;
|
||||
});
|
||||
});
|
||||
const code = require('fs').readFileSync(path.join(__dirname, '../../src/vs/loader.js'));
|
||||
const r = vm.runInThisContext('(function(require, module, exports) { ' + code + '\n});');
|
||||
const loaderModule = { exports: {} };
|
||||
r.call({}, require, loaderModule, loaderModule.exports);
|
||||
const loader = loaderModule.exports;
|
||||
config.isBuild = true;
|
||||
config.paths = config.paths || {};
|
||||
if (!config.paths['vs/nls']) {
|
||||
config.paths['vs/nls'] = 'out-build/vs/nls.build';
|
||||
}
|
||||
if (!config.paths['vs/css']) {
|
||||
config.paths['vs/css'] = 'out-build/vs/css.build';
|
||||
}
|
||||
loader.config(config);
|
||||
loader(['require'], (localRequire) => {
|
||||
const resolvePath = (path) => {
|
||||
const r = localRequire.toUrl(path);
|
||||
if (!/\.js/.test(r)) {
|
||||
return r + '.js';
|
||||
}
|
||||
return r;
|
||||
};
|
||||
for (const moduleId in entryPointsMap) {
|
||||
const entryPoint = entryPointsMap[moduleId];
|
||||
if (entryPoint.append) {
|
||||
entryPoint.append = entryPoint.append.map(resolvePath);
|
||||
}
|
||||
if (entryPoint.prepend) {
|
||||
entryPoint.prepend = entryPoint.prepend.map(resolvePath);
|
||||
}
|
||||
}
|
||||
});
|
||||
loader(Object.keys(allMentionedModulesMap), () => {
|
||||
const modules = loader.getBuildInfo();
|
||||
const partialResult = emitEntryPoints(modules, entryPointsMap);
|
||||
const cssInlinedResources = loader('vs/css').getInlinedResources();
|
||||
callback(null, {
|
||||
files: partialResult.files,
|
||||
cssInlinedResources: cssInlinedResources,
|
||||
bundleData: partialResult.bundleData
|
||||
});
|
||||
}, (err) => callback(err, null));
|
||||
}
|
||||
exports.bundle = bundle;
|
||||
function emitEntryPoints(modules, entryPoints) {
|
||||
const modulesMap = {};
|
||||
modules.forEach((m) => {
|
||||
modulesMap[m.id] = m;
|
||||
});
|
||||
const modulesGraph = {};
|
||||
modules.forEach((m) => {
|
||||
modulesGraph[m.id] = m.dependencies;
|
||||
});
|
||||
const sortedModules = topologicalSort(modulesGraph);
|
||||
let result = [];
|
||||
const usedPlugins = {};
|
||||
const bundleData = {
|
||||
graph: modulesGraph,
|
||||
bundles: {}
|
||||
};
|
||||
Object.keys(entryPoints).forEach((moduleToBundle) => {
|
||||
const info = entryPoints[moduleToBundle];
|
||||
const rootNodes = [moduleToBundle].concat(info.include || []);
|
||||
const allDependencies = visit(rootNodes, modulesGraph);
|
||||
const excludes = ['require', 'exports', 'module'].concat(info.exclude || []);
|
||||
excludes.forEach((excludeRoot) => {
|
||||
const allExcludes = visit([excludeRoot], modulesGraph);
|
||||
Object.keys(allExcludes).forEach((exclude) => {
|
||||
delete allDependencies[exclude];
|
||||
});
|
||||
});
|
||||
const includedModules = sortedModules.filter((module) => {
|
||||
return allDependencies[module];
|
||||
});
|
||||
bundleData.bundles[moduleToBundle] = includedModules;
|
||||
const res = emitEntryPoint(modulesMap, modulesGraph, moduleToBundle, includedModules, info.prepend || [], info.append || [], info.dest);
|
||||
result = result.concat(res.files);
|
||||
for (const pluginName in res.usedPlugins) {
|
||||
usedPlugins[pluginName] = usedPlugins[pluginName] || res.usedPlugins[pluginName];
|
||||
}
|
||||
});
|
||||
Object.keys(usedPlugins).forEach((pluginName) => {
|
||||
const plugin = usedPlugins[pluginName];
|
||||
if (typeof plugin.finishBuild === 'function') {
|
||||
const write = (filename, contents) => {
|
||||
result.push({
|
||||
dest: filename,
|
||||
sources: [{
|
||||
path: null,
|
||||
contents: contents
|
||||
}]
|
||||
});
|
||||
};
|
||||
plugin.finishBuild(write);
|
||||
}
|
||||
});
|
||||
return {
|
||||
// TODO@TS 2.1.2
|
||||
files: extractStrings(removeDuplicateTSBoilerplate(result)),
|
||||
bundleData: bundleData
|
||||
};
|
||||
}
|
||||
function extractStrings(destFiles) {
|
||||
const parseDefineCall = (moduleMatch, depsMatch) => {
|
||||
const module = moduleMatch.replace(/^"|"$/g, '');
|
||||
let deps = depsMatch.split(',');
|
||||
deps = deps.map((dep) => {
|
||||
dep = dep.trim();
|
||||
dep = dep.replace(/^"|"$/g, '');
|
||||
dep = dep.replace(/^'|'$/g, '');
|
||||
let prefix = null;
|
||||
let _path = null;
|
||||
const pieces = dep.split('!');
|
||||
if (pieces.length > 1) {
|
||||
prefix = pieces[0] + '!';
|
||||
_path = pieces[1];
|
||||
}
|
||||
else {
|
||||
prefix = '';
|
||||
_path = pieces[0];
|
||||
}
|
||||
if (/^\.\//.test(_path) || /^\.\.\//.test(_path)) {
|
||||
const res = path.join(path.dirname(module), _path).replace(/\\/g, '/');
|
||||
return prefix + res;
|
||||
}
|
||||
return prefix + _path;
|
||||
});
|
||||
return {
|
||||
module: module,
|
||||
deps: deps
|
||||
};
|
||||
};
|
||||
destFiles.forEach((destFile) => {
|
||||
if (!/\.js$/.test(destFile.dest)) {
|
||||
return;
|
||||
}
|
||||
if (/\.nls\.js$/.test(destFile.dest)) {
|
||||
return;
|
||||
}
|
||||
// Do one pass to record the usage counts for each module id
|
||||
const useCounts = {};
|
||||
destFile.sources.forEach((source) => {
|
||||
const matches = source.contents.match(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/);
|
||||
if (!matches) {
|
||||
return;
|
||||
}
|
||||
const defineCall = parseDefineCall(matches[1], matches[2]);
|
||||
useCounts[defineCall.module] = (useCounts[defineCall.module] || 0) + 1;
|
||||
defineCall.deps.forEach((dep) => {
|
||||
useCounts[dep] = (useCounts[dep] || 0) + 1;
|
||||
});
|
||||
});
|
||||
const sortedByUseModules = Object.keys(useCounts);
|
||||
sortedByUseModules.sort((a, b) => {
|
||||
return useCounts[b] - useCounts[a];
|
||||
});
|
||||
const replacementMap = {};
|
||||
sortedByUseModules.forEach((module, index) => {
|
||||
replacementMap[module] = index;
|
||||
});
|
||||
destFile.sources.forEach((source) => {
|
||||
source.contents = source.contents.replace(/define\(("[^"]+"),\s*\[(((, )?("|')[^"']+("|'))+)\]/, (_, moduleMatch, depsMatch) => {
|
||||
const defineCall = parseDefineCall(moduleMatch, depsMatch);
|
||||
return `define(__m[${replacementMap[defineCall.module]}/*${defineCall.module}*/], __M([${defineCall.deps.map(dep => replacementMap[dep] + '/*' + dep + '*/').join(',')}])`;
|
||||
});
|
||||
});
|
||||
destFile.sources.unshift({
|
||||
path: null,
|
||||
contents: [
|
||||
'(function() {',
|
||||
`var __m = ${JSON.stringify(sortedByUseModules)};`,
|
||||
`var __M = function(deps) {`,
|
||||
` var result = [];`,
|
||||
` for (var i = 0, len = deps.length; i < len; i++) {`,
|
||||
` result[i] = __m[deps[i]];`,
|
||||
` }`,
|
||||
` return result;`,
|
||||
`};`
|
||||
].join('\n')
|
||||
});
|
||||
destFile.sources.push({
|
||||
path: null,
|
||||
contents: '}).call(this);'
|
||||
});
|
||||
});
|
||||
return destFiles;
|
||||
}
|
||||
function removeDuplicateTSBoilerplate(destFiles) {
|
||||
// Taken from typescript compiler => emitFiles
|
||||
const BOILERPLATE = [
|
||||
{ start: /^var __extends/, end: /^}\)\(\);$/ },
|
||||
{ start: /^var __assign/, end: /^};$/ },
|
||||
{ start: /^var __decorate/, end: /^};$/ },
|
||||
{ start: /^var __metadata/, end: /^};$/ },
|
||||
{ start: /^var __param/, end: /^};$/ },
|
||||
{ start: /^var __awaiter/, end: /^};$/ },
|
||||
{ start: /^var __generator/, end: /^};$/ },
|
||||
];
|
||||
destFiles.forEach((destFile) => {
|
||||
const SEEN_BOILERPLATE = [];
|
||||
destFile.sources.forEach((source) => {
|
||||
const lines = source.contents.split(/\r\n|\n|\r/);
|
||||
const newLines = [];
|
||||
let IS_REMOVING_BOILERPLATE = false, END_BOILERPLATE;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (IS_REMOVING_BOILERPLATE) {
|
||||
newLines.push('');
|
||||
if (END_BOILERPLATE.test(line)) {
|
||||
IS_REMOVING_BOILERPLATE = false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (let j = 0; j < BOILERPLATE.length; j++) {
|
||||
const boilerplate = BOILERPLATE[j];
|
||||
if (boilerplate.start.test(line)) {
|
||||
if (SEEN_BOILERPLATE[j]) {
|
||||
IS_REMOVING_BOILERPLATE = true;
|
||||
END_BOILERPLATE = boilerplate.end;
|
||||
}
|
||||
else {
|
||||
SEEN_BOILERPLATE[j] = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (IS_REMOVING_BOILERPLATE) {
|
||||
newLines.push('');
|
||||
}
|
||||
else {
|
||||
newLines.push(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
source.contents = newLines.join('\n');
|
||||
});
|
||||
});
|
||||
return destFiles;
|
||||
}
|
||||
function emitEntryPoint(modulesMap, deps, entryPoint, includedModules, prepend, append, dest) {
|
||||
if (!dest) {
|
||||
dest = entryPoint + '.js';
|
||||
}
|
||||
const mainResult = {
|
||||
sources: [],
|
||||
dest: dest
|
||||
}, results = [mainResult];
|
||||
const usedPlugins = {};
|
||||
const getLoaderPlugin = (pluginName) => {
|
||||
if (!usedPlugins[pluginName]) {
|
||||
usedPlugins[pluginName] = modulesMap[pluginName].exports;
|
||||
}
|
||||
return usedPlugins[pluginName];
|
||||
};
|
||||
includedModules.forEach((c) => {
|
||||
const bangIndex = c.indexOf('!');
|
||||
if (bangIndex >= 0) {
|
||||
const pluginName = c.substr(0, bangIndex);
|
||||
const plugin = getLoaderPlugin(pluginName);
|
||||
mainResult.sources.push(emitPlugin(entryPoint, plugin, pluginName, c.substr(bangIndex + 1)));
|
||||
return;
|
||||
}
|
||||
const module = modulesMap[c];
|
||||
if (module.path === 'empty:') {
|
||||
return;
|
||||
}
|
||||
const contents = readFileAndRemoveBOM(module.path);
|
||||
if (module.shim) {
|
||||
mainResult.sources.push(emitShimmedModule(c, deps[c], module.shim, module.path, contents));
|
||||
}
|
||||
else {
|
||||
mainResult.sources.push(emitNamedModule(c, module.defineLocation, module.path, contents));
|
||||
}
|
||||
});
|
||||
Object.keys(usedPlugins).forEach((pluginName) => {
|
||||
const plugin = usedPlugins[pluginName];
|
||||
if (typeof plugin.writeFile === 'function') {
|
||||
const req = (() => {
|
||||
throw new Error('no-no!');
|
||||
});
|
||||
req.toUrl = something => something;
|
||||
const write = (filename, contents) => {
|
||||
results.push({
|
||||
dest: filename,
|
||||
sources: [{
|
||||
path: null,
|
||||
contents: contents
|
||||
}]
|
||||
});
|
||||
};
|
||||
plugin.writeFile(pluginName, entryPoint, req, write, {});
|
||||
}
|
||||
});
|
||||
const toIFile = (path) => {
|
||||
const contents = readFileAndRemoveBOM(path);
|
||||
return {
|
||||
path: path,
|
||||
contents: contents
|
||||
};
|
||||
};
|
||||
const toPrepend = (prepend || []).map(toIFile);
|
||||
const toAppend = (append || []).map(toIFile);
|
||||
mainResult.sources = toPrepend.concat(mainResult.sources).concat(toAppend);
|
||||
return {
|
||||
files: results,
|
||||
usedPlugins: usedPlugins
|
||||
};
|
||||
}
|
||||
function readFileAndRemoveBOM(path) {
|
||||
const BOM_CHAR_CODE = 65279;
|
||||
let contents = fs.readFileSync(path, 'utf8');
|
||||
// Remove BOM
|
||||
if (contents.charCodeAt(0) === BOM_CHAR_CODE) {
|
||||
contents = contents.substring(1);
|
||||
}
|
||||
return contents;
|
||||
}
|
||||
function emitPlugin(entryPoint, plugin, pluginName, moduleName) {
|
||||
let result = '';
|
||||
if (typeof plugin.write === 'function') {
|
||||
const write = ((what) => {
|
||||
result += what;
|
||||
});
|
||||
write.getEntryPoint = () => {
|
||||
return entryPoint;
|
||||
};
|
||||
write.asModule = (moduleId, code) => {
|
||||
code = code.replace(/^define\(/, 'define("' + moduleId + '",');
|
||||
result += code;
|
||||
};
|
||||
plugin.write(pluginName, moduleName, write);
|
||||
}
|
||||
return {
|
||||
path: null,
|
||||
contents: result
|
||||
};
|
||||
}
|
||||
function emitNamedModule(moduleId, defineCallPosition, path, contents) {
|
||||
// `defineCallPosition` is the position in code: |define()
|
||||
const defineCallOffset = positionToOffset(contents, defineCallPosition.line, defineCallPosition.col);
|
||||
// `parensOffset` is the position in code: define|()
|
||||
const parensOffset = contents.indexOf('(', defineCallOffset);
|
||||
const insertStr = '"' + moduleId + '", ';
|
||||
return {
|
||||
path: path,
|
||||
contents: contents.substr(0, parensOffset + 1) + insertStr + contents.substr(parensOffset + 1)
|
||||
};
|
||||
}
|
||||
function emitShimmedModule(moduleId, myDeps, factory, path, contents) {
|
||||
const strDeps = (myDeps.length > 0 ? '"' + myDeps.join('", "') + '"' : '');
|
||||
const strDefine = 'define("' + moduleId + '", [' + strDeps + '], ' + factory + ');';
|
||||
return {
|
||||
path: path,
|
||||
contents: contents + '\n;\n' + strDefine
|
||||
};
|
||||
}
|
||||
/**
|
||||
* Convert a position (line:col) to (offset) in string `str`
|
||||
*/
|
||||
function positionToOffset(str, desiredLine, desiredCol) {
|
||||
if (desiredLine === 1) {
|
||||
return desiredCol - 1;
|
||||
}
|
||||
let line = 1;
|
||||
let lastNewLineOffset = -1;
|
||||
do {
|
||||
if (desiredLine === line) {
|
||||
return lastNewLineOffset + 1 + desiredCol - 1;
|
||||
}
|
||||
lastNewLineOffset = str.indexOf('\n', lastNewLineOffset + 1);
|
||||
line++;
|
||||
} while (lastNewLineOffset >= 0);
|
||||
return -1;
|
||||
}
|
||||
/**
|
||||
* Return a set of reachable nodes in `graph` starting from `rootNodes`
|
||||
*/
|
||||
function visit(rootNodes, graph) {
|
||||
const result = {};
|
||||
const queue = rootNodes;
|
||||
rootNodes.forEach((node) => {
|
||||
result[node] = true;
|
||||
});
|
||||
while (queue.length > 0) {
|
||||
const el = queue.shift();
|
||||
const myEdges = graph[el] || [];
|
||||
myEdges.forEach((toNode) => {
|
||||
if (!result[toNode]) {
|
||||
result[toNode] = true;
|
||||
queue.push(toNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* Perform a topological sort on `graph`
|
||||
*/
|
||||
function topologicalSort(graph) {
|
||||
const allNodes = {}, outgoingEdgeCount = {}, inverseEdges = {};
|
||||
Object.keys(graph).forEach((fromNode) => {
|
||||
allNodes[fromNode] = true;
|
||||
outgoingEdgeCount[fromNode] = graph[fromNode].length;
|
||||
graph[fromNode].forEach((toNode) => {
|
||||
allNodes[toNode] = true;
|
||||
outgoingEdgeCount[toNode] = outgoingEdgeCount[toNode] || 0;
|
||||
inverseEdges[toNode] = inverseEdges[toNode] || [];
|
||||
inverseEdges[toNode].push(fromNode);
|
||||
});
|
||||
});
|
||||
// https://en.wikipedia.org/wiki/Topological_sorting
|
||||
const S = [], L = [];
|
||||
Object.keys(allNodes).forEach((node) => {
|
||||
if (outgoingEdgeCount[node] === 0) {
|
||||
delete outgoingEdgeCount[node];
|
||||
S.push(node);
|
||||
}
|
||||
});
|
||||
while (S.length > 0) {
|
||||
// Ensure the exact same order all the time with the same inputs
|
||||
S.sort();
|
||||
const n = S.shift();
|
||||
L.push(n);
|
||||
const myInverseEdges = inverseEdges[n] || [];
|
||||
myInverseEdges.forEach((m) => {
|
||||
outgoingEdgeCount[m]--;
|
||||
if (outgoingEdgeCount[m] === 0) {
|
||||
delete outgoingEdgeCount[m];
|
||||
S.push(m);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (Object.keys(outgoingEdgeCount).length > 0) {
|
||||
throw new Error('Cannot do topological sort on cyclic graph, remaining nodes: ' + Object.keys(outgoingEdgeCount));
|
||||
}
|
||||
return L;
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.watchTask = exports.compileTask = void 0;
|
||||
const es = require("event-stream");
|
||||
const fs = require("fs");
|
||||
const gulp = require("gulp");
|
||||
const bom = require("gulp-bom");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const tsb = require("gulp-tsb");
|
||||
const path = require("path");
|
||||
const monacodts = require("../monaco/api");
|
||||
const nls = require("./nls");
|
||||
const reporter_1 = require("./reporter");
|
||||
const util = require("./util");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const os = require("os");
|
||||
const watch = require('./watch');
|
||||
const reporter = reporter_1.createReporter();
|
||||
function getTypeScriptCompilerOptions(src) {
|
||||
const rootDir = path.join(__dirname, `../../${src}`);
|
||||
let options = {};
|
||||
options.verbose = false;
|
||||
options.sourceMap = true;
|
||||
if (process.env['VSCODE_NO_SOURCEMAP']) { // To be used by developers in a hurry
|
||||
options.sourceMap = false;
|
||||
}
|
||||
options.rootDir = rootDir;
|
||||
options.baseUrl = rootDir;
|
||||
options.sourceRoot = util.toFileUri(rootDir);
|
||||
options.newLine = /\r\n/.test(fs.readFileSync(__filename, 'utf8')) ? 0 : 1;
|
||||
return options;
|
||||
}
|
||||
function createCompile(src, build, emitError) {
|
||||
const projectPath = path.join(__dirname, '../../', src, 'tsconfig.json');
|
||||
const overrideOptions = Object.assign(Object.assign({}, getTypeScriptCompilerOptions(src)), { inlineSources: Boolean(build) });
|
||||
const compilation = tsb.create(projectPath, overrideOptions, false, err => reporter(err));
|
||||
function pipeline(token) {
|
||||
const utf8Filter = util.filter(data => /(\/|\\)test(\/|\\).*utf8/.test(data.path));
|
||||
const tsFilter = util.filter(data => /\.ts$/.test(data.path));
|
||||
const noDeclarationsFilter = util.filter(data => !(/\.d\.ts$/.test(data.path)));
|
||||
const input = es.through();
|
||||
const output = input
|
||||
.pipe(utf8Filter)
|
||||
.pipe(bom()) // this is required to preserve BOM in test files that loose it otherwise
|
||||
.pipe(utf8Filter.restore)
|
||||
.pipe(tsFilter)
|
||||
.pipe(util.loadSourcemaps())
|
||||
.pipe(compilation(token))
|
||||
.pipe(noDeclarationsFilter)
|
||||
.pipe(build ? nls() : es.through())
|
||||
.pipe(noDeclarationsFilter.restore)
|
||||
.pipe(sourcemaps.write('.', {
|
||||
addComment: false,
|
||||
includeContent: !!build,
|
||||
sourceRoot: overrideOptions.sourceRoot
|
||||
}))
|
||||
.pipe(tsFilter.restore)
|
||||
.pipe(reporter.end(!!emitError));
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
pipeline.tsProjectSrc = () => {
|
||||
return compilation.src({ base: src });
|
||||
};
|
||||
return pipeline;
|
||||
}
|
||||
function compileTask(src, out, build) {
|
||||
return function () {
|
||||
if (os.totalmem() < 4000000000) {
|
||||
throw new Error('compilation requires 4GB of RAM');
|
||||
}
|
||||
const compile = createCompile(src, build, true);
|
||||
const srcPipe = gulp.src(`${src}/**`, { base: `${src}` });
|
||||
let generator = new MonacoGenerator(false);
|
||||
if (src === 'src') {
|
||||
generator.execute();
|
||||
}
|
||||
return srcPipe
|
||||
.pipe(generator.stream)
|
||||
.pipe(compile())
|
||||
.pipe(gulp.dest(out));
|
||||
};
|
||||
}
|
||||
exports.compileTask = compileTask;
|
||||
function watchTask(out, build) {
|
||||
return function () {
|
||||
const compile = createCompile('src', build);
|
||||
const src = gulp.src('src/**', { base: 'src' });
|
||||
const watchSrc = watch('src/**', { base: 'src', readDelay: 200 });
|
||||
let generator = new MonacoGenerator(true);
|
||||
generator.execute();
|
||||
return watchSrc
|
||||
.pipe(generator.stream)
|
||||
.pipe(util.incremental(compile, src, true))
|
||||
.pipe(gulp.dest(out));
|
||||
};
|
||||
}
|
||||
exports.watchTask = watchTask;
|
||||
const REPO_SRC_FOLDER = path.join(__dirname, '../../src');
|
||||
class MonacoGenerator {
|
||||
constructor(isWatch) {
|
||||
this._executeSoonTimer = null;
|
||||
this._isWatch = isWatch;
|
||||
this.stream = es.through();
|
||||
this._watchedFiles = {};
|
||||
let onWillReadFile = (moduleId, filePath) => {
|
||||
if (!this._isWatch) {
|
||||
return;
|
||||
}
|
||||
if (this._watchedFiles[filePath]) {
|
||||
return;
|
||||
}
|
||||
this._watchedFiles[filePath] = true;
|
||||
fs.watchFile(filePath, () => {
|
||||
this._declarationResolver.invalidateCache(moduleId);
|
||||
this._executeSoon();
|
||||
});
|
||||
};
|
||||
this._fsProvider = new class extends monacodts.FSProvider {
|
||||
readFileSync(moduleId, filePath) {
|
||||
onWillReadFile(moduleId, filePath);
|
||||
return super.readFileSync(moduleId, filePath);
|
||||
}
|
||||
};
|
||||
this._declarationResolver = new monacodts.DeclarationResolver(this._fsProvider);
|
||||
if (this._isWatch) {
|
||||
fs.watchFile(monacodts.RECIPE_PATH, () => {
|
||||
this._executeSoon();
|
||||
});
|
||||
}
|
||||
}
|
||||
_executeSoon() {
|
||||
if (this._executeSoonTimer !== null) {
|
||||
clearTimeout(this._executeSoonTimer);
|
||||
this._executeSoonTimer = null;
|
||||
}
|
||||
this._executeSoonTimer = setTimeout(() => {
|
||||
this._executeSoonTimer = null;
|
||||
this.execute();
|
||||
}, 20);
|
||||
}
|
||||
_run() {
|
||||
let r = monacodts.run3(this._declarationResolver);
|
||||
if (!r && !this._isWatch) {
|
||||
// The build must always be able to generate the monaco.d.ts
|
||||
throw new Error(`monaco.d.ts generation error - Cannot continue`);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
_log(message, ...rest) {
|
||||
fancyLog(ansiColors.cyan('[monaco.d.ts]'), message, ...rest);
|
||||
}
|
||||
execute() {
|
||||
const startTime = Date.now();
|
||||
const result = this._run();
|
||||
if (!result) {
|
||||
// nothing really changed
|
||||
return;
|
||||
}
|
||||
if (result.isTheSame) {
|
||||
return;
|
||||
}
|
||||
fs.writeFileSync(result.filePath, result.content);
|
||||
fs.writeFileSync(path.join(REPO_SRC_FOLDER, 'vs/editor/common/standalone/standaloneEnums.ts'), result.enums);
|
||||
this._log(`monaco.d.ts is changed - total time took ${Date.now() - startTime} ms`);
|
||||
if (!this._isWatch) {
|
||||
this.stream.emit('error', 'monaco.d.ts is no longer up to date. Please run gulp watch and commit the new file.');
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,111 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.config = void 0;
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const vfs = require("vinyl-fs");
|
||||
const filter = require("gulp-filter");
|
||||
const json = require("gulp-json-editor");
|
||||
const _ = require("underscore");
|
||||
const util = require("./util");
|
||||
const electron = require('gulp-atom-electron');
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const product = JSON.parse(fs.readFileSync(path.join(root, 'product.json'), 'utf8'));
|
||||
const commit = util.getVersion(root);
|
||||
const darwinCreditsTemplate = product.darwinCredits && _.template(fs.readFileSync(path.join(root, product.darwinCredits), 'utf8'));
|
||||
function darwinBundleDocumentType(extensions, icon) {
|
||||
return {
|
||||
name: product.nameLong + ' document',
|
||||
role: 'Editor',
|
||||
ostypes: ["TEXT", "utxt", "TUTX", "****"],
|
||||
extensions: extensions,
|
||||
iconFile: icon
|
||||
};
|
||||
}
|
||||
exports.config = {
|
||||
version: util.getElectronVersion(),
|
||||
productAppName: product.nameLong,
|
||||
companyName: 'Microsoft Corporation',
|
||||
copyright: 'Copyright (C) 2019 Microsoft. All rights reserved',
|
||||
darwinIcon: 'resources/darwin/code.icns',
|
||||
darwinBundleIdentifier: product.darwinBundleIdentifier,
|
||||
darwinApplicationCategoryType: 'public.app-category.developer-tools',
|
||||
darwinHelpBookFolder: 'VS Code HelpBook',
|
||||
darwinHelpBookName: 'VS Code HelpBook',
|
||||
darwinBundleDocumentTypes: [
|
||||
darwinBundleDocumentType(["bat", "cmd"], 'resources/darwin/bat.icns'),
|
||||
darwinBundleDocumentType(["bowerrc"], 'resources/darwin/bower.icns'),
|
||||
darwinBundleDocumentType(["c", "h"], 'resources/darwin/c.icns'),
|
||||
darwinBundleDocumentType(["config", "editorconfig", "gitattributes", "gitconfig", "gitignore", "ini"], 'resources/darwin/config.icns'),
|
||||
darwinBundleDocumentType(["cc", "cpp", "cxx", "c++", "hh", "hpp", "hxx", "h++"], 'resources/darwin/cpp.icns'),
|
||||
darwinBundleDocumentType(["cs", "csx"], 'resources/darwin/csharp.icns'),
|
||||
darwinBundleDocumentType(["css"], 'resources/darwin/css.icns'),
|
||||
darwinBundleDocumentType(["go"], 'resources/darwin/go.icns'),
|
||||
darwinBundleDocumentType(["asp", "aspx", "cshtml", "htm", "html", "jshtm", "jsp", "phtml", "shtml"], 'resources/darwin/html.icns'),
|
||||
darwinBundleDocumentType(["jade"], 'resources/darwin/jade.icns'),
|
||||
darwinBundleDocumentType(["jav", "java"], 'resources/darwin/java.icns'),
|
||||
darwinBundleDocumentType(["js", "jscsrc", "jshintrc", "mjs", "cjs"], 'resources/darwin/javascript.icns'),
|
||||
darwinBundleDocumentType(["json"], 'resources/darwin/json.icns'),
|
||||
darwinBundleDocumentType(["less"], 'resources/darwin/less.icns'),
|
||||
darwinBundleDocumentType(["markdown", "md", "mdoc", "mdown", "mdtext", "mdtxt", "mdwn", "mkd", "mkdn"], 'resources/darwin/markdown.icns'),
|
||||
darwinBundleDocumentType(["php"], 'resources/darwin/php.icns'),
|
||||
darwinBundleDocumentType(["ps1", "psd1", "psm1"], 'resources/darwin/powershell.icns'),
|
||||
darwinBundleDocumentType(["py"], 'resources/darwin/python.icns'),
|
||||
darwinBundleDocumentType(["gemspec", "rb"], 'resources/darwin/ruby.icns'),
|
||||
darwinBundleDocumentType(["scss"], 'resources/darwin/sass.icns'),
|
||||
darwinBundleDocumentType(["bash", "bash_login", "bash_logout", "bash_profile", "bashrc", "profile", "rhistory", "rprofile", "sh", "zlogin", "zlogout", "zprofile", "zsh", "zshenv", "zshrc"], 'resources/darwin/shell.icns'),
|
||||
darwinBundleDocumentType(["sql"], 'resources/darwin/sql.icns'),
|
||||
darwinBundleDocumentType(["ts"], 'resources/darwin/typescript.icns'),
|
||||
darwinBundleDocumentType(["tsx", "jsx"], 'resources/darwin/react.icns'),
|
||||
darwinBundleDocumentType(["vue"], 'resources/darwin/vue.icns'),
|
||||
darwinBundleDocumentType(["ascx", "csproj", "dtd", "wxi", "wxl", "wxs", "xml", "xaml"], 'resources/darwin/xml.icns'),
|
||||
darwinBundleDocumentType(["eyaml", "eyml", "yaml", "yml"], 'resources/darwin/yaml.icns'),
|
||||
darwinBundleDocumentType(["clj", "cljs", "cljx", "clojure", "code-workspace", "coffee", "containerfile", "ctp", "dockerfile", "dot", "edn", "fs", "fsi", "fsscript", "fsx", "handlebars", "hbs", "lua", "m", "makefile", "ml", "mli", "pl", "pl6", "pm", "pm6", "pod", "pp", "properties", "psgi", "pug", "r", "rs", "rt", "svg", "svgz", "t", "txt", "vb", "xcodeproj", "xcworkspace"], 'resources/darwin/default.icns')
|
||||
],
|
||||
darwinBundleURLTypes: [{
|
||||
role: 'Viewer',
|
||||
name: product.nameLong,
|
||||
urlSchemes: [product.urlProtocol]
|
||||
}],
|
||||
darwinForceDarkModeSupport: true,
|
||||
darwinCredits: darwinCreditsTemplate ? Buffer.from(darwinCreditsTemplate({ commit: commit, date: new Date().toISOString() })) : undefined,
|
||||
linuxExecutableName: product.applicationName,
|
||||
winIcon: 'resources/win32/code.ico',
|
||||
token: process.env['VSCODE_MIXIN_PASSWORD'] || process.env['GITHUB_TOKEN'] || undefined,
|
||||
repo: product.electronRepository || undefined
|
||||
};
|
||||
function getElectron(arch) {
|
||||
return () => {
|
||||
const electronOpts = _.extend({}, exports.config, {
|
||||
platform: process.platform,
|
||||
arch: arch === 'armhf' ? 'arm' : arch,
|
||||
ffmpegChromium: true,
|
||||
keepDefaultApp: true
|
||||
});
|
||||
return vfs.src('package.json')
|
||||
.pipe(json({ name: product.nameShort }))
|
||||
.pipe(electron(electronOpts))
|
||||
.pipe(filter(['**', '!**/app/package.json']))
|
||||
.pipe(vfs.dest('.build/electron'));
|
||||
};
|
||||
}
|
||||
async function main(arch = process.arch) {
|
||||
const version = util.getElectronVersion();
|
||||
const electronPath = path.join(root, '.build', 'electron');
|
||||
const versionFile = path.join(electronPath, 'version');
|
||||
const isUpToDate = fs.existsSync(versionFile) && fs.readFileSync(versionFile, 'utf8') === `${version}`;
|
||||
if (!isUpToDate) {
|
||||
await util.rimraf(electronPath)();
|
||||
await util.streamToPromise(getElectron(arch)());
|
||||
}
|
||||
}
|
||||
if (require.main === module) {
|
||||
main(process.argv[2]).catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
|
@ -1,59 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const path_1 = require("path");
|
||||
const minimatch = require("minimatch");
|
||||
const utils_1 = require("./utils");
|
||||
module.exports = new class {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
badImport: 'Imports violates \'{{restrictions}}\' restrictions. See https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||
},
|
||||
docs: {
|
||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const configs = context.options;
|
||||
for (const config of configs) {
|
||||
if (minimatch(context.getFilename(), config.target)) {
|
||||
return utils_1.createImportRuleListener((node, value) => this._checkImport(context, config, node, value));
|
||||
}
|
||||
}
|
||||
return {};
|
||||
}
|
||||
_checkImport(context, config, node, path) {
|
||||
// resolve relative paths
|
||||
if (path[0] === '.') {
|
||||
path = path_1.join(context.getFilename(), path);
|
||||
}
|
||||
let restrictions;
|
||||
if (typeof config.restrictions === 'string') {
|
||||
restrictions = [config.restrictions];
|
||||
}
|
||||
else {
|
||||
restrictions = config.restrictions;
|
||||
}
|
||||
let matched = false;
|
||||
for (const pattern of restrictions) {
|
||||
if (minimatch(path, pattern)) {
|
||||
matched = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!matched) {
|
||||
// None of the restrictions matched
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
messageId: 'badImport',
|
||||
data: {
|
||||
restrictions: restrictions.join(' or ')
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
|
@ -1,68 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const path_1 = require("path");
|
||||
const utils_1 = require("./utils");
|
||||
module.exports = new class {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
layerbreaker: 'Bad layering. You are not allowed to access {{from}} from here, allowed layers are: [{{allowed}}]'
|
||||
},
|
||||
docs: {
|
||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const fileDirname = path_1.dirname(context.getFilename());
|
||||
const parts = fileDirname.split(/\\|\//);
|
||||
const ruleArgs = context.options[0];
|
||||
let config;
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
if (ruleArgs[parts[i]]) {
|
||||
config = {
|
||||
allowed: new Set(ruleArgs[parts[i]]).add(parts[i]),
|
||||
disallowed: new Set()
|
||||
};
|
||||
Object.keys(ruleArgs).forEach(key => {
|
||||
if (!config.allowed.has(key)) {
|
||||
config.disallowed.add(key);
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!config) {
|
||||
// nothing
|
||||
return {};
|
||||
}
|
||||
return utils_1.createImportRuleListener((node, path) => {
|
||||
if (path[0] === '.') {
|
||||
path = path_1.join(path_1.dirname(context.getFilename()), path);
|
||||
}
|
||||
const parts = path_1.dirname(path).split(/\\|\//);
|
||||
for (let i = parts.length - 1; i >= 0; i--) {
|
||||
const part = parts[i];
|
||||
if (config.allowed.has(part)) {
|
||||
// GOOD - same layer
|
||||
break;
|
||||
}
|
||||
if (config.disallowed.has(part)) {
|
||||
// BAD - wrong layer
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
messageId: 'layerbreaker',
|
||||
data: {
|
||||
from: part,
|
||||
allowed: [...config.allowed.keys()].join(', ')
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,38 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const path_1 = require("path");
|
||||
const utils_1 = require("./utils");
|
||||
module.exports = new class NoNlsInStandaloneEditorRule {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
noNls: 'Not allowed to import vs/nls in standalone editor modules. Use standaloneStrings.ts'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const fileName = context.getFilename();
|
||||
if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(fileName)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(fileName)) {
|
||||
return utils_1.createImportRuleListener((node, path) => {
|
||||
// resolve relative paths
|
||||
if (path[0] === '.') {
|
||||
path = path_1.join(context.getFilename(), path);
|
||||
}
|
||||
if (/vs(\/|\\)nls/.test(path)) {
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
messageId: 'noNls'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
return {};
|
||||
}
|
||||
};
|
|
@ -1,41 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const path_1 = require("path");
|
||||
const utils_1 = require("./utils");
|
||||
module.exports = new class NoNlsInStandaloneEditorRule {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
badImport: 'Not allowed to import standalone editor modules.'
|
||||
},
|
||||
docs: {
|
||||
url: 'https://github.com/microsoft/vscode/wiki/Source-Code-Organization'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
if (/vs(\/|\\)editor/.test(context.getFilename())) {
|
||||
// the vs/editor folder is allowed to use the standalone editor
|
||||
return {};
|
||||
}
|
||||
return utils_1.createImportRuleListener((node, path) => {
|
||||
// resolve relative paths
|
||||
if (path[0] === '.') {
|
||||
path = path_1.join(context.getFilename(), path);
|
||||
}
|
||||
if (/vs(\/|\\)editor(\/|\\)standalone(\/|\\)/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)common(\/|\\)standalone(\/|\\)/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.api/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.main/.test(path)
|
||||
|| /vs(\/|\\)editor(\/|\\)editor.worker/.test(path)) {
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
messageId: 'badImport'
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
|
@ -1,111 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
var _a;
|
||||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
||||
function isStringLiteral(node) {
|
||||
return !!node && node.type === experimental_utils_1.AST_NODE_TYPES.Literal && typeof node.value === 'string';
|
||||
}
|
||||
function isDoubleQuoted(node) {
|
||||
return node.raw[0] === '"' && node.raw[node.raw.length - 1] === '"';
|
||||
}
|
||||
module.exports = new (_a = class NoUnexternalizedStrings {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
doubleQuoted: 'Only use double-quoted strings for externalized strings.',
|
||||
badKey: 'The key \'{{key}}\' doesn\'t conform to a valid localize identifier.',
|
||||
duplicateKey: 'Duplicate key \'{{key}}\' with different message value.',
|
||||
badMessage: 'Message argument to \'{{message}}\' must be a string literal.'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const externalizedStringLiterals = new Map();
|
||||
const doubleQuotedStringLiterals = new Set();
|
||||
function collectDoubleQuotedStrings(node) {
|
||||
if (isStringLiteral(node) && isDoubleQuoted(node)) {
|
||||
doubleQuotedStringLiterals.add(node);
|
||||
}
|
||||
}
|
||||
function visitLocalizeCall(node) {
|
||||
// localize(key, message)
|
||||
const [keyNode, messageNode] = node.arguments;
|
||||
// (1)
|
||||
// extract key so that it can be checked later
|
||||
let key;
|
||||
if (isStringLiteral(keyNode)) {
|
||||
doubleQuotedStringLiterals.delete(keyNode); //todo@joh reconsider
|
||||
key = keyNode.value;
|
||||
}
|
||||
else if (keyNode.type === experimental_utils_1.AST_NODE_TYPES.ObjectExpression) {
|
||||
for (let property of keyNode.properties) {
|
||||
if (property.type === experimental_utils_1.AST_NODE_TYPES.Property && !property.computed) {
|
||||
if (property.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier && property.key.name === 'key') {
|
||||
if (isStringLiteral(property.value)) {
|
||||
doubleQuotedStringLiterals.delete(property.value); //todo@joh reconsider
|
||||
key = property.value.value;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (typeof key === 'string') {
|
||||
let array = externalizedStringLiterals.get(key);
|
||||
if (!array) {
|
||||
array = [];
|
||||
externalizedStringLiterals.set(key, array);
|
||||
}
|
||||
array.push({ call: node, message: messageNode });
|
||||
}
|
||||
// (2)
|
||||
// remove message-argument from doubleQuoted list and make
|
||||
// sure it is a string-literal
|
||||
doubleQuotedStringLiterals.delete(messageNode);
|
||||
if (!isStringLiteral(messageNode)) {
|
||||
context.report({
|
||||
loc: messageNode.loc,
|
||||
messageId: 'badMessage',
|
||||
data: { message: context.getSourceCode().getText(node) }
|
||||
});
|
||||
}
|
||||
}
|
||||
function reportBadStringsAndBadKeys() {
|
||||
// (1)
|
||||
// report all strings that are in double quotes
|
||||
for (const node of doubleQuotedStringLiterals) {
|
||||
context.report({ loc: node.loc, messageId: 'doubleQuoted' });
|
||||
}
|
||||
for (const [key, values] of externalizedStringLiterals) {
|
||||
// (2)
|
||||
// report all invalid NLS keys
|
||||
if (!key.match(NoUnexternalizedStrings._rNlsKeys)) {
|
||||
for (let value of values) {
|
||||
context.report({ loc: value.call.loc, messageId: 'badKey', data: { key } });
|
||||
}
|
||||
}
|
||||
// (2)
|
||||
// report all invalid duplicates (same key, different message)
|
||||
if (values.length > 1) {
|
||||
for (let i = 1; i < values.length; i++) {
|
||||
if (context.getSourceCode().getText(values[i - 1].message) !== context.getSourceCode().getText(values[i].message)) {
|
||||
context.report({ loc: values[i].call.loc, messageId: 'duplicateKey', data: { key } });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return {
|
||||
['Literal']: (node) => collectDoubleQuotedStrings(node),
|
||||
['ExpressionStatement[directive] Literal:exit']: (node) => doubleQuotedStringLiterals.delete(node),
|
||||
['CallExpression[callee.type="MemberExpression"][callee.object.name="nls"][callee.property.name="localize"]:exit']: (node) => visitLocalizeCall(node),
|
||||
['CallExpression[callee.name="localize"][arguments.length>=2]:exit']: (node) => visitLocalizeCall(node),
|
||||
['Program:exit']: reportBadStringsAndBadKeys,
|
||||
};
|
||||
}
|
||||
},
|
||||
_a._rNlsKeys = /^[_a-zA-Z0-9][ .\-_a-zA-Z0-9]*$/,
|
||||
_a);
|
|
@ -1,57 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
var _a;
|
||||
const fs_1 = require("fs");
|
||||
const utils_1 = require("./utils");
|
||||
module.exports = new (_a = class TranslationRemind {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
missing: 'Please add \'{{resource}}\' to ./build/lib/i18n.resources.json file to use translations here.'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
return utils_1.createImportRuleListener((node, path) => this._checkImport(context, node, path));
|
||||
}
|
||||
_checkImport(context, node, path) {
|
||||
if (path !== TranslationRemind.NLS_MODULE) {
|
||||
return;
|
||||
}
|
||||
const currentFile = context.getFilename();
|
||||
const matchService = currentFile.match(/vs\/workbench\/services\/\w+/);
|
||||
const matchPart = currentFile.match(/vs\/workbench\/contrib\/\w+/);
|
||||
if (!matchService && !matchPart) {
|
||||
return;
|
||||
}
|
||||
const resource = matchService ? matchService[0] : matchPart[0];
|
||||
let resourceDefined = false;
|
||||
let json;
|
||||
try {
|
||||
json = fs_1.readFileSync('./build/lib/i18n.resources.json', 'utf8');
|
||||
}
|
||||
catch (e) {
|
||||
console.error('[translation-remind rule]: File with resources to pull from Transifex was not found. Aborting translation resource check for newly defined workbench part/service.');
|
||||
return;
|
||||
}
|
||||
const workbenchResources = JSON.parse(json).workbench;
|
||||
workbenchResources.forEach((existingResource) => {
|
||||
if (existingResource.name === resource) {
|
||||
resourceDefined = true;
|
||||
return;
|
||||
}
|
||||
});
|
||||
if (!resourceDefined) {
|
||||
context.report({
|
||||
loc: node.loc,
|
||||
messageId: 'missing',
|
||||
data: { resource }
|
||||
});
|
||||
}
|
||||
}
|
||||
},
|
||||
_a.NLS_MODULE = 'vs/nls',
|
||||
_a);
|
|
@ -1,37 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createImportRuleListener = void 0;
|
||||
function createImportRuleListener(validateImport) {
|
||||
function _checkImport(node) {
|
||||
if (node && node.type === 'Literal' && typeof node.value === 'string') {
|
||||
validateImport(node, node.value);
|
||||
}
|
||||
}
|
||||
return {
|
||||
// import ??? from 'module'
|
||||
ImportDeclaration: (node) => {
|
||||
_checkImport(node.source);
|
||||
},
|
||||
// import('module').then(...) OR await import('module')
|
||||
['CallExpression[callee.type="Import"][arguments.length=1] > Literal']: (node) => {
|
||||
_checkImport(node);
|
||||
},
|
||||
// import foo = ...
|
||||
['TSImportEqualsDeclaration > TSExternalModuleReference > Literal']: (node) => {
|
||||
_checkImport(node);
|
||||
},
|
||||
// export ?? from 'module'
|
||||
ExportAllDeclaration: (node) => {
|
||||
_checkImport(node.source);
|
||||
},
|
||||
// export {foo} from 'module'
|
||||
ExportNamedDeclaration: (node) => {
|
||||
_checkImport(node.source);
|
||||
},
|
||||
};
|
||||
}
|
||||
exports.createImportRuleListener = createImportRuleListener;
|
|
@ -1,35 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
||||
module.exports = new class ApiLiteralOrTypes {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#creating-objects' },
|
||||
messages: { sync: '`createXYZ`-functions are constructor-replacements and therefore must return sync', }
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
return {
|
||||
['TSDeclareFunction Identifier[name=/create.*/]']: (node) => {
|
||||
var _a;
|
||||
const decl = node.parent;
|
||||
if (((_a = decl.returnType) === null || _a === void 0 ? void 0 : _a.typeAnnotation.type) !== experimental_utils_1.AST_NODE_TYPES.TSTypeReference) {
|
||||
return;
|
||||
}
|
||||
if (decl.returnType.typeAnnotation.typeName.type !== experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return;
|
||||
}
|
||||
const ident = decl.returnType.typeAnnotation.typeName.name;
|
||||
if (ident === 'Promise' || ident === 'Thenable') {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'sync'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -1,87 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
var _a;
|
||||
const experimental_utils_1 = require("@typescript-eslint/experimental-utils");
|
||||
module.exports = new (_a = class ApiEventNaming {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
docs: {
|
||||
url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#event-naming'
|
||||
},
|
||||
messages: {
|
||||
naming: 'Event names must follow this patten: `on[Did|Will]<Verb><Subject>`',
|
||||
verb: 'Unknown verb \'{{verb}}\' - is this really a verb? Iff so, then add this verb to the configuration',
|
||||
subject: 'Unknown subject \'{{subject}}\' - This subject has not been used before but it should refer to something in the API',
|
||||
unknown: 'UNKNOWN event declaration, lint-rule needs tweaking'
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
const config = context.options[0];
|
||||
const allowed = new Set(config.allowed);
|
||||
const verbs = new Set(config.verbs);
|
||||
return {
|
||||
['TSTypeAnnotation TSTypeReference Identifier[name="Event"]']: (node) => {
|
||||
var _a, _b;
|
||||
const def = (_b = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.parent) === null || _b === void 0 ? void 0 : _b.parent;
|
||||
const ident = this.getIdent(def);
|
||||
if (!ident) {
|
||||
// event on unknown structure...
|
||||
return context.report({
|
||||
node,
|
||||
message: 'unknown'
|
||||
});
|
||||
}
|
||||
if (allowed.has(ident.name)) {
|
||||
// configured exception
|
||||
return;
|
||||
}
|
||||
const match = ApiEventNaming._nameRegExp.exec(ident.name);
|
||||
if (!match) {
|
||||
context.report({
|
||||
node: ident,
|
||||
messageId: 'naming'
|
||||
});
|
||||
return;
|
||||
}
|
||||
// check that <verb> is spelled out (configured) as verb
|
||||
if (!verbs.has(match[2].toLowerCase())) {
|
||||
context.report({
|
||||
node: ident,
|
||||
messageId: 'verb',
|
||||
data: { verb: match[2] }
|
||||
});
|
||||
}
|
||||
// check that a subject (if present) has occurred
|
||||
if (match[3]) {
|
||||
const regex = new RegExp(match[3], 'ig');
|
||||
const parts = context.getSourceCode().getText().split(regex);
|
||||
if (parts.length < 3) {
|
||||
context.report({
|
||||
node: ident,
|
||||
messageId: 'subject',
|
||||
data: { subject: match[3] }
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
getIdent(def) {
|
||||
if (!def) {
|
||||
return;
|
||||
}
|
||||
if (def.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return def;
|
||||
}
|
||||
else if ((def.type === experimental_utils_1.AST_NODE_TYPES.TSPropertySignature || def.type === experimental_utils_1.AST_NODE_TYPES.ClassProperty) && def.key.type === experimental_utils_1.AST_NODE_TYPES.Identifier) {
|
||||
return def.key;
|
||||
}
|
||||
return this.getIdent(def.parent);
|
||||
}
|
||||
},
|
||||
_a._nameRegExp = /on(Did|Will)([A-Z][a-z]+)([A-Z][a-z]+)?/,
|
||||
_a);
|
|
@ -1,30 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
var _a;
|
||||
module.exports = new (_a = class ApiInterfaceNaming {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
messages: {
|
||||
naming: 'Interfaces must not be prefixed with uppercase `I`',
|
||||
}
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
return {
|
||||
['TSInterfaceDeclaration Identifier']: (node) => {
|
||||
const name = node.name;
|
||||
if (ApiInterfaceNaming._nameRegExp.test(name)) {
|
||||
context.report({
|
||||
node,
|
||||
messageId: 'naming'
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
},
|
||||
_a._nameRegExp = /I[A-Z]/,
|
||||
_a);
|
|
@ -1,27 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
module.exports = new class ApiLiteralOrTypes {
|
||||
constructor() {
|
||||
this.meta = {
|
||||
docs: { url: 'https://github.com/microsoft/vscode/wiki/Extension-API-guidelines#enums' },
|
||||
messages: { useEnum: 'Use enums, not literal-or-types', }
|
||||
};
|
||||
}
|
||||
create(context) {
|
||||
return {
|
||||
['TSTypeAnnotation TSUnionType TSLiteralType']: (node) => {
|
||||
var _a;
|
||||
if (((_a = node.literal) === null || _a === void 0 ? void 0 : _a.type) === 'TSNullKeyword') {
|
||||
return;
|
||||
}
|
||||
context.report({
|
||||
node: node,
|
||||
messageId: 'useEnum'
|
||||
});
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
|
@ -1,325 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.translatePackageJSON = exports.scanBuiltinExtensions = exports.packageMarketplaceExtensionsStream = exports.packageLocalExtensionsStream = exports.fromMarketplace = void 0;
|
||||
const es = require("event-stream");
|
||||
const fs = require("fs");
|
||||
const glob = require("glob");
|
||||
const gulp = require("gulp");
|
||||
const path = require("path");
|
||||
const File = require("vinyl");
|
||||
const vsce = require("vsce");
|
||||
const stats_1 = require("./stats");
|
||||
const util2 = require("./util");
|
||||
const remote = require("gulp-remote-retry-src");
|
||||
const vzip = require('gulp-vinyl-zip');
|
||||
const filter = require("gulp-filter");
|
||||
const rename = require("gulp-rename");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const buffer = require('gulp-buffer');
|
||||
const json = require("gulp-json-editor");
|
||||
const jsoncParser = require("jsonc-parser");
|
||||
const webpack = require('webpack');
|
||||
const webpackGulp = require('webpack-stream');
|
||||
const util = require('./util');
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const commit = util.getVersion(root);
|
||||
const sourceMappingURLBase = `https://ticino.blob.core.windows.net/sourcemaps/${commit}`;
|
||||
function minifyExtensionResources(input) {
|
||||
const jsonFilter = filter(['**/*.json', '**/*.code-snippets'], { restore: true });
|
||||
return input
|
||||
.pipe(jsonFilter)
|
||||
.pipe(buffer())
|
||||
.pipe(es.mapSync((f) => {
|
||||
const errors = [];
|
||||
const value = jsoncParser.parse(f.contents.toString('utf8'), errors);
|
||||
if (errors.length === 0) {
|
||||
// file parsed OK => just stringify to drop whitespace and comments
|
||||
f.contents = Buffer.from(JSON.stringify(value));
|
||||
}
|
||||
return f;
|
||||
}))
|
||||
.pipe(jsonFilter.restore);
|
||||
}
|
||||
function updateExtensionPackageJSON(input, update) {
|
||||
const packageJsonFilter = filter('extensions/*/package.json', { restore: true });
|
||||
return input
|
||||
.pipe(packageJsonFilter)
|
||||
.pipe(buffer())
|
||||
.pipe(es.mapSync((f) => {
|
||||
const data = JSON.parse(f.contents.toString('utf8'));
|
||||
f.contents = Buffer.from(JSON.stringify(update(data)));
|
||||
return f;
|
||||
}))
|
||||
.pipe(packageJsonFilter.restore);
|
||||
}
|
||||
function fromLocal(extensionPath, forWeb) {
|
||||
const webpackConfigFileName = forWeb ? 'extension-browser.webpack.config.js' : 'extension.webpack.config.js';
|
||||
const isWebPacked = fs.existsSync(path.join(extensionPath, webpackConfigFileName));
|
||||
let input = isWebPacked
|
||||
? fromLocalWebpack(extensionPath, webpackConfigFileName)
|
||||
: fromLocalNormal(extensionPath);
|
||||
if (isWebPacked) {
|
||||
input = updateExtensionPackageJSON(input, (data) => {
|
||||
delete data.scripts;
|
||||
delete data.dependencies;
|
||||
delete data.devDependencies;
|
||||
if (data.main) {
|
||||
data.main = data.main.replace('/out/', /dist/);
|
||||
}
|
||||
return data;
|
||||
});
|
||||
}
|
||||
return input;
|
||||
}
|
||||
function fromLocalWebpack(extensionPath, webpackConfigFileName) {
|
||||
const result = es.through();
|
||||
const packagedDependencies = [];
|
||||
const packageJsonConfig = require(path.join(extensionPath, 'package.json'));
|
||||
if (packageJsonConfig.dependencies) {
|
||||
const webpackRootConfig = require(path.join(extensionPath, webpackConfigFileName));
|
||||
for (const key in webpackRootConfig.externals) {
|
||||
if (key in packageJsonConfig.dependencies) {
|
||||
packagedDependencies.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn, packagedDependencies }).then(fileNames => {
|
||||
const files = fileNames
|
||||
.map(fileName => path.join(extensionPath, fileName))
|
||||
.map(filePath => new File({
|
||||
path: filePath,
|
||||
stat: fs.statSync(filePath),
|
||||
base: extensionPath,
|
||||
contents: fs.createReadStream(filePath)
|
||||
}));
|
||||
// check for a webpack configuration files, then invoke webpack
|
||||
// and merge its output with the files stream.
|
||||
const webpackConfigLocations = glob.sync(path.join(extensionPath, '**', webpackConfigFileName), { ignore: ['**/node_modules'] });
|
||||
const webpackStreams = webpackConfigLocations.map(webpackConfigPath => {
|
||||
const webpackDone = (err, stats) => {
|
||||
fancyLog(`Bundled extension: ${ansiColors.yellow(path.join(path.basename(extensionPath), path.relative(extensionPath, webpackConfigPath)))}...`);
|
||||
if (err) {
|
||||
result.emit('error', err);
|
||||
}
|
||||
const { compilation } = stats;
|
||||
if (compilation.errors.length > 0) {
|
||||
result.emit('error', compilation.errors.join('\n'));
|
||||
}
|
||||
if (compilation.warnings.length > 0) {
|
||||
result.emit('error', compilation.warnings.join('\n'));
|
||||
}
|
||||
};
|
||||
const webpackConfig = Object.assign(Object.assign({}, require(webpackConfigPath)), { mode: 'production' });
|
||||
const relativeOutputPath = path.relative(extensionPath, webpackConfig.output.path);
|
||||
return webpackGulp(webpackConfig, webpack, webpackDone)
|
||||
.pipe(es.through(function (data) {
|
||||
data.stat = data.stat || {};
|
||||
data.base = extensionPath;
|
||||
this.emit('data', data);
|
||||
}))
|
||||
.pipe(es.through(function (data) {
|
||||
// source map handling:
|
||||
// * rewrite sourceMappingURL
|
||||
// * save to disk so that upload-task picks this up
|
||||
const contents = data.contents.toString('utf8');
|
||||
data.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, function (_m, g1) {
|
||||
return `\n//# sourceMappingURL=${sourceMappingURLBase}/extensions/${path.basename(extensionPath)}/${relativeOutputPath}/${g1}`;
|
||||
}), 'utf8');
|
||||
this.emit('data', data);
|
||||
}));
|
||||
});
|
||||
es.merge(...webpackStreams, es.readArray(files))
|
||||
// .pipe(es.through(function (data) {
|
||||
// // debug
|
||||
// console.log('out', data.path, data.contents.length);
|
||||
// this.emit('data', data);
|
||||
// }))
|
||||
.pipe(result);
|
||||
}).catch(err => {
|
||||
console.error(extensionPath);
|
||||
console.error(packagedDependencies);
|
||||
result.emit('error', err);
|
||||
});
|
||||
return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
|
||||
}
|
||||
function fromLocalNormal(extensionPath) {
|
||||
const result = es.through();
|
||||
vsce.listFiles({ cwd: extensionPath, packageManager: vsce.PackageManager.Yarn })
|
||||
.then(fileNames => {
|
||||
const files = fileNames
|
||||
.map(fileName => path.join(extensionPath, fileName))
|
||||
.map(filePath => new File({
|
||||
path: filePath,
|
||||
stat: fs.statSync(filePath),
|
||||
base: extensionPath,
|
||||
contents: fs.createReadStream(filePath)
|
||||
}));
|
||||
es.readArray(files).pipe(result);
|
||||
})
|
||||
.catch(err => result.emit('error', err));
|
||||
return result.pipe(stats_1.createStatsStream(path.basename(extensionPath)));
|
||||
}
|
||||
const baseHeaders = {
|
||||
'X-Market-Client-Id': 'VSCode Build',
|
||||
'User-Agent': 'VSCode Build',
|
||||
'X-Market-User-Id': '291C1CD0-051A-4123-9B4B-30D60EF52EE2',
|
||||
};
|
||||
function fromMarketplace(extensionName, version, metadata) {
|
||||
const [publisher, name] = extensionName.split('.');
|
||||
const url = `https://marketplace.visualstudio.com/_apis/public/gallery/publishers/${publisher}/vsextensions/${name}/${version}/vspackage`;
|
||||
fancyLog('Downloading extension:', ansiColors.yellow(`${extensionName}@${version}`), '...');
|
||||
const options = {
|
||||
base: url,
|
||||
requestOptions: {
|
||||
gzip: true,
|
||||
headers: baseHeaders
|
||||
}
|
||||
};
|
||||
const packageJsonFilter = filter('package.json', { restore: true });
|
||||
return remote('', options)
|
||||
.pipe(vzip.src())
|
||||
.pipe(filter('extension/**'))
|
||||
.pipe(rename(p => p.dirname = p.dirname.replace(/^extension\/?/, '')))
|
||||
.pipe(packageJsonFilter)
|
||||
.pipe(buffer())
|
||||
.pipe(json({ __metadata: metadata }))
|
||||
.pipe(packageJsonFilter.restore);
|
||||
}
|
||||
exports.fromMarketplace = fromMarketplace;
|
||||
const excludedExtensions = [
|
||||
'vscode-api-tests',
|
||||
'vscode-colorize-tests',
|
||||
'vscode-test-resolver',
|
||||
'ms-vscode.node-debug',
|
||||
'ms-vscode.node-debug2',
|
||||
'vscode-notebook-tests',
|
||||
'vscode-custom-editor-tests',
|
||||
];
|
||||
const marketplaceWebExtensions = [
|
||||
'ms-vscode.references-view'
|
||||
];
|
||||
const productJson = JSON.parse(fs.readFileSync(path.join(__dirname, '../../product.json'), 'utf8'));
|
||||
const builtInExtensions = productJson.builtInExtensions || [];
|
||||
const webBuiltInExtensions = productJson.webBuiltInExtensions || [];
|
||||
/**
|
||||
* Loosely based on `getExtensionKind` from `src/vs/workbench/services/extensions/common/extensionsUtil.ts`
|
||||
*/
|
||||
function isWebExtension(manifest) {
|
||||
if (typeof manifest.extensionKind !== 'undefined') {
|
||||
const extensionKind = Array.isArray(manifest.extensionKind) ? manifest.extensionKind : [manifest.extensionKind];
|
||||
return (extensionKind.indexOf('web') >= 0);
|
||||
}
|
||||
return (!Boolean(manifest.main) || Boolean(manifest.browser));
|
||||
}
|
||||
function packageLocalExtensionsStream(forWeb) {
|
||||
const localExtensionsDescriptions = (glob.sync('extensions/*/package.json')
|
||||
.map(manifestPath => {
|
||||
const absoluteManifestPath = path.join(root, manifestPath);
|
||||
const extensionPath = path.dirname(path.join(root, manifestPath));
|
||||
const extensionName = path.basename(extensionPath);
|
||||
return { name: extensionName, path: extensionPath, manifestPath: absoluteManifestPath };
|
||||
})
|
||||
.filter(({ name }) => excludedExtensions.indexOf(name) === -1)
|
||||
.filter(({ name }) => builtInExtensions.every(b => b.name !== name))
|
||||
.filter(({ manifestPath }) => (forWeb ? isWebExtension(require(manifestPath)) : true)));
|
||||
const localExtensionsStream = minifyExtensionResources(es.merge(...localExtensionsDescriptions.map(extension => {
|
||||
return fromLocal(extension.path, forWeb)
|
||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||
})));
|
||||
let result;
|
||||
if (forWeb) {
|
||||
result = localExtensionsStream;
|
||||
}
|
||||
else {
|
||||
// also include shared node modules
|
||||
result = es.merge(localExtensionsStream, gulp.src('extensions/node_modules/**', { base: '.' }));
|
||||
}
|
||||
return (result
|
||||
.pipe(util2.setExecutableBit(['**/*.sh'])));
|
||||
}
|
||||
exports.packageLocalExtensionsStream = packageLocalExtensionsStream;
|
||||
function packageMarketplaceExtensionsStream(forWeb) {
|
||||
const marketplaceExtensionsDescriptions = [
|
||||
...builtInExtensions.filter(({ name }) => (forWeb ? marketplaceWebExtensions.indexOf(name) >= 0 : true)),
|
||||
...(forWeb ? webBuiltInExtensions : [])
|
||||
];
|
||||
const marketplaceExtensionsStream = minifyExtensionResources(es.merge(...marketplaceExtensionsDescriptions
|
||||
.map(extension => {
|
||||
const input = fromMarketplace(extension.name, extension.version, extension.metadata)
|
||||
.pipe(rename(p => p.dirname = `extensions/${extension.name}/${p.dirname}`));
|
||||
return updateExtensionPackageJSON(input, (data) => {
|
||||
delete data.scripts;
|
||||
delete data.dependencies;
|
||||
delete data.devDependencies;
|
||||
return data;
|
||||
});
|
||||
})));
|
||||
return (marketplaceExtensionsStream
|
||||
.pipe(util2.setExecutableBit(['**/*.sh'])));
|
||||
}
|
||||
exports.packageMarketplaceExtensionsStream = packageMarketplaceExtensionsStream;
|
||||
function scanBuiltinExtensions(extensionsRoot, exclude = []) {
|
||||
const scannedExtensions = [];
|
||||
try {
|
||||
const extensionsFolders = fs.readdirSync(extensionsRoot);
|
||||
for (const extensionFolder of extensionsFolders) {
|
||||
if (exclude.indexOf(extensionFolder) >= 0) {
|
||||
continue;
|
||||
}
|
||||
const packageJSONPath = path.join(extensionsRoot, extensionFolder, 'package.json');
|
||||
if (!fs.existsSync(packageJSONPath)) {
|
||||
continue;
|
||||
}
|
||||
let packageJSON = JSON.parse(fs.readFileSync(packageJSONPath).toString('utf8'));
|
||||
if (!isWebExtension(packageJSON)) {
|
||||
continue;
|
||||
}
|
||||
const children = fs.readdirSync(path.join(extensionsRoot, extensionFolder));
|
||||
const packageNLSPath = children.filter(child => child === 'package.nls.json')[0];
|
||||
const packageNLS = packageNLSPath ? JSON.parse(fs.readFileSync(path.join(extensionsRoot, extensionFolder, packageNLSPath)).toString()) : undefined;
|
||||
const readme = children.filter(child => /^readme(\.txt|\.md|)$/i.test(child))[0];
|
||||
const changelog = children.filter(child => /^changelog(\.txt|\.md|)$/i.test(child))[0];
|
||||
scannedExtensions.push({
|
||||
extensionPath: extensionFolder,
|
||||
packageJSON,
|
||||
packageNLS,
|
||||
readmePath: readme ? path.join(extensionFolder, readme) : undefined,
|
||||
changelogPath: changelog ? path.join(extensionFolder, changelog) : undefined,
|
||||
});
|
||||
}
|
||||
return scannedExtensions;
|
||||
}
|
||||
catch (ex) {
|
||||
return scannedExtensions;
|
||||
}
|
||||
}
|
||||
exports.scanBuiltinExtensions = scanBuiltinExtensions;
|
||||
function translatePackageJSON(packageJSON, packageNLSPath) {
|
||||
const CharCode_PC = '%'.charCodeAt(0);
|
||||
const packageNls = JSON.parse(fs.readFileSync(packageNLSPath).toString());
|
||||
const translate = (obj) => {
|
||||
for (let key in obj) {
|
||||
const val = obj[key];
|
||||
if (Array.isArray(val)) {
|
||||
val.forEach(translate);
|
||||
}
|
||||
else if (val && typeof val === 'object') {
|
||||
translate(val);
|
||||
}
|
||||
else if (typeof val === 'string' && val.charCodeAt(0) === CharCode_PC && val.charCodeAt(val.length - 1) === CharCode_PC) {
|
||||
const translated = packageNls[val.substr(1, val.length - 2)];
|
||||
if (translated) {
|
||||
obj[key] = translated;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
translate(packageJSON);
|
||||
return packageJSON;
|
||||
}
|
||||
exports.translatePackageJSON = translatePackageJSON;
|
|
@ -1,54 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getVersion = void 0;
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
/**
|
||||
* Returns the sha1 commit version of a repository or undefined in case of failure.
|
||||
*/
|
||||
function getVersion(repo) {
|
||||
const git = path.join(repo, '.git');
|
||||
const headPath = path.join(git, 'HEAD');
|
||||
let head;
|
||||
try {
|
||||
head = fs.readFileSync(headPath, 'utf8').trim();
|
||||
}
|
||||
catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
if (/^[0-9a-f]{40}$/i.test(head)) {
|
||||
return head;
|
||||
}
|
||||
const refMatch = /^ref: (.*)$/.exec(head);
|
||||
if (!refMatch) {
|
||||
return undefined;
|
||||
}
|
||||
const ref = refMatch[1];
|
||||
const refPath = path.join(git, ref);
|
||||
try {
|
||||
return fs.readFileSync(refPath, 'utf8').trim();
|
||||
}
|
||||
catch (e) {
|
||||
// noop
|
||||
}
|
||||
const packedRefsPath = path.join(git, 'packed-refs');
|
||||
let refsRaw;
|
||||
try {
|
||||
refsRaw = fs.readFileSync(packedRefsPath, 'utf8').trim();
|
||||
}
|
||||
catch (e) {
|
||||
return undefined;
|
||||
}
|
||||
const refsRegex = /^([0-9a-f]{40})\s+(.+)$/gm;
|
||||
let refsMatch;
|
||||
let refs = {};
|
||||
while (refsMatch = refsRegex.exec(refsRaw)) {
|
||||
refs[refsMatch[2]] = refsMatch[1];
|
||||
}
|
||||
return refs[ref];
|
||||
}
|
||||
exports.getVersion = getVersion;
|
1204
build/lib/i18n.js
1204
build/lib/i18n.js
File diff suppressed because it is too large
Load diff
|
@ -1,285 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const ts = require("typescript");
|
||||
const fs_1 = require("fs");
|
||||
const path_1 = require("path");
|
||||
const minimatch_1 = require("minimatch");
|
||||
//
|
||||
// #############################################################################################
|
||||
//
|
||||
// A custom typescript checker for the specific task of detecting the use of certain types in a
|
||||
// layer that does not allow such use. For example:
|
||||
// - using DOM globals in common/node/electron-main layer (e.g. HTMLElement)
|
||||
// - using node.js globals in common/browser layer (e.g. process)
|
||||
//
|
||||
// Make changes to below RULES to lift certain files from these checks only if absolutely needed
|
||||
//
|
||||
// #############################################################################################
|
||||
//
|
||||
// Types we assume are present in all implementations of JS VMs (node.js, browsers)
|
||||
// Feel free to add more core types as you see needed if present in node.js and browsers
|
||||
const CORE_TYPES = [
|
||||
'require',
|
||||
'atob',
|
||||
'btoa',
|
||||
'setTimeout',
|
||||
'clearTimeout',
|
||||
'setInterval',
|
||||
'clearInterval',
|
||||
'console',
|
||||
'log',
|
||||
'info',
|
||||
'warn',
|
||||
'error',
|
||||
'group',
|
||||
'groupEnd',
|
||||
'table',
|
||||
'assert',
|
||||
'Error',
|
||||
'String',
|
||||
'throws',
|
||||
'stack',
|
||||
'captureStackTrace',
|
||||
'stackTraceLimit',
|
||||
'TextDecoder',
|
||||
'TextEncoder',
|
||||
'encode',
|
||||
'decode',
|
||||
'self',
|
||||
'trimLeft',
|
||||
'trimRight'
|
||||
];
|
||||
// Types that are defined in a common layer but are known to be only
|
||||
// available in native environments should not be allowed in browser
|
||||
const NATIVE_TYPES = [
|
||||
'NativeParsedArgs',
|
||||
'INativeEnvironmentService',
|
||||
'INativeWindowConfiguration',
|
||||
'ICommonNativeHostService'
|
||||
];
|
||||
const RULES = [
|
||||
// Tests: skip
|
||||
{
|
||||
target: '**/vs/**/test/**',
|
||||
skip: true // -> skip all test files
|
||||
},
|
||||
// Common: vs/base/common/platform.ts
|
||||
{
|
||||
target: '**/vs/base/common/platform.ts',
|
||||
allowedTypes: [
|
||||
...CORE_TYPES,
|
||||
// Safe access to postMessage() and friends
|
||||
'MessageEvent',
|
||||
'data'
|
||||
],
|
||||
disallowedTypes: NATIVE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common: vs/platform/environment/common/argv.ts
|
||||
{
|
||||
target: '**/vs/platform/environment/common/argv.ts',
|
||||
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common: vs/platform/environment/common/environment.ts
|
||||
{
|
||||
target: '**/vs/platform/environment/common/environment.ts',
|
||||
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common: vs/platform/windows/common/windows.ts
|
||||
{
|
||||
target: '**/vs/platform/windows/common/windows.ts',
|
||||
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common: vs/platform/native/common/native.ts
|
||||
{
|
||||
target: '**/vs/platform/native/common/native.ts',
|
||||
disallowedTypes: [ /* Ignore native types that are defined from here */],
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common: vs/workbench/api/common/extHostExtensionService.ts
|
||||
{
|
||||
target: '**/vs/workbench/api/common/extHostExtensionService.ts',
|
||||
allowedTypes: [
|
||||
...CORE_TYPES,
|
||||
// Safe access to global
|
||||
'global'
|
||||
],
|
||||
disallowedTypes: NATIVE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Common
|
||||
{
|
||||
target: '**/vs/**/common/**',
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedTypes: NATIVE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts',
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Browser
|
||||
{
|
||||
target: '**/vs/**/browser/**',
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedTypes: NATIVE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Browser (editor contrib)
|
||||
{
|
||||
target: '**/src/vs/editor/contrib/**',
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedTypes: NATIVE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// node.js
|
||||
{
|
||||
target: '**/vs/**/node/**',
|
||||
allowedTypes: [
|
||||
...CORE_TYPES,
|
||||
// --> types from node.d.ts that duplicate from lib.dom.d.ts
|
||||
'URL',
|
||||
'protocol',
|
||||
'hostname',
|
||||
'port',
|
||||
'pathname',
|
||||
'search',
|
||||
'username',
|
||||
'password'
|
||||
],
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts' // no DOM
|
||||
]
|
||||
},
|
||||
// Electron (sandbox)
|
||||
{
|
||||
target: '**/vs/**/electron-sandbox/**',
|
||||
allowedTypes: CORE_TYPES,
|
||||
disallowedDefinitions: [
|
||||
'@types/node' // no node.js
|
||||
]
|
||||
},
|
||||
// Electron (renderer): skip
|
||||
{
|
||||
target: '**/vs/**/electron-browser/**',
|
||||
skip: true // -> supports all types
|
||||
},
|
||||
// Electron (main)
|
||||
{
|
||||
target: '**/vs/**/electron-main/**',
|
||||
allowedTypes: [
|
||||
...CORE_TYPES,
|
||||
// --> types from electron.d.ts that duplicate from lib.dom.d.ts
|
||||
'Event',
|
||||
'Request'
|
||||
],
|
||||
disallowedDefinitions: [
|
||||
'lib.dom.d.ts' // no DOM
|
||||
]
|
||||
}
|
||||
];
|
||||
const TS_CONFIG_PATH = path_1.join(__dirname, '../../', 'src', 'tsconfig.json');
|
||||
let hasErrors = false;
|
||||
function checkFile(program, sourceFile, rule) {
|
||||
checkNode(sourceFile);
|
||||
function checkNode(node) {
|
||||
var _a, _b;
|
||||
if (node.kind !== ts.SyntaxKind.Identifier) {
|
||||
return ts.forEachChild(node, checkNode); // recurse down
|
||||
}
|
||||
const text = node.getText(sourceFile);
|
||||
if ((_a = rule.allowedTypes) === null || _a === void 0 ? void 0 : _a.some(allowed => allowed === text)) {
|
||||
return; // override
|
||||
}
|
||||
if ((_b = rule.disallowedTypes) === null || _b === void 0 ? void 0 : _b.some(disallowed => disallowed === text)) {
|
||||
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
||||
console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
|
||||
hasErrors = true;
|
||||
return;
|
||||
}
|
||||
const checker = program.getTypeChecker();
|
||||
const symbol = checker.getSymbolAtLocation(node);
|
||||
if (symbol) {
|
||||
const declarations = symbol.declarations;
|
||||
if (Array.isArray(declarations)) {
|
||||
for (const declaration of declarations) {
|
||||
if (declaration) {
|
||||
const parent = declaration.parent;
|
||||
if (parent) {
|
||||
const parentSourceFile = parent.getSourceFile();
|
||||
if (parentSourceFile) {
|
||||
const definitionFileName = parentSourceFile.fileName;
|
||||
if (rule.disallowedDefinitions) {
|
||||
for (const disallowedDefinition of rule.disallowedDefinitions) {
|
||||
if (definitionFileName.indexOf(disallowedDefinition) >= 0) {
|
||||
const { line, character } = sourceFile.getLineAndCharacterOfPosition(node.getStart());
|
||||
console.log(`[build/lib/layersChecker.ts]: Reference to '${text}' from '${disallowedDefinition}' violates layer '${rule.target}' (${sourceFile.fileName} (${line + 1},${character + 1})`);
|
||||
hasErrors = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function createProgram(tsconfigPath) {
|
||||
const tsConfig = ts.readConfigFile(tsconfigPath, ts.sys.readFile);
|
||||
const configHostParser = { fileExists: fs_1.existsSync, readDirectory: ts.sys.readDirectory, readFile: file => fs_1.readFileSync(file, 'utf8'), useCaseSensitiveFileNames: process.platform === 'linux' };
|
||||
const tsConfigParsed = ts.parseJsonConfigFileContent(tsConfig.config, configHostParser, path_1.resolve(path_1.dirname(tsconfigPath)), { noEmit: true });
|
||||
const compilerHost = ts.createCompilerHost(tsConfigParsed.options, true);
|
||||
return ts.createProgram(tsConfigParsed.fileNames, tsConfigParsed.options, compilerHost);
|
||||
}
|
||||
//
|
||||
// Create program and start checking
|
||||
//
|
||||
const program = createProgram(TS_CONFIG_PATH);
|
||||
for (const sourceFile of program.getSourceFiles()) {
|
||||
for (const rule of RULES) {
|
||||
if (minimatch_1.match([sourceFile.fileName], rule.target).length > 0) {
|
||||
if (!rule.skip) {
|
||||
checkFile(program, sourceFile, rule);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (hasErrors) {
|
||||
process.exit(1);
|
||||
}
|
354
build/lib/nls.js
354
build/lib/nls.js
|
@ -1,354 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
const ts = require("typescript");
|
||||
const lazy = require("lazy.js");
|
||||
const event_stream_1 = require("event-stream");
|
||||
const File = require("vinyl");
|
||||
const sm = require("source-map");
|
||||
const path = require("path");
|
||||
var CollectStepResult;
|
||||
(function (CollectStepResult) {
|
||||
CollectStepResult[CollectStepResult["Yes"] = 0] = "Yes";
|
||||
CollectStepResult[CollectStepResult["YesAndRecurse"] = 1] = "YesAndRecurse";
|
||||
CollectStepResult[CollectStepResult["No"] = 2] = "No";
|
||||
CollectStepResult[CollectStepResult["NoAndRecurse"] = 3] = "NoAndRecurse";
|
||||
})(CollectStepResult || (CollectStepResult = {}));
|
||||
function collect(node, fn) {
|
||||
const result = [];
|
||||
function loop(node) {
|
||||
const stepResult = fn(node);
|
||||
if (stepResult === CollectStepResult.Yes || stepResult === CollectStepResult.YesAndRecurse) {
|
||||
result.push(node);
|
||||
}
|
||||
if (stepResult === CollectStepResult.YesAndRecurse || stepResult === CollectStepResult.NoAndRecurse) {
|
||||
ts.forEachChild(node, loop);
|
||||
}
|
||||
}
|
||||
loop(node);
|
||||
return result;
|
||||
}
|
||||
function clone(object) {
|
||||
const result = {};
|
||||
for (const id in object) {
|
||||
result[id] = object[id];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function template(lines) {
|
||||
let indent = '', wrap = '';
|
||||
if (lines.length > 1) {
|
||||
indent = '\t';
|
||||
wrap = '\n';
|
||||
}
|
||||
return `/*---------------------------------------------------------
|
||||
* Copyright (C) Microsoft Corporation. All rights reserved.
|
||||
*--------------------------------------------------------*/
|
||||
define([], [${wrap + lines.map(l => indent + l).join(',\n') + wrap}]);`;
|
||||
}
|
||||
/**
|
||||
* Returns a stream containing the patched JavaScript and source maps.
|
||||
*/
|
||||
function nls() {
|
||||
const input = event_stream_1.through();
|
||||
const output = input.pipe(event_stream_1.through(function (f) {
|
||||
if (!f.sourceMap) {
|
||||
return this.emit('error', new Error(`File ${f.relative} does not have sourcemaps.`));
|
||||
}
|
||||
let source = f.sourceMap.sources[0];
|
||||
if (!source) {
|
||||
return this.emit('error', new Error(`File ${f.relative} does not have a source in the source map.`));
|
||||
}
|
||||
const root = f.sourceMap.sourceRoot;
|
||||
if (root) {
|
||||
source = path.join(root, source);
|
||||
}
|
||||
const typescript = f.sourceMap.sourcesContent[0];
|
||||
if (!typescript) {
|
||||
return this.emit('error', new Error(`File ${f.relative} does not have the original content in the source map.`));
|
||||
}
|
||||
nls.patchFiles(f, typescript).forEach(f => this.emit('data', f));
|
||||
}));
|
||||
return event_stream_1.duplex(input, output);
|
||||
}
|
||||
function isImportNode(node) {
|
||||
return node.kind === ts.SyntaxKind.ImportDeclaration || node.kind === ts.SyntaxKind.ImportEqualsDeclaration;
|
||||
}
|
||||
(function (nls_1) {
|
||||
function fileFrom(file, contents, path = file.path) {
|
||||
return new File({
|
||||
contents: Buffer.from(contents),
|
||||
base: file.base,
|
||||
cwd: file.cwd,
|
||||
path: path
|
||||
});
|
||||
}
|
||||
nls_1.fileFrom = fileFrom;
|
||||
function mappedPositionFrom(source, lc) {
|
||||
return { source, line: lc.line + 1, column: lc.character };
|
||||
}
|
||||
nls_1.mappedPositionFrom = mappedPositionFrom;
|
||||
function lcFrom(position) {
|
||||
return { line: position.line - 1, character: position.column };
|
||||
}
|
||||
nls_1.lcFrom = lcFrom;
|
||||
class SingleFileServiceHost {
|
||||
constructor(options, filename, contents) {
|
||||
this.options = options;
|
||||
this.filename = filename;
|
||||
this.getCompilationSettings = () => this.options;
|
||||
this.getScriptFileNames = () => [this.filename];
|
||||
this.getScriptVersion = () => '1';
|
||||
this.getScriptSnapshot = (name) => name === this.filename ? this.file : this.lib;
|
||||
this.getCurrentDirectory = () => '';
|
||||
this.getDefaultLibFileName = () => 'lib.d.ts';
|
||||
this.file = ts.ScriptSnapshot.fromString(contents);
|
||||
this.lib = ts.ScriptSnapshot.fromString('');
|
||||
}
|
||||
}
|
||||
nls_1.SingleFileServiceHost = SingleFileServiceHost;
|
||||
function isCallExpressionWithinTextSpanCollectStep(textSpan, node) {
|
||||
if (!ts.textSpanContainsTextSpan({ start: node.pos, length: node.end - node.pos }, textSpan)) {
|
||||
return CollectStepResult.No;
|
||||
}
|
||||
return node.kind === ts.SyntaxKind.CallExpression ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse;
|
||||
}
|
||||
function analyze(contents, options = {}) {
|
||||
const filename = 'file.ts';
|
||||
const serviceHost = new SingleFileServiceHost(Object.assign(clone(options), { noResolve: true }), filename, contents);
|
||||
const service = ts.createLanguageService(serviceHost);
|
||||
const sourceFile = ts.createSourceFile(filename, contents, ts.ScriptTarget.ES5, true);
|
||||
// all imports
|
||||
const imports = lazy(collect(sourceFile, n => isImportNode(n) ? CollectStepResult.YesAndRecurse : CollectStepResult.NoAndRecurse));
|
||||
// import nls = require('vs/nls');
|
||||
const importEqualsDeclarations = imports
|
||||
.filter(n => n.kind === ts.SyntaxKind.ImportEqualsDeclaration)
|
||||
.map(n => n)
|
||||
.filter(d => d.moduleReference.kind === ts.SyntaxKind.ExternalModuleReference)
|
||||
.filter(d => d.moduleReference.expression.getText() === '\'vs/nls\'');
|
||||
// import ... from 'vs/nls';
|
||||
const importDeclarations = imports
|
||||
.filter(n => n.kind === ts.SyntaxKind.ImportDeclaration)
|
||||
.map(n => n)
|
||||
.filter(d => d.moduleSpecifier.kind === ts.SyntaxKind.StringLiteral)
|
||||
.filter(d => d.moduleSpecifier.getText() === '\'vs/nls\'')
|
||||
.filter(d => !!d.importClause && !!d.importClause.namedBindings);
|
||||
const nlsExpressions = importEqualsDeclarations
|
||||
.map(d => d.moduleReference.expression)
|
||||
.concat(importDeclarations.map(d => d.moduleSpecifier))
|
||||
.map(d => ({
|
||||
start: ts.getLineAndCharacterOfPosition(sourceFile, d.getStart()),
|
||||
end: ts.getLineAndCharacterOfPosition(sourceFile, d.getEnd())
|
||||
}));
|
||||
// `nls.localize(...)` calls
|
||||
const nlsLocalizeCallExpressions = importDeclarations
|
||||
.filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamespaceImport))
|
||||
.map(d => d.importClause.namedBindings.name)
|
||||
.concat(importEqualsDeclarations.map(d => d.name))
|
||||
// find read-only references to `nls`
|
||||
.map(n => service.getReferencesAtPosition(filename, n.pos + 1))
|
||||
.flatten()
|
||||
.filter(r => !r.isWriteAccess)
|
||||
// find the deepest call expressions AST nodes that contain those references
|
||||
.map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
|
||||
.map(a => lazy(a).last())
|
||||
.filter(n => !!n)
|
||||
.map(n => n)
|
||||
// only `localize` calls
|
||||
.filter(n => n.expression.kind === ts.SyntaxKind.PropertyAccessExpression && n.expression.name.getText() === 'localize');
|
||||
// `localize` named imports
|
||||
const allLocalizeImportDeclarations = importDeclarations
|
||||
.filter(d => !!(d.importClause && d.importClause.namedBindings && d.importClause.namedBindings.kind === ts.SyntaxKind.NamedImports))
|
||||
.map(d => [].concat(d.importClause.namedBindings.elements))
|
||||
.flatten();
|
||||
// `localize` read-only references
|
||||
const localizeReferences = allLocalizeImportDeclarations
|
||||
.filter(d => d.name.getText() === 'localize')
|
||||
.map(n => service.getReferencesAtPosition(filename, n.pos + 1))
|
||||
.flatten()
|
||||
.filter(r => !r.isWriteAccess);
|
||||
// custom named `localize` read-only references
|
||||
const namedLocalizeReferences = allLocalizeImportDeclarations
|
||||
.filter(d => d.propertyName && d.propertyName.getText() === 'localize')
|
||||
.map(n => service.getReferencesAtPosition(filename, n.name.pos + 1))
|
||||
.flatten()
|
||||
.filter(r => !r.isWriteAccess);
|
||||
// find the deepest call expressions AST nodes that contain those references
|
||||
const localizeCallExpressions = localizeReferences
|
||||
.concat(namedLocalizeReferences)
|
||||
.map(r => collect(sourceFile, n => isCallExpressionWithinTextSpanCollectStep(r.textSpan, n)))
|
||||
.map(a => lazy(a).last())
|
||||
.filter(n => !!n)
|
||||
.map(n => n);
|
||||
// collect everything
|
||||
const localizeCalls = nlsLocalizeCallExpressions
|
||||
.concat(localizeCallExpressions)
|
||||
.map(e => e.arguments)
|
||||
.filter(a => a.length > 1)
|
||||
.sort((a, b) => a[0].getStart() - b[0].getStart())
|
||||
.map(a => ({
|
||||
keySpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[0].getEnd()) },
|
||||
key: a[0].getText(),
|
||||
valueSpan: { start: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getStart()), end: ts.getLineAndCharacterOfPosition(sourceFile, a[1].getEnd()) },
|
||||
value: a[1].getText()
|
||||
}));
|
||||
return {
|
||||
localizeCalls: localizeCalls.toArray(),
|
||||
nlsExpressions: nlsExpressions.toArray()
|
||||
};
|
||||
}
|
||||
nls_1.analyze = analyze;
|
||||
class TextModel {
|
||||
constructor(contents) {
|
||||
const regex = /\r\n|\r|\n/g;
|
||||
let index = 0;
|
||||
let match;
|
||||
this.lines = [];
|
||||
this.lineEndings = [];
|
||||
while (match = regex.exec(contents)) {
|
||||
this.lines.push(contents.substring(index, match.index));
|
||||
this.lineEndings.push(match[0]);
|
||||
index = regex.lastIndex;
|
||||
}
|
||||
if (contents.length > 0) {
|
||||
this.lines.push(contents.substring(index, contents.length));
|
||||
this.lineEndings.push('');
|
||||
}
|
||||
}
|
||||
get(index) {
|
||||
return this.lines[index];
|
||||
}
|
||||
set(index, line) {
|
||||
this.lines[index] = line;
|
||||
}
|
||||
get lineCount() {
|
||||
return this.lines.length;
|
||||
}
|
||||
/**
|
||||
* Applies patch(es) to the model.
|
||||
* Multiple patches must be ordered.
|
||||
* Does not support patches spanning multiple lines.
|
||||
*/
|
||||
apply(patch) {
|
||||
const startLineNumber = patch.span.start.line;
|
||||
const endLineNumber = patch.span.end.line;
|
||||
const startLine = this.lines[startLineNumber] || '';
|
||||
const endLine = this.lines[endLineNumber] || '';
|
||||
this.lines[startLineNumber] = [
|
||||
startLine.substring(0, patch.span.start.character),
|
||||
patch.content,
|
||||
endLine.substring(patch.span.end.character)
|
||||
].join('');
|
||||
for (let i = startLineNumber + 1; i <= endLineNumber; i++) {
|
||||
this.lines[i] = '';
|
||||
}
|
||||
}
|
||||
toString() {
|
||||
return lazy(this.lines).zip(this.lineEndings)
|
||||
.flatten().toArray().join('');
|
||||
}
|
||||
}
|
||||
nls_1.TextModel = TextModel;
|
||||
function patchJavascript(patches, contents, moduleId) {
|
||||
const model = new nls.TextModel(contents);
|
||||
// patch the localize calls
|
||||
lazy(patches).reverse().each(p => model.apply(p));
|
||||
// patch the 'vs/nls' imports
|
||||
const firstLine = model.get(0);
|
||||
const patchedFirstLine = firstLine.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
|
||||
model.set(0, patchedFirstLine);
|
||||
return model.toString();
|
||||
}
|
||||
nls_1.patchJavascript = patchJavascript;
|
||||
function patchSourcemap(patches, rsm, smc) {
|
||||
const smg = new sm.SourceMapGenerator({
|
||||
file: rsm.file,
|
||||
sourceRoot: rsm.sourceRoot
|
||||
});
|
||||
patches = patches.reverse();
|
||||
let currentLine = -1;
|
||||
let currentLineDiff = 0;
|
||||
let source = null;
|
||||
smc.eachMapping(m => {
|
||||
const patch = patches[patches.length - 1];
|
||||
const original = { line: m.originalLine, column: m.originalColumn };
|
||||
const generated = { line: m.generatedLine, column: m.generatedColumn };
|
||||
if (currentLine !== generated.line) {
|
||||
currentLineDiff = 0;
|
||||
}
|
||||
currentLine = generated.line;
|
||||
generated.column += currentLineDiff;
|
||||
if (patch && m.generatedLine - 1 === patch.span.end.line && m.generatedColumn === patch.span.end.character) {
|
||||
const originalLength = patch.span.end.character - patch.span.start.character;
|
||||
const modifiedLength = patch.content.length;
|
||||
const lengthDiff = modifiedLength - originalLength;
|
||||
currentLineDiff += lengthDiff;
|
||||
generated.column += lengthDiff;
|
||||
patches.pop();
|
||||
}
|
||||
source = rsm.sourceRoot ? path.relative(rsm.sourceRoot, m.source) : m.source;
|
||||
source = source.replace(/\\/g, '/');
|
||||
smg.addMapping({ source, name: m.name, original, generated });
|
||||
}, null, sm.SourceMapConsumer.GENERATED_ORDER);
|
||||
if (source) {
|
||||
smg.setSourceContent(source, smc.sourceContentFor(source));
|
||||
}
|
||||
return JSON.parse(smg.toString());
|
||||
}
|
||||
nls_1.patchSourcemap = patchSourcemap;
|
||||
function patch(moduleId, typescript, javascript, sourcemap) {
|
||||
const { localizeCalls, nlsExpressions } = analyze(typescript);
|
||||
if (localizeCalls.length === 0) {
|
||||
return { javascript, sourcemap };
|
||||
}
|
||||
const nlsKeys = template(localizeCalls.map(lc => lc.key));
|
||||
const nls = template(localizeCalls.map(lc => lc.value));
|
||||
const smc = new sm.SourceMapConsumer(sourcemap);
|
||||
const positionFrom = mappedPositionFrom.bind(null, sourcemap.sources[0]);
|
||||
let i = 0;
|
||||
// build patches
|
||||
const patches = lazy(localizeCalls)
|
||||
.map(lc => ([
|
||||
{ range: lc.keySpan, content: '' + (i++) },
|
||||
{ range: lc.valueSpan, content: 'null' }
|
||||
]))
|
||||
.flatten()
|
||||
.map(c => {
|
||||
const start = lcFrom(smc.generatedPositionFor(positionFrom(c.range.start)));
|
||||
const end = lcFrom(smc.generatedPositionFor(positionFrom(c.range.end)));
|
||||
return { span: { start, end }, content: c.content };
|
||||
})
|
||||
.toArray();
|
||||
javascript = patchJavascript(patches, javascript, moduleId);
|
||||
// since imports are not within the sourcemap information,
|
||||
// we must do this MacGyver style
|
||||
if (nlsExpressions.length) {
|
||||
javascript = javascript.replace(/^define\(.*$/m, line => {
|
||||
return line.replace(/(['"])vs\/nls\1/g, `$1vs/nls!${moduleId}$1`);
|
||||
});
|
||||
}
|
||||
sourcemap = patchSourcemap(patches, sourcemap, smc);
|
||||
return { javascript, sourcemap, nlsKeys, nls };
|
||||
}
|
||||
nls_1.patch = patch;
|
||||
function patchFiles(javascriptFile, typescript) {
|
||||
// hack?
|
||||
const moduleId = javascriptFile.relative
|
||||
.replace(/\.js$/, '')
|
||||
.replace(/\\/g, '/');
|
||||
const { javascript, sourcemap, nlsKeys, nls } = patch(moduleId, typescript, javascriptFile.contents.toString(), javascriptFile.sourceMap);
|
||||
const result = [fileFrom(javascriptFile, javascript)];
|
||||
result[0].sourceMap = sourcemap;
|
||||
if (nlsKeys) {
|
||||
result.push(fileFrom(javascriptFile, nlsKeys, javascriptFile.path.replace(/\.js$/, '.nls.keys.js')));
|
||||
}
|
||||
if (nls) {
|
||||
result.push(fileFrom(javascriptFile, nls, javascriptFile.path.replace(/\.js$/, '.nls.js')));
|
||||
}
|
||||
return result;
|
||||
}
|
||||
nls_1.patchFiles = patchFiles;
|
||||
})(nls || (nls = {}));
|
||||
module.exports = nls;
|
|
@ -1,15 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const yarnrcPath = path.join(root, 'remote', '.yarnrc');
|
||||
const yarnrc = fs.readFileSync(yarnrcPath, 'utf8');
|
||||
const version = /^target\s+"([^"]+)"$/m.exec(yarnrc)[1];
|
||||
const node = process.platform === 'win32' ? 'node.exe' : 'node';
|
||||
const nodePath = path.join(root, '.build', 'node', `v${version}`, `${process.platform}-${process.arch}`, node);
|
||||
console.log(nodePath);
|
|
@ -1,235 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.minifyTask = exports.optimizeTask = exports.loaderConfig = void 0;
|
||||
const es = require("event-stream");
|
||||
const gulp = require("gulp");
|
||||
const concat = require("gulp-concat");
|
||||
const minifyCSS = require("gulp-cssnano");
|
||||
const filter = require("gulp-filter");
|
||||
const flatmap = require("gulp-flatmap");
|
||||
const sourcemaps = require("gulp-sourcemaps");
|
||||
const uglify = require("gulp-uglify");
|
||||
const composer = require("gulp-uglify/composer");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const path = require("path");
|
||||
const pump = require("pump");
|
||||
const terser = require("terser");
|
||||
const VinylFile = require("vinyl");
|
||||
const bundle = require("./bundle");
|
||||
const i18n_1 = require("./i18n");
|
||||
const stats_1 = require("./stats");
|
||||
const util = require("./util");
|
||||
const REPO_ROOT_PATH = path.join(__dirname, '../..');
|
||||
function log(prefix, message) {
|
||||
fancyLog(ansiColors.cyan('[' + prefix + ']'), message);
|
||||
}
|
||||
function loaderConfig() {
|
||||
const result = {
|
||||
paths: {
|
||||
'vs': 'out-build/vs',
|
||||
'vscode': 'empty:'
|
||||
},
|
||||
amdModulesPattern: /^vs\//
|
||||
};
|
||||
result['vs/css'] = { inlineResources: true };
|
||||
return result;
|
||||
}
|
||||
exports.loaderConfig = loaderConfig;
|
||||
const IS_OUR_COPYRIGHT_REGEXP = /Copyright \(C\) Microsoft Corporation/i;
|
||||
function loader(src, bundledFileHeader, bundleLoader) {
|
||||
let sources = [
|
||||
`${src}/vs/loader.js`
|
||||
];
|
||||
if (bundleLoader) {
|
||||
sources = sources.concat([
|
||||
`${src}/vs/css.js`,
|
||||
`${src}/vs/nls.js`
|
||||
]);
|
||||
}
|
||||
let isFirst = true;
|
||||
return (gulp
|
||||
.src(sources, { base: `${src}` })
|
||||
.pipe(es.through(function (data) {
|
||||
if (isFirst) {
|
||||
isFirst = false;
|
||||
this.emit('data', new VinylFile({
|
||||
path: 'fake',
|
||||
base: '',
|
||||
contents: Buffer.from(bundledFileHeader)
|
||||
}));
|
||||
this.emit('data', data);
|
||||
}
|
||||
else {
|
||||
this.emit('data', data);
|
||||
}
|
||||
}))
|
||||
.pipe(concat('vs/loader.js')));
|
||||
}
|
||||
function toConcatStream(src, bundledFileHeader, sources, dest, fileContentMapper) {
|
||||
const useSourcemaps = /\.js$/.test(dest) && !/\.nls\.js$/.test(dest);
|
||||
// If a bundle ends up including in any of the sources our copyright, then
|
||||
// insert a fake source at the beginning of each bundle with our copyright
|
||||
let containsOurCopyright = false;
|
||||
for (let i = 0, len = sources.length; i < len; i++) {
|
||||
const fileContents = sources[i].contents;
|
||||
if (IS_OUR_COPYRIGHT_REGEXP.test(fileContents)) {
|
||||
containsOurCopyright = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (containsOurCopyright) {
|
||||
sources.unshift({
|
||||
path: null,
|
||||
contents: bundledFileHeader
|
||||
});
|
||||
}
|
||||
const treatedSources = sources.map(function (source) {
|
||||
const root = source.path ? REPO_ROOT_PATH.replace(/\\/g, '/') : '';
|
||||
const base = source.path ? root + `/${src}` : '';
|
||||
const path = source.path ? root + '/' + source.path.replace(/\\/g, '/') : 'fake';
|
||||
const contents = source.path ? fileContentMapper(source.contents, path) : source.contents;
|
||||
return new VinylFile({
|
||||
path: path,
|
||||
base: base,
|
||||
contents: Buffer.from(contents)
|
||||
});
|
||||
});
|
||||
return es.readArray(treatedSources)
|
||||
.pipe(useSourcemaps ? util.loadSourcemaps() : es.through())
|
||||
.pipe(concat(dest))
|
||||
.pipe(stats_1.createStatsStream(dest));
|
||||
}
|
||||
function toBundleStream(src, bundledFileHeader, bundles, fileContentMapper) {
|
||||
return es.merge(bundles.map(function (bundle) {
|
||||
return toConcatStream(src, bundledFileHeader, bundle.sources, bundle.dest, fileContentMapper);
|
||||
}));
|
||||
}
|
||||
const DEFAULT_FILE_HEADER = [
|
||||
'/*!--------------------------------------------------------',
|
||||
' * Copyright (C) Microsoft Corporation. All rights reserved.',
|
||||
' *--------------------------------------------------------*/'
|
||||
].join('\n');
|
||||
function optimizeTask(opts) {
|
||||
const src = opts.src;
|
||||
const entryPoints = opts.entryPoints;
|
||||
const resources = opts.resources;
|
||||
const loaderConfig = opts.loaderConfig;
|
||||
const bundledFileHeader = opts.header || DEFAULT_FILE_HEADER;
|
||||
const bundleLoader = (typeof opts.bundleLoader === 'undefined' ? true : opts.bundleLoader);
|
||||
const out = opts.out;
|
||||
const fileContentMapper = opts.fileContentMapper || ((contents, _path) => contents);
|
||||
return function () {
|
||||
const bundlesStream = es.through(); // this stream will contain the bundled files
|
||||
const resourcesStream = es.through(); // this stream will contain the resources
|
||||
const bundleInfoStream = es.through(); // this stream will contain bundleInfo.json
|
||||
bundle.bundle(entryPoints, loaderConfig, function (err, result) {
|
||||
if (err || !result) {
|
||||
return bundlesStream.emit('error', JSON.stringify(err));
|
||||
}
|
||||
toBundleStream(src, bundledFileHeader, result.files, fileContentMapper).pipe(bundlesStream);
|
||||
// Remove css inlined resources
|
||||
const filteredResources = resources.slice();
|
||||
result.cssInlinedResources.forEach(function (resource) {
|
||||
if (process.env['VSCODE_BUILD_VERBOSE']) {
|
||||
log('optimizer', 'excluding inlined: ' + resource);
|
||||
}
|
||||
filteredResources.push('!' + resource);
|
||||
});
|
||||
gulp.src(filteredResources, { base: `${src}`, allowEmpty: true }).pipe(resourcesStream);
|
||||
const bundleInfoArray = [];
|
||||
if (opts.bundleInfo) {
|
||||
bundleInfoArray.push(new VinylFile({
|
||||
path: 'bundleInfo.json',
|
||||
base: '.',
|
||||
contents: Buffer.from(JSON.stringify(result.bundleData, null, '\t'))
|
||||
}));
|
||||
}
|
||||
es.readArray(bundleInfoArray).pipe(bundleInfoStream);
|
||||
});
|
||||
const result = es.merge(loader(src, bundledFileHeader, bundleLoader), bundlesStream, resourcesStream, bundleInfoStream);
|
||||
return result
|
||||
.pipe(sourcemaps.write('./', {
|
||||
sourceRoot: undefined,
|
||||
addComment: true,
|
||||
includeContent: true
|
||||
}))
|
||||
.pipe(opts.languages && opts.languages.length ? i18n_1.processNlsFiles({
|
||||
fileHeader: bundledFileHeader,
|
||||
languages: opts.languages
|
||||
}) : es.through())
|
||||
.pipe(gulp.dest(out));
|
||||
};
|
||||
}
|
||||
exports.optimizeTask = optimizeTask;
|
||||
/**
|
||||
* Wrap around uglify and allow the preserveComments function
|
||||
* to have a file "context" to include our copyright only once per file.
|
||||
*/
|
||||
function uglifyWithCopyrights() {
|
||||
const preserveComments = (f) => {
|
||||
return (_node, comment) => {
|
||||
const text = comment.value;
|
||||
const type = comment.type;
|
||||
if (/@minifier_do_not_preserve/.test(text)) {
|
||||
return false;
|
||||
}
|
||||
const isOurCopyright = IS_OUR_COPYRIGHT_REGEXP.test(text);
|
||||
if (isOurCopyright) {
|
||||
if (f.__hasOurCopyright) {
|
||||
return false;
|
||||
}
|
||||
f.__hasOurCopyright = true;
|
||||
return true;
|
||||
}
|
||||
if ('comment2' === type) {
|
||||
// check for /*!. Note that text doesn't contain leading /*
|
||||
return (text.length > 0 && text[0] === '!') || /@preserve|license|@cc_on|copyright/i.test(text);
|
||||
}
|
||||
else if ('comment1' === type) {
|
||||
return /license|copyright/i.test(text);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
};
|
||||
const minify = composer(terser);
|
||||
const input = es.through();
|
||||
const output = input
|
||||
.pipe(flatmap((stream, f) => {
|
||||
return stream.pipe(minify({
|
||||
output: {
|
||||
comments: preserveComments(f),
|
||||
max_line_len: 1024
|
||||
}
|
||||
}));
|
||||
}));
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
function minifyTask(src, sourceMapBaseUrl) {
|
||||
const sourceMappingURL = sourceMapBaseUrl ? ((f) => `${sourceMapBaseUrl}/${f.relative}.map`) : undefined;
|
||||
return cb => {
|
||||
const jsFilter = filter('**/*.js', { restore: true });
|
||||
const cssFilter = filter('**/*.css', { restore: true });
|
||||
pump(gulp.src([src + '/**', '!' + src + '/**/*.map']), jsFilter, sourcemaps.init({ loadMaps: true }), uglifyWithCopyrights(), jsFilter.restore, cssFilter, minifyCSS({ reduceIdents: false }), cssFilter.restore, sourcemaps.mapSources((sourcePath) => {
|
||||
if (sourcePath === 'bootstrap-fork.js') {
|
||||
return 'bootstrap-fork.orig.js';
|
||||
}
|
||||
return sourcePath;
|
||||
}), sourcemaps.write('./', {
|
||||
sourceMappingURL,
|
||||
sourceRoot: undefined,
|
||||
includeContent: true,
|
||||
addComment: true
|
||||
}), gulp.dest(src + '-min'), (err) => {
|
||||
if (err instanceof uglify.GulpUglifyError) {
|
||||
console.error(`Uglify error in '${err.cause && err.cause.filename}'`);
|
||||
}
|
||||
cb(err);
|
||||
});
|
||||
};
|
||||
}
|
||||
exports.minifyTask = minifyTask;
|
|
@ -1,55 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
// @ts-check
|
||||
const path = require("path");
|
||||
const child_process_1 = require("child_process");
|
||||
const fs_1 = require("fs");
|
||||
const yarn = process.platform === 'win32' ? 'yarn.cmd' : 'yarn';
|
||||
const rootDir = path.resolve(__dirname, '..', '..');
|
||||
function runProcess(command, args = []) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const child = child_process_1.spawn(command, args, { cwd: rootDir, stdio: 'inherit', env: process.env });
|
||||
child.on('exit', err => !err ? resolve() : process.exit(err !== null && err !== void 0 ? err : 1));
|
||||
child.on('error', reject);
|
||||
});
|
||||
}
|
||||
async function exists(subdir) {
|
||||
try {
|
||||
await fs_1.promises.stat(path.join(rootDir, subdir));
|
||||
return true;
|
||||
}
|
||||
catch (_a) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
async function ensureNodeModules() {
|
||||
if (!(await exists('node_modules'))) {
|
||||
await runProcess(yarn);
|
||||
}
|
||||
}
|
||||
async function getElectron() {
|
||||
await runProcess(yarn, ['electron']);
|
||||
}
|
||||
async function ensureCompiled() {
|
||||
if (!(await exists('out'))) {
|
||||
await runProcess(yarn, ['compile']);
|
||||
}
|
||||
}
|
||||
async function main() {
|
||||
await ensureNodeModules();
|
||||
await getElectron();
|
||||
await ensureCompiled();
|
||||
// Can't require this until after dependencies are installed
|
||||
const { getBuiltInExtensions } = require('./builtInExtensions');
|
||||
await getBuiltInExtensions();
|
||||
}
|
||||
if (require.main === module) {
|
||||
main().catch(err => {
|
||||
console.error(err);
|
||||
process.exit(1);
|
||||
});
|
||||
}
|
|
@ -1,86 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createReporter = void 0;
|
||||
const es = require("event-stream");
|
||||
const _ = require("underscore");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const allErrors = [];
|
||||
let startTime = null;
|
||||
let count = 0;
|
||||
function onStart() {
|
||||
if (count++ > 0) {
|
||||
return;
|
||||
}
|
||||
startTime = new Date().getTime();
|
||||
fancyLog(`Starting ${ansiColors.green('compilation')}...`);
|
||||
}
|
||||
function onEnd() {
|
||||
if (--count > 0) {
|
||||
return;
|
||||
}
|
||||
log();
|
||||
}
|
||||
const buildLogPath = path.join(path.dirname(path.dirname(__dirname)), '.build', 'log');
|
||||
try {
|
||||
fs.mkdirSync(path.dirname(buildLogPath));
|
||||
}
|
||||
catch (err) {
|
||||
// ignore
|
||||
}
|
||||
function log() {
|
||||
const errors = _.flatten(allErrors);
|
||||
const seen = new Set();
|
||||
errors.map(err => {
|
||||
if (!seen.has(err)) {
|
||||
seen.add(err);
|
||||
fancyLog(`${ansiColors.red('Error')}: ${err}`);
|
||||
}
|
||||
});
|
||||
const regex = /^([^(]+)\((\d+),(\d+)\): (.*)$/;
|
||||
const messages = errors
|
||||
.map(err => regex.exec(err))
|
||||
.filter(match => !!match)
|
||||
.map(x => x)
|
||||
.map(([, path, line, column, message]) => ({ path, line: parseInt(line), column: parseInt(column), message }));
|
||||
try {
|
||||
fs.writeFileSync(buildLogPath, JSON.stringify(messages));
|
||||
}
|
||||
catch (err) {
|
||||
//noop
|
||||
}
|
||||
fancyLog(`Finished ${ansiColors.green('compilation')} with ${errors.length} errors after ${ansiColors.magenta((new Date().getTime() - startTime) + ' ms')}`);
|
||||
}
|
||||
function createReporter() {
|
||||
const errors = [];
|
||||
allErrors.push(errors);
|
||||
const result = (err) => errors.push(err);
|
||||
result.hasErrors = () => errors.length > 0;
|
||||
result.end = (emitError) => {
|
||||
errors.length = 0;
|
||||
onStart();
|
||||
return es.through(undefined, function () {
|
||||
onEnd();
|
||||
if (emitError && errors.length > 0) {
|
||||
if (!errors.__logged__) {
|
||||
log();
|
||||
}
|
||||
errors.__logged__ = true;
|
||||
const err = new Error(`Found ${errors.length} errors`);
|
||||
err.__reporter__ = true;
|
||||
this.emit('error', err);
|
||||
}
|
||||
else {
|
||||
this.emit('end');
|
||||
}
|
||||
});
|
||||
};
|
||||
return result;
|
||||
}
|
||||
exports.createReporter = createReporter;
|
|
@ -1,55 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
var snaps;
|
||||
(function (snaps) {
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const cp = require('child_process');
|
||||
const mksnapshot = path.join(__dirname, `../../node_modules/.bin/${process.platform === 'win32' ? 'mksnapshot.cmd' : 'mksnapshot'}`);
|
||||
const product = require('../../product.json');
|
||||
const arch = (process.argv.join('').match(/--arch=(.*)/) || [])[1];
|
||||
//
|
||||
let loaderFilepath;
|
||||
let startupBlobFilepath;
|
||||
switch (process.platform) {
|
||||
case 'darwin':
|
||||
loaderFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Resources/app/out/vs/loader.js`;
|
||||
startupBlobFilepath = `VSCode-darwin/${product.nameLong}.app/Contents/Frameworks/Electron Framework.framework/Resources/snapshot_blob.bin`;
|
||||
break;
|
||||
case 'win32':
|
||||
case 'linux':
|
||||
loaderFilepath = `VSCode-${process.platform}-${arch}/resources/app/out/vs/loader.js`;
|
||||
startupBlobFilepath = `VSCode-${process.platform}-${arch}/snapshot_blob.bin`;
|
||||
break;
|
||||
default:
|
||||
throw new Error('Unknown platform');
|
||||
}
|
||||
loaderFilepath = path.join(__dirname, '../../../', loaderFilepath);
|
||||
startupBlobFilepath = path.join(__dirname, '../../../', startupBlobFilepath);
|
||||
snapshotLoader(loaderFilepath, startupBlobFilepath);
|
||||
function snapshotLoader(loaderFilepath, startupBlobFilepath) {
|
||||
const inputFile = fs.readFileSync(loaderFilepath);
|
||||
const wrappedInputFile = `
|
||||
var Monaco_Loader_Init;
|
||||
(function() {
|
||||
var doNotInitLoader = true;
|
||||
${inputFile.toString()};
|
||||
Monaco_Loader_Init = function() {
|
||||
AMDLoader.init();
|
||||
CSSLoaderPlugin.init();
|
||||
NLSLoaderPlugin.init();
|
||||
|
||||
return { define, require };
|
||||
}
|
||||
})();
|
||||
`;
|
||||
const wrappedInputFilepath = path.join(os.tmpdir(), 'wrapped-loader.js');
|
||||
console.log(wrappedInputFilepath);
|
||||
fs.writeFileSync(wrappedInputFilepath, wrappedInputFile);
|
||||
cp.execFileSync(mksnapshot, [wrappedInputFilepath, `--startup_blob`, startupBlobFilepath]);
|
||||
}
|
||||
})(snaps || (snaps = {}));
|
|
@ -1,314 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.createESMSourcesAndResources2 = exports.extractEditor = void 0;
|
||||
const ts = require("typescript");
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const tss = require("./treeshaking");
|
||||
const REPO_ROOT = path.join(__dirname, '../../');
|
||||
const SRC_DIR = path.join(REPO_ROOT, 'src');
|
||||
let dirCache = {};
|
||||
function writeFile(filePath, contents) {
|
||||
function ensureDirs(dirPath) {
|
||||
if (dirCache[dirPath]) {
|
||||
return;
|
||||
}
|
||||
dirCache[dirPath] = true;
|
||||
ensureDirs(path.dirname(dirPath));
|
||||
if (fs.existsSync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
fs.mkdirSync(dirPath);
|
||||
}
|
||||
ensureDirs(path.dirname(filePath));
|
||||
fs.writeFileSync(filePath, contents);
|
||||
}
|
||||
function extractEditor(options) {
|
||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.monaco.json')).toString());
|
||||
let compilerOptions;
|
||||
if (tsConfig.extends) {
|
||||
compilerOptions = Object.assign({}, require(path.join(options.sourcesRoot, tsConfig.extends)).compilerOptions, tsConfig.compilerOptions);
|
||||
delete tsConfig.extends;
|
||||
}
|
||||
else {
|
||||
compilerOptions = tsConfig.compilerOptions;
|
||||
}
|
||||
tsConfig.compilerOptions = compilerOptions;
|
||||
compilerOptions.noEmit = false;
|
||||
compilerOptions.noUnusedLocals = false;
|
||||
compilerOptions.preserveConstEnums = false;
|
||||
compilerOptions.declaration = false;
|
||||
compilerOptions.moduleResolution = ts.ModuleResolutionKind.Classic;
|
||||
options.compilerOptions = compilerOptions;
|
||||
console.log(`Running tree shaker with shakeLevel ${tss.toStringShakeLevel(options.shakeLevel)}`);
|
||||
// Take the extra included .d.ts files from `tsconfig.monaco.json`
|
||||
options.typings = tsConfig.include.filter(includedFile => /\.d\.ts$/.test(includedFile));
|
||||
let result = tss.shake(options);
|
||||
for (let fileName in result) {
|
||||
if (result.hasOwnProperty(fileName)) {
|
||||
writeFile(path.join(options.destRoot, fileName), result[fileName]);
|
||||
}
|
||||
}
|
||||
let copied = {};
|
||||
const copyFile = (fileName) => {
|
||||
if (copied[fileName]) {
|
||||
return;
|
||||
}
|
||||
copied[fileName] = true;
|
||||
const srcPath = path.join(options.sourcesRoot, fileName);
|
||||
const dstPath = path.join(options.destRoot, fileName);
|
||||
writeFile(dstPath, fs.readFileSync(srcPath));
|
||||
};
|
||||
const writeOutputFile = (fileName, contents) => {
|
||||
writeFile(path.join(options.destRoot, fileName), contents);
|
||||
};
|
||||
for (let fileName in result) {
|
||||
if (result.hasOwnProperty(fileName)) {
|
||||
const fileContents = result[fileName];
|
||||
const info = ts.preProcessFile(fileContents);
|
||||
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
|
||||
const importedFileName = info.importedFiles[i].fileName;
|
||||
let importedFilePath;
|
||||
if (/^vs\/css!/.test(importedFileName)) {
|
||||
importedFilePath = importedFileName.substr('vs/css!'.length) + '.css';
|
||||
}
|
||||
else {
|
||||
importedFilePath = importedFileName;
|
||||
}
|
||||
if (/(^\.\/)|(^\.\.\/)/.test(importedFilePath)) {
|
||||
importedFilePath = path.join(path.dirname(fileName), importedFilePath);
|
||||
}
|
||||
if (/\.css$/.test(importedFilePath)) {
|
||||
transportCSS(importedFilePath, copyFile, writeOutputFile);
|
||||
}
|
||||
else {
|
||||
if (fs.existsSync(path.join(options.sourcesRoot, importedFilePath + '.js'))) {
|
||||
copyFile(importedFilePath + '.js');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
delete tsConfig.compilerOptions.moduleResolution;
|
||||
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
||||
[
|
||||
'vs/css.build.js',
|
||||
'vs/css.d.ts',
|
||||
'vs/css.js',
|
||||
'vs/loader.js',
|
||||
'vs/nls.build.js',
|
||||
'vs/nls.d.ts',
|
||||
'vs/nls.js',
|
||||
'vs/nls.mock.ts',
|
||||
].forEach(copyFile);
|
||||
}
|
||||
exports.extractEditor = extractEditor;
|
||||
function createESMSourcesAndResources2(options) {
|
||||
const SRC_FOLDER = path.join(REPO_ROOT, options.srcFolder);
|
||||
const OUT_FOLDER = path.join(REPO_ROOT, options.outFolder);
|
||||
const OUT_RESOURCES_FOLDER = path.join(REPO_ROOT, options.outResourcesFolder);
|
||||
const getDestAbsoluteFilePath = (file) => {
|
||||
let dest = options.renames[file.replace(/\\/g, '/')] || file;
|
||||
if (dest === 'tsconfig.json') {
|
||||
return path.join(OUT_FOLDER, `tsconfig.json`);
|
||||
}
|
||||
if (/\.ts$/.test(dest)) {
|
||||
return path.join(OUT_FOLDER, dest);
|
||||
}
|
||||
return path.join(OUT_RESOURCES_FOLDER, dest);
|
||||
};
|
||||
const allFiles = walkDirRecursive(SRC_FOLDER);
|
||||
for (const file of allFiles) {
|
||||
if (options.ignores.indexOf(file.replace(/\\/g, '/')) >= 0) {
|
||||
continue;
|
||||
}
|
||||
if (file === 'tsconfig.json') {
|
||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
|
||||
tsConfig.compilerOptions.module = 'es6';
|
||||
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs').replace(/\\/g, '/');
|
||||
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
|
||||
continue;
|
||||
}
|
||||
if (/\.d\.ts$/.test(file) || /\.css$/.test(file) || /\.js$/.test(file) || /\.ttf$/.test(file)) {
|
||||
// Transport the files directly
|
||||
write(getDestAbsoluteFilePath(file), fs.readFileSync(path.join(SRC_FOLDER, file)));
|
||||
continue;
|
||||
}
|
||||
if (/\.ts$/.test(file)) {
|
||||
// Transform the .ts file
|
||||
let fileContents = fs.readFileSync(path.join(SRC_FOLDER, file)).toString();
|
||||
const info = ts.preProcessFile(fileContents);
|
||||
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
|
||||
const importedFilename = info.importedFiles[i].fileName;
|
||||
const pos = info.importedFiles[i].pos;
|
||||
const end = info.importedFiles[i].end;
|
||||
let importedFilepath;
|
||||
if (/^vs\/css!/.test(importedFilename)) {
|
||||
importedFilepath = importedFilename.substr('vs/css!'.length) + '.css';
|
||||
}
|
||||
else {
|
||||
importedFilepath = importedFilename;
|
||||
}
|
||||
if (/(^\.\/)|(^\.\.\/)/.test(importedFilepath)) {
|
||||
importedFilepath = path.join(path.dirname(file), importedFilepath);
|
||||
}
|
||||
let relativePath;
|
||||
if (importedFilepath === path.dirname(file).replace(/\\/g, '/')) {
|
||||
relativePath = '../' + path.basename(path.dirname(file));
|
||||
}
|
||||
else if (importedFilepath === path.dirname(path.dirname(file)).replace(/\\/g, '/')) {
|
||||
relativePath = '../../' + path.basename(path.dirname(path.dirname(file)));
|
||||
}
|
||||
else {
|
||||
relativePath = path.relative(path.dirname(file), importedFilepath);
|
||||
}
|
||||
relativePath = relativePath.replace(/\\/g, '/');
|
||||
if (!/(^\.\/)|(^\.\.\/)/.test(relativePath)) {
|
||||
relativePath = './' + relativePath;
|
||||
}
|
||||
fileContents = (fileContents.substring(0, pos + 1)
|
||||
+ relativePath
|
||||
+ fileContents.substring(end + 1));
|
||||
}
|
||||
fileContents = fileContents.replace(/import ([a-zA-z0-9]+) = require\(('[^']+')\);/g, function (_, m1, m2) {
|
||||
return `import * as ${m1} from ${m2};`;
|
||||
});
|
||||
write(getDestAbsoluteFilePath(file), fileContents);
|
||||
continue;
|
||||
}
|
||||
console.log(`UNKNOWN FILE: ${file}`);
|
||||
}
|
||||
function walkDirRecursive(dir) {
|
||||
if (dir.charAt(dir.length - 1) !== '/' || dir.charAt(dir.length - 1) !== '\\') {
|
||||
dir += '/';
|
||||
}
|
||||
let result = [];
|
||||
_walkDirRecursive(dir, result, dir.length);
|
||||
return result;
|
||||
}
|
||||
function _walkDirRecursive(dir, result, trimPos) {
|
||||
const files = fs.readdirSync(dir);
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
const file = path.join(dir, files[i]);
|
||||
if (fs.statSync(file).isDirectory()) {
|
||||
_walkDirRecursive(file, result, trimPos);
|
||||
}
|
||||
else {
|
||||
result.push(file.substr(trimPos));
|
||||
}
|
||||
}
|
||||
}
|
||||
function write(absoluteFilePath, contents) {
|
||||
if (/(\.ts$)|(\.js$)/.test(absoluteFilePath)) {
|
||||
contents = toggleComments(contents.toString());
|
||||
}
|
||||
writeFile(absoluteFilePath, contents);
|
||||
function toggleComments(fileContents) {
|
||||
let lines = fileContents.split(/\r\n|\r|\n/);
|
||||
let mode = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
const line = lines[i];
|
||||
if (mode === 0) {
|
||||
if (/\/\/ ESM-comment-begin/.test(line)) {
|
||||
mode = 1;
|
||||
continue;
|
||||
}
|
||||
if (/\/\/ ESM-uncomment-begin/.test(line)) {
|
||||
mode = 2;
|
||||
continue;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (mode === 1) {
|
||||
if (/\/\/ ESM-comment-end/.test(line)) {
|
||||
mode = 0;
|
||||
continue;
|
||||
}
|
||||
lines[i] = '// ' + line;
|
||||
continue;
|
||||
}
|
||||
if (mode === 2) {
|
||||
if (/\/\/ ESM-uncomment-end/.test(line)) {
|
||||
mode = 0;
|
||||
continue;
|
||||
}
|
||||
lines[i] = line.replace(/^(\s*)\/\/ ?/, function (_, indent) {
|
||||
return indent;
|
||||
});
|
||||
}
|
||||
}
|
||||
return lines.join('\n');
|
||||
}
|
||||
}
|
||||
}
|
||||
exports.createESMSourcesAndResources2 = createESMSourcesAndResources2;
|
||||
function transportCSS(module, enqueue, write) {
|
||||
if (!/\.css/.test(module)) {
|
||||
return false;
|
||||
}
|
||||
const filename = path.join(SRC_DIR, module);
|
||||
const fileContents = fs.readFileSync(filename).toString();
|
||||
const inlineResources = 'base64'; // see https://github.com/microsoft/monaco-editor/issues/148
|
||||
const newContents = _rewriteOrInlineUrls(fileContents, inlineResources === 'base64');
|
||||
write(module, newContents);
|
||||
return true;
|
||||
function _rewriteOrInlineUrls(contents, forceBase64) {
|
||||
return _replaceURL(contents, (url) => {
|
||||
const fontMatch = url.match(/^(.*).ttf\?(.*)$/);
|
||||
if (fontMatch) {
|
||||
const relativeFontPath = `${fontMatch[1]}.ttf`; // trim the query parameter
|
||||
const fontPath = path.join(path.dirname(module), relativeFontPath);
|
||||
enqueue(fontPath);
|
||||
return relativeFontPath;
|
||||
}
|
||||
const imagePath = path.join(path.dirname(module), url);
|
||||
const fileContents = fs.readFileSync(path.join(SRC_DIR, imagePath));
|
||||
const MIME = /\.svg$/.test(url) ? 'image/svg+xml' : 'image/png';
|
||||
let DATA = ';base64,' + fileContents.toString('base64');
|
||||
if (!forceBase64 && /\.svg$/.test(url)) {
|
||||
// .svg => url encode as explained at https://codepen.io/tigt/post/optimizing-svgs-in-data-uris
|
||||
let newText = fileContents.toString()
|
||||
.replace(/"/g, '\'')
|
||||
.replace(/</g, '%3C')
|
||||
.replace(/>/g, '%3E')
|
||||
.replace(/&/g, '%26')
|
||||
.replace(/#/g, '%23')
|
||||
.replace(/\s+/g, ' ');
|
||||
let encodedData = ',' + newText;
|
||||
if (encodedData.length < DATA.length) {
|
||||
DATA = encodedData;
|
||||
}
|
||||
}
|
||||
return '"data:' + MIME + DATA + '"';
|
||||
});
|
||||
}
|
||||
function _replaceURL(contents, replacer) {
|
||||
// Use ")" as the terminator as quotes are oftentimes not used at all
|
||||
return contents.replace(/url\(\s*([^\)]+)\s*\)?/g, (_, ...matches) => {
|
||||
let url = matches[0];
|
||||
// Eliminate starting quotes (the initial whitespace is not captured)
|
||||
if (url.charAt(0) === '"' || url.charAt(0) === '\'') {
|
||||
url = url.substring(1);
|
||||
}
|
||||
// The ending whitespace is captured
|
||||
while (url.length > 0 && (url.charAt(url.length - 1) === ' ' || url.charAt(url.length - 1) === '\t')) {
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
// Eliminate ending quotes
|
||||
if (url.charAt(url.length - 1) === '"' || url.charAt(url.length - 1) === '\'') {
|
||||
url = url.substring(0, url.length - 1);
|
||||
}
|
||||
if (!_startsWith(url, 'data:') && !_startsWith(url, 'http://') && !_startsWith(url, 'https://')) {
|
||||
url = replacer(url);
|
||||
}
|
||||
return 'url(' + url + ')';
|
||||
});
|
||||
}
|
||||
function _startsWith(haystack, needle) {
|
||||
return haystack.length >= needle.length && haystack.substr(0, needle.length) === needle;
|
||||
}
|
||||
}
|
|
@ -1,137 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.submitAllStats = exports.createStatsStream = void 0;
|
||||
const es = require("event-stream");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const appInsights = require("applicationinsights");
|
||||
class Entry {
|
||||
constructor(name, totalCount, totalSize) {
|
||||
this.name = name;
|
||||
this.totalCount = totalCount;
|
||||
this.totalSize = totalSize;
|
||||
}
|
||||
toString(pretty) {
|
||||
if (!pretty) {
|
||||
if (this.totalCount === 1) {
|
||||
return `${this.name}: ${this.totalSize} bytes`;
|
||||
}
|
||||
else {
|
||||
return `${this.name}: ${this.totalCount} files with ${this.totalSize} bytes`;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (this.totalCount === 1) {
|
||||
return `Stats for '${ansiColors.grey(this.name)}': ${Math.round(this.totalSize / 1204)}KB`;
|
||||
}
|
||||
else {
|
||||
const count = this.totalCount < 100
|
||||
? ansiColors.green(this.totalCount.toString())
|
||||
: ansiColors.red(this.totalCount.toString());
|
||||
return `Stats for '${ansiColors.grey(this.name)}': ${count} files, ${Math.round(this.totalSize / 1204)}KB`;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
const _entries = new Map();
|
||||
function createStatsStream(group, log) {
|
||||
const entry = new Entry(group, 0, 0);
|
||||
_entries.set(entry.name, entry);
|
||||
return es.through(function (data) {
|
||||
const file = data;
|
||||
if (typeof file.path === 'string') {
|
||||
entry.totalCount += 1;
|
||||
if (Buffer.isBuffer(file.contents)) {
|
||||
entry.totalSize += file.contents.length;
|
||||
}
|
||||
else if (file.stat && typeof file.stat.size === 'number') {
|
||||
entry.totalSize += file.stat.size;
|
||||
}
|
||||
else {
|
||||
// funky file...
|
||||
}
|
||||
}
|
||||
this.emit('data', data);
|
||||
}, function () {
|
||||
if (log) {
|
||||
if (entry.totalCount === 1) {
|
||||
fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${Math.round(entry.totalSize / 1204)}KB`);
|
||||
}
|
||||
else {
|
||||
const count = entry.totalCount < 100
|
||||
? ansiColors.green(entry.totalCount.toString())
|
||||
: ansiColors.red(entry.totalCount.toString());
|
||||
fancyLog(`Stats for '${ansiColors.grey(entry.name)}': ${count} files, ${Math.round(entry.totalSize / 1204)}KB`);
|
||||
}
|
||||
}
|
||||
this.emit('end');
|
||||
});
|
||||
}
|
||||
exports.createStatsStream = createStatsStream;
|
||||
function submitAllStats(productJson, commit) {
|
||||
const sorted = [];
|
||||
// move entries for single files to the front
|
||||
_entries.forEach(value => {
|
||||
if (value.totalCount === 1) {
|
||||
sorted.unshift(value);
|
||||
}
|
||||
else {
|
||||
sorted.push(value);
|
||||
}
|
||||
});
|
||||
// print to console
|
||||
for (const entry of sorted) {
|
||||
console.log(entry.toString(true));
|
||||
}
|
||||
// send data as telementry event when the
|
||||
// product is configured to send telemetry
|
||||
if (!productJson || !productJson.aiConfig || typeof productJson.aiConfig.asimovKey !== 'string') {
|
||||
return Promise.resolve(false);
|
||||
}
|
||||
return new Promise(resolve => {
|
||||
try {
|
||||
const sizes = {};
|
||||
const counts = {};
|
||||
for (const entry of sorted) {
|
||||
sizes[entry.name] = entry.totalSize;
|
||||
counts[entry.name] = entry.totalCount;
|
||||
}
|
||||
appInsights.setup(productJson.aiConfig.asimovKey)
|
||||
.setAutoCollectConsole(false)
|
||||
.setAutoCollectExceptions(false)
|
||||
.setAutoCollectPerformance(false)
|
||||
.setAutoCollectRequests(false)
|
||||
.setAutoCollectDependencies(false)
|
||||
.setAutoDependencyCorrelation(false)
|
||||
.start();
|
||||
appInsights.defaultClient.config.endpointUrl = 'https://vortex.data.microsoft.com/collect/v1';
|
||||
/* __GDPR__
|
||||
"monacoworkbench/packagemetrics" : {
|
||||
"commit" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"size" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" },
|
||||
"count" : {"classification": "SystemMetaData", "purpose": "PerformanceAndHealth" }
|
||||
}
|
||||
*/
|
||||
appInsights.defaultClient.trackEvent({
|
||||
name: 'monacoworkbench/packagemetrics',
|
||||
properties: { commit, size: JSON.stringify(sizes), count: JSON.stringify(counts) }
|
||||
});
|
||||
appInsights.defaultClient.flush({
|
||||
callback: () => {
|
||||
appInsights.dispose();
|
||||
resolve(true);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (err) {
|
||||
console.error('ERROR sending build stats as telemetry event!');
|
||||
console.error(err);
|
||||
resolve(false);
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.submitAllStats = submitAllStats;
|
|
@ -1,97 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.define = exports.parallel = exports.series = void 0;
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
function _isPromise(p) {
|
||||
if (typeof p.then === 'function') {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function _renderTime(time) {
|
||||
return `${Math.round(time)} ms`;
|
||||
}
|
||||
async function _execute(task) {
|
||||
const name = task.taskName || task.displayName || `<anonymous>`;
|
||||
if (!task._tasks) {
|
||||
fancyLog('Starting', ansiColors.cyan(name), '...');
|
||||
}
|
||||
const startTime = process.hrtime();
|
||||
await _doExecute(task);
|
||||
const elapsedArr = process.hrtime(startTime);
|
||||
const elapsedNanoseconds = (elapsedArr[0] * 1e9 + elapsedArr[1]);
|
||||
if (!task._tasks) {
|
||||
fancyLog(`Finished`, ansiColors.cyan(name), 'after', ansiColors.magenta(_renderTime(elapsedNanoseconds / 1e6)));
|
||||
}
|
||||
}
|
||||
async function _doExecute(task) {
|
||||
// Always invoke as if it were a callback task
|
||||
return new Promise((resolve, reject) => {
|
||||
if (task.length === 1) {
|
||||
// this is a callback task
|
||||
task((err) => {
|
||||
if (err) {
|
||||
return reject(err);
|
||||
}
|
||||
resolve();
|
||||
});
|
||||
return;
|
||||
}
|
||||
const taskResult = task();
|
||||
if (typeof taskResult === 'undefined') {
|
||||
// this is a sync task
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
if (_isPromise(taskResult)) {
|
||||
// this is a promise returning task
|
||||
taskResult.then(resolve, reject);
|
||||
return;
|
||||
}
|
||||
// this is a stream returning task
|
||||
taskResult.on('end', _ => resolve());
|
||||
taskResult.on('error', err => reject(err));
|
||||
});
|
||||
}
|
||||
function series(...tasks) {
|
||||
const result = async () => {
|
||||
for (let i = 0; i < tasks.length; i++) {
|
||||
await _execute(tasks[i]);
|
||||
}
|
||||
};
|
||||
result._tasks = tasks;
|
||||
return result;
|
||||
}
|
||||
exports.series = series;
|
||||
function parallel(...tasks) {
|
||||
const result = async () => {
|
||||
await Promise.all(tasks.map(t => _execute(t)));
|
||||
};
|
||||
result._tasks = tasks;
|
||||
return result;
|
||||
}
|
||||
exports.parallel = parallel;
|
||||
function define(name, task) {
|
||||
if (task._tasks) {
|
||||
// This is a composite task
|
||||
const lastTask = task._tasks[task._tasks.length - 1];
|
||||
if (lastTask._tasks || lastTask.taskName) {
|
||||
// This is a composite task without a real task function
|
||||
// => generate a fake task function
|
||||
return define(name, series(task, () => Promise.resolve()));
|
||||
}
|
||||
lastTask.taskName = name;
|
||||
task.displayName = name;
|
||||
return task;
|
||||
}
|
||||
// This is a simple task
|
||||
task.taskName = name;
|
||||
task.displayName = name;
|
||||
return task;
|
||||
}
|
||||
exports.define = define;
|
|
@ -1,40 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
const assert = require("assert");
|
||||
const i18n = require("../i18n");
|
||||
suite('XLF Parser Tests', () => {
|
||||
const sampleXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &</source></trans-unit></body></file></xliff>';
|
||||
const sampleTranslatedXlf = '<?xml version="1.0" encoding="utf-8"?><xliff version="1.2" xmlns="urn:oasis:names:tc:xliff:document:1.2"><file original="vs/base/common/keybinding" source-language="en" target-language="ru" datatype="plaintext"><body><trans-unit id="key1"><source xml:lang="en">Key #1</source><target>Кнопка #1</target></trans-unit><trans-unit id="key2"><source xml:lang="en">Key #2 &</source><target>Кнопка #2 &</target></trans-unit></body></file></xliff>';
|
||||
const originalFilePath = 'vs/base/common/keybinding';
|
||||
const keys = ['key1', 'key2'];
|
||||
const messages = ['Key #1', 'Key #2 &'];
|
||||
const translatedMessages = { key1: 'Кнопка #1', key2: 'Кнопка #2 &' };
|
||||
test('Keys & messages to XLF conversion', () => {
|
||||
const xlf = new i18n.XLF('vscode-workbench');
|
||||
xlf.addFile(originalFilePath, keys, messages);
|
||||
const xlfString = xlf.toString();
|
||||
assert.strictEqual(xlfString.replace(/\s{2,}/g, ''), sampleXlf);
|
||||
});
|
||||
test('XLF to keys & messages conversion', () => {
|
||||
i18n.XLF.parse(sampleTranslatedXlf).then(function (resolvedFiles) {
|
||||
assert.deepEqual(resolvedFiles[0].messages, translatedMessages);
|
||||
assert.strictEqual(resolvedFiles[0].originalFilePath, originalFilePath);
|
||||
});
|
||||
});
|
||||
test('JSON file source path to Transifex resource match', () => {
|
||||
const editorProject = 'vscode-editor', workbenchProject = 'vscode-workbench';
|
||||
const platform = { name: 'vs/platform', project: editorProject }, editorContrib = { name: 'vs/editor/contrib', project: editorProject }, editor = { name: 'vs/editor', project: editorProject }, base = { name: 'vs/base', project: editorProject }, code = { name: 'vs/code', project: workbenchProject }, workbenchParts = { name: 'vs/workbench/contrib/html', project: workbenchProject }, workbenchServices = { name: 'vs/workbench/services/textfile', project: workbenchProject }, workbench = { name: 'vs/workbench', project: workbenchProject };
|
||||
assert.deepEqual(i18n.getResource('vs/platform/actions/browser/menusExtensionPoint'), platform);
|
||||
assert.deepEqual(i18n.getResource('vs/editor/contrib/clipboard/browser/clipboard'), editorContrib);
|
||||
assert.deepEqual(i18n.getResource('vs/editor/common/modes/modesRegistry'), editor);
|
||||
assert.deepEqual(i18n.getResource('vs/base/common/errorMessage'), base);
|
||||
assert.deepEqual(i18n.getResource('vs/code/electron-main/window'), code);
|
||||
assert.deepEqual(i18n.getResource('vs/workbench/contrib/html/browser/webview'), workbenchParts);
|
||||
assert.deepEqual(i18n.getResource('vs/workbench/services/textfile/node/testFileService'), workbenchServices);
|
||||
assert.deepEqual(i18n.getResource('vs/workbench/browser/parts/panel/panelActions'), workbench);
|
||||
});
|
||||
});
|
|
@ -1,779 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.shake = exports.toStringShakeLevel = exports.ShakeLevel = void 0;
|
||||
const fs = require("fs");
|
||||
const path = require("path");
|
||||
const ts = require("typescript");
|
||||
const TYPESCRIPT_LIB_FOLDER = path.dirname(require.resolve('typescript/lib/lib.d.ts'));
|
||||
var ShakeLevel;
|
||||
(function (ShakeLevel) {
|
||||
ShakeLevel[ShakeLevel["Files"] = 0] = "Files";
|
||||
ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile";
|
||||
ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers";
|
||||
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
|
||||
function toStringShakeLevel(shakeLevel) {
|
||||
switch (shakeLevel) {
|
||||
case 0 /* Files */:
|
||||
return 'Files (0)';
|
||||
case 1 /* InnerFile */:
|
||||
return 'InnerFile (1)';
|
||||
case 2 /* ClassMembers */:
|
||||
return 'ClassMembers (2)';
|
||||
}
|
||||
}
|
||||
exports.toStringShakeLevel = toStringShakeLevel;
|
||||
function printDiagnostics(options, diagnostics) {
|
||||
for (const diag of diagnostics) {
|
||||
let result = '';
|
||||
if (diag.file) {
|
||||
result += `${path.join(options.sourcesRoot, diag.file.fileName)}`;
|
||||
}
|
||||
if (diag.file && diag.start) {
|
||||
let location = diag.file.getLineAndCharacterOfPosition(diag.start);
|
||||
result += `:${location.line + 1}:${location.character}`;
|
||||
}
|
||||
result += ` - ` + JSON.stringify(diag.messageText);
|
||||
console.log(result);
|
||||
}
|
||||
}
|
||||
function shake(options) {
|
||||
const languageService = createTypeScriptLanguageService(options);
|
||||
const program = languageService.getProgram();
|
||||
const globalDiagnostics = program.getGlobalDiagnostics();
|
||||
if (globalDiagnostics.length > 0) {
|
||||
printDiagnostics(options, globalDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
const syntacticDiagnostics = program.getSyntacticDiagnostics();
|
||||
if (syntacticDiagnostics.length > 0) {
|
||||
printDiagnostics(options, syntacticDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
const semanticDiagnostics = program.getSemanticDiagnostics();
|
||||
if (semanticDiagnostics.length > 0) {
|
||||
printDiagnostics(options, semanticDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
markNodes(languageService, options);
|
||||
return generateResult(languageService, options.shakeLevel);
|
||||
}
|
||||
exports.shake = shake;
|
||||
//#region Discovery, LanguageService & Setup
|
||||
function createTypeScriptLanguageService(options) {
|
||||
// Discover referenced files
|
||||
const FILES = discoverAndReadFiles(options);
|
||||
// Add fake usage files
|
||||
options.inlineEntryPoints.forEach((inlineEntryPoint, index) => {
|
||||
FILES[`inlineEntryPoint.${index}.ts`] = inlineEntryPoint;
|
||||
});
|
||||
// Add additional typings
|
||||
options.typings.forEach((typing) => {
|
||||
const filePath = path.join(options.sourcesRoot, typing);
|
||||
FILES[typing] = fs.readFileSync(filePath).toString();
|
||||
});
|
||||
// Resolve libs
|
||||
const RESOLVED_LIBS = processLibFiles(options);
|
||||
const compilerOptions = ts.convertCompilerOptionsFromJson(options.compilerOptions, options.sourcesRoot).options;
|
||||
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, compilerOptions);
|
||||
return ts.createLanguageService(host);
|
||||
}
|
||||
/**
|
||||
* Read imports and follow them until all files have been handled
|
||||
*/
|
||||
function discoverAndReadFiles(options) {
|
||||
const FILES = {};
|
||||
const in_queue = Object.create(null);
|
||||
const queue = [];
|
||||
const enqueue = (moduleId) => {
|
||||
if (in_queue[moduleId]) {
|
||||
return;
|
||||
}
|
||||
in_queue[moduleId] = true;
|
||||
queue.push(moduleId);
|
||||
};
|
||||
options.entryPoints.forEach((entryPoint) => enqueue(entryPoint));
|
||||
while (queue.length > 0) {
|
||||
const moduleId = queue.shift();
|
||||
const dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts');
|
||||
if (fs.existsSync(dts_filename)) {
|
||||
const dts_filecontents = fs.readFileSync(dts_filename).toString();
|
||||
FILES[`${moduleId}.d.ts`] = dts_filecontents;
|
||||
continue;
|
||||
}
|
||||
const js_filename = path.join(options.sourcesRoot, moduleId + '.js');
|
||||
if (fs.existsSync(js_filename)) {
|
||||
// This is an import for a .js file, so ignore it...
|
||||
continue;
|
||||
}
|
||||
let ts_filename;
|
||||
if (options.redirects[moduleId]) {
|
||||
ts_filename = path.join(options.sourcesRoot, options.redirects[moduleId] + '.ts');
|
||||
}
|
||||
else {
|
||||
ts_filename = path.join(options.sourcesRoot, moduleId + '.ts');
|
||||
}
|
||||
const ts_filecontents = fs.readFileSync(ts_filename).toString();
|
||||
const info = ts.preProcessFile(ts_filecontents);
|
||||
for (let i = info.importedFiles.length - 1; i >= 0; i--) {
|
||||
const importedFileName = info.importedFiles[i].fileName;
|
||||
if (options.importIgnorePattern.test(importedFileName)) {
|
||||
// Ignore vs/css! imports
|
||||
continue;
|
||||
}
|
||||
let importedModuleId = importedFileName;
|
||||
if (/(^\.\/)|(^\.\.\/)/.test(importedModuleId)) {
|
||||
importedModuleId = path.join(path.dirname(moduleId), importedModuleId);
|
||||
}
|
||||
enqueue(importedModuleId);
|
||||
}
|
||||
FILES[`${moduleId}.ts`] = ts_filecontents;
|
||||
}
|
||||
return FILES;
|
||||
}
|
||||
/**
|
||||
* Read lib files and follow lib references
|
||||
*/
|
||||
function processLibFiles(options) {
|
||||
const stack = [...options.compilerOptions.lib];
|
||||
const result = {};
|
||||
while (stack.length > 0) {
|
||||
const filename = `lib.${stack.shift().toLowerCase()}.d.ts`;
|
||||
const key = `defaultLib:${filename}`;
|
||||
if (!result[key]) {
|
||||
// add this file
|
||||
const filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename);
|
||||
const sourceText = fs.readFileSync(filepath).toString();
|
||||
result[key] = sourceText;
|
||||
// precess dependencies and "recurse"
|
||||
const info = ts.preProcessFile(sourceText);
|
||||
for (let ref of info.libReferenceDirectives) {
|
||||
stack.push(ref.fileName);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* A TypeScript language service host
|
||||
*/
|
||||
class TypeScriptLanguageServiceHost {
|
||||
constructor(libs, files, compilerOptions) {
|
||||
this._libs = libs;
|
||||
this._files = files;
|
||||
this._compilerOptions = compilerOptions;
|
||||
}
|
||||
// --- language service host ---------------
|
||||
getCompilationSettings() {
|
||||
return this._compilerOptions;
|
||||
}
|
||||
getScriptFileNames() {
|
||||
return ([]
|
||||
.concat(Object.keys(this._libs))
|
||||
.concat(Object.keys(this._files)));
|
||||
}
|
||||
getScriptVersion(_fileName) {
|
||||
return '1';
|
||||
}
|
||||
getProjectVersion() {
|
||||
return '1';
|
||||
}
|
||||
getScriptSnapshot(fileName) {
|
||||
if (this._files.hasOwnProperty(fileName)) {
|
||||
return ts.ScriptSnapshot.fromString(this._files[fileName]);
|
||||
}
|
||||
else if (this._libs.hasOwnProperty(fileName)) {
|
||||
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
|
||||
}
|
||||
else {
|
||||
return ts.ScriptSnapshot.fromString('');
|
||||
}
|
||||
}
|
||||
getScriptKind(_fileName) {
|
||||
return ts.ScriptKind.TS;
|
||||
}
|
||||
getCurrentDirectory() {
|
||||
return '';
|
||||
}
|
||||
getDefaultLibFileName(_options) {
|
||||
return 'defaultLib:lib.d.ts';
|
||||
}
|
||||
isDefaultLibFileName(fileName) {
|
||||
return fileName === this.getDefaultLibFileName(this._compilerOptions);
|
||||
}
|
||||
}
|
||||
//#endregion
|
||||
//#region Tree Shaking
|
||||
var NodeColor;
|
||||
(function (NodeColor) {
|
||||
NodeColor[NodeColor["White"] = 0] = "White";
|
||||
NodeColor[NodeColor["Gray"] = 1] = "Gray";
|
||||
NodeColor[NodeColor["Black"] = 2] = "Black";
|
||||
})(NodeColor || (NodeColor = {}));
|
||||
function getColor(node) {
|
||||
return node.$$$color || 0 /* White */;
|
||||
}
|
||||
function setColor(node, color) {
|
||||
node.$$$color = color;
|
||||
}
|
||||
function nodeOrParentIsBlack(node) {
|
||||
while (node) {
|
||||
const color = getColor(node);
|
||||
if (color === 2 /* Black */) {
|
||||
return true;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function nodeOrChildIsBlack(node) {
|
||||
if (getColor(node) === 2 /* Black */) {
|
||||
return true;
|
||||
}
|
||||
for (const child of node.getChildren()) {
|
||||
if (nodeOrChildIsBlack(child)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function markNodes(languageService, options) {
|
||||
const program = languageService.getProgram();
|
||||
if (!program) {
|
||||
throw new Error('Could not get program from language service');
|
||||
}
|
||||
if (options.shakeLevel === 0 /* Files */) {
|
||||
// Mark all source files Black
|
||||
program.getSourceFiles().forEach((sourceFile) => {
|
||||
setColor(sourceFile, 2 /* Black */);
|
||||
});
|
||||
return;
|
||||
}
|
||||
const black_queue = [];
|
||||
const gray_queue = [];
|
||||
const export_import_queue = [];
|
||||
const sourceFilesLoaded = {};
|
||||
function enqueueTopLevelModuleStatements(sourceFile) {
|
||||
sourceFile.forEachChild((node) => {
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
if (!node.importClause && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
setColor(node, 2 /* Black */);
|
||||
enqueueImport(node, node.moduleSpecifier.text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ts.isExportDeclaration(node)) {
|
||||
if (!node.exportClause && node.moduleSpecifier && ts.isStringLiteral(node.moduleSpecifier)) {
|
||||
// export * from "foo";
|
||||
setColor(node, 2 /* Black */);
|
||||
enqueueImport(node, node.moduleSpecifier.text);
|
||||
}
|
||||
if (node.exportClause && ts.isNamedExports(node.exportClause)) {
|
||||
for (const exportSpecifier of node.exportClause.elements) {
|
||||
export_import_queue.push(exportSpecifier);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (ts.isExpressionStatement(node)
|
||||
|| ts.isIfStatement(node)
|
||||
|| ts.isIterationStatement(node, true)
|
||||
|| ts.isExportAssignment(node)) {
|
||||
enqueue_black(node);
|
||||
}
|
||||
if (ts.isImportEqualsDeclaration(node)) {
|
||||
if (/export/.test(node.getFullText(sourceFile))) {
|
||||
// e.g. "export import Severity = BaseSeverity;"
|
||||
enqueue_black(node);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function enqueue_gray(node) {
|
||||
if (nodeOrParentIsBlack(node) || getColor(node) === 1 /* Gray */) {
|
||||
return;
|
||||
}
|
||||
setColor(node, 1 /* Gray */);
|
||||
gray_queue.push(node);
|
||||
}
|
||||
function enqueue_black(node) {
|
||||
const previousColor = getColor(node);
|
||||
if (previousColor === 2 /* Black */) {
|
||||
return;
|
||||
}
|
||||
if (previousColor === 1 /* Gray */) {
|
||||
// remove from gray queue
|
||||
gray_queue.splice(gray_queue.indexOf(node), 1);
|
||||
setColor(node, 0 /* White */);
|
||||
// add to black queue
|
||||
enqueue_black(node);
|
||||
// // move from one queue to the other
|
||||
// black_queue.push(node);
|
||||
// setColor(node, NodeColor.Black);
|
||||
return;
|
||||
}
|
||||
if (nodeOrParentIsBlack(node)) {
|
||||
return;
|
||||
}
|
||||
const fileName = node.getSourceFile().fileName;
|
||||
if (/^defaultLib:/.test(fileName) || /\.d\.ts$/.test(fileName)) {
|
||||
setColor(node, 2 /* Black */);
|
||||
return;
|
||||
}
|
||||
const sourceFile = node.getSourceFile();
|
||||
if (!sourceFilesLoaded[sourceFile.fileName]) {
|
||||
sourceFilesLoaded[sourceFile.fileName] = true;
|
||||
enqueueTopLevelModuleStatements(sourceFile);
|
||||
}
|
||||
if (ts.isSourceFile(node)) {
|
||||
return;
|
||||
}
|
||||
setColor(node, 2 /* Black */);
|
||||
black_queue.push(node);
|
||||
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isMethodDeclaration(node) || ts.isMethodSignature(node) || ts.isPropertySignature(node) || ts.isPropertyDeclaration(node) || ts.isGetAccessor(node) || ts.isSetAccessor(node))) {
|
||||
const references = languageService.getReferencesAtPosition(node.getSourceFile().fileName, node.name.pos + node.name.getLeadingTriviaWidth());
|
||||
if (references) {
|
||||
for (let i = 0, len = references.length; i < len; i++) {
|
||||
const reference = references[i];
|
||||
const referenceSourceFile = program.getSourceFile(reference.fileName);
|
||||
if (!referenceSourceFile) {
|
||||
continue;
|
||||
}
|
||||
const referenceNode = getTokenAtPosition(referenceSourceFile, reference.textSpan.start, false, false);
|
||||
if (ts.isMethodDeclaration(referenceNode.parent)
|
||||
|| ts.isPropertyDeclaration(referenceNode.parent)
|
||||
|| ts.isGetAccessor(referenceNode.parent)
|
||||
|| ts.isSetAccessor(referenceNode.parent)) {
|
||||
enqueue_gray(referenceNode.parent);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function enqueueFile(filename) {
|
||||
const sourceFile = program.getSourceFile(filename);
|
||||
if (!sourceFile) {
|
||||
console.warn(`Cannot find source file ${filename}`);
|
||||
return;
|
||||
}
|
||||
enqueue_black(sourceFile);
|
||||
}
|
||||
function enqueueImport(node, importText) {
|
||||
if (options.importIgnorePattern.test(importText)) {
|
||||
// this import should be ignored
|
||||
return;
|
||||
}
|
||||
const nodeSourceFile = node.getSourceFile();
|
||||
let fullPath;
|
||||
if (/(^\.\/)|(^\.\.\/)/.test(importText)) {
|
||||
fullPath = path.join(path.dirname(nodeSourceFile.fileName), importText) + '.ts';
|
||||
}
|
||||
else {
|
||||
fullPath = importText + '.ts';
|
||||
}
|
||||
enqueueFile(fullPath);
|
||||
}
|
||||
options.entryPoints.forEach(moduleId => enqueueFile(moduleId + '.ts'));
|
||||
// Add fake usage files
|
||||
options.inlineEntryPoints.forEach((_, index) => enqueueFile(`inlineEntryPoint.${index}.ts`));
|
||||
let step = 0;
|
||||
const checker = program.getTypeChecker();
|
||||
while (black_queue.length > 0 || gray_queue.length > 0) {
|
||||
++step;
|
||||
let node;
|
||||
if (step % 100 === 0) {
|
||||
console.log(`Treeshaking - ${Math.floor(100 * step / (step + black_queue.length + gray_queue.length))}% - ${step}/${step + black_queue.length + gray_queue.length} (${black_queue.length}, ${gray_queue.length})`);
|
||||
}
|
||||
if (black_queue.length === 0) {
|
||||
for (let i = 0; i < gray_queue.length; i++) {
|
||||
const node = gray_queue[i];
|
||||
const nodeParent = node.parent;
|
||||
if ((ts.isClassDeclaration(nodeParent) || ts.isInterfaceDeclaration(nodeParent)) && nodeOrChildIsBlack(nodeParent)) {
|
||||
gray_queue.splice(i, 1);
|
||||
black_queue.push(node);
|
||||
setColor(node, 2 /* Black */);
|
||||
i--;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (black_queue.length > 0) {
|
||||
node = black_queue.shift();
|
||||
}
|
||||
else {
|
||||
// only gray nodes remaining...
|
||||
break;
|
||||
}
|
||||
const nodeSourceFile = node.getSourceFile();
|
||||
const loop = (node) => {
|
||||
const [symbol, symbolImportNode] = getRealNodeSymbol(checker, node);
|
||||
if (symbolImportNode) {
|
||||
setColor(symbolImportNode, 2 /* Black */);
|
||||
}
|
||||
if (symbol && !nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol)) {
|
||||
for (let i = 0, len = symbol.declarations.length; i < len; i++) {
|
||||
const declaration = symbol.declarations[i];
|
||||
if (ts.isSourceFile(declaration)) {
|
||||
// Do not enqueue full source files
|
||||
// (they can be the declaration of a module import)
|
||||
continue;
|
||||
}
|
||||
if (options.shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(declaration) || ts.isInterfaceDeclaration(declaration)) && !isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration)) {
|
||||
enqueue_black(declaration.name);
|
||||
for (let j = 0; j < declaration.members.length; j++) {
|
||||
const member = declaration.members[j];
|
||||
const memberName = member.name ? member.name.getText() : null;
|
||||
if (ts.isConstructorDeclaration(member)
|
||||
|| ts.isConstructSignatureDeclaration(member)
|
||||
|| ts.isIndexSignatureDeclaration(member)
|
||||
|| ts.isCallSignatureDeclaration(member)
|
||||
|| memberName === '[Symbol.iterator]'
|
||||
|| memberName === '[Symbol.toStringTag]'
|
||||
|| memberName === 'toJSON'
|
||||
|| memberName === 'toString'
|
||||
|| memberName === 'dispose' // TODO: keeping all `dispose` methods
|
||||
|| /^_(.*)Brand$/.test(memberName || '') // TODO: keeping all members ending with `Brand`...
|
||||
) {
|
||||
enqueue_black(member);
|
||||
}
|
||||
}
|
||||
// queue the heritage clauses
|
||||
if (declaration.heritageClauses) {
|
||||
for (let heritageClause of declaration.heritageClauses) {
|
||||
enqueue_black(heritageClause);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
enqueue_black(declaration);
|
||||
}
|
||||
}
|
||||
}
|
||||
node.forEachChild(loop);
|
||||
};
|
||||
node.forEachChild(loop);
|
||||
}
|
||||
while (export_import_queue.length > 0) {
|
||||
const node = export_import_queue.shift();
|
||||
if (nodeOrParentIsBlack(node)) {
|
||||
continue;
|
||||
}
|
||||
const symbol = node.symbol;
|
||||
if (!symbol) {
|
||||
continue;
|
||||
}
|
||||
const aliased = checker.getAliasedSymbol(symbol);
|
||||
if (aliased.declarations && aliased.declarations.length > 0) {
|
||||
if (nodeOrParentIsBlack(aliased.declarations[0]) || nodeOrChildIsBlack(aliased.declarations[0])) {
|
||||
setColor(node, 2 /* Black */);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function nodeIsInItsOwnDeclaration(nodeSourceFile, node, symbol) {
|
||||
for (let i = 0, len = symbol.declarations.length; i < len; i++) {
|
||||
const declaration = symbol.declarations[i];
|
||||
const declarationSourceFile = declaration.getSourceFile();
|
||||
if (nodeSourceFile === declarationSourceFile) {
|
||||
if (declaration.pos <= node.pos && node.end <= declaration.end) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function generateResult(languageService, shakeLevel) {
|
||||
const program = languageService.getProgram();
|
||||
if (!program) {
|
||||
throw new Error('Could not get program from language service');
|
||||
}
|
||||
let result = {};
|
||||
const writeFile = (filePath, contents) => {
|
||||
result[filePath] = contents;
|
||||
};
|
||||
program.getSourceFiles().forEach((sourceFile) => {
|
||||
const fileName = sourceFile.fileName;
|
||||
if (/^defaultLib:/.test(fileName)) {
|
||||
return;
|
||||
}
|
||||
const destination = fileName;
|
||||
if (/\.d\.ts$/.test(fileName)) {
|
||||
if (nodeOrChildIsBlack(sourceFile)) {
|
||||
writeFile(destination, sourceFile.text);
|
||||
}
|
||||
return;
|
||||
}
|
||||
let text = sourceFile.text;
|
||||
let result = '';
|
||||
function keep(node) {
|
||||
result += text.substring(node.pos, node.end);
|
||||
}
|
||||
function write(data) {
|
||||
result += data;
|
||||
}
|
||||
function writeMarkedNodes(node) {
|
||||
if (getColor(node) === 2 /* Black */) {
|
||||
return keep(node);
|
||||
}
|
||||
// Always keep certain top-level statements
|
||||
if (ts.isSourceFile(node.parent)) {
|
||||
if (ts.isExpressionStatement(node) && ts.isStringLiteral(node.expression) && node.expression.text === 'use strict') {
|
||||
return keep(node);
|
||||
}
|
||||
if (ts.isVariableStatement(node) && nodeOrChildIsBlack(node)) {
|
||||
return keep(node);
|
||||
}
|
||||
}
|
||||
// Keep the entire import in import * as X cases
|
||||
if (ts.isImportDeclaration(node)) {
|
||||
if (node.importClause && node.importClause.namedBindings) {
|
||||
if (ts.isNamespaceImport(node.importClause.namedBindings)) {
|
||||
if (getColor(node.importClause.namedBindings) === 2 /* Black */) {
|
||||
return keep(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let survivingImports = [];
|
||||
for (const importNode of node.importClause.namedBindings.elements) {
|
||||
if (getColor(importNode) === 2 /* Black */) {
|
||||
survivingImports.push(importNode.getFullText(sourceFile));
|
||||
}
|
||||
}
|
||||
const leadingTriviaWidth = node.getLeadingTriviaWidth();
|
||||
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
|
||||
if (survivingImports.length > 0) {
|
||||
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
|
||||
return write(`${leadingTrivia}import ${node.importClause.name.text}, {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||
}
|
||||
return write(`${leadingTrivia}import {${survivingImports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||
}
|
||||
else {
|
||||
if (node.importClause && node.importClause.name && getColor(node.importClause) === 2 /* Black */) {
|
||||
return write(`${leadingTrivia}import ${node.importClause.name.text} from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.importClause && getColor(node.importClause) === 2 /* Black */) {
|
||||
return keep(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ts.isExportDeclaration(node)) {
|
||||
if (node.exportClause && node.moduleSpecifier && ts.isNamedExports(node.exportClause)) {
|
||||
let survivingExports = [];
|
||||
for (const exportSpecifier of node.exportClause.elements) {
|
||||
if (getColor(exportSpecifier) === 2 /* Black */) {
|
||||
survivingExports.push(exportSpecifier.getFullText(sourceFile));
|
||||
}
|
||||
}
|
||||
const leadingTriviaWidth = node.getLeadingTriviaWidth();
|
||||
const leadingTrivia = sourceFile.text.substr(node.pos, leadingTriviaWidth);
|
||||
if (survivingExports.length > 0) {
|
||||
return write(`${leadingTrivia}export {${survivingExports.join(',')} } from${node.moduleSpecifier.getFullText(sourceFile)};`);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (shakeLevel === 2 /* ClassMembers */ && (ts.isClassDeclaration(node) || ts.isInterfaceDeclaration(node)) && nodeOrChildIsBlack(node)) {
|
||||
let toWrite = node.getFullText();
|
||||
for (let i = node.members.length - 1; i >= 0; i--) {
|
||||
const member = node.members[i];
|
||||
if (getColor(member) === 2 /* Black */ || !member.name) {
|
||||
// keep method
|
||||
continue;
|
||||
}
|
||||
let pos = member.pos - node.pos;
|
||||
let end = member.end - node.pos;
|
||||
toWrite = toWrite.substring(0, pos) + toWrite.substring(end);
|
||||
}
|
||||
return write(toWrite);
|
||||
}
|
||||
if (ts.isFunctionDeclaration(node)) {
|
||||
// Do not go inside functions if they haven't been marked
|
||||
return;
|
||||
}
|
||||
node.forEachChild(writeMarkedNodes);
|
||||
}
|
||||
if (getColor(sourceFile) !== 2 /* Black */) {
|
||||
if (!nodeOrChildIsBlack(sourceFile)) {
|
||||
// none of the elements are reachable => don't write this file at all!
|
||||
return;
|
||||
}
|
||||
sourceFile.forEachChild(writeMarkedNodes);
|
||||
result += sourceFile.endOfFileToken.getFullText(sourceFile);
|
||||
}
|
||||
else {
|
||||
result = text;
|
||||
}
|
||||
writeFile(destination, result);
|
||||
});
|
||||
return result;
|
||||
}
|
||||
//#endregion
|
||||
//#region Utils
|
||||
function isLocalCodeExtendingOrInheritingFromDefaultLibSymbol(program, checker, declaration) {
|
||||
if (!program.isSourceFileDefaultLibrary(declaration.getSourceFile()) && declaration.heritageClauses) {
|
||||
for (const heritageClause of declaration.heritageClauses) {
|
||||
for (const type of heritageClause.types) {
|
||||
const symbol = findSymbolFromHeritageType(checker, type);
|
||||
if (symbol) {
|
||||
const decl = symbol.valueDeclaration || (symbol.declarations && symbol.declarations[0]);
|
||||
if (decl && program.isSourceFileDefaultLibrary(decl.getSourceFile())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function findSymbolFromHeritageType(checker, type) {
|
||||
if (ts.isExpressionWithTypeArguments(type)) {
|
||||
return findSymbolFromHeritageType(checker, type.expression);
|
||||
}
|
||||
if (ts.isIdentifier(type)) {
|
||||
return getRealNodeSymbol(checker, type)[0];
|
||||
}
|
||||
if (ts.isPropertyAccessExpression(type)) {
|
||||
return findSymbolFromHeritageType(checker, type.name);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
/**
|
||||
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
|
||||
*/
|
||||
function getRealNodeSymbol(checker, node) {
|
||||
const getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType;
|
||||
const getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement;
|
||||
const getNameFromPropertyName = ts.getNameFromPropertyName;
|
||||
// Go to the original declaration for cases:
|
||||
//
|
||||
// (1) when the aliased symbol was declared in the location(parent).
|
||||
// (2) when the aliased symbol is originating from an import.
|
||||
//
|
||||
function shouldSkipAlias(node, declaration) {
|
||||
if (!ts.isShorthandPropertyAssignment(node) && node.kind !== ts.SyntaxKind.Identifier) {
|
||||
return false;
|
||||
}
|
||||
if (node.parent === declaration) {
|
||||
return true;
|
||||
}
|
||||
switch (declaration.kind) {
|
||||
case ts.SyntaxKind.ImportClause:
|
||||
case ts.SyntaxKind.ImportEqualsDeclaration:
|
||||
return true;
|
||||
case ts.SyntaxKind.ImportSpecifier:
|
||||
return declaration.parent.kind === ts.SyntaxKind.NamedImports;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!ts.isShorthandPropertyAssignment(node)) {
|
||||
if (node.getChildCount() !== 0) {
|
||||
return [null, null];
|
||||
}
|
||||
}
|
||||
const { parent } = node;
|
||||
let symbol = (ts.isShorthandPropertyAssignment(node)
|
||||
? checker.getShorthandAssignmentValueSymbol(node)
|
||||
: checker.getSymbolAtLocation(node));
|
||||
let importNode = null;
|
||||
// If this is an alias, and the request came at the declaration location
|
||||
// get the aliased symbol instead. This allows for goto def on an import e.g.
|
||||
// import {A, B} from "mod";
|
||||
// to jump to the implementation directly.
|
||||
if (symbol && symbol.flags & ts.SymbolFlags.Alias && shouldSkipAlias(node, symbol.declarations[0])) {
|
||||
const aliased = checker.getAliasedSymbol(symbol);
|
||||
if (aliased.declarations) {
|
||||
// We should mark the import as visited
|
||||
importNode = symbol.declarations[0];
|
||||
symbol = aliased;
|
||||
}
|
||||
}
|
||||
if (symbol) {
|
||||
// Because name in short-hand property assignment has two different meanings: property name and property value,
|
||||
// using go-to-definition at such position should go to the variable declaration of the property value rather than
|
||||
// go to the declaration of the property name (in this case stay at the same position). However, if go-to-definition
|
||||
// is performed at the location of property access, we would like to go to definition of the property in the short-hand
|
||||
// assignment. This case and others are handled by the following code.
|
||||
if (node.parent.kind === ts.SyntaxKind.ShorthandPropertyAssignment) {
|
||||
symbol = checker.getShorthandAssignmentValueSymbol(symbol.valueDeclaration);
|
||||
}
|
||||
// If the node is the name of a BindingElement within an ObjectBindingPattern instead of just returning the
|
||||
// declaration the symbol (which is itself), we should try to get to the original type of the ObjectBindingPattern
|
||||
// and return the property declaration for the referenced property.
|
||||
// For example:
|
||||
// import('./foo').then(({ b/*goto*/ar }) => undefined); => should get use to the declaration in file "./foo"
|
||||
//
|
||||
// function bar<T>(onfulfilled: (value: T) => void) { //....}
|
||||
// interface Test {
|
||||
// pr/*destination*/op1: number
|
||||
// }
|
||||
// bar<Test>(({pr/*goto*/op1})=>{});
|
||||
if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
|
||||
(node === (parent.propertyName || parent.name))) {
|
||||
const name = getNameFromPropertyName(node);
|
||||
const type = checker.getTypeAtLocation(parent.parent);
|
||||
if (name && type) {
|
||||
if (type.isUnion()) {
|
||||
const prop = type.types[0].getProperty(name);
|
||||
if (prop) {
|
||||
symbol = prop;
|
||||
}
|
||||
}
|
||||
else {
|
||||
const prop = type.getProperty(name);
|
||||
if (prop) {
|
||||
symbol = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// If the current location we want to find its definition is in an object literal, try to get the contextual type for the
|
||||
// object literal, lookup the property symbol in the contextual type, and use this for goto-definition.
|
||||
// For example
|
||||
// interface Props{
|
||||
// /*first*/prop1: number
|
||||
// prop2: boolean
|
||||
// }
|
||||
// function Foo(arg: Props) {}
|
||||
// Foo( { pr/*1*/op1: 10, prop2: false })
|
||||
const element = getContainingObjectLiteralElement(node);
|
||||
if (element) {
|
||||
const contextualType = element && checker.getContextualType(element.parent);
|
||||
if (contextualType) {
|
||||
const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
|
||||
if (propertySymbols) {
|
||||
symbol = propertySymbols[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (symbol && symbol.declarations) {
|
||||
return [symbol, importNode];
|
||||
}
|
||||
return [null, null];
|
||||
}
|
||||
/** Get the token whose text contains the position */
|
||||
function getTokenAtPosition(sourceFile, position, allowPositionInLeadingTrivia, includeEndPosition) {
|
||||
let current = sourceFile;
|
||||
outer: while (true) {
|
||||
// find the child that contains 'position'
|
||||
for (const child of current.getChildren()) {
|
||||
const start = allowPositionInLeadingTrivia ? child.getFullStart() : child.getStart(sourceFile, /*includeJsDoc*/ true);
|
||||
if (start > position) {
|
||||
// If this child begins after position, then all subsequent children will as well.
|
||||
break;
|
||||
}
|
||||
const end = child.getEnd();
|
||||
if (position < end || (position === end && (child.kind === ts.SyntaxKind.EndOfFileToken || includeEndPosition))) {
|
||||
current = child;
|
||||
continue outer;
|
||||
}
|
||||
}
|
||||
return current;
|
||||
}
|
||||
}
|
|
@ -1,264 +0,0 @@
|
|||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
'use strict';
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.getElectronVersion = exports.streamToPromise = exports.versionStringToNumber = exports.filter = exports.rebase = exports.getVersion = exports.ensureDir = exports.rreddir = exports.rimraf = exports.stripSourceMappingURL = exports.loadSourcemaps = exports.cleanNodeModules = exports.skipDirectories = exports.toFileUri = exports.setExecutableBit = exports.fixWin32DirectoryPermissions = exports.incremental = void 0;
|
||||
const es = require("event-stream");
|
||||
const debounce = require("debounce");
|
||||
const _filter = require("gulp-filter");
|
||||
const rename = require("gulp-rename");
|
||||
const path = require("path");
|
||||
const fs = require("fs");
|
||||
const _rimraf = require("rimraf");
|
||||
const git = require("./git");
|
||||
const VinylFile = require("vinyl");
|
||||
const root = path.dirname(path.dirname(__dirname));
|
||||
const NoCancellationToken = { isCancellationRequested: () => false };
|
||||
function incremental(streamProvider, initial, supportsCancellation) {
|
||||
const input = es.through();
|
||||
const output = es.through();
|
||||
let state = 'idle';
|
||||
let buffer = Object.create(null);
|
||||
const token = !supportsCancellation ? undefined : { isCancellationRequested: () => Object.keys(buffer).length > 0 };
|
||||
const run = (input, isCancellable) => {
|
||||
state = 'running';
|
||||
const stream = !supportsCancellation ? streamProvider() : streamProvider(isCancellable ? token : NoCancellationToken);
|
||||
input
|
||||
.pipe(stream)
|
||||
.pipe(es.through(undefined, () => {
|
||||
state = 'idle';
|
||||
eventuallyRun();
|
||||
}))
|
||||
.pipe(output);
|
||||
};
|
||||
if (initial) {
|
||||
run(initial, false);
|
||||
}
|
||||
const eventuallyRun = debounce(() => {
|
||||
const paths = Object.keys(buffer);
|
||||
if (paths.length === 0) {
|
||||
return;
|
||||
}
|
||||
const data = paths.map(path => buffer[path]);
|
||||
buffer = Object.create(null);
|
||||
run(es.readArray(data), true);
|
||||
}, 500);
|
||||
input.on('data', (f) => {
|
||||
buffer[f.path] = f;
|
||||
if (state === 'idle') {
|
||||
eventuallyRun();
|
||||
}
|
||||
});
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
exports.incremental = incremental;
|
||||
function fixWin32DirectoryPermissions() {
|
||||
if (!/win32/.test(process.platform)) {
|
||||
return es.through();
|
||||
}
|
||||
return es.mapSync(f => {
|
||||
if (f.stat && f.stat.isDirectory && f.stat.isDirectory()) {
|
||||
f.stat.mode = 16877;
|
||||
}
|
||||
return f;
|
||||
});
|
||||
}
|
||||
exports.fixWin32DirectoryPermissions = fixWin32DirectoryPermissions;
|
||||
function setExecutableBit(pattern) {
|
||||
const setBit = es.mapSync(f => {
|
||||
if (!f.stat) {
|
||||
f.stat = { isFile() { return true; } };
|
||||
}
|
||||
f.stat.mode = /* 100755 */ 33261;
|
||||
return f;
|
||||
});
|
||||
if (!pattern) {
|
||||
return setBit;
|
||||
}
|
||||
const input = es.through();
|
||||
const filter = _filter(pattern, { restore: true });
|
||||
const output = input
|
||||
.pipe(filter)
|
||||
.pipe(setBit)
|
||||
.pipe(filter.restore);
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
exports.setExecutableBit = setExecutableBit;
|
||||
function toFileUri(filePath) {
|
||||
const match = filePath.match(/^([a-z])\:(.*)$/i);
|
||||
if (match) {
|
||||
filePath = '/' + match[1].toUpperCase() + ':' + match[2];
|
||||
}
|
||||
return 'file://' + filePath.replace(/\\/g, '/');
|
||||
}
|
||||
exports.toFileUri = toFileUri;
|
||||
function skipDirectories() {
|
||||
return es.mapSync(f => {
|
||||
if (!f.isDirectory()) {
|
||||
return f;
|
||||
}
|
||||
});
|
||||
}
|
||||
exports.skipDirectories = skipDirectories;
|
||||
function cleanNodeModules(rulePath) {
|
||||
const rules = fs.readFileSync(rulePath, 'utf8')
|
||||
.split(/\r?\n/g)
|
||||
.map(line => line.trim())
|
||||
.filter(line => line && !/^#/.test(line));
|
||||
const excludes = rules.filter(line => !/^!/.test(line)).map(line => `!**/node_modules/${line}`);
|
||||
const includes = rules.filter(line => /^!/.test(line)).map(line => `**/node_modules/${line.substr(1)}`);
|
||||
const input = es.through();
|
||||
const output = es.merge(input.pipe(_filter(['**', ...excludes])), input.pipe(_filter(includes)));
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
exports.cleanNodeModules = cleanNodeModules;
|
||||
function loadSourcemaps() {
|
||||
const input = es.through();
|
||||
const output = input
|
||||
.pipe(es.map((f, cb) => {
|
||||
if (f.sourceMap) {
|
||||
cb(undefined, f);
|
||||
return;
|
||||
}
|
||||
if (!f.contents) {
|
||||
cb(undefined, f);
|
||||
return;
|
||||
}
|
||||
const contents = f.contents.toString('utf8');
|
||||
const reg = /\/\/# sourceMappingURL=(.*)$/g;
|
||||
let lastMatch = null;
|
||||
let match = null;
|
||||
while (match = reg.exec(contents)) {
|
||||
lastMatch = match;
|
||||
}
|
||||
if (!lastMatch) {
|
||||
f.sourceMap = {
|
||||
version: '3',
|
||||
names: [],
|
||||
mappings: '',
|
||||
sources: [f.relative],
|
||||
sourcesContent: [contents]
|
||||
};
|
||||
cb(undefined, f);
|
||||
return;
|
||||
}
|
||||
f.contents = Buffer.from(contents.replace(/\/\/# sourceMappingURL=(.*)$/g, ''), 'utf8');
|
||||
fs.readFile(path.join(path.dirname(f.path), lastMatch[1]), 'utf8', (err, contents) => {
|
||||
if (err) {
|
||||
return cb(err);
|
||||
}
|
||||
f.sourceMap = JSON.parse(contents);
|
||||
cb(undefined, f);
|
||||
});
|
||||
}));
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
exports.loadSourcemaps = loadSourcemaps;
|
||||
function stripSourceMappingURL() {
|
||||
const input = es.through();
|
||||
const output = input
|
||||
.pipe(es.mapSync(f => {
|
||||
const contents = f.contents.toString('utf8');
|
||||
f.contents = Buffer.from(contents.replace(/\n\/\/# sourceMappingURL=(.*)$/gm, ''), 'utf8');
|
||||
return f;
|
||||
}));
|
||||
return es.duplex(input, output);
|
||||
}
|
||||
exports.stripSourceMappingURL = stripSourceMappingURL;
|
||||
function rimraf(dir) {
|
||||
const result = () => new Promise((c, e) => {
|
||||
let retries = 0;
|
||||
const retry = () => {
|
||||
_rimraf(dir, { maxBusyTries: 1 }, (err) => {
|
||||
if (!err) {
|
||||
return c();
|
||||
}
|
||||
if (err.code === 'ENOTEMPTY' && ++retries < 5) {
|
||||
return setTimeout(() => retry(), 10);
|
||||
}
|
||||
return e(err);
|
||||
});
|
||||
};
|
||||
retry();
|
||||
});
|
||||
result.taskName = `clean-${path.basename(dir).toLowerCase()}`;
|
||||
return result;
|
||||
}
|
||||
exports.rimraf = rimraf;
|
||||
function _rreaddir(dirPath, prepend, result) {
|
||||
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
_rreaddir(path.join(dirPath, entry.name), `${prepend}/${entry.name}`, result);
|
||||
}
|
||||
else {
|
||||
result.push(`${prepend}/${entry.name}`);
|
||||
}
|
||||
}
|
||||
}
|
||||
function rreddir(dirPath) {
|
||||
let result = [];
|
||||
_rreaddir(dirPath, '', result);
|
||||
return result;
|
||||
}
|
||||
exports.rreddir = rreddir;
|
||||
function ensureDir(dirPath) {
|
||||
if (fs.existsSync(dirPath)) {
|
||||
return;
|
||||
}
|
||||
ensureDir(path.dirname(dirPath));
|
||||
fs.mkdirSync(dirPath);
|
||||
}
|
||||
exports.ensureDir = ensureDir;
|
||||
function getVersion(root) {
|
||||
let version = process.env['BUILD_SOURCEVERSION'];
|
||||
if (!version || !/^[0-9a-f]{40}$/i.test(version)) {
|
||||
version = git.getVersion(root);
|
||||
}
|
||||
return version;
|
||||
}
|
||||
exports.getVersion = getVersion;
|
||||
function rebase(count) {
|
||||
return rename(f => {
|
||||
const parts = f.dirname ? f.dirname.split(/[\/\\]/) : [];
|
||||
f.dirname = parts.slice(count).join(path.sep);
|
||||
});
|
||||
}
|
||||
exports.rebase = rebase;
|
||||
function filter(fn) {
|
||||
const result = es.through(function (data) {
|
||||
if (fn(data)) {
|
||||
this.emit('data', data);
|
||||
}
|
||||
else {
|
||||
result.restore.push(data);
|
||||
}
|
||||
});
|
||||
result.restore = es.through();
|
||||
return result;
|
||||
}
|
||||
exports.filter = filter;
|
||||
function versionStringToNumber(versionStr) {
|
||||
const semverRegex = /(\d+)\.(\d+)\.(\d+)/;
|
||||
const match = versionStr.match(semverRegex);
|
||||
if (!match) {
|
||||
throw new Error('Version string is not properly formatted: ' + versionStr);
|
||||
}
|
||||
return parseInt(match[1], 10) * 1e4 + parseInt(match[2], 10) * 1e2 + parseInt(match[3], 10);
|
||||
}
|
||||
exports.versionStringToNumber = versionStringToNumber;
|
||||
function streamToPromise(stream) {
|
||||
return new Promise((c, e) => {
|
||||
stream.on('error', err => e(err));
|
||||
stream.on('end', () => c());
|
||||
});
|
||||
}
|
||||
exports.streamToPromise = streamToPromise;
|
||||
function getElectronVersion() {
|
||||
const yarnrc = fs.readFileSync(path.join(root, '.yarnrc'), 'utf8');
|
||||
const target = /^target "(.*)"$/m.exec(yarnrc)[1];
|
||||
return target;
|
||||
}
|
||||
exports.getElectronVersion = getElectronVersion;
|
|
@ -1,627 +0,0 @@
|
|||
"use strict";
|
||||
/*---------------------------------------------------------------------------------------------
|
||||
* Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
* Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
*--------------------------------------------------------------------------------------------*/
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.execute = exports.run3 = exports.DeclarationResolver = exports.FSProvider = exports.RECIPE_PATH = void 0;
|
||||
const fs = require("fs");
|
||||
const ts = require("typescript");
|
||||
const path = require("path");
|
||||
const fancyLog = require("fancy-log");
|
||||
const ansiColors = require("ansi-colors");
|
||||
const dtsv = '3';
|
||||
const tsfmt = require('../../tsfmt.json');
|
||||
const SRC = path.join(__dirname, '../../src');
|
||||
exports.RECIPE_PATH = path.join(__dirname, './monaco.d.ts.recipe');
|
||||
const DECLARATION_PATH = path.join(__dirname, '../../src/vs/monaco.d.ts');
|
||||
function logErr(message, ...rest) {
|
||||
fancyLog(ansiColors.yellow(`[monaco.d.ts]`), message, ...rest);
|
||||
}
|
||||
function isDeclaration(a) {
|
||||
return (a.kind === ts.SyntaxKind.InterfaceDeclaration
|
||||
|| a.kind === ts.SyntaxKind.EnumDeclaration
|
||||
|| a.kind === ts.SyntaxKind.ClassDeclaration
|
||||
|| a.kind === ts.SyntaxKind.TypeAliasDeclaration
|
||||
|| a.kind === ts.SyntaxKind.FunctionDeclaration
|
||||
|| a.kind === ts.SyntaxKind.ModuleDeclaration);
|
||||
}
|
||||
function visitTopLevelDeclarations(sourceFile, visitor) {
|
||||
let stop = false;
|
||||
let visit = (node) => {
|
||||
if (stop) {
|
||||
return;
|
||||
}
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.InterfaceDeclaration:
|
||||
case ts.SyntaxKind.EnumDeclaration:
|
||||
case ts.SyntaxKind.ClassDeclaration:
|
||||
case ts.SyntaxKind.VariableStatement:
|
||||
case ts.SyntaxKind.TypeAliasDeclaration:
|
||||
case ts.SyntaxKind.FunctionDeclaration:
|
||||
case ts.SyntaxKind.ModuleDeclaration:
|
||||
stop = visitor(node);
|
||||
}
|
||||
if (stop) {
|
||||
return;
|
||||
}
|
||||
ts.forEachChild(node, visit);
|
||||
};
|
||||
visit(sourceFile);
|
||||
}
|
||||
function getAllTopLevelDeclarations(sourceFile) {
|
||||
let all = [];
|
||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
||||
if (node.kind === ts.SyntaxKind.InterfaceDeclaration || node.kind === ts.SyntaxKind.ClassDeclaration || node.kind === ts.SyntaxKind.ModuleDeclaration) {
|
||||
let interfaceDeclaration = node;
|
||||
let triviaStart = interfaceDeclaration.pos;
|
||||
let triviaEnd = interfaceDeclaration.name.pos;
|
||||
let triviaText = getNodeText(sourceFile, { pos: triviaStart, end: triviaEnd });
|
||||
if (triviaText.indexOf('@internal') === -1) {
|
||||
all.push(node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
let nodeText = getNodeText(sourceFile, node);
|
||||
if (nodeText.indexOf('@internal') === -1) {
|
||||
all.push(node);
|
||||
}
|
||||
}
|
||||
return false /*continue*/;
|
||||
});
|
||||
return all;
|
||||
}
|
||||
function getTopLevelDeclaration(sourceFile, typeName) {
|
||||
let result = null;
|
||||
visitTopLevelDeclarations(sourceFile, (node) => {
|
||||
if (isDeclaration(node) && node.name) {
|
||||
if (node.name.text === typeName) {
|
||||
result = node;
|
||||
return true /*stop*/;
|
||||
}
|
||||
return false /*continue*/;
|
||||
}
|
||||
// node is ts.VariableStatement
|
||||
if (getNodeText(sourceFile, node).indexOf(typeName) >= 0) {
|
||||
result = node;
|
||||
return true /*stop*/;
|
||||
}
|
||||
return false /*continue*/;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
function getNodeText(sourceFile, node) {
|
||||
return sourceFile.getFullText().substring(node.pos, node.end);
|
||||
}
|
||||
function hasModifier(modifiers, kind) {
|
||||
if (modifiers) {
|
||||
for (let i = 0; i < modifiers.length; i++) {
|
||||
let mod = modifiers[i];
|
||||
if (mod.kind === kind) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function isStatic(member) {
|
||||
return hasModifier(member.modifiers, ts.SyntaxKind.StaticKeyword);
|
||||
}
|
||||
function isDefaultExport(declaration) {
|
||||
return (hasModifier(declaration.modifiers, ts.SyntaxKind.DefaultKeyword)
|
||||
&& hasModifier(declaration.modifiers, ts.SyntaxKind.ExportKeyword));
|
||||
}
|
||||
function getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums) {
|
||||
let result = getNodeText(sourceFile, declaration);
|
||||
if (declaration.kind === ts.SyntaxKind.InterfaceDeclaration || declaration.kind === ts.SyntaxKind.ClassDeclaration) {
|
||||
let interfaceDeclaration = declaration;
|
||||
const staticTypeName = (isDefaultExport(interfaceDeclaration)
|
||||
? `${importName}.default`
|
||||
: `${importName}.${declaration.name.text}`);
|
||||
let instanceTypeName = staticTypeName;
|
||||
const typeParametersCnt = (interfaceDeclaration.typeParameters ? interfaceDeclaration.typeParameters.length : 0);
|
||||
if (typeParametersCnt > 0) {
|
||||
let arr = [];
|
||||
for (let i = 0; i < typeParametersCnt; i++) {
|
||||
arr.push('any');
|
||||
}
|
||||
instanceTypeName = `${instanceTypeName}<${arr.join(',')}>`;
|
||||
}
|
||||
const members = interfaceDeclaration.members;
|
||||
members.forEach((member) => {
|
||||
try {
|
||||
let memberText = getNodeText(sourceFile, member);
|
||||
if (memberText.indexOf('@internal') >= 0 || memberText.indexOf('private') >= 0) {
|
||||
result = result.replace(memberText, '');
|
||||
}
|
||||
else {
|
||||
const memberName = member.name.text;
|
||||
const memberAccess = (memberName.indexOf('.') >= 0 ? `['${memberName}']` : `.${memberName}`);
|
||||
if (isStatic(member)) {
|
||||
usage.push(`a = ${staticTypeName}${memberAccess};`);
|
||||
}
|
||||
else {
|
||||
usage.push(`a = (<${instanceTypeName}>b)${memberAccess};`);
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (err) {
|
||||
// life..
|
||||
}
|
||||
});
|
||||
}
|
||||
else if (declaration.kind === ts.SyntaxKind.VariableStatement) {
|
||||
const jsDoc = result.substr(0, declaration.getLeadingTriviaWidth(sourceFile));
|
||||
if (jsDoc.indexOf('@monacodtsreplace') >= 0) {
|
||||
const jsDocLines = jsDoc.split(/\r\n|\r|\n/);
|
||||
let directives = [];
|
||||
for (const jsDocLine of jsDocLines) {
|
||||
const m = jsDocLine.match(/^\s*\* \/([^/]+)\/([^/]+)\/$/);
|
||||
if (m) {
|
||||
directives.push([new RegExp(m[1], 'g'), m[2]]);
|
||||
}
|
||||
}
|
||||
// remove the jsdoc
|
||||
result = result.substr(jsDoc.length);
|
||||
if (directives.length > 0) {
|
||||
// apply replace directives
|
||||
const replacer = createReplacerFromDirectives(directives);
|
||||
result = replacer(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
result = result.replace(/export default /g, 'export ');
|
||||
result = result.replace(/export declare /g, 'export ');
|
||||
result = result.replace(/declare /g, '');
|
||||
let lines = result.split(/\r\n|\r|\n/);
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
if (/\s*\*/.test(lines[i])) {
|
||||
// very likely a comment
|
||||
continue;
|
||||
}
|
||||
lines[i] = lines[i].replace(/"/g, '\'');
|
||||
}
|
||||
result = lines.join('\n');
|
||||
if (declaration.kind === ts.SyntaxKind.EnumDeclaration) {
|
||||
result = result.replace(/const enum/, 'enum');
|
||||
enums.push({
|
||||
enumName: declaration.name.getText(sourceFile),
|
||||
text: result
|
||||
});
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function format(text, endl) {
|
||||
const REALLY_FORMAT = false;
|
||||
text = preformat(text, endl);
|
||||
if (!REALLY_FORMAT) {
|
||||
return text;
|
||||
}
|
||||
// Parse the source text
|
||||
let sourceFile = ts.createSourceFile('file.ts', text, ts.ScriptTarget.Latest, /*setParentPointers*/ true);
|
||||
// Get the formatting edits on the input sources
|
||||
let edits = ts.formatting.formatDocument(sourceFile, getRuleProvider(tsfmt), tsfmt);
|
||||
// Apply the edits on the input code
|
||||
return applyEdits(text, edits);
|
||||
function countParensCurly(text) {
|
||||
let cnt = 0;
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
if (text.charAt(i) === '(' || text.charAt(i) === '{') {
|
||||
cnt++;
|
||||
}
|
||||
if (text.charAt(i) === ')' || text.charAt(i) === '}') {
|
||||
cnt--;
|
||||
}
|
||||
}
|
||||
return cnt;
|
||||
}
|
||||
function repeatStr(s, cnt) {
|
||||
let r = '';
|
||||
for (let i = 0; i < cnt; i++) {
|
||||
r += s;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
function preformat(text, endl) {
|
||||
let lines = text.split(endl);
|
||||
let inComment = false;
|
||||
let inCommentDeltaIndent = 0;
|
||||
let indent = 0;
|
||||
for (let i = 0; i < lines.length; i++) {
|
||||
let line = lines[i].replace(/\s$/, '');
|
||||
let repeat = false;
|
||||
let lineIndent = 0;
|
||||
do {
|
||||
repeat = false;
|
||||
if (line.substring(0, 4) === ' ') {
|
||||
line = line.substring(4);
|
||||
lineIndent++;
|
||||
repeat = true;
|
||||
}
|
||||
if (line.charAt(0) === '\t') {
|
||||
line = line.substring(1);
|
||||
lineIndent++;
|
||||
repeat = true;
|
||||
}
|
||||
} while (repeat);
|
||||
if (line.length === 0) {
|
||||
continue;
|
||||
}
|
||||
if (inComment) {
|
||||
if (/\*\//.test(line)) {
|
||||
inComment = false;
|
||||
}
|
||||
lines[i] = repeatStr('\t', lineIndent + inCommentDeltaIndent) + line;
|
||||
continue;
|
||||
}
|
||||
if (/\/\*/.test(line)) {
|
||||
inComment = true;
|
||||
inCommentDeltaIndent = indent - lineIndent;
|
||||
lines[i] = repeatStr('\t', indent) + line;
|
||||
continue;
|
||||
}
|
||||
const cnt = countParensCurly(line);
|
||||
let shouldUnindentAfter = false;
|
||||
let shouldUnindentBefore = false;
|
||||
if (cnt < 0) {
|
||||
if (/[({]/.test(line)) {
|
||||
shouldUnindentAfter = true;
|
||||
}
|
||||
else {
|
||||
shouldUnindentBefore = true;
|
||||
}
|
||||
}
|
||||
else if (cnt === 0) {
|
||||
shouldUnindentBefore = /^\}/.test(line);
|
||||
}
|
||||
let shouldIndentAfter = false;
|
||||
if (cnt > 0) {
|
||||
shouldIndentAfter = true;
|
||||
}
|
||||
else if (cnt === 0) {
|
||||
shouldIndentAfter = /{$/.test(line);
|
||||
}
|
||||
if (shouldUnindentBefore) {
|
||||
indent--;
|
||||
}
|
||||
lines[i] = repeatStr('\t', indent) + line;
|
||||
if (shouldUnindentAfter) {
|
||||
indent--;
|
||||
}
|
||||
if (shouldIndentAfter) {
|
||||
indent++;
|
||||
}
|
||||
}
|
||||
return lines.join(endl);
|
||||
}
|
||||
function getRuleProvider(options) {
|
||||
// Share this between multiple formatters using the same options.
|
||||
// This represents the bulk of the space the formatter uses.
|
||||
return ts.formatting.getFormatContext(options);
|
||||
}
|
||||
function applyEdits(text, edits) {
|
||||
// Apply edits in reverse on the existing text
|
||||
let result = text;
|
||||
for (let i = edits.length - 1; i >= 0; i--) {
|
||||
let change = edits[i];
|
||||
let head = result.slice(0, change.span.start);
|
||||
let tail = result.slice(change.span.start + change.span.length);
|
||||
result = head + change.newText + tail;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
function createReplacerFromDirectives(directives) {
|
||||
return (str) => {
|
||||
for (let i = 0; i < directives.length; i++) {
|
||||
str = str.replace(directives[i][0], directives[i][1]);
|
||||
}
|
||||
return str;
|
||||
};
|
||||
}
|
||||
function createReplacer(data) {
|
||||
data = data || '';
|
||||
let rawDirectives = data.split(';');
|
||||
let directives = [];
|
||||
rawDirectives.forEach((rawDirective) => {
|
||||
if (rawDirective.length === 0) {
|
||||
return;
|
||||
}
|
||||
let pieces = rawDirective.split('=>');
|
||||
let findStr = pieces[0];
|
||||
let replaceStr = pieces[1];
|
||||
findStr = findStr.replace(/[\-\\\{\}\*\+\?\|\^\$\.\,\[\]\(\)\#\s]/g, '\\$&');
|
||||
findStr = '\\b' + findStr + '\\b';
|
||||
directives.push([new RegExp(findStr, 'g'), replaceStr]);
|
||||
});
|
||||
return createReplacerFromDirectives(directives);
|
||||
}
|
||||
function generateDeclarationFile(recipe, sourceFileGetter) {
|
||||
const endl = /\r\n/.test(recipe) ? '\r\n' : '\n';
|
||||
let lines = recipe.split(endl);
|
||||
let result = [];
|
||||
let usageCounter = 0;
|
||||
let usageImports = [];
|
||||
let usage = [];
|
||||
let failed = false;
|
||||
usage.push(`var a: any;`);
|
||||
usage.push(`var b: any;`);
|
||||
const generateUsageImport = (moduleId) => {
|
||||
let importName = 'm' + (++usageCounter);
|
||||
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
|
||||
return importName;
|
||||
};
|
||||
let enums = [];
|
||||
let version = null;
|
||||
lines.forEach(line => {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
let m0 = line.match(/^\/\/dtsv=(\d+)$/);
|
||||
if (m0) {
|
||||
version = m0[1];
|
||||
}
|
||||
let m1 = line.match(/^\s*#include\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
||||
if (m1) {
|
||||
let moduleId = m1[1];
|
||||
const sourceFile = sourceFileGetter(moduleId);
|
||||
if (!sourceFile) {
|
||||
logErr(`While handling ${line}`);
|
||||
logErr(`Cannot find ${moduleId}`);
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
const importName = generateUsageImport(moduleId);
|
||||
let replacer = createReplacer(m1[2]);
|
||||
let typeNames = m1[3].split(/,/);
|
||||
typeNames.forEach((typeName) => {
|
||||
typeName = typeName.trim();
|
||||
if (typeName.length === 0) {
|
||||
return;
|
||||
}
|
||||
let declaration = getTopLevelDeclaration(sourceFile, typeName);
|
||||
if (!declaration) {
|
||||
logErr(`While handling ${line}`);
|
||||
logErr(`Cannot find ${typeName}`);
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
||||
});
|
||||
return;
|
||||
}
|
||||
let m2 = line.match(/^\s*#includeAll\(([^;)]*)(;[^)]*)?\)\:(.*)$/);
|
||||
if (m2) {
|
||||
let moduleId = m2[1];
|
||||
const sourceFile = sourceFileGetter(moduleId);
|
||||
if (!sourceFile) {
|
||||
logErr(`While handling ${line}`);
|
||||
logErr(`Cannot find ${moduleId}`);
|
||||
failed = true;
|
||||
return;
|
||||
}
|
||||
const importName = generateUsageImport(moduleId);
|
||||
let replacer = createReplacer(m2[2]);
|
||||
let typeNames = m2[3].split(/,/);
|
||||
let typesToExcludeMap = {};
|
||||
let typesToExcludeArr = [];
|
||||
typeNames.forEach((typeName) => {
|
||||
typeName = typeName.trim();
|
||||
if (typeName.length === 0) {
|
||||
return;
|
||||
}
|
||||
typesToExcludeMap[typeName] = true;
|
||||
typesToExcludeArr.push(typeName);
|
||||
});
|
||||
getAllTopLevelDeclarations(sourceFile).forEach((declaration) => {
|
||||
if (isDeclaration(declaration) && declaration.name) {
|
||||
if (typesToExcludeMap[declaration.name.text]) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// node is ts.VariableStatement
|
||||
let nodeText = getNodeText(sourceFile, declaration);
|
||||
for (let i = 0; i < typesToExcludeArr.length; i++) {
|
||||
if (nodeText.indexOf(typesToExcludeArr[i]) >= 0) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
result.push(replacer(getMassagedTopLevelDeclarationText(sourceFile, declaration, importName, usage, enums)));
|
||||
});
|
||||
return;
|
||||
}
|
||||
result.push(line);
|
||||
});
|
||||
if (failed) {
|
||||
return null;
|
||||
}
|
||||
if (version !== dtsv) {
|
||||
if (!version) {
|
||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' is written before versioning was introduced.`);
|
||||
}
|
||||
else {
|
||||
logErr(`gulp watch restart required. 'monaco.d.ts.recipe' v${version} does not match runtime v${dtsv}.`);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
let resultTxt = result.join(endl);
|
||||
resultTxt = resultTxt.replace(/\bURI\b/g, 'Uri');
|
||||
resultTxt = resultTxt.replace(/\bEvent</g, 'IEvent<');
|
||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
||||
resultTxt = format(resultTxt, endl);
|
||||
resultTxt = resultTxt.split(/\r\n|\n|\r/).join(endl);
|
||||
enums.sort((e1, e2) => {
|
||||
if (e1.enumName < e2.enumName) {
|
||||
return -1;
|
||||
}
|
||||
if (e1.enumName > e2.enumName) {
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
});
|
||||
let resultEnums = [
|
||||
'/*---------------------------------------------------------------------------------------------',
|
||||
' * Copyright (c) Microsoft Corporation. All rights reserved.',
|
||||
' * Licensed under the MIT License. See License.txt in the project root for license information.',
|
||||
' *--------------------------------------------------------------------------------------------*/',
|
||||
'',
|
||||
'// THIS IS A GENERATED FILE. DO NOT EDIT DIRECTLY.',
|
||||
''
|
||||
].concat(enums.map(e => e.text)).join(endl);
|
||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
||||
resultEnums = format(resultEnums, endl);
|
||||
resultEnums = resultEnums.split(/\r\n|\n|\r/).join(endl);
|
||||
return {
|
||||
result: resultTxt,
|
||||
usageContent: `${usageImports.join('\n')}\n\n${usage.join('\n')}`,
|
||||
enums: resultEnums
|
||||
};
|
||||
}
|
||||
function _run(sourceFileGetter) {
|
||||
const recipe = fs.readFileSync(exports.RECIPE_PATH).toString();
|
||||
const t = generateDeclarationFile(recipe, sourceFileGetter);
|
||||
if (!t) {
|
||||
return null;
|
||||
}
|
||||
const result = t.result;
|
||||
const usageContent = t.usageContent;
|
||||
const enums = t.enums;
|
||||
const currentContent = fs.readFileSync(DECLARATION_PATH).toString();
|
||||
const one = currentContent.replace(/\r\n/gm, '\n');
|
||||
const other = result.replace(/\r\n/gm, '\n');
|
||||
const isTheSame = (one === other);
|
||||
return {
|
||||
content: result,
|
||||
usageContent: usageContent,
|
||||
enums: enums,
|
||||
filePath: DECLARATION_PATH,
|
||||
isTheSame
|
||||
};
|
||||
}
|
||||
class FSProvider {
|
||||
existsSync(filePath) {
|
||||
return fs.existsSync(filePath);
|
||||
}
|
||||
statSync(filePath) {
|
||||
return fs.statSync(filePath);
|
||||
}
|
||||
readFileSync(_moduleId, filePath) {
|
||||
return fs.readFileSync(filePath);
|
||||
}
|
||||
}
|
||||
exports.FSProvider = FSProvider;
|
||||
class CacheEntry {
|
||||
constructor(sourceFile, mtime) {
|
||||
this.sourceFile = sourceFile;
|
||||
this.mtime = mtime;
|
||||
}
|
||||
}
|
||||
class DeclarationResolver {
|
||||
constructor(_fsProvider) {
|
||||
this._fsProvider = _fsProvider;
|
||||
this._sourceFileCache = Object.create(null);
|
||||
}
|
||||
invalidateCache(moduleId) {
|
||||
this._sourceFileCache[moduleId] = null;
|
||||
}
|
||||
getDeclarationSourceFile(moduleId) {
|
||||
if (this._sourceFileCache[moduleId]) {
|
||||
// Since we cannot trust file watching to invalidate the cache, check also the mtime
|
||||
const fileName = this._getFileName(moduleId);
|
||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
||||
if (this._sourceFileCache[moduleId].mtime !== mtime) {
|
||||
this._sourceFileCache[moduleId] = null;
|
||||
}
|
||||
}
|
||||
if (!this._sourceFileCache[moduleId]) {
|
||||
this._sourceFileCache[moduleId] = this._getDeclarationSourceFile(moduleId);
|
||||
}
|
||||
return this._sourceFileCache[moduleId] ? this._sourceFileCache[moduleId].sourceFile : null;
|
||||
}
|
||||
_getFileName(moduleId) {
|
||||
if (/\.d\.ts$/.test(moduleId)) {
|
||||
return path.join(SRC, moduleId);
|
||||
}
|
||||
return path.join(SRC, `${moduleId}.ts`);
|
||||
}
|
||||
_getDeclarationSourceFile(moduleId) {
|
||||
const fileName = this._getFileName(moduleId);
|
||||
if (!this._fsProvider.existsSync(fileName)) {
|
||||
return null;
|
||||
}
|
||||
const mtime = this._fsProvider.statSync(fileName).mtime.getTime();
|
||||
if (/\.d\.ts$/.test(moduleId)) {
|
||||
// const mtime = this._fsProvider.statFileSync()
|
||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
||||
return new CacheEntry(ts.createSourceFile(fileName, fileContents, ts.ScriptTarget.ES5), mtime);
|
||||
}
|
||||
const fileContents = this._fsProvider.readFileSync(moduleId, fileName).toString();
|
||||
const fileMap = {
|
||||
'file.ts': fileContents
|
||||
};
|
||||
const service = ts.createLanguageService(new TypeScriptLanguageServiceHost({}, fileMap, {}));
|
||||
const text = service.getEmitOutput('file.ts', true, true).outputFiles[0].text;
|
||||
return new CacheEntry(ts.createSourceFile(fileName, text, ts.ScriptTarget.ES5), mtime);
|
||||
}
|
||||
}
|
||||
exports.DeclarationResolver = DeclarationResolver;
|
||||
function run3(resolver) {
|
||||
const sourceFileGetter = (moduleId) => resolver.getDeclarationSourceFile(moduleId);
|
||||
return _run(sourceFileGetter);
|
||||
}
|
||||
exports.run3 = run3;
|
||||
class TypeScriptLanguageServiceHost {
|
||||
constructor(libs, files, compilerOptions) {
|
||||
this._libs = libs;
|
||||
this._files = files;
|
||||
this._compilerOptions = compilerOptions;
|
||||
}
|
||||
// --- language service host ---------------
|
||||
getCompilationSettings() {
|
||||
return this._compilerOptions;
|
||||
}
|
||||
getScriptFileNames() {
|
||||
return ([]
|
||||
.concat(Object.keys(this._libs))
|
||||
.concat(Object.keys(this._files)));
|
||||
}
|
||||
getScriptVersion(_fileName) {
|
||||
return '1';
|
||||
}
|
||||
getProjectVersion() {
|
||||
return '1';
|
||||
}
|
||||
getScriptSnapshot(fileName) {
|
||||
if (this._files.hasOwnProperty(fileName)) {
|
||||
return ts.ScriptSnapshot.fromString(this._files[fileName]);
|
||||
}
|
||||
else if (this._libs.hasOwnProperty(fileName)) {
|
||||
return ts.ScriptSnapshot.fromString(this._libs[fileName]);
|
||||
}
|
||||
else {
|
||||
return ts.ScriptSnapshot.fromString('');
|
||||
}
|
||||
}
|
||||
getScriptKind(_fileName) {
|
||||
return ts.ScriptKind.TS;
|
||||
}
|
||||
getCurrentDirectory() {
|
||||
return '';
|
||||
}
|
||||
getDefaultLibFileName(_options) {
|
||||
return 'defaultLib:es5';
|
||||
}
|
||||
isDefaultLibFileName(fileName) {
|
||||
return fileName === this.getDefaultLibFileName(this._compilerOptions);
|
||||
}
|
||||
}
|
||||
function execute() {
|
||||
let r = run3(new DeclarationResolver(new FSProvider()));
|
||||
if (!r) {
|
||||
throw new Error(`monaco.d.ts generation error - Cannot continue`);
|
||||
}
|
||||
return r;
|
||||
}
|
||||
exports.execute = execute;
|
Loading…
Reference in a new issue