Merge branch 'master' into refactor_findallrefs

This commit is contained in:
Andy Hanson
2017-03-01 08:45:41 -08:00
684 changed files with 21666 additions and 5595 deletions
+1
View File
@@ -57,3 +57,4 @@ internal/
!tests/cases/projects/NodeModulesSearch/**/*
!tests/baselines/reference/project/nodeModules*/**/*
.idea
yarn.lock
+1
View File
@@ -17,6 +17,7 @@ branches:
only:
- master
- release-2.1
- release-2.2
install:
- npm uninstall typescript
+17 -7
View File
@@ -21,10 +21,6 @@ declare module "gulp-typescript" {
import * as insert from "gulp-insert";
import * as sourcemaps from "gulp-sourcemaps";
import Q = require("q");
declare global {
// `del` further depends on `Promise` (and is also not included), so we just, patch the global scope's Promise to Q's (which we already include in our deps because gulp depends on it)
type Promise<T> = Q.Promise<T>;
}
import del = require("del");
import mkdirP = require("mkdirp");
import minimist = require("minimist");
@@ -41,7 +37,7 @@ const {runTestsInParallel} = mochaParallel;
Error.stackTraceLimit = 1000;
const cmdLineOptions = minimist(process.argv.slice(2), {
boolean: ["debug", "light", "colors", "lint", "soft"],
boolean: ["debug", "inspect", "light", "colors", "lint", "soft"],
string: ["browser", "tests", "host", "reporter", "stackTraceLimit"],
alias: {
b: "browser",
@@ -58,6 +54,7 @@ const cmdLineOptions = minimist(process.argv.slice(2), {
soft: false,
colors: process.env.colors || process.env.color || true,
debug: process.env.debug || process.env.d,
inspect: process.env.inspect,
host: process.env.TYPESCRIPT_HOST || process.env.host || "node",
browser: process.env.browser || process.env.b || "IE",
tests: process.env.test || process.env.tests || process.env.t,
@@ -139,6 +136,14 @@ const es2017LibrarySourceMap = es2017LibrarySource.map(function(source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
const esnextLibrarySource = [
"esnext.asynciterable.d.ts"
];
const esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
const hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
const librarySourceMap = [
@@ -153,11 +158,12 @@ const librarySourceMap = [
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },
// JavaScript + all host library
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);
const libraryTargets = librarySourceMap.map(function(f) {
return path.join(builtLocalDirectory, f.target);
@@ -589,6 +595,7 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
cleanTestDirs((err) => {
if (err) { console.error(err); failWithStatus(err, 1); }
const debug = cmdLineOptions["debug"];
const inspect = cmdLineOptions["inspect"];
const tests = cmdLineOptions["tests"];
const light = cmdLineOptions["light"];
const stackTraceLimit = cmdLineOptions["stackTraceLimit"];
@@ -625,7 +632,10 @@ function runConsoleTests(defaultReporter: string, runInParallel: boolean, done:
// default timeout is 2sec which really should be enough, but maybe we just need a small amount longer
if (!runInParallel) {
const args = [];
if (debug) {
if (inspect) {
args.push("--inspect");
}
if (inspect || debug) {
args.push("--debug-brk");
}
args.push("-R", reporter);
+49 -11
View File
@@ -15,6 +15,7 @@ var servicesDirectory = "src/services/";
var serverDirectory = "src/server/";
var typingsInstallerDirectory = "src/server/typingsInstaller";
var cancellationTokenDirectory = "src/server/cancellationToken";
var watchGuardDirectory = "src/server/watchGuard";
var harnessDirectory = "src/harness/";
var libraryDirectory = "src/lib/";
var scriptsDirectory = "scripts/";
@@ -80,6 +81,7 @@ var compilerSources = filesFromConfig("./src/compiler/tsconfig.json");
var servicesSources = filesFromConfig("./src/services/tsconfig.json");
var cancellationTokenSources = filesFromConfig(path.join(serverDirectory, "cancellationToken/tsconfig.json"));
var typingsInstallerSources = filesFromConfig(path.join(serverDirectory, "typingsInstaller/tsconfig.json"));
var watchGuardSources = filesFromConfig(path.join(serverDirectory, "watchGuard/tsconfig.json"));
var serverSources = filesFromConfig(path.join(serverDirectory, "tsconfig.json"))
var languageServiceLibrarySources = filesFromConfig(path.join(serverDirectory, "tsconfig.library.json"));
@@ -129,6 +131,8 @@ var harnessSources = harnessCoreSources.concat([
"matchFiles.ts",
"initializeTSConfig.ts",
"printer.ts",
"transform.ts",
"customTransforms.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
@@ -170,13 +174,21 @@ var es2016LibrarySourceMap = es2016LibrarySource.map(function (source) {
var es2017LibrarySource = [
"es2017.object.d.ts",
"es2017.sharedmemory.d.ts",
"es2017.string.d.ts",
"es2017.string.d.ts"
];
var es2017LibrarySourceMap = es2017LibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
var esnextLibrarySource = [
"esnext.asynciterable.d.ts"
];
var esnextLibrarySourceMap = esnextLibrarySource.map(function (source) {
return { target: "lib." + source, sources: ["header.d.ts", source] };
});
var hostsLibrarySources = ["dom.generated.d.ts", "webworker.importscripts.d.ts", "scripthost.d.ts"];
var librarySourceMap = [
@@ -191,11 +203,12 @@ var librarySourceMap = [
{ target: "lib.es2015.d.ts", sources: ["header.d.ts", "es2015.d.ts"] },
{ target: "lib.es2016.d.ts", sources: ["header.d.ts", "es2016.d.ts"] },
{ target: "lib.es2017.d.ts", sources: ["header.d.ts", "es2017.d.ts"] },
{ target: "lib.esnext.d.ts", sources: ["header.d.ts", "esnext.d.ts"] },
// JavaScript + all host library
{ target: "lib.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(hostsLibrarySources) },
{ target: "lib.es6.d.ts", sources: ["header.d.ts", "es5.d.ts"].concat(es2015LibrarySources, hostsLibrarySources, "dom.iterable.d.ts") }
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap);
].concat(es2015LibrarySourceMap, es2016LibrarySourceMap, es2017LibrarySourceMap, esnextLibrarySourceMap);
var libraryTargets = librarySourceMap.map(function (f) {
return path.join(builtLocalDirectory, f.target);
@@ -570,8 +583,11 @@ compileFile(cancellationTokenFile, cancellationTokenSources, [builtLocalDirector
var typingsInstallerFile = path.join(builtLocalDirectory, "typingsInstaller.js");
compileFile(typingsInstallerFile, typingsInstallerSources, [builtLocalDirectory].concat(typingsInstallerSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
var watchGuardFile = path.join(builtLocalDirectory, "watchGuard.js");
compileFile(watchGuardFile, watchGuardSources, [builtLocalDirectory].concat(watchGuardSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { outDir: builtLocalDirectory, noOutFile: false });
var serverFile = path.join(builtLocalDirectory, "tsserver.js");
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile].concat(serverSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true });
compileFile(serverFile, serverSources, [builtLocalDirectory, copyright, cancellationTokenFile, typingsInstallerFile, watchGuardFile].concat(serverSources).concat(servicesSources), /*prefixes*/ [copyright], /*useBuiltCompiler*/ true, { types: ["node"], preserveConstEnums: true });
var tsserverLibraryFile = path.join(builtLocalDirectory, "tsserverlibrary.js");
var tsserverLibraryDefinitionFile = path.join(builtLocalDirectory, "tsserverlibrary.d.ts");
compileFile(
@@ -665,7 +681,7 @@ task("generate-spec", [specMd]);
// Makes a new LKG. This target does not build anything, but errors if not all the outputs are present in the built/local directory
desc("Makes a new LKG out of the built js files");
task("LKG", ["clean", "release", "local"].concat(libraryTargets), function () {
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts].concat(libraryTargets);
var expectedFiles = [tscFile, servicesFile, serverFile, nodePackageFile, nodeDefinitionsFile, standaloneDefinitionsFile, tsserverLibraryFile, tsserverLibraryDefinitionFile, cancellationTokenFile, typingsInstallerFile, buildProtocolDts, watchGuardFile].concat(libraryTargets);
var missingFiles = expectedFiles.filter(function (f) {
return !fs.existsSync(f);
});
@@ -778,6 +794,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
}
var debug = process.env.debug || process.env.d;
var inspect = process.env.inspect;
tests = process.env.test || process.env.tests || process.env.t;
var light = process.env.light || false;
var stackTraceLimit = process.env.stackTraceLimit;
@@ -807,18 +824,39 @@ function runConsoleTests(defaultReporter, runInParallel) {
testTimeout = 800000;
}
colors = process.env.colors || process.env.color;
colors = colors ? ' --no-colors ' : ' --colors ';
reporter = process.env.reporter || process.env.r || defaultReporter;
var bail = (process.env.bail || process.env.b) ? "--bail" : "";
var colors = process.env.colors || process.env.color || true;
var reporter = process.env.reporter || process.env.r || defaultReporter;
var bail = process.env.bail || process.env.b;
var lintFlag = process.env.lint !== 'false';
// 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
if (!runInParallel) {
var startTime = mark();
tests = tests ? ' -g "' + tests + '"' : '';
var cmd = "mocha" + (debug ? " --debug-brk" : "") + " -R " + reporter + tests + colors + bail + ' -t ' + testTimeout + ' ' + run;
var args = [];
if (inspect) {
args.push("--inspect");
}
if (inspect || debug) {
args.push("--debug-brk");
}
args.push("-R", reporter);
if (tests) {
args.push("-g", `"${tests}"`);
}
if (colors) {
args.push("--colors");
}
else {
args.push("--no-colors");
}
if (bail) {
args.push("--bail");
}
args.push("-t", testTimeout);
args.push(run);
var cmd = "mocha " + args.join(" ");
console.log(cmd);
var savedNodeEnv = process.env.NODE_ENV;
@@ -839,7 +877,7 @@ function runConsoleTests(defaultReporter, runInParallel) {
var savedNodeEnv = process.env.NODE_ENV;
process.env.NODE_ENV = "development";
var startTime = mark();
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: colors === " --no-colors " }, function (err) {
runTestsInParallel(taskConfigsFolder, run, { testTimeout: testTimeout, noColors: !colors }, function (err) {
process.env.NODE_ENV = savedNodeEnv;
measure(startTime);
// last worker clean everything and runs linter in case if there were no errors
+1 -1
View File
@@ -60,7 +60,7 @@
"gulp-insert": "latest",
"gulp-newer": "latest",
"gulp-sourcemaps": "latest",
"gulp-typescript": "3.1.3",
"gulp-typescript": "3.1.5",
"into-stream": "latest",
"istanbul": "latest",
"jake": "latest",
+121 -30
View File
@@ -265,6 +265,7 @@ namespace ts {
return "export=";
case SpecialPropertyAssignmentKind.ExportsProperty:
case SpecialPropertyAssignmentKind.ThisProperty:
case SpecialPropertyAssignmentKind.Property:
// exports.x = ... or this.y = ...
return ((node as BinaryExpression).left as PropertyAccessExpression).name.text;
case SpecialPropertyAssignmentKind.PrototypeProperty:
@@ -669,6 +670,12 @@ namespace ts {
case SyntaxKind.CallExpression:
bindCallExpressionFlow(<CallExpression>node);
break;
case SyntaxKind.JSDocComment:
bindJSDocComment(<JSDoc>node);
break;
case SyntaxKind.JSDocTypedefTag:
bindJSDocTypedefTag(<JSDocTypedefTag>node);
break;
default:
bindEachChild(node);
break;
@@ -956,6 +963,9 @@ namespace ts {
const postLoopLabel = createBranchLabel();
addAntecedent(preLoopLabel, currentFlow);
currentFlow = preLoopLabel;
if (node.kind === SyntaxKind.ForOfStatement) {
bind(node.awaitModifier);
}
bind(node.expression);
addAntecedent(postLoopLabel, currentFlow);
bind(node.initializer);
@@ -1051,8 +1061,8 @@ namespace ts {
// second -> edge that represents post-finally flow.
// these edges are used in following scenario:
// let a; (1)
// try { a = someOperation(); (2)}
// finally { (3) console.log(a) } (4)
// try { a = someOperation(); (2)}
// finally { (3) console.log(a) } (4)
// (5) a
// flow graph for this case looks roughly like this (arrows show ):
@@ -1064,11 +1074,11 @@ namespace ts {
// In case when we walk the flow starting from inside the finally block we want to take edge '*****' into account
// since it ensures that finally is always reachable. However when we start outside the finally block and go through label (5)
// then edge '*****' should be discarded because label 4 is only reachable if post-finally label-4 is reachable
// Simply speaking code inside finally block is treated as reachable as pre-try-flow
// Simply speaking code inside finally block is treated as reachable as pre-try-flow
// since we conservatively assume that any line in try block can throw or return in which case we'll enter finally.
// However code after finally is reachable only if control flow was not abrupted in try/catch or finally blocks - it should be composed from
// final flows of these blocks without taking pre-try flow into account.
//
//
// extra edges that we inject allows to control this behavior
// if when walking the flow we step on post-finally edge - we can mark matching pre-finally edge as locked so it will be skipped.
const preFinallyFlow: PreFinallyFlow = { flags: FlowFlags.PreFinally, antecedent: preTryFlow, lock: {} };
@@ -1331,6 +1341,26 @@ namespace ts {
}
}
function bindJSDocComment(node: JSDoc) {
forEachChild(node, n => {
if (n.kind !== SyntaxKind.JSDocTypedefTag) {
bind(n);
}
});
}
function bindJSDocTypedefTag(node: JSDocTypedefTag) {
forEachChild(node, n => {
// if the node has a fullName "A.B.C", that means symbol "C" was already bound
// when we visit "fullName"; so when we visit the name "C" as the next child of
// the jsDocTypedefTag, we should skip binding it.
if (node.fullName && n === node.name && node.fullName.kind !== SyntaxKind.Identifier) {
return;
}
bind(n);
});
}
function bindCallExpressionFlow(node: CallExpression) {
// If the target of the call expression is a function expression or arrow function we have
// an immediately invoked function expression (IIFE). Initialize the flowNode property to
@@ -1870,6 +1900,18 @@ namespace ts {
}
node.parent = parent;
const saveInStrictMode = inStrictMode;
// Even though in the AST the jsdoc @typedef node belongs to the current node,
// its symbol might be in the same scope with the current node's symbol. Consider:
//
// /** @typedef {string | number} MyType */
// function foo();
//
// Here the current node is "foo", which is a container, but the scope of "MyType" should
// not be inside "foo". Therefore we always bind @typedef before bind the parent node,
// and skip binding this tag later when binding all the other jsdoc tags.
bindJSDocTypedefTagIfAny(node);
// First we bind declaration nodes to a symbol if possible. We'll both create a symbol
// and then potentially add the symbol to an appropriate symbol table. Possible
// destination symbol tables are:
@@ -1904,6 +1946,27 @@ namespace ts {
inStrictMode = saveInStrictMode;
}
function bindJSDocTypedefTagIfAny(node: Node) {
if (!node.jsDoc) {
return;
}
for (const jsDoc of node.jsDoc) {
if (!jsDoc.tags) {
continue;
}
for (const tag of jsDoc.tags) {
if (tag.kind === SyntaxKind.JSDocTypedefTag) {
const savedParent = parent;
parent = jsDoc;
bind(tag);
parent = savedParent;
}
}
}
}
function updateStrictModeStatementList(statements: NodeArray<Statement>) {
if (!inStrictMode) {
for (const statement of statements) {
@@ -1969,6 +2032,9 @@ namespace ts {
case SpecialPropertyAssignmentKind.ThisProperty:
bindThisPropertyAssignment(<BinaryExpression>node);
break;
case SpecialPropertyAssignmentKind.Property:
bindStaticPropertyAssignment(<BinaryExpression>node);
break;
case SpecialPropertyAssignmentKind.None:
// Nothing to do
break;
@@ -2265,18 +2331,41 @@ namespace ts {
constructorFunction.parent = classPrototype;
classPrototype.parent = leftSideOfAssignment;
const funcSymbol = container.locals.get(constructorFunction.text);
if (!funcSymbol || !(funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
bindPropertyAssignment(constructorFunction.text, leftSideOfAssignment, /*isPrototypeProperty*/ true);
}
function bindStaticPropertyAssignment(node: BinaryExpression) {
// We saw a node of the form 'x.y = z'. Declare a 'member' y on x if x was a function.
// Look up the function in the local scope, since prototype assignments should
// follow the function declaration
const leftSideOfAssignment = node.left as PropertyAccessExpression;
const target = leftSideOfAssignment.expression as Identifier;
// Fix up parent pointers since we're going to use these nodes before we bind into them
leftSideOfAssignment.parent = node;
target.parent = leftSideOfAssignment;
bindPropertyAssignment(target.text, leftSideOfAssignment, /*isPrototypeProperty*/ false);
}
function bindPropertyAssignment(functionName: string, propertyAccessExpression: PropertyAccessExpression, isPrototypeProperty: boolean) {
let targetSymbol = container.locals.get(functionName);
if (targetSymbol && isDeclarationOfFunctionOrClassExpression(targetSymbol)) {
targetSymbol = (targetSymbol.valueDeclaration as VariableDeclaration).initializer.symbol;
}
if (!targetSymbol || !(targetSymbol.flags & (SymbolFlags.Function | SymbolFlags.Class))) {
return;
}
// Set up the members collection if it doesn't exist already
if (!funcSymbol.members) {
funcSymbol.members = createMap<Symbol>();
}
const symbolTable = isPrototypeProperty ?
(targetSymbol.members || (targetSymbol.members = createMap<Symbol>())) :
(targetSymbol.exports || (targetSymbol.exports = createMap<Symbol>()));
// Declare the method/property
declareSymbol(funcSymbol.members, funcSymbol, leftSideOfAssignment, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
declareSymbol(symbolTable, targetSymbol, propertyAccessExpression, SymbolFlags.Property, SymbolFlags.PropertyExcludes);
}
function bindCallExpression(node: CallExpression) {
@@ -2380,7 +2469,7 @@ namespace ts {
function bindFunctionDeclaration(node: FunctionDeclaration) {
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
if (isAsyncFunctionLike(node)) {
if (isAsyncFunction(node)) {
emitFlags |= NodeFlags.HasAsyncFunctions;
}
}
@@ -2397,7 +2486,7 @@ namespace ts {
function bindFunctionExpression(node: FunctionExpression) {
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
if (isAsyncFunctionLike(node)) {
if (isAsyncFunction(node)) {
emitFlags |= NodeFlags.HasAsyncFunctions;
}
}
@@ -2411,7 +2500,7 @@ namespace ts {
function bindPropertyOrMethodOrAccessor(node: Declaration, symbolFlags: SymbolFlags, symbolExcludes: SymbolFlags) {
if (!isDeclarationFile(file) && !isInAmbientContext(node)) {
if (isAsyncFunctionLike(node)) {
if (isAsyncFunction(node)) {
emitFlags |= NodeFlags.HasAsyncFunctions;
}
}
@@ -2845,11 +2934,10 @@ namespace ts {
// An async method declaration is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
}
// Currently, we only support generators that were originally async function bodies.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken) {
transformFlags |= TransformFlags.AssertGenerator;
}
@@ -2915,7 +3003,7 @@ namespace ts {
// An async function declaration is ES2017 syntax.
if (modifierFlags & ModifierFlags.Async) {
transformFlags |= TransformFlags.AssertES2017;
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
}
// function declarations with object rest destructuring are ES Next syntax
@@ -2935,7 +3023,7 @@ namespace ts {
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken) {
transformFlags |= TransformFlags.AssertGenerator;
}
}
@@ -2957,7 +3045,7 @@ namespace ts {
// An async function expression is ES2017 syntax.
if (hasModifier(node, ModifierFlags.Async)) {
transformFlags |= TransformFlags.AssertES2017;
transformFlags |= node.asteriskToken ? TransformFlags.AssertESNext : TransformFlags.AssertES2017;
}
// function expressions with object rest destructuring are ES Next syntax
@@ -2976,9 +3064,7 @@ namespace ts {
// If a FunctionExpression is generator function and is the body of a
// transformed async function, then this node can be transformed to a
// down-level generator.
// Currently we do not support transforming any other generator fucntions
// down level.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken) {
transformFlags |= TransformFlags.AssertGenerator;
}
@@ -3146,8 +3232,8 @@ namespace ts {
switch (kind) {
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitExpression:
// async/await is ES2017 syntax
transformFlags |= TransformFlags.AssertES2017;
// async/await is ES2017 syntax, but may be ESNext syntax (for async generators)
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2017;
break;
case SyntaxKind.PublicKeyword:
@@ -3179,10 +3265,6 @@ namespace ts {
transformFlags |= TransformFlags.AssertJsx;
break;
case SyntaxKind.ForOfStatement:
// for-of might be ESNext if it has a rest destructuring
transformFlags |= TransformFlags.AssertESNext;
// FALLTHROUGH
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateHead:
case SyntaxKind.TemplateMiddle:
@@ -3196,9 +3278,18 @@ namespace ts {
transformFlags |= TransformFlags.AssertES2015;
break;
case SyntaxKind.ForOfStatement:
// This node is either ES2015 syntax or ES2017 syntax (if it is a for-await-of).
if ((<ForOfStatement>node).awaitModifier) {
transformFlags |= TransformFlags.AssertESNext;
}
transformFlags |= TransformFlags.AssertES2015;
break;
case SyntaxKind.YieldExpression:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
// This node is either ES2015 syntax (in a generator) or ES2017 syntax (in an async
// generator).
transformFlags |= TransformFlags.AssertESNext | TransformFlags.AssertES2015 | TransformFlags.ContainsYield;
break;
case SyntaxKind.AnyKeyword:
+859 -599
View File
File diff suppressed because it is too large Load Diff
+7
View File
@@ -333,6 +333,11 @@ namespace ts {
type: "boolean",
description: Diagnostics.Disallow_inconsistently_cased_references_to_the_same_file
},
{
name: "downlevelIteration",
type: "boolean",
description: Diagnostics.Use_full_down_level_iteration_for_iterables_and_arrays_for_for_of_spread_and_destructuring_in_ES5_Slash3
},
{
name: "baseUrl",
type: "string",
@@ -418,6 +423,7 @@ namespace ts {
"es7": "lib.es2016.d.ts",
"es2016": "lib.es2016.d.ts",
"es2017": "lib.es2017.d.ts",
"esnext": "lib.esnext.d.ts",
// Host only
"dom": "lib.dom.d.ts",
"dom.iterable": "lib.dom.iterable.d.ts",
@@ -437,6 +443,7 @@ namespace ts {
"es2017.object": "lib.es2017.object.d.ts",
"es2017.sharedmemory": "lib.es2017.sharedmemory.d.ts",
"es2017.string": "lib.es2017.string.d.ts",
"esnext.asynciterable": "lib.esnext.asynciterable.d.ts",
}),
},
description: Diagnostics.Specify_library_files_to_be_included_in_the_compilation_Colon
+85 -20
View File
@@ -43,18 +43,14 @@ namespace ts {
}
if (node) {
const { pos, end } = getCommentRange(node);
const emitFlags = getEmitFlags(node);
hasWrittenComment = false;
const emitNode = node.emitNode;
const emitFlags = emitNode && emitNode.flags;
const { pos, end } = emitNode && emitNode.commentRange || node;
if ((pos < 0 && end < 0) || (pos === end)) {
// Both pos and end are synthesized, so just emit the node without comments.
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(hint, node);
}
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
}
else {
if (extendedDiagnostics) {
@@ -94,17 +90,10 @@ namespace ts {
performance.measure("commentTime", "preEmitNodeWithComment");
}
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(hint, node);
}
emitNodeWithSynthesizedComments(hint, node, emitNode, emitFlags, emitCallback);
if (extendedDiagnostics) {
performance.mark("beginEmitNodeWithComment");
performance.mark("postEmitNodeWithComment");
}
// Restore previous container state.
@@ -119,12 +108,88 @@ namespace ts {
}
if (extendedDiagnostics) {
performance.measure("commentTime", "beginEmitNodeWithComment");
performance.measure("commentTime", "postEmitNodeWithComment");
}
}
}
}
function emitNodeWithSynthesizedComments(hint: EmitHint, node: Node, emitNode: EmitNode, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
const leadingComments = emitNode && emitNode.leadingComments;
if (some(leadingComments)) {
if (extendedDiagnostics) {
performance.mark("preEmitNodeWithSynthesizedComments");
}
forEach(leadingComments, emitLeadingSynthesizedComment);
if (extendedDiagnostics) {
performance.measure("commentTime", "preEmitNodeWithSynthesizedComments");
}
}
emitNodeWithNestedComments(hint, node, emitFlags, emitCallback);
const trailingComments = emitNode && emitNode.trailingComments;
if (some(trailingComments)) {
if (extendedDiagnostics) {
performance.mark("postEmitNodeWithSynthesizedComments");
}
forEach(trailingComments, emitTrailingSynthesizedComment);
if (extendedDiagnostics) {
performance.measure("commentTime", "postEmitNodeWithSynthesizedComments");
}
}
}
function emitLeadingSynthesizedComment(comment: SynthesizedComment) {
if (comment.kind === SyntaxKind.SingleLineCommentTrivia) {
writer.writeLine();
}
writeSynthesizedComment(comment);
if (comment.hasTrailingNewLine || comment.kind === SyntaxKind.SingleLineCommentTrivia) {
writer.writeLine();
}
else {
writer.write(" ");
}
}
function emitTrailingSynthesizedComment(comment: SynthesizedComment) {
if (!writer.isAtStartOfLine()) {
writer.write(" ");
}
writeSynthesizedComment(comment);
if (comment.hasTrailingNewLine) {
writer.writeLine();
}
}
function writeSynthesizedComment(comment: SynthesizedComment) {
const text = formatSynthesizedComment(comment);
const lineMap = comment.kind === SyntaxKind.MultiLineCommentTrivia ? computeLineStarts(text) : undefined;
writeCommentRange(text, lineMap, writer, 0, text.length, newLine);
}
function formatSynthesizedComment(comment: SynthesizedComment) {
return comment.kind === SyntaxKind.MultiLineCommentTrivia
? `/*${comment.text}*/`
: `//${comment.text}`;
}
function emitNodeWithNestedComments(hint: EmitHint, node: Node, emitFlags: EmitFlags, emitCallback: (hint: EmitHint, node: Node) => void) {
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(hint, node);
}
}
function emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void) {
if (extendedDiagnostics) {
performance.mark("preEmitBodyWithDetachedComments");
+101 -65
View File
@@ -175,15 +175,15 @@
"category": "Error",
"code": 1057
},
"Operand for 'await' does not have a valid callable 'then' member.": {
"Type used as operand to 'await' or the return type of an async function must either be a valid promise or must not contain a callable 'then' member.": {
"category": "Error",
"code": 1058
},
"Return expression in async function does not have a valid callable 'then' member.": {
"A promise must have a 'then' method.": {
"category": "Error",
"code": 1059
},
"Expression body for async arrow function does not have a valid callable 'then' member.": {
"The first parameter of the 'then' method of a promise must be a callback.": {
"category": "Error",
"code": 1060
},
@@ -191,7 +191,7 @@
"category": "Error",
"code": 1061
},
"{0} is referenced directly or indirectly in the fulfillment callback of its own 'then' method.": {
"Type is referenced directly or indirectly in the fulfillment callback of its own 'then' method.": {
"category": "Error",
"code": 1062
},
@@ -291,6 +291,10 @@
"category": "Error",
"code": 1102
},
"A 'for-await-of' statement is only allowed within an async function or async generator.": {
"category": "Error",
"code": 1103
},
"A 'continue' statement can only be used within an enclosing iteration statement.": {
"category": "Error",
"code": 1104
@@ -319,7 +323,7 @@
"category": "Error",
"code": 1113
},
"Duplicate label '{0}'": {
"Duplicate label '{0}'.": {
"category": "Error",
"code": 1114
},
@@ -447,7 +451,7 @@
"category": "Error",
"code": 1148
},
"File name '{0}' differs from already included file name '{1}' only in casing": {
"File name '{0}' differs from already included file name '{1}' only in casing.": {
"category": "Error",
"code": 1149
},
@@ -455,7 +459,7 @@
"category": "Error",
"code": 1150
},
"'const' declarations must be initialized": {
"'const' declarations must be initialized.": {
"category": "Error",
"code": 1155
},
@@ -651,11 +655,11 @@
"category": "Error",
"code": 1210
},
"A class declaration without the 'default' modifier must have a name": {
"A class declaration without the 'default' modifier must have a name.": {
"category": "Error",
"code": 1211
},
"Identifier expected. '{0}' is a reserved word in strict mode": {
"Identifier expected. '{0}' is a reserved word in strict mode.": {
"category": "Error",
"code": 1212
},
@@ -1107,7 +1111,7 @@
"category": "Error",
"code": 2360
},
"The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter": {
"The right-hand side of an 'in' expression must be of type 'any', an object type or a type parameter.": {
"category": "Error",
"code": 2361
},
@@ -1131,7 +1135,7 @@
"category": "Error",
"code": 2366
},
"Type parameter name cannot be '{0}'": {
"Type parameter name cannot be '{0}'.": {
"category": "Error",
"code": 2368
},
@@ -1291,7 +1295,7 @@
"category": "Error",
"code": 2408
},
"Return type of constructor signature must be assignable to the instance type of the class": {
"Return type of constructor signature must be assignable to the instance type of the class.": {
"category": "Error",
"code": 2409
},
@@ -1311,7 +1315,7 @@
"category": "Error",
"code": 2413
},
"Class name cannot be '{0}'": {
"Class name cannot be '{0}'.": {
"category": "Error",
"code": 2414
},
@@ -1347,7 +1351,7 @@
"category": "Error",
"code": 2426
},
"Interface name cannot be '{0}'": {
"Interface name cannot be '{0}'.": {
"category": "Error",
"code": 2427
},
@@ -1359,7 +1363,7 @@
"category": "Error",
"code": 2430
},
"Enum name cannot be '{0}'": {
"Enum name cannot be '{0}'.": {
"category": "Error",
"code": 2431
},
@@ -1367,11 +1371,11 @@
"category": "Error",
"code": 2432
},
"A namespace declaration cannot be in a different file from a class or function with which it is merged": {
"A namespace declaration cannot be in a different file from a class or function with which it is merged.": {
"category": "Error",
"code": 2433
},
"A namespace declaration cannot be located prior to a class or function with which it is merged": {
"A namespace declaration cannot be located prior to a class or function with which it is merged.": {
"category": "Error",
"code": 2434
},
@@ -1383,11 +1387,11 @@
"category": "Error",
"code": 2436
},
"Module '{0}' is hidden by a local declaration with the same name": {
"Module '{0}' is hidden by a local declaration with the same name.": {
"category": "Error",
"code": 2437
},
"Import name cannot be '{0}'": {
"Import name cannot be '{0}'.": {
"category": "Error",
"code": 2438
},
@@ -1395,7 +1399,7 @@
"category": "Error",
"code": 2439
},
"Import declaration conflicts with local declaration of '{0}'": {
"Import declaration conflicts with local declaration of '{0}'.": {
"category": "Error",
"code": 2440
},
@@ -1455,7 +1459,7 @@
"category": "Error",
"code": 2456
},
"Type alias name cannot be '{0}'": {
"Type alias name cannot be '{0}'.": {
"category": "Error",
"code": 2457
},
@@ -1475,7 +1479,7 @@
"category": "Error",
"code": 2461
},
"A rest element must be last in a destructuring pattern": {
"A rest element must be last in a destructuring pattern.": {
"category": "Error",
"code": 2462
},
@@ -1559,7 +1563,7 @@
"category": "Error",
"code": 2483
},
"Export declaration conflicts with exported declaration of '{0}'": {
"Export declaration conflicts with exported declaration of '{0}'.": {
"category": "Error",
"code": 2484
},
@@ -1583,7 +1587,7 @@
"category": "Error",
"code": 2491
},
"Cannot redeclare identifier '{0}' in catch clause": {
"Cannot redeclare identifier '{0}' in catch clause.": {
"category": "Error",
"code": 2492
},
@@ -1631,6 +1635,10 @@
"category": "Error",
"code": 2503
},
"Type must have a '[Symbol.asyncIterator]()' method that returns an async iterator.": {
"category": "Error",
"code": 2504
},
"A generator cannot have a 'void' type annotation.": {
"category": "Error",
"code": 2505
@@ -1687,6 +1695,10 @@
"category": "Error",
"code": 2518
},
"An async iterator must have a 'next()' method.": {
"category": "Error",
"code": 2519
},
"Duplicate identifier '{0}'. Compiler uses declaration '{1}' to support async functions.": {
"category": "Error",
"code": 2520
@@ -1795,6 +1807,18 @@
"category": "Error",
"code": 2546
},
"The type returned by the 'next()' method of an async iterator must be a promise for a type with a 'value' property.": {
"category": "Error",
"code": 2547
},
"Type '{0}' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator.": {
"category": "Error",
"code": 2548
},
"Type '{0}' is not an array type or a string type or does not have a '[Symbol.iterator]()' method that returns an iterator.": {
"category": "Error",
"code": 2549
},
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
@@ -1807,7 +1831,7 @@
"category": "Error",
"code": 2602
},
"Property '{0}' in type '{1}' is not assignable to type '{2}'": {
"Property '{0}' in type '{1}' is not assignable to type '{2}'.": {
"category": "Error",
"code": 2603
},
@@ -1823,11 +1847,11 @@
"category": "Error",
"code": 2606
},
"JSX element class does not support attributes because it does not have a '{0}' property": {
"JSX element class does not support attributes because it does not have a '{0}' property.": {
"category": "Error",
"code": 2607
},
"The global type 'JSX.{0}' may not have more than one property": {
"The global type 'JSX.{0}' may not have more than one property.": {
"category": "Error",
"code": 2608
},
@@ -1839,7 +1863,7 @@
"category": "Error",
"code": 2649
},
"Cannot emit namespaced JSX elements in React": {
"Cannot emit namespaced JSX elements in React.": {
"category": "Error",
"code": 2650
},
@@ -1863,11 +1887,11 @@
"category": "Error",
"code": 2656
},
"JSX expressions must have one parent element": {
"JSX expressions must have one parent element.": {
"category": "Error",
"code": 2657
},
"Type '{0}' provides no match for the signature '{1}'": {
"Type '{0}' provides no match for the signature '{1}'.": {
"category": "Error",
"code": 2658
},
@@ -2047,11 +2071,11 @@
"category": "Error",
"code": 2702
},
"The operand of a delete operator must be a property reference": {
"The operand of a delete operator must be a property reference.": {
"category": "Error",
"code": 2703
},
"The operand of a delete operator cannot be a read-only property": {
"The operand of a delete operator cannot be a read-only property.": {
"category": "Error",
"code": 2704
},
@@ -2385,7 +2409,7 @@
"category": "Error",
"code": 5011
},
"Cannot read file '{0}': {1}": {
"Cannot read file '{0}': {1}.": {
"category": "Error",
"code": 5012
},
@@ -2405,7 +2429,7 @@
"category": "Error",
"code": 5024
},
"Could not write file '{0}': {1}": {
"Could not write file '{0}': {1}.": {
"category": "Error",
"code": 5033
},
@@ -2441,11 +2465,11 @@
"category": "Error",
"code": 5056
},
"Cannot find a tsconfig.json file at the specified directory: '{0}'": {
"Cannot find a tsconfig.json file at the specified directory: '{0}'.": {
"category": "Error",
"code": 5057
},
"The specified path does not exist: '{0}'": {
"The specified path does not exist: '{0}'.": {
"category": "Error",
"code": 5058
},
@@ -2457,11 +2481,11 @@
"category": "Error",
"code": 5060
},
"Pattern '{0}' can have at most one '*' character": {
"Pattern '{0}' can have at most one '*' character.": {
"category": "Error",
"code": 5061
},
"Substitution '{0}' in pattern '{1}' in can have at most one '*' character": {
"Substitution '{0}' in pattern '{1}' in can have at most one '*' character.": {
"category": "Error",
"code": 5062
},
@@ -2533,11 +2557,11 @@
"category": "Message",
"code": 6012
},
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'": {
"Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'.": {
"category": "Message",
"code": 6015
},
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'": {
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
"category": "Message",
"code": 6016
},
@@ -2549,7 +2573,7 @@
"category": "Message",
"code": 6019
},
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'": {
"Compile the project given the path to its configuration file, or to a folder with a 'tsconfig.json'.": {
"category": "Message",
"code": 6020
},
@@ -2629,7 +2653,7 @@
"category": "Error",
"code": 6045
},
"Argument for '{0}' option must be: {1}": {
"Argument for '{0}' option must be: {1}.": {
"category": "Error",
"code": 6046
},
@@ -2717,7 +2741,7 @@
"category": "Message",
"code": 6072
},
"Stylize errors and messages using color and context. (experimental)": {
"Stylize errors and messages using color and context (experimental).": {
"category": "Message",
"code": 6073
},
@@ -2745,7 +2769,7 @@
"category": "Message",
"code": 6079
},
"Specify JSX code generation: 'preserve', 'react-native', or 'react'": {
"Specify JSX code generation: 'preserve', 'react-native', or 'react'.": {
"category": "Message",
"code": 6080
},
@@ -2761,7 +2785,7 @@
"category": "Message",
"code": 6083
},
"Specify the object invoked for createElement and __spread when targeting 'react' JSX emit": {
"Specify the object invoked for createElement and __spread when targeting 'react' JSX emit.": {
"category": "Message",
"code": 6084
},
@@ -2849,27 +2873,27 @@
"category": "Message",
"code": 6105
},
"'baseUrl' option is set to '{0}', using this value to resolve non-relative module name '{1}'": {
"'baseUrl' option is set to '{0}', using this value to resolve non-relative module name '{1}'.": {
"category": "Message",
"code": 6106
},
"'rootDirs' option is set, using it to resolve relative module name '{0}'": {
"'rootDirs' option is set, using it to resolve relative module name '{0}'.": {
"category": "Message",
"code": 6107
},
"Longest matching prefix for '{0}' is '{1}'": {
"Longest matching prefix for '{0}' is '{1}'.": {
"category": "Message",
"code": 6108
},
"Loading '{0}' from the root dir '{1}', candidate location '{2}'": {
"Loading '{0}' from the root dir '{1}', candidate location '{2}'.": {
"category": "Message",
"code": 6109
},
"Trying other entries in 'rootDirs'": {
"Trying other entries in 'rootDirs'.": {
"category": "Message",
"code": 6110
},
"Module resolution using 'rootDirs' has failed": {
"Module resolution using 'rootDirs' has failed.": {
"category": "Message",
"code": 6111
},
@@ -2909,7 +2933,7 @@
"category": "Message",
"code": 6120
},
"Resolving with primary search path '{0}'": {
"Resolving with primary search path '{0}'.": {
"category": "Message",
"code": 6121
},
@@ -2925,7 +2949,7 @@
"category": "Message",
"code": 6124
},
"Looking up in 'node_modules' folder, initial location '{0}'": {
"Looking up in 'node_modules' folder, initial location '{0}'.": {
"category": "Message",
"code": 6125
},
@@ -2945,7 +2969,7 @@
"category": "Error",
"code": 6129
},
"Resolving real path for '{0}', result '{1}'": {
"Resolving real path for '{0}', result '{1}'.": {
"category": "Message",
"code": 6130
},
@@ -2953,7 +2977,7 @@
"category": "Error",
"code": 6131
},
"File name '{0}' has a '{1}' extension - stripping it": {
"File name '{0}' has a '{1}' extension - stripping it.": {
"category": "Message",
"code": 6132
},
@@ -2969,7 +2993,7 @@
"category": "Message",
"code": 6135
},
"The maximum dependency depth to search under node_modules and load JavaScript files": {
"The maximum dependency depth to search under node_modules and load JavaScript files.": {
"category": "Message",
"code": 6136
},
@@ -2985,7 +3009,7 @@
"category": "Error",
"code": 6140
},
"Parse in strict mode and emit \"use strict\" for each source file": {
"Parse in strict mode and emit \"use strict\" for each source file.": {
"category": "Message",
"code": 6141
},
@@ -3017,6 +3041,10 @@
"category": "Message",
"code": 6148
},
"Use full down-level iteration for iterables and arrays for 'for-of', spread, and destructuring in ES5/3.": {
"category": "Message",
"code": 6149
},
"Variable '{0}' implicitly has an '{1}' type.": {
"category": "Error",
"code": 7005
@@ -3085,7 +3113,7 @@
"category": "Error",
"code": 7025
},
"JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists": {
"JSX element implicitly has type 'any' because no interface 'JSX.{0}' exists.": {
"category": "Error",
"code": 7026
},
@@ -3213,7 +3241,7 @@
"category": "Error",
"code": 17004
},
"A constructor cannot contain a 'super' call when its class extends 'null'": {
"A constructor cannot contain a 'super' call when its class extends 'null'.": {
"category": "Error",
"code": 17005
},
@@ -3241,7 +3269,7 @@
"category": "Error",
"code": 17011
},
"'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{0}'?": {
"'{0}' is not a valid meta-property for keyword '{1}'. Did you mean '{2}'?": {
"category": "Error",
"code": 17012
},
@@ -3279,7 +3307,7 @@
"category": "Message",
"code": 90003
},
"Remove declaration for: {0}": {
"Remove declaration for: '{0}'.": {
"category": "Message",
"code": 90004
},
@@ -3295,7 +3323,7 @@
"category": "Message",
"code": 90008
},
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig": {
"Adding a tsconfig.json file will help organize projects that contain both TypeScript and JavaScript files. Learn more at https://aka.ms/tsconfig.": {
"category": "Error",
"code": 90009
},
@@ -3303,18 +3331,26 @@
"category": "Error",
"code": 90010
},
"Import {0} from {1}": {
"Import {0} from {1}.": {
"category": "Message",
"code": 90013
},
"Change {0} to {1}": {
"Change {0} to {1}.": {
"category": "Message",
"code": 90014
},
"Add {0} to existing import declaration from {1}": {
"Add {0} to existing import declaration from {1}.": {
"category": "Message",
"code": 90015
},
"Add declaration for missing property '{0}'.": {
"category": "Message",
"code": 90016
},
"Add index signature for missing property '{0}'.": {
"category": "Message",
"code": 90017
},
"Octal literal types must use ES2015 syntax. Use the syntax '{0}'.": {
"category": "Error",
"code": 8017
+16 -26
View File
@@ -10,14 +10,13 @@ namespace ts {
/*@internal*/
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean): EmitResult {
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile, emitOnlyDtsFiles?: boolean, transformers?: TransformerFactory<SourceFile>[]): EmitResult {
const compilerOptions = host.getCompilerOptions();
const moduleKind = getEmitModuleKind(compilerOptions);
const sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap || compilerOptions.inlineSourceMap ? [] : undefined;
const emittedFilesList: string[] = compilerOptions.listEmittedFiles ? [] : undefined;
const emitterDiagnostics = createDiagnosticCollection();
const newLine = host.getNewLine();
const transformers = emitOnlyDtsFiles ? [] : getTransformers(compilerOptions);
const writer = createTextWriter(newLine);
const sourceMap = createSourceMapWriter(host, writer);
@@ -29,7 +28,7 @@ namespace ts {
const sourceFiles = getSourceFilesToEmit(host, targetSourceFile);
// Transform the source files
const transform = transformFiles(resolver, host, sourceFiles, transformers);
const transform = transformNodes(resolver, host, compilerOptions, sourceFiles, transformers, /*allowDtsFiles*/ false);
// Create a printer to print the nodes
const printer = createPrinter(compilerOptions, {
@@ -38,7 +37,7 @@ namespace ts {
// transform hooks
onEmitNode: transform.emitNodeWithNotification,
onSubstituteNode: transform.emitNodeWithSubstitution,
substituteNode: transform.substituteNode,
// sourcemap hooks
onEmitSourceMapOfNode: sourceMap.emitNodeWithSourceMap,
@@ -56,9 +55,7 @@ namespace ts {
performance.measure("printTime", "beforePrint");
// Clean up emit nodes on parse tree
for (const sourceFile of sourceFiles) {
disposeEmitNodes(sourceFile);
}
transform.dispose();
return {
emitSkipped,
@@ -201,7 +198,7 @@ namespace ts {
onEmitNode,
onEmitHelpers,
onSetSourceFile,
onSubstituteNode,
substituteNode,
} = handlers;
const newLine = getNewLineCharacter(printerOptions);
@@ -331,8 +328,8 @@ namespace ts {
setWriter(/*output*/ undefined);
}
function emit(node: Node, hint = EmitHint.Unspecified) {
pipelineEmitWithNotification(hint, node);
function emit(node: Node) {
pipelineEmitWithNotification(EmitHint.Unspecified, node);
}
function emitIdentifierName(node: Identifier) {
@@ -353,6 +350,7 @@ namespace ts {
}
function pipelineEmitWithComments(hint: EmitHint, node: Node) {
node = trySubstituteNode(hint, node);
if (emitNodeWithComments && hint !== EmitHint.SourceFile) {
emitNodeWithComments(hint, node, pipelineEmitWithSourceMap);
}
@@ -363,16 +361,7 @@ namespace ts {
function pipelineEmitWithSourceMap(hint: EmitHint, node: Node) {
if (onEmitSourceMapOfNode && hint !== EmitHint.SourceFile && hint !== EmitHint.IdentifierName) {
onEmitSourceMapOfNode(hint, node, pipelineEmitWithSubstitution);
}
else {
pipelineEmitWithSubstitution(hint, node);
}
}
function pipelineEmitWithSubstitution(hint: EmitHint, node: Node) {
if (onSubstituteNode) {
onSubstituteNode(hint, node, pipelineEmitWithHint);
onEmitSourceMapOfNode(hint, node, pipelineEmitWithHint);
}
else {
pipelineEmitWithHint(hint, node);
@@ -640,7 +629,7 @@ namespace ts {
// If the node is an expression, try to emit it as an expression with
// substitution.
if (isExpression(node)) {
return pipelineEmitWithSubstitution(EmitHint.Expression, node);
return pipelineEmitExpression(trySubstituteNode(EmitHint.Expression, node));
}
}
@@ -737,6 +726,10 @@ namespace ts {
}
}
function trySubstituteNode(hint: EmitHint, node: Node) {
return node && substituteNode && substituteNode(hint, node) || node;
}
function emitBodyIndirect(node: Node, elements: NodeArray<Node>, emitCallback: (node: Node) => void): void {
if (emitBodyWithDetachedComments) {
emitBodyWithDetachedComments(node, elements, emitCallback);
@@ -759,9 +752,6 @@ namespace ts {
// SyntaxKind.NumericLiteral
function emitNumericLiteral(node: NumericLiteral) {
emitLiteral(node);
if (node.trailingComment) {
write(` /*${node.trailingComment}*/`);
}
}
// SyntaxKind.StringLiteral
@@ -1450,6 +1440,7 @@ namespace ts {
function emitForOfStatement(node: ForOfStatement) {
const openParenPos = writeToken(SyntaxKind.ForKeyword, node.pos);
write(" ");
emitWithSuffix(node.awaitModifier, " ");
writeToken(SyntaxKind.OpenParenToken, openParenPos);
emitForBinding(node.initializer);
write(" of ");
@@ -1762,7 +1753,6 @@ namespace ts {
else {
pushNameGenerationScope();
write("{");
increaseIndent();
emitBlockStatements(node);
write("}");
popNameGenerationScope();
@@ -2915,4 +2905,4 @@ namespace ts {
Parameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | Parenthesis,
IndexSignatureParameters = CommaDelimited | SpaceBetweenSiblings | SingleLine | Indented | SquareBrackets,
}
}
}
+264 -90
View File
@@ -215,7 +215,7 @@ namespace ts {
// Signature elements
export function createParameter(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) {
export function createParameter(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: string | BindingName, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression) {
const node = <ParameterDeclaration>createSynthesizedNode(SyntaxKind.Parameter);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -227,7 +227,7 @@ namespace ts {
return node;
}
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: BindingName, type: TypeNode, initializer: Expression) {
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, dotDotDotToken: DotDotDotToken | undefined, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.dotDotDotToken !== dotDotDotToken
@@ -252,7 +252,7 @@ namespace ts {
// Type members
export function createProperty(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, questionToken: QuestionToken, type: TypeNode, initializer: Expression) {
export function createProperty(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, questionToken: QuestionToken | undefined, type: TypeNode | undefined, initializer: Expression) {
const node = <PropertyDeclaration>createSynthesizedNode(SyntaxKind.PropertyDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -263,7 +263,7 @@ namespace ts {
return node;
}
export function updateProperty(node: PropertyDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, type: TypeNode, initializer: Expression) {
export function updateProperty(node: PropertyDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, type: TypeNode | undefined, initializer: Expression) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -273,7 +273,7 @@ namespace ts {
: node;
}
export function createMethod(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function createMethod(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
const node = <MethodDeclaration>createSynthesizedNode(SyntaxKind.MethodDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -286,19 +286,20 @@ namespace ts {
return node;
}
export function updateMethod(node: MethodDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function updateMethod(node: MethodDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: PropertyName, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.asteriskToken !== asteriskToken
|| node.name !== name
|| node.typeParameters !== typeParameters
|| node.parameters !== parameters
|| node.type !== type
|| node.body !== body
? updateNode(createMethod(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node)
? updateNode(createMethod(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
: node;
}
export function createConstructor(decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block) {
export function createConstructor(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], body: Block | undefined) {
const node = <ConstructorDeclaration>createSynthesizedNode(SyntaxKind.Constructor);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -309,7 +310,7 @@ namespace ts {
return node;
}
export function updateConstructor(node: ConstructorDeclaration, decorators: Decorator[], modifiers: Modifier[], parameters: ParameterDeclaration[], body: Block) {
export function updateConstructor(node: ConstructorDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, parameters: ParameterDeclaration[], body: Block | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.parameters !== parameters
@@ -318,7 +319,7 @@ namespace ts {
: node;
}
export function createGetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function createGetAccessor(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
const node = <GetAccessorDeclaration>createSynthesizedNode(SyntaxKind.GetAccessor);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -330,7 +331,7 @@ namespace ts {
return node;
}
export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function updateGetAccessor(node: GetAccessorDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -341,7 +342,7 @@ namespace ts {
: node;
}
export function createSetAccessor(decorators: Decorator[], modifiers: Modifier[], name: string | PropertyName, parameters: ParameterDeclaration[], body: Block) {
export function createSetAccessor(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | PropertyName, parameters: ParameterDeclaration[], body: Block | undefined) {
const node = <SetAccessorDeclaration>createSynthesizedNode(SyntaxKind.SetAccessor);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -352,7 +353,7 @@ namespace ts {
return node;
}
export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Decorator[], modifiers: Modifier[], name: PropertyName, parameters: ParameterDeclaration[], body: Block) {
export function updateSetAccessor(node: SetAccessorDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: PropertyName, parameters: ParameterDeclaration[], body: Block | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -388,21 +389,21 @@ namespace ts {
: node;
}
export function createBindingElement(propertyName: string | PropertyName, dotDotDotToken: DotDotDotToken, name: string | BindingName, initializer?: Expression) {
export function createBindingElement(dotDotDotToken: DotDotDotToken | undefined, propertyName: string | PropertyName | undefined, name: string | BindingName, initializer?: Expression) {
const node = <BindingElement>createSynthesizedNode(SyntaxKind.BindingElement);
node.propertyName = asName(propertyName);
node.dotDotDotToken = dotDotDotToken;
node.propertyName = asName(propertyName);
node.name = asName(name);
node.initializer = initializer;
return node;
}
export function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken, propertyName: PropertyName, name: BindingName, initializer: Expression) {
export function updateBindingElement(node: BindingElement, dotDotDotToken: DotDotDotToken | undefined, propertyName: PropertyName | undefined, name: BindingName, initializer: Expression | undefined) {
return node.propertyName !== propertyName
|| node.dotDotDotToken !== dotDotDotToken
|| node.name !== name
|| node.initializer !== initializer
? updateNode(createBindingElement(propertyName, dotDotDotToken, name, initializer), node)
? updateNode(createBindingElement(dotDotDotToken, propertyName, name, initializer), node)
: node;
}
@@ -470,7 +471,7 @@ namespace ts {
: node;
}
export function createCall(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) {
export function createCall(expression: Expression, typeArguments: TypeNode[] | undefined, argumentsArray: Expression[]) {
const node = <CallExpression>createSynthesizedNode(SyntaxKind.CallExpression);
node.expression = parenthesizeForAccess(expression);
node.typeArguments = asNodeArray(typeArguments);
@@ -478,7 +479,7 @@ namespace ts {
return node;
}
export function updateCall(node: CallExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) {
export function updateCall(node: CallExpression, expression: Expression, typeArguments: TypeNode[] | undefined, argumentsArray: Expression[]) {
return expression !== node.expression
|| typeArguments !== node.typeArguments
|| argumentsArray !== node.arguments
@@ -486,7 +487,7 @@ namespace ts {
: node;
}
export function createNew(expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) {
export function createNew(expression: Expression, typeArguments: TypeNode[] | undefined, argumentsArray: Expression[] | undefined) {
const node = <NewExpression>createSynthesizedNode(SyntaxKind.NewExpression);
node.expression = parenthesizeForNew(expression);
node.typeArguments = asNodeArray(typeArguments);
@@ -494,7 +495,7 @@ namespace ts {
return node;
}
export function updateNew(node: NewExpression, expression: Expression, typeArguments: TypeNode[], argumentsArray: Expression[]) {
export function updateNew(node: NewExpression, expression: Expression, typeArguments: TypeNode[] | undefined, argumentsArray: Expression[] | undefined) {
return node.expression !== expression
|| node.typeArguments !== typeArguments
|| node.arguments !== argumentsArray
@@ -542,7 +543,7 @@ namespace ts {
: node;
}
export function createFunctionExpression(modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function createFunctionExpression(modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block) {
const node = <FunctionExpression>createSynthesizedNode(SyntaxKind.FunctionExpression);
node.modifiers = asNodeArray(modifiers);
node.asteriskToken = asteriskToken;
@@ -554,18 +555,19 @@ namespace ts {
return node;
}
export function updateFunctionExpression(node: FunctionExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function updateFunctionExpression(node: FunctionExpression, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block) {
return node.name !== name
|| node.modifiers !== modifiers
|| node.asteriskToken !== asteriskToken
|| node.typeParameters !== typeParameters
|| node.parameters !== parameters
|| node.type !== type
|| node.body !== body
? updateNode(createFunctionExpression(modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node)
? updateNode(createFunctionExpression(modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
: node;
}
export function createArrowFunction(modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, equalsGreaterThanToken: EqualsGreaterThanToken, body: ConciseBody) {
export function createArrowFunction(modifiers: Modifier[] | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, equalsGreaterThanToken: EqualsGreaterThanToken | undefined, body: ConciseBody) {
const node = <ArrowFunction>createSynthesizedNode(SyntaxKind.ArrowFunction);
node.modifiers = asNodeArray(modifiers);
node.typeParameters = asNodeArray(typeParameters);
@@ -576,7 +578,7 @@ namespace ts {
return node;
}
export function updateArrowFunction(node: ArrowFunction, modifiers: Modifier[], typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: ConciseBody) {
export function updateArrowFunction(node: ArrowFunction, modifiers: Modifier[] | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: ConciseBody) {
return node.modifiers !== modifiers
|| node.typeParameters !== typeParameters
|| node.parameters !== parameters
@@ -720,9 +722,10 @@ namespace ts {
return node;
}
export function updateYield(node: YieldExpression, expression: Expression) {
export function updateYield(node: YieldExpression, asteriskToken: AsteriskToken | undefined, expression: Expression) {
return node.expression !== expression
? updateNode(createYield(node.asteriskToken, expression), node)
|| node.asteriskToken !== asteriskToken
? updateNode(createYield(asteriskToken, expression), node)
: node;
}
@@ -738,7 +741,7 @@ namespace ts {
: node;
}
export function createClassExpression(modifiers: Modifier[], name: string | Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) {
export function createClassExpression(modifiers: Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, heritageClauses: HeritageClause[], members: ClassElement[]) {
const node = <ClassExpression>createSynthesizedNode(SyntaxKind.ClassExpression);
node.decorators = undefined;
node.modifiers = asNodeArray(modifiers);
@@ -749,7 +752,7 @@ namespace ts {
return node;
}
export function updateClassExpression(node: ClassExpression, modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) {
export function updateClassExpression(node: ClassExpression, modifiers: Modifier[] | undefined, name: Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, heritageClauses: HeritageClause[], members: ClassElement[]) {
return node.modifiers !== modifiers
|| node.name !== name
|| node.typeParameters !== typeParameters
@@ -834,7 +837,7 @@ namespace ts {
: node;
}
export function createVariableStatement(modifiers: Modifier[], declarationList: VariableDeclarationList | VariableDeclaration[]): VariableStatement {
export function createVariableStatement(modifiers: Modifier[] | undefined, declarationList: VariableDeclarationList | VariableDeclaration[]) {
const node = <VariableStatement>createSynthesizedNode(SyntaxKind.VariableStatement);
node.decorators = undefined;
node.modifiers = asNodeArray(modifiers);
@@ -842,14 +845,14 @@ namespace ts {
return node;
}
export function updateVariableStatement(node: VariableStatement, modifiers: Modifier[], declarationList: VariableDeclarationList): VariableStatement {
export function updateVariableStatement(node: VariableStatement, modifiers: Modifier[] | undefined, declarationList: VariableDeclarationList) {
return node.modifiers !== modifiers
|| node.declarationList !== declarationList
? updateNode(createVariableStatement(modifiers, declarationList), node)
: node;
}
export function createVariableDeclarationList(declarations: VariableDeclaration[], flags?: NodeFlags): VariableDeclarationList {
export function createVariableDeclarationList(declarations: VariableDeclaration[], flags?: NodeFlags) {
const node = <VariableDeclarationList>createSynthesizedNode(SyntaxKind.VariableDeclarationList);
node.flags |= flags;
node.declarations = createNodeArray(declarations);
@@ -862,7 +865,7 @@ namespace ts {
: node;
}
export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression): VariableDeclaration {
export function createVariableDeclaration(name: string | BindingName, type?: TypeNode, initializer?: Expression) {
const node = <VariableDeclaration>createSynthesizedNode(SyntaxKind.VariableDeclaration);
node.name = asName(name);
node.type = type;
@@ -870,7 +873,7 @@ namespace ts {
return node;
}
export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode, initializer: Expression) {
export function updateVariableDeclaration(node: VariableDeclaration, name: BindingName, type: TypeNode | undefined, initializer: Expression | undefined) {
return node.name !== name
|| node.type !== type
|| node.initializer !== initializer
@@ -882,7 +885,7 @@ namespace ts {
return <EmptyStatement>createSynthesizedNode(SyntaxKind.EmptyStatement);
}
export function createStatement(expression: Expression): ExpressionStatement {
export function createStatement(expression: Expression) {
const node = <ExpressionStatement>createSynthesizedNode(SyntaxKind.ExpressionStatement);
node.expression = parenthesizeExpressionForExpressionStatement(expression);
return node;
@@ -902,7 +905,7 @@ namespace ts {
return node;
}
export function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement) {
export function updateIf(node: IfStatement, expression: Expression, thenStatement: Statement, elseStatement: Statement | undefined) {
return node.expression !== expression
|| node.thenStatement !== thenStatement
|| node.elseStatement !== elseStatement
@@ -938,7 +941,7 @@ namespace ts {
: node;
}
export function createFor(initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement) {
export function createFor(initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
const node = <ForStatement>createSynthesizedNode(SyntaxKind.ForStatement);
node.initializer = initializer;
node.condition = condition;
@@ -947,7 +950,7 @@ namespace ts {
return node;
}
export function updateFor(node: ForStatement, initializer: ForInitializer, condition: Expression, incrementor: Expression, statement: Statement) {
export function updateFor(node: ForStatement, initializer: ForInitializer | undefined, condition: Expression | undefined, incrementor: Expression | undefined, statement: Statement) {
return node.initializer !== initializer
|| node.condition !== condition
|| node.incrementor !== incrementor
@@ -972,19 +975,21 @@ namespace ts {
: node;
}
export function createForOf(initializer: ForInitializer, expression: Expression, statement: Statement) {
export function createForOf(awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) {
const node = <ForOfStatement>createSynthesizedNode(SyntaxKind.ForOfStatement);
node.awaitModifier = awaitModifier;
node.initializer = initializer;
node.expression = expression;
node.statement = statement;
return node;
}
export function updateForOf(node: ForOfStatement, initializer: ForInitializer, expression: Expression, statement: Statement) {
return node.initializer !== initializer
export function updateForOf(node: ForOfStatement, awaitModifier: AwaitKeywordToken, initializer: ForInitializer, expression: Expression, statement: Statement) {
return node.awaitModifier !== awaitModifier
|| node.initializer !== initializer
|| node.expression !== expression
|| node.statement !== statement
? updateNode(createForOf(initializer, expression, statement), node)
? updateNode(createForOf(awaitModifier, initializer, expression, statement), node)
: node;
}
@@ -994,7 +999,7 @@ namespace ts {
return node;
}
export function updateContinue(node: ContinueStatement, label: Identifier) {
export function updateContinue(node: ContinueStatement, label: Identifier | undefined) {
return node.label !== label
? updateNode(createContinue(label), node)
: node;
@@ -1006,7 +1011,7 @@ namespace ts {
return node;
}
export function updateBreak(node: BreakStatement, label: Identifier) {
export function updateBreak(node: BreakStatement, label: Identifier | undefined) {
return node.label !== label
? updateNode(createBreak(label), node)
: node;
@@ -1018,7 +1023,7 @@ namespace ts {
return node;
}
export function updateReturn(node: ReturnStatement, expression: Expression) {
export function updateReturn(node: ReturnStatement, expression: Expression | undefined) {
return node.expression !== expression
? updateNode(createReturn(expression), node)
: node;
@@ -1078,7 +1083,7 @@ namespace ts {
: node;
}
export function createTry(tryBlock: Block, catchClause: CatchClause, finallyBlock: Block) {
export function createTry(tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
const node = <TryStatement>createSynthesizedNode(SyntaxKind.TryStatement);
node.tryBlock = tryBlock;
node.catchClause = catchClause;
@@ -1086,7 +1091,7 @@ namespace ts {
return node;
}
export function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause, finallyBlock: Block) {
export function updateTry(node: TryStatement, tryBlock: Block, catchClause: CatchClause | undefined, finallyBlock: Block | undefined) {
return node.tryBlock !== tryBlock
|| node.catchClause !== catchClause
|| node.finallyBlock !== finallyBlock
@@ -1094,7 +1099,7 @@ namespace ts {
: node;
}
export function createFunctionDeclaration(decorators: Decorator[], modifiers: Modifier[], asteriskToken: AsteriskToken, name: string | Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function createFunctionDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
const node = <FunctionDeclaration>createSynthesizedNode(SyntaxKind.FunctionDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1107,19 +1112,20 @@ namespace ts {
return node;
}
export function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], parameters: ParameterDeclaration[], type: TypeNode, body: Block) {
export function updateFunctionDeclaration(node: FunctionDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, asteriskToken: AsteriskToken | undefined, name: Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, parameters: ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.asteriskToken !== asteriskToken
|| node.name !== name
|| node.typeParameters !== typeParameters
|| node.parameters !== parameters
|| node.type !== type
|| node.body !== body
? updateNode(createFunctionDeclaration(decorators, modifiers, node.asteriskToken, name, typeParameters, parameters, type, body), node)
? updateNode(createFunctionDeclaration(decorators, modifiers, asteriskToken, name, typeParameters, parameters, type, body), node)
: node;
}
export function createClassDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) {
export function createClassDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, heritageClauses: HeritageClause[], members: ClassElement[]) {
const node = <ClassDeclaration>createSynthesizedNode(SyntaxKind.ClassDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1130,7 +1136,7 @@ namespace ts {
return node;
}
export function updateClassDeclaration(node: ClassDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, typeParameters: TypeParameterDeclaration[], heritageClauses: HeritageClause[], members: ClassElement[]) {
export function updateClassDeclaration(node: ClassDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: Identifier | undefined, typeParameters: TypeParameterDeclaration[] | undefined, heritageClauses: HeritageClause[], members: ClassElement[]) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -1141,7 +1147,7 @@ namespace ts {
: node;
}
export function createEnumDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, members: EnumMember[]) {
export function createEnumDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | Identifier, members: EnumMember[]) {
const node = <EnumDeclaration>createSynthesizedNode(SyntaxKind.EnumDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1150,7 +1156,7 @@ namespace ts {
return node;
}
export function updateEnumDeclaration(node: EnumDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, members: EnumMember[]) {
export function updateEnumDeclaration(node: EnumDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: Identifier, members: EnumMember[]) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -1159,7 +1165,7 @@ namespace ts {
: node;
}
export function createModuleDeclaration(decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody, flags?: NodeFlags) {
export function createModuleDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags) {
const node = <ModuleDeclaration>createSynthesizedNode(SyntaxKind.ModuleDeclaration);
node.flags |= flags;
node.decorators = asNodeArray(decorators);
@@ -1169,7 +1175,7 @@ namespace ts {
return node;
}
export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Decorator[], modifiers: Modifier[], name: ModuleName, body: ModuleBody) {
export function updateModuleDeclaration(node: ModuleDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: ModuleName, body: ModuleBody | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -1179,7 +1185,7 @@ namespace ts {
}
export function createModuleBlock(statements: Statement[]) {
const node = <ModuleBlock>createSynthesizedNode(SyntaxKind.CaseBlock);
const node = <ModuleBlock>createSynthesizedNode(SyntaxKind.ModuleBlock);
node.statements = createNodeArray(statements);
return node;
}
@@ -1202,7 +1208,7 @@ namespace ts {
: node;
}
export function createImportEqualsDeclaration(decorators: Decorator[], modifiers: Modifier[], name: string | Identifier, moduleReference: ModuleReference) {
export function createImportEqualsDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: string | Identifier, moduleReference: ModuleReference) {
const node = <ImportEqualsDeclaration>createSynthesizedNode(SyntaxKind.ImportEqualsDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1211,7 +1217,7 @@ namespace ts {
return node;
}
export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Decorator[], modifiers: Modifier[], name: Identifier, moduleReference: ModuleReference) {
export function updateImportEqualsDeclaration(node: ImportEqualsDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, name: Identifier, moduleReference: ModuleReference) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.name !== name
@@ -1220,7 +1226,7 @@ namespace ts {
: node;
}
export function createImportDeclaration(decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier?: Expression): ImportDeclaration {
export function createImportDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier?: Expression): ImportDeclaration {
const node = <ImportDeclaration>createSynthesizedNode(SyntaxKind.ImportDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1229,7 +1235,7 @@ namespace ts {
return node;
}
export function updateImportDeclaration(node: ImportDeclaration, decorators: Decorator[], modifiers: Modifier[], importClause: ImportClause, moduleSpecifier: Expression) {
export function updateImportDeclaration(node: ImportDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, importClause: ImportClause | undefined, moduleSpecifier: Expression | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.importClause !== importClause || node.moduleSpecifier !== moduleSpecifier
@@ -1275,21 +1281,21 @@ namespace ts {
: node;
}
export function createImportSpecifier(propertyName: Identifier, name: Identifier) {
export function createImportSpecifier(propertyName: Identifier | undefined, name: Identifier) {
const node = <ImportSpecifier>createSynthesizedNode(SyntaxKind.ImportSpecifier);
node.propertyName = propertyName;
node.name = name;
return node;
}
export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier, name: Identifier) {
export function updateImportSpecifier(node: ImportSpecifier, propertyName: Identifier | undefined, name: Identifier) {
return node.propertyName !== propertyName
|| node.name !== name
? updateNode(createImportSpecifier(propertyName, name), node)
: node;
}
export function createExportAssignment(decorators: Decorator[], modifiers: Modifier[], isExportEquals: boolean, expression: Expression) {
export function createExportAssignment(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, isExportEquals: boolean, expression: Expression) {
const node = <ExportAssignment>createSynthesizedNode(SyntaxKind.ExportAssignment);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1298,7 +1304,7 @@ namespace ts {
return node;
}
export function updateExportAssignment(node: ExportAssignment, decorators: Decorator[], modifiers: Modifier[], expression: Expression) {
export function updateExportAssignment(node: ExportAssignment, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, expression: Expression) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.expression !== expression
@@ -1306,7 +1312,7 @@ namespace ts {
: node;
}
export function createExportDeclaration(decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier?: Expression) {
export function createExportDeclaration(decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier?: Expression) {
const node = <ExportDeclaration>createSynthesizedNode(SyntaxKind.ExportDeclaration);
node.decorators = asNodeArray(decorators);
node.modifiers = asNodeArray(modifiers);
@@ -1315,7 +1321,7 @@ namespace ts {
return node;
}
export function updateExportDeclaration(node: ExportDeclaration, decorators: Decorator[], modifiers: Modifier[], exportClause: NamedExports, moduleSpecifier: Expression) {
export function updateExportDeclaration(node: ExportDeclaration, decorators: Decorator[] | undefined, modifiers: Modifier[] | undefined, exportClause: NamedExports | undefined, moduleSpecifier: Expression | undefined) {
return node.decorators !== decorators
|| node.modifiers !== modifiers
|| node.exportClause !== exportClause
@@ -1336,16 +1342,17 @@ namespace ts {
: node;
}
export function createExportSpecifier(name: string | Identifier, propertyName?: string | Identifier) {
export function createExportSpecifier(propertyName: string | Identifier | undefined, name: string | Identifier) {
const node = <ExportSpecifier>createSynthesizedNode(SyntaxKind.ExportSpecifier);
node.name = asName(name);
node.propertyName = asName(propertyName);
node.name = asName(name);
return node;
}
export function updateExportSpecifier(node: ExportSpecifier, name: Identifier, propertyName: Identifier) {
return node.name !== name || node.propertyName !== propertyName
? updateNode(createExportSpecifier(name, propertyName), node)
export function updateExportSpecifier(node: ExportSpecifier, propertyName: Identifier | undefined, name: Identifier) {
return node.propertyName !== propertyName
|| node.name !== name
? updateNode(createExportSpecifier(propertyName, name), node)
: node;
}
@@ -1460,16 +1467,16 @@ namespace ts {
: node;
}
export function createJsxExpression(expression: Expression, dotDotDotToken: DotDotDotToken) {
export function createJsxExpression(dotDotDotToken: DotDotDotToken | undefined, expression: Expression | undefined) {
const node = <JsxExpression>createSynthesizedNode(SyntaxKind.JsxExpression);
node.dotDotDotToken = dotDotDotToken;
node.expression = expression;
return node;
}
export function updateJsxExpression(node: JsxExpression, expression: Expression) {
export function updateJsxExpression(node: JsxExpression, expression: Expression | undefined) {
return node.expression !== expression
? updateNode(createJsxExpression(expression, node.dotDotDotToken), node)
? updateNode(createJsxExpression(node.dotDotDotToken, expression), node)
: node;
}
@@ -1547,26 +1554,26 @@ namespace ts {
return node;
}
export function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer: Expression) {
export function createShorthandPropertyAssignment(name: string | Identifier, objectAssignmentInitializer?: Expression) {
const node = <ShorthandPropertyAssignment>createSynthesizedNode(SyntaxKind.ShorthandPropertyAssignment);
node.name = asName(name);
node.objectAssignmentInitializer = objectAssignmentInitializer !== undefined ? parenthesizeExpressionForList(objectAssignmentInitializer) : undefined;
return node;
}
export function createSpreadAssignment(expression: Expression) {
const node = <SpreadAssignment>createSynthesizedNode(SyntaxKind.SpreadAssignment);
node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined;
return node;
}
export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression) {
export function updateShorthandPropertyAssignment(node: ShorthandPropertyAssignment, name: Identifier, objectAssignmentInitializer: Expression | undefined) {
if (node.name !== name || node.objectAssignmentInitializer !== objectAssignmentInitializer) {
return updateNode(createShorthandPropertyAssignment(name, objectAssignmentInitializer), node);
}
return node;
}
export function createSpreadAssignment(expression: Expression) {
const node = <SpreadAssignment>createSynthesizedNode(SyntaxKind.SpreadAssignment);
node.expression = expression !== undefined ? parenthesizeExpressionForList(expression) : undefined;
return node;
}
export function updateSpreadAssignment(node: SpreadAssignment, expression: Expression) {
if (node.expression !== expression) {
return updateNode(createSpreadAssignment(expression), node);
@@ -1774,7 +1781,7 @@ namespace ts {
}
export function createExternalModuleExport(exportName: Identifier) {
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(exportName)]));
return createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createNamedExports([createExportSpecifier(/*propertyName*/ undefined, exportName)]));
}
// Utilities
@@ -1855,7 +1862,7 @@ namespace ts {
/**
* Gets flags that control emit behavior of a node.
*/
export function getEmitFlags(node: Node) {
export function getEmitFlags(node: Node): EmitFlags | undefined {
const emitNode = node.emitNode;
return emitNode && emitNode.flags;
}
@@ -1879,7 +1886,7 @@ namespace ts {
/**
* Sets a custom text range to use when emitting source maps.
*/
export function setSourceMapRange<T extends Node>(node: T, range: TextRange) {
export function setSourceMapRange<T extends Node>(node: T, range: TextRange | undefined) {
getOrCreateEmitNode(node).sourceMapRange = range;
return node;
}
@@ -1887,7 +1894,7 @@ namespace ts {
/**
* Gets the TextRange to use for source maps for a token of a node.
*/
export function getTokenSourceMapRange(node: Node, token: SyntaxKind) {
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): TextRange | undefined {
const emitNode = node.emitNode;
const tokenSourceMapRanges = emitNode && emitNode.tokenSourceMapRanges;
return tokenSourceMapRanges && tokenSourceMapRanges[token];
@@ -1896,7 +1903,7 @@ namespace ts {
/**
* Sets the TextRange to use for source maps for a token of a node.
*/
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange) {
export function setTokenSourceMapRange<T extends Node>(node: T, token: SyntaxKind, range: TextRange | undefined) {
const emitNode = getOrCreateEmitNode(node);
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges || (emitNode.tokenSourceMapRanges = []);
tokenSourceMapRanges[token] = range;
@@ -1919,6 +1926,34 @@ namespace ts {
return node;
}
export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined {
const emitNode = node.emitNode;
return emitNode && emitNode.leadingComments;
}
export function setSyntheticLeadingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
getOrCreateEmitNode(node).leadingComments = comments;
return node;
}
export function addSyntheticLeadingComment<T extends Node>(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) {
return setSyntheticLeadingComments(node, append(getSyntheticLeadingComments(node), <SynthesizedComment>{ kind, pos: -1, end: -1, hasTrailingNewLine, text }));
}
export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined {
const emitNode = node.emitNode;
return emitNode && emitNode.trailingComments;
}
export function setSyntheticTrailingComments<T extends Node>(node: T, comments: SynthesizedComment[]) {
getOrCreateEmitNode(node).trailingComments = comments;
return node;
}
export function addSyntheticTrailingComment<T extends Node>(node: T, kind: SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia, text: string, hasTrailingNewLine?: boolean) {
return setSyntheticTrailingComments(node, append(getSyntheticTrailingComments(node), <SynthesizedComment>{ kind, pos: -1, end: -1, hasTrailingNewLine, text }));
}
/**
* Gets the constant value to emit for an expression.
*/
@@ -2019,7 +2054,7 @@ namespace ts {
return compareValues(x.priority, y.priority);
}
export function setOriginalNode<T extends Node>(node: T, original: Node): T {
export function setOriginalNode<T extends Node>(node: T, original: Node | undefined): T {
node.original = original;
if (original) {
const emitNode = original.emitNode;
@@ -2031,6 +2066,8 @@ namespace ts {
function mergeEmitNode(sourceEmitNode: EmitNode, destEmitNode: EmitNode) {
const {
flags,
leadingComments,
trailingComments,
commentRange,
sourceMapRange,
tokenSourceMapRanges,
@@ -2038,6 +2075,8 @@ namespace ts {
helpers
} = sourceEmitNode;
if (!destEmitNode) destEmitNode = {};
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
if (flags) destEmitNode.flags = flags;
if (commentRange) destEmitNode.commentRange = commentRange;
if (sourceMapRange) destEmitNode.sourceMapRange = sourceMapRange;
@@ -2211,8 +2250,129 @@ namespace ts {
return setEmitFlags(createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
}
const valuesHelper: EmitHelper = {
name: "typescript:values",
scoped: false,
text: `
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
`
};
export function createValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
context.requestEmitHelper(valuesHelper);
return setTextRange(
createCall(
getHelperName("__values"),
/*typeArguments*/ undefined,
[expression]
),
location
);
}
const readHelper: EmitHelper = {
name: "typescript:read",
scoped: false,
text: `
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
`
};
export function createReadHelper(context: TransformationContext, iteratorRecord: Expression, count: number | undefined, location?: TextRange) {
context.requestEmitHelper(readHelper);
return setTextRange(
createCall(
getHelperName("__read"),
/*typeArguments*/ undefined,
count !== undefined
? [iteratorRecord, createLiteral(count)]
: [iteratorRecord]
),
location
);
}
const spreadHelper: EmitHelper = {
name: "typescript:spread",
scoped: false,
text: `
var __spread = (this && this.__spread) || function () {
for (var ar = [], i = 0; i < arguments.length; i++) ar = ar.concat(__read(arguments[i]));
return ar;
};`
};
export function createSpreadHelper(context: TransformationContext, argumentList: Expression[], location?: TextRange) {
context.requestEmitHelper(readHelper);
context.requestEmitHelper(spreadHelper);
return setTextRange(
createCall(
getHelperName("__spread"),
/*typeArguments*/ undefined,
argumentList
),
location
);
}
// Utilities
export function createForOfBindingStatement(node: ForInitializer, boundValue: Expression): Statement {
if (isVariableDeclarationList(node)) {
const firstDeclaration = firstOrUndefined(node.declarations);
const updatedDeclaration = updateVariableDeclaration(
firstDeclaration,
firstDeclaration.name,
/*typeNode*/ undefined,
boundValue
);
return setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
updateVariableDeclarationList(node, [updatedDeclaration])
),
/*location*/ node
);
}
else {
const updatedExpression = setTextRange(createAssignment(node, boundValue), /*location*/ node);
return setTextRange(createStatement(updatedExpression), /*location*/ node);
}
}
export function insertLeadingStatement(dest: Statement, source: Statement) {
if (isBlock(dest)) {
return updateBlock(dest, setTextRange(createNodeArray([source, ...dest.statements]), dest.statements));
}
else {
return createBlock(createNodeArray([dest, source]), /*multiLine*/ true);
}
}
export function restoreEnclosingLabel(node: Statement, outermostLabeledStatement: LabeledStatement, afterRestoreLabelCallback?: (node: LabeledStatement) => void): Statement {
if (!outermostLabeledStatement) {
return node;
@@ -2271,6 +2431,10 @@ namespace ts {
? setTextRange(createIdentifier("_super"), callee)
: <PrimaryExpression>callee;
}
else if (getEmitFlags(callee) & EmitFlags.HelperName) {
thisArg = createVoidZero();
target = parenthesizeForAccess(callee);
}
else {
switch (callee.kind) {
case SyntaxKind.PropertyAccessExpression: {
@@ -2684,6 +2848,16 @@ namespace ts {
return statements;
}
export function parenthesizeConditionalHead(condition: Expression) {
const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken);
const emittedCondition = skipPartiallyEmittedExpressions(condition);
const conditionPrecedence = getExpressionPrecedence(emittedCondition);
if (compareValues(conditionPrecedence, conditionalPrecedence) === Comparison.LessThan) {
return createParen(condition);
}
return condition;
}
/**
* Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended
* order of operations.
+17 -10
View File
@@ -243,7 +243,8 @@ namespace ts {
visitNode(cbNode, (<ForInStatement>node).expression) ||
visitNode(cbNode, (<ForInStatement>node).statement);
case SyntaxKind.ForOfStatement:
return visitNode(cbNode, (<ForOfStatement>node).initializer) ||
return visitNode(cbNode, (<ForOfStatement>node).awaitModifier) ||
visitNode(cbNode, (<ForOfStatement>node).initializer) ||
visitNode(cbNode, (<ForOfStatement>node).expression) ||
visitNode(cbNode, (<ForOfStatement>node).statement);
case SyntaxKind.ContinueStatement:
@@ -4462,6 +4463,7 @@ namespace ts {
function parseForOrForInOrForOfStatement(): Statement {
const pos = getNodePos();
parseExpected(SyntaxKind.ForKeyword);
const awaitToken = parseOptionalToken(SyntaxKind.AwaitKeyword);
parseExpected(SyntaxKind.OpenParenToken);
let initializer: VariableDeclarationList | Expression = undefined;
@@ -4474,20 +4476,21 @@ namespace ts {
}
}
let forOrForInOrForOfStatement: IterationStatement;
if (parseOptional(SyntaxKind.InKeyword)) {
if (awaitToken ? parseExpected(SyntaxKind.OfKeyword) : parseOptional(SyntaxKind.OfKeyword)) {
const forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
forOfStatement.awaitModifier = awaitToken;
forOfStatement.initializer = initializer;
forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
parseExpected(SyntaxKind.CloseParenToken);
forOrForInOrForOfStatement = forOfStatement;
}
else if (parseOptional(SyntaxKind.InKeyword)) {
const forInStatement = <ForInStatement>createNode(SyntaxKind.ForInStatement, pos);
forInStatement.initializer = initializer;
forInStatement.expression = allowInAnd(parseExpression);
parseExpected(SyntaxKind.CloseParenToken);
forOrForInOrForOfStatement = forInStatement;
}
else if (parseOptional(SyntaxKind.OfKeyword)) {
const forOfStatement = <ForOfStatement>createNode(SyntaxKind.ForOfStatement, pos);
forOfStatement.initializer = initializer;
forOfStatement.expression = allowInAnd(parseAssignmentExpressionOrHigher);
parseExpected(SyntaxKind.CloseParenToken);
forOrForInOrForOfStatement = forOfStatement;
}
else {
const forStatement = <ForStatement>createNode(SyntaxKind.ForStatement, pos);
forStatement.initializer = initializer;
@@ -5830,7 +5833,11 @@ namespace ts {
}
}
const range = { pos: triviaScanner.getTokenPos(), end: triviaScanner.getTextPos(), kind: triviaScanner.getToken() };
const range = {
kind: <SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia>triviaScanner.getToken(),
pos: triviaScanner.getTokenPos(),
end: triviaScanner.getTextPos(),
};
const comment = sourceText.substring(range.pos, range.end);
const referencePathMatchResult = getFileReferenceFromReferencePath(comment, range);
+6 -4
View File
@@ -754,15 +754,15 @@ namespace ts {
return noDiagnosticsTypeChecker || (noDiagnosticsTypeChecker = createTypeChecker(program, /*produceDiagnostics:*/ false));
}
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles));
function emit(sourceFile?: SourceFile, writeFileCallback?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, transformers?: CustomTransformers): EmitResult {
return runWithCancellationToken(() => emitWorker(program, sourceFile, writeFileCallback, cancellationToken, emitOnlyDtsFiles, transformers));
}
function isEmitBlocked(emitFileName: string): boolean {
return hasEmitBlockingDiagnostics.contains(toPath(emitFileName, currentDirectory, getCanonicalFileName));
}
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult {
function emitWorker(program: Program, sourceFile: SourceFile, writeFileCallback: WriteFileCallback, cancellationToken: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult {
let declarationDiagnostics: Diagnostic[] = [];
if (options.noEmit) {
@@ -804,11 +804,13 @@ namespace ts {
performance.mark("beforeEmit");
const transformers = emitOnlyDtsFiles ? [] : getTransformers(options, customTransformers);
const emitResult = emitFiles(
emitResolver,
getEmitHost(writeFileCallback),
sourceFile,
emitOnlyDtsFiles);
emitOnlyDtsFiles,
transformers);
performance.mark("afterEmit");
performance.measure("Emit", "beforeEmit", "afterEmit");
+8 -8
View File
@@ -608,10 +608,10 @@ namespace ts {
* @returns If "reduce" is true, the accumulated value. If "reduce" is false, the first truthy
* return value of the callback.
*/
function iterateCommentRanges<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial?: U): U {
function iterateCommentRanges<T, U>(reduce: boolean, text: string, pos: number, trailing: boolean, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial?: U): U {
let pendingPos: number;
let pendingEnd: number;
let pendingKind: SyntaxKind;
let pendingKind: CommentKind;
let pendingHasTrailingNewLine: boolean;
let hasPendingCommentRange = false;
let collecting = trailing || pos === 0;
@@ -707,28 +707,28 @@ namespace ts {
return accumulator;
}
export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
export function forEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ false, cb, state);
}
export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
export function forEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T) => U, state?: T) {
return iterateCommentRanges(/*reduce*/ false, text, pos, /*trailing*/ true, cb, state);
}
export function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
export function reduceEachLeadingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ false, cb, state, initial);
}
export function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
export function reduceEachTrailingCommentRange<T, U>(text: string, pos: number, cb: (pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, state: T, memo: U) => U, state: T, initial: U) {
return iterateCommentRanges(/*reduce*/ true, text, pos, /*trailing*/ true, cb, state, initial);
}
function appendCommentRange(pos: number, end: number, kind: SyntaxKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
function appendCommentRange(pos: number, end: number, kind: CommentKind, hasTrailingNewLine: boolean, _state: any, comments: CommentRange[]) {
if (!comments) {
comments = [];
}
comments.push({ pos, end, hasTrailingNewLine, kind });
comments.push({ kind, pos, end, hasTrailingNewLine });
return comments;
}
+20 -12
View File
@@ -59,6 +59,21 @@ namespace ts {
declare var global: any;
declare var __filename: string;
export function getNodeMajorVersion() {
if (typeof process === "undefined") {
return undefined;
}
const version: string = process.version;
if (!version) {
return undefined;
}
const dot = version.indexOf(".");
if (dot === -1) {
return undefined;
}
return parseInt(version.substring(1, dot));
}
declare class Enumerator {
public atEnd(): boolean;
public moveNext(): boolean;
@@ -315,9 +330,8 @@ namespace ts {
}
const watchedFileSet = createWatchedFileSet();
function isNode4OrLater(): boolean {
return parseInt(process.version.charAt(1)) >= 4;
}
const nodeVersion = getNodeMajorVersion();
const isNode4OrLater = nodeVersion >= 4;
function isFileSystemCaseSensitive(): boolean {
// win32\win64 are case insensitive platforms
@@ -485,14 +499,12 @@ namespace ts {
// Node 4.0 `fs.watch` function supports the "recursive" option on both OSX and Windows
// (ref: https://github.com/nodejs/node/pull/2649 and https://github.com/Microsoft/TypeScript/issues/4643)
let options: any;
if (!directoryExists(directoryName) || (isUNCPath(directoryName) && process.platform === "win32")) {
// do nothing if either
// - target folder does not exist
// - this is UNC path on Windows (https://github.com/Microsoft/TypeScript/issues/13874)
if (!directoryExists(directoryName)) {
// do nothing if target folder does not exist
return noOpFileWatcher;
}
if (isNode4OrLater() && (process.platform === "win32" || process.platform === "darwin")) {
if (isNode4OrLater && (process.platform === "win32" || process.platform === "darwin")) {
options = { persistent: true, recursive: !!recursive };
}
else {
@@ -512,10 +524,6 @@ namespace ts {
};
}
);
function isUNCPath(s: string): boolean {
return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash;
}
},
resolvePath: function(path: string): string {
return _path.resolve(path);
+99 -49
View File
@@ -13,7 +13,7 @@
/* @internal */
namespace ts {
function getModuleTransformer(moduleKind: ModuleKind): Transformer {
function getModuleTransformer(moduleKind: ModuleKind): TransformerFactory<SourceFile> {
switch (moduleKind) {
case ModuleKind.ES2015:
return transformES2015Module;
@@ -24,16 +24,25 @@ namespace ts {
}
}
const enum TransformationState {
Uninitialized,
Initialized,
Completed,
Disposed
}
const enum SyntaxKindFeatureFlags {
Substitution = 1 << 0,
EmitNotifications = 1 << 1,
}
export function getTransformers(compilerOptions: CompilerOptions) {
export function getTransformers(compilerOptions: CompilerOptions, customTransformers?: CustomTransformers) {
const jsx = compilerOptions.jsx;
const languageVersion = getEmitScriptTarget(compilerOptions);
const moduleKind = getEmitModuleKind(compilerOptions);
const transformers: Transformer[] = [];
const transformers: TransformerFactory<SourceFile>[] = [];
addRange(transformers, customTransformers && customTransformers.before);
transformers.push(transformTypeScript);
@@ -66,6 +75,8 @@ namespace ts {
transformers.push(transformES5);
}
addRange(transformers, customTransformers && customTransformers.after);
return transformers;
}
@@ -73,28 +84,29 @@ namespace ts {
* Transforms an array of SourceFiles by passing them through each transformer.
*
* @param resolver The emit resolver provided by the checker.
* @param host The emit host.
* @param sourceFiles An array of source files
* @param transforms An array of Transformers.
* @param host The emit host object used to interact with the file system.
* @param options Compiler options to surface in the `TransformationContext`.
* @param nodes An array of nodes to transform.
* @param transforms An array of `TransformerFactory` callbacks.
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
*/
export function transformFiles(resolver: EmitResolver, host: EmitHost, sourceFiles: SourceFile[], transformers: Transformer[]): TransformationResult {
export function transformNodes<T extends Node>(resolver: EmitResolver, host: EmitHost, options: CompilerOptions, nodes: T[], transformers: TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentDisabled = false;
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
let lexicalEnvironmentVariableDeclarationsStack: VariableDeclaration[][] = [];
let lexicalEnvironmentFunctionDeclarationsStack: FunctionDeclaration[][] = [];
let lexicalEnvironmentStackOffset = 0;
let lexicalEnvironmentSuspended = false;
let emitHelpers: EmitHelper[];
let onSubstituteNode: TransformationContext["onSubstituteNode"] = (_, node) => node;
let onEmitNode: TransformationContext["onEmitNode"] = (hint, node, callback) => callback(hint, node);
let state = TransformationState.Uninitialized;
// The transformation context is provided to each transformer as part of transformer
// initialization.
const context: TransformationContext = {
getCompilerOptions: () => host.getCompilerOptions(),
getCompilerOptions: () => options,
getEmitResolver: () => resolver,
getEmitHost: () => host,
startLexicalEnvironment,
@@ -105,51 +117,62 @@ namespace ts {
hoistFunctionDeclaration,
requestEmitHelper,
readEmitHelpers,
onSubstituteNode: (_, node) => node,
enableSubstitution,
isSubstitutionEnabled,
onEmitNode: (hint, node, callback) => callback(hint, node),
enableEmitNotification,
isEmitNotificationEnabled
isSubstitutionEnabled,
isEmitNotificationEnabled,
get onSubstituteNode() { return onSubstituteNode },
set onSubstituteNode(value) {
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
Debug.assert(value !== undefined, "Value must not be 'undefined'");
onSubstituteNode = value;
},
get onEmitNode() { return onEmitNode },
set onEmitNode(value) {
Debug.assert(state < TransformationState.Initialized, "Cannot modify transformation hooks after initialization has completed.");
Debug.assert(value !== undefined, "Value must not be 'undefined'");
onEmitNode = value;
}
};
// Ensure the parse tree is clean before applying transformations
for (const node of nodes) {
disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node)));
}
performance.mark("beforeTransform");
// Chain together and initialize each transformer.
const transformation = chain(...transformers)(context);
// Transform each source file.
const transformed = map(sourceFiles, transformSourceFile);
// prevent modification of transformation hooks.
state = TransformationState.Initialized;
// Disable modification of the lexical environment.
lexicalEnvironmentDisabled = true;
// Transform each node.
const transformed = map(nodes, allowDtsFiles ? transformation : transformRoot);
// prevent modification of the lexical environment.
state = TransformationState.Completed;
performance.mark("afterTransform");
performance.measure("transformTime", "beforeTransform", "afterTransform");
return {
transformed,
emitNodeWithSubstitution,
emitNodeWithNotification
substituteNode,
emitNodeWithNotification,
dispose
};
/**
* Transforms a source file.
*
* @param sourceFile The source file to transform.
*/
function transformSourceFile(sourceFile: SourceFile) {
if (isDeclarationFile(sourceFile)) {
return sourceFile;
}
return transformation(sourceFile);
function transformRoot(node: T) {
return node && (!isSourceFile(node) || !isDeclarationFile(node)) ? transformation(node) : node;
}
/**
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
*/
function enableSubstitution(kind: SyntaxKind) {
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.Substitution;
}
@@ -168,19 +191,16 @@ namespace ts {
* @param node The node to emit.
* @param emitCallback The callback used to emit the node or its substitute.
*/
function emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (node) {
if (isSubstitutionEnabled(node)) {
node = context.onSubstituteNode(hint, node) || node;
}
emitCallback(hint, node);
}
function substituteNode(hint: EmitHint, node: Node) {
Debug.assert(state < TransformationState.Disposed, "Cannot substitute a node after the result is disposed.");
return node && isSubstitutionEnabled(node) && onSubstituteNode(hint, node) || node;
}
/**
* Enables before/after emit notifications in the pretty printer for the provided SyntaxKind.
*/
function enableEmitNotification(kind: SyntaxKind) {
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
enabledSyntaxKindFeatures[kind] |= SyntaxKindFeatureFlags.EmitNotifications;
}
@@ -201,9 +221,10 @@ namespace ts {
* @param emitCallback The callback used to emit the node.
*/
function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
Debug.assert(state < TransformationState.Disposed, "Cannot invoke TransformationResult callbacks after the result is disposed.");
if (node) {
if (isEmitNotificationEnabled(node)) {
context.onEmitNode(hint, node, emitCallback);
onEmitNode(hint, node, emitCallback);
}
else {
emitCallback(hint, node);
@@ -215,7 +236,8 @@ namespace ts {
* Records a hoisted variable declaration for the provided name within a lexical environment.
*/
function hoistVariableDeclaration(name: Identifier): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
const decl = createVariableDeclaration(name);
if (!lexicalEnvironmentVariableDeclarations) {
lexicalEnvironmentVariableDeclarations = [decl];
@@ -229,7 +251,8 @@ namespace ts {
* Records a hoisted function declaration within a lexical environment.
*/
function hoistFunctionDeclaration(func: FunctionDeclaration): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
if (!lexicalEnvironmentFunctionDeclarations) {
lexicalEnvironmentFunctionDeclarations = [func];
}
@@ -243,7 +266,8 @@ namespace ts {
* are pushed onto a stack, and the related storage variables are reset.
*/
function startLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot start a lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
// Save the current lexical environment. Rather than resizing the array we adjust the
@@ -259,14 +283,16 @@ namespace ts {
/** Suspends the current lexical environment, usually after visiting a parameter list. */
function suspendLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot suspend a lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is already suspended.");
lexicalEnvironmentSuspended = true;
}
/** Resumes a suspended lexical environment, usually before visiting a function body. */
function resumeLexicalEnvironment(): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot resume a lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
Debug.assert(lexicalEnvironmentSuspended, "Lexical environment is not suspended.");
lexicalEnvironmentSuspended = false;
}
@@ -276,7 +302,8 @@ namespace ts {
* any hoisted declarations added in this environment are returned.
*/
function endLexicalEnvironment(): Statement[] {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot end a lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the lexical environment during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the lexical environment after transformation has completed.");
Debug.assert(!lexicalEnvironmentSuspended, "Lexical environment is suspended.");
let statements: Statement[];
@@ -312,16 +339,39 @@ namespace ts {
}
function requestEmitHelper(helper: EmitHelper): void {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
Debug.assert(!helper.scoped, "Cannot request a scoped emit helper.");
emitHelpers = append(emitHelpers, helper);
}
function readEmitHelpers(): EmitHelper[] | undefined {
Debug.assert(!lexicalEnvironmentDisabled, "Cannot modify the lexical environment during the print phase.");
Debug.assert(state > TransformationState.Uninitialized, "Cannot modify the transformation context during initialization.");
Debug.assert(state < TransformationState.Completed, "Cannot modify the transformation context after transformation has completed.");
const helpers = emitHelpers;
emitHelpers = undefined;
return helpers;
}
function dispose() {
if (state < TransformationState.Disposed) {
// Clean up emit nodes on parse tree
for (const node of nodes) {
disposeEmitNodes(getSourceFileOfNode(getParseTreeNode(node)));
}
// Release references to external entries for GC purposes.
lexicalEnvironmentVariableDeclarations = undefined;
lexicalEnvironmentVariableDeclarationsStack = undefined;
lexicalEnvironmentFunctionDeclarations = undefined;
lexicalEnvironmentFunctionDeclarationsStack = undefined;
onSubstituteNode = undefined;
onEmitNode = undefined;
emitHelpers = undefined;
// Prevent further use of the transformation result.
state = TransformationState.Disposed;
}
}
}
}
+21 -2
View File
@@ -6,6 +6,7 @@ namespace ts {
interface FlattenContext {
context: TransformationContext;
level: FlattenLevel;
downlevelIteration: boolean;
hoistTempVariables: boolean;
emitExpression: (value: Expression) => void;
emitBindingOrAssignment: (target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange, original: Node) => void;
@@ -57,6 +58,7 @@ namespace ts {
const flattenContext: FlattenContext = {
context,
level,
downlevelIteration: context.getCompilerOptions().downlevelIteration,
hoistTempVariables: true,
emitExpression,
emitBindingOrAssignment,
@@ -146,6 +148,7 @@ namespace ts {
const flattenContext: FlattenContext = {
context,
level,
downlevelIteration: context.getCompilerOptions().downlevelIteration,
hoistTempVariables,
emitExpression,
emitBindingOrAssignment,
@@ -312,7 +315,23 @@ namespace ts {
function flattenArrayBindingOrAssignmentPattern(flattenContext: FlattenContext, parent: BindingOrAssignmentElement, pattern: ArrayBindingOrAssignmentPattern, value: Expression, location: TextRange) {
const elements = getElementsOfBindingOrAssignmentPattern(pattern);
const numElements = elements.length;
if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)) {
if (flattenContext.level < FlattenLevel.ObjectRest && flattenContext.downlevelIteration) {
// Read the elements of the iterable into an array
value = ensureIdentifier(
flattenContext,
createReadHelper(
flattenContext.context,
value,
numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1])
? undefined
: numElements,
location
),
/*reuseIdentifierExpressions*/ false,
location
);
}
else if (numElements !== 1 && (flattenContext.level < FlattenLevel.ObjectRest || numElements === 0)) {
// 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,
@@ -448,7 +467,7 @@ namespace ts {
}
function makeBindingElement(name: Identifier) {
return createBindingElement(/*propertyName*/ undefined, /*dotDotDotToken*/ undefined, name);
return createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name);
}
function makeAssignmentElement(name: Identifier) {
+244 -119
View File
@@ -1,5 +1,6 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/// <reference path="./destructuring.ts" />
/*@internal*/
namespace ts {
@@ -268,6 +269,7 @@ namespace ts {
hoistVariableDeclaration,
} = context;
const compilerOptions = context.getCompilerOptions();
const resolver = context.getEmitResolver();
const previousOnSubstituteNode = context.onSubstituteNode;
const previousOnEmitNode = context.onEmitNode;
@@ -1716,6 +1718,7 @@ namespace ts {
return updateFunctionExpression(
node,
/*modifiers*/ undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
@@ -1747,6 +1750,7 @@ namespace ts {
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
@@ -1939,6 +1943,9 @@ namespace ts {
function visitParenthesizedExpression(node: ParenthesizedExpression, needsDestructuringValue: boolean): ParenthesizedExpression {
// If we are here it is most likely because our expression is a destructuring assignment.
if (!needsDestructuringValue) {
// By default we always emit the RHS at the end of a flattened destructuring
// expression. If we are in a state where we do not need the destructuring value,
// we pass that information along to the children that care about it.
switch (node.expression.kind) {
case SyntaxKind.ParenthesizedExpression:
return updateParen(node, visitParenthesizedExpression(<ParenthesizedExpression>node.expression, /*needsDestructuringValue*/ false));
@@ -1990,7 +1997,8 @@ namespace ts {
else {
assignment = createBinary(<Identifier>decl.name, SyntaxKind.EqualsToken, visitNode(decl.initializer, visitor, isExpression));
}
(assignments || (assignments = [])).push(assignment);
assignments = append(assignments, assignment);
}
}
if (assignments) {
@@ -2172,12 +2180,26 @@ namespace ts {
if (convertedLoopState && !convertedLoopState.labels) {
convertedLoopState.labels = createMap<string>();
}
const statement = unwrapInnermostStatmentOfLabel(node, convertedLoopState && recordLabel);
return isIterationStatement(statement, /*lookInLabeledStatements*/ false) && shouldConvertIterationStatementBody(statement)
const statement = unwrapInnermostStatementOfLabel(node, convertedLoopState && recordLabel);
return isIterationStatement(statement, /*lookInLabeledStatements*/ false)
? visitIterationStatement(statement, /*outermostLabeledStatement*/ node)
: restoreEnclosingLabel(visitNode(statement, visitor, isStatement), node, convertedLoopState && resetLabel);
}
function visitIterationStatement(node: IterationStatement, outermostLabeledStatement: LabeledStatement) {
switch (node.kind) {
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
return visitDoOrWhileStatement(<DoStatement | WhileStatement>node, outermostLabeledStatement);
case SyntaxKind.ForStatement:
return visitForStatement(<ForStatement>node, outermostLabeledStatement);
case SyntaxKind.ForInStatement:
return visitForInStatement(<ForInStatement>node, outermostLabeledStatement);
case SyntaxKind.ForOfStatement:
return visitForOfStatement(<ForOfStatement>node, outermostLabeledStatement);
}
}
function visitIterationStatementWithFacts(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts, node: IterationStatement, outermostLabeledStatement: LabeledStatement, convert?: LoopConverter) {
const ancestorFacts = enterSubtree(excludeFacts, includeFacts);
const updated = convertIterationStatementBodyIfNecessary(node, outermostLabeledStatement, convert);
@@ -2215,54 +2237,17 @@ namespace ts {
HierarchyFacts.ForInOrForOfStatementIncludes,
node,
outermostLabeledStatement,
convertForOfToFor);
compilerOptions.downlevelIteration ? convertForOfStatementForIterable : convertForOfStatementForArray);
}
function convertForOfToFor(node: ForOfStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
// The following ES6 code:
//
// for (let v of expr) { }
//
// should be emitted as
//
// for (var _i = 0, _a = expr; _i < _a.length; _i++) {
// var v = _a[_i];
// }
//
// where _a and _i are temps emitted to capture the RHS and the counter,
// respectively.
// When the left hand side is an expression instead of a let declaration,
// the "let v" is not emitted.
// When the left hand side is a let/const, the v is renamed if there is
// another v in scope.
// Note that all assignments to the LHS are emitted in the body, including
// all destructuring.
// Note also that because an extra statement is needed to assign to the LHS,
// for-of bodies are always emitted as blocks.
const expression = visitNode(node.expression, visitor, isExpression);
const initializer = node.initializer;
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression, convertedLoopBodyStatements: Statement[]) {
const statements: Statement[] = [];
// In the case where the user wrote an identifier as the RHS, like this:
//
// for (let v of arr) { }
//
// we don't want to emit a temporary variable for the RHS, just use it directly.
const counter = createLoopVariable();
const rhsReference = expression.kind === SyntaxKind.Identifier
? createUniqueName(unescapeIdentifier((<Identifier>expression).text))
: createTempVariable(/*recordTempVariable*/ undefined);
const elementAccess = createElementAccess(rhsReference, counter);
// Initialize LHS
// var v = _a[_i];
if (isVariableDeclarationList(initializer)) {
if (initializer.flags & NodeFlags.BlockScoped) {
if (isVariableDeclarationList(node.initializer)) {
if (node.initializer.flags & NodeFlags.BlockScoped) {
enableSubstitutionsForBlockScopedBindings();
}
const firstOriginalDeclaration = firstOrUndefined(initializer.declarations);
const firstOriginalDeclaration = firstOrUndefined(node.initializer.declarations);
if (firstOriginalDeclaration && isBindingPattern(firstOriginalDeclaration.name)) {
// This works whether the declaration is a var, let, or const.
// It will use rhsIterationValue _a[_i] as the initializer.
@@ -2271,12 +2256,11 @@ namespace ts {
visitor,
context,
FlattenLevel.All,
elementAccess
boundValue
);
const declarationList = createVariableDeclarationList(declarations);
setOriginalNode(declarationList, initializer);
setTextRange(declarationList, initializer);
const declarationList = setTextRange(createVariableDeclarationList(declarations), node.initializer);
setOriginalNode(declarationList, node.initializer);
// Adjust the source map range for the first declaration to align with the old
// emitter.
@@ -2304,15 +2288,15 @@ namespace ts {
createVariableDeclaration(
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
/*type*/ undefined,
createElementAccess(rhsReference, counter)
boundValue
)
]),
moveRangePos(initializer, -1)
moveRangePos(node.initializer, -1)
),
initializer
node.initializer
)
),
moveRangeEnd(initializer, -1)
moveRangeEnd(node.initializer, -1)
)
);
}
@@ -2320,25 +2304,14 @@ namespace ts {
else {
// Initializer is an expression. Emit the expression in the body, so that it's
// evaluated on every iteration.
const assignment = createAssignment(initializer, elementAccess);
const assignment = createAssignment(node.initializer, boundValue);
if (isDestructuringAssignment(assignment)) {
// This is a destructuring pattern, so we flatten the destructuring instead.
statements.push(
createStatement(
flattenDestructuringAssignment(
assignment,
visitor,
context,
FlattenLevel.All
)
)
);
aggregateTransformFlags(assignment);
statements.push(createStatement(visitBinaryExpression(assignment, /*needsDestructuringValue*/ false)));
}
else {
// Currently there is not way to check that assignment is binary expression of destructing assignment
// so we have to cast never type to binaryExpression
(<BinaryExpression>assignment).end = initializer.end;
statements.push(setTextRange(createStatement(assignment), moveRangeEnd(initializer, -1)));
assignment.end = node.initializer.end;
statements.push(setTextRange(createStatement(visitNode(assignment, visitor, isExpression)), moveRangeEnd(node.initializer, -1)));
}
}
@@ -2348,7 +2321,7 @@ namespace ts {
addRange(statements, convertedLoopBodyStatements);
}
else {
const statement = visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock);
const statement = visitNode(node.statement, visitor, isStatement, liftToBlock);
if (isBlock(statement)) {
addRange(statements, statement.statements);
bodyLocation = statement;
@@ -2359,38 +2332,82 @@ namespace ts {
}
}
// The old emitter does not emit source maps for the block.
// We add the location to preserve comments.
return setEmitFlags(
setTextRange(
createBlock(
setTextRange(createNodeArray(statements), statementsLocation),
/*multiLine*/ true
),
bodyLocation,
),
EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps
);
}
function convertForOfStatementForArray(node: ForOfStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
// The following ES6 code:
//
// for (let v of expr) { }
//
// should be emitted as
//
// for (var _i = 0, _a = expr; _i < _a.length; _i++) {
// var v = _a[_i];
// }
//
// where _a and _i are temps emitted to capture the RHS and the counter,
// respectively.
// When the left hand side is an expression instead of a let declaration,
// the "let v" is not emitted.
// When the left hand side is a let/const, the v is renamed if there is
// another v in scope.
// Note that all assignments to the LHS are emitted in the body, including
// all destructuring.
// Note also that because an extra statement is needed to assign to the LHS,
// for-of bodies are always emitted as blocks.
const expression = visitNode(node.expression, visitor, isExpression);
// In the case where the user wrote an identifier as the RHS, like this:
//
// for (let v of arr) { }
//
// we don't want to emit a temporary variable for the RHS, just use it directly.
const counter = createLoopVariable();
const rhsReference = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined);
// The old emitter does not emit source maps for the expression
setEmitFlags(expression, EmitFlags.NoSourceMap | getEmitFlags(expression));
// The old emitter does not emit source maps for the block.
// We add the location to preserve comments.
const body = createBlock(setTextRange(createNodeArray(statements), /*location*/ statementsLocation));
setTextRange(body, bodyLocation);
setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps);
const forStatement = createFor(
setEmitFlags(
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0)), moveRangePos(node.expression, -1)),
setTextRange(createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression)
]),
const forStatement = setTextRange(
createFor(
/*initializer*/ setEmitFlags(
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0)), moveRangePos(node.expression, -1)),
setTextRange(createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression)
]),
node.expression
),
EmitFlags.NoHoisting
),
/*condition*/ setTextRange(
createLessThan(
counter,
createPropertyAccess(rhsReference, "length")
),
node.expression
),
EmitFlags.NoHoisting
/*incrementor*/ setTextRange(createPostfixIncrement(counter), node.expression),
/*statement*/ convertForOfStatementHead(
node,
createElementAccess(rhsReference, counter),
convertedLoopBodyStatements
)
),
setTextRange(
createLessThan(
counter,
createPropertyAccess(rhsReference, "length")
),
node.expression
),
setTextRange(
createPostfixIncrement(counter),
node.expression
),
body
/*location*/ node
);
// Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter.
@@ -2399,18 +2416,110 @@ namespace ts {
return restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel);
}
function visitIterationStatement(node: IterationStatement, outermostLabeledStatement: LabeledStatement) {
switch (node.kind) {
case SyntaxKind.DoStatement:
case SyntaxKind.WhileStatement:
return visitDoOrWhileStatement(<DoStatement | WhileStatement>node, outermostLabeledStatement);
case SyntaxKind.ForStatement:
return visitForStatement(<ForStatement>node, outermostLabeledStatement);
case SyntaxKind.ForInStatement:
return visitForInStatement(<ForInStatement>node, outermostLabeledStatement);
case SyntaxKind.ForOfStatement:
return visitForOfStatement(<ForOfStatement>node, outermostLabeledStatement);
}
function convertForOfStatementForIterable(node: ForOfStatement, outermostLabeledStatement: LabeledStatement, convertedLoopBodyStatements: Statement[]): Statement {
const expression = visitNode(node.expression, visitor, isExpression);
const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined);
const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined);
const errorRecord = createUniqueName("e");
const catchVariable = getGeneratedNameForNode(errorRecord);
const returnMethod = createTempVariable(/*recordTempVariable*/ undefined);
const values = createValuesHelper(context, expression, node.expression);
const next = createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, []);
hoistVariableDeclaration(errorRecord);
hoistVariableDeclaration(returnMethod);
const forStatement = setEmitFlags(
setTextRange(
createFor(
/*initializer*/ setEmitFlags(
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, values), node.expression),
createVariableDeclaration(result, /*type*/ undefined, next)
]),
node.expression
),
EmitFlags.NoHoisting
),
/*condition*/ createLogicalNot(createPropertyAccess(result, "done")),
/*incrementor*/ createAssignment(result, next),
/*statement*/ convertForOfStatementHead(
node,
createPropertyAccess(result, "value"),
convertedLoopBodyStatements
)
),
/*location*/ node
),
EmitFlags.NoTokenTrailingSourceMaps
);
return createTry(
createBlock([
restoreEnclosingLabel(
forStatement,
outermostLabeledStatement,
convertedLoopState && resetLabel
)
]),
createCatchClause(createVariableDeclaration(catchVariable),
setEmitFlags(
createBlock([
createStatement(
createAssignment(
errorRecord,
createObjectLiteral([
createPropertyAssignment("error", catchVariable)
])
)
)
]),
EmitFlags.SingleLine
)
),
createBlock([
createTry(
/*tryBlock*/ createBlock([
setEmitFlags(
createIf(
createLogicalAnd(
createLogicalAnd(
result,
createLogicalNot(
createPropertyAccess(result, "done")
)
),
createAssignment(
returnMethod,
createPropertyAccess(iterator, "return")
)
),
createStatement(
createFunctionCall(returnMethod, iterator, [])
)
),
EmitFlags.SingleLine
),
]),
/*catchClause*/ undefined,
/*finallyBlock*/ setEmitFlags(
createBlock([
setEmitFlags(
createIf(
errorRecord,
createThrow(
createPropertyAccess(errorRecord, "error")
)
),
EmitFlags.SingleLine
)
]),
EmitFlags.SingleLine
)
)
])
);
}
/**
@@ -2570,7 +2679,7 @@ namespace ts {
}
startLexicalEnvironment();
let loopBody = visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock);
let loopBody = visitNode(node.statement, visitor, isStatement, liftToBlock);
const lexicalEnvironment = endLexicalEnvironment();
const currentState = convertedLoopState;
@@ -2712,6 +2821,7 @@ namespace ts {
}
const convertedLoopBodyStatements = generateCallToConvertedLoop(functionName, loopParameters, currentState, isAsyncBlockContainingAwait);
let loop: Statement;
if (convert) {
loop = convert(node, outermostLabeledStatement, convertedLoopBodyStatements);
@@ -3239,15 +3349,30 @@ namespace ts {
)
);
if (segments.length === 1) {
const firstElement = elements[0];
return needsUniqueCopy && isSpreadExpression(firstElement) && firstElement.expression.kind !== SyntaxKind.ArrayLiteralExpression
? createArraySlice(segments[0])
: segments[0];
}
if (compilerOptions.downlevelIteration) {
if (segments.length === 1) {
const firstSegment = segments[0];
if (isCallExpression(firstSegment)
&& isIdentifier(firstSegment.expression)
&& (getEmitFlags(firstSegment.expression) & EmitFlags.HelperName)
&& firstSegment.expression.text === "___spread") {
return segments[0];
}
}
// Rewrite using the pattern <segment0>.concat(<segment1>, <segment2>, ...)
return createArrayConcat(segments.shift(), segments);
return createSpreadHelper(context, segments);
}
else {
if (segments.length === 1) {
const firstElement = elements[0];
return needsUniqueCopy && isSpreadExpression(firstElement) && firstElement.expression.kind !== SyntaxKind.ArrayLiteralExpression
? createArraySlice(segments[0])
: segments[0];
}
// Rewrite using the pattern <segment0>.concat(<segment1>, <segment2>, ...)
return createArrayConcat(segments.shift(), segments);
}
}
function partitionSpread(node: Expression) {
@@ -3549,7 +3674,7 @@ namespace ts {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
const original = getParseTreeNode(node, isIdentifier);
if (original && isNameOfDeclarationWithCollidingName(original)) {
return getGeneratedNameForNode(original);
return setTextRange(getGeneratedNameForNode(original), node);
}
}
@@ -3602,7 +3727,7 @@ namespace ts {
if (enabledSubstitutions & ES2015SubstitutionFlags.BlockScopedBindings) {
const declaration = resolver.getReferencedDeclarationWithCollidingName(node);
if (declaration) {
return getGeneratedNameForNode(declaration.name);
return setTextRange(getGeneratedNameForNode(declaration.name), node);
}
}
+94 -116
View File
@@ -14,7 +14,7 @@ namespace ts {
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment,
endLexicalEnvironment
} = context;
const resolver = context.getEmitResolver();
@@ -34,7 +34,7 @@ namespace ts {
* This keeps track of containers where `super` is valid, for use with
* just-in-time substitution for `super` expressions inside of async methods.
*/
let currentSuperContainer: SuperContainer;
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
// Save the previous transformation hooks.
const previousOnEmitNode = context.onEmitNode;
@@ -71,23 +71,18 @@ namespace ts {
return undefined;
case SyntaxKind.AwaitExpression:
// ES2017 'await' expressions must be transformed for targets < ES2017.
return visitAwaitExpression(<AwaitExpression>node);
case SyntaxKind.MethodDeclaration:
// ES2017 method declarations may be 'async'
return visitMethodDeclaration(<MethodDeclaration>node);
case SyntaxKind.FunctionDeclaration:
// ES2017 function declarations may be 'async'
return visitFunctionDeclaration(<FunctionDeclaration>node);
case SyntaxKind.FunctionExpression:
// ES2017 function expressions may be 'async'
return visitFunctionExpression(<FunctionExpression>node);
case SyntaxKind.ArrowFunction:
// ES2017 arrow functions may be 'async'
return visitArrowFunction(<ArrowFunction>node);
default:
@@ -128,11 +123,12 @@ namespace ts {
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
isAsyncFunctionLike(node)
getFunctionFlags(node) & FunctionFlags.Async
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
@@ -151,11 +147,12 @@ namespace ts {
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
isAsyncFunctionLike(node)
getFunctionFlags(node) & FunctionFlags.Async
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
@@ -170,17 +167,15 @@ namespace ts {
* @param node The node to visit.
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
if (nodeIsMissing(node.body)) {
return createOmittedExpression();
}
return updateFunctionExpression(
node,
/*modifiers*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
isAsyncFunctionLike(node)
getFunctionFlags(node) & FunctionFlags.Async
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
@@ -201,7 +196,7 @@ namespace ts {
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
isAsyncFunctionLike(node)
getFunctionFlags(node) & FunctionFlags.Async
? transformAsyncFunctionBody(node)
: visitFunctionBody(node.body, visitor, context)
);
@@ -320,6 +315,44 @@ namespace ts {
}
}
/**
* Hook for node emit.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
if (superContainerFlags !== enclosingSuperContainerFlags) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = superContainerFlags;
previousOnEmitNode(hint, node, emitCallback);
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
return;
}
}
previousOnEmitNode(hint, node, emitCallback);
}
/**
* Hooks node substitutions.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression && enclosingSuperContainerFlags) {
return substituteExpression(<Expression>node);
}
return node;
}
function substituteExpression(node: Expression) {
switch (node.kind) {
case SyntaxKind.PropertyAccessExpression:
@@ -327,62 +360,45 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
return substituteElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.CallExpression:
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper) {
return substituteCallExpression(<CallExpression>node);
}
break;
return substituteCallExpression(<CallExpression>node);
}
return node;
}
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
createLiteral(node.name.text),
flags,
node
);
}
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
createLiteral(node.name.text),
node
);
}
return node;
}
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && node.expression.kind === SyntaxKind.SuperKeyword) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
return createSuperAccessInAsyncMethod(
node.argumentExpression,
flags,
node
);
}
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
node.argumentExpression,
node
);
}
return node;
}
function substituteCallExpression(node: CallExpression): Expression {
const expression = node.expression;
if (isSuperProperty(expression)) {
const flags = getSuperContainerAsyncMethodFlags();
if (flags) {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
...node.arguments
]
);
}
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
...node.arguments
]
);
}
return node;
}
@@ -396,44 +412,8 @@ namespace ts {
|| kind === SyntaxKind.SetAccessor;
}
/**
* Hook for node emit.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const savedCurrentSuperContainer = currentSuperContainer;
currentSuperContainer = node;
previousOnEmitNode(hint, node, emitCallback);
currentSuperContainer = savedCurrentSuperContainer;
}
else {
previousOnEmitNode(hint, node, emitCallback);
}
}
/**
* Hooks node substitutions.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
return node;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
@@ -457,15 +437,26 @@ namespace ts {
);
}
}
function getSuperContainerAsyncMethodFlags() {
return currentSuperContainer !== undefined
&& resolver.getNodeCheckFlags(currentSuperContainer) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
}
}
const awaiterHelper: EmitHelper = {
name: "typescript:awaiter",
scoped: false,
priority: 5,
text: `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};`
};
function createAwaiterHelper(context: TransformationContext, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression, body: Block) {
context.requestEmitHelper(awaiterHelper);
const generatorFunc = createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
@@ -491,35 +482,22 @@ namespace ts {
);
}
const awaiterHelper: EmitHelper = {
name: "typescript:awaiter",
scoped: false,
priority: 5,
text: `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};`
};
const asyncSuperHelper: EmitHelper = {
export const asyncSuperHelper: EmitHelper = {
name: "typescript:async-super",
scoped: true,
text: `
const _super = name => super[name];`
const _super = name => super[name];
`
};
const advancedAsyncSuperHelper: EmitHelper = {
export const advancedAsyncSuperHelper: EmitHelper = {
name: "typescript:advanced-async-super",
scoped: true,
text: `
const _super = (function (geti, seti) {
const cache = Object.create(null);
return name => cache[name] || (cache[name] = { get value() { return geti(name); }, set value(v) { seti(name, v); } });
})(name => super[name], (name, value) => super[name] = value);`
})(name => super[name], (name, value) => super[name] = value);
`
};
}
+613 -76
View File
@@ -1,13 +1,35 @@
/// <reference path="../factory.ts" />
/// <reference path="../visitor.ts" />
/// <reference path="es2017.ts" />
/*@internal*/
namespace ts {
const enum ESNextSubstitutionFlags {
/** Enables substitutions for async methods with `super` calls. */
AsyncMethodsWithSuper = 1 << 0
}
export function transformESNext(context: TransformationContext) {
const {
resumeLexicalEnvironment,
endLexicalEnvironment
endLexicalEnvironment,
hoistVariableDeclaration
} = context;
const resolver = context.getEmitResolver();
const compilerOptions = context.getCompilerOptions();
const languageVersion = getEmitScriptTarget(compilerOptions);
const previousOnEmitNode = context.onEmitNode;
context.onEmitNode = onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
context.onSubstituteNode = onSubstituteNode;
let enabledSubstitutions: ESNextSubstitutionFlags;
let enclosingFunctionFlags: FunctionFlags;
let enclosingSuperContainerFlags: NodeCheckFlags = 0;
return transformSourceFile;
function transformSourceFile(node: SourceFile) {
@@ -28,12 +50,25 @@ namespace ts {
return visitorWorker(node, /*noDestructuringValue*/ true);
}
function visitorNoAsyncModifier(node: Node): VisitResult<Node> {
if (node.kind === SyntaxKind.AsyncKeyword) {
return undefined;
}
return node;
}
function visitorWorker(node: Node, noDestructuringValue: boolean): VisitResult<Node> {
if ((node.transformFlags & TransformFlags.ContainsESNext) === 0) {
return node;
}
switch (node.kind) {
case SyntaxKind.AwaitExpression:
return visitAwaitExpression(node as AwaitExpression);
case SyntaxKind.YieldExpression:
return visitYieldExpression(node as YieldExpression);
case SyntaxKind.LabeledStatement:
return visitLabeledStatement(node as LabeledStatement);
case SyntaxKind.ObjectLiteralExpression:
return visitObjectLiteralExpression(node as ObjectLiteralExpression);
case SyntaxKind.BinaryExpression:
@@ -41,7 +76,7 @@ namespace ts {
case SyntaxKind.VariableDeclaration:
return visitVariableDeclaration(node as VariableDeclaration);
case SyntaxKind.ForOfStatement:
return visitForOfStatement(node as ForOfStatement);
return visitForOfStatement(node as ForOfStatement, /*outermostLabeledStatement*/ undefined);
case SyntaxKind.ForStatement:
return visitForStatement(node as ForStatement);
case SyntaxKind.VoidExpression:
@@ -71,6 +106,52 @@ namespace ts {
}
}
function visitAwaitExpression(node: AwaitExpression) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
const expression = visitNode(node.expression, visitor, isExpression);
return setOriginalNode(
setTextRange(
createYield(
/*asteriskToken*/ undefined,
createArrayLiteral([createLiteral("await"), expression])
),
/*location*/ node
),
node
);
}
return visitEachChild(node, visitor, context);
}
function visitYieldExpression(node: YieldExpression) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
const expression = visitNode(node.expression, visitor, isExpression);
return updateYield(
node,
node.asteriskToken,
node.asteriskToken
? createAsyncDelegatorHelper(context, expression, expression)
: createArrayLiteral(
expression
? [createLiteral("yield"), expression]
: [createLiteral("yield")]
)
);
}
return visitEachChild(node, visitor, context);
}
function visitLabeledStatement(node: LabeledStatement) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
const statement = unwrapInnermostStatementOfLabel(node);
if (statement.kind === SyntaxKind.ForOfStatement && (<ForOfStatement>statement).awaitModifier) {
return visitForOfStatement(<ForOfStatement>statement, node);
}
return restoreEnclosingLabel(visitEachChild(node, visitor, context), node);
}
return visitEachChild(node, visitor, context);
}
function chunkObjectLiteralElements(elements: ObjectLiteralElement[]): Expression[] {
let chunkObject: (ShorthandPropertyAssignment | PropertyAssignment)[];
const objects: Expression[] = [];
@@ -189,67 +270,199 @@ namespace ts {
*
* @param node A ForOfStatement.
*/
function visitForOfStatement(node: ForOfStatement): VisitResult<Statement> {
let leadingStatements: Statement[];
let temp: Identifier;
const initializer = skipParentheses(node.initializer);
if (initializer.transformFlags & TransformFlags.ContainsObjectRest) {
if (isVariableDeclarationList(initializer)) {
temp = createTempVariable(/*recordTempVariable*/ undefined);
const firstDeclaration = firstOrUndefined(initializer.declarations);
const declarations = flattenDestructuringBinding(
firstDeclaration,
visitor,
context,
FlattenLevel.ObjectRest,
temp,
/*doNotRecordTempVariablesInLine*/ false,
/*skipInitializer*/ true,
);
if (some(declarations)) {
const statement = createVariableStatement(
/*modifiers*/ undefined,
updateVariableDeclarationList(initializer, declarations),
);
setTextRange(statement, initializer);
leadingStatements = append(leadingStatements, statement);
}
}
else if (isAssignmentPattern(initializer)) {
temp = createTempVariable(/*recordTempVariable*/ undefined);
const expression = flattenDestructuringAssignment(
aggregateTransformFlags(
setTextRange(
createAssignment(initializer, temp),
node.initializer
)
),
visitor,
context,
FlattenLevel.ObjectRest
);
leadingStatements = append(leadingStatements, setTextRange(createStatement(expression), node.initializer));
}
function visitForOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement): VisitResult<Statement> {
if (node.initializer.transformFlags & TransformFlags.ContainsObjectRest) {
node = transformForOfStatementWithObjectRest(node);
}
if (temp) {
const expression = visitNode(node.expression, visitor, isExpression);
const statement = visitNode(node.statement, visitor, isStatement);
const block = isBlock(statement)
? updateBlock(statement, setTextRange(createNodeArray(concatenate(leadingStatements, statement.statements)), statement.statements))
: setTextRange(createBlock(append(leadingStatements, statement), /*multiLine*/ true), statement);
if (node.awaitModifier) {
return transformForAwaitOfStatement(node, outermostLabeledStatement);
}
else {
return restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement);
}
}
function transformForOfStatementWithObjectRest(node: ForOfStatement) {
const initializerWithoutParens = skipParentheses(node.initializer) as ForInitializer;
if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) {
let bodyLocation: TextRange;
let statementsLocation: TextRange;
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)];
if (isBlock(node.statement)) {
addRange(statements, node.statement.statements);
bodyLocation = node.statement;
statementsLocation = node.statement.statements;
}
return updateForOf(
node,
node.awaitModifier,
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(temp), node.initializer)
], NodeFlags.Let),
createVariableDeclarationList(
[
setTextRange(createVariableDeclaration(temp), node.initializer)
],
NodeFlags.Let
),
node.initializer
),
expression,
block
node.expression,
setTextRange(
createBlock(
setTextRange(createNodeArray(statements), statementsLocation),
/*multiLine*/ true
),
bodyLocation
)
);
}
return visitEachChild(node, visitor, context);
return node;
}
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) {
const binding = createForOfBindingStatement(node.initializer, boundValue);
let bodyLocation: TextRange;
let statementsLocation: TextRange;
const statements: Statement[] = [visitNode(binding, visitor, isStatement)];
const statement = visitNode(node.statement, visitor, isStatement);
if (isBlock(statement)) {
addRange(statements, statement.statements);
bodyLocation = statement;
statementsLocation = statement.statements;
}
else {
statements.push(statement);
}
return setEmitFlags(
setTextRange(
createBlock(
setTextRange(createNodeArray(statements), statementsLocation),
/*multiLine*/ true
),
bodyLocation
),
EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps
);
}
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement) {
const expression = visitNode(node.expression, visitor, isExpression);
const iterator = isIdentifier(expression) ? getGeneratedNameForNode(expression) : createTempVariable(/*recordTempVariable*/ undefined);
const result = isIdentifier(expression) ? getGeneratedNameForNode(iterator) : createTempVariable(/*recordTempVariable*/ undefined);
const errorRecord = createUniqueName("e");
const catchVariable = getGeneratedNameForNode(errorRecord);
const returnMethod = createTempVariable(/*recordTempVariable*/ undefined);
const values = createAsyncValuesHelper(context, expression, /*location*/ node.expression);
const next = createYield(
/*asteriskToken*/ undefined,
enclosingFunctionFlags & FunctionFlags.Generator
? createArrayLiteral([
createLiteral("await"),
createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, [])
])
: createCall(createPropertyAccess(iterator, "next" ), /*typeArguments*/ undefined, [])
);
hoistVariableDeclaration(errorRecord);
hoistVariableDeclaration(returnMethod);
const forStatement = setEmitFlags(
setTextRange(
createFor(
/*initializer*/ setEmitFlags(
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, values), node.expression),
createVariableDeclaration(result, /*type*/ undefined, next)
]),
node.expression
),
EmitFlags.NoHoisting
),
/*condition*/ createLogicalNot(createPropertyAccess(result, "done")),
/*incrementor*/ createAssignment(result, next),
/*statement*/ convertForOfStatementHead(node, createPropertyAccess(result, "value"))
),
/*location*/ node
),
EmitFlags.NoTokenTrailingSourceMaps
);
return createTry(
createBlock([
restoreEnclosingLabel(
forStatement,
outermostLabeledStatement
)
]),
createCatchClause(
createVariableDeclaration(catchVariable),
setEmitFlags(
createBlock([
createStatement(
createAssignment(
errorRecord,
createObjectLiteral([
createPropertyAssignment("error", catchVariable)
])
)
)
]),
EmitFlags.SingleLine
)
),
createBlock([
createTry(
/*tryBlock*/ createBlock([
setEmitFlags(
createIf(
createLogicalAnd(
createLogicalAnd(
result,
createLogicalNot(
createPropertyAccess(result, "done")
)
),
createAssignment(
returnMethod,
createPropertyAccess(iterator, "return")
)
),
createStatement(
createYield(
/*asteriskToken*/ undefined,
enclosingFunctionFlags & FunctionFlags.Generator
? createArrayLiteral([
createLiteral("await"),
createFunctionCall(returnMethod, iterator, [])
])
: createFunctionCall(returnMethod, iterator, [])
)
)
),
EmitFlags.SingleLine
)
]),
/*catchClause*/ undefined,
/*finallyBlock*/ setEmitFlags(
createBlock([
setEmitFlags(
createIf(
errorRecord,
createThrow(
createPropertyAccess(errorRecord, "error")
)
),
EmitFlags.SingleLine
)
]),
EmitFlags.SingleLine
)
)
])
);
}
function visitParameter(node: ParameterDeclaration): ParameterDeclaration {
@@ -270,17 +483,23 @@ namespace ts {
}
function visitConstructorDeclaration(node: ConstructorDeclaration) {
return updateConstructor(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateConstructor(
node,
/*decorators*/ undefined,
node.modifiers,
visitParameterList(node.parameters, visitor, context),
transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitGetAccessorDeclaration(node: GetAccessorDeclaration) {
return updateGetAccessor(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateGetAccessor(
node,
/*decorators*/ undefined,
node.modifiers,
@@ -289,10 +508,14 @@ namespace ts {
/*type*/ undefined,
transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitSetAccessorDeclaration(node: SetAccessorDeclaration) {
return updateSetAccessor(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateSetAccessor(
node,
/*decorators*/ undefined,
node.modifiers,
@@ -300,36 +523,62 @@ namespace ts {
visitParameterList(node.parameters, visitor, context),
transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitMethodDeclaration(node: MethodDeclaration) {
return updateMethod(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateMethod(
node,
/*decorators*/ undefined,
node.modifiers,
enclosingFunctionFlags & FunctionFlags.Generator
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
: node.modifiers,
enclosingFunctionFlags & FunctionFlags.Async
? undefined
: node.asteriskToken,
visitNode(node.name, visitor, isPropertyName),
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
? transformAsyncGeneratorFunctionBody(node)
: transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitFunctionDeclaration(node: FunctionDeclaration) {
return updateFunctionDeclaration(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateFunctionDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
enclosingFunctionFlags & FunctionFlags.Generator
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
: node.modifiers,
enclosingFunctionFlags & FunctionFlags.Async
? undefined
: node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
? transformAsyncGeneratorFunctionBody(node)
: transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitArrowFunction(node: ArrowFunction) {
return updateArrowFunction(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateArrowFunction(
node,
node.modifiers,
/*typeParameters*/ undefined,
@@ -337,25 +586,92 @@ namespace ts {
/*type*/ undefined,
transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function visitFunctionExpression(node: FunctionExpression) {
return updateFunctionExpression(
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateFunctionExpression(
node,
node.modifiers,
enclosingFunctionFlags & FunctionFlags.Generator
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
: node.modifiers,
enclosingFunctionFlags & FunctionFlags.Async
? undefined
: node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node)
enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator
? transformAsyncGeneratorFunctionBody(node)
: transformFunctionBody(node)
);
enclosingFunctionFlags = savedEnclosingFunctionFlags;
return updated;
}
function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
resumeLexicalEnvironment();
const statements: Statement[] = [];
const statementOffset = addPrologueDirectives(statements, node.body.statements, /*ensureUseStrict*/ false, visitor);
appendObjectRestAssignmentsIfNeeded(statements, node);
statements.push(
createReturn(
createAsyncGeneratorHelper(
context,
createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
node.name && getGeneratedNameForNode(node.name),
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
updateBlock(
node.body,
visitLexicalEnvironment(node.body.statements, visitor, context, statementOffset)
)
)
)
)
);
addRange(statements, endLexicalEnvironment());
const block = updateBlock(node.body, statements);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
if (languageVersion >= ScriptTarget.ES2015) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, advancedAsyncSuperHelper);
}
else if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuper) {
enableSubstitutionForAsyncMethodsWithSuper();
addEmitHelper(block, asyncSuperHelper);
}
}
return block;
}
function transformFunctionBody(node: FunctionDeclaration | FunctionExpression | ConstructorDeclaration | MethodDeclaration | AccessorDeclaration): FunctionBody;
function transformFunctionBody(node: ArrowFunction): ConciseBody;
function transformFunctionBody(node: FunctionLikeDeclaration): ConciseBody {
resumeLexicalEnvironment();
let leadingStatements: Statement[];
const leadingStatements = appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node);
const body = visitNode(node.body, visitor, isConciseBody);
const trailingStatements = endLexicalEnvironment();
if (some(leadingStatements) || some(trailingStatements)) {
const block = convertToFunctionBody(body, /*multiLine*/ true);
return updateBlock(block, setTextRange(createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements)), block.statements));
}
return body;
}
function appendObjectRestAssignmentsIfNeeded(statements: Statement[], node: FunctionLikeDeclaration): Statement[] {
for (const parameter of node.parameters) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRest) {
const temp = getGeneratedNameForNode(parameter);
@@ -376,17 +692,153 @@ namespace ts {
)
);
setEmitFlags(statement, EmitFlags.CustomPrologue);
leadingStatements = append(leadingStatements, statement);
statements = append(statements, statement);
}
}
}
const body = visitNode(node.body, visitor, isConciseBody);
const trailingStatements = endLexicalEnvironment();
if (some(leadingStatements) || some(trailingStatements)) {
const block = convertToFunctionBody(body, /*multiLine*/ true);
return updateBlock(block, setTextRange(createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements)), block.statements));
return statements;
}
function enableSubstitutionForAsyncMethodsWithSuper() {
if ((enabledSubstitutions & ESNextSubstitutionFlags.AsyncMethodsWithSuper) === 0) {
enabledSubstitutions |= ESNextSubstitutionFlags.AsyncMethodsWithSuper;
// We need to enable substitutions for call, property access, and element access
// if we need to rewrite super calls.
context.enableSubstitution(SyntaxKind.CallExpression);
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.ElementAccessExpression);
// We need to be notified when entering and exiting declarations that bind super.
context.enableEmitNotification(SyntaxKind.ClassDeclaration);
context.enableEmitNotification(SyntaxKind.MethodDeclaration);
context.enableEmitNotification(SyntaxKind.GetAccessor);
context.enableEmitNotification(SyntaxKind.SetAccessor);
context.enableEmitNotification(SyntaxKind.Constructor);
}
}
/**
* Called by the printer just before a node is printed.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to be printed.
* @param emitCallback The callback used to emit the node.
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ESNextSubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const superContainerFlags = resolver.getNodeCheckFlags(node) & (NodeCheckFlags.AsyncMethodWithSuper | NodeCheckFlags.AsyncMethodWithSuperBinding);
if (superContainerFlags !== enclosingSuperContainerFlags) {
const savedEnclosingSuperContainerFlags = enclosingSuperContainerFlags;
enclosingSuperContainerFlags = superContainerFlags;
previousOnEmitNode(hint, node, emitCallback);
enclosingSuperContainerFlags = savedEnclosingSuperContainerFlags;
return;
}
}
previousOnEmitNode(hint, node, emitCallback);
}
/**
* Hooks node substitutions.
*
* @param hint The context for the emitter.
* @param node The node to substitute.
*/
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression && enclosingSuperContainerFlags) {
return substituteExpression(<Expression>node);
}
return node;
}
function substituteExpression(node: Expression) {
switch (node.kind) {
case SyntaxKind.PropertyAccessExpression:
return substitutePropertyAccessExpression(<PropertyAccessExpression>node);
case SyntaxKind.ElementAccessExpression:
return substituteElementAccessExpression(<ElementAccessExpression>node);
case SyntaxKind.CallExpression:
return substituteCallExpression(<CallExpression>node);
}
return node;
}
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
createLiteral(node.name.text),
node
);
}
return node;
}
function substituteElementAccessExpression(node: ElementAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return createSuperAccessInAsyncMethod(
node.argumentExpression,
node
);
}
return node;
}
function substituteCallExpression(node: CallExpression): Expression {
const expression = node.expression;
if (isSuperProperty(expression)) {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
...node.arguments
]
);
}
return node;
}
function isSuperContainer(node: Node) {
const kind = node.kind;
return kind === SyntaxKind.ClassDeclaration
|| kind === SyntaxKind.Constructor
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor;
}
function createSuperAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
"value"
),
location
);
}
else {
return setTextRange(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
location
);
}
return body;
}
}
@@ -418,4 +870,89 @@ namespace ts {
attributesSegments
);
}
const asyncGeneratorHelper: EmitHelper = {
name: "typescript:asyncGenerator",
scoped: false,
text: `
var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var g = generator.apply(thisArg, _arguments || []), q = [], c, i;
return i = { next: verb("next"), "throw": verb("throw"), "return": verb("return") }, i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { return function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]), next(); }); }; }
function next() { if (!c && q.length) resume((c = q.shift())[0], c[1]); }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(c[3], e); } }
function step(r) { r.done ? settle(c[2], r) : r.value[0] === "yield" ? settle(c[2], { value: r.value[1], done: false }) : Promise.resolve(r.value[1]).then(r.value[0] === "delegate" ? delegate : fulfill, reject); }
function delegate(r) { step(r.done ? r : { value: ["yield", r.value], done: false }); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { c = void 0, f(v), next(); }
};
`
};
function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression) {
context.requestEmitHelper(asyncGeneratorHelper);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {})).flags |= EmitFlags.AsyncFunctionBody;
return createCall(
getHelperName("__asyncGenerator"),
/*typeArguments*/ undefined,
[
createThis(),
createIdentifier("arguments"),
generatorFunc
]
);
}
const asyncDelegator: EmitHelper = {
name: "typescript:asyncDelegator",
scoped: false,
text: `
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
var i = { next: verb("next"), "throw": verb("throw", function (e) { throw e; }), "return": verb("return", function (v) { return { value: v, done: true }; }) };
return o = __asyncValues(o), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { return function (v) { return { value: ["delegate", (o[n] || f).call(o, v)], done: false }; }; }
};
`
};
function createAsyncDelegatorHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
context.requestEmitHelper(asyncDelegator);
return setTextRange(
createCall(
getHelperName("__asyncDelegator"),
/*typeArguments*/ undefined,
[expression]
),
location
);
}
const asyncValues: EmitHelper = {
name: "typescript:asyncValues",
scoped: false,
text: `
var __asyncValues = (this && this.__asyncIterator) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator];
return m ? m.call(o) : typeof __values === "function" ? __values(o) : o[Symbol.iterator]();
};
`
};
function createAsyncValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
context.requestEmitHelper(asyncValues);
return setTextRange(
createCall(
getHelperName("__asyncValues"),
/*typeArguments*/ undefined,
[expression]
),
location
);
}
}
+41 -31
View File
@@ -232,7 +232,7 @@ namespace ts {
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistFunctionDeclaration,
hoistVariableDeclaration,
hoistVariableDeclaration
} = context;
const compilerOptions = context.getCompilerOptions();
@@ -448,7 +448,7 @@ namespace ts {
*/
function visitFunctionDeclaration(node: FunctionDeclaration): Statement {
// Currently, we only support generators that were originally async functions.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken) {
node = setOriginalNode(
setTextRange(
createFunctionDeclaration(
@@ -498,7 +498,7 @@ namespace ts {
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
// Currently, we only support generators that were originally async functions.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
if (node.asteriskToken) {
node = setOriginalNode(
setTextRange(
createFunctionExpression(
@@ -936,11 +936,10 @@ namespace ts {
// .mark resumeLabel
// x = %sent%;
// NOTE: we are explicitly not handling YieldStar at this time.
const resumeLabel = defineLabel();
const expression = visitNode(node.expression, visitor, isExpression);
if (node.asteriskToken) {
emitYieldStar(expression, /*location*/ node);
emitYieldStar(createValuesHelper(context, expression, /*location*/ node), /*location*/ node);
}
else {
emitYield(expression, /*location*/ node);
@@ -978,9 +977,10 @@ namespace ts {
// ar = _a.concat([%sent%, 2]);
const numInitialElements = countInitialNodesWithoutYield(elements);
const temp = declareLocal();
let hasAssignedTemp = false;
let temp: Identifier;
if (numInitialElements > 0) {
temp = declareLocal();
const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements);
emitAssignment(temp,
createArrayLiteral(
@@ -990,11 +990,10 @@ namespace ts {
)
);
leadingElement = undefined;
hasAssignedTemp = true;
}
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
return hasAssignedTemp
return temp
? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)])
: setTextRange(
createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine),
@@ -1003,6 +1002,11 @@ namespace ts {
function reduceElement(expressions: Expression[], element: Expression) {
if (containsYield(element) && expressions.length > 0) {
const hasAssignedTemp = temp !== undefined;
if (!temp) {
temp = declareLocal();
}
emitAssignment(
temp,
hasAssignedTemp
@@ -1015,7 +1019,6 @@ namespace ts {
multiLine
)
);
hasAssignedTemp = true;
leadingElement = undefined;
expressions = [];
}
@@ -1227,7 +1230,7 @@ namespace ts {
case SyntaxKind.TryStatement:
return transformAndEmitTryStatement(<TryStatement>node);
default:
return emitStatement(visitNode(node, visitor, isStatement, /*optional*/ true));
return emitStatement(visitNode(node, visitor, isStatement));
}
}
@@ -1485,9 +1488,9 @@ namespace ts {
variables.length > 0
? inlineExpressions(map(variables, transformInitializedVariable))
: undefined,
visitNode(node.condition, visitor, isExpression, /*optional*/ true),
visitNode(node.incrementor, visitor, isExpression, /*optional*/ true),
visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, visitor, isStatement, liftToBlock)
);
}
else {
@@ -1609,7 +1612,7 @@ namespace ts {
node = updateForIn(node,
<Identifier>initializer.declarations[0].name,
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, visitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, visitor, isStatement, liftToBlock)
);
}
else {
@@ -1659,14 +1662,14 @@ namespace ts {
function transformAndEmitReturnStatement(node: ReturnStatement): void {
emitReturn(
visitNode(node.expression, visitor, isExpression, /*optional*/ true),
visitNode(node.expression, visitor, isExpression),
/*location*/ node
);
}
function visitReturnStatement(node: ReturnStatement) {
return createInlineReturn(
visitNode(node.expression, visitor, isExpression, /*optional*/ true),
visitNode(node.expression, visitor, isExpression),
/*location*/ node
);
}
@@ -1939,7 +1942,7 @@ namespace ts {
}
function substituteExpressionIdentifier(node: Identifier) {
if (renamedCatchVariables && renamedCatchVariables.has(node.text)) {
if (!isGeneratedIdentifier(node) && renamedCatchVariables && renamedCatchVariables.has(node.text)) {
const original = getOriginalNode(node);
if (isIdentifier(original) && original.parent) {
const declaration = resolver.getReferencedValueDeclaration(original);
@@ -1960,7 +1963,7 @@ namespace ts {
function cacheExpression(node: Expression): Identifier {
let temp: Identifier;
if (isGeneratedIdentifier(node)) {
if (isGeneratedIdentifier(node) || getEmitFlags(node) & EmitFlags.HelperName) {
return <Identifier>node;
}
@@ -2105,17 +2108,24 @@ namespace ts {
function beginCatchBlock(variable: VariableDeclaration): void {
Debug.assert(peekBlockKind() === CodeBlockKind.Exception);
const text = (<Identifier>variable.name).text;
const name = declareLocal(text);
if (!renamedCatchVariables) {
renamedCatchVariables = createMap<boolean>();
renamedCatchVariableDeclarations = [];
context.enableSubstitution(SyntaxKind.Identifier);
// generated identifiers should already be unique within a file
let name: Identifier;
if (isGeneratedIdentifier(variable.name)) {
name = variable.name;
hoistVariableDeclaration(variable.name);
}
else {
const text = (<Identifier>variable.name).text;
name = declareLocal(text);
if (!renamedCatchVariables) {
renamedCatchVariables = createMap<boolean>();
renamedCatchVariableDeclarations = [];
context.enableSubstitution(SyntaxKind.Identifier);
}
renamedCatchVariables.set(text, true);
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
renamedCatchVariables.set(text, true);
renamedCatchVariableDeclarations[getOriginalNodeId(variable)] = name;
}
const exception = <ExceptionBlock>peekBlock();
Debug.assert(exception.state < ExceptionBlockState.Catch);
@@ -2419,7 +2429,7 @@ namespace ts {
*/
function createInstruction(instruction: Instruction): NumericLiteral {
const literal = createLiteral(instruction);
literal.trailingComment = getInstructionName(instruction);
addSyntheticTrailingComment(literal, SyntaxKind.MultiLineCommentTrivia, getInstructionName(instruction));
return literal;
}
@@ -3229,8 +3239,8 @@ namespace ts {
priority: 6,
text: `
var __generator = (this && this.__generator) || function (thisArg, body) {
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t;
return { next: verb(0), "throw": verb(1), "return": verb(2) };
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
function verb(n) { return function (v) { return step([n, v]); }; }
function step(op) {
if (f) throw new TypeError("Generator is already executing.");
-5
View File
@@ -6,7 +6,6 @@
namespace ts {
export function transformJsx(context: TransformationContext) {
const compilerOptions = context.getCompilerOptions();
let currentSourceFile: SourceFile;
return transformSourceFile;
@@ -20,12 +19,8 @@ namespace ts {
return node;
}
currentSourceFile = node;
const visited = visitEachChild(node, visitor, context);
addEmitHelpers(visited, context.readEmitHelpers());
currentSourceFile = undefined;
return visited;
}
@@ -101,6 +101,7 @@ namespace ts {
if (isIdentifier(node) && hint === EmitHint.Expression) {
return substituteExpressionIdentifier(node);
}
return node;
}
+10 -6
View File
@@ -1,5 +1,6 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/// <reference path="../destructuring.ts" />
/*@internal*/
namespace ts {
@@ -88,13 +89,15 @@ namespace ts {
append(statements, createUnderscoreUnderscoreESModule());
}
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
addRange(statements, endLexicalEnvironment());
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
addRange(statements, endLexicalEnvironment());
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
if (currentModuleInfo.hasExportStarsToExportValues) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
addEmitHelper(updated, exportStarHelper);
}
return updated;
@@ -380,16 +383,16 @@ namespace ts {
}
// Visit each statement of the module body.
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true));
append(statements, visitNode(currentModuleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement));
addRange(statements, visitNodes(node.statements, sourceElementVisitor, isStatement, statementOffset));
// Append the 'export =' statement if provided.
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
// End the lexical environment for the module body
// and merge any new lexical declarations.
addRange(statements, endLexicalEnvironment());
// Append the 'export =' statement if provided.
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
const body = createBlock(statements, /*multiLine*/ true);
if (currentModuleInfo.hasExportStarsToExportValues) {
// If we have any `export * from ...` declarations
@@ -1334,6 +1337,7 @@ namespace ts {
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
return node;
}
+14 -11
View File
@@ -1,5 +1,6 @@
/// <reference path="../../factory.ts" />
/// <reference path="../../visitor.ts" />
/// <reference path="../destructuring.ts" />
/*@internal*/
namespace ts {
@@ -136,7 +137,6 @@ namespace ts {
contextObject = undefined;
hoistedStatements = undefined;
enclosingBlockScopedContainer = undefined;
return aggregateTransformFlags(updated);
}
@@ -245,7 +245,7 @@ namespace ts {
);
// Visit the synthetic external helpers import declaration if present
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement, /*optional*/ true);
visitNode(moduleInfo.externalHelpersImportDeclaration, sourceElementVisitor, isStatement);
// Visit the statements of the source file, emitting any transformations into
// the `executeStatements` array. We do this *before* we fill the `setters` array
@@ -669,6 +669,7 @@ namespace ts {
node,
node.decorators,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
visitNodes(node.parameters, destructuringVisitor, isParameterDeclaration),
@@ -1218,8 +1219,8 @@ namespace ts {
node = updateFor(
node,
visitForInitializer(node.initializer),
visitNode(node.condition, destructuringVisitor, isExpression, /*optional*/ true),
visitNode(node.incrementor, destructuringVisitor, isExpression, /*optional*/ true),
visitNode(node.condition, destructuringVisitor, isExpression),
visitNode(node.incrementor, destructuringVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement)
);
@@ -1240,7 +1241,7 @@ namespace ts {
node,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@@ -1258,9 +1259,10 @@ namespace ts {
node = updateForOf(
node,
node.awaitModifier,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@@ -1305,7 +1307,7 @@ namespace ts {
function visitDoStatement(node: DoStatement): VisitResult<Statement> {
return updateDo(
node,
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock),
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock),
visitNode(node.expression, destructuringVisitor, isExpression)
);
}
@@ -1319,7 +1321,7 @@ namespace ts {
return updateWhile(
node,
visitNode(node.expression, destructuringVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
);
}
@@ -1332,7 +1334,7 @@ namespace ts {
return updateLabel(
node,
node.label,
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
);
}
@@ -1345,7 +1347,7 @@ namespace ts {
return updateWith(
node,
visitNode(node.expression, destructuringVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, /*optional*/ false, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
);
}
@@ -1492,7 +1494,7 @@ namespace ts {
* @param node The destructuring target.
*/
function hasExportedReferenceInDestructuringTarget(node: Expression | ObjectLiteralElementLike): boolean {
if (isAssignmentExpression(node)) {
if (isAssignmentExpression(node, /*excludeCompoundAssignment*/ true)) {
return hasExportedReferenceInDestructuringTarget(node.left);
}
else if (isSpreadExpression(node)) {
@@ -1625,6 +1627,7 @@ namespace ts {
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
}
return node;
}
+86 -70
View File
@@ -872,7 +872,7 @@ namespace ts {
* @param hasExtendsClause A value indicating whether the class has an extends clause.
*/
function transformConstructorBody(node: ClassExpression | ClassDeclaration, constructor: ConstructorDeclaration, hasExtendsClause: boolean) {
const statements: Statement[] = [];
let statements: Statement[] = [];
let indexOfFirstStatement = 0;
resumeLexicalEnvironment();
@@ -930,7 +930,7 @@ namespace ts {
}
// End the lexical environment.
addRange(statements, endLexicalEnvironment());
statements = mergeLexicalEnvironment(statements, endLexicalEnvironment());
return setTextRange(
createBlock(
setTextRange(
@@ -1651,7 +1651,7 @@ namespace ts {
if (isFunctionLike(node) && node.type) {
return serializeTypeNode(node.type);
}
else if (isAsyncFunctionLike(node)) {
else if (isAsyncFunction(node)) {
return createIdentifier("Promise");
}
@@ -2019,7 +2019,13 @@ namespace ts {
return undefined;
}
return visitEachChild(node, visitor, context);
return updateConstructor(
node,
visitNodes(node.decorators, visitor, isDecorator),
visitNodes(node.modifiers, visitor, isModifier),
visitParameterList(node.parameters, visitor, context),
visitFunctionBody(node.body, visitor, context)
);
}
/**
@@ -2040,6 +2046,7 @@ namespace ts {
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
visitPropertyNameOfClassElement(node),
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
@@ -2144,6 +2151,7 @@ namespace ts {
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
@@ -2167,17 +2175,18 @@ namespace ts {
* @param node The function expression node.
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
if (nodeIsMissing(node.body)) {
if (!shouldEmitFunctionLikeDeclaration(node)) {
return createOmittedExpression();
}
const updated = updateFunctionExpression(
node,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
visitFunctionBody(node.body, visitor, context)
visitFunctionBody(node.body, visitor, context) || createBlock([])
);
return updated;
}
@@ -2833,7 +2842,7 @@ namespace ts {
}
// Elide the declaration if the import clause was elided.
const importClause = visitNode(node.importClause, visitImportClause, isImportClause, /*optional*/ true);
const importClause = visitNode(node.importClause, visitImportClause, isImportClause);
return importClause
? updateImportDeclaration(
node,
@@ -2852,7 +2861,7 @@ namespace ts {
function visitImportClause(node: ImportClause): VisitResult<ImportClause> {
// Elide the import clause if we elide both its name and its named bindings.
const name = resolver.isReferencedAliasDeclaration(node) ? node.name : undefined;
const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings, /*optional*/ true);
const namedBindings = visitNode(node.namedBindings, visitNamedImportBindings, isNamedImportBindings);
return (name || namedBindings) ? updateImportClause(node, name, namedBindings) : undefined;
}
@@ -2914,7 +2923,7 @@ namespace ts {
}
// Elide the export declaration if all of its named exports are elided.
const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports, /*optional*/ true);
const exportClause = visitNode(node.exportClause, visitNamedExports, isNamedExports);
return exportClause
? updateExportDeclaration(
node,
@@ -3187,6 +3196,11 @@ namespace ts {
*/
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
const savedApplicableSubstitutions = applicableSubstitutions;
const savedCurrentSourceFile = currentSourceFile;
if (isSourceFile(node)) {
currentSourceFile = node;
}
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) {
applicableSubstitutions |= TypeScriptSubstitutionFlags.NamespaceExports;
@@ -3199,6 +3213,7 @@ namespace ts {
previousOnEmitNode(hint, node, emitCallback);
applicableSubstitutions = savedApplicableSubstitutions;
currentSourceFile = savedCurrentSourceFile;
}
/**
@@ -3312,17 +3327,18 @@ namespace ts {
function substituteConstantValue(node: PropertyAccessExpression | ElementAccessExpression): LeftHandSideExpression {
const constantValue = tryGetConstEnumValue(node);
if (constantValue !== undefined) {
// track the constant value on the node for the printer in needsDotDotForPropertyAccess
setConstantValue(node, constantValue);
const substitute = createLiteral(constantValue);
setSourceMapRange(substitute, node);
setCommentRange(substitute, node);
if (!compilerOptions.removeComments) {
const propertyName = isPropertyAccessExpression(node)
? declarationNameToString(node.name)
: getTextOfNode(node.argumentExpression);
substitute.trailingComment = ` ${propertyName} `;
addSyntheticTrailingComment(substitute, SyntaxKind.MultiLineCommentTrivia, ` ${propertyName} `);
}
setConstantValue(node, constantValue);
return substitute;
}
@@ -3340,13 +3356,60 @@ namespace ts {
}
}
const paramHelper: EmitHelper = {
name: "typescript:param",
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
const argumentsArray: Expression[] = [];
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true));
argumentsArray.push(target);
if (memberName) {
argumentsArray.push(memberName);
if (descriptor) {
argumentsArray.push(descriptor);
}
}
context.requestEmitHelper(decorateHelper);
return setTextRange(
createCall(
getHelperName("__decorate"),
/*typeArguments*/ undefined,
argumentsArray
),
location
);
}
const decorateHelper: EmitHelper = {
name: "typescript:decorate",
scoped: false,
priority: 4,
priority: 2,
text: `
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};`
};
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
context.requestEmitHelper(metadataHelper);
return createCall(
getHelperName("__metadata"),
/*typeArguments*/ undefined,
[
createLiteral(metadataKey),
metadataValue
]
);
}
const metadataHelper: EmitHelper = {
name: "typescript:metadata",
scoped: false,
priority: 3,
text: `
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};`
};
@@ -3365,60 +3428,13 @@ namespace ts {
);
}
const metadataHelper: EmitHelper = {
name: "typescript:metadata",
const paramHelper: EmitHelper = {
name: "typescript:param",
scoped: false,
priority: 3,
priority: 4,
text: `
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};`
};
function createMetadataHelper(context: TransformationContext, metadataKey: string, metadataValue: Expression) {
context.requestEmitHelper(metadataHelper);
return createCall(
getHelperName("__metadata"),
/*typeArguments*/ undefined,
[
createLiteral(metadataKey),
metadataValue
]
);
}
const decorateHelper: EmitHelper = {
name: "typescript:decorate",
scoped: false,
priority: 2,
text: `
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};`
};
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
context.requestEmitHelper(decorateHelper);
const argumentsArray: Expression[] = [];
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true));
argumentsArray.push(target);
if (memberName) {
argumentsArray.push(memberName);
if (descriptor) {
argumentsArray.push(descriptor);
}
}
return setTextRange(
createCall(
getHelperName("__decorate"),
/*typeArguments*/ undefined,
argumentsArray
),
location
);
}
}
+117 -56
View File
@@ -381,9 +381,6 @@
JSDocPropertyTag,
JSDocTypeLiteral,
JSDocLiteralType,
JSDocNullKeyword,
JSDocUndefinedKeyword,
JSDocNeverKeyword,
// Synthesized list
SyntaxList,
@@ -423,9 +420,9 @@
LastBinaryOperator = CaretEqualsToken,
FirstNode = QualifiedName,
FirstJSDocNode = JSDocTypeExpression,
LastJSDocNode = JSDocNeverKeyword,
LastJSDocNode = JSDocLiteralType,
FirstJSDocTagNode = JSDocComment,
LastJSDocTagNode = JSDocNeverKeyword
LastJSDocTagNode = JSDocLiteralType
}
export const enum NodeFlags {
@@ -542,6 +539,7 @@
export type EndOfFileToken = Token<SyntaxKind.EndOfFileToken>;
export type AtToken = Token<SyntaxKind.AtToken>;
export type ReadonlyToken = Token<SyntaxKind.ReadonlyKeyword>;
export type AwaitKeywordToken = Token<SyntaxKind.AwaitKeyword>;
export type Modifier
= Token<SyntaxKind.AbstractKeyword>
@@ -699,7 +697,13 @@
name?: PropertyName;
}
export type ObjectLiteralElementLike = PropertyAssignment | ShorthandPropertyAssignment | MethodDeclaration | AccessorDeclaration | SpreadAssignment;
export type ObjectLiteralElementLike
= PropertyAssignment
| ShorthandPropertyAssignment
| SpreadAssignment
| MethodDeclaration
| AccessorDeclaration
;
export interface PropertyAssignment extends ObjectLiteralElement {
kind: SyntaxKind.PropertyAssignment;
@@ -1316,7 +1320,6 @@
export interface NumericLiteral extends LiteralExpression {
kind: SyntaxKind.NumericLiteral;
trailingComment?: string;
}
export interface TemplateHead extends LiteralLikeNode {
@@ -1637,6 +1640,7 @@
export interface ForOfStatement extends IterationStatement {
kind: SyntaxKind.ForOfStatement;
awaitModifier?: AwaitKeywordToken;
initializer: ForInitializer;
expression: Expression;
}
@@ -1904,9 +1908,17 @@
fileName: string;
}
export type CommentKind = SyntaxKind.SingleLineCommentTrivia | SyntaxKind.MultiLineCommentTrivia;
export interface CommentRange extends TextRange {
hasTrailingNewLine?: boolean;
kind: SyntaxKind;
kind: CommentKind;
}
export interface SynthesizedComment extends CommentRange {
text: string;
pos: -1;
end: -1;
}
// represents a top level: { type } expression in a JSDoc comment.
@@ -2291,7 +2303,7 @@
* used for writing the JavaScript and declaration files. Otherwise, the writeFile parameter
* will be invoked when writing the JavaScript and declaration files.
*/
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean): EmitResult;
emit(targetSourceFile?: SourceFile, writeFile?: WriteFileCallback, cancellationToken?: CancellationToken, emitOnlyDtsFiles?: boolean, customTransformers?: CustomTransformers): EmitResult;
getOptionsDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
getGlobalDiagnostics(cancellationToken?: CancellationToken): Diagnostic[];
@@ -2325,6 +2337,13 @@
/* @internal */ structureIsReused?: boolean;
}
export interface CustomTransformers {
/** Custom transformers to evaluate before built-in transformations. */
before?: TransformerFactory<SourceFile>[];
/** Custom transformers to evaluate after built-in transformations. */
after?: TransformerFactory<SourceFile>[];
}
export interface SourceMapSpan {
/** Line number in the .js file. */
emittedLine: number;
@@ -2393,6 +2412,8 @@
getSignaturesOfType(type: Type, kind: SignatureKind): Signature[];
getIndexTypeOfType(type: Type, kind: IndexKind): Type;
getBaseTypes(type: InterfaceType): BaseType[];
getBaseTypeOfLiteralType(type: Type): Type;
getWidenedType(type: Type): Type;
getReturnTypeOfSignature(signature: Signature): Type;
/**
* Gets the type of a parameter at a given position in a signature.
@@ -3066,8 +3087,17 @@
// Just a place to cache element types of iterables and iterators
/* @internal */
export interface IterableOrIteratorType extends ObjectType, UnionType {
iterableElementType?: Type;
iteratorElementType?: Type;
iteratedTypeOfIterable?: Type;
iteratedTypeOfIterator?: Type;
iteratedTypeOfAsyncIterable?: Type;
iteratedTypeOfAsyncIterator?: Type;
}
/* @internal */
export interface PromiseOrAwaitableType extends ObjectType, UnionType {
promiseTypeOfPromiseConstructor?: Type;
promisedTypeOfPromise?: Type;
awaitedTypeOfType?: Type;
}
export interface TypeVariable extends Type {
@@ -3190,7 +3220,9 @@
/// className.prototype.name = expr
PrototypeProperty,
/// this.name = expr
ThisProperty
ThisProperty,
// F.name = expr
Property
}
export interface JsFileExtensionInfo {
@@ -3259,6 +3291,7 @@
/* @internal */ diagnostics?: boolean;
/* @internal */ extendedDiagnostics?: boolean;
disableSizeLimit?: boolean;
downlevelIteration?: boolean;
emitBOM?: boolean;
emitDecoratorMetadata?: boolean;
experimentalDecorators?: boolean;
@@ -3777,9 +3810,11 @@
export interface EmitNode {
annotatedNodes?: Node[]; // Tracks Parse-tree nodes with EmitNodes for eventual cleanup.
flags?: EmitFlags; // Flags that customize emit
leadingComments?: SynthesizedComment[]; // Synthesized leading comments
trailingComments?: SynthesizedComment[]; // Synthesized trailing comments
commentRange?: TextRange; // The text range to use when emitting leading or trailing comments
sourceMapRange?: TextRange; // The text range to use when emitting leading or trailing source mappings
tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens
tokenSourceMapRanges?: TextRange[]; // The text range to use when emitting source mappings for tokens
constantValue?: number; // The constant value of an expression
externalHelpersModuleName?: Identifier; // The local name for an imported helpers module
helpers?: EmitHelper[]; // Emit helpers for the node
@@ -3815,7 +3850,7 @@
export interface EmitHelper {
readonly name: string; // A unique name for this helper.
readonly scoped: boolean; // Indicates whether ther helper MUST be emitted in the current scope.
readonly scoped: boolean; // Indicates whether the helper MUST be emitted in the current scope.
readonly text: string; // ES3-compatible raw script text.
readonly priority?: number; // Helpers with a higher priority are emitted earlier than other helpers on the node.
}
@@ -3834,9 +3869,24 @@
Param = 1 << 5, // __param (used by TypeScript decorators transformation)
Awaiter = 1 << 6, // __awaiter (used by ES2017 async functions transformation)
Generator = 1 << 7, // __generator (used by ES2015 generator transformation)
Values = 1 << 8, // __values (used by ES2015 for..of and yield* transformations)
Read = 1 << 9, // __read (used by ES2015 iterator destructuring transformation)
Spread = 1 << 10, // __spread (used by ES2015 array spread and argument list spread transformations)
AsyncGenerator = 1 << 11, // __asyncGenerator (used by ES2017 async generator transformation)
AsyncDelegator = 1 << 12, // __asyncDelegator (used by ES2017 async generator yield* transformation)
AsyncValues = 1 << 13, // __asyncValues (used by ES2017 for..await..of transformation)
// Helpers included by ES2015 for..of
ForOfIncludes = Values,
// Helpers included by ES2017 for..await..of
ForAwaitOfIncludes = AsyncValues,
// Helpers included by ES2015 spread
SpreadIncludes = Read | Spread,
FirstEmitHelper = Extends,
LastEmitHelper = Generator
LastEmitHelper = AsyncValues
}
export const enum EmitHint {
@@ -3862,11 +3912,12 @@
writeFile: WriteFileCallback;
}
/* @internal */
export interface TransformationContext {
/*@internal*/ getEmitResolver(): EmitResolver;
/*@internal*/ getEmitHost(): EmitHost;
/** Gets the compiler options supplied to the transformer. */
getCompilerOptions(): CompilerOptions;
getEmitResolver(): EmitResolver;
getEmitHost(): EmitHost;
/** Starts a new lexical environment. */
startLexicalEnvironment(): void;
@@ -3880,41 +3931,32 @@
/** Ends a lexical environment, returning any declarations. */
endLexicalEnvironment(): Statement[];
/**
* Hoists a function declaration to the containing scope.
*/
/** Hoists a function declaration to the containing scope. */
hoistFunctionDeclaration(node: FunctionDeclaration): void;
/**
* Hoists a variable declaration to the containing scope.
*/
/** Hoists a variable declaration to the containing scope. */
hoistVariableDeclaration(node: Identifier): void;
/**
* Records a request for a non-scoped emit helper in the current context.
*/
/** Records a request for a non-scoped emit helper in the current context. */
requestEmitHelper(helper: EmitHelper): void;
/**
* Gets and resets the requested non-scoped emit helpers.
*/
/** Gets and resets the requested non-scoped emit helpers. */
readEmitHelpers(): EmitHelper[] | undefined;
/**
* Enables expression substitutions in the pretty printer for the provided SyntaxKind.
*/
/** Enables expression substitutions in the pretty printer for the provided SyntaxKind. */
enableSubstitution(kind: SyntaxKind): void;
/**
* Determines whether expression substitutions are enabled for the provided node.
*/
/** Determines whether expression substitutions are enabled for the provided node. */
isSubstitutionEnabled(node: Node): boolean;
/**
* Hook used by transformers to substitute expressions just before they
* are emitted by the pretty printer.
*
* NOTE: Transformation hooks should only be modified during `Transformer` initialization,
* before returning the `NodeTransformer` callback.
*/
onSubstituteNode?: (hint: EmitHint, node: Node) => Node;
onSubstituteNode: (hint: EmitHint, node: Node) => Node;
/**
* Enables before/after emit notifications in the pretty printer for the provided
@@ -3931,25 +3973,27 @@
/**
* Hook used to allow transformers to capture state before or after
* the printer emits a node.
*
* NOTE: Transformation hooks should only be modified during `Transformer` initialization,
* before returning the `NodeTransformer` callback.
*/
onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
onEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
}
/* @internal */
export interface TransformationResult {
/**
* Gets the transformed source files.
*/
transformed: SourceFile[];
export interface TransformationResult<T extends Node> {
/** Gets the transformed source files. */
transformed: T[];
/** Gets diagnostics for the transformation. */
diagnostics?: Diagnostic[];
/**
* Emits the substitute for a node, if one is available; otherwise, emits the node.
* Gets a substitute for a node, if one is available; otherwise, returns the original node.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
* @param emitCallback A callback used to emit the node or its substitute.
*/
emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
substituteNode(hint: EmitHint, node: Node): Node;
/**
* Emits a node with possible notification.
@@ -3959,10 +4003,30 @@
* @param emitCallback A callback used to emit the node.
*/
emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
/**
* Clean up EmitNode entries on any parse-tree nodes.
*/
dispose(): void;
}
/* @internal */
export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile;
/**
* A function that is used to initialize and return a `Transformer` callback, which in turn
* will be used to transform one or more nodes.
*/
export type TransformerFactory<T extends Node> = (context: TransformationContext) => Transformer<T>;
/**
* A function that transforms a node.
*/
export type Transformer<T extends Node> = (node: T) => T;
/**
* A function that accepts and possible transforms a node.
*/
export type Visitor = (node: Node) => VisitResult<Node>;
export type VisitResult<T extends Node> = T | T[];
export interface Printer {
/**
@@ -4020,23 +4084,20 @@
/**
* A hook used by the Printer to perform just-in-time substitution of a node. This is
* primarily used by node transformations that need to substitute one node for another,
* such as replacing `myExportedVar` with `exports.myExportedVar`. A compatible
* implementation **must** invoke `emitCallback` eith the provided `hint` and either
* the provided `node`, or its substitute.
* such as replacing `myExportedVar` with `exports.myExportedVar`.
* @param hint A hint indicating the intended purpose of the node.
* @param node The node to emit.
* @param emitCallback A callback that, when invoked, will emit the node.
* @example
* ```ts
* var printer = createPrinter(printerOptions, {
* onSubstituteNode(hint, node, emitCallback) {
* substituteNode(hint, node) {
* // perform substitution if necessary...
* emitCallback(hint, node);
* return node;
* }
* });
* ```
*/
onSubstituteNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
substituteNode?(hint: EmitHint, node: Node): Node;
/*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
/*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number;
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
+70 -12
View File
@@ -960,7 +960,7 @@ namespace ts {
return false;
}
export function unwrapInnermostStatmentOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) {
export function unwrapInnermostStatementOfLabel(node: LabeledStatement, beforeUnwrapLabelCallback?: (node: LabeledStatement) => void) {
while (true) {
if (beforeUnwrapLabelCallback) {
beforeUnwrapLabelCallback(node);
@@ -1417,10 +1417,10 @@ namespace ts {
* Returns true if the node is a variable declaration whose initializer is a function expression.
* This function does not test if the node is in a JavaScript file or not.
*/
export function isDeclarationOfFunctionExpression(s: Symbol) {
export function isDeclarationOfFunctionOrClassExpression(s: Symbol) {
if (s.valueDeclaration && s.valueDeclaration.kind === SyntaxKind.VariableDeclaration) {
const declaration = s.valueDeclaration as VariableDeclaration;
return declaration.initializer && declaration.initializer.kind === SyntaxKind.FunctionExpression;
return declaration.initializer && (declaration.initializer.kind === SyntaxKind.FunctionExpression || declaration.initializer.kind === SyntaxKind.ClassExpression);
}
return false;
}
@@ -1449,6 +1449,10 @@ namespace ts {
// module.exports = expr
return SpecialPropertyAssignmentKind.ModuleExports;
}
else {
// F.x = expr
return SpecialPropertyAssignmentKind.Property;
}
}
else if (lhs.expression.kind === SyntaxKind.ThisKeyword) {
return SpecialPropertyAssignmentKind.ThisProperty;
@@ -1468,6 +1472,7 @@ namespace ts {
}
}
return SpecialPropertyAssignmentKind.None;
}
@@ -1549,7 +1554,10 @@ namespace ts {
}
}
else {
result.push(...filter((doc as JSDoc).tags, tag => tag.kind === kind));
const tags = (doc as JSDoc).tags;
if (tags) {
result.push(...filter(tags, tag => tag.kind === kind));
}
}
}
return result;
@@ -1945,8 +1953,51 @@ namespace ts {
return SyntaxKind.FirstTriviaToken <= token && token <= SyntaxKind.LastTriviaToken;
}
export function isAsyncFunctionLike(node: Node): boolean {
return isFunctionLike(node) && hasModifier(node, ModifierFlags.Async) && !isAccessor(node);
export const enum FunctionFlags {
Normal = 0,
Generator = 1 << 0,
Async = 1 << 1,
AsyncOrAsyncGenerator = Async | Generator,
Invalid = 1 << 2,
InvalidAsyncOrAsyncGenerator = AsyncOrAsyncGenerator | Invalid,
InvalidGenerator = Generator | Invalid,
}
export function getFunctionFlags(node: FunctionLikeDeclaration) {
let flags = FunctionFlags.Normal;
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.MethodDeclaration:
if (node.asteriskToken) {
flags |= FunctionFlags.Generator;
}
// fall through
case SyntaxKind.ArrowFunction:
if (hasModifier(node, ModifierFlags.Async)) {
flags |= FunctionFlags.Async;
}
break;
}
if (!node.body) {
flags |= FunctionFlags.Invalid;
}
return flags;
}
export function isAsyncFunction(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.MethodDeclaration:
return (<FunctionLikeDeclaration>node).body !== undefined
&& (<FunctionLikeDeclaration>node).asteriskToken === undefined
&& hasModifier(node, ModifierFlags.Async);
}
return false;
}
export function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
@@ -3751,6 +3802,12 @@ namespace ts {
return node.kind === SyntaxKind.PropertyAccessExpression;
}
export function isPropertyAccessOrQualifiedName(node: Node): node is PropertyAccessExpression | QualifiedName {
const kind = node.kind;
return kind === SyntaxKind.PropertyAccessExpression
|| kind === SyntaxKind.QualifiedName;
}
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
return node.kind === SyntaxKind.ElementAccessExpression;
}
@@ -4101,16 +4158,18 @@ namespace ts {
return node.kind === SyntaxKind.JsxAttribute;
}
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
return node.kind === SyntaxKind.JsxOpeningElement || node.kind === SyntaxKind.JsxSelfClosingElement;
}
export function isStringLiteralOrJsxExpression(node: Node): node is StringLiteral | JsxExpression {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.JsxExpression;
}
export function isJsxOpeningLikeElement(node: Node): node is JsxOpeningLikeElement {
const kind = node.kind;
return kind === SyntaxKind.JsxOpeningElement
|| kind === SyntaxKind.JsxSelfClosingElement;
}
// Clauses
export function isCaseOrDefaultClause(node: Node): node is CaseOrDefaultClause {
@@ -4165,7 +4224,6 @@ namespace ts {
return "lib.es2016.d.ts";
case ScriptTarget.ES2015:
return "lib.es6.d.ts";
default:
return "lib.d.ts";
}
@@ -4561,7 +4619,7 @@ namespace ts {
*/
export function getParseTreeNode<T extends Node>(node: Node, nodeTest?: (node: Node) => node is T): T;
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
if (isParseTreeNode(node)) {
if (node == undefined || isParseTreeNode(node)) {
return node;
}
+762 -754
View File
File diff suppressed because it is too large Load Diff
+17 -9
View File
@@ -2214,7 +2214,7 @@ namespace FourSlash {
* Because codefixes are only applied on the working file, it is unsafe
* to apply this more than once (consider a refactoring across files).
*/
public verifyRangeAfterCodeFix(expectedText: string, errorCode?: number, includeWhiteSpace?: boolean) {
public verifyRangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number) {
const ranges = this.getRanges();
if (ranges.length !== 1) {
this.raiseError("Exactly one range should be specified in the testfile.");
@@ -2222,7 +2222,7 @@ namespace FourSlash {
const fileName = this.activeFile.fileName;
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName, errorCode));
this.applyCodeAction(fileName, this.getCodeFixActions(fileName, errorCode), index);
const actualText = this.rangeText(ranges[0]);
@@ -2247,7 +2247,7 @@ namespace FourSlash {
public verifyFileAfterCodeFix(expectedContents: string, fileName?: string) {
fileName = fileName ? fileName : this.activeFile.fileName;
this.applyCodeFixActions(fileName, this.getCodeFixActions(fileName));
this.applyCodeAction(fileName, this.getCodeFixActions(fileName));
const actualContents: string = this.getFileContent(fileName);
if (this.removeWhitespace(actualContents) !== this.removeWhitespace(expectedContents)) {
@@ -2285,12 +2285,20 @@ namespace FourSlash {
return actions;
}
private applyCodeFixActions(fileName: string, actions: ts.CodeAction[]): void {
if (!(actions && actions.length === 1)) {
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
private applyCodeAction(fileName: string, actions: ts.CodeAction[], index?: number): void {
if (index === undefined) {
if (!(actions && actions.length === 1)) {
this.raiseError(`Should find exactly one codefix, but ${actions ? actions.length : "none"} found.`);
}
index = 0;
}
else {
if (!(actions && actions.length >= index + 1)) {
this.raiseError(`Should find at least ${index + 1} codefix(es), but ${actions ? actions.length : "none"} found.`);
}
}
const fileChanges = ts.find(actions[0].changes, change => change.fileName === fileName);
const fileChanges = ts.find(actions[index].changes, change => change.fileName === fileName);
if (!fileChanges) {
this.raiseError("The CodeFix found doesn't provide any changes in this file.");
}
@@ -3631,8 +3639,8 @@ namespace FourSlashInterface {
this.DocCommentTemplate(/*expectedText*/ undefined, /*expectedOffset*/ undefined, /*empty*/ true);
}
public rangeAfterCodeFix(expectedText: string, errorCode?: number, includeWhiteSpace?: boolean): void {
this.state.verifyRangeAfterCodeFix(expectedText, errorCode, includeWhiteSpace);
public rangeAfterCodeFix(expectedText: string, includeWhiteSpace?: boolean, errorCode?: number, index?: number): void {
this.state.verifyRangeAfterCodeFix(expectedText, includeWhiteSpace, errorCode, index);
}
public importFixAtPosition(expectedTextArray: string[], errorCode?: number): void {
+4 -2
View File
@@ -77,8 +77,8 @@
"../services/codefixes/helpers.ts",
"../services/codefixes/importFixes.ts",
"../services/codefixes/unusedIdentifierFixes.ts",
"../services/harness.ts",
"harness.ts",
"sourceMapRecorder.ts",
"harnessLanguageService.ts",
"fourslash.ts",
@@ -119,6 +119,8 @@
"./unittests/compileOnSave.ts",
"./unittests/typingsInstaller.ts",
"./unittests/projectErrors.ts",
"./unittests/printer.ts"
"./unittests/printer.ts",
"./unittests/transform.ts",
"./unittests/customTransforms.ts"
]
}
+8 -8
View File
@@ -60,7 +60,7 @@ namespace ts {
assertParseResult(["--lib", "es5,invalidOption", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -87,7 +87,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'",
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -113,7 +113,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -139,7 +139,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -165,7 +165,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'",
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -191,7 +191,7 @@ namespace ts {
start: undefined,
length: undefined,
}, {
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -263,7 +263,7 @@ namespace ts {
assertParseResult(["--lib", "es5,", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -283,7 +283,7 @@ namespace ts {
assertParseResult(["--lib", "es5, ", "es7", "0.ts"],
{
errors: [{
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
category: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.category,
code: ts.Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
@@ -94,7 +94,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'",
messageText: "Argument for '--jsx' option must be: 'preserve', 'react-native', 'react'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -122,7 +122,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'",
messageText: "Argument for '--module' option must be: 'none', 'commonjs', 'amd', 'system', 'umd', 'es6', 'es2015'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -150,7 +150,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'",
messageText: "Argument for '--newLine' option must be: 'crlf', 'lf'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -176,7 +176,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'",
messageText: "Argument for '--target' option must be: 'es3', 'es5', 'es6', 'es2015', 'es2016', 'es2017', 'esnext'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -202,7 +202,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'",
messageText: "Argument for '--moduleResolution' option must be: 'node', 'classic'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -233,7 +233,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -264,7 +264,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -295,7 +295,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
@@ -326,7 +326,7 @@ namespace ts {
file: undefined,
start: 0,
length: 0,
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string'",
messageText: "Argument for '--lib' option must be: 'es5', 'es6', 'es2015', 'es7', 'es2016', 'es2017', 'esnext', 'dom', 'dom.iterable', 'webworker', 'scripthost', 'es2015.core', 'es2015.collection', 'es2015.generator', 'es2015.iterable', 'es2015.promise', 'es2015.proxy', 'es2015.reflect', 'es2015.symbol', 'es2015.symbol.wellknown', 'es2016.array.include', 'es2017.object', 'es2017.sharedmemory', 'es2017.string', 'esnext.asynciterable'.",
code: Diagnostics.Argument_for_0_option_must_be_Colon_1.code,
category: Diagnostics.Argument_for_0_option_must_be_Colon_1.category
}]
+86
View File
@@ -0,0 +1,86 @@
/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
describe("customTransforms", () => {
function emitsCorrectly(name: string, sources: { file: string, text: string }[], customTransformers: CustomTransformers) {
it(name, () => {
const roots = sources.map(source => createSourceFile(source.file, source.text, ScriptTarget.ES2015));
const fileMap = arrayToMap(roots, file => file.fileName);
const outputs = createMap<string>();
const options: CompilerOptions = {};
const host: CompilerHost = {
getSourceFile: (fileName) => fileMap.get(fileName),
getDefaultLibFileName: () => "lib.d.ts",
getCurrentDirectory: () => "",
getDirectories: () => [],
getCanonicalFileName: (fileName) => fileName,
useCaseSensitiveFileNames: () => true,
getNewLine: () => "\n",
fileExists: (fileName) => fileMap.has(fileName),
readFile: (fileName) => fileMap.has(fileName) ? fileMap.get(fileName).text : undefined,
writeFile: (fileName, text) => outputs.set(fileName, text),
};
const program = createProgram(arrayFrom(fileMap.keys()), options, host);
program.emit(/*targetSourceFile*/ undefined, host.writeFile, /*cancellationToken*/ undefined, /*emitOnlyDtsFiles*/ false, customTransformers);
Harness.Baseline.runBaseline(`customTransforms/${name}.js`, () => {
let content = "";
for (const [file, text] of arrayFrom(outputs.entries())) {
if (content) content += "\n\n";
content += `// [${file}]\n`;
content += text;
}
return content;
});
});
}
const sources = [{
file: "source.ts",
text: `
function f1() { }
class c() { }
enum e { }
// leading
function f2() { } // trailing
`
}];
const before: TransformerFactory<SourceFile> = context => {
return file => visitEachChild(file, visit, context);
function visit(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
return visitFunction(<FunctionDeclaration>node);
default:
return visitEachChild(node, visit, context);
}
}
function visitFunction(node: FunctionDeclaration) {
addSyntheticLeadingComment(node, SyntaxKind.MultiLineCommentTrivia, "@before", /*hasTrailingNewLine*/ true);
return node;
}
};
const after: TransformerFactory<SourceFile> = context => {
return file => visitEachChild(file, visit, context);
function visit(node: Node): VisitResult<Node> {
switch (node.kind) {
case SyntaxKind.VariableStatement:
return visitVariableStatement(<VariableStatement>node);
default:
return visitEachChild(node, visit, context);
}
}
function visitVariableStatement(node: VariableStatement) {
addSyntheticLeadingComment(node, SyntaxKind.SingleLineCommentTrivia, "@after");
return node;
}
};
emitsCorrectly("before", sources, { before: [before] });
emitsCorrectly("after", sources, { after: [after] });
emitsCorrectly("both", sources, { before: [before], after: [after] });
});
}
+43
View File
@@ -0,0 +1,43 @@
/// <reference path="..\..\services\transform.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
describe("TransformAPI", () => {
function transformsCorrectly(name: string, source: string, transformers: TransformerFactory<SourceFile>[]) {
it(name, () => {
Harness.Baseline.runBaseline(`transformApi/transformsCorrectly.${name}.js`, () => {
const transformed = transform(createSourceFile("source.ts", source, ScriptTarget.ES2015), transformers);
const printer = createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed }, {
onEmitNode: transformed.emitNodeWithNotification,
substituteNode: transformed.substituteNode
});
const result = printer.printBundle(createBundle(transformed.transformed));
transformed.dispose();
return result;
});
});
}
transformsCorrectly("substitution", `
var a = undefined;
`, [
context => {
const previousOnSubstituteNode = context.onSubstituteNode;
context.enableSubstitution(SyntaxKind.Identifier);
context.onSubstituteNode = (hint, node) => {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression && node.kind === SyntaxKind.Identifier && (<Identifier>node).text === "undefined") {
node = createPartiallyEmittedExpression(
addSyntheticTrailingComment(
setTextRange(
createVoidZero(),
node),
SyntaxKind.MultiLineCommentTrivia, "undefined"));
}
return node;
};
return file => file;
}
]);
});
}
@@ -3035,6 +3035,33 @@ namespace ts.projectSystem {
const inferredProject = projectService.inferredProjects[0];
assert.isTrue(inferredProject.containsFile(<server.NormalizedPath>file1.path));
});
it("should be able to handle @types if input file list is empty", () => {
const f = {
path: "/a/app.ts",
content: "let x = 1"
};
const config = {
path: "/a/tsconfig.json",
content: JSON.stringify({
compiler: {},
files: []
})
};
const t1 = {
path: "/a/node_modules/@types/typings/index.d.ts",
content: `export * from "./lib"`
};
const t2 = {
path: "/a/node_modules/@types/typings/lib.d.ts",
content: `export const x: number`
};
const host = createServerHost([f, config, t1, t2], { currentDirectory: getDirectoryPath(f.path) });
const projectService = createProjectService(host);
projectService.openClientFile(f.path);
projectService.checkNumberOfProjects({ configuredProjects: 1, inferredProjects: 1 });
});
});
describe("reload", () => {
+47 -47
View File
@@ -1,8 +1,8 @@
/// <reference path="lib.es2015.symbol.d.ts" />
interface SymbolConstructor {
/**
* A method that returns the default iterator for an object. Called by the semantics of the
/**
* A method that returns the default iterator for an object. Called by the semantics of the
* for-of statement.
*/
readonly iterator: symbol;
@@ -31,17 +31,17 @@ interface Array<T> {
/** Iterator */
[Symbol.iterator](): IterableIterator<T>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, T]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<T>;
@@ -55,7 +55,7 @@ interface ArrayConstructor {
* @param thisArg Value of 'this' used to invoke the mapfn.
*/
from<T, U>(iterable: Iterable<T>, mapfn: (v: T, k: number) => U, thisArg?: any): Array<U>;
/**
* Creates an array from an iterable object.
* @param iterable An iterable object to convert to an array.
@@ -67,17 +67,17 @@ interface ReadonlyArray<T> {
/** Iterator */
[Symbol.iterator](): IterableIterator<T>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, T]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<T>;
@@ -126,15 +126,15 @@ interface Promise<T> { }
interface PromiseConstructor {
/**
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* Creates a Promise that is resolved with an array of results when all of the provided Promises
* resolve, or rejected when any Promise is rejected.
* @param values An array of Promises.
* @returns A new Promise.
*/
all<TAll>(values: Iterable<TAll | PromiseLike<TAll>>): Promise<TAll[]>;
/**
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* Creates a Promise that is resolved or rejected when any of the provided Promises are resolved
* or rejected.
* @param values An array of Promises.
* @returns A new Promise.
@@ -152,20 +152,20 @@ interface String {
}
/**
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* A typed array of 8-bit integer values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Int8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -184,20 +184,20 @@ interface Int8ArrayConstructor {
}
/**
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* A typed array of 8-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -216,22 +216,22 @@ interface Uint8ArrayConstructor {
}
/**
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* A typed array of 8-bit unsigned integer (clamped) values. The contents are initialized to 0.
* If the requested number of bytes could not be allocated an exception is raised.
*/
interface Uint8ClampedArray {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -251,22 +251,22 @@ interface Uint8ClampedArrayConstructor {
}
/**
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* A typed array of 16-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -285,20 +285,20 @@ interface Int16ArrayConstructor {
}
/**
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* A typed array of 16-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint16Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -317,20 +317,20 @@ interface Uint16ArrayConstructor {
}
/**
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* A typed array of 32-bit signed integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Int32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -349,20 +349,20 @@ interface Int32ArrayConstructor {
}
/**
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* A typed array of 32-bit unsigned integer values. The contents are initialized to 0. If the
* requested number of bytes could not be allocated an exception is raised.
*/
interface Uint32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -386,15 +386,15 @@ interface Uint32ArrayConstructor {
*/
interface Float32Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
@@ -413,20 +413,20 @@ interface Float32ArrayConstructor {
}
/**
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* A typed array of 64-bit float values. The contents are initialized to 0. If the requested
* number of bytes could not be allocated an exception is raised.
*/
interface Float64Array {
[Symbol.iterator](): IterableIterator<number>;
/**
/**
* Returns an array of key, value pairs for every entry in the array
*/
entries(): IterableIterator<[number, number]>;
/**
/**
* Returns an list of keys in the array
*/
keys(): IterableIterator<number>;
/**
/**
* Returns an list of values in the array
*/
values(): IterableIterator<number>;
+1 -1
View File
@@ -1,4 +1,4 @@
/// <reference path="lib.es2016.d.ts" />
/// <reference path="lib.es2017.object.d.ts" />
/// <reference path="lib.es2017.sharedmemory.d.ts" />
/// <reference path="lib.es2017.string.d.ts" />
/// <reference path="lib.es2017.string.d.ts" />
+1 -1
View File
@@ -140,7 +140,7 @@ interface ObjectConstructor {
* Creates an object that has the specified prototype or that has null prototype.
* @param o Object to use as a prototype. May be null.
*/
create<T extends object>(o: T | null): T | object;
create(o: object | null): any;
/**
* Creates an object that has the specified prototype, and that optionally contains specified properties.
+24
View File
@@ -0,0 +1,24 @@
/// <reference path="lib.es2015.symbol.d.ts" />
/// <reference path="lib.es2015.iterable.d.ts" />
interface SymbolConstructor {
/**
* A method that returns the default async iterator for an object. Called by the semantics of
* the for-await-of statement.
*/
readonly asyncIterator: symbol;
}
interface AsyncIterator<T> {
next(value?: any): Promise<IteratorResult<T>>;
return?(value?: any): Promise<IteratorResult<T>>;
throw?(e?: any): Promise<IteratorResult<T>>;
}
interface AsyncIterable<T> {
[Symbol.asyncIterator](): AsyncIterator<T>;
}
interface AsyncIterableIterator<T> extends AsyncIterator<T> {
[Symbol.asyncIterator](): AsyncIterableIterator<T>;
}
+2
View File
@@ -0,0 +1,2 @@
/// <reference path="lib.es2017.d.ts" />
/// <reference path="lib.esnext.asynciterable.d.ts" />
+2 -2
View File
@@ -948,9 +948,9 @@ namespace ts.server {
private openConfigFile(configFileName: NormalizedPath, clientFileName?: string): OpenConfigFileResult {
const conversionResult = this.convertConfigFileContentToProjectOptions(configFileName);
const projectOptions = conversionResult.success
const projectOptions: ProjectOptions = conversionResult.success
? conversionResult.projectOptions
: { files: [], compilerOptions: {} };
: { files: [], compilerOptions: {}, typeAcquisition: { enable: false } };
const project = this.createAndAddConfiguredProject(configFileName, projectOptions, conversionResult.configFileErrors, clientFileName);
return {
success: conversionResult.success,
+1 -1
View File
@@ -820,7 +820,7 @@ namespace ts.server.protocol {
* Represents a file in external project.
* External project is project whose set of files, compilation options and open\close state
* is maintained by the client (i.e. if all this data come from .csproj file in Visual Studio).
* External project will exist even if all files in it are closed and should be closed explicity.
* External project will exist even if all files in it are closed and should be closed explicitly.
* If external project includes one or more tsconfig.json/jsconfig.json files then tsserver will
* create configured project for every config file but will maintain a link that these projects were created
* as a result of opening external project so they should be removed once external project is closed.
+79 -1
View File
@@ -12,6 +12,7 @@ namespace ts.server {
const childProcess: {
fork(modulePath: string, args: string[], options?: { execArgv: string[], env?: MapLike<string> }): NodeChildProcess;
execFileSync(file: string, args: string[], options: { stdio: "ignore", env: MapLike<string> }): string | Buffer;
} = require("child_process");
const os: {
@@ -59,7 +60,7 @@ namespace ts.server {
interface NodeChildProcess {
send(message: any, sendHandle?: any): void;
on(message: "message", f: (m: any) => void): void;
on(message: "message" | "exit", f: (m: any) => void): void;
kill(): void;
pid: number;
}
@@ -576,7 +577,84 @@ namespace ts.server {
}
}
function extractWatchDirectoryCacheKey(path: string, currentDriveKey: string) {
path = normalizeSlashes(path);
if (isUNCPath(path)) {
// UNC path: extract server name
// //server/location
// ^ <- from 0 to this position
const firstSlash = path.indexOf(directorySeparator, 2);
return firstSlash !== -1 ? path.substring(0, firstSlash).toLowerCase() : path;
}
const rootLength = getRootLength(path);
if (rootLength === 0) {
// relative path - assume file is on the current drive
return currentDriveKey;
}
if (path.charCodeAt(1) === CharacterCodes.colon && path.charCodeAt(2) === CharacterCodes.slash) {
// rooted path that starts with c:/... - extract drive letter
return path.charAt(0).toLowerCase();
}
if (path.charCodeAt(0) === CharacterCodes.slash && path.charCodeAt(1) !== CharacterCodes.slash) {
// rooted path that starts with slash - /somename - use key for current drive
return currentDriveKey;
}
// do not cache any other cases
return undefined;
}
function isUNCPath(s: string): boolean {
return s.length > 2 && s.charCodeAt(0) === CharacterCodes.slash && s.charCodeAt(1) === CharacterCodes.slash;
}
const sys = <ServerHost>ts.sys;
// use watchGuard process on Windows when node version is 4 or later
const useWatchGuard = process.platform === "win32" && getNodeMajorVersion() >= 4;
if (useWatchGuard) {
const currentDrive = extractWatchDirectoryCacheKey(sys.resolvePath(sys.getCurrentDirectory()), /*currentDriveKey*/ undefined);
const statusCache = createMap<boolean>();
const originalWatchDirectory = sys.watchDirectory;
sys.watchDirectory = function (path: string, callback: DirectoryWatcherCallback, recursive?: boolean): FileWatcher {
const cacheKey = extractWatchDirectoryCacheKey(path, currentDrive);
let status = cacheKey && statusCache.get(cacheKey);
if (status === undefined) {
if (logger.hasLevel(LogLevel.verbose)) {
logger.info(`${cacheKey} for path ${path} not found in cache...`);
}
try {
const args = [combinePaths(__dirname, "watchGuard.js"), path];
if (logger.hasLevel(LogLevel.verbose)) {
logger.info(`Starting ${process.execPath} with args ${JSON.stringify(args)}`);
}
childProcess.execFileSync(process.execPath, args, { stdio: "ignore", env: { "ELECTRON_RUN_AS_NODE": "1" } });
status = true;
if (logger.hasLevel(LogLevel.verbose)) {
logger.info(`WatchGuard for path ${path} returned: OK`);
}
}
catch (e) {
status = false;
if (logger.hasLevel(LogLevel.verbose)) {
logger.info(`WatchGuard for path ${path} returned: ${e.message}`);
}
}
if (cacheKey) {
statusCache.set(cacheKey, status);
}
}
else if (logger.hasLevel(LogLevel.verbose)) {
logger.info(`watchDirectory for ${path} uses cached drive information.`);
}
if (status) {
// this drive is safe to use - call real 'watchDirectory'
return originalWatchDirectory.call(sys, path, callback, recursive);
}
else {
// this drive is unsafe - return no-op watcher
return { close() { } };
}
}
}
// Override sys.write because fs.writeSync is not reliable on Node 4
sys.write = (s: string) => writeMessage(new Buffer(s, "utf8"));
+3
View File
@@ -1412,6 +1412,9 @@ namespace ts.server {
}
private getCodeFixes(args: protocol.CodeFixRequestArgs, simplifiedResult: boolean): protocol.CodeAction[] | CodeAction[] {
if (args.errorCodes.length === 0) {
return undefined;
}
const { file, project } = this.getFileAndProjectWithoutRefreshingInferredProjects(args);
const scriptInfo = project.getScriptInfoForNormalizedPath(file);
+10
View File
@@ -0,0 +1,10 @@
{
"extends": "../../tsconfig-base",
"compilerOptions": {
"removeComments": true,
"outFile": "../../../built/local/watchGuard.js"
},
"files": [
"watchGuard.ts"
]
}
+19
View File
@@ -0,0 +1,19 @@
/// <reference types="node" />
if (process.argv.length < 3) {
process.exit(1);
}
const directoryName = process.argv[2];
const fs: { watch(directoryName: string, options: any, callback: () => {}): any } = require("fs");
// main reason why we need separate process to check if it is safe to watch some path
// is to guard against crashes that cannot be intercepted with protected blocks and
// code in tsserver already can handle normal cases, like non-existing folders.
// This means that here we treat any result (success or exception) from fs.watch as success since it does not tear down the process.
// The only case that should be considered as failure - when watchGuard process crashes.
try {
const watcher = fs.watch(directoryName, { recursive: true }, () => ({}))
watcher.close();
}
catch (_e) {
}
process.exit(0);
@@ -0,0 +1,67 @@
/* @internal */
namespace ts.codefix {
registerCodeFix({
errorCodes: [Diagnostics.Property_0_does_not_exist_on_type_1.code],
getCodeActions: getActionsForAddMissingMember
});
function getActionsForAddMissingMember(context: CodeFixContext): CodeAction[] | undefined {
const sourceFile = context.sourceFile;
const start = context.span.start;
// This is the identifier of the missing property. eg:
// this.missing = 1;
// ^^^^^^^
const token = getTokenAtPosition(sourceFile, start);
if (token.kind != SyntaxKind.Identifier) {
return undefined;
}
const classDeclaration = getContainingClass(token);
if (!classDeclaration) {
return undefined;
}
if (!(token.parent && token.parent.kind === SyntaxKind.PropertyAccessExpression)) {
return undefined;
}
if ((token.parent as PropertyAccessExpression).expression.kind !== SyntaxKind.ThisKeyword) {
return undefined;
}
let typeString = "any";
if (token.parent.parent.kind === SyntaxKind.BinaryExpression) {
const binaryExpression = token.parent.parent as BinaryExpression;
const checker = context.program.getTypeChecker();
const widenedType = checker.getWidenedType(checker.getBaseTypeOfLiteralType(checker.getTypeAtLocation(binaryExpression.right)));
typeString = checker.typeToString(widenedType);
}
const startPos = classDeclaration.members.pos;
return [{
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_declaration_for_missing_property_0), [token.getText()]),
changes: [{
fileName: sourceFile.fileName,
textChanges: [{
span: { start: startPos, length: 0 },
newText: `${token.getFullText(sourceFile)}: ${typeString};`
}]
}]
},
{
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Add_index_signature_for_missing_property_0), [token.getText()]),
changes: [{
fileName: sourceFile.fileName,
textChanges: [{
span: { start: startPos, length: 0 },
newText: `[name: string]: ${typeString};`
}]
}]
}];
}
}
+1
View File
@@ -1,4 +1,5 @@
/// <reference path="fixClassIncorrectlyImplementsInterface.ts" />
/// <reference path="fixAddMissingMember.ts" />
/// <reference path="fixClassDoesntImplementInheritedAbstractMember.ts" />
/// <reference path="fixClassSuperMustPrecedeThisAccess.ts" />
/// <reference path="fixConstructorForDerivedNeedSuperCall.ts" />
+10 -6
View File
@@ -32,7 +32,7 @@ namespace ts.codefix {
const declaration = declarations[0] as Declaration;
const name = declaration.name ? declaration.name.getText() : undefined;
const visibility = getVisibilityPrefix(getModifierFlags(declaration));
const visibility = getVisibilityPrefixWithSpace(getModifierFlags(declaration));
switch (declaration.kind) {
case SyntaxKind.GetAccessor:
@@ -58,7 +58,7 @@ namespace ts.codefix {
if (declarations.length === 1) {
Debug.assert(signatures.length === 1);
const sigString = checker.signatureToString(signatures[0], enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
return `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
return getStubbedMethod(visibility, name, sigString, newlineChar);
}
let result = "";
@@ -78,7 +78,7 @@ namespace ts.codefix {
bodySig = createBodySignatureWithAnyTypes(signatures, enclosingDeclaration, checker);
}
const sigString = checker.signatureToString(bodySig, enclosingDeclaration, TypeFormatFlags.SuppressAnyReturnType, SignatureKind.Call);
result += `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
result += getStubbedMethod(visibility, name, sigString, newlineChar);
return result;
default:
@@ -138,11 +138,15 @@ namespace ts.codefix {
}
}
function getMethodBodyStub(newLineChar: string) {
return ` {${newLineChar}throw new Error('Method not implemented.');${newLineChar}}${newLineChar}`;
export function getStubbedMethod(visibility: string, name: string, sigString = "()", newlineChar: string): string {
return `${visibility}${name}${sigString}${getMethodBodyStub(newlineChar)}`;
}
function getVisibilityPrefix(flags: ModifierFlags): string {
function getMethodBodyStub(newlineChar: string) {
return ` {${newlineChar}throw new Error('Method not implemented.');${newlineChar}}${newlineChar}`;
}
function getVisibilityPrefixWithSpace(flags: ModifierFlags): string {
if (flags & ModifierFlags.Public) {
return "public ";
}
+5 -1
View File
@@ -198,7 +198,11 @@ namespace ts.GoToDefinition {
return false;
}
function tryAddSignature(signatureDeclarations: Declaration[], selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
function tryAddSignature(signatureDeclarations: Declaration[] | undefined, selectConstructors: boolean, symbolKind: string, symbolName: string, containerName: string, result: DefinitionInfo[]) {
if (!signatureDeclarations) {
return false;
}
const declarations: Declaration[] = [];
let definition: Declaration | undefined;
+2 -2
View File
@@ -67,10 +67,10 @@ namespace ts.OutliningElementsCollector {
// Only outline spans of two or more consecutive single line comments
if (count > 1) {
const multipleSingleLineComments = {
const multipleSingleLineComments: CommentRange = {
kind: SyntaxKind.SingleLineCommentTrivia,
pos: start,
end: end,
kind: SyntaxKind.SingleLineCommentTrivia
};
addOutliningSpanComments(multipleSingleLineComments, /*autoCollapse*/ false);
+3 -2
View File
@@ -411,7 +411,7 @@ namespace ts {
getDeclaration(): SignatureDeclaration {
return this.declaration;
}
getTypeParameters(): Type[] {
getTypeParameters(): TypeParameter[] {
return this.typeParameters;
}
getParameters(): Symbol[] {
@@ -1440,7 +1440,8 @@ namespace ts {
});
}
const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles);
const customTransformers = host.getCustomTransformers && host.getCustomTransformers();
const emitOutput = program.emit(sourceFile, writeFile, cancellationToken, emitOnlyDtsFiles, customTransformers);
return {
outputFiles,
+18
View File
@@ -0,0 +1,18 @@
/// <reference path="..\compiler\transformer.ts"/>
/// <reference path="transpile.ts"/>
namespace ts {
/**
* Transform one or more nodes using the supplied transformers.
* @param source A single `Node` or an array of `Node` objects.
* @param transformers An array of `TransformerFactory` callbacks used to process the transformation.
* @param compilerOptions Optional compiler options.
*/
export function transform<T extends Node>(source: T | T[], transformers: TransformerFactory<T>[], compilerOptions?: CompilerOptions) {
const diagnostics: Diagnostic[] = [];
compilerOptions = fixupCompilerOptions(compilerOptions, diagnostics);
const nodes = isArray(source) ? source : [source];
const result = transformNodes(/*resolver*/ undefined, /*emitHost*/ undefined, compilerOptions, nodes, transformers, /*allowDtsFiles*/ true);
result.diagnostics = concatenate(result.diagnostics, diagnostics);
return result;
}
}
+2 -1
View File
@@ -123,7 +123,8 @@
let commandLineOptionsStringToEnum: CommandLineOptionOfCustomType[];
/** JS users may pass in string values for enum compiler options (such as ModuleKind), so convert. */
function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
/*@internal*/
export function fixupCompilerOptions(options: CompilerOptions, diagnostics: Diagnostic[]): CompilerOptions {
// Lazily create this value to fix module loading errors.
commandLineOptionsStringToEnum = commandLineOptionsStringToEnum || <CommandLineOptionOfCustomType[]>filter(optionDeclarations, o =>
typeof o.type === "object" && !forEachEntry(o.type, v => typeof v !== "number"));
+2
View File
@@ -57,6 +57,7 @@
"preProcess.ts",
"rename.ts",
"services.ts",
"transform.ts",
"transpile.ts",
"shims.ts",
"signatureHelp.ts",
@@ -78,6 +79,7 @@
"formatting/smartIndenter.ts",
"formatting/tokenRange.ts",
"codeFixProvider.ts",
"codefixes/fixAddMissingMember.ts",
"codefixes/fixExtendsInterfaceBecomesImplements.ts",
"codefixes/fixClassIncorrectlyImplementsInterface.ts",
"codefixes/fixClassDoesntImplementInheritedAbstractMember.ts",
+6 -1
View File
@@ -39,7 +39,7 @@ namespace ts {
export interface Signature {
getDeclaration(): SignatureDeclaration;
getTypeParameters(): Type[];
getTypeParameters(): TypeParameter[];
getParameters(): Symbol[];
getReturnType(): Type;
getDocumentationComment(): SymbolDisplayPart[];
@@ -170,6 +170,11 @@ namespace ts {
* completions will not be provided
*/
getDirectories?(directoryName: string): string[];
/**
* Gets a set of custom transformers to use during emit.
*/
getCustomTransformers?(): CustomTransformers | undefined;
}
//
@@ -1,4 +1,4 @@
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
==== tests/cases/conformance/internalModules/DeclarationMerging/class.ts (0 errors) ====
@@ -17,7 +17,7 @@ tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): erro
module X.Y {
export module Point {
~~~~~
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
export var Origin = new Point(0, 0);
}
}
@@ -1,4 +1,4 @@
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
==== tests/cases/conformance/internalModules/DeclarationMerging/class.ts (0 errors) ====
@@ -17,7 +17,7 @@ tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): erro
module X.Y {
export module Point {
~~~~~
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
export var Origin = new Point(0, 0);
}
}
@@ -1,8 +1,8 @@
tests/cases/compiler/ClassDeclaration24.ts(1,7): error TS2414: Class name cannot be 'any'
tests/cases/compiler/ClassDeclaration24.ts(1,7): error TS2414: Class name cannot be 'any'.
==== tests/cases/compiler/ClassDeclaration24.ts (1 errors) ====
class any {
~~~
!!! error TS2414: Class name cannot be 'any'
!!! error TS2414: Class name cannot be 'any'.
}
@@ -1,5 +1,5 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of20.ts(3,20): error TS2448: Block-scoped variable 'v' used before its declaration.
tests/cases/conformance/statements/for-ofStatements/ES5For-of20.ts(4,15): error TS1155: 'const' declarations must be initialized
tests/cases/conformance/statements/for-ofStatements/ES5For-of20.ts(4,15): error TS1155: 'const' declarations must be initialized.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of20.ts (2 errors) ====
@@ -10,6 +10,6 @@ tests/cases/conformance/statements/for-ofStatements/ES5For-of20.ts(4,15): error
!!! error TS2448: Block-scoped variable 'v' used before its declaration.
const v;
~
!!! error TS1155: 'const' declarations must be initialized
!!! error TS1155: 'const' declarations must be initialized.
}
}
@@ -0,0 +1,9 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts(2,5): error TS2304: Cannot find name 'console'.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of33.ts (1 errors) ====
for (var v of ['a', 'b', 'c']) {
console.log(v);
~~~~~~~
!!! error TS2304: Cannot find name 'console'.
}
+31
View File
@@ -0,0 +1,31 @@
//// [ES5For-of33.ts]
for (var v of ['a', 'b', 'c']) {
console.log(v);
}
//// [ES5For-of33.js]
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
try {
for (var _a = __values(['a', 'b', 'c']), _b = _a.next(); !_b.done; _b = _a.next()) {
var v = _b.value;
console.log(v);
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a["return"])) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _c;
//# sourceMappingURL=ES5For-of33.js.map
@@ -0,0 +1,2 @@
//// [ES5For-of33.js.map]
{"version":3,"file":"ES5For-of33.js","sourceRoot":"","sources":["ES5For-of33.ts"],"names":[],"mappings":";;;;;;;;;;;IAAA,GAAG,CAAC,CAAU,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA;QAAxB,IAAI,CAAC,WAAA;QACN,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;KAClB"}
@@ -0,0 +1,128 @@
===================================================================
JsFile: ES5For-of33.js
mapUrl: ES5For-of33.js.map
sourceRoot:
sources: ES5For-of33.ts
===================================================================
-------------------------------------------------------------------
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of33.js
sourceFile:ES5For-of33.ts
-------------------------------------------------------------------
>>>var __values = (this && this.__values) || function (o) {
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
>>> if (m) return m.call(o);
>>> return {
>>> next: function () {
>>> if (o && i >= o.length) o = void 0;
>>> return { value: o && o[i++], done: !o };
>>> }
>>> };
>>>};
>>>try {
>>> for (var _a = __values(['a', 'b', 'c']), _b = _a.next(); !_b.done; _b = _a.next()) {
1 >^^^^
2 > ^^^
3 > ^
4 > ^
5 > ^^^^
6 > ^^^^^
7 > ^^^^^^^^^
8 > ^
9 > ^^^
10> ^^
11> ^^^
12> ^^
13> ^^^
14> ^
15> ^
16> ^^^^^^^^^^^^^^^^
1 >
2 > for
3 >
4 > (var v of
5 >
6 >
7 >
8 > [
9 > 'a'
10> ,
11> 'b'
12> ,
13> 'c'
14> ]
15>
16>
1 >Emitted(12, 5) Source(1, 1) + SourceIndex(0)
2 >Emitted(12, 8) Source(1, 4) + SourceIndex(0)
3 >Emitted(12, 9) Source(1, 5) + SourceIndex(0)
4 >Emitted(12, 10) Source(1, 15) + SourceIndex(0)
5 >Emitted(12, 14) Source(1, 15) + SourceIndex(0)
6 >Emitted(12, 19) Source(1, 15) + SourceIndex(0)
7 >Emitted(12, 28) Source(1, 15) + SourceIndex(0)
8 >Emitted(12, 29) Source(1, 16) + SourceIndex(0)
9 >Emitted(12, 32) Source(1, 19) + SourceIndex(0)
10>Emitted(12, 34) Source(1, 21) + SourceIndex(0)
11>Emitted(12, 37) Source(1, 24) + SourceIndex(0)
12>Emitted(12, 39) Source(1, 26) + SourceIndex(0)
13>Emitted(12, 42) Source(1, 29) + SourceIndex(0)
14>Emitted(12, 43) Source(1, 30) + SourceIndex(0)
15>Emitted(12, 44) Source(1, 30) + SourceIndex(0)
16>Emitted(12, 60) Source(1, 30) + SourceIndex(0)
---
>>> var v = _b.value;
1 >^^^^^^^^
2 > ^^^^
3 > ^
4 > ^^^^^^^^^^^
1 >
2 > var
3 > v
4 >
1 >Emitted(13, 9) Source(1, 6) + SourceIndex(0)
2 >Emitted(13, 13) Source(1, 10) + SourceIndex(0)
3 >Emitted(13, 14) Source(1, 11) + SourceIndex(0)
4 >Emitted(13, 25) Source(1, 11) + SourceIndex(0)
---
>>> console.log(v);
1 >^^^^^^^^
2 > ^^^^^^^
3 > ^
4 > ^^^
5 > ^
6 > ^
7 > ^
8 > ^
1 > of ['a', 'b', 'c']) {
>
2 > console
3 > .
4 > log
5 > (
6 > v
7 > )
8 > ;
1 >Emitted(14, 9) Source(2, 5) + SourceIndex(0)
2 >Emitted(14, 16) Source(2, 12) + SourceIndex(0)
3 >Emitted(14, 17) Source(2, 13) + SourceIndex(0)
4 >Emitted(14, 20) Source(2, 16) + SourceIndex(0)
5 >Emitted(14, 21) Source(2, 17) + SourceIndex(0)
6 >Emitted(14, 22) Source(2, 18) + SourceIndex(0)
7 >Emitted(14, 23) Source(2, 19) + SourceIndex(0)
8 >Emitted(14, 24) Source(2, 20) + SourceIndex(0)
---
>>> }
1 >^^^^^
1 >
>}
1 >Emitted(15, 6) Source(3, 2) + SourceIndex(0)
---
>>>}
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
>>>finally {
>>> try {
>>> if (_b && !_b.done && (_c = _a["return"])) _c.call(_a);
>>> }
>>> finally { if (e_1) throw e_1.error; }
>>>}
>>>var e_1, _c;
>>>//# sourceMappingURL=ES5For-of33.js.map
@@ -0,0 +1,12 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts(4,6): error TS2322: Type 'string' is not assignable to type 'number'.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of34.ts (1 errors) ====
function foo() {
return { x: 0 };
}
for (foo().x of ['a', 'b', 'c']) {
~~~~~~~
!!! error TS2322: Type 'string' is not assignable to type 'number'.
var p = foo().x;
}
+37
View File
@@ -0,0 +1,37 @@
//// [ES5For-of34.ts]
function foo() {
return { x: 0 };
}
for (foo().x of ['a', 'b', 'c']) {
var p = foo().x;
}
//// [ES5For-of34.js]
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
function foo() {
return { x: 0 };
}
try {
for (var _a = __values(['a', 'b', 'c']), _b = _a.next(); !_b.done; _b = _a.next()) {
foo().x = _b.value;
var p = foo().x;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_c = _a["return"])) _c.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _c;
//# sourceMappingURL=ES5For-of34.js.map
@@ -0,0 +1,2 @@
//// [ES5For-of34.js.map]
{"version":3,"file":"ES5For-of34.js","sourceRoot":"","sources":["ES5For-of34.ts"],"names":[],"mappings":";;;;;;;;;;AAAA;IACI,MAAM,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,CAAC;AACpB,CAAC;;IACD,GAAG,CAAC,CAAY,IAAA,KAAA,SAAA,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAA,gBAAA;QAA1B,GAAG,EAAE,CAAC,CAAC,WAAA;QACR,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC,CAAC,CAAC;KACnB"}
@@ -0,0 +1,184 @@
===================================================================
JsFile: ES5For-of34.js
mapUrl: ES5For-of34.js.map
sourceRoot:
sources: ES5For-of34.ts
===================================================================
-------------------------------------------------------------------
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of34.js
sourceFile:ES5For-of34.ts
-------------------------------------------------------------------
>>>var __values = (this && this.__values) || function (o) {
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
>>> if (m) return m.call(o);
>>> return {
>>> next: function () {
>>> if (o && i >= o.length) o = void 0;
>>> return { value: o && o[i++], done: !o };
>>> }
>>> };
>>>};
>>>function foo() {
1 >
2 >^^^^^^^^^^^^^^^^^^^^^->
1 >
1 >Emitted(11, 1) Source(1, 1) + SourceIndex(0)
---
>>> return { x: 0 };
1->^^^^
2 > ^^^^^^
3 > ^
4 > ^^
5 > ^
6 > ^^
7 > ^
8 > ^^
9 > ^
1->function foo() {
>
2 > return
3 >
4 > {
5 > x
6 > :
7 > 0
8 > }
9 > ;
1->Emitted(12, 5) Source(2, 5) + SourceIndex(0)
2 >Emitted(12, 11) Source(2, 11) + SourceIndex(0)
3 >Emitted(12, 12) Source(2, 12) + SourceIndex(0)
4 >Emitted(12, 14) Source(2, 14) + SourceIndex(0)
5 >Emitted(12, 15) Source(2, 15) + SourceIndex(0)
6 >Emitted(12, 17) Source(2, 17) + SourceIndex(0)
7 >Emitted(12, 18) Source(2, 18) + SourceIndex(0)
8 >Emitted(12, 20) Source(2, 20) + SourceIndex(0)
9 >Emitted(12, 21) Source(2, 21) + SourceIndex(0)
---
>>>}
1 >
2 >^
3 > ^^^^^->
1 >
>
2 >}
1 >Emitted(13, 1) Source(3, 1) + SourceIndex(0)
2 >Emitted(13, 2) Source(3, 2) + SourceIndex(0)
---
>>>try {
>>> for (var _a = __values(['a', 'b', 'c']), _b = _a.next(); !_b.done; _b = _a.next()) {
1->^^^^
2 > ^^^
3 > ^
4 > ^
5 > ^^^^
6 > ^^^^^
7 > ^^^^^^^^^
8 > ^
9 > ^^^
10> ^^
11> ^^^
12> ^^
13> ^^^
14> ^
15> ^
16> ^^^^^^^^^^^^^^^^
1->
>
2 > for
3 >
4 > (foo().x of
5 >
6 >
7 >
8 > [
9 > 'a'
10> ,
11> 'b'
12> ,
13> 'c'
14> ]
15>
16>
1->Emitted(15, 5) Source(4, 1) + SourceIndex(0)
2 >Emitted(15, 8) Source(4, 4) + SourceIndex(0)
3 >Emitted(15, 9) Source(4, 5) + SourceIndex(0)
4 >Emitted(15, 10) Source(4, 17) + SourceIndex(0)
5 >Emitted(15, 14) Source(4, 17) + SourceIndex(0)
6 >Emitted(15, 19) Source(4, 17) + SourceIndex(0)
7 >Emitted(15, 28) Source(4, 17) + SourceIndex(0)
8 >Emitted(15, 29) Source(4, 18) + SourceIndex(0)
9 >Emitted(15, 32) Source(4, 21) + SourceIndex(0)
10>Emitted(15, 34) Source(4, 23) + SourceIndex(0)
11>Emitted(15, 37) Source(4, 26) + SourceIndex(0)
12>Emitted(15, 39) Source(4, 28) + SourceIndex(0)
13>Emitted(15, 42) Source(4, 31) + SourceIndex(0)
14>Emitted(15, 43) Source(4, 32) + SourceIndex(0)
15>Emitted(15, 44) Source(4, 32) + SourceIndex(0)
16>Emitted(15, 60) Source(4, 32) + SourceIndex(0)
---
>>> foo().x = _b.value;
1 >^^^^^^^^
2 > ^^^
3 > ^^
4 > ^
5 > ^
6 > ^^^^^^^^^^^
1 >
2 > foo
3 > ()
4 > .
5 > x
6 >
1 >Emitted(16, 9) Source(4, 6) + SourceIndex(0)
2 >Emitted(16, 12) Source(4, 9) + SourceIndex(0)
3 >Emitted(16, 14) Source(4, 11) + SourceIndex(0)
4 >Emitted(16, 15) Source(4, 12) + SourceIndex(0)
5 >Emitted(16, 16) Source(4, 13) + SourceIndex(0)
6 >Emitted(16, 27) Source(4, 13) + SourceIndex(0)
---
>>> var p = foo().x;
1 >^^^^^^^^
2 > ^^^^
3 > ^
4 > ^^^
5 > ^^^
6 > ^^
7 > ^
8 > ^
9 > ^
1 > of ['a', 'b', 'c']) {
>
2 > var
3 > p
4 > =
5 > foo
6 > ()
7 > .
8 > x
9 > ;
1 >Emitted(17, 9) Source(5, 5) + SourceIndex(0)
2 >Emitted(17, 13) Source(5, 9) + SourceIndex(0)
3 >Emitted(17, 14) Source(5, 10) + SourceIndex(0)
4 >Emitted(17, 17) Source(5, 13) + SourceIndex(0)
5 >Emitted(17, 20) Source(5, 16) + SourceIndex(0)
6 >Emitted(17, 22) Source(5, 18) + SourceIndex(0)
7 >Emitted(17, 23) Source(5, 19) + SourceIndex(0)
8 >Emitted(17, 24) Source(5, 20) + SourceIndex(0)
9 >Emitted(17, 25) Source(5, 21) + SourceIndex(0)
---
>>> }
1 >^^^^^
1 >
>}
1 >Emitted(18, 6) Source(6, 2) + SourceIndex(0)
---
>>>}
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
>>>finally {
>>> try {
>>> if (_b && !_b.done && (_c = _a["return"])) _c.call(_a);
>>> }
>>> finally { if (e_1) throw e_1.error; }
>>>}
>>>var e_1, _c;
>>>//# sourceMappingURL=ES5For-of34.js.map
@@ -0,0 +1,13 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts(1,13): error TS2459: Type 'number' has no property 'x' and no string index signature.
tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts(1,23): error TS2459: Type 'number' has no property 'y' and no string index signature.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of35.ts (2 errors) ====
for (const {x: a = 0, y: b = 1} of [2, 3]) {
~
!!! error TS2459: Type 'number' has no property 'x' and no string index signature.
~
!!! error TS2459: Type 'number' has no property 'y' and no string index signature.
a;
b;
}
+33
View File
@@ -0,0 +1,33 @@
//// [ES5For-of35.ts]
for (const {x: a = 0, y: b = 1} of [2, 3]) {
a;
b;
}
//// [ES5For-of35.js]
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
try {
for (var _a = __values([2, 3]), _b = _a.next(); !_b.done; _b = _a.next()) {
var _c = _b.value, _d = _c.x, a = _d === void 0 ? 0 : _d, _e = _c.y, b = _e === void 0 ? 1 : _e;
a;
b;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_f = _a["return"])) _f.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _f;
//# sourceMappingURL=ES5For-of35.js.map
@@ -0,0 +1,2 @@
//// [ES5For-of35.js.map]
{"version":3,"file":"ES5For-of35.js","sourceRoot":"","sources":["ES5For-of35.ts"],"names":[],"mappings":";;;;;;;;;;;IAAA,GAAG,CAAC,CAA+B,IAAA,KAAA,SAAA,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,gBAAA;QAA9B,IAAA,aAAoB,EAAnB,SAAQ,EAAR,0BAAQ,EAAE,SAAQ,EAAR,0BAAQ;QAC1B,CAAC,CAAC;QACF,CAAC,CAAC;KACL"}
@@ -0,0 +1,142 @@
===================================================================
JsFile: ES5For-of35.js
mapUrl: ES5For-of35.js.map
sourceRoot:
sources: ES5For-of35.ts
===================================================================
-------------------------------------------------------------------
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of35.js
sourceFile:ES5For-of35.ts
-------------------------------------------------------------------
>>>var __values = (this && this.__values) || function (o) {
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
>>> if (m) return m.call(o);
>>> return {
>>> next: function () {
>>> if (o && i >= o.length) o = void 0;
>>> return { value: o && o[i++], done: !o };
>>> }
>>> };
>>>};
>>>try {
>>> for (var _a = __values([2, 3]), _b = _a.next(); !_b.done; _b = _a.next()) {
1 >^^^^
2 > ^^^
3 > ^
4 > ^
5 > ^^^^
6 > ^^^^^
7 > ^^^^^^^^^
8 > ^
9 > ^
10> ^^
11> ^
12> ^
13> ^
14> ^^^^^^^^^^^^^^^^
15> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
1 >
2 > for
3 >
4 > (const {x: a = 0, y: b = 1} of
5 >
6 >
7 >
8 > [
9 > 2
10> ,
11> 3
12> ]
13>
14>
1 >Emitted(12, 5) Source(1, 1) + SourceIndex(0)
2 >Emitted(12, 8) Source(1, 4) + SourceIndex(0)
3 >Emitted(12, 9) Source(1, 5) + SourceIndex(0)
4 >Emitted(12, 10) Source(1, 36) + SourceIndex(0)
5 >Emitted(12, 14) Source(1, 36) + SourceIndex(0)
6 >Emitted(12, 19) Source(1, 36) + SourceIndex(0)
7 >Emitted(12, 28) Source(1, 36) + SourceIndex(0)
8 >Emitted(12, 29) Source(1, 37) + SourceIndex(0)
9 >Emitted(12, 30) Source(1, 38) + SourceIndex(0)
10>Emitted(12, 32) Source(1, 40) + SourceIndex(0)
11>Emitted(12, 33) Source(1, 41) + SourceIndex(0)
12>Emitted(12, 34) Source(1, 42) + SourceIndex(0)
13>Emitted(12, 35) Source(1, 42) + SourceIndex(0)
14>Emitted(12, 51) Source(1, 42) + SourceIndex(0)
---
>>> var _c = _b.value, _d = _c.x, a = _d === void 0 ? 0 : _d, _e = _c.y, b = _e === void 0 ? 1 : _e;
1->^^^^^^^^
2 > ^^^^
3 > ^^^^^^^^^^^^^
4 > ^^
5 > ^^^^^^^^^
6 > ^^
7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^
8 > ^^
9 > ^^^^^^^^^
10> ^^
11> ^^^^^^^^^^^^^^^^^^^^^^^^^^
1->
2 >
3 > {x: a = 0, y: b = 1}
4 >
5 > x: a = 0
6 >
7 > x: a = 0
8 > ,
9 > y: b = 1
10>
11> y: b = 1
1->Emitted(13, 9) Source(1, 12) + SourceIndex(0)
2 >Emitted(13, 13) Source(1, 12) + SourceIndex(0)
3 >Emitted(13, 26) Source(1, 32) + SourceIndex(0)
4 >Emitted(13, 28) Source(1, 13) + SourceIndex(0)
5 >Emitted(13, 37) Source(1, 21) + SourceIndex(0)
6 >Emitted(13, 39) Source(1, 13) + SourceIndex(0)
7 >Emitted(13, 65) Source(1, 21) + SourceIndex(0)
8 >Emitted(13, 67) Source(1, 23) + SourceIndex(0)
9 >Emitted(13, 76) Source(1, 31) + SourceIndex(0)
10>Emitted(13, 78) Source(1, 23) + SourceIndex(0)
11>Emitted(13, 104) Source(1, 31) + SourceIndex(0)
---
>>> a;
1 >^^^^^^^^
2 > ^
3 > ^
4 > ^->
1 >} of [2, 3]) {
>
2 > a
3 > ;
1 >Emitted(14, 9) Source(2, 5) + SourceIndex(0)
2 >Emitted(14, 10) Source(2, 6) + SourceIndex(0)
3 >Emitted(14, 11) Source(2, 7) + SourceIndex(0)
---
>>> b;
1->^^^^^^^^
2 > ^
3 > ^
1->
>
2 > b
3 > ;
1->Emitted(15, 9) Source(3, 5) + SourceIndex(0)
2 >Emitted(15, 10) Source(3, 6) + SourceIndex(0)
3 >Emitted(15, 11) Source(3, 7) + SourceIndex(0)
---
>>> }
1 >^^^^^
1 >
>}
1 >Emitted(16, 6) Source(4, 2) + SourceIndex(0)
---
>>>}
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
>>>finally {
>>> try {
>>> if (_b && !_b.done && (_f = _a["return"])) _f.call(_a);
>>> }
>>> finally { if (e_1) throw e_1.error; }
>>>}
>>>var e_1, _f;
>>>//# sourceMappingURL=ES5For-of35.js.map
@@ -0,0 +1,10 @@
tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts(1,10): error TS2548: Type 'number' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator.
==== tests/cases/conformance/statements/for-ofStatements/ES5For-of36.ts (1 errors) ====
for (let [a = 0, b = 1] of [2, 3]) {
~~~~~~~~~~~~~~
!!! error TS2548: Type 'number' is not an array type or does not have a '[Symbol.iterator]()' method that returns an iterator.
a;
b;
}
+49
View File
@@ -0,0 +1,49 @@
//// [ES5For-of36.ts]
for (let [a = 0, b = 1] of [2, 3]) {
a;
b;
}
//// [ES5For-of36.js]
var __values = (this && this.__values) || function (o) {
var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
if (m) return m.call(o);
return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
};
var __read = (this && this.__read) || function (o, n) {
var m = typeof Symbol === "function" && o[Symbol.iterator];
if (!m) return o;
var i = m.call(o), r, ar = [], e;
try {
while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
}
catch (error) { e = { error: error }; }
finally {
try {
if (r && !r.done && (m = i["return"])) m.call(i);
}
finally { if (e) throw e.error; }
}
return ar;
};
try {
for (var _a = __values([2, 3]), _b = _a.next(); !_b.done; _b = _a.next()) {
var _c = __read(_b.value, 2), _d = _c[0], a = _d === void 0 ? 0 : _d, _e = _c[1], b = _e === void 0 ? 1 : _e;
a;
b;
}
}
catch (e_1_1) { e_1 = { error: e_1_1 }; }
finally {
try {
if (_b && !_b.done && (_f = _a["return"])) _f.call(_a);
}
finally { if (e_1) throw e_1.error; }
}
var e_1, _f;
//# sourceMappingURL=ES5For-of36.js.map
@@ -0,0 +1,2 @@
//// [ES5For-of36.js.map]
{"version":3,"file":"ES5For-of36.js","sourceRoot":"","sources":["ES5For-of36.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;IAAA,GAAG,CAAC,CAAuB,IAAA,KAAA,SAAA,CAAC,CAAC,EAAE,CAAC,CAAC,CAAA,gBAAA;QAAxB,IAAA,wBAAc,EAAb,UAAK,EAAL,0BAAK,EAAE,UAAK,EAAL,0BAAK;QAClB,CAAC,CAAC;QACF,CAAC,CAAC;KACL"}
@@ -0,0 +1,158 @@
===================================================================
JsFile: ES5For-of36.js
mapUrl: ES5For-of36.js.map
sourceRoot:
sources: ES5For-of36.ts
===================================================================
-------------------------------------------------------------------
emittedFile:tests/cases/conformance/statements/for-ofStatements/ES5For-of36.js
sourceFile:ES5For-of36.ts
-------------------------------------------------------------------
>>>var __values = (this && this.__values) || function (o) {
>>> var m = typeof Symbol === "function" && o[Symbol.iterator], i = 0;
>>> if (m) return m.call(o);
>>> return {
>>> next: function () {
>>> if (o && i >= o.length) o = void 0;
>>> return { value: o && o[i++], done: !o };
>>> }
>>> };
>>>};
>>>var __read = (this && this.__read) || function (o, n) {
>>> var m = typeof Symbol === "function" && o[Symbol.iterator];
>>> if (!m) return o;
>>> var i = m.call(o), r, ar = [], e;
>>> try {
>>> while ((n === void 0 || n-- > 0) && !(r = i.next()).done) ar.push(r.value);
>>> }
>>> catch (error) { e = { error: error }; }
>>> finally {
>>> try {
>>> if (r && !r.done && (m = i["return"])) m.call(i);
>>> }
>>> finally { if (e) throw e.error; }
>>> }
>>> return ar;
>>>};
>>>try {
>>> for (var _a = __values([2, 3]), _b = _a.next(); !_b.done; _b = _a.next()) {
1 >^^^^
2 > ^^^
3 > ^
4 > ^
5 > ^^^^
6 > ^^^^^
7 > ^^^^^^^^^
8 > ^
9 > ^
10> ^^
11> ^
12> ^
13> ^
14> ^^^^^^^^^^^^^^^^
15> ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^->
1 >
2 > for
3 >
4 > (let [a = 0, b = 1] of
5 >
6 >
7 >
8 > [
9 > 2
10> ,
11> 3
12> ]
13>
14>
1 >Emitted(28, 5) Source(1, 1) + SourceIndex(0)
2 >Emitted(28, 8) Source(1, 4) + SourceIndex(0)
3 >Emitted(28, 9) Source(1, 5) + SourceIndex(0)
4 >Emitted(28, 10) Source(1, 28) + SourceIndex(0)
5 >Emitted(28, 14) Source(1, 28) + SourceIndex(0)
6 >Emitted(28, 19) Source(1, 28) + SourceIndex(0)
7 >Emitted(28, 28) Source(1, 28) + SourceIndex(0)
8 >Emitted(28, 29) Source(1, 29) + SourceIndex(0)
9 >Emitted(28, 30) Source(1, 30) + SourceIndex(0)
10>Emitted(28, 32) Source(1, 32) + SourceIndex(0)
11>Emitted(28, 33) Source(1, 33) + SourceIndex(0)
12>Emitted(28, 34) Source(1, 34) + SourceIndex(0)
13>Emitted(28, 35) Source(1, 34) + SourceIndex(0)
14>Emitted(28, 51) Source(1, 34) + SourceIndex(0)
---
>>> var _c = __read(_b.value, 2), _d = _c[0], a = _d === void 0 ? 0 : _d, _e = _c[1], b = _e === void 0 ? 1 : _e;
1->^^^^^^^^
2 > ^^^^
3 > ^^^^^^^^^^^^^^^^^^^^^^^^
4 > ^^
5 > ^^^^^^^^^^
6 > ^^
7 > ^^^^^^^^^^^^^^^^^^^^^^^^^^
8 > ^^
9 > ^^^^^^^^^^
10> ^^
11> ^^^^^^^^^^^^^^^^^^^^^^^^^^
1->
2 >
3 > [a = 0, b = 1]
4 >
5 > a = 0
6 >
7 > a = 0
8 > ,
9 > b = 1
10>
11> b = 1
1->Emitted(29, 9) Source(1, 10) + SourceIndex(0)
2 >Emitted(29, 13) Source(1, 10) + SourceIndex(0)
3 >Emitted(29, 37) Source(1, 24) + SourceIndex(0)
4 >Emitted(29, 39) Source(1, 11) + SourceIndex(0)
5 >Emitted(29, 49) Source(1, 16) + SourceIndex(0)
6 >Emitted(29, 51) Source(1, 11) + SourceIndex(0)
7 >Emitted(29, 77) Source(1, 16) + SourceIndex(0)
8 >Emitted(29, 79) Source(1, 18) + SourceIndex(0)
9 >Emitted(29, 89) Source(1, 23) + SourceIndex(0)
10>Emitted(29, 91) Source(1, 18) + SourceIndex(0)
11>Emitted(29, 117) Source(1, 23) + SourceIndex(0)
---
>>> a;
1 >^^^^^^^^
2 > ^
3 > ^
4 > ^->
1 >] of [2, 3]) {
>
2 > a
3 > ;
1 >Emitted(30, 9) Source(2, 5) + SourceIndex(0)
2 >Emitted(30, 10) Source(2, 6) + SourceIndex(0)
3 >Emitted(30, 11) Source(2, 7) + SourceIndex(0)
---
>>> b;
1->^^^^^^^^
2 > ^
3 > ^
1->
>
2 > b
3 > ;
1->Emitted(31, 9) Source(3, 5) + SourceIndex(0)
2 >Emitted(31, 10) Source(3, 6) + SourceIndex(0)
3 >Emitted(31, 11) Source(3, 7) + SourceIndex(0)
---
>>> }
1 >^^^^^
1 >
>}
1 >Emitted(32, 6) Source(4, 2) + SourceIndex(0)
---
>>>}
>>>catch (e_1_1) { e_1 = { error: e_1_1 }; }
>>>finally {
>>> try {
>>> if (_b && !_b.done && (_f = _a["return"])) _f.call(_a);
>>> }
>>> finally { if (e_1) throw e_1.error; }
>>>}
>>>var e_1, _f;
>>>//# sourceMappingURL=ES5For-of36.js.map
@@ -1,4 +1,4 @@
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
tests/cases/conformance/internalModules/DeclarationMerging/module.ts(2,19): error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
tests/cases/conformance/internalModules/DeclarationMerging/simple.ts(13,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'fn' must be of type '() => { x: number; y: number; }', but here has type 'typeof Point'.
tests/cases/conformance/internalModules/DeclarationMerging/test.ts(2,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'fn' must be of type '() => { x: number; y: number; }', but here has type 'typeof Point'.
@@ -14,7 +14,7 @@ tests/cases/conformance/internalModules/DeclarationMerging/test.ts(2,5): error T
module A {
export module Point {
~~~~~
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged
!!! error TS2433: A namespace declaration cannot be in a different file from a class or function with which it is merged.
export var Origin = { x: 0, y: 0 };
}
}
@@ -3,9 +3,7 @@ function * foo(a = yield => yield) {
}
//// [FunctionDeclaration10_es6.js]
function* foo(a) {
if (a === void 0) { a = yield; }
}
function* foo(a = yield) { }
yield;
{
}
@@ -1,8 +0,0 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts (1 errors) ====
function * yield() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts ===
function * yield() {
>yield : Symbol(yield, Decl(FunctionDeclaration11_es6.ts, 0, 0))
}
@@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration11_es6.ts ===
function * yield() {
>yield : () => IterableIterator<any>
}
@@ -2,4 +2,4 @@
var v = function * yield() { }
//// [FunctionDeclaration12_es6.js]
var v = function* () { }, yield = function () { };
var v = function* () { }, yield = () => { };
@@ -1,11 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts(3,11): error TS2304: Cannot find name 'yield'.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts (2 errors) ====
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration13_es6.ts (1 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
// Legal to use 'yield' in a type context.
var v: yield;
~~~~~
@@ -1,8 +0,0 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts (1 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
}
@@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts ===
function * foo() {
>foo : Symbol(foo, Decl(FunctionDeclaration1_es6.ts, 0, 0))
}
@@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration1_es6.ts ===
function * foo() {
>foo : () => IterableIterator<any>
}
@@ -3,6 +3,5 @@ function f(yield = yield) {
}
//// [FunctionDeclaration3_es6.js]
function f(yield) {
if (yield === void 0) { yield = yield; }
function f(yield = yield) {
}
@@ -1,11 +1,8 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts(1,18): error TS2523: 'yield' expressions cannot be used in a parameter initializer.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts (2 errors) ====
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration6_es6.ts (1 errors) ====
function*foo(a = yield) {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~~~
!!! error TS2523: 'yield' expressions cannot be used in a parameter initializer.
}
@@ -3,6 +3,5 @@ function*foo(a = yield) {
}
//// [FunctionDeclaration6_es6.js]
function* foo(a) {
if (a === void 0) { a = yield; }
function* foo(a = yield) {
}
@@ -1,16 +1,10 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(1,9): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,11): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts(3,20): error TS2523: 'yield' expressions cannot be used in a parameter initializer.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts (3 errors) ====
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration7_es6.ts (1 errors) ====
function*bar() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
// 'yield' here is an identifier, and not a yield expression.
function*foo(a = yield) {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
~~~~~
!!! error TS2523: 'yield' expressions cannot be used in a parameter initializer.
}
@@ -8,7 +8,6 @@ function*bar() {
//// [FunctionDeclaration7_es6.js]
function* bar() {
// 'yield' here is an identifier, and not a yield expression.
function* foo(a) {
if (a === void 0) { a = yield; }
function* foo(a = yield) {
}
}
@@ -1,9 +0,0 @@
tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts(1,10): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts (1 errors) ====
function * foo() {
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
var v = { [yield]: foo }
}
@@ -5,6 +5,5 @@ function * foo() {
//// [FunctionDeclaration9_es6.js]
function* foo() {
var v = (_a = {}, _a[yield] = foo, _a);
var _a;
var v = { [yield]: foo };
}
@@ -0,0 +1,8 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts ===
function * foo() {
>foo : Symbol(foo, Decl(FunctionDeclaration9_es6.ts, 0, 0))
var v = { [yield]: foo }
>v : Symbol(v, Decl(FunctionDeclaration9_es6.ts, 1, 5))
>foo : Symbol(foo, Decl(FunctionDeclaration9_es6.ts, 0, 0))
}
@@ -0,0 +1,10 @@
=== tests/cases/conformance/es6/functionDeclarations/FunctionDeclaration9_es6.ts ===
function * foo() {
>foo : () => IterableIterator<any>
var v = { [yield]: foo }
>v : { [x: number]: () => IterableIterator<any>; }
>{ [yield]: foo } : { [x: number]: () => IterableIterator<any>; }
>yield : any
>foo : () => IterableIterator<any>
}
@@ -1,7 +0,0 @@
tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts(1,18): error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
==== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts (1 errors) ====
var v = function * () { }
~
!!! error TS1220: Generators are only available when targeting ECMAScript 2015 or higher.
@@ -0,0 +1,4 @@
=== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts ===
var v = function * () { }
>v : Symbol(v, Decl(FunctionExpression1_es6.ts, 0, 3))
@@ -0,0 +1,5 @@
=== tests/cases/conformance/es6/functionExpressions/FunctionExpression1_es6.ts ===
var v = function * () { }
>v : () => IterableIterator<any>
>function * () { } : () => IterableIterator<any>

Some files were not shown because too many files have changed in this diff Show More