Compare commits

...

64 commits

Author SHA1 Message Date
Ron Buckton a5b8c3f9a3 Merge branch 'master' into experimentalTransforms 2015-11-11 16:05:56 -08:00
Ron Buckton 6db601a921 Added initial source map position tracking for tokens. 2015-10-28 17:43:48 -07:00
Ron Buckton 21574cd8a6 Added source maps to printer 2015-10-28 17:24:24 -07:00
Ron Buckton 2a3f802841 Force experimental transforms for performance tests. 2015-10-28 13:36:40 -07:00
Ron Buckton bbfe33f7cd Enables source maps for exceptions in the compiler, if available. 2015-10-28 13:33:57 -07:00
Ron Buckton 74ac4c5b1c Fixed bugs in emit for more consistent output and missing hints for transformations. 2015-10-28 13:33:03 -07:00
Ron Buckton 686c94cd67 Added support for System modules. 2015-10-23 17:14:51 -07:00
Ron Buckton aa639d3ce7 Fixed bug in discoverKind. 2015-10-20 14:47:25 -07:00
Ron Buckton be1de23248 Modified associativity rules due to addition of exponentiation operator. 2015-10-16 17:57:41 -07:00
Ron Buckton 738388050f Merge branch 'master' into experimentalTransforms 2015-10-16 17:00:38 -07:00
Ron Buckton 9aafff669f Changes to the transformation chain implementation. 2015-10-16 16:18:06 -07:00
Ron Buckton abd46f9f36 Progress on printer. Added substitutions. 2015-10-16 15:03:22 -07:00
Ron Buckton e4bcfd2a5d Fixed issues with type discovery in processTypes script. 2015-10-16 13:43:12 -07:00
Ron Buckton 2403cc4414 Fixed incorrect check in tryPushNode 2015-10-16 13:39:21 -07:00
Ron Buckton 6e461e330e Initial work on simplified pretty printer. 2015-10-14 13:49:46 -07:00
Ron Buckton 2e4975d4a8 Fixed bug with discovery in processTypes 2015-10-14 13:49:17 -07:00
Ron Buckton 6a61fd295c Reverted jsDocParsing tests. 2015-10-14 13:48:12 -07:00
Ron Buckton 3ddfe83386 Clean up of jakefile 2015-10-09 15:20:52 -07:00
Ron Buckton 6235fe8280 Cleanup of processTypes script and various transformations. Added JSX 2015-10-09 15:19:07 -07:00
Ron Buckton 1c5a595d3f Merge branch 'master' into transformPerf 2015-09-16 11:38:43 -07:00
Ron Buckton 867f554a9d Partial cleanup to remove "transform" namespace. 2015-09-14 18:41:58 -07:00
Ron Buckton f6fcd5c54a Added offset information when visiting an array of nodes. 2015-09-14 15:48:26 -07:00
Ron Buckton 8cb5f78af3 Removed duplicate entries in transformNodeWorker for es6 2015-09-14 14:58:30 -07:00
Ron Buckton 36fad618f6 Fixed issue with transform flag computation in binder, and emitTokenText when the position is synthesized. 2015-09-14 13:34:42 -07:00
Ron Buckton dd998b981f Cleanup and naming 2015-09-14 09:40:18 -07:00
Ron Buckton f15d20b9f2 Cleanup and organization 2015-09-12 15:32:05 -07:00
Ron Buckton 380452becb Migrated to NodeStack for transforms 2015-09-08 17:03:30 -07:00
Ron Buckton b73bef89fc Merge branch 'noParentNodesInEmitter' into transformPerf 2015-09-08 16:51:21 -07:00
Ron Buckton 923ec29eb9 Moved createParentNavigator and createNodeStack to core 2015-09-04 10:49:45 -07:00
Ron Buckton 49a3a3f5b2 Centralized parent navigation and node stack logic 2015-09-03 15:19:47 -07:00
Ron Buckton 14d079e4d7 Merged branch 'master' into noParentNodesInEmitter 2015-08-31 12:35:22 -07:00
Ron Buckton 5d0797b2e0 Cleanup and organization 2015-08-26 13:19:18 -07:00
Ron Buckton 152e3ebc44 Moved initial transform flag aggregation to binder 2015-08-10 15:50:38 -07:00
Ron Buckton 1ba577b88d removed forced transforms 2015-08-10 10:54:54 -07:00
Ron Buckton 38c24798e4 Added performance metrics for transform and flags for types 2015-08-10 10:44:48 -07:00
Ron Buckton e984fb80b6 Set current source file as the first node in VisitorContext 2015-08-07 16:14:36 -07:00
Ron Buckton 558fc40303 Progress on downlevel transformations 2015-08-07 09:39:18 -07:00
Ron Buckton 92a7bb0462 Merge branch 'noParentNodesInEmitter' into prototypeTransformClass 2015-07-24 11:28:24 -07:00
Ron Buckton 7d97d28221 Additional comments around 'getAncestorOrSelf' callbacks 2015-07-24 11:03:35 -07:00
Ron Buckton 0b01cb85f3 Merge branch 'master' into noParentNodesInEmitter 2015-07-23 18:31:47 -07:00
Ron Buckton 3e6214939c Added stack behavior verification and ensured proper stack behavior for all emit functions 2015-07-23 18:07:31 -07:00
Ron Buckton 87e146c189 Tracking node stack behavior 2015-07-20 12:34:54 -07:00
Ron Buckton a484bb7f46 Removes most parent node references from the emitter 2015-07-17 17:00:43 -07:00
Ron Buckton 861a353ec3 Merge branch 'generateTransformMethods' into prototypeTransformClass 2015-07-15 12:45:12 -07:00
Ron Buckton 4eb12adff7 Merge branch 'generateFactoryMethods' into generateTransformMethods 2015-07-15 12:44:52 -07:00
Ron Buckton c5673b292d Merge branch 'master' into generateFactoryMethods 2015-07-15 12:44:11 -07:00
Ron Buckton 2de761cce8 cache computed property name expressions for decorators 2015-07-15 12:42:06 -07:00
Ron Buckton 4652f053b1 Partial transform for class decorators 2015-07-15 12:13:34 -07:00
Ron Buckton f3d310360b Initial transform for TypeScript class syntax extensions 2015-07-14 20:25:42 -07:00
Ron Buckton 01b34906c7 Merge branch 'generateFactoryMethods' into generateTransformMethods 2015-07-10 15:59:59 -07:00
Ron Buckton fae1d50bd7 Added flags to createNode and factory methods 2015-07-10 15:55:16 -07:00
Ron Buckton 3fe0f31e17 Added cloneNode 2015-07-10 14:17:35 -07:00
Ron Buckton 9c644dadec Merge branch 'generateFactoryMethods' into generateTransformMethods 2015-07-10 13:59:22 -07:00
Ron Buckton b3e9c25e84 Merge branch 'master' into generateFactoryMethods 2015-07-10 13:53:44 -07:00
Ron Buckton 0305d37c9e Merge branch 'generateFactoryMethods' into generateTransformMethods 2015-07-10 12:16:51 -07:00
Ron Buckton c547018e99 Added isAnyNode tests and cleaned up comment annotation parsing. 2015-07-10 12:13:10 -07:00
Ron Buckton 2c1d2184e2 Added location for factory create methods with no other arguments 2015-07-10 11:47:39 -07:00
Ron Buckton e5fce042ca Added location parameter to argument list for create functions 2015-07-10 11:42:03 -07:00
Ron Buckton 555f36b1e6 Merge branch 'generateFactoryMethods' into generateTransformMethods 2015-07-08 10:57:42 -07:00
Ron Buckton b6207f2f36 Minor cleanup 2015-07-08 10:47:01 -07:00
Ron Buckton fc51e4574b Automatic line wrapping in factory.generated.ts 2015-07-08 10:38:24 -07:00
Ron Buckton a665ef0384 Generate transform.generated.ts from processTypes script 2015-07-07 16:39:55 -07:00
Ron Buckton 66d3060210 Merge branch 'master' into generateFactoryMethods 2015-07-06 18:24:42 -07:00
Ron Buckton 474298503d Adds script to generate factory functions for each node kind 2015-07-06 18:18:59 -07:00
49 changed files with 19670 additions and 477 deletions

2
.gitignore vendored
View file

@ -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
View file

@ -0,0 +1,4 @@
// Place your settings in this file to overwrite default and user settings.
{
"files.trimTrailingWhitespace": true
}

View file

@ -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

File diff suppressed because it is too large Load diff

View 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;
}
}

View 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);
}
}

View file

@ -0,0 +1,12 @@
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"outDir": "../../built/scripts/processTypes/",
"experimentalDecorators": true,
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"sourceMap": true
}
}

File diff suppressed because it is too large Load diff

View 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;

View file

@ -0,0 +1 @@
module.exports = require("../../../lib/typescript");

View 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;
}

View file

@ -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);
}
}

View file

@ -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);

View file

@ -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",

View file

@ -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,

View file

@ -443,7 +443,7 @@ namespace ts {
}
}
}
function emitTypeReference(type: TypeReferenceNode) {
emitEntityName(type.typeName);
if (type.typeArguments) {

View file

@ -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);
}
}
}
}

File diff suppressed because it is too large Load diff

672
src/compiler/factory.ts Normal file
View 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());
}
}

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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;
}
}
}
}

View file

@ -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
View 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

File diff suppressed because it is too large Load diff

View 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);
}
}

File diff suppressed because it is too large Load diff

View 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 &nbsp;
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
};
}

View 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;
}
}
}

View 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 };
}
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -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);

View file

@ -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

View file

@ -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;
}
}

View file

@ -73,4 +73,4 @@ class TypeWriterWalker {
symbol: symbolString
});
}
}
}

View file

@ -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);
}

View file

@ -129,7 +129,6 @@ var CC = (function () {
}
return CC;
})();
var CC;
(function (CC) {
CC.bar = 1;
})(CC || (CC = {}));

View file

@ -156,7 +156,6 @@ var c = (function () {
}
return c;
})();
var c;
(function (c) {
c.bar = 1;
})(c || (c = {}));

View file

@ -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); } }

View file

@ -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); } }

View file

@ -3,5 +3,4 @@ var v = class C {};
//// [classExpressionES61.js]
var v = class C {
}
;
};

View file

@ -6,5 +6,4 @@ var v = class C extends D {};
class D {
}
var v = class C extends D {
}
;
};

View file

@ -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;

View file

@ -6,6 +6,5 @@ function* g() {
//// [generatorTypeCheck55.js]
function* g() {
var x = class C extends (yield) {
}
;
};
}

View file

@ -13,6 +13,5 @@ function* g() {
*[yield 0]() {
yield 0;
}
}
;
};
}

View file

@ -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
*/`);
});
});