Compare commits
64 commits
main
...
experiment
Author | SHA1 | Date | |
---|---|---|---|
a5b8c3f9a3 | |||
6db601a921 | |||
21574cd8a6 | |||
2a3f802841 | |||
bbfe33f7cd | |||
74ac4c5b1c | |||
686c94cd67 | |||
aa639d3ce7 | |||
be1de23248 | |||
738388050f | |||
9aafff669f | |||
abd46f9f36 | |||
e4bcfd2a5d | |||
2403cc4414 | |||
6e461e330e | |||
2e4975d4a8 | |||
6a61fd295c | |||
3ddfe83386 | |||
6235fe8280 | |||
1c5a595d3f | |||
867f554a9d | |||
f6fcd5c54a | |||
8cb5f78af3 | |||
36fad618f6 | |||
dd998b981f | |||
f15d20b9f2 | |||
380452becb | |||
b73bef89fc | |||
923ec29eb9 | |||
49a3a3f5b2 | |||
14d079e4d7 | |||
5d0797b2e0 | |||
152e3ebc44 | |||
1ba577b88d | |||
38c24798e4 | |||
e984fb80b6 | |||
558fc40303 | |||
92a7bb0462 | |||
7d97d28221 | |||
0b01cb85f3 | |||
3e6214939c | |||
87e146c189 | |||
a484bb7f46 | |||
861a353ec3 | |||
4eb12adff7 | |||
c5673b292d | |||
2de761cce8 | |||
4652f053b1 | |||
f3d310360b | |||
01b34906c7 | |||
fae1d50bd7 | |||
3fe0f31e17 | |||
9c644dadec | |||
b3e9c25e84 | |||
0305d37c9e | |||
c547018e99 | |||
2c1d2184e2 | |||
e5fce042ca | |||
555f36b1e6 | |||
b6207f2f36 | |||
fc51e4574b | |||
a665ef0384 | |||
66d3060210 | |||
474298503d |
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -29,6 +29,8 @@ scripts/configureNightly.js
|
|||
scripts/processDiagnosticMessages.d.ts
|
||||
scripts/processDiagnosticMessages.js
|
||||
scripts/importDefinitelyTypedTests/importDefinitelyTypedTests.js
|
||||
scripts/processTypes.d.ts
|
||||
scripts/processTypes.js
|
||||
src/harness/*.js
|
||||
src/compiler/diagnosticInformationMap.generated.ts
|
||||
src/compiler/diagnosticMessages.generated.json
|
||||
|
|
4
.vscode/settings.json
vendored
Normal file
4
.vscode/settings.json
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
// Place your settings in this file to overwrite default and user settings.
|
||||
{
|
||||
"files.trimTrailingWhitespace": true
|
||||
}
|
325
Jakefile.js
325
Jakefile.js
|
@ -1,5 +1,5 @@
|
|||
// This file contains the build logic for the public repo
|
||||
|
||||
/* global process, jake, task, desc, file, directory, fail, complete */
|
||||
var fs = require("fs");
|
||||
var os = require("os");
|
||||
var path = require("path");
|
||||
|
@ -18,6 +18,7 @@ var docDirectory = "doc/";
|
|||
|
||||
var builtDirectory = "built/";
|
||||
var builtLocalDirectory = "built/local/";
|
||||
var builtScriptsDirectory = "built/scripts/";
|
||||
var LKGDirectory = "lib/";
|
||||
|
||||
var copyright = "CopyrightNotice.txt";
|
||||
|
@ -32,15 +33,27 @@ if (process.env.path !== undefined) {
|
|||
}
|
||||
|
||||
var compilerSources = [
|
||||
"types.ts",
|
||||
"core.ts",
|
||||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"factory.ts",
|
||||
"factory.generated.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"transform.ts",
|
||||
"transforms/destructuring.ts",
|
||||
"transforms/ts.ts",
|
||||
"transforms/module/module.ts",
|
||||
"transforms/module/system.ts",
|
||||
"transforms/module/es6.ts",
|
||||
"transforms/jsx.ts",
|
||||
"transforms/es6.ts",
|
||||
"declarationEmitter.ts",
|
||||
"sourcemap.ts",
|
||||
"printer.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
|
@ -55,11 +68,23 @@ var servicesSources = [
|
|||
"sys.ts",
|
||||
"types.ts",
|
||||
"scanner.ts",
|
||||
"factory.ts",
|
||||
"factory.generated.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"transform.ts",
|
||||
"transforms/destructuring.ts",
|
||||
"transforms/ts.ts",
|
||||
"transforms/module/module.ts",
|
||||
"transforms/module/system.ts",
|
||||
"transforms/module/es6.ts",
|
||||
"transforms/jsx.ts",
|
||||
"transforms/es6.ts",
|
||||
"declarationEmitter.ts",
|
||||
"sourcemap.ts",
|
||||
"printer.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
|
@ -208,25 +233,41 @@ function concatenateFiles(destinationFile, sourceFiles) {
|
|||
}
|
||||
|
||||
var useDebugMode = true;
|
||||
var useTransforms = false;
|
||||
var host = (process.env.host || process.env.TYPESCRIPT_HOST || "node");
|
||||
var compilerFilename = "tsc.js";
|
||||
var LKGCompiler = path.join(LKGDirectory, compilerFilename);
|
||||
var builtLocalCompiler = path.join(builtLocalDirectory, compilerFilename);
|
||||
|
||||
/* Compiles a file from a list of sources
|
||||
* @param outFile: the target file name
|
||||
* @param sources: an array of the names of the source files
|
||||
* @param prereqs: prerequisite tasks to compiling the file
|
||||
* @param prefixes: a list of files to prepend to the target file
|
||||
* @param useBuiltCompiler: true to use the built compiler, false to use the LKG
|
||||
* @param noOutFile: true to compile without using --out
|
||||
* @param generateDeclarations: true to compile using --declaration
|
||||
* @param outDir: true to compile using --outDir
|
||||
* @param keepComments: false to compile using --removeComments
|
||||
* @param callback: a function to execute after the compilation process ends
|
||||
* @param {string} outFile - the target file name
|
||||
* @param {string[]} sources - an array of the names of the source files
|
||||
* @param {string[]} prereqs - prerequisite tasks to compiling the file
|
||||
* @param {object=} opts - Additional options to the compiler
|
||||
* @param {string[]=} opts.prefixes - a list of files to prepend to the target file
|
||||
* @param {boolean=} opts.useBuiltCompiler - true to use the built compiler, false to use the LKG
|
||||
* @param {boolean=} opts.noOutFile - true to compile without using --out
|
||||
* @param {boolean=} opts.generateDeclarations - true to compile using --declaration
|
||||
* @param {boolean=} opts.outDir - true to compile using --outDir
|
||||
* @param {boolean=} opts.keepComments - false to compile using --removeComments
|
||||
* @param {function=} callback - a function to execute after the compilation process ends
|
||||
*/
|
||||
function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOutFile, generateDeclarations, outDir, preserveConstEnums, keepComments, noResolve, stripInternal, callback) {
|
||||
function compileFile(outFile, sources, prereqs, opts, callback) {
|
||||
file(outFile, prereqs, function() {
|
||||
var prefixes = opts && opts.prefixes
|
||||
, useBuiltCompiler = opts && opts.useBuiltCompiler
|
||||
, noOutFile = opts && opts.noOutFile
|
||||
, generateDeclarations = opts && opts.generateDeclarations
|
||||
, outDir = opts && opts.outDir
|
||||
, preserveConstEnums = opts && opts.preserveConstEnums
|
||||
, keepComments = opts && opts.keepComments
|
||||
, noResolve = opts && opts.noResolve
|
||||
, stripInternal = opts && opts.stripInternal
|
||||
, experimentalDecorators = opts && opts.experimentalDecorators
|
||||
, experimentalTransforms = opts && opts.experimentalTransforms
|
||||
, target = opts && opts.target
|
||||
, diagnostics = opts && opts.diagnostics;
|
||||
|
||||
var compilerPath = useBuiltCompiler ? builtLocalCompiler : LKGCompiler;
|
||||
var options = "--noImplicitAny --noEmitOnError --pretty";
|
||||
|
||||
|
@ -264,7 +305,23 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu
|
|||
}
|
||||
|
||||
if (stripInternal) {
|
||||
options += " --stripInternal"
|
||||
options += " --stripInternal";
|
||||
}
|
||||
|
||||
if (experimentalDecorators) {
|
||||
options += " --experimentalDecorators";
|
||||
}
|
||||
|
||||
if (experimentalTransforms || (useBuiltCompiler && useTransforms)) {
|
||||
options += " --experimentalTransforms";
|
||||
}
|
||||
|
||||
if (target) {
|
||||
options += " --target " + target;
|
||||
}
|
||||
|
||||
if (diagnostics) {
|
||||
options += " --diagnostics";
|
||||
}
|
||||
|
||||
var cmd = host + " " + compilerPath + " " + options + " ";
|
||||
|
@ -304,16 +361,16 @@ function compileFile(outFile, sources, prereqs, prefixes, useBuiltCompiler, noOu
|
|||
directory(builtLocalDirectory);
|
||||
|
||||
for (var i in libraryTargets) {
|
||||
(function (i) {
|
||||
var entry = librarySourceMap[i];
|
||||
var target = libraryTargets[i];
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
})(i);
|
||||
concatenateLibraryTargets(librarySourceMap[i], libraryTargets[i]);
|
||||
}
|
||||
|
||||
function concatenateLibraryTargets(entry, target) {
|
||||
var sources = [copyright].concat(entry.sources.map(function (s) {
|
||||
return path.join(libraryDirectory, s);
|
||||
}));
|
||||
file(target, [builtLocalDirectory].concat(sources), function() {
|
||||
concatenateFiles(target, sources);
|
||||
});
|
||||
}
|
||||
|
||||
// Lib target to build the library files
|
||||
|
@ -332,11 +389,9 @@ var builtGeneratedDiagnosticMessagesJSON = path.join(builtLocalDirectory, "diagn
|
|||
file(processDiagnosticMessagesTs);
|
||||
|
||||
// processDiagnosticMessages script
|
||||
compileFile(processDiagnosticMessagesJs,
|
||||
[processDiagnosticMessagesTs],
|
||||
[processDiagnosticMessagesTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
compileFile(processDiagnosticMessagesJs, [processDiagnosticMessagesTs], [processDiagnosticMessagesTs], {
|
||||
useBuiltCompiler: false
|
||||
});
|
||||
|
||||
// The generated diagnostics map; built for the compiler and for the 'generate-diagnostics' task
|
||||
file(diagnosticInfoMapTs, [processDiagnosticMessagesJs, diagnosticMessagesJson], function () {
|
||||
|
@ -365,6 +420,66 @@ file(builtGeneratedDiagnosticMessagesJSON,[generatedDiagnosticMessagesJSON], fun
|
|||
desc("Generates a diagnostic file in TypeScript based on an input JSON file");
|
||||
task("generate-diagnostics", [diagnosticInfoMapTs]);
|
||||
|
||||
// Generate the node factory
|
||||
var processTypesBuiltDirectory = path.join(builtScriptsDirectory, "processTypes");
|
||||
var processTypesJs = path.join(processTypesBuiltDirectory, "processTypes.js");
|
||||
var processTypesDirectory = path.join(scriptsDirectory, "processTypes");
|
||||
var processTypesTs = path.join(processTypesDirectory, "processTypes.ts");
|
||||
var processTypesSources = [
|
||||
"typescript-internal.d.ts",
|
||||
"processTypes.ts",
|
||||
"discovery.ts",
|
||||
"utilities.ts",
|
||||
"types.ts",
|
||||
].map(function (f) {
|
||||
return path.join(processTypesDirectory, f);
|
||||
});
|
||||
var typesTs = path.join(compilerDirectory, "types.ts");
|
||||
var factoryTs = path.join(compilerDirectory, "factory.ts");
|
||||
var utilitiesTs = path.join(compilerDirectory, "utilities.ts");
|
||||
var factoryGeneratedTs = path.join(compilerDirectory, "factory.generated.ts");
|
||||
|
||||
directory(builtScriptsDirectory);
|
||||
directory(processTypesBuiltDirectory);
|
||||
file(processTypesTs);
|
||||
|
||||
// processTypes script
|
||||
compileFile(processTypesJs, processTypesSources, [processTypesBuiltDirectory].concat(processTypesSources), {
|
||||
useBuiltCompiler: false,
|
||||
noOutFile: true,
|
||||
outDir: processTypesBuiltDirectory,
|
||||
target: "es5",
|
||||
experimentalDecorators: true,
|
||||
}, function () {
|
||||
jake.cpR(
|
||||
path.join(processTypesDirectory, "typescript-internal.js"),
|
||||
path.join(builtScriptsDirectory, "processTypes/typescript-internal.js"));
|
||||
});
|
||||
|
||||
// The generated factory; built for the compiler and for the 'generate-factory' task
|
||||
file(factoryGeneratedTs, [processTypesJs, typesTs, factoryTs, utilitiesTs], function() {
|
||||
var cmd = "node " + processTypesJs
|
||||
+ " " + typesTs
|
||||
+ " " + factoryTs
|
||||
+ " " + utilitiesTs;
|
||||
console.log(cmd);
|
||||
var ex = jake.createExec([cmd]);
|
||||
// Add listeners for output and error
|
||||
ex.addListener("stdout", function(output) {
|
||||
process.stdout.write(output);
|
||||
});
|
||||
ex.addListener("stderr", function(error) {
|
||||
process.stderr.write(error);
|
||||
});
|
||||
ex.addListener("cmdEnd", function() {
|
||||
complete();
|
||||
});
|
||||
ex.run();
|
||||
}, { async: true });
|
||||
|
||||
desc("Generates a TypeScript file that contains factory methods to create each Syntax Node.")
|
||||
task("generate-factory", [factoryGeneratedTs]);
|
||||
|
||||
|
||||
// Publish nightly
|
||||
var configureNightlyJs = path.join(scriptsDirectory, "configureNightly.js");
|
||||
|
@ -391,6 +506,10 @@ task("setDebugMode", function() {
|
|||
useDebugMode = true;
|
||||
});
|
||||
|
||||
task("setTransforms", function() {
|
||||
useTransforms = true;
|
||||
});
|
||||
|
||||
task("configure-nightly", [configureNightlyJs], function() {
|
||||
var cmd = host + " " + configureNightlyJs + " " + packageJson + " " + programTs;
|
||||
console.log(cmd);
|
||||
|
@ -432,7 +551,10 @@ task("importDefinitelyTypedTests", [importDefinitelyTypedTestsJs], function () {
|
|||
|
||||
// Local target to build the compiler and services
|
||||
var tscFile = path.join(builtLocalDirectory, compilerFilename);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), [copyright], /*useBuiltCompiler:*/ false);
|
||||
compileFile(tscFile, compilerSources, [builtLocalDirectory, copyright].concat(compilerSources), {
|
||||
prefixes: [copyright],
|
||||
useBuiltCompiler: false
|
||||
});
|
||||
|
||||
var servicesFile = path.join(builtLocalDirectory, "typescriptServices.js");
|
||||
var standaloneDefinitionsFile = path.join(builtLocalDirectory, "typescriptServices.d.ts");
|
||||
|
@ -440,51 +562,51 @@ var nodePackageFile = path.join(builtLocalDirectory, "typescript.js");
|
|||
var nodeDefinitionsFile = path.join(builtLocalDirectory, "typescript.d.ts");
|
||||
var nodeStandaloneDefinitionsFile = path.join(builtLocalDirectory, "typescript_standalone.d.ts");
|
||||
|
||||
compileFile(servicesFile, servicesSources,[builtLocalDirectory, copyright].concat(servicesSources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ true,
|
||||
/*outDir*/ undefined,
|
||||
/*preserveConstEnums*/ true,
|
||||
/*keepComments*/ true,
|
||||
/*noResolve*/ false,
|
||||
/*stripInternal*/ true,
|
||||
/*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
compileFile(servicesFile, servicesSources, [builtLocalDirectory, copyright].concat(servicesSources), {
|
||||
prefixes: [copyright],
|
||||
useBuiltCompiler: true,
|
||||
noOutFile: false,
|
||||
generateDeclarations: true,
|
||||
outDir: undefined,
|
||||
preserveConstEnums: true,
|
||||
keepComments: true,
|
||||
noResolve: false,
|
||||
stripInternal: true
|
||||
}, /*callback*/ function () {
|
||||
jake.cpR(servicesFile, nodePackageFile, {silent: true});
|
||||
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
prependFile(copyright, standaloneDefinitionsFile);
|
||||
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
// Stanalone/web definition file using global 'ts' namespace
|
||||
jake.cpR(standaloneDefinitionsFile, nodeDefinitionsFile, {silent: true});
|
||||
var definitionFileContents = fs.readFileSync(nodeDefinitionsFile).toString();
|
||||
definitionFileContents = definitionFileContents.replace(/^(\s*)(export )?const enum (\S+) {(\s*)$/gm, '$1$2enum $3 {$4');
|
||||
fs.writeFileSync(standaloneDefinitionsFile, definitionFileContents);
|
||||
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
// Official node package definition file, pointed to by 'typings' in package.json
|
||||
// Created by appending 'export = ts;' at the end of the standalone file to turn it into an external module
|
||||
var nodeDefinitionsFileContents = definitionFileContents + "\r\nexport = ts;";
|
||||
fs.writeFileSync(nodeDefinitionsFile, nodeDefinitionsFileContents);
|
||||
|
||||
// Node package definition file to be distributed without the package. Created by replacing
|
||||
// 'ts' namespace with '"typescript"' as a module.
|
||||
var nodeStandaloneDefinitionsFileContents = definitionFileContents.replace(/declare (namespace|module) ts/g, 'declare module "typescript"');
|
||||
fs.writeFileSync(nodeStandaloneDefinitionsFile, nodeStandaloneDefinitionsFileContents);
|
||||
});
|
||||
|
||||
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true);
|
||||
compileFile(serverFile, serverSources,[builtLocalDirectory, copyright].concat(serverSources), {
|
||||
prefixes: [copyright],
|
||||
useBuiltCompiler: true
|
||||
});
|
||||
|
||||
var lsslFile = path.join(builtLocalDirectory, "tslssl.js");
|
||||
compileFile(
|
||||
lsslFile,
|
||||
languageServiceLibrarySources,
|
||||
[builtLocalDirectory, copyright].concat(languageServiceLibrarySources),
|
||||
/*prefixes*/ [copyright],
|
||||
/*useBuiltCompiler*/ true,
|
||||
/*noOutFile*/ false,
|
||||
/*generateDeclarations*/ true);
|
||||
compileFile(lsslFile, languageServiceLibrarySources, [builtLocalDirectory, copyright].concat(languageServiceLibrarySources), {
|
||||
prefixes: [copyright],
|
||||
useBuiltCompiler: true,
|
||||
noOutFile: false,
|
||||
generateDeclarations: true
|
||||
});
|
||||
|
||||
// Local target to build the language service server library
|
||||
desc("Builds language service server library");
|
||||
|
@ -492,11 +614,11 @@ task("lssl", [lsslFile]);
|
|||
|
||||
// Local target to build the compiler and services
|
||||
desc("Builds the full compiler and services");
|
||||
task("local", ["generate-diagnostics", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON]);
|
||||
task("local", ["generate-diagnostics", "generate-factory", "lib", tscFile, servicesFile, nodeDefinitionsFile, serverFile, builtGeneratedDiagnosticMessagesJSON]);
|
||||
|
||||
// Local target to build only tsc.js
|
||||
desc("Builds only the compiler");
|
||||
task("tsc", ["generate-diagnostics", "lib", tscFile]);
|
||||
task("tsc", ["generate-diagnostics", "generate-factory", "lib", tscFile]);
|
||||
|
||||
// Local target to build the compiler and services
|
||||
desc("Sets release mode flag");
|
||||
|
@ -523,11 +645,9 @@ var specMd = path.join(docDirectory, "spec.md");
|
|||
file(word2mdTs);
|
||||
|
||||
// word2md script
|
||||
compileFile(word2mdJs,
|
||||
[word2mdTs],
|
||||
[word2mdTs],
|
||||
[],
|
||||
/*useBuiltCompiler*/ false);
|
||||
compileFile(word2mdJs, [word2mdTs], [word2mdTs], {
|
||||
useBuiltCompiler: false
|
||||
});
|
||||
|
||||
// The generated spec.md; built for the 'generate-spec' task
|
||||
file(specMd, [word2mdJs, specWord], function () {
|
||||
|
@ -571,9 +691,12 @@ directory(builtLocalDirectory);
|
|||
|
||||
// Task to build the tests infrastructure using the built compiler
|
||||
var run = path.join(builtLocalDirectory, "run.js");
|
||||
compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), [], /*useBuiltCompiler:*/ true);
|
||||
compileFile(run, harnessSources, [builtLocalDirectory, tscFile].concat(libraryTargets).concat(harnessSources), {
|
||||
useBuiltCompiler: true,
|
||||
diagnostics: true
|
||||
});
|
||||
|
||||
var internalTests = "internal/"
|
||||
var internalTests = "internal/";
|
||||
|
||||
var localBaseline = "tests/baselines/local/";
|
||||
var refBaseline = "tests/baselines/reference/";
|
||||
|
@ -645,10 +768,10 @@ function deleteTemporaryProjectOutput() {
|
|||
function runConsoleTests(defaultReporter, defaultSubsets, postLint) {
|
||||
cleanTestDirs();
|
||||
var debug = process.env.debug || process.env.d;
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
if (fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
|
||||
|
@ -660,9 +783,9 @@ function runConsoleTests(defaultReporter, defaultSubsets, postLint) {
|
|||
testTimeout = 100000;
|
||||
}
|
||||
|
||||
colors = process.env.colors || process.env.color
|
||||
var colors = process.env.colors || process.env.color
|
||||
colors = colors ? ' --no-colors ' : ' --colors ';
|
||||
reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
var reporter = process.env.reporter || process.env.r || defaultReporter;
|
||||
|
||||
// timeout normally isn't necessary but Travis-CI has been timing out on compiler baselines occasionally
|
||||
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
|
||||
|
@ -714,9 +837,12 @@ task("generate-code-coverage", ["tests", builtLocalDirectory], function () {
|
|||
}, { async: true });
|
||||
|
||||
// Browser tests
|
||||
var nodeServerOutFile = 'tests/webTestServer.js'
|
||||
var nodeServerInFile = 'tests/webTestServer.ts'
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], [], /*useBuiltCompiler:*/ true, /*noOutFile*/ true);
|
||||
var nodeServerOutFile = 'tests/webTestServer.js';
|
||||
var nodeServerInFile = 'tests/webTestServer.ts';
|
||||
compileFile(nodeServerOutFile, [nodeServerInFile], [builtLocalDirectory, tscFile], {
|
||||
useBuiltCompiler: true,
|
||||
noOutFile: true
|
||||
});
|
||||
|
||||
desc("Runs browserify on run.js to produce a file suitable for running tests in the browser");
|
||||
task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function() {
|
||||
|
@ -727,27 +853,27 @@ task("browserify", ["tests", builtLocalDirectory, nodeServerOutFile], function()
|
|||
desc("Runs the tests using the built run.js file like 'jake runtests'. Syntax is jake runtests-browser. Additional optional parameters tests=[regex], port=, browser=[chrome|IE]");
|
||||
task("runtests-browser", ["tests", "browserify", builtLocalDirectory], function() {
|
||||
cleanTestDirs();
|
||||
host = "node"
|
||||
port = process.env.port || process.env.p || '8888';
|
||||
browser = process.env.browser || process.env.b || "IE";
|
||||
tests = process.env.test || process.env.tests || process.env.t;
|
||||
var host = "node";
|
||||
var port = process.env.port || process.env.p || '8888';
|
||||
var browser = process.env.browser || process.env.b || "IE";
|
||||
var tests = process.env.test || process.env.tests || process.env.t;
|
||||
var light = process.env.light || false;
|
||||
var testConfigFile = 'test.config';
|
||||
if(fs.existsSync(testConfigFile)) {
|
||||
if (fs.existsSync(testConfigFile)) {
|
||||
fs.unlinkSync(testConfigFile);
|
||||
}
|
||||
if(tests || light) {
|
||||
if (tests || light) {
|
||||
writeTestConfigFile(tests, light, testConfigFile);
|
||||
}
|
||||
|
||||
tests = tests ? tests : '';
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests
|
||||
var cmd = host + " tests/webTestServer.js " + port + " " + browser + " " + tests;
|
||||
console.log(cmd);
|
||||
exec(cmd);
|
||||
}, {async: true});
|
||||
|
||||
function getDiffTool() {
|
||||
var program = process.env['DIFF']
|
||||
var program = process.env['DIFF'];
|
||||
if (!program) {
|
||||
fail("Add the 'DIFF' environment variable to the path of the program you want to use.");
|
||||
}
|
||||
|
@ -805,7 +931,9 @@ task("baseline-accept-test262", function() {
|
|||
// Webhost
|
||||
var webhostPath = "tests/webhost/webtsc.ts";
|
||||
var webhostJsPath = "tests/webhost/webtsc.js";
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), [], /*useBuiltCompiler*/true);
|
||||
compileFile(webhostJsPath, [webhostPath], [tscFile, webhostPath].concat(libraryTargets), {
|
||||
useBuiltCompiler: true
|
||||
});
|
||||
|
||||
desc("Builds the tsc web host");
|
||||
task("webhost", [webhostJsPath], function() {
|
||||
|
@ -815,7 +943,10 @@ task("webhost", [webhostJsPath], function() {
|
|||
// Perf compiler
|
||||
var perftscPath = "tests/perftsc.ts";
|
||||
var perftscJsPath = "built/local/perftsc.js";
|
||||
compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
compileFile(perftscJsPath, [perftscPath], [tscFile, perftscPath, "tests/perfsys.ts"].concat(libraryTargets), {
|
||||
useBuiltCompiler: true
|
||||
});
|
||||
|
||||
desc("Builds augmented version of the compiler for perf tests");
|
||||
task("perftsc", [perftscJsPath]);
|
||||
|
||||
|
@ -839,7 +970,9 @@ file(loggedIOJsPath, [builtLocalDirectory, loggedIOpath], function() {
|
|||
|
||||
var instrumenterPath = harnessDirectory + 'instrumenter.ts';
|
||||
var instrumenterJsPath = builtLocalDirectory + 'instrumenter.js';
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), [], /*useBuiltCompiler*/ true);
|
||||
compileFile(instrumenterJsPath, [instrumenterPath], [tscFile, instrumenterPath].concat(libraryTargets), {
|
||||
useBuiltCompiler: true
|
||||
});
|
||||
|
||||
desc("Builds an instrumented tsc.js");
|
||||
task('tsc-instrumented', [loggedIOJsPath, instrumenterJsPath, tscFile], function() {
|
||||
|
@ -875,7 +1008,7 @@ var tslintRulesOutFiles = tslintRules.map(function(p) {
|
|||
desc("Compiles tslint rules to js");
|
||||
task("build-rules", tslintRulesOutFiles);
|
||||
tslintRulesFiles.forEach(function(ruleFile, i) {
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
|
||||
compileFile(tslintRulesOutFiles[i], [ruleFile], [ruleFile], [], /*useBuiltCompiler*/ false, /*noOutFile*/ true, /*generateDeclarations*/ false, path.join(builtLocalDirectory, "tslint"));
|
||||
});
|
||||
|
||||
function getLinterOptions() {
|
||||
|
@ -937,7 +1070,7 @@ function lintWatchFile(filename) {
|
|||
if (event !== "change") {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (!lintSemaphores[filename]) {
|
||||
lintSemaphores[filename] = true;
|
||||
lintFileAsync(getLinterOptions(), filename, function(err, result) {
|
||||
|
|
2144
lib/typescript_standalone.d.ts
vendored
Normal file
2144
lib/typescript_standalone.d.ts
vendored
Normal file
File diff suppressed because it is too large
Load diff
552
scripts/processTypes/discovery.ts
Normal file
552
scripts/processTypes/discovery.ts
Normal file
|
@ -0,0 +1,552 @@
|
|||
import { SyntaxKind, Symbol, SymbolFlags, Map, } from "./typescript-internal";
|
||||
import { hasProperty, getProperty } from "./utilities";
|
||||
import { getType, getTypes, makeArrayType, resolveQualifiedName, annotation, EnumValue, Annotation, AnnotationTargets, TypeInfo, PropertyInfo } from "./types";
|
||||
|
||||
export interface DiscoveryResult {
|
||||
createableNodes: SyntaxNode[];
|
||||
updateableNodes: SyntaxNode[];
|
||||
testableNodes: SyntaxNode[];
|
||||
testableTypes: SyntaxType[];
|
||||
}
|
||||
|
||||
export interface SyntaxType {
|
||||
type: TypeInfo;
|
||||
typeName: string;
|
||||
syntaxNodes?: SyntaxNode[];
|
||||
testFunctionName?: string;
|
||||
}
|
||||
|
||||
export interface SyntaxNode {
|
||||
kind: SyntaxKind;
|
||||
kindName: string;
|
||||
typeName: string;
|
||||
createFunctionName: string;
|
||||
createParameters: SyntaxMember[];
|
||||
updateFunctionName: string;
|
||||
updateParameters: SyntaxMember[];
|
||||
testFunctionName: string;
|
||||
}
|
||||
|
||||
export interface SyntaxMember {
|
||||
propertyName?: string;
|
||||
parameterName?: string;
|
||||
parameterTypeName: string;
|
||||
isFactoryParameter?: boolean;
|
||||
isNodeArray?: boolean;
|
||||
isModifiersArray?: boolean;
|
||||
testFunctionName?: string;
|
||||
visitorFunctionName?: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Discovers type information and symbols for various SyntaxNodes
|
||||
*/
|
||||
export function discover(): DiscoveryResult {
|
||||
const typesReferencedByProperties: boolean[] = [];
|
||||
const syntaxTypeForTypeInfo: SyntaxType[] = [];
|
||||
const syntaxNodesForType: SyntaxNode[][] = [];
|
||||
const syntaxNodesForTypeFlat: SyntaxNode[][] = [];
|
||||
const createableNodes: SyntaxNode[] = [];
|
||||
const updateableNodes: SyntaxNode[] = [];
|
||||
const testableNodes: SyntaxNode[] = [];
|
||||
const syntaxTypes: SyntaxType[] = [];
|
||||
const testableTypes: SyntaxType[] = [];
|
||||
const localNames: Map<string> = {};
|
||||
|
||||
let types = getTypes("ts");
|
||||
let nodeType = getType("ts.Node");
|
||||
let modifierType = getType("ts.Modifier");
|
||||
let statementType = getType("ts.Statement");
|
||||
let conciseBodyType = getType("ts.ConciseBody");
|
||||
let functionBodyType = getType("ts.FunctionBody");
|
||||
let moduleBodyType = getType("ts.ModuleBody");
|
||||
let sourceFileType = getType("ts.SourceFile");
|
||||
let nodeArrayType = getType("ts.NodeArray");
|
||||
let modifiersArrayType = getType("ts.ModifiersArray");
|
||||
|
||||
for (let type of types) {
|
||||
discoverType(type);
|
||||
}
|
||||
|
||||
for (let type of syntaxTypes) {
|
||||
discoverTestableType(type);
|
||||
}
|
||||
|
||||
createableNodes.sort((a, b) => a.kind - b.kind);
|
||||
updateableNodes.sort((a, b) => a.kind - b.kind);
|
||||
testableNodes.sort((a, b) => a.kind - b.kind);
|
||||
testableTypes.sort((a, b) => a.toString().localeCompare(b.toString()));
|
||||
|
||||
return { createableNodes, updateableNodes, testableNodes, testableTypes };
|
||||
|
||||
function discoverType(type: TypeInfo) {
|
||||
let syntaxType = syntaxTypeForTypeInfo[type.id];
|
||||
if (!syntaxType) {
|
||||
if (nodeType.isAssignableFrom(type)) {
|
||||
let typeName = type.toString();
|
||||
|
||||
syntaxType = {
|
||||
type,
|
||||
typeName,
|
||||
};
|
||||
|
||||
syntaxTypes.push(syntaxType);
|
||||
syntaxTypeForTypeInfo[type.id] = syntaxType;
|
||||
|
||||
for (let superType of type.getSuperTypes()) {
|
||||
discoverType(superType);
|
||||
}
|
||||
|
||||
for (let kind of type.findAllAnnotations(/*inherited*/ false, KindAnnotation.match)) {
|
||||
discoverKind(type, kind);
|
||||
}
|
||||
}
|
||||
}
|
||||
return syntaxType;
|
||||
}
|
||||
|
||||
function discoverKind(type: TypeInfo, kind: KindAnnotation) {
|
||||
let kindName = kind.kindSymbol.name;
|
||||
let typeName = type.toString();
|
||||
let createFunctionName = discoverFunctionName(kindName, "create", kind.create);
|
||||
let createParameters: SyntaxMember[] = createFunctionName ? [] : undefined;
|
||||
let updateFunctionName = discoverFunctionName(kindName, "update", kind.update);
|
||||
let updateParameters: SyntaxMember[] = updateFunctionName ? [] : undefined;
|
||||
let testFunctionName = discoverFunctionName(kindName, "is", kind.test);
|
||||
if (type.name === "StringLiteral") {
|
||||
debugger;
|
||||
}
|
||||
for (let property of type.getProperties(/*inherited*/ true)) {
|
||||
if (FactoryHiddenAnnotation.getState(type, property.name) === FactoryHiddenState.Hidden) {
|
||||
continue;
|
||||
}
|
||||
|
||||
let isFactoryParameter = property.findFirstAnnotation(/*inherited*/ true, FactoryParamAnnotation.match) !== undefined;
|
||||
let isNode = nodeType.isAssignableFrom(property.propertyType);
|
||||
let isModifiersArray = modifiersArrayType.isAssignableFrom(property.propertyType);
|
||||
let isNodeArray = !isModifiersArray && nodeArrayType.isAssignableFrom(property.propertyType);
|
||||
if (isFactoryParameter || isNode || isNodeArray || isModifiersArray) {
|
||||
let propertyName = property.name;
|
||||
let parameterName = property.name === "arguments" ? "_arguments" : property.name;
|
||||
let parameterType: TypeInfo;
|
||||
let elementType: TypeInfo;
|
||||
if (isModifiersArray) {
|
||||
elementType = modifierType;
|
||||
parameterType = makeArrayType(elementType);
|
||||
}
|
||||
else if (isNodeArray) {
|
||||
elementType = property.propertyType.getGenericTypeArguments()[0];
|
||||
parameterType = makeArrayType(elementType);
|
||||
}
|
||||
else if (isNode) {
|
||||
elementType = property.propertyType;
|
||||
parameterType = elementType;
|
||||
}
|
||||
else {
|
||||
parameterType = property.propertyType;
|
||||
}
|
||||
|
||||
if (elementType) {
|
||||
typesReferencedByProperties[elementType.id] = true;
|
||||
discoverType(elementType);
|
||||
}
|
||||
|
||||
let parameterTypeName = parameterType.toString();
|
||||
let testFunctionName: string;
|
||||
let visitorFunctionName: string;
|
||||
if (!isFactoryParameter) {
|
||||
switch (property.propertyType) {
|
||||
case nodeType: break;
|
||||
case statementType: visitorFunctionName = "transformer.visitStatement"; break;
|
||||
case conciseBodyType: visitorFunctionName = "transformer.visitConciseBody"; break;
|
||||
case functionBodyType: visitorFunctionName = "transformer.visitFunctionBody"; break;
|
||||
case moduleBodyType: visitorFunctionName = "transformer.visitModuleBody"; break;
|
||||
case sourceFileType: visitorFunctionName = "transformer.visitSourceFile"; break;
|
||||
default:
|
||||
if (isModifiersArray || isNodeArray) {
|
||||
visitorFunctionName = "transformer.visitNodes";
|
||||
visitorFunctionName = "transformer.visitNodes";
|
||||
}
|
||||
else if (isNode) {
|
||||
visitorFunctionName = "transformer.visitNode";
|
||||
}
|
||||
|
||||
if (isModifiersArray) {
|
||||
testFunctionName = "isModifier";
|
||||
}
|
||||
else if (isNodeArray || isNode) {
|
||||
testFunctionName = getIsAnyNodeFunctionName(elementType);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
let syntaxMember = {
|
||||
propertyName,
|
||||
parameterName,
|
||||
parameterTypeName,
|
||||
isFactoryParameter,
|
||||
isNodeArray,
|
||||
isModifiersArray,
|
||||
testFunctionName,
|
||||
visitorFunctionName
|
||||
};
|
||||
|
||||
if (createFunctionName) {
|
||||
createParameters.push(syntaxMember);
|
||||
}
|
||||
|
||||
if (updateFunctionName && !isFactoryParameter) {
|
||||
updateParameters.push(syntaxMember);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let factoryOrder = type.findFirstAnnotation(/*inherited*/ true, FactoryOrderAnnotation.match);
|
||||
if (factoryOrder) {
|
||||
if (createFunctionName) {
|
||||
createParameters = sortMembers(createParameters, factoryOrder.propertyNames);
|
||||
}
|
||||
|
||||
if (updateFunctionName) {
|
||||
updateParameters = sortMembers(updateParameters, factoryOrder.propertyNames);
|
||||
}
|
||||
}
|
||||
|
||||
let syntaxNode = {
|
||||
kind: kind.kind,
|
||||
kindName,
|
||||
typeName,
|
||||
createFunctionName,
|
||||
createParameters,
|
||||
updateFunctionName,
|
||||
updateParameters,
|
||||
testFunctionName
|
||||
};
|
||||
|
||||
if (createFunctionName) {
|
||||
createableNodes.push(syntaxNode);
|
||||
localNames[createFunctionName] = createFunctionName;
|
||||
}
|
||||
|
||||
if (updateFunctionName && updateParameters.length > 0) {
|
||||
updateableNodes.push(syntaxNode);
|
||||
localNames[updateFunctionName] = updateFunctionName;
|
||||
}
|
||||
|
||||
if (testFunctionName) {
|
||||
testableNodes.push(syntaxNode);
|
||||
localNames[testFunctionName] = testFunctionName;
|
||||
}
|
||||
|
||||
let typeNodes = syntaxNodesForType[type.id] || (syntaxNodesForType[type.id] = []);
|
||||
typeNodes.push(syntaxNode);
|
||||
return syntaxNode;
|
||||
}
|
||||
|
||||
function sortMembers(members: SyntaxMember[], order: string[]) {
|
||||
let indices = members.map((_, i) => i);
|
||||
indices.sort((a, b) => {
|
||||
let aOverride = order.indexOf(members[a].propertyName);
|
||||
let bOverride = order.indexOf(members[b].propertyName);
|
||||
if (aOverride >= 0) {
|
||||
if (bOverride >= 0) {
|
||||
return aOverride - bOverride;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
else if (bOverride >= 0) {
|
||||
return +1;
|
||||
}
|
||||
|
||||
return a - b;
|
||||
});
|
||||
|
||||
return indices.map(i => members[i]);
|
||||
}
|
||||
|
||||
function discoverFunctionName(kindName: string, prefix: string, option: boolean | string) {
|
||||
if (typeof option === "string") {
|
||||
return option;
|
||||
}
|
||||
else if (option) {
|
||||
let functionName = prefix + kindName;
|
||||
if (!hasProperty(localNames, functionName)) {
|
||||
let symbol = resolveQualifiedName("ts." + functionName, SymbolFlags.Function);
|
||||
if (!symbol) {
|
||||
return functionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getIsAnyNodeFunctionName(type: TypeInfo) {
|
||||
if (type !== nodeType) {
|
||||
let functionName: string;
|
||||
let nodeTest = type.findFirstAnnotation(/*inherited*/ false, NodeTestAnnotation.match);
|
||||
if (nodeTest) {
|
||||
return nodeTest.functionName;
|
||||
}
|
||||
else if (type.isTypeAlias || type.isInterface) {
|
||||
return "is" + getKindOrTypeNameForType(type);
|
||||
}
|
||||
else if (type.isUnionType) {
|
||||
return "is" + type.getConstituentTypes().map(getKindOrTypeNameForType).join("Or");
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function discoverTestableType(syntaxType: SyntaxType) {
|
||||
if (syntaxType.type !== nodeType && !syntaxType.syntaxNodes) {
|
||||
syntaxType.syntaxNodes = discoverSyntaxNodes(syntaxType.type);
|
||||
if (syntaxType.syntaxNodes.length > 0) {
|
||||
let testFunctionName = discoverIsAnyNodeFunctionName(syntaxType.type);
|
||||
if (testFunctionName) {
|
||||
syntaxType.testFunctionName = testFunctionName;
|
||||
testableTypes.push(syntaxType);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
// EntityName is a union type of Identifier | QualifiedName.
|
||||
// We want anything that can be an identifier and anything that can be a qualified name.
|
||||
isEntityName(node: Node): node is EntityName {
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
function discoverSyntaxNodes(type: TypeInfo) {
|
||||
let syntaxNodesFlat = syntaxNodesForTypeFlat[type.id];
|
||||
if (!syntaxNodesFlat) {
|
||||
syntaxNodesFlat = syntaxNodesForTypeFlat[type.id] = [];
|
||||
|
||||
let seen: boolean[] = [];
|
||||
copySyntaxNodes(syntaxNodesForType[type.id], syntaxNodesFlat, seen);
|
||||
|
||||
if (type.isTypeAlias) {
|
||||
let aliasedType = type.getAliasedType();
|
||||
copySyntaxNodes(discoverSyntaxNodes(aliasedType), syntaxNodesFlat, seen);
|
||||
}
|
||||
else if (type.isInterface) {
|
||||
for (let subType of type.getSubTypes()) {
|
||||
copySyntaxNodes(discoverSyntaxNodes(subType), syntaxNodesFlat, seen);
|
||||
}
|
||||
}
|
||||
else if (type.isUnionType) {
|
||||
for (let constituentType of type.getConstituentTypes()) {
|
||||
copySyntaxNodes(discoverSyntaxNodes(constituentType), syntaxNodesFlat, seen);
|
||||
}
|
||||
}
|
||||
}
|
||||
return syntaxNodesFlat;
|
||||
}
|
||||
|
||||
function copySyntaxNodes(source: SyntaxNode[], dest: SyntaxNode[], seen: boolean[]) {
|
||||
if (source) {
|
||||
for (let syntaxNode of source) {
|
||||
if (!seen[syntaxNode.kind]) {
|
||||
seen[syntaxNode.kind] = true;
|
||||
dest.push(syntaxNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function discoverIsAnyNodeFunctionName(type: TypeInfo) {
|
||||
if (typesReferencedByProperties[type.id]) {
|
||||
let functionName = getIsAnyNodeFunctionName(type);
|
||||
if (functionName && !hasProperty(localNames, functionName)) {
|
||||
let symbol = resolveQualifiedName("ts." + functionName, SymbolFlags.Function);
|
||||
if (!symbol) {
|
||||
localNames[functionName] = functionName;
|
||||
return functionName;
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getKindOrTypeNameForType(type: TypeInfo) {
|
||||
let kinds = type.findAllAnnotations(/*inherited*/ false, KindAnnotation.match);
|
||||
if (kinds.length === 1) {
|
||||
return kinds[0].kindSymbol.name;
|
||||
}
|
||||
|
||||
return type.name;
|
||||
}
|
||||
}
|
||||
|
||||
export interface KindOptions {
|
||||
create: boolean | string;
|
||||
update: boolean | string;
|
||||
test: boolean | string;
|
||||
}
|
||||
|
||||
@annotation("kind", { inherited: false, targets: AnnotationTargets.Interface })
|
||||
export class KindAnnotation extends Annotation {
|
||||
public kind: SyntaxKind;
|
||||
public kindSymbol: Symbol;
|
||||
public create: boolean | string;
|
||||
public update: boolean | string;
|
||||
public test: boolean | string;
|
||||
|
||||
constructor([{ value, symbol }, { create = true, update = true, test = true } = <KindOptions>{}, ..._arguments]: [EnumValue<SyntaxKind>, KindOptions, any]) {
|
||||
super(_arguments);
|
||||
this.kind = value;
|
||||
this.kindSymbol = symbol;
|
||||
this.create = create;
|
||||
this.update = update;
|
||||
this.test = test;
|
||||
}
|
||||
|
||||
public static match(annotation: Annotation): annotation is KindAnnotation {
|
||||
return annotation instanceof KindAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
export const enum FactoryHiddenState {
|
||||
None,
|
||||
Hidden,
|
||||
Visible
|
||||
}
|
||||
|
||||
@annotation("factoryhidden", { inherited: true, allowMultiple: true, targets: AnnotationTargets.Interface | AnnotationTargets.Property })
|
||||
export class FactoryHiddenAnnotation extends Annotation {
|
||||
public propertyName: string;
|
||||
public hidden: boolean;
|
||||
constructor([ propertyName, hidden, ..._arguments]: [string | boolean, boolean, any]) {
|
||||
super(_arguments);
|
||||
if (typeof propertyName === "boolean") {
|
||||
this.hidden = propertyName;
|
||||
}
|
||||
else if (typeof propertyName === "string") {
|
||||
this.propertyName = propertyName;
|
||||
if (typeof hidden === "boolean") {
|
||||
this.hidden = hidden;
|
||||
}
|
||||
else {
|
||||
this.hidden = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
this.hidden = true;
|
||||
}
|
||||
}
|
||||
|
||||
public static getState(type: TypeInfo, propertyName?: string) {
|
||||
if (propertyName) {
|
||||
return this.getStateForProperty(type, propertyName);
|
||||
}
|
||||
else {
|
||||
return this.getStateForType(type);
|
||||
}
|
||||
}
|
||||
|
||||
private static getStateForProperty(type: TypeInfo, propertyName: string) {
|
||||
let factoryHiddenState = FactoryHiddenState.None;
|
||||
let inheritedTypes: TypeInfo[] = [type];
|
||||
while (factoryHiddenState === FactoryHiddenState.None && inheritedTypes.length) {
|
||||
[factoryHiddenState, inheritedTypes] = this.getStateForPropertyBreadthFirst(inheritedTypes, propertyName);
|
||||
}
|
||||
return factoryHiddenState;
|
||||
}
|
||||
|
||||
private static getStateForPropertyBreadthFirst(types: TypeInfo[], propertyName: string): [FactoryHiddenState, TypeInfo[]] {
|
||||
let inheritedTypes: TypeInfo[] = [];
|
||||
let factoryHidden: FactoryHiddenAnnotation;
|
||||
let factoryHiddenState: FactoryHiddenState = FactoryHiddenState.None;
|
||||
for (let type of types) {
|
||||
let property = type.getProperty(propertyName, /*inherited*/ false);
|
||||
if (property) {
|
||||
if (factoryHidden = property.findFirstAnnotation(/*inherited*/ false, FactoryHiddenAnnotation.match)) {
|
||||
factoryHiddenState = factoryHidden.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (factoryHidden = type.findFirstAnnotation(/*inherited*/ false, FactoryHiddenAnnotation.matchProperty(propertyName))) {
|
||||
factoryHiddenState = factoryHidden.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible;
|
||||
break;
|
||||
}
|
||||
|
||||
if (property) {
|
||||
factoryHiddenState = FactoryHiddenState.Visible;
|
||||
break;
|
||||
}
|
||||
|
||||
if (type.isInterface) {
|
||||
inheritedTypes = inheritedTypes.concat(type.getSuperTypes());
|
||||
}
|
||||
else if (type.isTypeAlias) {
|
||||
inheritedTypes.push(type.getAliasedType());
|
||||
}
|
||||
else if (type.isUnionType) {
|
||||
inheritedTypes = inheritedTypes.concat(type.getConstituentTypes());
|
||||
}
|
||||
}
|
||||
|
||||
return [factoryHiddenState, inheritedTypes];
|
||||
}
|
||||
|
||||
private static getStateForType(type: TypeInfo) {
|
||||
let annotation = type.findFirstAnnotation(/*inherited*/ false, this.matchProperty(undefined));
|
||||
return annotation ? annotation.hidden ? FactoryHiddenState.Hidden : FactoryHiddenState.Visible : FactoryHiddenState.None;
|
||||
}
|
||||
|
||||
public static matchProperty(propertyName: string): (annotation: Annotation) => annotation is FactoryHiddenAnnotation {
|
||||
return (annotation): annotation is FactoryHiddenAnnotation => this.match(annotation) && annotation.propertyName === propertyName;
|
||||
}
|
||||
|
||||
public static match(annotation: Annotation): annotation is FactoryHiddenAnnotation {
|
||||
return annotation instanceof FactoryHiddenAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
@annotation("factoryorder", { inherited: true, targets: AnnotationTargets.Interface })
|
||||
export class FactoryOrderAnnotation extends Annotation {
|
||||
public propertyNames: string[];
|
||||
constructor(propertyNames: string[]) {
|
||||
super([]);
|
||||
this.propertyNames = propertyNames;
|
||||
}
|
||||
|
||||
public static match(annotation: Annotation): annotation is FactoryOrderAnnotation {
|
||||
return annotation instanceof FactoryOrderAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
@annotation("factoryparam", { inherited: true, allowMultiple: true, targets: AnnotationTargets.Interface | AnnotationTargets.Property })
|
||||
export class FactoryParamAnnotation extends Annotation {
|
||||
public propertyName: string;
|
||||
constructor([propertyName, ..._arguments]: [string, any]) {
|
||||
super(_arguments);
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public static matchProperty(propertyName: string): (annotation: Annotation) => annotation is FactoryParamAnnotation {
|
||||
return (annotation): annotation is FactoryParamAnnotation => this.match(annotation) && annotation.propertyName === propertyName;
|
||||
}
|
||||
|
||||
public static match(annotation: Annotation): annotation is FactoryParamAnnotation {
|
||||
return annotation instanceof FactoryParamAnnotation;
|
||||
}
|
||||
}
|
||||
|
||||
@annotation("nodetest", { inherited: false, allowMultiple: false, targets: AnnotationTargets.Interface | AnnotationTargets.TypeAlias })
|
||||
export class NodeTestAnnotation extends Annotation {
|
||||
public functionName: string;
|
||||
constructor([functionName, ..._arguments]: [string, any]) {
|
||||
super(_arguments);
|
||||
this.functionName = functionName
|
||||
}
|
||||
|
||||
public static match(annotation: Annotation): annotation is NodeTestAnnotation {
|
||||
return annotation instanceof NodeTestAnnotation;
|
||||
}
|
||||
}
|
101
scripts/processTypes/processTypes.ts
Normal file
101
scripts/processTypes/processTypes.ts
Normal file
|
@ -0,0 +1,101 @@
|
|||
import { sys, getDefaultCompilerOptions, createProgram, createCompilerHost } from "./typescript-internal";
|
||||
import { loadSourceFiles } from "./types";
|
||||
import { discover, DiscoveryResult } from "./discovery";
|
||||
import { combinePaths } from "./utilities";
|
||||
|
||||
declare var global: any, require: any;
|
||||
if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') {
|
||||
try {
|
||||
require("source-map-support").install();
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
|
||||
main();
|
||||
|
||||
function main() {
|
||||
if (sys.args.length < 3) {
|
||||
sys.write("Usage:" + sys.newLine)
|
||||
sys.write("\tnode processTypes.js <types-ts-input-file> <factory-ts-input-file> <utilities-ts-input-file>" + sys.newLine);
|
||||
return;
|
||||
}
|
||||
|
||||
const typesTsFileName = sys.resolvePath(sys.args[0]);
|
||||
const factoryTsFileName = sys.resolvePath(sys.args[1]);
|
||||
const utilitiesTsFileName = sys.resolvePath(sys.args[2]);
|
||||
|
||||
loadSourceFiles([
|
||||
/*typesTsFileName*/ sys.resolvePath(sys.args[0]),
|
||||
/*factoryTsFileName*/ sys.resolvePath(sys.args[1]),
|
||||
/*utilitiesTsFileName*/ sys.resolvePath(sys.args[2])
|
||||
]);
|
||||
|
||||
// Discover syntax nodes
|
||||
const discovery = discover();
|
||||
|
||||
// Emit the generated factory output file
|
||||
const factoryDirectory = sys.resolvePath(combinePaths(factoryTsFileName, ".."));
|
||||
const factoryOutputFile = combinePaths(factoryDirectory, "factory.generated.ts");
|
||||
const factoryOutput = generateFactory(discovery);
|
||||
sys.writeFile(factoryOutputFile, factoryOutput);
|
||||
}
|
||||
|
||||
export function generateFactory(discovery: DiscoveryResult) {
|
||||
return `
|
||||
// <auto-generated />
|
||||
/// <reference path="factory.ts" />
|
||||
namespace ts {${each(discovery.createableNodes, syntaxNode => `
|
||||
export function ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member => `${member.parameterName}?: ${member.parameterTypeName}, `)}location?: TextRange, flags?: NodeFlags): ${syntaxNode.typeName} {
|
||||
let node = createNode<${syntaxNode.typeName}>(SyntaxKind.${syntaxNode.kindName}, location, flags); ${each(syntaxNode.createParameters, member => `
|
||||
if (${member.parameterName}) ${
|
||||
member.isModifiersArray
|
||||
? `setModifiers(node, ${member.parameterName});`
|
||||
: member.isNodeArray
|
||||
? `node.${member.propertyName} = createNodeArray(${member.parameterName});`
|
||||
: `node.${member.propertyName} = ${member.parameterName};`
|
||||
}`)}
|
||||
return node;
|
||||
}`)}${each(discovery.updateableNodes, syntaxNode => `
|
||||
export function ${syntaxNode.updateFunctionName}(node: ${syntaxNode.typeName}${each(syntaxNode.updateParameters, member => `, ${member.parameterName}: ${member.parameterTypeName}`)}): ${syntaxNode.typeName} {
|
||||
if (${each(syntaxNode.updateParameters, member => `${member.parameterName} !== node.${member.propertyName}`, ` || `)}) {
|
||||
let newNode = ${syntaxNode.createFunctionName}(${each(syntaxNode.createParameters, member =>
|
||||
member.isFactoryParameter
|
||||
? `node.${member.propertyName}`
|
||||
: member.parameterName, `, `)});
|
||||
return updateFrom(node, newNode);
|
||||
}
|
||||
return node;
|
||||
}`)}${each(discovery.testableNodes, syntaxNode => `
|
||||
export function ${syntaxNode.testFunctionName}(node: Node): node is ${syntaxNode.typeName} {
|
||||
return node && node.kind === SyntaxKind.${syntaxNode.kindName};
|
||||
}`)}${each(discovery.testableTypes, syntaxType => `
|
||||
export function ${syntaxType.testFunctionName}(node: Node): node is ${syntaxType.typeName} {
|
||||
if (node) {
|
||||
switch (node.kind) {${each(syntaxType.syntaxNodes, syntaxNode => `
|
||||
case SyntaxKind.${syntaxNode.kindName}:`)}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}`)}
|
||||
export function acceptTransformer(transformer: Transformer, node: Node, visitor: (node: Node, write: (node: Node) => void) => void): Node {
|
||||
if (node) {
|
||||
switch (node.kind) {${each(discovery.updateableNodes, syntaxNode => `
|
||||
case SyntaxKind.${syntaxNode.kindName}:
|
||||
return ${syntaxNode.updateFunctionName}(<${syntaxNode.typeName}>node${each(syntaxNode.updateParameters, member =>
|
||||
member.visitorFunctionName && member.testFunctionName
|
||||
? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor, ${member.testFunctionName})`
|
||||
: member.visitorFunctionName
|
||||
? `, ${member.visitorFunctionName}((<${syntaxNode.typeName}>node).${member.propertyName}, visitor)`
|
||||
: `, (<${syntaxNode.typeName}>node).${member.propertyName}`
|
||||
)});`)}
|
||||
}
|
||||
}
|
||||
return node;
|
||||
}
|
||||
}`;
|
||||
|
||||
function each<T>(items: T[], callbackfn: (item: T) => string, separator = ``) {
|
||||
return items.map(callbackfn).join(separator);
|
||||
}
|
||||
}
|
12
scripts/processTypes/tsconfig.json
Normal file
12
scripts/processTypes/tsconfig.json
Normal file
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"target": "ES5",
|
||||
"module": "commonjs",
|
||||
"outDir": "../../built/scripts/processTypes/",
|
||||
"experimentalDecorators": true,
|
||||
"noImplicitAny": true,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": true
|
||||
}
|
||||
}
|
1292
scripts/processTypes/types.ts
Normal file
1292
scripts/processTypes/types.ts
Normal file
File diff suppressed because it is too large
Load diff
4
scripts/processTypes/typescript-internal.d.ts
vendored
Normal file
4
scripts/processTypes/typescript-internal.d.ts
vendored
Normal file
|
@ -0,0 +1,4 @@
|
|||
/// <reference path="../../lib/typescript_standalone.d.ts" />
|
||||
import { Symbol } from "typescript";
|
||||
export * from "typescript";
|
||||
export declare function getSymbolId(symbol: Symbol): number;
|
1
scripts/processTypes/typescript-internal.js
Normal file
1
scripts/processTypes/typescript-internal.js
Normal file
|
@ -0,0 +1 @@
|
|||
module.exports = require("../../../lib/typescript");
|
49
scripts/processTypes/utilities.ts
Normal file
49
scripts/processTypes/utilities.ts
Normal file
|
@ -0,0 +1,49 @@
|
|||
import { Map } from "./typescript-internal";
|
||||
|
||||
let hasOwnProperty = Object.prototype.hasOwnProperty;
|
||||
|
||||
export function hasProperty<T>(map: Map<T>, key: string): boolean {
|
||||
return hasOwnProperty.call(map, key);
|
||||
}
|
||||
|
||||
export function getProperty<T>(map: Map<T>, key: string): T {
|
||||
return hasOwnProperty.call(map, key) ? map[key] : undefined;
|
||||
}
|
||||
|
||||
export let directorySeparator = "/";
|
||||
|
||||
export function getRootLength(path: string): number {
|
||||
if (path.charAt(0) === directorySeparator) {
|
||||
if (path.charAt(1) !== directorySeparator) return 1;
|
||||
let p1 = path.indexOf("/", 2);
|
||||
if (p1 < 0) return 2;
|
||||
let p2 = path.indexOf("/", p1 + 1);
|
||||
if (p2 < 0) return p1 + 1;
|
||||
return p2 + 1;
|
||||
}
|
||||
if (path.charAt(1) === ":") {
|
||||
if (path.charAt(2) === directorySeparator) return 3;
|
||||
return 2;
|
||||
}
|
||||
// Per RFC 1738 'file' URI schema has the shape file://<host>/<path>
|
||||
// if <host> is omitted then it is assumed that host value is 'localhost',
|
||||
// however slash after the omitted <host> is not removed.
|
||||
// file:///folder1/file1 - this is a correct URI
|
||||
// file://folder2/file2 - this is an incorrect URI
|
||||
if (path.lastIndexOf("file:///", 0) === 0) {
|
||||
return "file:///".length;
|
||||
}
|
||||
let idx = path.indexOf("://");
|
||||
if (idx !== -1) {
|
||||
return idx + "://".length;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
export function combinePaths(path1: string, path2: string) {
|
||||
if (!(path1 && path1.length)) return path2;
|
||||
if (!(path2 && path2.length)) return path1;
|
||||
if (getRootLength(path2) !== 0) return path2;
|
||||
if (path1.charAt(path1.length - 1) === directorySeparator) return path1 + path2;
|
||||
return path1 + directorySeparator + path2;
|
||||
}
|
|
@ -125,12 +125,16 @@ namespace ts {
|
|||
let symbolCount = 0;
|
||||
let Symbol: { new (flags: SymbolFlags, name: string): Symbol };
|
||||
let classifiableNames: Map<string>;
|
||||
let subtreeTransformFlags: TransformFlags;
|
||||
let skipTransformFlagAggregation: boolean;
|
||||
|
||||
function bindSourceFile(f: SourceFile, opts: CompilerOptions) {
|
||||
file = f;
|
||||
options = opts;
|
||||
inStrictMode = !!file.externalModuleIndicator;
|
||||
classifiableNames = {};
|
||||
subtreeTransformFlags = undefined;
|
||||
skipTransformFlagAggregation = isDeclarationFile(file);
|
||||
Symbol = objectAllocator.getSymbolConstructor();
|
||||
|
||||
if (!file.locals) {
|
||||
|
@ -1106,11 +1110,40 @@ namespace ts {
|
|||
// symbols we do specialized work when we recurse. For example, we'll keep track of
|
||||
// the current 'container' node when it changes. This helps us know which symbol table
|
||||
// a local should go into for example.
|
||||
bindChildren(node);
|
||||
aggregateTransformFlagsIfNeededAnd(bindChildren, node);
|
||||
|
||||
inStrictMode = savedInStrictMode;
|
||||
}
|
||||
|
||||
function aggregateTransformFlagsIfNeededAnd<T>(cbNode: (node: Node) => T, node: Node): T {
|
||||
return node.transformFlags !== undefined
|
||||
? skipTransformFlagAggregationAnd(cbNode, node)
|
||||
: aggregateTransformFlagsAnd(cbNode, node);
|
||||
}
|
||||
|
||||
function skipTransformFlagAggregationAnd<T>(cbNode: (node: Node) => T, node: Node): T {
|
||||
if (!skipTransformFlagAggregation) {
|
||||
skipTransformFlagAggregation = true;
|
||||
let result = cbNode(node);
|
||||
skipTransformFlagAggregation = false;
|
||||
return result;
|
||||
}
|
||||
|
||||
return cbNode(node);
|
||||
}
|
||||
|
||||
function aggregateTransformFlagsAnd<T>(cbNode: (node: Node) => T, node: Node): T {
|
||||
if (!skipTransformFlagAggregation) {
|
||||
let savedSubtreeTransformFlags = subtreeTransformFlags;
|
||||
subtreeTransformFlags = 0;
|
||||
let result = cbNode(node);
|
||||
subtreeTransformFlags = savedSubtreeTransformFlags | (computeTransformFlagsForNode(node, subtreeTransformFlags) & ~TransformFlags.NodeExcludes);
|
||||
return result;
|
||||
}
|
||||
|
||||
return cbNode(node);
|
||||
}
|
||||
|
||||
function updateStrictMode(node: Node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.SourceFile:
|
||||
|
@ -1191,8 +1224,9 @@ namespace ts {
|
|||
case SyntaxKind.BindingElement:
|
||||
return bindVariableDeclarationOrBindingElement(<VariableDeclaration | BindingElement>node);
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.PropertySignature:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertyDeclaration>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property | ((<PropertySignature>node).questionToken ? SymbolFlags.Optional : SymbolFlags.None), SymbolFlags.PropertyExcludes);
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
|
||||
|
@ -1570,4 +1604,427 @@ namespace ts {
|
|||
implicitLabels = [];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Computes the transform flags for a node, given the transform flags of its subtree
|
||||
* @param node The node to analyze
|
||||
* @param subtreeFlags Transform flags computed for this node's subtree
|
||||
*/
|
||||
export function computeTransformFlagsForNode(node: Node, subtreeFlags: TransformFlags) {
|
||||
Debug.assert((subtreeFlags & TransformFlags.NodeExcludes) == 0, "Subtree includes a `ThisNode...` flag.");
|
||||
|
||||
if (node.flags & NodeFlags.Ambient) {
|
||||
return node.transformFlags = TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
// Mark transformations needed for each node
|
||||
let transformFlags: TransformFlags;
|
||||
let excludeFlags: TransformFlags;
|
||||
let kind = node.kind;
|
||||
switch (kind) {
|
||||
case SyntaxKind.PublicKeyword:
|
||||
case SyntaxKind.PrivateKeyword:
|
||||
case SyntaxKind.ProtectedKeyword:
|
||||
case SyntaxKind.AbstractKeyword:
|
||||
case SyntaxKind.DeclareKeyword:
|
||||
case SyntaxKind.AsyncKeyword:
|
||||
case SyntaxKind.ConstKeyword:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.EnumMember:
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
case SyntaxKind.AsExpression:
|
||||
// These nodes are TypeScript syntax.
|
||||
transformFlags |= TransformFlags.TypeScript;
|
||||
break;
|
||||
|
||||
case SyntaxKind.JsxElement:
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
case SyntaxKind.JsxOpeningElement:
|
||||
case SyntaxKind.JsxText:
|
||||
case SyntaxKind.JsxClosingElement:
|
||||
case SyntaxKind.JsxAttribute:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
case SyntaxKind.JsxExpression:
|
||||
// These nodes are Jsx syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsJsx;
|
||||
break;
|
||||
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
case SyntaxKind.TemplateHead:
|
||||
case SyntaxKind.TemplateMiddle:
|
||||
case SyntaxKind.TemplateTail:
|
||||
case SyntaxKind.TemplateExpression:
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.ShorthandPropertyAssignment:
|
||||
case SyntaxKind.ForOfStatement:
|
||||
case SyntaxKind.YieldExpression:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
break;
|
||||
|
||||
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.NumberKeyword:
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
case SyntaxKind.SymbolKeyword:
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.TypeParameter:
|
||||
case SyntaxKind.PropertySignature:
|
||||
case SyntaxKind.MethodSignature:
|
||||
case SyntaxKind.CallSignature:
|
||||
case SyntaxKind.ConstructSignature:
|
||||
case SyntaxKind.IndexSignature:
|
||||
case SyntaxKind.TypePredicate:
|
||||
case SyntaxKind.TypeReference:
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.IntersectionType:
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
// Types and signatures are TypeScript syntax, and exclude all other facts.
|
||||
excludeFlags = TransformFlags.TypeExcludes;
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ComputedPropertyName:
|
||||
// Even though computed property names are ES6, we don't treat them as such.
|
||||
// This is so that they can flow through PropertyName transforms unaffected.
|
||||
// Instead, we mark the container as ES6, so that it can properly handle the transform.
|
||||
transformFlags |= TransformFlags.ContainsComputedPropertyName;
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
// This node is ES6 syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadElementExpression;
|
||||
break;
|
||||
|
||||
case SyntaxKind.SuperKeyword:
|
||||
// This node is ES6 syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ThisKeyword:
|
||||
// Mark this node and its ancestors as containing a lexical `this` keyword.
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
// These nodes are ES6 syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
excludeFlags = TransformFlags.ObjectLiteralExpressionExcludes;
|
||||
if (subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
|
||||
// If an ObjectLiteralExpression contains a ComputedPropertyName, then it
|
||||
// is an ES6 node.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExpressionExcludes;
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression ||
|
||||
(<CallExpression>node).expression.kind === SyntaxKind.SuperKeyword ||
|
||||
(<CallExpression>node).expression.kind === SyntaxKind.PropertyAccessExpression &&
|
||||
(<PropertyAccessExpression>(<CallExpression>node).expression).expression.kind === SyntaxKind.SuperKeyword) {
|
||||
// If the this node contains a SpreadElementExpression, or is a super call, then it is an ES6
|
||||
// node.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
case SyntaxKind.NewExpression:
|
||||
excludeFlags = TransformFlags.ArrayLiteralOrCallOrNewExpressionExcludes;
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) {
|
||||
// If the this node contains a SpreadElementExpression, then it is an ES6
|
||||
// node.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.Decorator:
|
||||
// This node is TypeScript syntax, and marks its container as also being TypeScript syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainsDecorator;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
// This node is TypeScript syntax, and excludes markers that should not escape the module scope.
|
||||
excludeFlags = TransformFlags.ModuleScopeExcludes;
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
break;
|
||||
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
// If the node is synthesized, it means the emitter put the parentheses there,
|
||||
// not the user. If we didn't want them, the emitter would not have put them
|
||||
// there.
|
||||
if (!nodeIsSynthesized(node) && (isTypeAssertionExpression((<ParenthesizedExpression>node).expression) || isAsExpression((<ParenthesizedExpression>node).expression))) {
|
||||
transformFlags = TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExpressionStatement:
|
||||
if (node.flags & NodeFlags.Generated) {
|
||||
let expression = (<ExpressionStatement>node).expression;
|
||||
if (isCallExpression(expression) && isSuperKeyword(expression.expression)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (isDestructuringAssignment(node)) {
|
||||
// Destructuring assignments are ES6 syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
else if ((<BinaryExpression>node).operatorToken.kind === SyntaxKind.AsteriskAsteriskToken ||
|
||||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.AsteriskAsteriskEqualsToken) {
|
||||
// Exponentiation is ES7 syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.Parameter:
|
||||
// If the parameter has a question token, then it is TypeScript syntax.
|
||||
if ((<ParameterDeclaration>node).questionToken) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
// If a parameter has an accessibility modifier, then it is TypeScript syntax.
|
||||
if ((<ParameterDeclaration>node).flags & NodeFlags.AccessibilityModifier) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript | TransformFlags.ContainsParameterPropertyAssignment;
|
||||
}
|
||||
|
||||
// If a parameter has an initializer, a binding pattern or a dotDotDot token, then
|
||||
// it is ES6 syntax and its container must emit default value assignments or parameter destructuring downlevel.
|
||||
if ((<ParameterDeclaration>node).initializer ||
|
||||
isBindingPattern((<ParameterDeclaration>node).name) ||
|
||||
(<ParameterDeclaration>node).dotDotDotToken) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6 | TransformFlags.ContainsDefaultValueAssignments;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ArrowFunction:
|
||||
// An ArrowFunction is ES6 syntax, and excludes markers that should not escape the scope of an ArrowFunction.
|
||||
excludeFlags = TransformFlags.ArrowFunctionExcludes;
|
||||
transformFlags = TransformFlags.ThisNodeIsES6;
|
||||
|
||||
// If an ArrowFunction contains a lexical this, its container must capture the lexical this.
|
||||
if (subtreeFlags & TransformFlags.ContainsLexicalThis) {
|
||||
transformFlags |= TransformFlags.ContainsCapturedLexicalThis;
|
||||
}
|
||||
|
||||
// An async arrow function is TypeScript syntax.
|
||||
if (node.flags & NodeFlags.Async) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionExpression:
|
||||
// A FunctionExpression excludes markers that should not escape the scope of a FunctionExpression.
|
||||
excludeFlags = TransformFlags.FunctionDeclarationOrExpressionExcludes;
|
||||
|
||||
// If a FunctionExpression contains an asterisk token, or its subtree has marked the container
|
||||
// as needing to capture the lexical this, then this node is ES6 syntax.
|
||||
if ((<FunctionLikeDeclaration>node).asteriskToken || transformFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
// An async function expression is TypeScript syntax.
|
||||
if (node.flags & NodeFlags.Async) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
// A FunctionDeclaration excludes markers that should not escape the scope of a FunctionDeclaration.
|
||||
excludeFlags = TransformFlags.FunctionDeclarationOrExpressionExcludes;
|
||||
|
||||
// A FunctionDeclaration without a body is an overload and is TypeScript syntax.
|
||||
if (!(<FunctionDeclaration>node).body) {
|
||||
transformFlags = TransformFlags.ThisNodeIsTypeScript;
|
||||
break;
|
||||
}
|
||||
|
||||
// If a FunctionDeclaration has an asterisk token, is exported, or its
|
||||
// subtree has marked the container as needing to capture the lexical `this`,
|
||||
// then this node is ES6 syntax.
|
||||
if ((<FunctionLikeDeclaration>node).asteriskToken
|
||||
|| node.flags & NodeFlags.Export
|
||||
|| subtreeFlags & (TransformFlags.ContainsCapturedLexicalThis | TransformFlags.ContainsDefaultValueAssignments)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
// An async function declaration is TypeScript syntax.
|
||||
if (node.flags & NodeFlags.Async) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableDeclaration:
|
||||
// A VariableDeclaration with a binding pattern is ES6 syntax.
|
||||
if (isBindingPattern((<VariableDeclaration>node).name)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableDeclarationList:
|
||||
// If a VariableDeclarationList is `let` or `const`, then it is ES6 syntax.
|
||||
if (node.flags & (NodeFlags.Let | NodeFlags.Const)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.VariableStatement:
|
||||
// If a VariableStatement is exported, then it is ES6 syntax.
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.ClassExpression:
|
||||
// A ClassDeclarations or ClassExpression is ES6 syntax.
|
||||
excludeFlags = TransformFlags.ClassDeclarationOrExpressionExcludes;
|
||||
transformFlags = TransformFlags.ThisNodeIsES6;
|
||||
|
||||
// A class with a parameter property assignment, property initializer, or decorator is
|
||||
// TypeScript syntax.
|
||||
if (subtreeFlags & TransformFlags.TypeScriptClassSyntaxExtensionsMask) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.HeritageClause:
|
||||
// An `extends` HertiageClause is ES6 syntax.
|
||||
if ((<HeritageClause>node).token === SyntaxKind.ExtendsKeyword) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
// An `implements` HeritageClause, or an `extends` HeritageClause with more than
|
||||
// one type must be TypeScript syntax.
|
||||
if ((<HeritageClause>node).token !== SyntaxKind.ExtendsKeyword ||
|
||||
(<HeritageClause>node).types.length > 1) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExpressionWithTypeArguments:
|
||||
// An ExpressionWithTypeArguments is ES6 syntax, as it is used in the
|
||||
// extends clause of a class.
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
|
||||
// If an ExpressionWithTypeArguments contains type arguments, then it
|
||||
// is TypeScript syntax.
|
||||
if ((<ExpressionWithTypeArguments>node).typeArguments) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.Constructor:
|
||||
// A Constructor is ES6 syntax.
|
||||
excludeFlags = TransformFlags.ConstructorExcludes;
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
|
||||
// An overload constructor is TypeScript syntax.
|
||||
if (!(<ConstructorDeclaration>node).body) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
// A PropertyDeclaration is TypeScript syntax.
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
|
||||
// If the PropertyDeclaration has an initializer, we need to inform its ancestor
|
||||
// so that it handle the transformation.
|
||||
if ((<PropertyDeclaration>node).initializer) {
|
||||
transformFlags |= TransformFlags.ContainsPropertyInitializer;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
// A MethodDeclaration is ES6 syntax.
|
||||
excludeFlags = TransformFlags.MethodDeclarationExcludes;
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
|
||||
// A MethodDeclaration is TypeScript syntax if it is either async, abstract, overloaded,
|
||||
// generic, or has both a computed property name and a decorator.
|
||||
if ((<MethodDeclaration>node).body === undefined ||
|
||||
(<MethodDeclaration>node).typeParameters !== undefined ||
|
||||
node.flags & (NodeFlags.Async | NodeFlags.Abstract) ||
|
||||
subtreeFlags & TransformFlags.ContainsDecorator &&
|
||||
subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
// A GetAccessor or SetAccessor is ES5 syntax.
|
||||
excludeFlags = TransformFlags.GetOrSetAccessorExcludes;
|
||||
|
||||
// A GetAccessor or SetAccessor is TypeScript syntax if it is either abstract,
|
||||
// or has both a computed property name and a decorator.
|
||||
if (node.flags & NodeFlags.Abstract ||
|
||||
subtreeFlags & TransformFlags.ContainsDecorator &&
|
||||
subtreeFlags & TransformFlags.ContainsComputedPropertyName) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
// An ImportEqualsDeclaration with a namespace reference is TypeScript.
|
||||
if (!isExternalModuleImportEqualsDeclaration(node)) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsTypeScript;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
// If a PropertyAccessExpression starts with a super keyword, then it is
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
if ((<PropertyAccessExpression>node).expression.kind === SyntaxKind.SuperKeyword) {
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.SourceFile:
|
||||
if (subtreeFlags & TransformFlags.ContainsCapturedLexicalThis) {
|
||||
transformFlags |= TransformFlags.ThisNodeIsES6;
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
return (node.transformFlags = subtreeFlags | transformFlags)
|
||||
& ~(node.excludeTransformFlags = excludeFlags);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ namespace ts {
|
|||
let emitDecorate = false;
|
||||
let emitParam = false;
|
||||
let emitAwaiter = false;
|
||||
const emitGenerator = false;
|
||||
let emitGenerator = false;
|
||||
|
||||
const resolutionTargets: TypeSystemEntity[] = [];
|
||||
const resolutionResults: boolean[] = [];
|
||||
|
@ -497,7 +497,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Because of module/namespace merging, a module's exports are in scope,
|
||||
// yet we never want to treat an export specifier as putting a member in scope.
|
||||
// yet we never want to treat an export specifier as putting a member in scope.
|
||||
// Therefore, if the name we find is purely an export specifier, it is not actually considered in scope.
|
||||
// Two things to note about this:
|
||||
// 1. We have to check this without calling getSymbol. The problem with calling getSymbol
|
||||
|
@ -1434,7 +1434,12 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function isEntityNameOrExpression(node: Node): node is EntityName | Expression {
|
||||
return isEntityName(node) || isExpressionNode(node);
|
||||
}
|
||||
|
||||
function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult {
|
||||
entityName = getOriginalNodeIf(entityName, isEntityNameOrExpression);
|
||||
// get symbol of the first identifier of the entityName
|
||||
let meaning: SymbolFlags;
|
||||
if (entityName.parent.kind === SyntaxKind.TypeQuery) {
|
||||
|
@ -2061,6 +2066,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isDeclarationVisible(node: Declaration): boolean {
|
||||
node = getOriginalNodeIf(node, isDeclaration);
|
||||
function getContainingExternalModule(node: Node) {
|
||||
for (; node; node = node.parent) {
|
||||
if (node.kind === SyntaxKind.ModuleDeclaration) {
|
||||
|
@ -2209,6 +2215,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function collectLinkedAliases(node: Identifier): Node[] {
|
||||
node = getOriginalNodeIf(node, isIdentifier);
|
||||
let exportSymbol: Symbol;
|
||||
if (node.parent && node.parent.kind === SyntaxKind.ExportAssignment) {
|
||||
exportSymbol = resolveName(node.parent, node.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias, Diagnostics.Cannot_find_name_0, node);
|
||||
|
@ -9860,7 +9867,7 @@ namespace ts {
|
|||
return type;
|
||||
}
|
||||
|
||||
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
|
||||
function checkFunctionExpressionOrObjectLiteralMethodBody(node: ArrowFunction | FunctionExpression | MethodDeclaration) {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
|
||||
const isAsync = isAsyncFunctionLike(node);
|
||||
|
@ -10164,7 +10171,7 @@ namespace ts {
|
|||
checkDestructuringAssignment(<ShorthandPropertyAssignment>p, type);
|
||||
}
|
||||
else {
|
||||
// non-shorthand property assignments should always have initializers
|
||||
// non-shorthand property assignments should always have initializers
|
||||
checkDestructuringAssignment((<PropertyAssignment>p).initializer, type);
|
||||
}
|
||||
}
|
||||
|
@ -14263,6 +14270,8 @@ namespace ts {
|
|||
emitExtends = false;
|
||||
emitDecorate = false;
|
||||
emitParam = false;
|
||||
emitAwaiter = false;
|
||||
emitGenerator = false;
|
||||
potentialThisCollisions.length = 0;
|
||||
|
||||
forEach(node.statements, checkSourceElement);
|
||||
|
@ -14793,6 +14802,7 @@ namespace ts {
|
|||
// When resolved as an expression identifier, if the given node references an exported entity, return the declaration
|
||||
// node of the exported entity's container. Otherwise, return undefined.
|
||||
function getReferencedExportContainer(node: Identifier): SourceFile | ModuleDeclaration | EnumDeclaration {
|
||||
node = getOriginalNodeIf(node, isIdentifier);
|
||||
let symbol = getReferencedValueSymbol(node);
|
||||
if (symbol) {
|
||||
if (symbol.flags & SymbolFlags.ExportValue) {
|
||||
|
@ -14822,6 +14832,7 @@ namespace ts {
|
|||
// When resolved as an expression identifier, if the given node references an import, return the declaration of
|
||||
// that import. Otherwise, return undefined.
|
||||
function getReferencedImportDeclaration(node: Identifier): Declaration {
|
||||
node = getOriginalNodeIf(node, isIdentifier);
|
||||
const symbol = getReferencedValueSymbol(node);
|
||||
return symbol && symbol.flags & SymbolFlags.Alias ? getDeclarationOfAliasSymbol(symbol) : undefined;
|
||||
}
|
||||
|
@ -14854,6 +14865,7 @@ namespace ts {
|
|||
// When resolved as an expression identifier, if the given node references a nested block scoped entity with
|
||||
// a name that hides an existing name, return the declaration of that entity. Otherwise, return undefined.
|
||||
function getReferencedNestedRedeclaration(node: Identifier): Declaration {
|
||||
node = getOriginalNodeIf(node, isIdentifier);
|
||||
const symbol = getReferencedValueSymbol(node);
|
||||
return symbol && isNestedRedeclarationSymbol(symbol) ? symbol.valueDeclaration : undefined;
|
||||
}
|
||||
|
@ -14861,10 +14873,13 @@ namespace ts {
|
|||
// Return true if the given node is a declaration of a nested block scoped entity with a name that hides an
|
||||
// existing name.
|
||||
function isNestedRedeclaration(node: Declaration): boolean {
|
||||
return isNestedRedeclarationSymbol(getSymbolOfNode(node));
|
||||
let original = getOriginalNode(node);
|
||||
let symbol = !nodeIsSynthesized(original) && getSymbolOfNode(original);
|
||||
return symbol && isNestedRedeclarationSymbol(getSymbolOfNode(original));
|
||||
}
|
||||
|
||||
function isValueAliasDeclaration(node: Node): boolean {
|
||||
node = getOriginalNode(node);
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.ImportClause:
|
||||
|
@ -14882,6 +14897,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isTopLevelValueImportEqualsWithEntityName(node: ImportEqualsDeclaration): boolean {
|
||||
node = getOriginalNodeIf(node, isImportEqualsDeclaration);
|
||||
if (node.parent.kind !== SyntaxKind.SourceFile || !isInternalModuleImportEqualsDeclaration(node)) {
|
||||
// parent is not source file or it is not reference to internal module
|
||||
return false;
|
||||
|
@ -14909,6 +14925,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isReferencedAliasDeclaration(node: Node, checkChildren?: boolean): boolean {
|
||||
node = getOriginalNode(node);
|
||||
if (isAliasSymbolDeclaration(node)) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
if (getSymbolLinks(symbol).referenced) {
|
||||
|
@ -14923,6 +14940,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isImplementationOfOverload(node: FunctionLikeDeclaration) {
|
||||
node = getOriginalNodeIf(node, isFunctionLike);
|
||||
if (nodeIsPresent(node.body)) {
|
||||
const symbol = getSymbolOfNode(node);
|
||||
const signaturesOfSymbol = getSignaturesOfSymbol(symbol);
|
||||
|
@ -14944,6 +14962,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getNodeCheckFlags(node: Node): NodeCheckFlags {
|
||||
node = getOriginalNode(node);
|
||||
return getNodeLinks(node).flags;
|
||||
}
|
||||
|
||||
|
@ -14952,7 +14971,12 @@ namespace ts {
|
|||
return getNodeLinks(node).enumMemberValue;
|
||||
}
|
||||
|
||||
function isEnumMemberOrPropertyAccessExpressionOrElementAccessExpression(node: Node): node is EnumMember | PropertyAccessExpression | ElementAccessExpression {
|
||||
return isEnumMember(node) || isPropertyAccessExpression(node) || isElementAccessExpression(node);
|
||||
}
|
||||
|
||||
function getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number {
|
||||
node = getOriginalNodeIf(node, isEnumMemberOrPropertyAccessExpressionOrElementAccessExpression);
|
||||
if (node.kind === SyntaxKind.EnumMember) {
|
||||
return getEnumMemberValue(<EnumMember>node);
|
||||
}
|
||||
|
@ -15053,6 +15077,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function getReferencedValueDeclaration(reference: Identifier): Declaration {
|
||||
reference = getOriginalNodeIf(reference, isIdentifier);
|
||||
Debug.assert(!nodeIsSynthesized(reference));
|
||||
const symbol = getReferencedValueSymbol(reference);
|
||||
return symbol && getExportSymbolOfValueSymbolIfExported(symbol).valueDeclaration;
|
||||
|
@ -15748,7 +15773,7 @@ namespace ts {
|
|||
// Grammar checking for computedPropertName and shorthandPropertyAssignment
|
||||
checkGrammarForInvalidQuestionMark(prop, (<PropertyAssignment>prop).questionToken, Diagnostics.An_object_member_cannot_be_declared_optional);
|
||||
if (name.kind === SyntaxKind.NumericLiteral) {
|
||||
checkGrammarNumericLiteral(<Identifier>name);
|
||||
checkGrammarNumericLiteral(<LiteralExpression>name);
|
||||
}
|
||||
currentKind = Property;
|
||||
}
|
||||
|
@ -16253,7 +16278,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function checkGrammarNumericLiteral(node: Identifier): boolean {
|
||||
function checkGrammarNumericLiteral(node: LiteralExpression): boolean {
|
||||
// Grammar checking
|
||||
if (node.flags & NodeFlags.OctalLiteral && languageVersion >= ScriptTarget.ES5) {
|
||||
return grammarErrorOnNode(node, Diagnostics.Octal_literals_are_not_available_when_targeting_ECMAScript_5_and_higher);
|
||||
|
|
|
@ -240,6 +240,11 @@ namespace ts {
|
|||
type: "boolean",
|
||||
description: Diagnostics.Enables_experimental_support_for_ES7_decorators
|
||||
},
|
||||
{
|
||||
name: "experimentalTransforms",
|
||||
type: "boolean",
|
||||
experimental: true
|
||||
},
|
||||
{
|
||||
name: "emitDecoratorMetadata",
|
||||
type: "boolean",
|
||||
|
|
|
@ -140,6 +140,19 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
export function every<T>(array: T[], f: (x: T) => boolean): boolean {
|
||||
if (array) {
|
||||
for (let item of array) {
|
||||
if (!f(item)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
export function map<T, U>(array: T[], f: (x: T) => U): U[] {
|
||||
let result: U[];
|
||||
if (array) {
|
||||
|
@ -187,6 +200,61 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
export function trimArray<T>(array: T[]): T[] {
|
||||
let result: T[];
|
||||
if (array) {
|
||||
result = [];
|
||||
for (let v of array) {
|
||||
if (v !== undefined) {
|
||||
result.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function skip<T>(array: T[], count: number) {
|
||||
if (array) {
|
||||
return count === 0 ? array : array.slice(count);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function take<T>(array: T[], count: number) {
|
||||
if (array) {
|
||||
return count >= array.length ? array : array.slice(0, count);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function takeWhile<T>(array: T[], callbackfn: (item: T) => boolean): T[] {
|
||||
if (array) {
|
||||
for (let i = 0; i < array.length; i++) {
|
||||
if (!callbackfn(array[i])) {
|
||||
return array.slice(0, i);
|
||||
}
|
||||
}
|
||||
return array.slice(0);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function append<T>(to: T[], ...values: T[]): T[] {
|
||||
let result: T[];
|
||||
if (to) {
|
||||
for (let v of values) {
|
||||
if (v !== undefined) {
|
||||
if (!result) {
|
||||
result = to.slice(0);
|
||||
}
|
||||
result.push(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result || to;
|
||||
}
|
||||
|
||||
export function rangeEquals<T>(array1: T[], array2: T[], pos: number, end: number) {
|
||||
while (pos < end) {
|
||||
if (array1[pos] !== array2[pos]) {
|
||||
|
@ -197,6 +265,28 @@ namespace ts {
|
|||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the first element of an array if non-empty, undefined otherwise.
|
||||
*/
|
||||
export function firstOrUndefined<T>(array: T[]): T {
|
||||
if (array.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return array[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the only element of an array if non-empty, undefined otherwise.
|
||||
*/
|
||||
export function singleOrUndefined<T>(array: T[]): T {
|
||||
if (array.length === 1) {
|
||||
return array[0];
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the last element of an array if non-empty, undefined otherwise.
|
||||
*/
|
||||
|
@ -356,6 +446,22 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
export function reduceProperties<T, U>(map: Map<T>, f: (a: U, v: T, k: string) => U, initial: U): U {
|
||||
let result = initial;
|
||||
if (map) {
|
||||
for (let key in map) {
|
||||
if (hasProperty(map, key)) {
|
||||
result = f(result, map[key], String(key));
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function isArray(value: any): value is any[] {
|
||||
return Array.isArray ? Array.isArray(value) : Object.prototype.toString.call(value) === "[object Array]";
|
||||
}
|
||||
|
||||
export function memoize<T>(callback: () => T): () => T {
|
||||
let value: T;
|
||||
return () => {
|
||||
|
@ -806,7 +912,17 @@ namespace ts {
|
|||
this.end = end;
|
||||
this.flags = NodeFlags.None;
|
||||
this.parent = undefined;
|
||||
this.original = undefined;
|
||||
this.transformFlags = undefined;
|
||||
this.excludeTransformFlags = undefined;
|
||||
this.modifiers = undefined;
|
||||
}
|
||||
|
||||
Node.prototype = {
|
||||
createParentNavigator(): ParentNavigator {
|
||||
return createParentNavigator(<Node>this);
|
||||
}
|
||||
};
|
||||
|
||||
export let objectAllocator: ObjectAllocator = {
|
||||
getNodeConstructor: () => <any>Node,
|
||||
|
@ -816,6 +932,234 @@ namespace ts {
|
|||
getSignatureConstructor: () => <any>Signature
|
||||
};
|
||||
|
||||
/**
|
||||
* Creates an object used to navigate the ancestor's of a node by following parent pointers.
|
||||
* @param currentNode The current node for the navigator.
|
||||
*/
|
||||
export function createParentNavigator(currentNode: Node): ParentNavigator {
|
||||
/** Gets the grandparent of the current node, without moving the navigator. */
|
||||
function getGrandparentNode() {
|
||||
let parent = getParentNode();
|
||||
return parent ? parent.parent : undefined;
|
||||
}
|
||||
|
||||
/** Gets the parent of the current node, without moving the navigator. */
|
||||
function getParentNode() {
|
||||
return currentNode ? currentNode.parent : undefined;
|
||||
}
|
||||
|
||||
/** Gets the current node. */
|
||||
function getCurrentNode() {
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
/** Gets the SyntaxKind for the current node. */
|
||||
function getKind() {
|
||||
return currentNode ? currentNode.kind : undefined;
|
||||
}
|
||||
|
||||
/** Navigates to the parent of the current node if it has one. */
|
||||
function moveToParent(): boolean {
|
||||
let parent = getParentNode();
|
||||
if (parent) {
|
||||
currentNode = parent;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Creates a new ParentNavigator from the current node. */
|
||||
function createParentNavigator() {
|
||||
return ts.createParentNavigator(currentNode);
|
||||
}
|
||||
|
||||
return {
|
||||
getGrandparentNode,
|
||||
getParentNode,
|
||||
getCurrentNode,
|
||||
getKind,
|
||||
moveToParent,
|
||||
createParentNavigator,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a node stack used to maintain parent relationships without parent pointers.
|
||||
*/
|
||||
export function createNodeStack(): NodeStack {
|
||||
let stackSize: number = 0;
|
||||
let stack: Node[] = [];
|
||||
let rootNode: Node;
|
||||
let parentNode: Node;
|
||||
let currentNode: Node;
|
||||
|
||||
function getStackSize(): number {
|
||||
return stackSize;
|
||||
}
|
||||
|
||||
/** Gets the node two steps back from the top of the stack. */
|
||||
function getGrandparentNode() {
|
||||
return peekNode(2);
|
||||
}
|
||||
|
||||
/** Gets the node one step back from the top of the stack. */
|
||||
function getParentNode() {
|
||||
return parentNode;
|
||||
}
|
||||
|
||||
/** Gets the node at the top of the stack. */
|
||||
function getCurrentNode() {
|
||||
return currentNode;
|
||||
}
|
||||
|
||||
/** Gets the SyntaxKind for the node at the top of the stack. */
|
||||
function getKind() {
|
||||
return currentNode ? currentNode.kind : undefined;
|
||||
}
|
||||
|
||||
/** Pushes a node onto the stack. */
|
||||
function pushNode(node: Node): void {
|
||||
stackSize++;
|
||||
if (stackSize > 2) {
|
||||
stack.push(parentNode);
|
||||
}
|
||||
else if (stackSize === 1) {
|
||||
rootNode = node;
|
||||
}
|
||||
parentNode = currentNode;
|
||||
currentNode = node;
|
||||
}
|
||||
|
||||
/** Pushes a node onto the stack if it is not already at the top of the stack. */
|
||||
function tryPushNode(node: Node): boolean {
|
||||
if (currentNode === node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
pushNode(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Pops the top node from the stack. */
|
||||
function popNode(): void {
|
||||
currentNode = parentNode;
|
||||
parentNode = stackSize > 2 ? stack.pop() : undefined;
|
||||
stackSize--;
|
||||
if (stackSize === 0) {
|
||||
rootNode = undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/** Replaces the node at the top of the stack. */
|
||||
function setNode(node: Node): void {
|
||||
currentNode = node;
|
||||
}
|
||||
|
||||
/** Peeks at a node a specified number of steps back from the top of the stack. */
|
||||
function peekNode(stackOffset: number): Node {
|
||||
switch (stackOffset) {
|
||||
case 0: return currentNode;
|
||||
case 1: return parentNode;
|
||||
default: return stackSize > 2 ? stack[stackSize - 1 - stackOffset] : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
|
||||
function findAncestorNode<T extends Node>(match: (node: Node) => node is T): T;
|
||||
/** Traverses the stack from top to bottom until it finds a node that matches the supplied predicate. */
|
||||
function findAncestorNode(match: (node: Node) => boolean): Node;
|
||||
function findAncestorNode(match: (node: Node) => boolean) {
|
||||
if (parentNode && match(parentNode)) {
|
||||
return parentNode;
|
||||
}
|
||||
for (let i = stack.length - 1; i >= 0; i--) {
|
||||
let node = stack[i];
|
||||
if (match(node)) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Creates a parent navigator from the top of the stack. */
|
||||
function createParentNavigator() {
|
||||
return createParentNavigatorFromStackOffset(0);
|
||||
}
|
||||
|
||||
/** Creates a parent navigator a specified number of steps back from the top of the stack. */
|
||||
function createParentNavigatorFromStackOffset(stackOffset: number): ParentNavigator {
|
||||
/** Gets the node two steps back from the current stack offset. */
|
||||
function getGrandparentNode() {
|
||||
return peekNode(stackOffset + 2);
|
||||
}
|
||||
|
||||
/** Gets the node one step back from the current stack offset. */
|
||||
function getParentNode() {
|
||||
return peekNode(stackOffset + 1);
|
||||
}
|
||||
|
||||
/** Gets the node at the current stack offset. */
|
||||
function getCurrentNode() {
|
||||
return peekNode(stackOffset);
|
||||
}
|
||||
|
||||
/** Gets the SyntaxKind of the node at the current stack offset. */
|
||||
function getKind() {
|
||||
let node = getCurrentNode();
|
||||
return node ? node.kind : undefined;
|
||||
}
|
||||
|
||||
/** Navigates to the node one step back from the current stack offset. */
|
||||
function moveToParent() {
|
||||
if (getParentNode()) {
|
||||
stackOffset++;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Navigates to the node at the bottom of the stack. */
|
||||
function moveToRoot() {
|
||||
if (stackSize > 0) {
|
||||
stackOffset = stackSize;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/** Creates a new ParentNavigator from the current stack offset. */
|
||||
function createParentNavigator() {
|
||||
return createParentNavigatorFromStackOffset(stackOffset);
|
||||
}
|
||||
|
||||
return {
|
||||
getGrandparentNode,
|
||||
getParentNode,
|
||||
getCurrentNode,
|
||||
getKind,
|
||||
moveToParent,
|
||||
createParentNavigator,
|
||||
};
|
||||
}
|
||||
|
||||
return {
|
||||
getStackSize,
|
||||
getGrandparentNode,
|
||||
getParentNode,
|
||||
getCurrentNode,
|
||||
getKind,
|
||||
pushNode,
|
||||
tryPushNode,
|
||||
setNode,
|
||||
popNode,
|
||||
findAncestorNode,
|
||||
createParentNavigator,
|
||||
};
|
||||
}
|
||||
|
||||
export const enum AssertionLevel {
|
||||
None = 0,
|
||||
Normal = 1,
|
||||
|
|
|
@ -443,7 +443,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function emitTypeReference(type: TypeReferenceNode) {
|
||||
emitEntityName(type.typeName);
|
||||
if (type.typeArguments) {
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
/// <reference path="checker.ts"/>
|
||||
/// <reference path="declarationEmitter.ts"/>
|
||||
/// <reference path="transform.ts"/>
|
||||
/// <reference path="printer.ts"/>
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
|
@ -8199,11 +8201,101 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
|||
}
|
||||
|
||||
function emitFile(jsFilePath: string, sourceFile?: SourceFile) {
|
||||
emitJavaScript(jsFilePath, sourceFile);
|
||||
if (compilerOptions.experimentalTransforms) {
|
||||
let writer = createTextWriter(host.getNewLine());
|
||||
let nodes = sourceFile ? [sourceFile] : host.getSourceFiles();
|
||||
let transformationChain = getTransformationChain(compilerOptions);
|
||||
let sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap
|
||||
? createSourceMapWriter(host, writer, jsFilePath, sourceFile)
|
||||
: getNullSourceMapWriter();
|
||||
|
||||
printFiles(resolver, host, writer, filter(nodes, isNonDeclarationFile), transformationChain, sourceMap);
|
||||
|
||||
if (compilerOptions.sourceMap) {
|
||||
writeFile(host, diagnostics, jsFilePath + ".map", sourceMap.getText(), /*writeByteOrderMark*/ false);
|
||||
}
|
||||
|
||||
writeFile(host, diagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM);
|
||||
}
|
||||
else {
|
||||
emitJavaScript(jsFilePath, sourceFile);
|
||||
}
|
||||
|
||||
if (compilerOptions.declaration) {
|
||||
writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
// @internal
|
||||
export function emitFilesUsingTransforms(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
let compilerOptions = host.getCompilerOptions();
|
||||
let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
|
||||
let diagnostics: Diagnostic[] = [];
|
||||
let jsxDesugaring = host.getCompilerOptions().jsx !== JsxEmit.Preserve;
|
||||
let shouldEmitJsx = (s: SourceFile) => (s.languageVariant === LanguageVariant.JSX && !jsxDesugaring);
|
||||
|
||||
if (targetSourceFile === undefined) {
|
||||
forEach(host.getSourceFiles(), sourceFile => {
|
||||
if (shouldEmitToOwnFile(sourceFile, compilerOptions)) {
|
||||
let jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, shouldEmitJsx(sourceFile) ? ".jsx" : ".js");
|
||||
printFile(jsFilePath, sourceFile);
|
||||
}
|
||||
});
|
||||
|
||||
if (compilerOptions.outFile || compilerOptions.out) {
|
||||
printFile(compilerOptions.outFile || compilerOptions.out);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// targetSourceFile is specified (e.g calling emitter from language service or calling getSemanticDiagnostic from language service)
|
||||
if (shouldEmitToOwnFile(targetSourceFile, compilerOptions)) {
|
||||
let jsFilePath = getOwnEmitOutputFilePath(targetSourceFile, host, shouldEmitJsx(targetSourceFile) ? ".jsx" : ".js");
|
||||
printFile(jsFilePath, targetSourceFile);
|
||||
}
|
||||
else if (!isDeclarationFile(targetSourceFile) && (compilerOptions.outFile || compilerOptions.out)) {
|
||||
printFile(compilerOptions.outFile || compilerOptions.out);
|
||||
}
|
||||
}
|
||||
|
||||
// Sort and make the unique list of diagnostics
|
||||
diagnostics = sortAndDeduplicateDiagnostics(diagnostics);
|
||||
|
||||
return {
|
||||
emitSkipped: false,
|
||||
diagnostics,
|
||||
sourceMaps: sourceMapDataList
|
||||
};
|
||||
|
||||
function printFile(jsFilePath: string, sourceFile?: SourceFile) {
|
||||
let writer = createTextWriter(host.getNewLine());
|
||||
let nodes = sourceFile ? [sourceFile] : host.getSourceFiles();
|
||||
let transformationChain = getTransformationChain(compilerOptions);
|
||||
let sourceMap = compilerOptions.sourceMap || compilerOptions.inlineSourceMap
|
||||
? createSourceMapWriter(host, writer, jsFilePath, sourceFile)
|
||||
: getNullSourceMapWriter();
|
||||
|
||||
// Print each file to the writer after executing the transformation chain.
|
||||
printFiles(resolver, host, writer, filter(nodes, isNonDeclarationFile), transformationChain, sourceMap);
|
||||
|
||||
// Write the output file.
|
||||
writeFile(host, diagnostics, jsFilePath, writer.getText(), compilerOptions.emitBOM);
|
||||
|
||||
// If source maps were requested, write the source map.
|
||||
if (compilerOptions.sourceMap) {
|
||||
writeFile(host, diagnostics, jsFilePath + ".map", sourceMap.getText(), /*writeByteOrderMark*/ false);
|
||||
}
|
||||
|
||||
// If declarations were requested, write the declaration file.
|
||||
if (compilerOptions.declaration) {
|
||||
writeDeclarationFile(jsFilePath, sourceFile, host, resolver, diagnostics);
|
||||
}
|
||||
|
||||
// Record source map data for the test harness.
|
||||
if (sourceMapDataList) {
|
||||
sourceMapDataList.push(sourceMap.sourceMapData);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
2287
src/compiler/factory.generated.ts
Normal file
2287
src/compiler/factory.generated.ts
Normal file
File diff suppressed because it is too large
Load diff
672
src/compiler/factory.ts
Normal file
672
src/compiler/factory.ts
Normal file
|
@ -0,0 +1,672 @@
|
|||
/// <reference path="core.ts"/>
|
||||
/// <reference path="factory.generated.ts" />
|
||||
namespace ts {
|
||||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
export function setNodeFlags<T extends Node>(node: T, flags: NodeFlags): T {
|
||||
if (!node || flags === undefined) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node.flags = flags;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setTextRange<T extends TextRange>(node: T, range: TextRange): T {
|
||||
if (!node || !range) {
|
||||
return node;
|
||||
}
|
||||
|
||||
node.pos = range.pos;
|
||||
node.end = range.end;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setModifiers<T extends Node>(node: T, modifiers: Node[]): T {
|
||||
if (modifiers) {
|
||||
node.modifiers = createModifiersArray(modifiers);
|
||||
node.flags |= node.modifiers.flags;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function setOriginalNode<T extends Node>(node: T, original: Node): T {
|
||||
if (node && node !== original) {
|
||||
node.original = node;
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function attachCommentRanges<T extends Node>(node: T, leadingCommentRanges: CommentRange[], trailingCommentRanges?: CommentRange[]): T {
|
||||
(<SynthesizedNode>node).leadingCommentRanges = leadingCommentRanges;
|
||||
(<SynthesizedNode>node).trailingCommentRanges = trailingCommentRanges;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function startOnNewLine<T extends Node>(node: T, value?: boolean): T {
|
||||
(<SynthesizedNode>node).startsOnNewLine = value === undefined ? true : value;
|
||||
return node;
|
||||
}
|
||||
|
||||
export function updateFrom<T extends Node>(oldNode: T, newNode: T): T {
|
||||
let flags = oldNode.flags;
|
||||
if (oldNode.modifiers) {
|
||||
flags &= ~oldNode.modifiers.flags;
|
||||
}
|
||||
|
||||
if (newNode.modifiers) {
|
||||
flags |= newNode.modifiers.flags;
|
||||
}
|
||||
|
||||
newNode.flags = flags;
|
||||
newNode.original = oldNode;
|
||||
newNode.pos = oldNode.pos;
|
||||
newNode.end = oldNode.end;
|
||||
newNode.id = oldNode.id;
|
||||
|
||||
//mergeCommentRanges(oldNode, newNode);
|
||||
return newNode;
|
||||
}
|
||||
|
||||
function mergeCommentRanges(oldNode: Node, newNode: Node) {
|
||||
if ((<SynthesizedNode>oldNode).leadingCommentRanges && !(<SynthesizedNode>newNode).leadingCommentRanges) {
|
||||
(<SynthesizedNode>newNode).leadingCommentRanges = (<SynthesizedNode>oldNode).leadingCommentRanges;
|
||||
}
|
||||
if ((<SynthesizedNode>oldNode).trailingCommentRanges && !(<SynthesizedNode>newNode).trailingCommentRanges) {
|
||||
(<SynthesizedNode>newNode).trailingCommentRanges = (<SynthesizedNode>oldNode).trailingCommentRanges;
|
||||
}
|
||||
}
|
||||
|
||||
export function cloneNodeArray<T extends Node>(array: NodeArray<T>): NodeArray<T> {
|
||||
return array ? createNodeArray(array.slice(0), /*location*/ array) : undefined;
|
||||
}
|
||||
|
||||
export function createSynthesizedNode<T extends Node>(kind: SyntaxKind, startsOnNewLine?: boolean): T {
|
||||
let node = createNode<T>(kind);
|
||||
if (startsOnNewLine) {
|
||||
startOnNewLine(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createNode<T extends Node>(kind: SyntaxKind, location?: TextRange, flags?: NodeFlags): T {
|
||||
let pos = location !== undefined ? location.pos : -1;
|
||||
let end = location !== undefined ? location.end : -1;
|
||||
|
||||
let node: T;
|
||||
if (kind === SyntaxKind.SourceFile) {
|
||||
node = <T>new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
|
||||
}
|
||||
else {
|
||||
node = <T>new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, pos, end);
|
||||
}
|
||||
|
||||
if (flags) {
|
||||
node.flags = flags;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createSynthesizedNodeArray<T extends Node>(elements?: T[]) {
|
||||
return createNodeArray<T>(elements);
|
||||
}
|
||||
|
||||
export function createNodeArray<T extends Node>(elements?: T[], location?: TextRange) {
|
||||
let nodes = <NodeArray<T>>(elements || []);
|
||||
if (location) {
|
||||
nodes.pos = location.pos;
|
||||
nodes.end = location.end;
|
||||
}
|
||||
if (nodes.pos === undefined || nodes.end === undefined) {
|
||||
nodes.pos = -1;
|
||||
nodes.end = -1;
|
||||
}
|
||||
|
||||
return nodes;
|
||||
}
|
||||
|
||||
export function createModifiersArray(elements?: Node[], location?: TextRange) {
|
||||
let modifiers = <ModifiersArray>createNodeArray(elements || [], location);
|
||||
if (modifiers.flags === undefined) {
|
||||
let flags = 0;
|
||||
for (let modifier of modifiers) {
|
||||
flags |= modifierToFlag(modifier.kind);
|
||||
}
|
||||
|
||||
modifiers.flags = flags;
|
||||
}
|
||||
|
||||
return modifiers;
|
||||
}
|
||||
|
||||
export function createNumericLiteral2(value: number, location?: TextRange, flags?: NodeFlags): LiteralExpression {
|
||||
let node = createNumericLiteral(String(value), location, flags);
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createPropertyAccessExpression2(expression: Expression, name: Identifier, location?: TextRange, flags?: NodeFlags) {
|
||||
return createPropertyAccessExpression(parenthesizeForAccess(expression), createNode(SyntaxKind.DotToken), name, location, flags);
|
||||
}
|
||||
|
||||
export function createPropertyAccessExpression3(expression: Expression, name: string, location?: TextRange, flags?: NodeFlags) {
|
||||
return createPropertyAccessExpression(parenthesizeForAccess(expression), createNode(SyntaxKind.DotToken), createIdentifier(name), location, flags);
|
||||
}
|
||||
|
||||
export function makeSynthesized<TNode extends Node>(node: TNode): TNode {
|
||||
return nodeIsSynthesized(node) ? node : cloneNode(node, /*location*/ undefined, node.flags);
|
||||
}
|
||||
|
||||
const cloneExcludedProperties: Map<boolean> = {
|
||||
"pos": true,
|
||||
"end": true,
|
||||
"flags": true,
|
||||
"original": true,
|
||||
"transformFlags": true,
|
||||
"excludeTransformFlags": true,
|
||||
"createParentNavigator": true
|
||||
};
|
||||
|
||||
export function cloneNode<T extends Node>(node: T, location?: TextRange, flags?: NodeFlags): T {
|
||||
let clone = createNode<T>(node.kind);
|
||||
for (let id in node) {
|
||||
if (hasProperty(cloneExcludedProperties, id)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
(<any>clone)[id] = (<any>node)[id];
|
||||
}
|
||||
|
||||
if (location !== undefined) {
|
||||
clone.pos = location.pos;
|
||||
clone.end = location.end;
|
||||
}
|
||||
|
||||
if (flags !== undefined) {
|
||||
clone.flags = flags;
|
||||
}
|
||||
|
||||
return clone;
|
||||
}
|
||||
|
||||
const enum BinaryOperandSide {
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
|
||||
function parenthesizeForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (operand.kind === SyntaxKind.TypeAssertionExpression || operand.kind === SyntaxKind.AsExpression) {
|
||||
operand = (<AssertionExpression>operand).expression;
|
||||
}
|
||||
|
||||
// If the resulting expression is already parenthesized, we do not need to do any further processing.
|
||||
if (isParenthesizedExpression(operand)) {
|
||||
return operand;
|
||||
}
|
||||
|
||||
return needsParenthesesForBinary(operand, operator, side)
|
||||
? createParenthesizedExpression(operand)
|
||||
: operand;
|
||||
}
|
||||
|
||||
function needsParenthesesForBinary(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
let operandPrecedence = getExpressionPrecedence(operand);
|
||||
let operatorPrecedence = getBinaryOperatorPrecedence(operator);
|
||||
switch (compareValues(operandPrecedence, operatorPrecedence)) {
|
||||
case Comparison.LessThan:
|
||||
return true;
|
||||
case Comparison.EqualTo:
|
||||
return isRightAssociativeOperandOnLeftHandSide(operand, side)
|
||||
|| isModuloOperandOnRightHandSide(operand, operator, side);
|
||||
case Comparison.GreaterThan:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function isRightAssociativeOperandOnLeftHandSide(operand: Expression, side: BinaryOperandSide) {
|
||||
return side === BinaryOperandSide.Left
|
||||
&& getExpressionAssociativity(operand) === Associativity.Right;
|
||||
}
|
||||
|
||||
function isModuloOperandOnRightHandSide(operand: Expression, operator: SyntaxKind, side: BinaryOperandSide) {
|
||||
return side === BinaryOperandSide.Right
|
||||
&& operator !== SyntaxKind.PercentToken
|
||||
&& isBinaryExpression(operand)
|
||||
&& operand.operatorToken.kind === SyntaxKind.PercentToken;
|
||||
}
|
||||
|
||||
export function parenthesizeForAccess(expr: Expression): LeftHandSideExpression {
|
||||
// When diagnosing whether the expression needs parentheses, the decision should be based
|
||||
// on the innermost expression in a chain of nested type assertions.
|
||||
while (expr.kind === SyntaxKind.TypeAssertionExpression || expr.kind === SyntaxKind.AsExpression) {
|
||||
expr = (<AssertionExpression>expr).expression;
|
||||
}
|
||||
|
||||
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
|
||||
// to parenthesize the expression before a dot. The known exceptions are:
|
||||
//
|
||||
// NewExpression:
|
||||
// new C.x -> not the same as (new C).x
|
||||
// NumberLiteral
|
||||
// 1.x -> not the same as (1).x
|
||||
//
|
||||
if (isLeftHandSideExpression(expr) &&
|
||||
expr.kind !== SyntaxKind.NewExpression &&
|
||||
expr.kind !== SyntaxKind.NumericLiteral) {
|
||||
|
||||
return <LeftHandSideExpression>expr;
|
||||
}
|
||||
|
||||
return createParenthesizedExpression(expr);
|
||||
}
|
||||
|
||||
export function createCallExpression2(expression: Expression, _arguments?: Expression[], location?: TextRange, flags?: NodeFlags) {
|
||||
return createCallExpression(parenthesizeForAccess(expression), undefined, _arguments, location, flags);
|
||||
}
|
||||
|
||||
export function createPropertyAssignment2(name: string, initializer: Expression) {
|
||||
return createPropertyAssignment(createIdentifier(name), initializer);
|
||||
}
|
||||
|
||||
export function createAssignmentStatement(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createExpressionStatement(createAssignmentExpression(left, right), location);
|
||||
}
|
||||
|
||||
export function createAssignmentExpression(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createBinaryExpression2(left, SyntaxKind.EqualsToken, right, location);
|
||||
}
|
||||
|
||||
export function createStrictEqualityExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.EqualsEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createStrictInequalityExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.ExclamationEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createLogicalNotExpression(operand: LeftHandSideExpression) {
|
||||
return createPrefixUnaryExpression(SyntaxKind.ExclamationToken, operand);
|
||||
}
|
||||
|
||||
export function createLogicalAndExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.AmpersandAmpersandToken, right);
|
||||
}
|
||||
|
||||
export function createLogicalOrExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.BarBarToken, right);
|
||||
}
|
||||
|
||||
export function createLessThanExpression(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createBinaryExpression2(left, SyntaxKind.LessThanToken, right, location);
|
||||
}
|
||||
|
||||
export function createAddExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.PlusToken, right);
|
||||
}
|
||||
|
||||
export function createSubtractExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.MinusToken, right);
|
||||
}
|
||||
|
||||
export function createCommaExpression(left: Expression, right: Expression) {
|
||||
return createBinaryExpression2(left, SyntaxKind.CommaToken, right);
|
||||
}
|
||||
|
||||
export function createBinaryExpression2(left: Expression, operator: SyntaxKind, right: Expression, location?: TextRange) {
|
||||
return createBinaryExpression(parenthesizeForBinary(left, operator, BinaryOperandSide.Left), createNode(operator), parenthesizeForBinary(right, operator, BinaryOperandSide.Right), location);
|
||||
}
|
||||
|
||||
export function createConditionalExpression2(condition: Expression, whenTrue: Expression, whenFalse: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createConditionalExpression(condition, createNode(SyntaxKind.QuestionToken), whenTrue, createNode(SyntaxKind.ColonToken), whenFalse, location, flags);
|
||||
}
|
||||
|
||||
export function createParameter2(name: BindingPattern | Identifier, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createParameter(undefined, undefined, undefined, name, undefined, undefined, initializer, location, flags);
|
||||
}
|
||||
|
||||
export function createParameter3(name: string) {
|
||||
return createParameter2(createIdentifier(name));
|
||||
}
|
||||
|
||||
export function createRestParameter(name: Identifier, location?: TextRange, flags?: NodeFlags) {
|
||||
return createParameter(undefined, undefined, createNode(SyntaxKind.DotDotDotToken), name, undefined, undefined, undefined, location, flags);
|
||||
}
|
||||
|
||||
export function createVariableDeclarationList2(name: Identifier | BindingPattern, initializer?: Expression) {
|
||||
return createVariableDeclarationList([createVariableDeclaration2(name, initializer)]);
|
||||
}
|
||||
|
||||
export function createVariableDeclaration2(name: Identifier | BindingPattern, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createVariableDeclaration(name, undefined, initializer, location, flags);
|
||||
}
|
||||
|
||||
export function createVariableStatement2(declarationList: VariableDeclarationList, location?: TextRange, flags?: NodeFlags) {
|
||||
return createVariableStatement(undefined, undefined, declarationList, location, flags);
|
||||
}
|
||||
|
||||
export function createVariableStatement3(name: Identifier | BindingPattern, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
let varDecl = createVariableDeclaration2(name, initializer);
|
||||
let varDeclList = createVariableDeclarationList([varDecl], undefined, flags & (NodeFlags.Let | NodeFlags.Const));
|
||||
return createVariableStatement2(varDeclList, location, flags & ~(NodeFlags.Let | NodeFlags.Const));
|
||||
}
|
||||
|
||||
export function createVariableStatement4(name: string, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createVariableStatement3(createIdentifier(name), initializer, location, flags);
|
||||
}
|
||||
|
||||
export function createLetStatement(name: Identifier, initializer: Expression, location?: TextRange, exported?: boolean) {
|
||||
return createVariableStatement3(name, initializer, location, exported ? NodeFlags.Let | NodeFlags.Export : NodeFlags.Let);
|
||||
}
|
||||
|
||||
export function createExportDefaultStatement(expression: Expression): ExportAssignment {
|
||||
return createExportAssignment(undefined, undefined, expression);
|
||||
}
|
||||
|
||||
function createClassHeritageClauses(baseTypeNode: ExpressionWithTypeArguments) {
|
||||
return baseTypeNode ? [createHeritageClause(SyntaxKind.ExtendsKeyword, [baseTypeNode])] : undefined;
|
||||
}
|
||||
|
||||
export function createClassDeclaration2(name: Identifier, baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[], location?: TextRange, flags?: NodeFlags): ClassDeclaration {
|
||||
return createClassDeclaration(undefined, undefined, name, undefined, createClassHeritageClauses(baseTypeNode), members, location, flags);
|
||||
}
|
||||
|
||||
export function createClassExpression2(name: Identifier, baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[], location?: TextRange): ClassExpression {
|
||||
return createClassExpression(undefined, undefined, name, undefined, createClassHeritageClauses(baseTypeNode), members, location);
|
||||
}
|
||||
|
||||
export function createClassExpression3(baseTypeNode: ExpressionWithTypeArguments, members: ClassElement[]): ClassExpression {
|
||||
return createClassExpression2(undefined, baseTypeNode, members);
|
||||
}
|
||||
|
||||
export function createConstructor2(parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): ConstructorDeclaration {
|
||||
return createConstructor(undefined, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createMethodDeclaration2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): MethodDeclaration {
|
||||
return createMethodDeclaration(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createGetAccessor2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): GetAccessorDeclaration {
|
||||
return createGetAccessor(undefined, undefined, name, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createSetAccessor2(name: PropertyName, parameters: Array<ParameterDeclaration>, body: Block, location?: TextRange, flags?: NodeFlags): SetAccessorDeclaration {
|
||||
return createSetAccessor(undefined, undefined, name, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createFunctionDeclaration2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionDeclaration(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createFunctionDeclaration3(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionDeclaration(undefined, undefined, asteriskToken, name, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createFunctionExpression2(name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionExpression(undefined, undefined, undefined, name, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createFunctionExpression3(parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionExpression(undefined, undefined, undefined, undefined, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createFunctionExpression4(asteriskToken: Node, name: Identifier, parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionExpression(undefined, undefined, asteriskToken, name, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createArrowFunction2(parameters: ParameterDeclaration[], body: Block | Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createArrowFunction(undefined, undefined, undefined, parameters, undefined, createNode(SyntaxKind.EqualsGreaterThanToken), body, location, flags);
|
||||
}
|
||||
|
||||
export function createGeneratorFunctionExpression(parameters: ParameterDeclaration[], body: Block, location?: TextRange, flags?: NodeFlags) {
|
||||
return createFunctionExpression(undefined, undefined, createNode(SyntaxKind.AsteriskToken), undefined, undefined, parameters, undefined, body, location, flags);
|
||||
}
|
||||
|
||||
export function createVoidZeroExpression(location?: TextRange, flags?: NodeFlags): VoidExpression {
|
||||
return createVoidExpression(createNumericLiteral2(0), location, flags);
|
||||
}
|
||||
|
||||
export function createPropertyOrElementAccessExpression(expression: Expression, propName: Identifier | LiteralExpression, location?: TextRange, flags?: NodeFlags): LeftHandSideExpression {
|
||||
return isIdentifier(propName)
|
||||
? createPropertyAccessExpression2(expression, makeSynthesized(propName), location, flags)
|
||||
: createElementAccessExpression2(expression, makeSynthesized(propName), location, flags);
|
||||
}
|
||||
|
||||
export function createElementAccessExpression2(expression: Expression, argumentExpression: Expression, location?: TextRange, flags?: NodeFlags): ElementAccessExpression {
|
||||
return createElementAccessExpression(parenthesizeForAccess(expression), argumentExpression, location, flags);
|
||||
}
|
||||
|
||||
export function createElementAccessExpression3(expression: Expression, index: number, location?: TextRange, flags?: NodeFlags): ElementAccessExpression {
|
||||
return createElementAccessExpression2(expression, createNumericLiteral2(index), location, flags);
|
||||
}
|
||||
|
||||
export function createObjectLiteralExpression2(propertyMap: Map<Expression>) {
|
||||
let properties: PropertyAssignment[] = [];
|
||||
for (let key in propertyMap) {
|
||||
if (hasProperty(propertyMap, key)) {
|
||||
properties.push(createPropertyAssignment2(key, propertyMap[key]));
|
||||
}
|
||||
}
|
||||
|
||||
return createObjectLiteralExpression(properties);
|
||||
}
|
||||
|
||||
export function createConcatCall(value: Expression, _arguments: Expression[]) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(value, "concat"), _arguments);
|
||||
}
|
||||
|
||||
export function createSliceCall(value: Expression, sliceIndex?: number, location?: TextRange, flags?: NodeFlags): CallExpression {
|
||||
let sliceArguments: Expression[] = typeof sliceIndex === "number" ? [createNumericLiteral2(sliceIndex)] : [];
|
||||
return createCallExpression2(createPropertyAccessExpression3(value, "slice"), sliceArguments, location, flags);
|
||||
}
|
||||
|
||||
export function createCallCall(target: Expression, thisArg: Expression, _arguments: Expression[], location?: TextRange, flags?: NodeFlags) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(target, "call"), [thisArg, ..._arguments], location, flags);
|
||||
}
|
||||
|
||||
export function createApplyCall(target: Expression, thisArg: Expression, _arguments: Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(target, "apply"), [thisArg, _arguments], location, flags);
|
||||
}
|
||||
|
||||
export function createMathPowCall(left: Expression, right: Expression, location?: TextRange) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Math"), "pow"), [left, right], location);
|
||||
}
|
||||
|
||||
export function createExtendsHelperCall(name: Identifier) {
|
||||
return createCallExpression2(createIdentifier("__extends"), [name, createIdentifier("_super")]);
|
||||
}
|
||||
|
||||
export function createAwaiterHelperCall(hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
|
||||
let argumentsExpr = hasLexicalArguments ? createIdentifier("arguments") : createVoidZeroExpression();
|
||||
let promiseExpr = promiseConstructor ? convertEntityNameToExpression(promiseConstructor) : createIdentifier("Promise");
|
||||
return createCallExpression2(createIdentifier("__awaiter"), [createThisKeyword(), argumentsExpr, promiseExpr, createGeneratorFunctionExpression([], body)]);
|
||||
}
|
||||
|
||||
export function convertEntityNameToExpression(node: EntityName | Expression): Expression {
|
||||
return isQualifiedName(node) ? createPropertyAccessExpression2(convertEntityNameToExpression(node.left), cloneNode(node.right)) : cloneNode(node);
|
||||
}
|
||||
|
||||
export function createDecorateHelperCall(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) {
|
||||
return createCallExpression2(createIdentifier("__decorate"), append([createArrayLiteralExpression(decoratorExpressions), target], memberName, descriptor));
|
||||
}
|
||||
|
||||
export function createParamHelperCall(parameterIndex: number, decoratorExpression: Expression) {
|
||||
return createCallExpression2(createIdentifier("__param"), [createNumericLiteral2(parameterIndex), decoratorExpression]);
|
||||
}
|
||||
|
||||
export function createMetadataHelperCall(metadataKey: string, metadataValue: Expression) {
|
||||
return createCallExpression2(createIdentifier("__metadata"), [createStringLiteral(metadataKey), metadataValue]);
|
||||
}
|
||||
|
||||
export function createHasOwnPropertyCall(target: LeftHandSideExpression, property: Expression) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(target, "hasOwnProperty"), [property]);
|
||||
}
|
||||
|
||||
export function createExportStarHelperCall(moduleValue: Expression) {
|
||||
return createCallExpression2(createIdentifier("__export"), [moduleValue]);
|
||||
}
|
||||
|
||||
export const enum PropertyDescriptorFlags {
|
||||
Empty = 0,
|
||||
|
||||
Enumerable = 1 << 0,
|
||||
NotEnumerable = 1 << 1,
|
||||
|
||||
Configurable = 1 << 2,
|
||||
NotConfigurable = 1 << 3,
|
||||
|
||||
Writable = 1 << 4,
|
||||
NotWritable = 1 << 5,
|
||||
|
||||
PreferNewLine = 1 << 6,
|
||||
|
||||
Default = Enumerable | Configurable | Writable | PreferNewLine,
|
||||
DefaultDataProperty = Enumerable | Configurable | Writable | PreferNewLine,
|
||||
DefaultAccessorProperty = Enumerable | Configurable | PreferNewLine,
|
||||
|
||||
EnumerableMask = Enumerable | NotEnumerable,
|
||||
ConfigurableMask = Configurable | NotConfigurable,
|
||||
WritableMask = Writable | NotWritable,
|
||||
|
||||
TrueMask = Enumerable | Configurable | Writable,
|
||||
FalseMask = NotEnumerable | NotConfigurable | NotWritable,
|
||||
|
||||
DataPropertyMask = EnumerableMask | ConfigurableMask | WritableMask,
|
||||
AccessorPropertyMask = EnumerableMask | ConfigurableMask,
|
||||
}
|
||||
|
||||
export function createDataPropertyDescriptor(value: Expression, flags?: PropertyDescriptorFlags) {
|
||||
return createPropertyDescriptor(/*get*/ undefined, /*set*/ undefined, value, flags);
|
||||
}
|
||||
|
||||
export function createAccessorPropertyDescriptor(get: Expression, set: Expression, flags?: PropertyDescriptorFlags) {
|
||||
return createPropertyDescriptor(get, set, /*value*/ undefined, flags);
|
||||
}
|
||||
|
||||
function createPropertyDescriptor(get: Expression, set: Expression, value: Expression, flags: PropertyDescriptorFlags = PropertyDescriptorFlags.Default) {
|
||||
let isDataProperty = get === undefined && set === undefined;
|
||||
let properties: ObjectLiteralElement[] = [];
|
||||
addPropertyDescriptorProperty(properties, isDataProperty, "get", flags, get);
|
||||
addPropertyDescriptorProperty(properties, isDataProperty, "set", flags, set);
|
||||
addPropertyDescriptorProperty(properties, isDataProperty, "value", flags, value);
|
||||
addPropertyDescriptorOption(properties, isDataProperty, "enumerable", flags, PropertyDescriptorFlags.EnumerableMask);
|
||||
addPropertyDescriptorOption(properties, isDataProperty, "configurable", flags, PropertyDescriptorFlags.ConfigurableMask);
|
||||
addPropertyDescriptorOption(properties, isDataProperty, "writable", flags, PropertyDescriptorFlags.WritableMask);
|
||||
return createObjectLiteralExpression(properties);
|
||||
}
|
||||
|
||||
function addPropertyDescriptorProperty(properties: ObjectLiteralElement[], isDataProperty: boolean, propertyName: string, flags: PropertyDescriptorFlags, propertyValue: Expression) {
|
||||
if (propertyValue && isDataProperty === (propertyName === "value")) {
|
||||
let property = createPropertyAssignment2(propertyName, propertyValue);
|
||||
startOnNewLine(property, (flags & PropertyDescriptorFlags.PreferNewLine) !== 0);
|
||||
properties.push(property);
|
||||
}
|
||||
}
|
||||
|
||||
function addPropertyDescriptorOption(properties: ObjectLiteralElement[], isDataProperty: boolean, optionName: string, flags: PropertyDescriptorFlags, optionMask: PropertyDescriptorFlags) {
|
||||
let flagsMask = isDataProperty
|
||||
? PropertyDescriptorFlags.DataPropertyMask
|
||||
: PropertyDescriptorFlags.AccessorPropertyMask;
|
||||
|
||||
if (flags & flagsMask & optionMask) {
|
||||
let propertyValue = flags & PropertyDescriptorFlags.FalseMask
|
||||
? createFalseKeyword()
|
||||
: createTrueKeyword();
|
||||
|
||||
let property = createPropertyAssignment2(optionName, propertyValue);
|
||||
startOnNewLine(property, (flags & PropertyDescriptorFlags.PreferNewLine) !== 0);
|
||||
properties.push(property);
|
||||
}
|
||||
}
|
||||
|
||||
export function createDefinePropertyCall(target: Expression, memberName: Expression, descriptor: Expression, location?: TextRange) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "defineProperty"), [target, memberName, descriptor], location);
|
||||
}
|
||||
|
||||
export function createDefinePropertyCall2(target: Expression, memberName: Expression, getter: Expression, setter: Expression, location?: TextRange) {
|
||||
let descriptor = createAccessorPropertyDescriptor(getter, setter, PropertyDescriptorFlags.DefaultAccessorProperty);
|
||||
return createDefinePropertyCall(target, memberName, descriptor, location);
|
||||
}
|
||||
|
||||
export function createGetOwnPropertyDescriptorCall(target: Expression, memberName: Expression) {
|
||||
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("Object"), "getOwnPropertyDescriptor"), [target, memberName]);
|
||||
}
|
||||
|
||||
export function createReactCreateElementCall(tagName: Expression, props: Expression, children: Expression[]): LeftHandSideExpression {
|
||||
let args: Expression[] = [tagName];
|
||||
if (props) {
|
||||
args.push(props)
|
||||
}
|
||||
if (children && children.length > 0) {
|
||||
if (!props) {
|
||||
args.push(<Expression>createNode(SyntaxKind.NullKeyword));
|
||||
}
|
||||
|
||||
args.push(...children);
|
||||
}
|
||||
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("React"), "createElement"), args);
|
||||
}
|
||||
|
||||
export function createReactSpreadCall(segments: Expression[]): LeftHandSideExpression {
|
||||
return createCallExpression2(createPropertyAccessExpression3(createIdentifier("React"), "__spread"), segments);
|
||||
}
|
||||
|
||||
export function createMemberAccessForPropertyName(target: Expression, memberName: PropertyName, location?: TextRange, flags?: NodeFlags): MemberExpression {
|
||||
return isIdentifier(memberName) ? createPropertyAccessExpression2(target, cloneNode(memberName), location, flags)
|
||||
: isComputedPropertyName(memberName) ? createElementAccessExpression2(target, cloneNode(memberName.expression), location, flags)
|
||||
: createElementAccessExpression2(target, cloneNode(memberName), location, flags);
|
||||
}
|
||||
|
||||
export function createStringLiteralForIdentifier(name: Identifier): StringLiteral {
|
||||
return createStringLiteral(name.text)
|
||||
}
|
||||
|
||||
export function createExpressionForPropertyName(memberName: PropertyName, location?: TextRange): Expression {
|
||||
return isIdentifier(memberName) ? createStringLiteral(memberName.text, location)
|
||||
: isComputedPropertyName(memberName) ? cloneNode(memberName.expression, location)
|
||||
: cloneNode(memberName, location);
|
||||
}
|
||||
|
||||
export function makeFunctionBody(body: ConciseBody): FunctionBody {
|
||||
return isBlock(body) ? body : createBlock([createReturnStatement(body)]);
|
||||
}
|
||||
|
||||
export function inlineExpressions(expressions: Expression[]) {
|
||||
return reduceLeft(expressions, createCommaExpression);
|
||||
}
|
||||
|
||||
export function isDeclarationStatement(node: Node): node is DeclarationStatement {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
case SyntaxKind.MissingDeclaration:
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.InterfaceDeclaration:
|
||||
case SyntaxKind.TypeAliasDeclaration:
|
||||
case SyntaxKind.EnumDeclaration:
|
||||
case SyntaxKind.ModuleDeclaration:
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function createIsObjectExpression(expression: LeftHandSideExpression) {
|
||||
return createStrictEqualityExpression(createTypeOfExpression(expression), createStringLiteral("object"));
|
||||
}
|
||||
|
||||
function createIsFunctionExpression(expression: LeftHandSideExpression) {
|
||||
return createStrictEqualityExpression(createTypeOfExpression(expression), createStringLiteral("function"));
|
||||
}
|
||||
|
||||
function createIsNotUndefinedExpression(expression: LeftHandSideExpression) {
|
||||
return createStrictInequalityExpression(expression, createVoidZeroExpression());
|
||||
}
|
||||
}
|
|
@ -1,3 +1,4 @@
|
|||
/// <reference path="factory.ts"/>
|
||||
/// <reference path="utilities.ts"/>
|
||||
/// <reference path="scanner.ts"/>
|
||||
|
||||
|
@ -7,7 +8,7 @@ namespace ts {
|
|||
let NodeConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
let SourceFileConstructor: new (kind: SyntaxKind, pos: number, end: number) => Node;
|
||||
|
||||
export function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
|
||||
function createNode(kind: SyntaxKind, pos?: number, end?: number): Node {
|
||||
if (kind === SyntaxKind.SourceFile) {
|
||||
return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, pos, end);
|
||||
}
|
||||
|
@ -407,6 +408,25 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
|
||||
// @internal
|
||||
export function parseSynthesizedStatements(sourceText: string) {
|
||||
let sourceFile = Parser.parseSourceFile("parseStatement.ts", sourceText, ScriptTarget.Latest, /*syntaxCursor*/ undefined, /*setParentNodes*/ false, /*synthesized*/ true);
|
||||
return sourceFile.statements;
|
||||
}
|
||||
|
||||
// @internal
|
||||
export function parseSynthesizedStatement(sourceText: string) {
|
||||
let statements = parseSynthesizedStatements(sourceText);
|
||||
return firstOrUndefined(statements);
|
||||
}
|
||||
|
||||
// @internal
|
||||
export function parseSynthesizedExpression(sourceText: string) {
|
||||
let statement = parseSynthesizedStatement(`(${sourceText})`);
|
||||
let expression = (<ExpressionStatement>statement).expression;
|
||||
return (<ParenthesizedExpression>expression).expression;
|
||||
}
|
||||
|
||||
// Produces a new SourceFile for the 'newText' provided. The 'textChangeRange' parameter
|
||||
// indicates what changed between the 'text' that this SourceFile has and the 'newText'.
|
||||
// The SourceFile will be created with the compiler attempting to reuse as many nodes from
|
||||
|
@ -533,11 +553,11 @@ namespace ts {
|
|||
// attached to the EOF token.
|
||||
let parseErrorBeforeNextFinishedNode = false;
|
||||
|
||||
export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean): SourceFile {
|
||||
export function parseSourceFile(fileName: string, _sourceText: string, languageVersion: ScriptTarget, _syntaxCursor: IncrementalParser.SyntaxCursor, setParentNodes?: boolean, synthesized?: boolean): SourceFile {
|
||||
const isJavaScriptFile = hasJavaScriptFileExtension(fileName) || _sourceText.lastIndexOf("// @language=javascript", 0) === 0;
|
||||
initializeState(fileName, _sourceText, languageVersion, isJavaScriptFile, _syntaxCursor);
|
||||
|
||||
const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes);
|
||||
const result = parseSourceFileWorker(fileName, languageVersion, setParentNodes, synthesized);
|
||||
|
||||
clearState();
|
||||
|
||||
|
@ -580,7 +600,7 @@ namespace ts {
|
|||
sourceText = undefined;
|
||||
}
|
||||
|
||||
function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean): SourceFile {
|
||||
function parseSourceFileWorker(fileName: string, languageVersion: ScriptTarget, setParentNodes: boolean, synthesized: boolean): SourceFile {
|
||||
sourceFile = createSourceFile(fileName, languageVersion);
|
||||
|
||||
if (contextFlags & ParserContextFlags.JavaScriptFile) {
|
||||
|
@ -606,6 +626,10 @@ namespace ts {
|
|||
fixupParentReferences(sourceFile);
|
||||
}
|
||||
|
||||
if (synthesized) {
|
||||
makeSynthesized(sourceFile);
|
||||
}
|
||||
|
||||
// If this is a javascript file, proactively see if we can get JSDoc comments for
|
||||
// relevant nodes in the file. We'll use these to provide typing informaion if they're
|
||||
// available.
|
||||
|
@ -646,6 +670,22 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
|
||||
function makeSynthesized(sourceFile: Node) {
|
||||
visitNode(sourceFile);
|
||||
|
||||
function visitNode(n: Node) {
|
||||
delete n.pos;
|
||||
delete n.end;
|
||||
forEachChild(n, visitNode, visitNodes);
|
||||
}
|
||||
|
||||
function visitNodes(n: NodeArray<Node>) {
|
||||
delete n.pos;
|
||||
delete n.end;
|
||||
forEach(n, visitNode);
|
||||
}
|
||||
}
|
||||
|
||||
export function fixupParentReferences(sourceFile: Node) {
|
||||
// normally parent references are set during binding. However, for clients that only need
|
||||
// a syntax tree, and no semantic features, then the binding process is an unnecessary
|
||||
|
@ -1157,7 +1197,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function parseAnyContextualModifier(): boolean {
|
||||
return isModifier(token) && tryParse(nextTokenCanFollowModifier);
|
||||
return isModifierKind(token) && tryParse(nextTokenCanFollowModifier);
|
||||
}
|
||||
|
||||
function canFollowModifier(): boolean {
|
||||
|
@ -2004,7 +2044,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isStartOfParameter(): boolean {
|
||||
return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifier(token) || token === SyntaxKind.AtToken;
|
||||
return token === SyntaxKind.DotDotDotToken || isIdentifierOrPattern() || isModifierKind(token) || token === SyntaxKind.AtToken;
|
||||
}
|
||||
|
||||
function setModifiers(node: Node, modifiers: ModifiersArray) {
|
||||
|
@ -2025,7 +2065,7 @@ namespace ts {
|
|||
|
||||
node.name = parseIdentifierOrPattern();
|
||||
|
||||
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifier(token)) {
|
||||
if (getFullWidth(node.name) === 0 && node.flags === 0 && isModifierKind(token)) {
|
||||
// in cases like
|
||||
// 'use strict'
|
||||
// function foo(static)
|
||||
|
@ -2132,8 +2172,8 @@ namespace ts {
|
|||
parseSemicolon();
|
||||
}
|
||||
|
||||
function parseSignatureMember(kind: SyntaxKind): SignatureDeclaration {
|
||||
const node = <SignatureDeclaration>createNode(kind);
|
||||
function parseSignatureMember(kind: SyntaxKind): CallSignatureDeclaration | ConstructSignatureDeclaration {
|
||||
const node = <CallSignatureDeclaration | ConstructSignatureDeclaration>createNode(kind);
|
||||
if (kind === SyntaxKind.ConstructSignature) {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
}
|
||||
|
@ -2172,7 +2212,7 @@ namespace ts {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (isModifier(token)) {
|
||||
if (isModifierKind(token)) {
|
||||
nextToken();
|
||||
if (isIdentifier()) {
|
||||
return true;
|
||||
|
@ -2215,13 +2255,13 @@ namespace ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parsePropertyOrMethodSignature(): Declaration {
|
||||
function parsePropertyOrMethodSignature(): PropertySignature | MethodSignature {
|
||||
const fullStart = scanner.getStartPos();
|
||||
const name = parsePropertyName();
|
||||
const questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
|
||||
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.LessThanToken) {
|
||||
const method = <MethodDeclaration>createNode(SyntaxKind.MethodSignature, fullStart);
|
||||
const method = <MethodSignature>createNode(SyntaxKind.MethodSignature, fullStart);
|
||||
method.name = name;
|
||||
method.questionToken = questionToken;
|
||||
|
||||
|
@ -2232,7 +2272,7 @@ namespace ts {
|
|||
return finishNode(method);
|
||||
}
|
||||
else {
|
||||
const property = <PropertyDeclaration>createNode(SyntaxKind.PropertySignature, fullStart);
|
||||
const property = <PropertySignature>createNode(SyntaxKind.PropertySignature, fullStart);
|
||||
property.name = name;
|
||||
property.questionToken = questionToken;
|
||||
property.type = parseTypeAnnotation();
|
||||
|
@ -2248,7 +2288,7 @@ namespace ts {
|
|||
case SyntaxKind.OpenBracketToken: // Both for indexers and computed properties
|
||||
return true;
|
||||
default:
|
||||
if (isModifier(token)) {
|
||||
if (isModifierKind(token)) {
|
||||
const result = lookAhead(isStartOfIndexSignatureDeclaration);
|
||||
if (result) {
|
||||
return result;
|
||||
|
@ -2260,7 +2300,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function isStartOfIndexSignatureDeclaration() {
|
||||
while (isModifier(token)) {
|
||||
while (isModifierKind(token)) {
|
||||
nextToken();
|
||||
}
|
||||
|
||||
|
@ -2276,7 +2316,7 @@ namespace ts {
|
|||
canParseSemicolon();
|
||||
}
|
||||
|
||||
function parseTypeMember(): Declaration {
|
||||
function parseTypeMember(): TypeElement {
|
||||
switch (token) {
|
||||
case SyntaxKind.OpenParenToken:
|
||||
case SyntaxKind.LessThanToken:
|
||||
|
@ -2301,7 +2341,7 @@ namespace ts {
|
|||
// when incrementally parsing as the parser will produce the Index declaration
|
||||
// if it has the same text regardless of whether it is inside a class or an
|
||||
// object type.
|
||||
if (isModifier(token)) {
|
||||
if (isModifierKind(token)) {
|
||||
const result = tryParse(parseIndexSignatureWithModifiers);
|
||||
if (result) {
|
||||
return result;
|
||||
|
@ -2334,14 +2374,14 @@ namespace ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseObjectTypeMembers(): NodeArray<Declaration> {
|
||||
let members: NodeArray<Declaration>;
|
||||
function parseObjectTypeMembers(): NodeArray<TypeElement> {
|
||||
let members: NodeArray<TypeElement>;
|
||||
if (parseExpected(SyntaxKind.OpenBraceToken)) {
|
||||
members = parseList(ParsingContext.TypeMembers, parseTypeMember);
|
||||
parseExpected(SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
else {
|
||||
members = createMissingList<Declaration>();
|
||||
members = createMissingList<TypeElement>();
|
||||
}
|
||||
|
||||
return members;
|
||||
|
@ -2483,11 +2523,11 @@ namespace ts {
|
|||
// ( ...
|
||||
return true;
|
||||
}
|
||||
if (isIdentifier() || isModifier(token)) {
|
||||
if (isIdentifier() || isModifierKind(token)) {
|
||||
nextToken();
|
||||
if (token === SyntaxKind.ColonToken || token === SyntaxKind.CommaToken ||
|
||||
token === SyntaxKind.QuestionToken || token === SyntaxKind.EqualsToken ||
|
||||
isIdentifier() || isModifier(token)) {
|
||||
isIdentifier() || isModifierKind(token)) {
|
||||
// ( id :
|
||||
// ( id ,
|
||||
// ( id ?
|
||||
|
@ -3220,7 +3260,7 @@ namespace ts {
|
|||
|
||||
/**
|
||||
* Parse ES7 unary expression and await expression
|
||||
*
|
||||
*
|
||||
* ES7 UnaryExpression:
|
||||
* 1) SimpleUnaryExpression[?yield]
|
||||
* 2) IncrementExpression[?yield] ** UnaryExpression[?yield]
|
||||
|
@ -4720,7 +4760,7 @@ namespace ts {
|
|||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: DeclarationName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
|
||||
function parseMethodDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, asteriskToken: Node, name: PropertyName, questionToken: Node, diagnosticMessage?: DiagnosticMessage): MethodDeclaration {
|
||||
const method = <MethodDeclaration>createNode(SyntaxKind.MethodDeclaration, fullStart);
|
||||
method.decorators = decorators;
|
||||
setModifiers(method, modifiers);
|
||||
|
@ -4734,7 +4774,7 @@ namespace ts {
|
|||
return finishNode(method);
|
||||
}
|
||||
|
||||
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: DeclarationName, questionToken: Node): ClassElement {
|
||||
function parsePropertyDeclaration(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, name: PropertyName, questionToken: Node): ClassElement {
|
||||
const property = <PropertyDeclaration>createNode(SyntaxKind.PropertyDeclaration, fullStart);
|
||||
property.decorators = decorators;
|
||||
setModifiers(property, modifiers);
|
||||
|
@ -4808,7 +4848,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
// Eat up all modifiers, but hold on to the last one in case it is actually an identifier.
|
||||
while (isModifier(token)) {
|
||||
while (isModifierKind(token)) {
|
||||
idToken = token;
|
||||
// If the idToken is a class modifier (protected, private, public, and static), it is
|
||||
// certain that we are starting to parse class member. This allows better error recovery
|
||||
|
@ -5018,8 +5058,8 @@ namespace ts {
|
|||
// implements is a future reserved word so
|
||||
// 'class implements' might mean either
|
||||
// - class expression with omitted name, 'implements' starts heritage clause
|
||||
// - class with name 'implements'
|
||||
// 'isImplementsClause' helps to disambiguate between these two cases
|
||||
// - class with name 'implements'
|
||||
// 'isImplementsClause' helps to disambiguate between these two cases
|
||||
return isIdentifier() && !isImplementsClause()
|
||||
? parseIdentifier()
|
||||
: undefined;
|
||||
|
|
2437
src/compiler/printer.ts
Normal file
2437
src/compiler/printer.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -95,7 +95,7 @@ namespace ts {
|
|||
jsonContent = jsonText ? <{ typings?: string }>JSON.parse(jsonText) : { typings: undefined };
|
||||
}
|
||||
catch (e) {
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
// gracefully handle if readFile fails or returns not JSON
|
||||
jsonContent = { typings: undefined };
|
||||
}
|
||||
|
||||
|
@ -167,7 +167,7 @@ namespace ts {
|
|||
searchName = normalizePath(combinePaths(searchPath, moduleName));
|
||||
referencedSourceFile = forEach(extensions, extension => {
|
||||
if (extension === ".tsx" && !compilerOptions.jsx) {
|
||||
// resolve .tsx files only if jsx support is enabled
|
||||
// resolve .tsx files only if jsx support is enabled
|
||||
// 'logical not' handles both undefined and None cases
|
||||
return undefined;
|
||||
}
|
||||
|
@ -559,7 +559,11 @@ namespace ts {
|
|||
|
||||
const start = new Date().getTime();
|
||||
|
||||
const emitResult = emitFiles(
|
||||
const emitter = options.experimentalTransforms
|
||||
? emitFilesUsingTransforms
|
||||
: emitFiles;
|
||||
|
||||
const emitResult = emitter(
|
||||
emitResolver,
|
||||
getEmitHost(writeFileCallback),
|
||||
sourceFile);
|
||||
|
@ -1093,6 +1097,10 @@ namespace ts {
|
|||
!options.experimentalDecorators) {
|
||||
programDiagnostics.add(createCompilerDiagnostic(Diagnostics.Option_0_cannot_be_specified_without_specifying_option_1, "emitDecoratorMetadata", "experimentalDecorators"));
|
||||
}
|
||||
|
||||
if (FORCE_TRANSFORMS) {
|
||||
options.experimentalTransforms = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -425,6 +425,10 @@ namespace ts {
|
|||
|
||||
/* @internal */
|
||||
export function skipTrivia(text: string, pos: number, stopAfterLineBreak?: boolean): number {
|
||||
if (positionIsSynthesized(pos)) {
|
||||
return pos;
|
||||
}
|
||||
|
||||
// Keep in sync with couldStartTrivia
|
||||
while (true) {
|
||||
const ch = text.charCodeAt(pos);
|
||||
|
@ -567,12 +571,12 @@ namespace ts {
|
|||
}
|
||||
|
||||
/**
|
||||
* Extract comments from text prefixing the token closest following `pos`.
|
||||
* Extract comments from text prefixing the token closest following `pos`.
|
||||
* The return value is an array containing a TextRange for each comment.
|
||||
* Single-line comment ranges include the beginning '//' characters but not the ending line break.
|
||||
* Multi - line comment ranges include the beginning '/* and ending '<asterisk>/' characters.
|
||||
* The return value is undefined if no comments were found.
|
||||
* @param trailing
|
||||
* @param trailing
|
||||
* If false, whitespace is skipped until the first line break and comments between that location
|
||||
* and the next token are returned.
|
||||
* If true, comments occurring between the given position and the next line break are returned.
|
||||
|
|
400
src/compiler/sourcemap.ts
Normal file
400
src/compiler/sourcemap.ts
Normal file
|
@ -0,0 +1,400 @@
|
|||
/// <reference path="checker.ts"/>
|
||||
/// <reference path="transform.ts" />
|
||||
/// <reference path="declarationEmitter.ts"/>
|
||||
|
||||
/* @internal */
|
||||
namespace ts {
|
||||
export interface SourceMapWriter {
|
||||
sourceMapData?: SourceMapData;
|
||||
setSourceFile(sourceFile: SourceFile): void;
|
||||
emitPos(pos: number): void;
|
||||
emitStart(range: TextRange): void;
|
||||
emitEnd(range: TextRange): void;
|
||||
pushScope(scopeDeclaration: Node, scopeName?: string): void;
|
||||
popScope(): void;
|
||||
getText(): string;
|
||||
getSourceMappingURL(): string;
|
||||
}
|
||||
|
||||
let nop = <(...args: any[]) => any>Function.prototype;
|
||||
let nullSourceMapWriter: SourceMapWriter;
|
||||
|
||||
export function getNullSourceMapWriter(): SourceMapWriter {
|
||||
if (nullSourceMapWriter === undefined) {
|
||||
nullSourceMapWriter = {
|
||||
setSourceFile: nop,
|
||||
emitStart: nop,
|
||||
emitEnd: nop,
|
||||
emitPos: nop,
|
||||
pushScope: nop,
|
||||
popScope: nop,
|
||||
getText: nop,
|
||||
getSourceMappingURL: nop
|
||||
};
|
||||
}
|
||||
|
||||
return nullSourceMapWriter;
|
||||
}
|
||||
|
||||
export function createSourceMapWriter(host: EmitHost, writer: EmitTextWriter, filePath: string, root?: SourceFile): SourceMapWriter {
|
||||
let compilerOptions = host.getCompilerOptions();
|
||||
let currentSourceFile: SourceFile;
|
||||
let sourceMapDir: string; // The directory in which sourcemap will be
|
||||
|
||||
// Current source map file and its index in the sources list
|
||||
let sourceMapSourceIndex = -1;
|
||||
|
||||
// Names and its index map
|
||||
let sourceMapNameIndexMap: Map<number> = {};
|
||||
let sourceMapNameIndices: number[] = [];
|
||||
|
||||
// Last recorded and encoded spans
|
||||
let lastRecordedSourceMapSpan: SourceMapSpan;
|
||||
let lastEncodedSourceMapSpan: SourceMapSpan = {
|
||||
emittedLine: 1,
|
||||
emittedColumn: 1,
|
||||
sourceLine: 1,
|
||||
sourceColumn: 1,
|
||||
sourceIndex: 0
|
||||
};
|
||||
let lastEncodedNameIndex = 0;
|
||||
|
||||
// Initialize source map data
|
||||
let sourceMapJsFile = getBaseFileName(normalizeSlashes(filePath));
|
||||
let sourceMapData: SourceMapData = {
|
||||
sourceMapFilePath: filePath + ".map",
|
||||
jsSourceMappingURL: sourceMapJsFile + ".map",
|
||||
sourceMapFile: sourceMapJsFile,
|
||||
sourceMapSourceRoot: compilerOptions.sourceRoot || "",
|
||||
sourceMapSources: [],
|
||||
inputSourceFileNames: [],
|
||||
sourceMapNames: [],
|
||||
sourceMapMappings: "",
|
||||
sourceMapSourcesContent: compilerOptions.inlineSources ? [] : undefined,
|
||||
sourceMapDecodedMappings: []
|
||||
};
|
||||
|
||||
// Normalize source root and make sure it has trailing "/" so that it can be used to combine paths with the
|
||||
// relative paths of the sources list in the sourcemap
|
||||
sourceMapData.sourceMapSourceRoot = ts.normalizeSlashes(sourceMapData.sourceMapSourceRoot);
|
||||
if (sourceMapData.sourceMapSourceRoot.length && sourceMapData.sourceMapSourceRoot.charCodeAt(sourceMapData.sourceMapSourceRoot.length - 1) !== CharacterCodes.slash) {
|
||||
sourceMapData.sourceMapSourceRoot += directorySeparator;
|
||||
}
|
||||
|
||||
if (compilerOptions.mapRoot) {
|
||||
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
|
||||
if (root) { // emitting single module file
|
||||
// For modules or multiple emit files the mapRoot will have directory structure like the sources
|
||||
// So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
|
||||
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(root, host, sourceMapDir));
|
||||
}
|
||||
|
||||
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
|
||||
// The relative paths are relative to the common directory
|
||||
sourceMapDir = combinePaths(host.getCommonSourceDirectory(), sourceMapDir);
|
||||
sourceMapData.jsSourceMappingURL = getRelativePathToDirectoryOrUrl(
|
||||
getDirectoryPath(normalizePath(filePath)), // get the relative sourceMapDir path based on jsFilePath
|
||||
combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL), // this is where user expects to see sourceMap
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
}
|
||||
else {
|
||||
sourceMapData.jsSourceMappingURL = combinePaths(sourceMapDir, sourceMapData.jsSourceMappingURL);
|
||||
}
|
||||
}
|
||||
else {
|
||||
sourceMapDir = getDirectoryPath(normalizePath(filePath));
|
||||
}
|
||||
|
||||
return {
|
||||
sourceMapData,
|
||||
setSourceFile: recordNewSourceFileStart,
|
||||
emitPos: recordSourceMapSpan,
|
||||
emitStart: recordEmitNodeStartSpan,
|
||||
emitEnd: recordEmitNodeEndSpan,
|
||||
pushScope: recordScopeNameOfNode,
|
||||
popScope: recordScopeNameEnd,
|
||||
getText,
|
||||
getSourceMappingURL,
|
||||
};
|
||||
|
||||
function getSourceMapNameIndex() {
|
||||
return sourceMapNameIndices.length ? lastOrUndefined(sourceMapNameIndices) : -1;
|
||||
}
|
||||
|
||||
// Encoding for sourcemap span
|
||||
function encodeLastRecordedSourceMapSpan() {
|
||||
if (!lastRecordedSourceMapSpan || lastRecordedSourceMapSpan === lastEncodedSourceMapSpan) {
|
||||
return;
|
||||
}
|
||||
|
||||
let prevEncodedEmittedColumn = lastEncodedSourceMapSpan.emittedColumn;
|
||||
// Line/Comma delimiters
|
||||
if (lastEncodedSourceMapSpan.emittedLine === lastRecordedSourceMapSpan.emittedLine) {
|
||||
// Emit comma to separate the entry
|
||||
if (sourceMapData.sourceMapMappings) {
|
||||
sourceMapData.sourceMapMappings += ",";
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Emit line delimiters
|
||||
for (let encodedLine = lastEncodedSourceMapSpan.emittedLine; encodedLine < lastRecordedSourceMapSpan.emittedLine; encodedLine++) {
|
||||
sourceMapData.sourceMapMappings += ";";
|
||||
}
|
||||
prevEncodedEmittedColumn = 1;
|
||||
}
|
||||
|
||||
// 1. Relative Column 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.emittedColumn - prevEncodedEmittedColumn);
|
||||
|
||||
// 2. Relative sourceIndex
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceIndex - lastEncodedSourceMapSpan.sourceIndex);
|
||||
|
||||
// 3. Relative sourceLine 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceLine - lastEncodedSourceMapSpan.sourceLine);
|
||||
|
||||
// 4. Relative sourceColumn 0 based
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.sourceColumn - lastEncodedSourceMapSpan.sourceColumn);
|
||||
|
||||
// 5. Relative namePosition 0 based
|
||||
if (lastRecordedSourceMapSpan.nameIndex >= 0) {
|
||||
sourceMapData.sourceMapMappings += base64VLQFormatEncode(lastRecordedSourceMapSpan.nameIndex - lastEncodedNameIndex);
|
||||
lastEncodedNameIndex = lastRecordedSourceMapSpan.nameIndex;
|
||||
}
|
||||
|
||||
lastEncodedSourceMapSpan = lastRecordedSourceMapSpan;
|
||||
sourceMapData.sourceMapDecodedMappings.push(lastEncodedSourceMapSpan);
|
||||
}
|
||||
|
||||
function recordSourceMapSpan(pos: number) {
|
||||
if (pos === -1) {
|
||||
return;
|
||||
}
|
||||
|
||||
let sourceLinePos = getLineAndCharacterOfPosition(currentSourceFile, pos);
|
||||
|
||||
// Convert the location to be one-based.
|
||||
sourceLinePos.line++;
|
||||
sourceLinePos.character++;
|
||||
|
||||
let emittedLine = writer.getLine();
|
||||
let emittedColumn = writer.getColumn();
|
||||
|
||||
// If this location wasn't recorded or the location in source is going backwards, record the span
|
||||
if (!lastRecordedSourceMapSpan ||
|
||||
lastRecordedSourceMapSpan.emittedLine !== emittedLine ||
|
||||
lastRecordedSourceMapSpan.emittedColumn !== emittedColumn ||
|
||||
(lastRecordedSourceMapSpan.sourceIndex === sourceMapSourceIndex &&
|
||||
(lastRecordedSourceMapSpan.sourceLine > sourceLinePos.line ||
|
||||
(lastRecordedSourceMapSpan.sourceLine === sourceLinePos.line && lastRecordedSourceMapSpan.sourceColumn > sourceLinePos.character)))) {
|
||||
|
||||
// Encode the last recordedSpan before assigning new
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
// New span
|
||||
lastRecordedSourceMapSpan = {
|
||||
emittedLine: emittedLine,
|
||||
emittedColumn: emittedColumn,
|
||||
sourceLine: sourceLinePos.line,
|
||||
sourceColumn: sourceLinePos.character,
|
||||
nameIndex: getSourceMapNameIndex(),
|
||||
sourceIndex: sourceMapSourceIndex
|
||||
};
|
||||
}
|
||||
else {
|
||||
// Take the new pos instead since there is no change in emittedLine and column since last location
|
||||
lastRecordedSourceMapSpan.sourceLine = sourceLinePos.line;
|
||||
lastRecordedSourceMapSpan.sourceColumn = sourceLinePos.character;
|
||||
lastRecordedSourceMapSpan.sourceIndex = sourceMapSourceIndex;
|
||||
}
|
||||
}
|
||||
|
||||
function recordEmitNodeStartSpan(range: TextRange) {
|
||||
recordSourceMapSpan(range.pos !== -1 ? skipTrivia(currentSourceFile.text, range.pos) : -1);
|
||||
}
|
||||
|
||||
function recordEmitNodeEndSpan(range: TextRange) {
|
||||
recordSourceMapSpan(range.end);
|
||||
}
|
||||
|
||||
function recordNewSourceFileStart(sourceFile: SourceFile) {
|
||||
currentSourceFile = getOriginalNodeIf(sourceFile, isSourceFile);
|
||||
|
||||
// Add the file to tsFilePaths
|
||||
// If sourceroot option: Use the relative path corresponding to the common directory path
|
||||
// otherwise source locations relative to map file location
|
||||
let sourcesDirectoryPath = compilerOptions.sourceRoot ? host.getCommonSourceDirectory() : sourceMapDir;
|
||||
|
||||
let source = getRelativePathToDirectoryOrUrl(sourcesDirectoryPath,
|
||||
currentSourceFile.fileName,
|
||||
host.getCurrentDirectory(),
|
||||
host.getCanonicalFileName,
|
||||
/*isAbsolutePathAnUrl*/ true);
|
||||
|
||||
sourceMapSourceIndex = indexOf(sourceMapData.sourceMapSources, source);
|
||||
if (sourceMapSourceIndex === -1) {
|
||||
sourceMapSourceIndex = sourceMapData.sourceMapSources.length;
|
||||
sourceMapData.sourceMapSources.push(source);
|
||||
|
||||
// The one that can be used from program to get the actual source file
|
||||
sourceMapData.inputSourceFileNames.push(sourceFile.fileName);
|
||||
|
||||
if (compilerOptions.inlineSources) {
|
||||
sourceMapData.sourceMapSourcesContent.push(sourceFile.text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function recordScopeNameIndex(scopeNameIndex: number) {
|
||||
sourceMapNameIndices.push(scopeNameIndex);
|
||||
}
|
||||
|
||||
function recordScopeNameStart(scopeDeclaration: Node, scopeName: string) {
|
||||
let scopeNameIndex = -1;
|
||||
if (scopeName) {
|
||||
let parentIndex = getSourceMapNameIndex();
|
||||
if (parentIndex !== -1) {
|
||||
// Child scopes are always shown with a dot (even if they have no name),
|
||||
// unless it is a computed property. Then it is shown with brackets,
|
||||
// but the brackets are included in the name.
|
||||
let name = (<Declaration>scopeDeclaration).name;
|
||||
if (!name || name.kind !== SyntaxKind.ComputedPropertyName) {
|
||||
scopeName = "." + scopeName;
|
||||
}
|
||||
scopeName = sourceMapData.sourceMapNames[parentIndex] + scopeName;
|
||||
}
|
||||
|
||||
scopeNameIndex = getProperty(sourceMapNameIndexMap, scopeName);
|
||||
if (scopeNameIndex === undefined) {
|
||||
scopeNameIndex = sourceMapData.sourceMapNames.length;
|
||||
sourceMapData.sourceMapNames.push(scopeName);
|
||||
sourceMapNameIndexMap[scopeName] = scopeNameIndex;
|
||||
}
|
||||
}
|
||||
recordScopeNameIndex(scopeNameIndex);
|
||||
}
|
||||
|
||||
function recordScopeNameOfNode(scopeDeclaration: Node, scopeName?: string) {
|
||||
if (scopeName) {
|
||||
// The scope was already given a name use it
|
||||
recordScopeNameStart(scopeDeclaration, scopeName);
|
||||
}
|
||||
else if (scopeDeclaration.kind === SyntaxKind.FunctionDeclaration ||
|
||||
scopeDeclaration.kind === SyntaxKind.FunctionExpression ||
|
||||
scopeDeclaration.kind === SyntaxKind.MethodDeclaration ||
|
||||
scopeDeclaration.kind === SyntaxKind.MethodSignature ||
|
||||
scopeDeclaration.kind === SyntaxKind.GetAccessor ||
|
||||
scopeDeclaration.kind === SyntaxKind.SetAccessor ||
|
||||
scopeDeclaration.kind === SyntaxKind.ModuleDeclaration ||
|
||||
scopeDeclaration.kind === SyntaxKind.ClassDeclaration ||
|
||||
scopeDeclaration.kind === SyntaxKind.EnumDeclaration) {
|
||||
// Declaration and has associated name use it
|
||||
if ((<Declaration>scopeDeclaration).name) {
|
||||
let name = (<Declaration>scopeDeclaration).name;
|
||||
// For computed property names, the text will include the brackets
|
||||
scopeName = name.kind === SyntaxKind.ComputedPropertyName
|
||||
? getTextOfNode(name)
|
||||
: (<Identifier>(<Declaration>scopeDeclaration).name).text;
|
||||
}
|
||||
|
||||
recordScopeNameStart(scopeDeclaration, scopeName);
|
||||
}
|
||||
else {
|
||||
// Block just use the name from upper level scope
|
||||
recordScopeNameIndex(getSourceMapNameIndex());
|
||||
}
|
||||
}
|
||||
|
||||
function recordScopeNameEnd() {
|
||||
sourceMapNameIndices.pop();
|
||||
}
|
||||
|
||||
function getText() {
|
||||
encodeLastRecordedSourceMapSpan();
|
||||
|
||||
return stringify({
|
||||
version: 3,
|
||||
file: sourceMapData.sourceMapFile,
|
||||
sourceRoot: sourceMapData.sourceMapSourceRoot,
|
||||
sources: sourceMapData.sourceMapSources,
|
||||
sourcesContent: sourceMapData.sourceMapSourcesContent,
|
||||
names: sourceMapData.sourceMapNames,
|
||||
mappings: sourceMapData.sourceMapMappings
|
||||
});
|
||||
}
|
||||
|
||||
function getSourceMappingURL() {
|
||||
if (compilerOptions.inlineSourceMap) {
|
||||
// Encode the sourceMap into the sourceMap url
|
||||
let base64SourceMapText = convertToBase64(getText());
|
||||
return `data:application/json;base64,${base64SourceMapText}`;
|
||||
}
|
||||
else {
|
||||
return sourceMapData.jsSourceMappingURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const base64Chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
|
||||
|
||||
function base64FormatEncode(inValue: number) {
|
||||
if (inValue < 64) {
|
||||
return base64Chars.charAt(inValue);
|
||||
}
|
||||
|
||||
throw TypeError(inValue + ": not a 64 based value");
|
||||
}
|
||||
|
||||
function base64VLQFormatEncode(inValue: number) {
|
||||
// Add a new least significant bit that has the sign of the value.
|
||||
// if negative number the least significant bit that gets added to the number has value 1
|
||||
// else least significant bit value that gets added is 0
|
||||
// eg. -1 changes to binary : 01 [1] => 3
|
||||
// +1 changes to binary : 01 [0] => 2
|
||||
if (inValue < 0) {
|
||||
inValue = ((-inValue) << 1) + 1;
|
||||
}
|
||||
else {
|
||||
inValue = inValue << 1;
|
||||
}
|
||||
|
||||
// Encode 5 bits at a time starting from least significant bits
|
||||
let encodedStr = "";
|
||||
do {
|
||||
let currentDigit = inValue & 31; // 11111
|
||||
inValue = inValue >> 5;
|
||||
if (inValue > 0) {
|
||||
// There are still more digits to decode, set the msb (6th bit)
|
||||
currentDigit = currentDigit | 32;
|
||||
}
|
||||
encodedStr = encodedStr + base64FormatEncode(currentDigit);
|
||||
} while (inValue > 0);
|
||||
|
||||
return encodedStr;
|
||||
}
|
||||
|
||||
var stringify = JSON && JSON.stringify ? JSON.stringify : function stringify(value: any): string {
|
||||
return value == null ? "null"
|
||||
: typeof value === "string" ? `"${escapeString(value)}"`
|
||||
: typeof value === "number" ? String(value)
|
||||
: typeof value === "boolean" ? value ? "true" : "false"
|
||||
: hasToJson(value) ? stringify(value.toJSON())
|
||||
: isArray(value) ? `[${reduceLeft(value, stringifyElement, "")}]`
|
||||
: typeof value === "object" ? `{${reduceProperties(value, stringifyProperty, "")}}`
|
||||
: "null";
|
||||
}
|
||||
|
||||
function hasToJson(value: any) {
|
||||
return typeof value === "object" && typeof value.toJSON === "function";
|
||||
}
|
||||
|
||||
function stringifyElement(memo: string, value: any) {
|
||||
return (memo ? memo + "," : memo) + stringify(value);
|
||||
}
|
||||
|
||||
function stringifyProperty(memo: string, value: any, key: string) {
|
||||
return value === undefined ? memo
|
||||
: (memo ? memo + "," : memo) + `"${escapeString(key)}":${stringify(value)}`;
|
||||
}
|
||||
}
|
1039
src/compiler/transform.ts
Normal file
1039
src/compiler/transform.ts
Normal file
File diff suppressed because it is too large
Load diff
303
src/compiler/transforms/destructuring.ts
Normal file
303
src/compiler/transforms/destructuring.ts
Normal file
|
@ -0,0 +1,303 @@
|
|||
/// <reference path="../checker.ts" />
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
/**
|
||||
* Flattens binding patterns in a variable declaration.
|
||||
* @param transformer The transformer context to use during destructuring.
|
||||
* @param node The variable declaration to flatten.
|
||||
* @param write The callback to execute to write variable declarations.
|
||||
* @param visitor An optional visitor used to visit the initializers of a binding pattern.
|
||||
*/
|
||||
export function flattenVariableDestructuring(transformer: Transformer, node: VariableDeclaration, write: (node: VariableDeclaration) => void, visitor?: (node: Node, write: (node: Node) => void) => void): void {
|
||||
transformDestructuring(transformer, node, /*writeExpression*/ undefined, write, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens binding patterns in a parameter declaration.
|
||||
* @param transformer The transformer context to use during destructuring.
|
||||
* @param node The parameter declaration to flatten.
|
||||
* @param write The callback to execute to write variable declarations.
|
||||
* @param visitor An optional visitor used to visit the initializers of a binding pattern.
|
||||
*/
|
||||
export function flattenParameterDestructuring(transformer: Transformer, node: ParameterDeclaration, write: (node: VariableDeclaration) => void, visitor?: (node: Node, write: (node: Node) => void) => void): void {
|
||||
transformDestructuring(transformer, node, /*writeExpression*/ undefined, write, visitor, transformer.getGeneratedNameForNode(node));
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens a destructuring assignment.
|
||||
* @param transformer The transformer context to use during destructuring.
|
||||
* @param node The assignment expression to flatten.
|
||||
* @param write The callback to execute to write the resulting expression.
|
||||
* @param visitor An optional visitor used to visit the initializers and right-hand side of the destructuring assignment.
|
||||
*/
|
||||
export function flattenDestructuringAssignment(transformer: Transformer, node: BinaryExpression, write: (node: Expression) => void, visitor?: (node: Node, write: (node: Node) => void) => void): void {
|
||||
transformDestructuring(transformer, node, write, /*writeDeclaration*/ undefined, visitor);
|
||||
}
|
||||
|
||||
/**
|
||||
* Flattens binding patterns in a variable declaration and transforms them into an expression.
|
||||
* @param transformer The transformer context to use during destructuring.
|
||||
* @param node The variable declaration to flatten.
|
||||
* @param write The callback to execute to write the resulting expression.
|
||||
* @param visitor An optional visitor used to visit the initializers of a binding pattern.
|
||||
*/
|
||||
export function flattenVariableDestructuringAsExpression(transformer: Transformer, node: VariableDeclaration, write: (node: Expression) => void, visitor?: (node: Node, write: (node: Node) => void) => void): void {
|
||||
transformDestructuring(transformer, node, write, /*writeDeclaration*/ undefined, visitor);
|
||||
}
|
||||
|
||||
function transformDestructuring(
|
||||
transformer: Transformer,
|
||||
root: BinaryExpression | VariableDeclaration | ParameterDeclaration,
|
||||
writeExpression: (node: Expression) => void,
|
||||
writeDeclaration: (node: VariableDeclaration) => void,
|
||||
visitor?: (node: Node, write: (node: Node) => void) => void,
|
||||
value?: Expression) {
|
||||
let {
|
||||
createTempVariable,
|
||||
hoistVariableDeclaration,
|
||||
mapNode,
|
||||
flattenNode,
|
||||
visitNode,
|
||||
} = transformer;
|
||||
|
||||
let parentNode = transformer.getParentNode();
|
||||
let isVariableDeclarationList = writeDeclaration !== undefined;
|
||||
|
||||
if (isBinaryExpression(root)) {
|
||||
return emitAssignmentExpression(root, writeExpression);
|
||||
}
|
||||
else {
|
||||
return emitBindingElement(<BindingElement>root, value, writeExpression || writeDeclaration);
|
||||
}
|
||||
|
||||
function emitAssignmentExpression(root: BinaryExpression, write: (node: Expression) => void) {
|
||||
if (isEmptyObjectLiteralOrArrayLiteral(root.left)) {
|
||||
return write(root.right);
|
||||
}
|
||||
else {
|
||||
let expressions = flattenNode(root, emitDestructuringExpressions);
|
||||
let expression = inlineExpressions(expressions);
|
||||
if (!isExpressionStatement(parentNode) && !isParenthesizedExpression(parentNode)) {
|
||||
expression = createParenthesizedExpression(expression);
|
||||
}
|
||||
|
||||
return write(expression);
|
||||
}
|
||||
}
|
||||
|
||||
function emitBindingElement(target: BindingElement, value: Expression, write: (node: Expression | VariableDeclaration) => void): void {
|
||||
if (target.initializer) {
|
||||
// Combine value and initializer
|
||||
let initializer = visitNode(target.initializer, visitor, isExpressionNode);
|
||||
value = value ? createDefaultValueCheck(value, initializer, write) : initializer;
|
||||
}
|
||||
else if (!value) {
|
||||
// Use 'void 0' in absence of value and initializer
|
||||
value = createVoidZeroExpression();
|
||||
}
|
||||
|
||||
let name = target.name;
|
||||
if (isBindingPattern(name)) {
|
||||
const elements = name.elements;
|
||||
const numElements = elements.length;
|
||||
if (numElements !== 1) {
|
||||
// For anything other than a single-element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once. Additionally, if we have zero elements
|
||||
// we need to emit *something* to ensure that in case a 'var' keyword was already emitted,
|
||||
// so in that case, we'll intentionally create that temporary.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ numElements !== 0, write);
|
||||
}
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let element = elements[i];
|
||||
if (name.kind === SyntaxKind.ObjectBindingPattern) {
|
||||
// Rewrite element to a declaration with an initializer that fetches property
|
||||
let propName = element.propertyName || <Identifier>element.name;
|
||||
emitBindingElement(element, createPropertyAccessForDestructuringProperty(value, propName, write), write);
|
||||
}
|
||||
else if (element.kind !== SyntaxKind.OmittedExpression) {
|
||||
if (!element.dotDotDotToken) {
|
||||
// Rewrite element to a declaration that accesses array element at index i
|
||||
emitBindingElement(element, createElementAccessExpression3(value, i), write);
|
||||
}
|
||||
else if (i === elements.length - 1) {
|
||||
emitBindingElement(element, createSliceCall(value, i), write);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
emitAssignment(name, value, /*isTempVariable*/ false, /*originalNode*/ target, write);
|
||||
}
|
||||
}
|
||||
|
||||
function createPropertyAccessForDestructuringProperty(object: Expression, propName: PropertyName, write: (node: Expression | VariableDeclaration) => void) {
|
||||
let index: Expression;
|
||||
const nameIsComputed = isComputedPropertyName(propName);
|
||||
if (nameIsComputed) {
|
||||
index = ensureIdentifier((<ComputedPropertyName>propName).expression, /* reuseIdentifierExpression */ false, write);
|
||||
}
|
||||
else {
|
||||
// We create a synthetic copy of the identifier in order to avoid the rewriting that might
|
||||
// otherwise occur when the identifier is emitted.
|
||||
index = <Identifier | LiteralExpression>createSynthesizedNode(propName.kind);
|
||||
(<Identifier | LiteralExpression>index).text = (<Identifier | LiteralExpression>propName).text;
|
||||
}
|
||||
|
||||
return !nameIsComputed && index.kind === SyntaxKind.Identifier
|
||||
? createPropertyAccessExpression2(object, <Identifier>index)
|
||||
: createElementAccessExpression2(object, index);
|
||||
}
|
||||
|
||||
function emitDestructuringExpressions(node: BinaryExpression, write: (node: Expression) => void): void {
|
||||
let target = node.left;
|
||||
let value = node.right;
|
||||
if (isExpressionStatement(parentNode)) {
|
||||
emitDestructuringAssignment(target, value, write);
|
||||
}
|
||||
else {
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, write);
|
||||
emitDestructuringAssignment(target, value, write);
|
||||
write(value);
|
||||
}
|
||||
}
|
||||
|
||||
function emitDestructuringAssignment(target: Expression, value: Expression, write: (node: Expression) => void) {
|
||||
if (isBinaryExpression(target) && target.operatorToken.kind === SyntaxKind.EqualsToken) {
|
||||
let right = visitNode((<BinaryExpression>target).right, visitor, isExpressionNode);
|
||||
value = createDefaultValueCheck(value, right, write);
|
||||
target = (<BinaryExpression>target).left;
|
||||
}
|
||||
if (isObjectLiteralExpression(target)) {
|
||||
emitObjectLiteralAssignment(target, value, write);
|
||||
}
|
||||
else if (isArrayLiteralExpression(target)) {
|
||||
emitArrayLiteralAssignment(target, value, write);
|
||||
}
|
||||
else if (isIdentifier(target)) {
|
||||
emitAssignment(target, value, /*isTempVariable*/ false, /*originalNode*/ undefined, write);
|
||||
}
|
||||
else {
|
||||
Debug.fail();
|
||||
}
|
||||
}
|
||||
|
||||
function emitObjectLiteralAssignment(target: ObjectLiteralExpression, value: Expression, write: (node: Expression) => void): void {
|
||||
let properties = target.properties;
|
||||
if (properties.length !== 1) {
|
||||
// For anything but a single element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, write);
|
||||
}
|
||||
|
||||
for (let p of properties) {
|
||||
if (isPropertyAssignment(p) || isShorthandPropertyAssignment(p)) {
|
||||
let propName = <Identifier | LiteralExpression>(<PropertyAssignment>p).name;
|
||||
let expr = createPropertyOrElementAccessExpression(value, propName);
|
||||
emitDestructuringAssignment((<PropertyAssignment>p).initializer || propName, expr, write);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitArrayLiteralAssignment(target: ArrayLiteralExpression, value: Expression, write: (node: Expression) => void): void {
|
||||
let elements = target.elements;
|
||||
if (elements.length !== 1) {
|
||||
// For anything but a single element destructuring we need to generate a temporary
|
||||
// to ensure value is evaluated exactly once.
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, write);
|
||||
}
|
||||
|
||||
for (let i = 0; i < elements.length; i++) {
|
||||
let e = elements[i];
|
||||
if (e.kind !== SyntaxKind.OmittedExpression) {
|
||||
if (e.kind !== SyntaxKind.SpreadElementExpression) {
|
||||
emitDestructuringAssignment(e, createElementAccessExpression3(value, i), write);
|
||||
}
|
||||
else if (i === elements.length - 1) {
|
||||
emitDestructuringAssignment((<SpreadElementExpression>e).expression, createSliceCall(value, i), write);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitAssignment(left: Identifier, right: Expression, isTempVariable: boolean, originalNode: Node, write: (node: Expression | VariableDeclaration) => void): void {
|
||||
let node: VariableDeclaration | Expression;
|
||||
if (isVariableDeclarationList) {
|
||||
node = createVariableDeclaration2(left, right);
|
||||
}
|
||||
else {
|
||||
node = createAssignmentExpression(left, right);
|
||||
}
|
||||
|
||||
if (originalNode) {
|
||||
node.original = originalNode;
|
||||
}
|
||||
|
||||
write(node);
|
||||
}
|
||||
|
||||
function ensureIdentifier(value: Expression, reuseIdentifierExpressions: boolean, write: (node: Expression | VariableDeclaration) => void) {
|
||||
if (isIdentifier(value) && reuseIdentifierExpressions) {
|
||||
return value;
|
||||
}
|
||||
else {
|
||||
let temp = createTempVariable(TempFlags.Auto);
|
||||
if (!isVariableDeclarationList) {
|
||||
hoistVariableDeclaration(temp);
|
||||
}
|
||||
|
||||
emitAssignment(temp, value, /*isTempVariable*/ true, /*originalNode*/ undefined, write);
|
||||
return temp;
|
||||
}
|
||||
}
|
||||
|
||||
function createDefaultValueCheck(value: Expression, defaultValue: Expression, write: (node: Expression | VariableDeclaration) => void): Expression {
|
||||
value = ensureIdentifier(value, /*reuseIdentifierExpressions*/ true, write);
|
||||
let equalityExpr = createStrictEqualityExpression(value, createVoidZeroExpression());
|
||||
return createConditionalExpression2(equalityExpr, defaultValue, value);
|
||||
}
|
||||
}
|
||||
|
||||
export function convertBindingPatternToExpression(node: BindingPattern): Expression {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return convertObjectBindingPatternToExpression(<ObjectBindingPattern>node);
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return convertArrayBindingPatternToExpression(<ObjectBindingPattern>node);
|
||||
}
|
||||
}
|
||||
|
||||
function convertBindingElementToExpression(node: BindingElement): Expression {
|
||||
let name = node.name;
|
||||
let expression = isIdentifier(name) ? name : convertBindingPatternToExpression(name);
|
||||
if (node.initializer) {
|
||||
expression = createAssignmentExpression(expression, node.initializer, node);
|
||||
}
|
||||
else if (node.dotDotDotToken) {
|
||||
expression = createSpreadElementExpression(expression, node);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
function convertObjectBindingPatternToExpression(node: ObjectBindingPattern): Expression {
|
||||
let properties = map(node.elements, convertBindingElementToObjectLiteralElement);
|
||||
return createObjectLiteralExpression(properties);
|
||||
}
|
||||
|
||||
function convertArrayBindingPatternToExpression(node: ArrayBindingPattern): Expression {
|
||||
let elements = map(node.elements, convertBindingElementToExpression);
|
||||
return createArrayLiteralExpression(elements);
|
||||
}
|
||||
|
||||
function convertBindingElementToObjectLiteralElement(node: BindingElement): ObjectLiteralElement {
|
||||
let name = node.name;
|
||||
if (!node.propertyName && isIdentifier(name) && !node.initializer) {
|
||||
return createShorthandPropertyAssignment(name, node);
|
||||
}
|
||||
|
||||
let propertyName = node.propertyName || <Identifier>name;
|
||||
let expr = convertBindingElementToExpression(node);
|
||||
return createPropertyAssignment(propertyName, expr);
|
||||
}
|
||||
}
|
1179
src/compiler/transforms/es6.ts
Normal file
1179
src/compiler/transforms/es6.ts
Normal file
File diff suppressed because it is too large
Load diff
515
src/compiler/transforms/jsx.ts
Normal file
515
src/compiler/transforms/jsx.ts
Normal file
|
@ -0,0 +1,515 @@
|
|||
/// <reference path="../checker.ts" />
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function createJsxTransformation(transformer: Transformer): Transformation {
|
||||
// create local aliases for transformer methods
|
||||
let {
|
||||
tryPushNode,
|
||||
popNode,
|
||||
pipeNode,
|
||||
pipeNodes,
|
||||
visitNode,
|
||||
visitSourceFile,
|
||||
accept,
|
||||
} = transformer;
|
||||
|
||||
return transformJsx;
|
||||
|
||||
function transformJsx(node: SourceFile): SourceFile {
|
||||
if (node.transformFlags & TransformFlags.ContainsJsx) {
|
||||
return transformJsxWorker(node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function transformJsxWorker(node: SourceFile): SourceFile {
|
||||
return visitSourceFile(node, visitor);
|
||||
}
|
||||
|
||||
function visitor(node: Node, write: (node: Node) => void): void {
|
||||
if (node.transformFlags & TransformFlags.Jsx) {
|
||||
visitorWorker(node, write);
|
||||
}
|
||||
else if (node.transformFlags & TransformFlags.ContainsJsx) {
|
||||
write(accept(node, visitor));
|
||||
}
|
||||
else {
|
||||
write(node);
|
||||
}
|
||||
}
|
||||
|
||||
function visitorWorker(node: Node, write: (node: Node) => void): void {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.JsxElement:
|
||||
visitJsxElement(<JsxElement>node, write);
|
||||
break;
|
||||
|
||||
case SyntaxKind.JsxSelfClosingElement:
|
||||
visitJsxSelfClosingElement(<JsxSelfClosingElement>node, write);
|
||||
break;
|
||||
|
||||
case SyntaxKind.JsxText:
|
||||
visitJsxText(<JsxText>node, write);
|
||||
break;
|
||||
|
||||
case SyntaxKind.JsxExpression:
|
||||
visitJsxExpression(<JsxExpression>node, write);
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.fail("Encountered unhandled node kind when transforming Jsx syntax.");
|
||||
write(accept(node, visitor));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
function visitJsxElement(node: JsxElement, write: (node: Expression) => void): void {
|
||||
emitJsxOpeningLikeElement(node.openingElement, node.children, write);
|
||||
}
|
||||
|
||||
function visitJsxSelfClosingElement(node: JsxSelfClosingElement, write: (node: Expression) => void): void {
|
||||
emitJsxOpeningLikeElement(node, /*children*/ undefined, write);
|
||||
}
|
||||
|
||||
function emitJsxOpeningLikeElement(node: JsxOpeningLikeElement, children: JsxChild[], write: (node: Expression) => void): void {
|
||||
// We must the node onto the node stack if it is not already at the top.
|
||||
let wasPushed = tryPushNode(node);
|
||||
let tagName = getTagName(node);
|
||||
let objectProperties: Expression;
|
||||
if (node.attributes.length === 0) {
|
||||
// When there are no attributes, React wants "null"
|
||||
objectProperties = createNullKeyword();
|
||||
}
|
||||
else {
|
||||
// Either emit one big object literal (no spread attribs), or
|
||||
// a call to React.__spread
|
||||
let attrs = node.attributes;
|
||||
let hasSpreadAttribute = forEach(attrs, isJsxSpreadAttribute);
|
||||
if (hasSpreadAttribute) {
|
||||
let segments: Expression[] = [];
|
||||
let properties: ObjectLiteralElement[] = [];
|
||||
for (let attr of attrs) {
|
||||
if (isJsxSpreadAttribute(attr)) {
|
||||
if (properties) {
|
||||
segments.push(createObjectLiteralExpression(properties));
|
||||
properties = undefined;
|
||||
}
|
||||
|
||||
pipeNode(attr, emitJsxSpreadAttributeAsExpression, segments);
|
||||
}
|
||||
else {
|
||||
if (!properties) {
|
||||
properties = [];
|
||||
}
|
||||
|
||||
pipeNode(attr, emitJsxAttributeAsObjectLiteralElement, properties);
|
||||
}
|
||||
}
|
||||
|
||||
if (properties) {
|
||||
segments.push(createObjectLiteralExpression(properties));
|
||||
}
|
||||
|
||||
objectProperties = createReactSpreadCall(segments);
|
||||
}
|
||||
else {
|
||||
let properties: ObjectLiteralElement[] = [];
|
||||
pipeNodes(node.attributes, emitJsxAttributeAsObjectLiteralElement, properties);
|
||||
objectProperties = createObjectLiteralExpression(properties);
|
||||
}
|
||||
}
|
||||
|
||||
if (wasPushed) {
|
||||
popNode();
|
||||
}
|
||||
|
||||
let childExpressions: Expression[] = [];
|
||||
pipeNodes(children, emitJsxChildAsExpression, childExpressions);
|
||||
|
||||
let reactCreateElementCall = createReactCreateElementCall(tagName, objectProperties, childExpressions);
|
||||
write(reactCreateElementCall);
|
||||
}
|
||||
|
||||
function emitJsxSpreadAttributeAsExpression(node: JsxSpreadAttribute, write: (node: Expression) => void): void {
|
||||
write(visitNode(node.expression, visitor, isExpressionNode));
|
||||
}
|
||||
|
||||
function emitJsxAttributeAsObjectLiteralElement(node: JsxAttribute, write: (node: ObjectLiteralElement) => void): void {
|
||||
let name = getAttributeName(node);
|
||||
let expression = node.initializer
|
||||
? visitNode(node.initializer, visitor, isExpressionNode)
|
||||
: createTrueKeyword();
|
||||
|
||||
write(createPropertyAssignment(name, expression));
|
||||
}
|
||||
|
||||
function emitJsxChildAsExpression(node: JsxChild, write: (node: Expression) => void): void {
|
||||
if (isJsxText(node)) {
|
||||
pipeNode(node, emitNonEmptyJsxText, write);
|
||||
}
|
||||
else {
|
||||
write(visitNode(node, visitor, isExpressionNode));
|
||||
}
|
||||
}
|
||||
|
||||
function emitNonEmptyJsxText(node: JsxText, write: (node: Expression) => void): void {
|
||||
let text = getTextToEmit(node);
|
||||
if (text !== undefined) {
|
||||
write(createStringLiteral(text));
|
||||
}
|
||||
}
|
||||
|
||||
function getTextToEmit(node: JsxText) {
|
||||
let text = trimReactWhitespaceAndApplyEntities(node);
|
||||
if (text === undefined || text.length === 0) {
|
||||
return undefined;
|
||||
}
|
||||
else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
function trimReactWhitespaceAndApplyEntities(node: JsxText): string {
|
||||
let result: string = undefined;
|
||||
let text = getTextOfNode(node, /*includeTrivia*/ true);
|
||||
let firstNonWhitespace = 0;
|
||||
let lastNonWhitespace = -1;
|
||||
|
||||
// JSX trims whitespace at the end and beginning of lines, except that the
|
||||
// start/end of a tag is considered a start/end of a line only if that line is
|
||||
// on the same line as the closing tag. See examples in tests/cases/conformance/jsx/tsxReactEmitWhitespace.tsx
|
||||
for (let i = 0; i < text.length; i++) {
|
||||
let c = text.charCodeAt(i);
|
||||
if (isLineBreak(c)) {
|
||||
if (firstNonWhitespace !== -1 && (lastNonWhitespace - firstNonWhitespace + 1 > 0)) {
|
||||
let part = text.substr(firstNonWhitespace, lastNonWhitespace - firstNonWhitespace + 1);
|
||||
result = (result ? result + "\" + ' ' + \"" : "") + part;
|
||||
}
|
||||
firstNonWhitespace = -1;
|
||||
}
|
||||
else if (!isWhiteSpace(c)) {
|
||||
lastNonWhitespace = i;
|
||||
if (firstNonWhitespace === -1) {
|
||||
firstNonWhitespace = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (firstNonWhitespace !== -1) {
|
||||
let part = text.substr(firstNonWhitespace);
|
||||
result = (result ? result + "\" + ' ' + \"" : "") + part;
|
||||
}
|
||||
|
||||
if (result) {
|
||||
// Replace entities like
|
||||
result = result.replace(/&(\w+);/g, function(s: any, m: string) {
|
||||
if (entities[m] !== undefined) {
|
||||
return String.fromCharCode(entities[m]);
|
||||
}
|
||||
else {
|
||||
return s;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
function getTagName(node: JsxElement | JsxOpeningLikeElement): Expression {
|
||||
if (isJsxElement(node)) {
|
||||
return getTagName(node.openingElement);
|
||||
}
|
||||
else {
|
||||
let name = node.tagName;
|
||||
if (isIdentifier(name) && isIntrinsicJsxName(name.text)) {
|
||||
return createStringLiteral(name.text);
|
||||
}
|
||||
else {
|
||||
return convertEntityNameToExpression(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emit an attribute name, which is quoted if it needs to be quoted. Because
|
||||
* these emit into an object literal property name, we don't need to be worried
|
||||
* about keywords, just non-identifier characters
|
||||
*/
|
||||
function getAttributeName(node: JsxAttribute): StringLiteral | Identifier {
|
||||
let name = node.name;
|
||||
if (/[A-Za-z_]+[\w*]/.test(name.text)) {
|
||||
return createStringLiteral(name.text);
|
||||
}
|
||||
else {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
|
||||
function visitJsxText(node: JsxText, write: (node: Node) => void): void {
|
||||
let text = trimReactWhitespaceAndApplyEntities(node);
|
||||
write(createStringLiteral(text || ""));
|
||||
}
|
||||
|
||||
function visitJsxExpression(node: JsxExpression, write: (node: Expression) => void): void {
|
||||
let expression = visitNode((<JsxExpression>node).expression, visitor, isExpressionNode);
|
||||
write(expression);
|
||||
}
|
||||
}
|
||||
|
||||
var entities: Map<number> = {
|
||||
"quot": 0x0022,
|
||||
"amp": 0x0026,
|
||||
"apos": 0x0027,
|
||||
"lt": 0x003C,
|
||||
"gt": 0x003E,
|
||||
"nbsp": 0x00A0,
|
||||
"iexcl": 0x00A1,
|
||||
"cent": 0x00A2,
|
||||
"pound": 0x00A3,
|
||||
"curren": 0x00A4,
|
||||
"yen": 0x00A5,
|
||||
"brvbar": 0x00A6,
|
||||
"sect": 0x00A7,
|
||||
"uml": 0x00A8,
|
||||
"copy": 0x00A9,
|
||||
"ordf": 0x00AA,
|
||||
"laquo": 0x00AB,
|
||||
"not": 0x00AC,
|
||||
"shy": 0x00AD,
|
||||
"reg": 0x00AE,
|
||||
"macr": 0x00AF,
|
||||
"deg": 0x00B0,
|
||||
"plusmn": 0x00B1,
|
||||
"sup2": 0x00B2,
|
||||
"sup3": 0x00B3,
|
||||
"acute": 0x00B4,
|
||||
"micro": 0x00B5,
|
||||
"para": 0x00B6,
|
||||
"middot": 0x00B7,
|
||||
"cedil": 0x00B8,
|
||||
"sup1": 0x00B9,
|
||||
"ordm": 0x00BA,
|
||||
"raquo": 0x00BB,
|
||||
"frac14": 0x00BC,
|
||||
"frac12": 0x00BD,
|
||||
"frac34": 0x00BE,
|
||||
"iquest": 0x00BF,
|
||||
"Agrave": 0x00C0,
|
||||
"Aacute": 0x00C1,
|
||||
"Acirc": 0x00C2,
|
||||
"Atilde": 0x00C3,
|
||||
"Auml": 0x00C4,
|
||||
"Aring": 0x00C5,
|
||||
"AElig": 0x00C6,
|
||||
"Ccedil": 0x00C7,
|
||||
"Egrave": 0x00C8,
|
||||
"Eacute": 0x00C9,
|
||||
"Ecirc": 0x00CA,
|
||||
"Euml": 0x00CB,
|
||||
"Igrave": 0x00CC,
|
||||
"Iacute": 0x00CD,
|
||||
"Icirc": 0x00CE,
|
||||
"Iuml": 0x00CF,
|
||||
"ETH": 0x00D0,
|
||||
"Ntilde": 0x00D1,
|
||||
"Ograve": 0x00D2,
|
||||
"Oacute": 0x00D3,
|
||||
"Ocirc": 0x00D4,
|
||||
"Otilde": 0x00D5,
|
||||
"Ouml": 0x00D6,
|
||||
"times": 0x00D7,
|
||||
"Oslash": 0x00D8,
|
||||
"Ugrave": 0x00D9,
|
||||
"Uacute": 0x00DA,
|
||||
"Ucirc": 0x00DB,
|
||||
"Uuml": 0x00DC,
|
||||
"Yacute": 0x00DD,
|
||||
"THORN": 0x00DE,
|
||||
"szlig": 0x00DF,
|
||||
"agrave": 0x00E0,
|
||||
"aacute": 0x00E1,
|
||||
"acirc": 0x00E2,
|
||||
"atilde": 0x00E3,
|
||||
"auml": 0x00E4,
|
||||
"aring": 0x00E5,
|
||||
"aelig": 0x00E6,
|
||||
"ccedil": 0x00E7,
|
||||
"egrave": 0x00E8,
|
||||
"eacute": 0x00E9,
|
||||
"ecirc": 0x00EA,
|
||||
"euml": 0x00EB,
|
||||
"igrave": 0x00EC,
|
||||
"iacute": 0x00ED,
|
||||
"icirc": 0x00EE,
|
||||
"iuml": 0x00EF,
|
||||
"eth": 0x00F0,
|
||||
"ntilde": 0x00F1,
|
||||
"ograve": 0x00F2,
|
||||
"oacute": 0x00F3,
|
||||
"ocirc": 0x00F4,
|
||||
"otilde": 0x00F5,
|
||||
"ouml": 0x00F6,
|
||||
"divide": 0x00F7,
|
||||
"oslash": 0x00F8,
|
||||
"ugrave": 0x00F9,
|
||||
"uacute": 0x00FA,
|
||||
"ucirc": 0x00FB,
|
||||
"uuml": 0x00FC,
|
||||
"yacute": 0x00FD,
|
||||
"thorn": 0x00FE,
|
||||
"yuml": 0x00FF,
|
||||
"OElig": 0x0152,
|
||||
"oelig": 0x0153,
|
||||
"Scaron": 0x0160,
|
||||
"scaron": 0x0161,
|
||||
"Yuml": 0x0178,
|
||||
"fnof": 0x0192,
|
||||
"circ": 0x02C6,
|
||||
"tilde": 0x02DC,
|
||||
"Alpha": 0x0391,
|
||||
"Beta": 0x0392,
|
||||
"Gamma": 0x0393,
|
||||
"Delta": 0x0394,
|
||||
"Epsilon": 0x0395,
|
||||
"Zeta": 0x0396,
|
||||
"Eta": 0x0397,
|
||||
"Theta": 0x0398,
|
||||
"Iota": 0x0399,
|
||||
"Kappa": 0x039A,
|
||||
"Lambda": 0x039B,
|
||||
"Mu": 0x039C,
|
||||
"Nu": 0x039D,
|
||||
"Xi": 0x039E,
|
||||
"Omicron": 0x039F,
|
||||
"Pi": 0x03A0,
|
||||
"Rho": 0x03A1,
|
||||
"Sigma": 0x03A3,
|
||||
"Tau": 0x03A4,
|
||||
"Upsilon": 0x03A5,
|
||||
"Phi": 0x03A6,
|
||||
"Chi": 0x03A7,
|
||||
"Psi": 0x03A8,
|
||||
"Omega": 0x03A9,
|
||||
"alpha": 0x03B1,
|
||||
"beta": 0x03B2,
|
||||
"gamma": 0x03B3,
|
||||
"delta": 0x03B4,
|
||||
"epsilon": 0x03B5,
|
||||
"zeta": 0x03B6,
|
||||
"eta": 0x03B7,
|
||||
"theta": 0x03B8,
|
||||
"iota": 0x03B9,
|
||||
"kappa": 0x03BA,
|
||||
"lambda": 0x03BB,
|
||||
"mu": 0x03BC,
|
||||
"nu": 0x03BD,
|
||||
"xi": 0x03BE,
|
||||
"omicron": 0x03BF,
|
||||
"pi": 0x03C0,
|
||||
"rho": 0x03C1,
|
||||
"sigmaf": 0x03C2,
|
||||
"sigma": 0x03C3,
|
||||
"tau": 0x03C4,
|
||||
"upsilon": 0x03C5,
|
||||
"phi": 0x03C6,
|
||||
"chi": 0x03C7,
|
||||
"psi": 0x03C8,
|
||||
"omega": 0x03C9,
|
||||
"thetasym": 0x03D1,
|
||||
"upsih": 0x03D2,
|
||||
"piv": 0x03D6,
|
||||
"ensp": 0x2002,
|
||||
"emsp": 0x2003,
|
||||
"thinsp": 0x2009,
|
||||
"zwnj": 0x200C,
|
||||
"zwj": 0x200D,
|
||||
"lrm": 0x200E,
|
||||
"rlm": 0x200F,
|
||||
"ndash": 0x2013,
|
||||
"mdash": 0x2014,
|
||||
"lsquo": 0x2018,
|
||||
"rsquo": 0x2019,
|
||||
"sbquo": 0x201A,
|
||||
"ldquo": 0x201C,
|
||||
"rdquo": 0x201D,
|
||||
"bdquo": 0x201E,
|
||||
"dagger": 0x2020,
|
||||
"Dagger": 0x2021,
|
||||
"bull": 0x2022,
|
||||
"hellip": 0x2026,
|
||||
"permil": 0x2030,
|
||||
"prime": 0x2032,
|
||||
"Prime": 0x2033,
|
||||
"lsaquo": 0x2039,
|
||||
"rsaquo": 0x203A,
|
||||
"oline": 0x203E,
|
||||
"frasl": 0x2044,
|
||||
"euro": 0x20AC,
|
||||
"image": 0x2111,
|
||||
"weierp": 0x2118,
|
||||
"real": 0x211C,
|
||||
"trade": 0x2122,
|
||||
"alefsym": 0x2135,
|
||||
"larr": 0x2190,
|
||||
"uarr": 0x2191,
|
||||
"rarr": 0x2192,
|
||||
"darr": 0x2193,
|
||||
"harr": 0x2194,
|
||||
"crarr": 0x21B5,
|
||||
"lArr": 0x21D0,
|
||||
"uArr": 0x21D1,
|
||||
"rArr": 0x21D2,
|
||||
"dArr": 0x21D3,
|
||||
"hArr": 0x21D4,
|
||||
"forall": 0x2200,
|
||||
"part": 0x2202,
|
||||
"exist": 0x2203,
|
||||
"empty": 0x2205,
|
||||
"nabla": 0x2207,
|
||||
"isin": 0x2208,
|
||||
"notin": 0x2209,
|
||||
"ni": 0x220B,
|
||||
"prod": 0x220F,
|
||||
"sum": 0x2211,
|
||||
"minus": 0x2212,
|
||||
"lowast": 0x2217,
|
||||
"radic": 0x221A,
|
||||
"prop": 0x221D,
|
||||
"infin": 0x221E,
|
||||
"ang": 0x2220,
|
||||
"and": 0x2227,
|
||||
"or": 0x2228,
|
||||
"cap": 0x2229,
|
||||
"cup": 0x222A,
|
||||
"int": 0x222B,
|
||||
"there4": 0x2234,
|
||||
"sim": 0x223C,
|
||||
"cong": 0x2245,
|
||||
"asymp": 0x2248,
|
||||
"ne": 0x2260,
|
||||
"equiv": 0x2261,
|
||||
"le": 0x2264,
|
||||
"ge": 0x2265,
|
||||
"sub": 0x2282,
|
||||
"sup": 0x2283,
|
||||
"nsub": 0x2284,
|
||||
"sube": 0x2286,
|
||||
"supe": 0x2287,
|
||||
"oplus": 0x2295,
|
||||
"otimes": 0x2297,
|
||||
"perp": 0x22A5,
|
||||
"sdot": 0x22C5,
|
||||
"lceil": 0x2308,
|
||||
"rceil": 0x2309,
|
||||
"lfloor": 0x230A,
|
||||
"rfloor": 0x230B,
|
||||
"lang": 0x2329,
|
||||
"rang": 0x232A,
|
||||
"loz": 0x25CA,
|
||||
"spades": 0x2660,
|
||||
"clubs": 0x2663,
|
||||
"hearts": 0x2665,
|
||||
"diams": 0x2666
|
||||
};
|
||||
}
|
11
src/compiler/transforms/module/es6.ts
Normal file
11
src/compiler/transforms/module/es6.ts
Normal file
|
@ -0,0 +1,11 @@
|
|||
/// <reference path="./module.ts" />
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function createES6ModuleTransformation(transformer: Transformer): Transformation {
|
||||
return transformES6Module;
|
||||
|
||||
function transformES6Module(node: SourceFile) {
|
||||
return node;
|
||||
}
|
||||
}
|
||||
}
|
705
src/compiler/transforms/module/module.ts
Normal file
705
src/compiler/transforms/module/module.ts
Normal file
|
@ -0,0 +1,705 @@
|
|||
/// <reference path="../../checker.ts" />
|
||||
/*@internal*/
|
||||
namespace ts {
|
||||
export function createModuleTransformation(transformer: Transformer): Transformation {
|
||||
const emitModuleDelegates: Map<(node: SourceFile, write: (node: Statement) => void) => void> = {
|
||||
[ModuleKind.None]: emitCommonJSModule,
|
||||
[ModuleKind.AMD]: emitAMDModule,
|
||||
[ModuleKind.UMD]: emitUMDModule,
|
||||
[ModuleKind.CommonJS]: emitCommonJSModule,
|
||||
};
|
||||
|
||||
let {
|
||||
getGeneratedNameForNode,
|
||||
hoistVariableDeclaration,
|
||||
hoistFunctionDeclaration,
|
||||
startLexicalEnvironment,
|
||||
endLexicalEnvironment,
|
||||
pipeNode,
|
||||
pipeNodes,
|
||||
mapNode,
|
||||
mapNodes,
|
||||
flattenNode,
|
||||
visitNode,
|
||||
visitNodes,
|
||||
accept
|
||||
} = transformer;
|
||||
|
||||
let compilerOptions = transformer.getCompilerOptions();
|
||||
let resolver = transformer.getEmitResolver();
|
||||
let languageVersion = getLanguageVersion(compilerOptions);
|
||||
let moduleKind = getModuleKind(compilerOptions);
|
||||
let currentSourceFile: SourceFile;
|
||||
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[];
|
||||
let exportSpecifiers: Map<ExportSpecifier[]>;
|
||||
let exportEquals: ExportAssignment;
|
||||
let hasExportStars: boolean;
|
||||
let exportAssignmentWriter: (node: Statement) => void;
|
||||
let savedExpressionSubstution = transformer.getExpressionSubstitution();
|
||||
transformer.setExpressionSubstitution(substituteExpressionWithFallback);
|
||||
return transformModule;
|
||||
|
||||
/**
|
||||
* Transforms a source file via the provided module emit callback.
|
||||
*/
|
||||
function transformModule(node: SourceFile): SourceFile {
|
||||
if (isExternalModule(node) || compilerOptions.isolatedModules) {
|
||||
currentSourceFile = node;
|
||||
|
||||
// collect information about the external module
|
||||
({ externalImports, exportSpecifiers, exportEquals, hasExportStars } = collectExternalModuleInfo(node, resolver));
|
||||
|
||||
let emitModule = emitModuleDelegates[moduleKind];
|
||||
node = updateSourceFileNode(node, flattenNode(node, emitModule), node.endOfFileToken);
|
||||
|
||||
if (hasExportStars && emitModule === emitCommonJSModule) {
|
||||
transformer.setGeneratedNodeFlags(node, GeneratedNodeFlags.EmitExportStar);
|
||||
}
|
||||
|
||||
currentSourceFile = undefined;
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits file prologue directives prior to a module body.
|
||||
*/
|
||||
function emitPrologueDirectives(statements: NodeArray<Statement>, write: (node: Statement) => void): number {
|
||||
for (let i = 0; i < statements.length; ++i) {
|
||||
if (isPrologueDirective(statements[i])) {
|
||||
write(statements[i]);
|
||||
}
|
||||
else {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return statements.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits a CommonJS module.
|
||||
*/
|
||||
function emitCommonJSModule(node: SourceFile, write: (node: Statement) => void) {
|
||||
startLexicalEnvironment();
|
||||
|
||||
let statementOffset = emitPrologueDirectives(node.statements, write);
|
||||
|
||||
pipeNodes(node.statements, visitModuleElement, write, statementOffset);
|
||||
endLexicalEnvironment(write);
|
||||
|
||||
let exportEquals = tryCreateExportEquals(/*emitAsReturn*/ false);
|
||||
if (exportEquals) {
|
||||
write(exportEquals);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an AMD module.
|
||||
*/
|
||||
function emitAMDModule(node: SourceFile, write: (node: Statement) => void) {
|
||||
let define = createIdentifier("define");
|
||||
let moduleName = node.moduleName ? createStringLiteral(node.moduleName) : undefined;
|
||||
emitAsynchronousModule(node, write, define, moduleName, /*includeNonAmdDependencies*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an UMD module.
|
||||
*/
|
||||
function emitUMDModule(node: SourceFile, write: (node: Statement) => void) {
|
||||
let define = createIdentifier("define");
|
||||
transformer.setGeneratedNodeFlags(define, GeneratedNodeFlags.UMDDefine);
|
||||
emitAsynchronousModule(node, write, define, /*moduleName*/ undefined, /*includeNonAmdDependencies*/ false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Emits an asynchronous module (AMD/UMD).
|
||||
* @param node The source file to transform.
|
||||
* @param write The callback used to emit the module body.
|
||||
* @param define The expression called to define the asynchronous module body.
|
||||
* @param moduleName The expression
|
||||
*/
|
||||
function emitAsynchronousModule(node: SourceFile, write: (node: Statement) => void, define: Expression, moduleName: Expression, includeNonAmdDependencies: boolean) {
|
||||
// Start the lexical environment for the source file.
|
||||
startLexicalEnvironment();
|
||||
|
||||
let statementOffset = emitPrologueDirectives(node.statements, write);
|
||||
|
||||
// An AMD define function has the following shape:
|
||||
// define(id?, dependencies?, factory);
|
||||
//
|
||||
// This has the shape of
|
||||
// define(name, ["module1", "module2"], function (module1Alias) {
|
||||
// The location of the alias in the parameter list in the factory function needs to
|
||||
// match the position of the module name in the dependency list.
|
||||
//
|
||||
// To ensure this is true in cases of modules with no aliases, e.g.:
|
||||
// `import "module"` or `<amd-dependency path= "a.css" />`
|
||||
// we need to add modules without alias names to the end of the dependencies list
|
||||
|
||||
let defineArguments: Expression[] = [];
|
||||
if (moduleName) {
|
||||
defineArguments.push(moduleName);
|
||||
}
|
||||
|
||||
let aliasedModuleNames: Expression[] = [
|
||||
createStringLiteral("require"),
|
||||
createStringLiteral("exports")
|
||||
];
|
||||
|
||||
let unaliasedModuleNames: Expression[] = [];
|
||||
|
||||
let importAliasNames: ParameterDeclaration[] = [
|
||||
createParameter3("require"),
|
||||
createParameter3("exports")
|
||||
];
|
||||
|
||||
for (let amdDependency of node.amdDependencies) {
|
||||
if (amdDependency.name) {
|
||||
aliasedModuleNames.push(createStringLiteral(amdDependency.name));
|
||||
importAliasNames.push(createParameter3(amdDependency.name));
|
||||
}
|
||||
else {
|
||||
unaliasedModuleNames.push(createStringLiteral(amdDependency.path));
|
||||
}
|
||||
}
|
||||
|
||||
for (let importNode of externalImports) {
|
||||
// Find the name of the external module
|
||||
let externalModuleName = getExternalModuleNameLiteral(importNode);
|
||||
// Find the name of the module alias, if there is one
|
||||
let importAliasName = getLocalNameForExternalImport(importNode);
|
||||
if (includeNonAmdDependencies && importAliasName) {
|
||||
aliasedModuleNames.push(externalModuleName);
|
||||
importAliasNames.push(createParameter2(importAliasName));
|
||||
}
|
||||
else {
|
||||
unaliasedModuleNames.push(externalModuleName);
|
||||
}
|
||||
}
|
||||
|
||||
// Create the import names array.
|
||||
let imports = createArrayLiteralExpression(concatenate(aliasedModuleNames, unaliasedModuleNames));
|
||||
defineArguments.push(imports);
|
||||
|
||||
// Create the body of the module.
|
||||
let statements: Statement[] = [];
|
||||
|
||||
// Start the lexical environment for the module body.
|
||||
startLexicalEnvironment();
|
||||
|
||||
// Pipe each statement of the source file through a visitor and out to the module body
|
||||
pipeNodes(node.statements, visitModuleElement, statements, statementOffset);
|
||||
|
||||
// End the lexical environment for the module body.
|
||||
endLexicalEnvironment(statements);
|
||||
|
||||
// Append the 'export =' statement if provided.
|
||||
let exportEquals = tryCreateExportEquals(/*emitAsReturn*/ true);
|
||||
if (exportEquals) {
|
||||
statements.push(exportEquals);
|
||||
}
|
||||
|
||||
// Create the function for the module body.
|
||||
let moduleBody = createBlock(statements);
|
||||
|
||||
if (hasExportStars) {
|
||||
transformer.setGeneratedNodeFlags(moduleBody, GeneratedNodeFlags.EmitExportStar);
|
||||
}
|
||||
|
||||
let moduleFunc = createFunctionExpression3(importAliasNames, moduleBody);
|
||||
defineArguments.push(moduleFunc);
|
||||
|
||||
// create the definition
|
||||
let defineCall = createCallExpression2(define, defineArguments);
|
||||
write(createExpressionStatement(defineCall));
|
||||
|
||||
// End the lexical environment for the source file.
|
||||
endLexicalEnvironment(write);
|
||||
}
|
||||
|
||||
function visitModuleElement(node: Statement, write: (node: Statement) => void) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
return visitImportDeclaration(<ImportDeclaration>node, write);
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
return visitImportEqualsDeclaration(<ImportEqualsDeclaration>node, write);
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
return visitExportDeclaration(<ExportDeclaration>node, write);
|
||||
case SyntaxKind.ExportAssignment:
|
||||
return visitExportAssignment(<ExportAssignment>node, write);
|
||||
case SyntaxKind.VariableStatement:
|
||||
return visitVariableStatement(<VariableStatement>node, write);
|
||||
case SyntaxKind.FunctionDeclaration:
|
||||
return visitFunctionDeclaration(<FunctionDeclaration>node, write);
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
return visitClassDeclaration(<ClassDeclaration>node, write);
|
||||
default:
|
||||
return write(node);
|
||||
}
|
||||
}
|
||||
|
||||
function visitImportDeclaration(node: ImportDeclaration, write: (node: Statement) => void): void {
|
||||
if (contains(externalImports, node)) {
|
||||
let namespaceDeclaration = getNamespaceDeclarationNode(node);
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
let require = createRequireCall(node);
|
||||
if (!node.importClause) {
|
||||
// import "mod";
|
||||
write(createExpressionStatement(require, /*location*/ node));
|
||||
}
|
||||
else {
|
||||
let variables: VariableDeclaration[] = [];
|
||||
if (namespaceDeclaration && !isDefaultImport(node)) {
|
||||
// import * as n from "mod";
|
||||
variables.push(createVariableDeclaration2(makeSynthesized(namespaceDeclaration.name), require));
|
||||
}
|
||||
else {
|
||||
// import d from "mod";
|
||||
// import { x, y } from "mod";
|
||||
// import d, { x, y } from "mod";
|
||||
// import d, * as n from "mod";
|
||||
variables.push(createVariableDeclaration2(getGeneratedNameForNode(node), require));
|
||||
if (namespaceDeclaration && isDefaultImport(node)) {
|
||||
variables.push(createVariableDeclaration2(makeSynthesized(namespaceDeclaration.name), getGeneratedNameForNode(node)));
|
||||
}
|
||||
}
|
||||
|
||||
write(createVariableStatement2(createVariableDeclarationList(variables), /*location*/ node));
|
||||
}
|
||||
}
|
||||
else if (namespaceDeclaration && isDefaultImport(node)) {
|
||||
// import d, * as n from "mod";
|
||||
write(createVariableStatement3(makeSynthesized(namespaceDeclaration.name), getGeneratedNameForNode(node), /*location*/ node));
|
||||
}
|
||||
|
||||
emitExportImportAssignments(node, write);
|
||||
}
|
||||
}
|
||||
|
||||
function visitImportEqualsDeclaration(node: ImportEqualsDeclaration, write: (node: Statement) => void): void {
|
||||
if (contains(externalImports, node)) {
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
let require = createRequireCall(node);
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
write(createExpressionStatement(createExportAssignment(node.name, require), /*location*/ node));
|
||||
}
|
||||
else {
|
||||
write(createVariableStatement3(makeSynthesized(node.name), require, /*location*/ node));
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
write(createExpressionStatement(createExportAssignment(node.name, node.name), /*location*/ node));
|
||||
}
|
||||
}
|
||||
|
||||
emitExportImportAssignments(node, write);
|
||||
}
|
||||
}
|
||||
|
||||
function visitExportDeclaration(node: ExportDeclaration, write: (node: Statement) => void): void {
|
||||
if (contains(externalImports, node)) {
|
||||
let generatedName = getGeneratedNameForNode(node);
|
||||
if (node.exportClause) {
|
||||
// export { x, y } from "mod";
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
write(createVariableStatement3(generatedName, createRequireCall(node)));
|
||||
}
|
||||
for (let specifier of node.exportClause.elements) {
|
||||
if (resolver.isValueAliasDeclaration(specifier)) {
|
||||
let exportedValue = createPropertyAccessExpression2(generatedName, specifier.propertyName || specifier.name);
|
||||
write(createExpressionStatement(createExportAssignment(specifier.name, exportedValue), /*location*/ specifier));
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export * from "mod";
|
||||
if (moduleKind !== ModuleKind.AMD) {
|
||||
write(createExpressionStatement(createExportStarHelperCall(createRequireCall(node)), /*location*/ node));
|
||||
}
|
||||
else {
|
||||
write(createExpressionStatement(createExportStarHelperCall(generatedName), /*location*/ node));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function visitExportAssignment(node: ExportAssignment, write: (node: Statement) => void): void {
|
||||
if (!node.isExportEquals && resolver.isValueAliasDeclaration(node)) {
|
||||
emitExportDefault(node.expression, /*location*/ node, write);
|
||||
}
|
||||
}
|
||||
|
||||
function emitExportDefault(expression: Expression, location: TextRange, write: (node: Statement) => void): void {
|
||||
emitExportDefaultCompat(write);
|
||||
let defaultName = createIdentifier("default", SyntaxKind.DefaultKeyword);
|
||||
write(createExpressionStatement(createExportAssignment(defaultName, expression), location));
|
||||
}
|
||||
|
||||
function emitExportDefaultCompat(write: (node: Statement) => void): void {
|
||||
let originalSourceFile = getOriginalNodeIf(currentSourceFile, isSourceFile);
|
||||
if (!originalSourceFile.symbol.exports["___esModule"]) {
|
||||
if (languageVersion === ScriptTarget.ES3) {
|
||||
let esModule = createIdentifier("__esModule");
|
||||
write(createExpressionStatement(createExportAssignment(esModule, createTrueKeyword())));
|
||||
}
|
||||
else {
|
||||
let exports = createIdentifier("exports");
|
||||
let esModule = createStringLiteral("__esModule");
|
||||
let descriptor = createDataPropertyDescriptor(createTrueKeyword(), PropertyDescriptorFlags.Empty);
|
||||
write(createExpressionStatement(createDefinePropertyCall(exports, esModule, descriptor)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitExportImportAssignments(node: Node, write: (node: Statement) => void) {
|
||||
let savedExportImportAssignmentWriter = exportAssignmentWriter;
|
||||
exportAssignmentWriter = write;
|
||||
emitExportImportAssignmentsUsingCapturedWriter(node);
|
||||
exportAssignmentWriter = savedExportImportAssignmentWriter;
|
||||
}
|
||||
|
||||
function emitExportImportAssignmentsUsingCapturedWriter(node: Node) {
|
||||
if (isAliasSymbolDeclaration(node) && resolver.isValueAliasDeclaration(node)) {
|
||||
emitExportMemberAssignmentsUsingCapturedWriter(<Identifier>(<Declaration>node).name);
|
||||
}
|
||||
|
||||
forEachChild(node, emitExportImportAssignmentsUsingCapturedWriter);
|
||||
}
|
||||
|
||||
function emitExportMemberAssignmentsUsingCapturedWriter(name: Identifier) {
|
||||
emitExportMemberAssignments(name, exportAssignmentWriter);
|
||||
}
|
||||
|
||||
function emitExportMemberAssignments(name: Identifier, write: (node: Statement) => void): void {
|
||||
if (!exportEquals && exportSpecifiers && hasProperty(exportSpecifiers, name.text)) {
|
||||
for (let specifier of exportSpecifiers[name.text]) {
|
||||
write(createExpressionStatement(createExportAssignment(specifier.name, name), /*location*/ specifier.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function visitVariableStatement(node: VariableStatement, write: (node: Statement) => void): void {
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
pipeNode(node.declarationList, transformVariableDeclarationListToExpressionStatement, write);
|
||||
}
|
||||
else {
|
||||
write(node);
|
||||
}
|
||||
}
|
||||
|
||||
function transformVariableDeclarationListToExpressionStatement(node: VariableDeclarationList, write: (node: Statement) => void): void {
|
||||
let expressions = mapNodes(node.declarations, transformVariableDeclarationToExpression);
|
||||
if (expressions.length) {
|
||||
write(createExpressionStatement(inlineExpressions(expressions)));
|
||||
}
|
||||
|
||||
pipeNodes(node.declarations, emitVariableExportAssignments, write);
|
||||
}
|
||||
|
||||
function transformVariableDeclarationToExpression(node: VariableDeclaration, write: (node: Expression) => void): void {
|
||||
if (!node.initializer) {
|
||||
return;
|
||||
}
|
||||
|
||||
transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from either `transformVariableDeclarationToExpression` or
|
||||
* `transformBindingElementToExpression` and should not be called otherwise.
|
||||
*/
|
||||
function transformBindingElementToExpressionWithParenthesisIfNeeded(node: BindingElement, write: (node: Expression) => void, parenthesizeObjectLiteralAssignment?: boolean) {
|
||||
let name = node.name;
|
||||
let expr = isBindingPattern(name)
|
||||
? mapNode(name, transformBindingPatternToExpression)
|
||||
: createPropertyAccessExpression2(createIdentifier("exports"), makeSynthesized(name));
|
||||
|
||||
let initializer = node.initializer;
|
||||
if (initializer) {
|
||||
expr = createAssignmentExpression(expr, initializer, /*location*/ node);
|
||||
}
|
||||
|
||||
if (parenthesizeObjectLiteralAssignment && isObjectBindingPattern(name)) {
|
||||
expr = createParenthesizedExpression(expr);
|
||||
}
|
||||
else if (node.dotDotDotToken) {
|
||||
expr = createSpreadElementExpression(expr);
|
||||
}
|
||||
|
||||
write(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from `transformVariableDeclarationToExpression` and should not be called otherwise.
|
||||
*/
|
||||
function transformBindingPatternToExpression(node: BindingPattern, write: (node: Expression) => void) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ObjectBindingPattern:
|
||||
return transformObjectBindingPatternToExpression(<ObjectBindingPattern>node, write);
|
||||
|
||||
case SyntaxKind.ArrayBindingPattern:
|
||||
return transformArrayBindingPatternToExpression(<ObjectBindingPattern>node, write);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from `transformBindingPatternToExpression` and should not be called otherwise.
|
||||
*/
|
||||
function transformObjectBindingPatternToExpression(node: ObjectBindingPattern, write: (node: Expression) => void) {
|
||||
let properties = mapNodes(node.elements, transformBindingElementToObjectLiteralElement);
|
||||
write(createObjectLiteralExpression(properties, /*location*/ node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from `transformBindingPatternToExpression` and should not be called otherwise.
|
||||
*/
|
||||
function transformArrayBindingPatternToExpression(node: ArrayBindingPattern, write: (node: Expression) => void) {
|
||||
let elements = mapNodes(node.elements, transformBindingElementToExpression);
|
||||
write(createArrayLiteralExpression(elements, /*location*/ node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from `transformObjectBindingPatternToExpression` and should not be called otherwise.
|
||||
*/
|
||||
function transformBindingElementToObjectLiteralElement(node: BindingElement, write: (node: ObjectLiteralElement) => void) {
|
||||
let propertyName = node.propertyName || <Identifier>node.name;
|
||||
let expr = mapNode(node, transformBindingElementToExpression);
|
||||
write(createPropertyAssignment(propertyName, expr, /*location*/ node));
|
||||
}
|
||||
|
||||
/**
|
||||
* @remarks
|
||||
* This function is intended to be called from `transformArrayBindingPatternToExpression` or
|
||||
* `transformBindingElementToObjectLiteralElement` and should not be called otherwise.
|
||||
*/
|
||||
function transformBindingElementToExpression(node: BindingElement, write: (node: Expression) => void) {
|
||||
transformBindingElementToExpressionWithParenthesisIfNeeded(node, write, /*parenthesizeObjectLiteralAssignment*/ false);
|
||||
}
|
||||
|
||||
function emitVariableExportAssignments(node: VariableDeclaration | BindingElement, write: (node: Statement) => void): void {
|
||||
let name = node.name;
|
||||
if (isIdentifier(name)) {
|
||||
emitExportMemberAssignments(name, write);
|
||||
}
|
||||
else if (isBindingPattern(name)) {
|
||||
pipeNodes(name.elements, emitVariableExportAssignments, write);
|
||||
}
|
||||
}
|
||||
|
||||
function visitFunctionDeclaration(node: FunctionDeclaration, write: (node: Statement) => void): void {
|
||||
const location: TextRange = node;
|
||||
if (node.name) {
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
write(createFunctionDeclaration2(node.name, node.parameters, node.body, location));
|
||||
if (node.flags & NodeFlags.Default) {
|
||||
emitExportDefault(makeSynthesized(node.name), location, write);
|
||||
}
|
||||
}
|
||||
else {
|
||||
write(node);
|
||||
}
|
||||
|
||||
emitExportMemberAssignments(node.name, write);
|
||||
}
|
||||
else if (node.flags & NodeFlags.Default) {
|
||||
emitExportDefault(createFunctionExpression3(node.parameters, node.body), location, write);
|
||||
}
|
||||
}
|
||||
|
||||
function visitClassDeclaration(node: ClassDeclaration, write: (node: Statement) => void): void {
|
||||
const location: TextRange = node;
|
||||
if (node.name) {
|
||||
if (node.flags & NodeFlags.Export) {
|
||||
write(createClassDeclaration2(node.name, getClassExtendsHeritageClauseElement(node), node.members, location));
|
||||
if (node.flags & NodeFlags.Default) {
|
||||
emitExportDefault(makeSynthesized(node.name), location, write);
|
||||
}
|
||||
}
|
||||
else {
|
||||
write(node);
|
||||
}
|
||||
|
||||
emitExportMemberAssignments(node.name, write);
|
||||
}
|
||||
else if (node.flags & NodeFlags.Default) {
|
||||
emitExportDefault(createClassExpression3(getClassExtendsHeritageClauseElement(node), node.members), location, write);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Substitution for identifiers exported at the top level of a module.
|
||||
*/
|
||||
function substituteExpressionWithFallback(node: Expression): Expression {
|
||||
let substitute = substituteExpression(node);
|
||||
return savedExpressionSubstution ? savedExpressionSubstution(substitute) : substitute;
|
||||
}
|
||||
|
||||
function substituteExpression(node: Expression): Expression {
|
||||
if (isIdentifier(node)) {
|
||||
return substituteExpressionIdentifier(node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
function substituteExpressionIdentifier(node: Identifier): Expression {
|
||||
let container = resolver.getReferencedExportContainer(node);
|
||||
if (isSourceFile(container)) {
|
||||
return createPropertyAccessExpression2(createIdentifier("exports"), makeSynthesized(node), /*location*/ node);
|
||||
}
|
||||
|
||||
return node;
|
||||
}
|
||||
|
||||
function tryCreateExportEquals(emitAsReturn: boolean) {
|
||||
if (exportEquals && resolver.isValueAliasDeclaration(exportEquals)) {
|
||||
if (emitAsReturn) {
|
||||
return createReturnStatement(exportEquals.expression);
|
||||
}
|
||||
else {
|
||||
let moduleExports = createPropertyAccessExpression3(createIdentifier("module"), "exports");
|
||||
let exportExpression = createAssignmentExpression(moduleExports, exportEquals.expression);
|
||||
return createExpressionStatement(exportExpression);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getExternalModuleNameLiteral(importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration) {
|
||||
let moduleName = getExternalModuleName(importNode);
|
||||
if (isStringLiteral(moduleName)) {
|
||||
return tryRenameExternalModule(moduleName) || makeSynthesized(moduleName);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/**
|
||||
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
|
||||
* Here we check if alternative name was provided for a given moduleName and return it if possible.
|
||||
*/
|
||||
function tryRenameExternalModule(moduleName: LiteralExpression) {
|
||||
if (currentSourceFile.renamedDependencies && hasProperty(currentSourceFile.renamedDependencies, moduleName.text)) {
|
||||
return createStringLiteral(currentSourceFile.renamedDependencies[moduleName.text]);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function getLocalNameForExternalImport(node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration): Identifier {
|
||||
let namespaceDeclaration = getNamespaceDeclarationNode(node);
|
||||
if (namespaceDeclaration && !isDefaultImport(node)) {
|
||||
return createIdentifier(getSourceTextOfNodeFromSourceFile(currentSourceFile, namespaceDeclaration.name));
|
||||
}
|
||||
if (node.kind === SyntaxKind.ImportDeclaration && (<ImportDeclaration>node).importClause) {
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
if (node.kind === SyntaxKind.ExportDeclaration && (<ExportDeclaration>node).moduleSpecifier) {
|
||||
return getGeneratedNameForNode(node);
|
||||
}
|
||||
}
|
||||
|
||||
function getNamespaceDeclarationNode(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
|
||||
if (node.kind === SyntaxKind.ImportEqualsDeclaration) {
|
||||
return <ImportEqualsDeclaration>node;
|
||||
}
|
||||
|
||||
let importClause = (<ImportDeclaration>node).importClause;
|
||||
if (importClause && importClause.namedBindings && importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
|
||||
return <NamespaceImport>importClause.namedBindings;
|
||||
}
|
||||
}
|
||||
|
||||
function isDefaultImport(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
|
||||
return isImportDeclaration(node) && node.importClause && !!node.importClause.name;
|
||||
}
|
||||
|
||||
function createRequireCall(importNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration) {
|
||||
let moduleName = getExternalModuleNameLiteral(importNode);
|
||||
return createCallExpression2(createIdentifier("require"), moduleName ? [moduleName] : []);
|
||||
}
|
||||
|
||||
function emitExportAssignment(name: Identifier, value: Expression, location: TextRange, write: (node: Statement) => void) {
|
||||
write(createExpressionStatement(createExportAssignment(name, value), location));
|
||||
}
|
||||
|
||||
function createExportAssignment(name: Identifier, value: Expression) {
|
||||
let exports = createIdentifier("exports");
|
||||
let exportMember: LeftHandSideExpression;
|
||||
if (name.originalKeywordKind && languageVersion === ScriptTarget.ES3) {
|
||||
let exportName = createStringLiteral(name.text);
|
||||
exportMember = createElementAccessExpression2(exports, exportName);
|
||||
}
|
||||
else {
|
||||
let exportName = makeSynthesized(name);
|
||||
exportMember = createPropertyAccessExpression2(exports, exportName);
|
||||
}
|
||||
|
||||
return createAssignmentExpression(exportMember, value);
|
||||
}
|
||||
}
|
||||
|
||||
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver) {
|
||||
let externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
|
||||
let exportSpecifiers: Map<ExportSpecifier[]> = {};
|
||||
let exportEquals: ExportAssignment = undefined;
|
||||
let hasExportStars = false;
|
||||
for (let node of sourceFile.statements) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ImportDeclaration:
|
||||
if (!(<ImportDeclaration>node).importClause ||
|
||||
resolver.isReferencedAliasDeclaration((<ImportDeclaration>node).importClause, /*checkChildren*/ true)) {
|
||||
// import "mod"
|
||||
// import x from "mod" where x is referenced
|
||||
// import * as x from "mod" where x is referenced
|
||||
// import { x, y } from "mod" where at least one import is referenced
|
||||
externalImports.push(<ImportDeclaration>node);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ImportEqualsDeclaration:
|
||||
if ((<ImportEqualsDeclaration>node).moduleReference.kind === SyntaxKind.ExternalModuleReference && resolver.isReferencedAliasDeclaration(node)) {
|
||||
// import x = require("mod") where x is referenced
|
||||
externalImports.push(<ImportEqualsDeclaration>node);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportDeclaration:
|
||||
if ((<ExportDeclaration>node).moduleSpecifier) {
|
||||
if (!(<ExportDeclaration>node).exportClause) {
|
||||
// export * from "mod"
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
hasExportStars = true;
|
||||
}
|
||||
else if (resolver.isValueAliasDeclaration(node)) {
|
||||
// export { x, y } from "mod" where at least one export is a value symbol
|
||||
externalImports.push(<ExportDeclaration>node);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// export { x, y }
|
||||
for (let specifier of (<ExportDeclaration>node).exportClause.elements) {
|
||||
let name = (specifier.propertyName || specifier.name).text;
|
||||
(exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.ExportAssignment:
|
||||
if ((<ExportAssignment>node).isExportEquals && !exportEquals) {
|
||||
// export = x
|
||||
exportEquals = <ExportAssignment>node;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return { externalImports, exportSpecifiers, exportEquals, hasExportStars };
|
||||
}
|
||||
}
|
1161
src/compiler/transforms/module/system.ts
Normal file
1161
src/compiler/transforms/module/system.ts
Normal file
File diff suppressed because it is too large
Load diff
1776
src/compiler/transforms/ts.ts
Normal file
1776
src/compiler/transforms/ts.ts
Normal file
File diff suppressed because it is too large
Load diff
|
@ -225,7 +225,7 @@ namespace ts {
|
|||
}
|
||||
|
||||
function reportStatisticalValue(name: string, value: string) {
|
||||
sys.write(padRight(name + ":", 12) + padLeft(value.toString(), 10) + sys.newLine);
|
||||
sys.write(padRight(name + ":", 20) + padLeft(value.toString(), 10) + sys.newLine);
|
||||
}
|
||||
|
||||
function reportCountStatistic(name: string, count: number) {
|
||||
|
@ -324,7 +324,7 @@ namespace ts {
|
|||
if (sys.watchDirectory && configFileName) {
|
||||
const directory = ts.getDirectoryPath(configFileName);
|
||||
directoryWatcher = sys.watchDirectory(
|
||||
// When the configFileName is just "tsconfig.json", the watched directory should be
|
||||
// When the configFileName is just "tsconfig.json", the watched directory should be
|
||||
// the current direcotry; if there is a given "project" parameter, then the configFileName
|
||||
// is an absolute file name.
|
||||
directory == "" ? "." : directory,
|
||||
|
@ -519,6 +519,7 @@ namespace ts {
|
|||
bindTime = 0;
|
||||
checkTime = 0;
|
||||
emitTime = 0;
|
||||
transformTime = 0;
|
||||
|
||||
const program = createProgram(fileNames, compilerOptions, compilerHost);
|
||||
const exitStatus = compileProgram();
|
||||
|
@ -551,6 +552,7 @@ namespace ts {
|
|||
reportTimeStatistic("Parse time", programTime);
|
||||
reportTimeStatistic("Bind time", bindTime);
|
||||
reportTimeStatistic("Check time", checkTime);
|
||||
reportTimeStatistic("Transform time", transformTime);
|
||||
reportTimeStatistic("Emit time", emitTime);
|
||||
reportTimeStatistic("Total time", programTime + bindTime + checkTime + emitTime);
|
||||
}
|
||||
|
@ -756,6 +758,14 @@ namespace ts {
|
|||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
declare var global: any, require: any;
|
||||
if (typeof global !== "undefined" && Object.prototype.toString.call(global.process) === '[object process]') {
|
||||
try {
|
||||
require("source-map-support").install();
|
||||
}
|
||||
catch (e) { }
|
||||
}
|
||||
}
|
||||
|
||||
ts.executeCommandLine(ts.sys.args);
|
||||
|
|
|
@ -13,10 +13,23 @@
|
|||
"types.ts",
|
||||
"diagnosticInformationMap.generated.ts",
|
||||
"scanner.ts",
|
||||
"factory.ts",
|
||||
"factory.generated.ts",
|
||||
"parser.ts",
|
||||
"utilities.ts",
|
||||
"binder.ts",
|
||||
"checker.ts",
|
||||
"transform.ts",
|
||||
"transforms/destructuring.ts",
|
||||
"transforms/ts.ts",
|
||||
"transforms/module/module.ts",
|
||||
"transforms/module/system.ts",
|
||||
"transforms/module/es6.ts",
|
||||
"transforms/jsx.ts",
|
||||
"transforms/es6.ts",
|
||||
"declarationEmitter.ts",
|
||||
"sourcemap.ts",
|
||||
"printer.ts",
|
||||
"emitter.ts",
|
||||
"program.ts",
|
||||
"commandLineParser.ts",
|
||||
|
|
File diff suppressed because it is too large
Load diff
File diff suppressed because it is too large
Load diff
1
src/harness/external/chai.d.ts
vendored
1
src/harness/external/chai.d.ts
vendored
|
@ -171,5 +171,6 @@ declare module chai {
|
|||
function isFalse(value: any, message?: string): void;
|
||||
function isNull(value: any, message?: string): void;
|
||||
function isNotNull(value: any, message?: string): void;
|
||||
function deepEqual(actual: any, expected: any, message?: string): void;
|
||||
}
|
||||
}
|
|
@ -73,4 +73,4 @@ class TypeWriterWalker {
|
|||
symbol: symbolString
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -231,7 +231,7 @@ namespace ts {
|
|||
public getText(sourceFile?: SourceFile): string {
|
||||
return (sourceFile || this.getSourceFile()).text.substring(this.getStart(), this.getEnd());
|
||||
}
|
||||
|
||||
|
||||
private addSyntheticNodes(nodes: Node[], pos: number, end: number): number {
|
||||
scanner.setTextPos(pos);
|
||||
while (pos < end) {
|
||||
|
@ -328,6 +328,10 @@ namespace ts {
|
|||
|
||||
return child.kind < SyntaxKind.FirstNode ? child : child.getLastToken(sourceFile);
|
||||
}
|
||||
|
||||
public createParentNavigator(): ParentNavigator {
|
||||
return createParentNavigator(this);
|
||||
}
|
||||
}
|
||||
|
||||
class SymbolObject implements Symbol {
|
||||
|
@ -5003,7 +5007,7 @@ namespace ts {
|
|||
}
|
||||
break;
|
||||
default:
|
||||
if (isModifier(node.kind) && node.parent &&
|
||||
if (isModifier(node) && node.parent &&
|
||||
(isDeclaration(node.parent) || node.parent.kind === SyntaxKind.VariableStatement)) {
|
||||
return getModifierOccurrences(node.kind, node.parent);
|
||||
}
|
||||
|
|
|
@ -129,7 +129,6 @@ var CC = (function () {
|
|||
}
|
||||
return CC;
|
||||
})();
|
||||
var CC;
|
||||
(function (CC) {
|
||||
CC.bar = 1;
|
||||
})(CC || (CC = {}));
|
||||
|
|
|
@ -156,7 +156,6 @@ var c = (function () {
|
|||
}
|
||||
return c;
|
||||
})();
|
||||
var c;
|
||||
(function (c) {
|
||||
c.bar = 1;
|
||||
})(c || (c = {}));
|
||||
|
|
|
@ -42,7 +42,7 @@ module M {
|
|||
//// [asyncAwaitIsolatedModules_es6.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
generator = generator.call(thisArg, _arguments);
|
||||
generator = generator.apply(thisArg, _arguments);
|
||||
function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
|
||||
function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
|
||||
function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
|
||||
|
|
|
@ -42,7 +42,7 @@ module M {
|
|||
//// [asyncAwait_es6.js]
|
||||
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promise, generator) {
|
||||
return new Promise(function (resolve, reject) {
|
||||
generator = generator.call(thisArg, _arguments);
|
||||
generator = generator.apply(thisArg, _arguments);
|
||||
function cast(value) { return value instanceof Promise && value.constructor === Promise ? value : new Promise(function (resolve) { resolve(value); }); }
|
||||
function onfulfill(value) { try { step("next", value); } catch (e) { reject(e); } }
|
||||
function onreject(value) { try { step("throw", value); } catch (e) { reject(e); } }
|
||||
|
|
|
@ -3,5 +3,4 @@ var v = class C {};
|
|||
|
||||
//// [classExpressionES61.js]
|
||||
var v = class C {
|
||||
}
|
||||
;
|
||||
};
|
||||
|
|
|
@ -6,5 +6,4 @@ var v = class C extends D {};
|
|||
class D {
|
||||
}
|
||||
var v = class C extends D {
|
||||
}
|
||||
;
|
||||
};
|
||||
|
|
|
@ -11,20 +11,17 @@ let C = class extends class extends class {
|
|||
constructor() {
|
||||
this.a = 1;
|
||||
}
|
||||
}
|
||||
{
|
||||
} {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.b = 2;
|
||||
}
|
||||
}
|
||||
{
|
||||
} {
|
||||
constructor(...args) {
|
||||
super(...args);
|
||||
this.c = 3;
|
||||
}
|
||||
}
|
||||
;
|
||||
};
|
||||
let c = new C();
|
||||
c.a;
|
||||
c.b;
|
||||
|
|
|
@ -6,6 +6,5 @@ function* g() {
|
|||
//// [generatorTypeCheck55.js]
|
||||
function* g() {
|
||||
var x = class C extends (yield) {
|
||||
}
|
||||
;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -13,6 +13,5 @@ function* g() {
|
|||
*[yield 0]() {
|
||||
yield 0;
|
||||
}
|
||||
}
|
||||
;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -992,7 +992,7 @@ module ts {
|
|||
? JSON.parse(Utils.sourceFileToJSON(v))
|
||||
: v;
|
||||
}, " ");
|
||||
|
||||
|
||||
assert.equal(result, expected);
|
||||
}
|
||||
|
||||
|
@ -1017,7 +1017,7 @@ module ts {
|
|||
it("multipleTypes", () => {
|
||||
parsesIncorrectly(
|
||||
`/**
|
||||
* @type {number}
|
||||
* @type {number}
|
||||
* @type {string}
|
||||
*/`);
|
||||
});
|
||||
|
@ -1054,7 +1054,7 @@ module ts {
|
|||
it("paramWithoutTypeOrName", () => {
|
||||
parsesIncorrectly(
|
||||
`/**
|
||||
* @param
|
||||
* @param
|
||||
*/`);
|
||||
});
|
||||
});
|
||||
|
|
Loading…
Reference in a new issue