mirror of
https://github.com/Microsoft/vscode
synced 2024-08-28 13:29:44 +00:00
Fix standalone editor gulp scripts.
Tree Shaking: - do not proceed with tree shaking when there are compilation errors - load .d.ts files in the language service - adopt TS 3.1.1 in symbol resolution - use the real tsconfig.json / with "node" resolution Bundling: - fix issue where files were being looked for in out-build instead of out-editor-build
This commit is contained in:
parent
4312f42a4f
commit
d729e50521
|
@ -28,7 +28,7 @@ var editorEntryPoints = [
|
|||
name: 'vs/editor/editor.main',
|
||||
include: [],
|
||||
exclude: ['vs/css', 'vs/nls'],
|
||||
prepend: ['out-build/vs/css.js', 'out-build/vs/nls.js'],
|
||||
prepend: ['out-editor-build/vs/css.js', 'out-editor-build/vs/nls.js'],
|
||||
},
|
||||
{
|
||||
name: 'vs/base/common/worker/simpleWorker',
|
||||
|
@ -79,16 +79,21 @@ gulp.task('extract-editor-src', ['clean-editor-src'], function () {
|
|||
apiusages,
|
||||
extrausages
|
||||
],
|
||||
typings: [
|
||||
'typings/lib.ie11_safe_es6.d.ts',
|
||||
'typings/thenable.d.ts',
|
||||
'typings/es6-promise.d.ts',
|
||||
'typings/require-monaco.d.ts',
|
||||
'vs/monaco.d.ts'
|
||||
],
|
||||
libs: [
|
||||
`lib.d.ts`,
|
||||
`lib.es2015.collection.d.ts`
|
||||
`lib.es5.d.ts`,
|
||||
`lib.dom.d.ts`,
|
||||
`lib.webworker.importscripts.d.ts`
|
||||
],
|
||||
redirects: {
|
||||
'vs/base/browser/ui/octiconLabel/octiconLabel': 'vs/base/browser/ui/octiconLabel/octiconLabel.mock',
|
||||
},
|
||||
compilerOptions: {
|
||||
module: 2, // ModuleKind.AMD
|
||||
},
|
||||
shakeLevel: 2, // 0-Files, 1-InnerFile, 2-ClassMembers
|
||||
importIgnorePattern: /^vs\/css!/,
|
||||
destRoot: path.join(root, 'out-editor-src')
|
||||
|
@ -108,6 +113,8 @@ gulp.task('optimize-editor', ['clean-optimized-editor', 'compile-editor-build'],
|
|||
loaderConfig: {
|
||||
paths: {
|
||||
'vs': 'out-editor-build/vs',
|
||||
'vs/css': 'out-editor-build/vs/css.build',
|
||||
'vs/nls': 'out-editor-build/vs/nls.build',
|
||||
'vscode': 'empty:'
|
||||
}
|
||||
},
|
||||
|
@ -125,7 +132,7 @@ gulp.task('clean-editor-esm', util.rimraf('out-editor-esm'));
|
|||
gulp.task('extract-editor-esm', ['clean-editor-esm', 'clean-editor-distro', 'extract-editor-src'], function () {
|
||||
standalone.createESMSourcesAndResources2({
|
||||
srcFolder: './out-editor-src',
|
||||
outFolder: './out-editor-esm/src',
|
||||
outFolder: './out-editor-esm',
|
||||
outResourcesFolder: './out-monaco-editor-core/esm',
|
||||
ignores: [
|
||||
'inlineEntryPoint:0.ts',
|
||||
|
|
|
@ -32,8 +32,12 @@ function bundle(entryPoints, config, callback) {
|
|||
var loader = loaderModule.exports;
|
||||
config.isBuild = true;
|
||||
config.paths = config.paths || {};
|
||||
config.paths['vs/nls'] = 'out-build/vs/nls.build';
|
||||
config.paths['vs/css'] = 'out-build/vs/css.build';
|
||||
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'], function (localRequire) {
|
||||
var resolvePath = function (path) {
|
||||
|
|
|
@ -123,8 +123,12 @@ export function bundle(entryPoints: IEntryPoint[], config: ILoaderConfig, callba
|
|||
const loader: any = loaderModule.exports;
|
||||
config.isBuild = true;
|
||||
config.paths = config.paths || {};
|
||||
config.paths['vs/nls'] = 'out-build/vs/nls.build';
|
||||
config.paths['vs/css'] = 'out-build/vs/css.build';
|
||||
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: any) => {
|
||||
|
|
|
@ -27,6 +27,13 @@ function writeFile(filePath, contents) {
|
|||
fs.writeFileSync(filePath, contents);
|
||||
}
|
||||
function extractEditor(options) {
|
||||
var tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
|
||||
tsConfig.compilerOptions.noUnusedLocals = false;
|
||||
tsConfig.compilerOptions.preserveConstEnums = false;
|
||||
tsConfig.compilerOptions.declaration = false;
|
||||
delete tsConfig.compilerOptions.types;
|
||||
tsConfig.exclude = [];
|
||||
options.compilerOptions = tsConfig.compilerOptions;
|
||||
var result = tss.shake(options);
|
||||
for (var fileName in result) {
|
||||
if (result.hasOwnProperty(fileName)) {
|
||||
|
@ -73,25 +80,16 @@ function extractEditor(options) {
|
|||
}
|
||||
}
|
||||
}
|
||||
var tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
|
||||
tsConfig.compilerOptions.noUnusedLocals = false;
|
||||
tsConfig.compilerOptions.preserveConstEnums = false;
|
||||
tsConfig.compilerOptions.declaration = false;
|
||||
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
||||
[
|
||||
'vs/css.build.js',
|
||||
'vs/css.d.ts',
|
||||
'vs/css.js',
|
||||
'vs/loader.js',
|
||||
'vs/monaco.d.ts',
|
||||
'vs/nls.build.js',
|
||||
'vs/nls.d.ts',
|
||||
'vs/nls.js',
|
||||
'vs/nls.mock.ts',
|
||||
'typings/lib.ie11_safe_es6.d.ts',
|
||||
'typings/thenable.d.ts',
|
||||
'typings/es6-promise.d.ts',
|
||||
'typings/require.d.ts',
|
||||
].forEach(copyFile);
|
||||
}
|
||||
exports.extractEditor = extractEditor;
|
||||
|
@ -102,7 +100,7 @@ function createESMSourcesAndResources2(options) {
|
|||
var getDestAbsoluteFilePath = function (file) {
|
||||
var dest = options.renames[file.replace(/\\/g, '/')] || file;
|
||||
if (dest === 'tsconfig.json') {
|
||||
return path.join(OUT_FOLDER, "../tsconfig.json");
|
||||
return path.join(OUT_FOLDER, "tsconfig.json");
|
||||
}
|
||||
if (/\.ts$/.test(dest)) {
|
||||
return path.join(OUT_FOLDER, dest);
|
||||
|
@ -117,11 +115,8 @@ function createESMSourcesAndResources2(options) {
|
|||
}
|
||||
if (file === 'tsconfig.json') {
|
||||
var tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
|
||||
tsConfig.compilerOptions.moduleResolution = undefined;
|
||||
tsConfig.compilerOptions.baseUrl = undefined;
|
||||
tsConfig.compilerOptions.module = 'es6';
|
||||
tsConfig.compilerOptions.rootDir = 'src';
|
||||
tsConfig.compilerOptions.outDir = path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER);
|
||||
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs');
|
||||
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -31,6 +31,15 @@ function writeFile(filePath: string, contents: Buffer | string): void {
|
|||
}
|
||||
|
||||
export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: string }): void {
|
||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
|
||||
tsConfig.compilerOptions.noUnusedLocals = false;
|
||||
tsConfig.compilerOptions.preserveConstEnums = false;
|
||||
tsConfig.compilerOptions.declaration = false;
|
||||
delete tsConfig.compilerOptions.types;
|
||||
tsConfig.exclude = [];
|
||||
|
||||
options.compilerOptions = tsConfig.compilerOptions;
|
||||
|
||||
let result = tss.shake(options);
|
||||
for (let fileName in result) {
|
||||
if (result.hasOwnProperty(fileName)) {
|
||||
|
@ -79,10 +88,6 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
|
|||
}
|
||||
}
|
||||
|
||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(options.sourcesRoot, 'tsconfig.json')).toString());
|
||||
tsConfig.compilerOptions.noUnusedLocals = false;
|
||||
tsConfig.compilerOptions.preserveConstEnums = false;
|
||||
tsConfig.compilerOptions.declaration = false;
|
||||
writeOutputFile('tsconfig.json', JSON.stringify(tsConfig, null, '\t'));
|
||||
|
||||
[
|
||||
|
@ -90,15 +95,10 @@ export function extractEditor(options: tss.ITreeShakingOptions & { destRoot: str
|
|||
'vs/css.d.ts',
|
||||
'vs/css.js',
|
||||
'vs/loader.js',
|
||||
'vs/monaco.d.ts',
|
||||
'vs/nls.build.js',
|
||||
'vs/nls.d.ts',
|
||||
'vs/nls.js',
|
||||
'vs/nls.mock.ts',
|
||||
'typings/lib.ie11_safe_es6.d.ts',
|
||||
'typings/thenable.d.ts',
|
||||
'typings/es6-promise.d.ts',
|
||||
'typings/require.d.ts',
|
||||
].forEach(copyFile);
|
||||
}
|
||||
|
||||
|
@ -118,7 +118,7 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
|
|||
const getDestAbsoluteFilePath = (file: string): string => {
|
||||
let dest = options.renames[file.replace(/\\/g, '/')] || file;
|
||||
if (dest === 'tsconfig.json') {
|
||||
return path.join(OUT_FOLDER, `../tsconfig.json`);
|
||||
return path.join(OUT_FOLDER, `tsconfig.json`);
|
||||
}
|
||||
if (/\.ts$/.test(dest)) {
|
||||
return path.join(OUT_FOLDER, dest);
|
||||
|
@ -136,11 +136,8 @@ export function createESMSourcesAndResources2(options: IOptions2): void {
|
|||
|
||||
if (file === 'tsconfig.json') {
|
||||
const tsConfig = JSON.parse(fs.readFileSync(path.join(SRC_FOLDER, file)).toString());
|
||||
tsConfig.compilerOptions.moduleResolution = undefined;
|
||||
tsConfig.compilerOptions.baseUrl = undefined;
|
||||
tsConfig.compilerOptions.module = 'es6';
|
||||
tsConfig.compilerOptions.rootDir = 'src';
|
||||
tsConfig.compilerOptions.outDir = path.relative(path.dirname(OUT_FOLDER), OUT_RESOURCES_FOLDER);
|
||||
tsConfig.compilerOptions.outDir = path.join(path.relative(OUT_FOLDER, OUT_RESOURCES_FOLDER), 'vs');
|
||||
write(getDestAbsoluteFilePath(file), JSON.stringify(tsConfig, null, '\t'));
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -14,8 +14,39 @@ var ShakeLevel;
|
|||
ShakeLevel[ShakeLevel["InnerFile"] = 1] = "InnerFile";
|
||||
ShakeLevel[ShakeLevel["ClassMembers"] = 2] = "ClassMembers";
|
||||
})(ShakeLevel = exports.ShakeLevel || (exports.ShakeLevel = {}));
|
||||
function printDiagnostics(diagnostics) {
|
||||
for (var i = 0; i < diagnostics.length; i++) {
|
||||
var diag = diagnostics[i];
|
||||
var result = '';
|
||||
if (diag.file) {
|
||||
result += diag.file.fileName + ": ";
|
||||
}
|
||||
if (diag.file && diag.start) {
|
||||
var location_1 = diag.file.getLineAndCharacterOfPosition(diag.start);
|
||||
result += "- " + (location_1.line + 1) + "," + location_1.character + " - ";
|
||||
}
|
||||
result += JSON.stringify(diag.messageText);
|
||||
console.log(result);
|
||||
}
|
||||
}
|
||||
function shake(options) {
|
||||
var languageService = createTypeScriptLanguageService(options);
|
||||
var program = languageService.getProgram();
|
||||
var globalDiagnostics = program.getGlobalDiagnostics();
|
||||
if (globalDiagnostics.length > 0) {
|
||||
printDiagnostics(globalDiagnostics);
|
||||
throw new Error("Compilation Errors encountered.");
|
||||
}
|
||||
var syntacticDiagnostics = program.getSyntacticDiagnostics();
|
||||
if (syntacticDiagnostics.length > 0) {
|
||||
printDiagnostics(syntacticDiagnostics);
|
||||
throw new Error("Compilation Errors encountered.");
|
||||
}
|
||||
var semanticDiagnostics = program.getSemanticDiagnostics();
|
||||
if (semanticDiagnostics.length > 0) {
|
||||
printDiagnostics(semanticDiagnostics);
|
||||
throw new Error("Compilation Errors encountered.");
|
||||
}
|
||||
markNodes(languageService, options);
|
||||
return generateResult(languageService, options.shakeLevel);
|
||||
}
|
||||
|
@ -28,13 +59,18 @@ function createTypeScriptLanguageService(options) {
|
|||
options.inlineEntryPoints.forEach(function (inlineEntryPoint, index) {
|
||||
FILES["inlineEntryPoint:" + index + ".ts"] = inlineEntryPoint;
|
||||
});
|
||||
// Add additional typings
|
||||
options.typings.forEach(function (typing) {
|
||||
var filePath = path.join(options.sourcesRoot, typing);
|
||||
FILES[typing] = fs.readFileSync(filePath).toString();
|
||||
});
|
||||
// Resolve libs
|
||||
var RESOLVED_LIBS = {};
|
||||
options.libs.forEach(function (filename) {
|
||||
var filepath = path.join(TYPESCRIPT_LIB_FOLDER, filename);
|
||||
RESOLVED_LIBS["defaultLib:" + filename] = fs.readFileSync(filepath).toString();
|
||||
});
|
||||
var host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions);
|
||||
var host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, ts.convertCompilerOptionsFromJson(options.compilerOptions, "").options);
|
||||
return ts.createLanguageService(host);
|
||||
}
|
||||
/**
|
||||
|
@ -57,7 +93,7 @@ function discoverAndReadFiles(options) {
|
|||
var dts_filename = path.join(options.sourcesRoot, moduleId + '.d.ts');
|
||||
if (fs.existsSync(dts_filename)) {
|
||||
var dts_filecontents = fs.readFileSync(dts_filename).toString();
|
||||
FILES[moduleId + '.d.ts'] = dts_filecontents;
|
||||
FILES[moduleId + ".d.ts"] = dts_filecontents;
|
||||
continue;
|
||||
}
|
||||
var ts_filename = void 0;
|
||||
|
@ -81,7 +117,7 @@ function discoverAndReadFiles(options) {
|
|||
}
|
||||
enqueue(importedModuleId);
|
||||
}
|
||||
FILES[moduleId + '.ts'] = ts_filecontents;
|
||||
FILES[moduleId + ".ts"] = ts_filecontents;
|
||||
}
|
||||
return FILES;
|
||||
}
|
||||
|
@ -517,68 +553,9 @@ function generateResult(languageService, shakeLevel) {
|
|||
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
|
||||
*/
|
||||
function getRealNodeSymbol(checker, node) {
|
||||
/**
|
||||
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
|
||||
*/
|
||||
/* @internal */
|
||||
function getContainingObjectLiteralElement(node) {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.NumericLiteral:
|
||||
if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) {
|
||||
return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
|
||||
}
|
||||
// falls through
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return ts.isObjectLiteralElement(node.parent) &&
|
||||
(node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) &&
|
||||
node.parent.name === node ? node.parent : undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function getPropertySymbolsFromType(type, propName) {
|
||||
function getTextOfPropertyName(name) {
|
||||
function isStringOrNumericLiteral(node) {
|
||||
var kind = node.kind;
|
||||
return kind === ts.SyntaxKind.StringLiteral
|
||||
|| kind === ts.SyntaxKind.NumericLiteral;
|
||||
}
|
||||
switch (name.kind) {
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return name.text;
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.NumericLiteral:
|
||||
return name.text;
|
||||
case ts.SyntaxKind.ComputedPropertyName:
|
||||
return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined;
|
||||
}
|
||||
}
|
||||
var name = getTextOfPropertyName(propName);
|
||||
if (name && type) {
|
||||
var result = [];
|
||||
var symbol_1 = type.getProperty(name);
|
||||
if (type.flags & ts.TypeFlags.Union) {
|
||||
for (var _i = 0, _a = type.types; _i < _a.length; _i++) {
|
||||
var t = _a[_i];
|
||||
var symbol_2 = t.getProperty(name);
|
||||
if (symbol_2) {
|
||||
result.push(symbol_2);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
if (symbol_1) {
|
||||
result.push(symbol_1);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function getPropertySymbolsFromContextualType(typeChecker, node) {
|
||||
var objectLiteral = node.parent;
|
||||
var contextualType = typeChecker.getContextualType(objectLiteral);
|
||||
return getPropertySymbolsFromType(contextualType, node.name);
|
||||
}
|
||||
var getPropertySymbolsFromContextualType = ts.getPropertySymbolsFromContextualType;
|
||||
var getContainingObjectLiteralElement = ts.getContainingObjectLiteralElement;
|
||||
var getNameFromPropertyName = ts.getNameFromPropertyName;
|
||||
// Go to the original declaration for cases:
|
||||
//
|
||||
// (1) when the aliased symbol was declared in the location(parent).
|
||||
|
@ -606,8 +583,13 @@ function getRealNodeSymbol(checker, node) {
|
|||
return [null, null];
|
||||
}
|
||||
}
|
||||
var parent = node.parent;
|
||||
var symbol = checker.getSymbolAtLocation(node);
|
||||
var 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])) {
|
||||
var aliased = checker.getAliasedSymbol(symbol);
|
||||
if (aliased.declarations) {
|
||||
|
@ -636,13 +618,22 @@ function getRealNodeSymbol(checker, node) {
|
|||
// pr/*destination*/op1: number
|
||||
// }
|
||||
// bar<Test>(({pr/*goto*/op1})=>{});
|
||||
if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) &&
|
||||
(node === (node.parent.propertyName || node.parent.name))) {
|
||||
var type = checker.getTypeAtLocation(node.parent.parent);
|
||||
if (type) {
|
||||
var propSymbols = getPropertySymbolsFromType(type, node);
|
||||
if (propSymbols) {
|
||||
symbol = propSymbols[0];
|
||||
if (ts.isPropertyName(node) && ts.isBindingElement(parent) && ts.isObjectBindingPattern(parent.parent) &&
|
||||
(node === (parent.propertyName || parent.name))) {
|
||||
var name_1 = getNameFromPropertyName(node);
|
||||
var type = checker.getTypeAtLocation(parent.parent);
|
||||
if (name_1 && type) {
|
||||
if (type.isUnion()) {
|
||||
var prop = type.types[0].getProperty(name_1);
|
||||
if (prop) {
|
||||
symbol = prop;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var prop = type.getProperty(name_1);
|
||||
if (prop) {
|
||||
symbol = prop;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -656,10 +647,13 @@ function getRealNodeSymbol(checker, node) {
|
|||
// function Foo(arg: Props) {}
|
||||
// Foo( { pr/*1*/op1: 10, prop2: false })
|
||||
var element = getContainingObjectLiteralElement(node);
|
||||
if (element && checker.getContextualType(element.parent)) {
|
||||
var propertySymbols = getPropertySymbolsFromContextualType(checker, element);
|
||||
if (propertySymbols) {
|
||||
symbol = propertySymbols[0];
|
||||
if (element) {
|
||||
var contextualType = element && checker.getContextualType(element.parent);
|
||||
if (contextualType) {
|
||||
var propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
|
||||
if (propertySymbols) {
|
||||
symbol = propertySymbols[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,14 @@ export interface ITreeShakingOptions {
|
|||
* e.g. `lib.d.ts`, `lib.es2015.collection.d.ts`
|
||||
*/
|
||||
libs: string[];
|
||||
/**
|
||||
* Other .d.ts files
|
||||
*/
|
||||
typings: string[];
|
||||
/**
|
||||
* TypeScript compiler options.
|
||||
*/
|
||||
compilerOptions: ts.CompilerOptions;
|
||||
compilerOptions?: any;
|
||||
/**
|
||||
* The shake level to perform.
|
||||
*/
|
||||
|
@ -56,8 +60,43 @@ export interface ITreeShakingResult {
|
|||
[file: string]: string;
|
||||
}
|
||||
|
||||
function printDiagnostics(diagnostics: ReadonlyArray<ts.Diagnostic>): void {
|
||||
for (let i = 0; i < diagnostics.length; i++) {
|
||||
const diag = diagnostics[i];
|
||||
let result = '';
|
||||
if (diag.file) {
|
||||
result += `${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);
|
||||
}
|
||||
}
|
||||
|
||||
export function shake(options: ITreeShakingOptions): ITreeShakingResult {
|
||||
const languageService = createTypeScriptLanguageService(options);
|
||||
const program = languageService.getProgram()!;
|
||||
|
||||
const globalDiagnostics = program.getGlobalDiagnostics();
|
||||
if (globalDiagnostics.length > 0) {
|
||||
printDiagnostics(globalDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
|
||||
const syntacticDiagnostics = program.getSyntacticDiagnostics();
|
||||
if (syntacticDiagnostics.length > 0) {
|
||||
printDiagnostics(syntacticDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
|
||||
const semanticDiagnostics = program.getSemanticDiagnostics();
|
||||
if (semanticDiagnostics.length > 0) {
|
||||
printDiagnostics(semanticDiagnostics);
|
||||
throw new Error(`Compilation Errors encountered.`);
|
||||
}
|
||||
|
||||
markNodes(languageService, options);
|
||||
|
||||
|
@ -74,6 +113,12 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu
|
|||
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: ILibMap = {};
|
||||
options.libs.forEach((filename) => {
|
||||
|
@ -81,7 +126,7 @@ function createTypeScriptLanguageService(options: ITreeShakingOptions): ts.Langu
|
|||
RESOLVED_LIBS[`defaultLib:${filename}`] = fs.readFileSync(filepath).toString();
|
||||
});
|
||||
|
||||
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, options.compilerOptions);
|
||||
const host = new TypeScriptLanguageServiceHost(RESOLVED_LIBS, FILES, ts.convertCompilerOptionsFromJson(options.compilerOptions, ``).options);
|
||||
return ts.createLanguageService(host);
|
||||
}
|
||||
|
||||
|
@ -109,7 +154,7 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap {
|
|||
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;
|
||||
FILES[`${moduleId}.d.ts`] = dts_filecontents;
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -136,7 +181,7 @@ function discoverAndReadFiles(options: ITreeShakingOptions): IFileMap {
|
|||
enqueue(importedModuleId);
|
||||
}
|
||||
|
||||
FILES[moduleId + '.ts'] = ts_filecontents;
|
||||
FILES[`${moduleId}.ts`] = ts_filecontents;
|
||||
}
|
||||
|
||||
return FILES;
|
||||
|
@ -636,73 +681,12 @@ function generateResult(languageService: ts.LanguageService, shakeLevel: ShakeLe
|
|||
* Returns the node's symbol and the `import` node (if the symbol resolved from a different module)
|
||||
*/
|
||||
function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol | null, ts.Declaration | null] {
|
||||
/**
|
||||
* Returns the containing object literal property declaration given a possible name node, e.g. "a" in x = { "a": 1 }
|
||||
*/
|
||||
/* @internal */
|
||||
function getContainingObjectLiteralElement(node: ts.Node): ts.ObjectLiteralElement | undefined {
|
||||
switch (node.kind) {
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.NumericLiteral:
|
||||
if (node.parent.kind === ts.SyntaxKind.ComputedPropertyName) {
|
||||
return ts.isObjectLiteralElement(node.parent.parent) ? node.parent.parent : undefined;
|
||||
}
|
||||
// falls through
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return ts.isObjectLiteralElement(node.parent) &&
|
||||
(node.parent.parent.kind === ts.SyntaxKind.ObjectLiteralExpression || node.parent.parent.kind === ts.SyntaxKind.JsxAttributes) &&
|
||||
node.parent.name === node ? node.parent : undefined;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPropertySymbolsFromType(type: ts.Type, propName: ts.PropertyName) {
|
||||
function getTextOfPropertyName(name: ts.PropertyName): string {
|
||||
|
||||
function isStringOrNumericLiteral(node: ts.Node): node is ts.StringLiteral | ts.NumericLiteral {
|
||||
const kind = node.kind;
|
||||
return kind === ts.SyntaxKind.StringLiteral
|
||||
|| kind === ts.SyntaxKind.NumericLiteral;
|
||||
}
|
||||
|
||||
switch (name.kind) {
|
||||
case ts.SyntaxKind.Identifier:
|
||||
return name.text;
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.NumericLiteral:
|
||||
return name.text;
|
||||
case ts.SyntaxKind.ComputedPropertyName:
|
||||
return isStringOrNumericLiteral(name.expression) ? name.expression.text : undefined!;
|
||||
}
|
||||
}
|
||||
|
||||
const name = getTextOfPropertyName(propName);
|
||||
if (name && type) {
|
||||
const result: ts.Symbol[] = [];
|
||||
const symbol = type.getProperty(name);
|
||||
if (type.flags & ts.TypeFlags.Union) {
|
||||
for (const t of (<ts.UnionType>type).types) {
|
||||
const symbol = t.getProperty(name);
|
||||
if (symbol) {
|
||||
result.push(symbol);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (symbol) {
|
||||
result.push(symbol);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getPropertySymbolsFromContextualType(typeChecker: ts.TypeChecker, node: ts.ObjectLiteralElement): ts.Symbol[] {
|
||||
const objectLiteral = <ts.ObjectLiteralExpression | ts.JsxAttributes>node.parent;
|
||||
const contextualType = typeChecker.getContextualType(objectLiteral)!;
|
||||
return getPropertySymbolsFromType(contextualType, node.name!)!;
|
||||
}
|
||||
// Use some TypeScript internals to avoid code duplication
|
||||
type ObjectLiteralElementWithName = ts.ObjectLiteralElement & { name: ts.PropertyName; parent: ts.ObjectLiteralExpression | ts.JsxAttributes };
|
||||
const getPropertySymbolsFromContextualType: (node: ObjectLiteralElementWithName, checker: ts.TypeChecker, contextualType: ts.Type, unionSymbolOk: boolean) => ReadonlyArray<ts.Symbol> = (<any>ts).getPropertySymbolsFromContextualType;
|
||||
const getContainingObjectLiteralElement: (node: ts.Node) => ObjectLiteralElementWithName | undefined = (<any>ts).getContainingObjectLiteralElement;
|
||||
const getNameFromPropertyName: (name: ts.PropertyName) => string | undefined = (<any>ts).getNameFromPropertyName;
|
||||
|
||||
// Go to the original declaration for cases:
|
||||
//
|
||||
|
@ -733,8 +717,14 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol |
|
|||
}
|
||||
}
|
||||
|
||||
const { parent } = node;
|
||||
|
||||
let symbol = checker.getSymbolAtLocation(node);
|
||||
let importNode: ts.Declaration | null = 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) {
|
||||
|
@ -765,13 +755,21 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol |
|
|||
// pr/*destination*/op1: number
|
||||
// }
|
||||
// bar<Test>(({pr/*goto*/op1})=>{});
|
||||
if (ts.isPropertyName(node) && ts.isBindingElement(node.parent) && ts.isObjectBindingPattern(node.parent.parent) &&
|
||||
(node === (node.parent.propertyName || node.parent.name))) {
|
||||
const type = checker.getTypeAtLocation(node.parent.parent);
|
||||
if (type) {
|
||||
const propSymbols = getPropertySymbolsFromType(type, node);
|
||||
if (propSymbols) {
|
||||
symbol = propSymbols[0];
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -786,10 +784,13 @@ function getRealNodeSymbol(checker: ts.TypeChecker, node: ts.Node): [ts.Symbol |
|
|||
// function Foo(arg: Props) {}
|
||||
// Foo( { pr/*1*/op1: 10, prop2: false })
|
||||
const element = getContainingObjectLiteralElement(node);
|
||||
if (element && checker.getContextualType(element.parent as ts.Expression)) {
|
||||
const propertySymbols = getPropertySymbolsFromContextualType(checker, element);
|
||||
if (propertySymbols) {
|
||||
symbol = propertySymbols[0];
|
||||
if (element) {
|
||||
const contextualType = element && checker.getContextualType(element.parent);
|
||||
if (contextualType) {
|
||||
const propertySymbols = getPropertySymbolsFromContextualType(element, checker, contextualType, /*unionSymbolOk*/ false);
|
||||
if (propertySymbols) {
|
||||
symbol = propertySymbols[0];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -241,7 +241,7 @@ function generateDeclarationFile(out, inputFiles, recipe) {
|
|||
usage.push("var b;");
|
||||
var generateUsageImport = function (moduleId) {
|
||||
var importName = 'm' + (++usageCounter);
|
||||
usageImports.push("import * as " + importName + " from '" + moduleId.replace(/\.d\.ts$/, '') + "';");
|
||||
usageImports.push("import * as " + importName + " from './" + moduleId.replace(/\.d\.ts$/, '') + "';");
|
||||
return importName;
|
||||
};
|
||||
lines.forEach(function (line) {
|
||||
|
|
|
@ -281,7 +281,7 @@ function generateDeclarationFile(out: string, inputFiles: { [file: string]: stri
|
|||
|
||||
const generateUsageImport = (moduleId: string) => {
|
||||
let importName = 'm' + (++usageCounter);
|
||||
usageImports.push(`import * as ${importName} from '${moduleId.replace(/\.d\.ts$/, '')}';`);
|
||||
usageImports.push(`import * as ${importName} from './${moduleId.replace(/\.d\.ts$/, '')}';`);
|
||||
return importName;
|
||||
};
|
||||
|
||||
|
|
|
@ -1,19 +1,19 @@
|
|||
|
||||
// This file is adding references to various symbols which should not be removed via tree shaking
|
||||
|
||||
import { ServiceIdentifier } from 'vs/platform/instantiation/common/instantiation';
|
||||
import { IContextViewService } from 'vs/platform/contextview/browser/contextView';
|
||||
import { IHighlight } from 'vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { IWorkspaceContextService } from 'vs/platform/workspace/common/workspace';
|
||||
import { IEnvironmentService } from 'vs/platform/environment/common/environment';
|
||||
import { CountBadge } from 'vs/base/browser/ui/countBadge/countBadge';
|
||||
import { SimpleWorkerClient, create as create1 } from 'vs/base/common/worker/simpleWorker';
|
||||
import { create as create2 } from 'vs/editor/common/services/editorSimpleWorker';
|
||||
import { QuickOpenWidget } from 'vs/base/parts/quickopen/browser/quickOpenWidget';
|
||||
import { SyncDescriptor0, SyncDescriptor1, SyncDescriptor2, SyncDescriptor3, SyncDescriptor4, SyncDescriptor5, SyncDescriptor6, SyncDescriptor7, SyncDescriptor8 } from 'vs/platform/instantiation/common/descriptors';
|
||||
import { PolyfillPromise } from 'vs/base/common/winjs.polyfill.promise';
|
||||
import { DiffNavigator } from 'vs/editor/browser/widget/diffNavigator';
|
||||
import * as editorAPI from 'vs/editor/editor.api';
|
||||
import { ServiceIdentifier } from './vs/platform/instantiation/common/instantiation';
|
||||
import { IContextViewService } from './vs/platform/contextview/browser/contextView';
|
||||
import { IHighlight } from './vs/base/parts/quickopen/browser/quickOpenModel';
|
||||
import { IWorkspaceContextService } from './vs/platform/workspace/common/workspace';
|
||||
import { IEnvironmentService } from './vs/platform/environment/common/environment';
|
||||
import { CountBadge } from './vs/base/browser/ui/countBadge/countBadge';
|
||||
import { SimpleWorkerClient, create as create1 } from './vs/base/common/worker/simpleWorker';
|
||||
import { create as create2 } from './vs/editor/common/services/editorSimpleWorker';
|
||||
import { QuickOpenWidget } from './vs/base/parts/quickopen/browser/quickOpenWidget';
|
||||
import { SyncDescriptor0, SyncDescriptor1, SyncDescriptor2, SyncDescriptor3, SyncDescriptor4, SyncDescriptor5, SyncDescriptor6, SyncDescriptor7, SyncDescriptor8 } from './vs/platform/instantiation/common/descriptors';
|
||||
import { PolyfillPromise } from './vs/base/common/winjs.polyfill.promise';
|
||||
import { DiffNavigator } from './vs/editor/browser/widget/diffNavigator';
|
||||
import * as editorAPI from './vs/editor/editor.api';
|
||||
|
||||
(function () {
|
||||
var a: any;
|
||||
|
|
6
src/typings/require-monaco.d.ts
vendored
6
src/typings/require-monaco.d.ts
vendored
|
@ -4,7 +4,9 @@
|
|||
*--------------------------------------------------------------------------------------------*/
|
||||
|
||||
interface NodeRequire {
|
||||
(moduleName: string): any;
|
||||
}
|
||||
toUrl(path: string): string;
|
||||
(dependencies: string[], callback: (...args: any[]) => any, errorback?: (err: any) => void): any;
|
||||
config(data: any): any;
|
||||
}
|
||||
|
||||
declare var require: NodeRequire;
|
Loading…
Reference in a new issue