Refactor node factory API, use node factory in parser (#35282)

* Refactor node factory API, use node factory in parser

* Move UnparsedSource nodes to factory

* Make most Node properties read-only

* Make pos/end/parent and JSDoc 'comment' read-only

* Update function/constructor-type factories

* Remove treeStateObserver

* Simplify Debug.deprecate

* Remove unused factory methods, simplify lazy factory methods

* Fix base factory used for source file updates

* Update test baseline due to merge from master

* Rename factory methods to be more consistent (#39058)
This commit is contained in:
Ron Buckton 2020-06-16 16:55:03 -07:00 committed by GitHub
parent 0232d4ae8e
commit eb3645f16b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
206 changed files with 23665 additions and 17367 deletions

View File

@ -43,7 +43,7 @@
},
"sourceMaps": true,
"smartStep": true,
"preLaunchTask": "tests",
"preLaunchTask": "gulp: tests",
"console": "integratedTerminal",
"outFiles": [
"${workspaceRoot}/built/local/run.js"

43
.vscode/tasks.json vendored
View File

@ -4,31 +4,42 @@
"version": "2.0.0",
"tasks": [
{
"type": "shell",
"identifier": "local",
"type": "gulp",
"label": "gulp: local",
"command": "gulp",
"args": ["local"],
"group": { "kind": "build", "isDefault": true },
"problemMatcher": ["$gulp-tsc"]
"task": "local",
"group": {
"kind": "build",
"isDefault": true
},
"problemMatcher": [
"$tsc"
]
},
{
"type": "shell",
"identifier": "tsc",
"type": "gulp",
"label": "gulp: tsc",
"command": "gulp",
"args": ["tsc"],
"task": "tsc",
"group": "build",
"problemMatcher": ["$gulp-tsc"]
"problemMatcher": [
"$tsc"
]
},
{
"type": "shell",
"identifier": "tests",
"type": "gulp",
"label": "gulp: tests",
"command": "gulp",
"args": ["tests"],
"task": "tests",
"group": "build",
"problemMatcher": ["$gulp-tsc"]
"problemMatcher": [
"$tsc"
]
},
{
"type": "gulp",
"task": "services",
"label": "gulp: services",
"problemMatcher": [
"$tsc"
],
}
]
}

1324
src/compat/deprecations.ts Normal file

File diff suppressed because it is too large Load Diff

12
src/compat/tsconfig.json Normal file
View File

@ -0,0 +1,12 @@
{
"extends": "../tsconfig-base",
"compilerOptions": {
"outFile": "../../built/local/compat.js"
},
"references": [
{ "path": "../compiler" }
],
"files": [
"deprecations.ts"
]
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -1516,6 +1516,20 @@ namespace ts {
};
}
/** A version of `memoize` that supports a single primitive argument */
export function memoizeOne<A extends string | number | boolean | undefined, T>(callback: (arg: A) => T): (arg: A) => T {
const map = createMap<T>();
return (arg: A) => {
const key = `${typeof arg}:${arg}`;
let value = map.get(key);
if (value === undefined && !map.has(key)) {
value = callback(arg);
map.set(key, value);
}
return value!;
};
}
/**
* High-order function, composes functions. Note that functions are composed inside-out;
* for example, `compose(a, b)` is the equivalent of `x => b(a(x))`.

View File

@ -79,6 +79,7 @@ namespace ts {
/** Array that is only intended to be pushed to, never read. */
export interface Push<T> {
push(...values: T[]): void;
/* @internal*/ readonly length: number;
}
/* @internal */

View File

@ -1,12 +1,72 @@
/* @internal */
namespace ts {
export namespace Debug {
let currentAssertionLevel = AssertionLevel.None;
export enum LogLevel {
Off,
Error,
Warning,
Info,
Verbose
}
// eslint-disable-next-line prefer-const
export interface LoggingHost {
log(level: LogLevel, s: string): void;
}
export interface DeprecationOptions {
message?: string;
error?: boolean;
since?: Version | string;
warnAfter?: Version | string;
errorAfter?: Version | string;
typeScriptVersion?: Version | string;
}
export namespace Debug {
let typeScriptVersion: Version | undefined;
/* eslint-disable prefer-const */
let currentAssertionLevel = AssertionLevel.None;
export let currentLogLevel = LogLevel.Warning;
export let isDebugging = false;
export let loggingHost: LoggingHost | undefined;
/* eslint-enable prefer-const */
type AssertionKeys = MatchingKeys<typeof Debug, AnyFunction>;
export function getTypeScriptVersion() {
return typeScriptVersion ?? (typeScriptVersion = new Version(version));
}
export function shouldLog(level: LogLevel): boolean {
return currentLogLevel <= level;
}
function logMessage(level: LogLevel, s: string): void {
if (loggingHost && shouldLog(level)) {
loggingHost.log(level, s);
}
}
export function log(s: string): void {
logMessage(LogLevel.Info, s);
}
export namespace log {
export function error(s: string): void {
logMessage(LogLevel.Error, s);
}
export function warn(s: string): void {
logMessage(LogLevel.Warning, s);
}
export function log(s: string): void {
logMessage(LogLevel.Info, s);
}
export function trace(s: string): void {
logMessage(LogLevel.Verbose, s);
}
}
const assertionCache: Partial<Record<AssertionKeys, { level: AssertionLevel, assertion: AnyFunction }>> = {};
@ -385,7 +445,7 @@ namespace ts {
if (nodeIsSynthesized(this)) return "";
const parseNode = getParseTreeNode(this);
const sourceFile = parseNode && getSourceFileOfNode(parseNode);
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode, includeTrivia) : "";
return sourceFile ? getSourceTextOfNodeFromSourceFile(sourceFile, parseNode!, includeTrivia) : "";
}
}
});
@ -410,5 +470,56 @@ namespace ts {
isDebugInfoEnabled = true;
}
function formatDeprecationMessage(name: string, error: boolean | undefined, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let deprecationMessage = error ? "DeprecationError: " : "DeprecationWarning: ";
deprecationMessage += `'${name}' `;
deprecationMessage += since ? `has been deprecated since v${since}` : "is deprecated";
deprecationMessage += error ? " and can no longer be used." : errorAfter ? ` and will no longer be usable after v${errorAfter}.` : ".";
deprecationMessage += message ? ` ${formatStringFromArgs(message, [name], 0)}` : "";
return deprecationMessage;
}
function createErrorDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
const deprecationMessage = formatDeprecationMessage(name, /*error*/ true, errorAfter, since, message);
return () => {
throw new TypeError(deprecationMessage);
};
}
function createWarningDeprecation(name: string, errorAfter: Version | undefined, since: Version | undefined, message: string | undefined) {
let hasWrittenDeprecation = false;
return () => {
if (!hasWrittenDeprecation) {
log.warn(formatDeprecationMessage(name, /*error*/ false, errorAfter, since, message));
hasWrittenDeprecation = true;
}
};
}
function createDeprecation(name: string, options: DeprecationOptions & { error: true }): () => never;
function createDeprecation(name: string, options?: DeprecationOptions): () => void;
function createDeprecation(name: string, options: DeprecationOptions = {}) {
const version = typeof options.typeScriptVersion === "string" ? new Version(options.typeScriptVersion) : options.typeScriptVersion ?? getTypeScriptVersion();
const errorAfter = typeof options.errorAfter === "string" ? new Version(options.errorAfter) : options.errorAfter;
const warnAfter = typeof options.warnAfter === "string" ? new Version(options.warnAfter) : options.warnAfter;
const since = typeof options.since === "string" ? new Version(options.since) : options.since ?? warnAfter;
const error = options.error || errorAfter && version.compareTo(errorAfter) <= 0;
const warn = !warnAfter || version.compareTo(warnAfter) >= 0;
return error ? createErrorDeprecation(name, errorAfter, since, options.message) :
warn ? createWarningDeprecation(name, errorAfter, since, options.message) :
noop;
}
function wrapFunction<F extends (...args: any[]) => any>(deprecation: () => void, func: F): F {
return function (this: unknown) {
deprecation();
return func.apply(this, arguments);
} as F;
}
export function deprecate<F extends (...args: any[]) => any>(func: F, options?: DeprecationOptions): F {
const deprecation = createDeprecation(getFunctionName(func), options);
return wrapFunction(deprecation, func);
}
}
}

View File

@ -28,7 +28,7 @@ namespace ts {
if (outFile(options)) {
const prepends = host.getPrependNodes();
if (sourceFiles.length || prepends.length) {
const bundle = createBundle(sourceFiles, prepends);
const bundle = factory.createBundle(sourceFiles, prepends);
const result = action(getOutputPathsFor(bundle, host, forceDtsEmit), bundle);
if (result) {
return result;
@ -356,7 +356,7 @@ namespace ts {
return;
}
// Transform the source files
const transform = transformNodes(resolver, host, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);
const transform = transformNodes(resolver, host, factory, compilerOptions, [sourceFileOrBundle], scriptTransformers, /*allowDtsFiles*/ false);
const printerOptions: PrinterOptions = {
removeComments: compilerOptions.removeComments,
@ -404,13 +404,13 @@ namespace ts {
const sourceFiles = isSourceFile(sourceFileOrBundle) ? [sourceFileOrBundle] : sourceFileOrBundle.sourceFiles;
const filesForEmit = forceDtsEmit ? sourceFiles : filter(sourceFiles, isSourceFileNotJson);
// Setup and perform the transformation to retrieve declarations from the input files
const inputListOrBundle = outFile(compilerOptions) ? [createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
const inputListOrBundle = outFile(compilerOptions) ? [factory.createBundle(filesForEmit, !isSourceFile(sourceFileOrBundle) ? sourceFileOrBundle.prepends : undefined)] : filesForEmit;
if (emitOnlyDtsFiles && !getEmitDeclarations(compilerOptions)) {
// Checker wont collect the linked aliases since thats only done when declaration is enabled.
// Do that here when emitting only dts files
filesForEmit.forEach(collectLinkedAliases);
}
const declarationTransform = transformNodes(resolver, host, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
const declarationTransform = transformNodes(resolver, host, factory, compilerOptions, inputListOrBundle, declarationTransformers, /*allowDtsFiles*/ false);
if (length(declarationTransform.diagnostics)) {
for (const diagnostic of declarationTransform.diagnostics!) {
emitterDiagnostics.add(diagnostic);
@ -680,30 +680,30 @@ namespace ts {
}
function createSourceFilesFromBundleBuildInfo(bundle: BundleBuildInfo, buildInfoDirectory: string, host: EmitUsingBuildInfoHost): readonly SourceFile[] {
const sourceFiles = bundle.sourceFiles.map(fileName => {
const sourceFile = createNode(SyntaxKind.SourceFile, 0, 0) as SourceFile;
const jsBundle = Debug.checkDefined(bundle.js);
const prologueMap = jsBundle.sources?.prologues && arrayToMap(jsBundle.sources.prologues, prologueInfo => "" + prologueInfo.file);
return bundle.sourceFiles.map((fileName, index) => {
const prologueInfo = prologueMap?.get("" + index);
const statements = prologueInfo?.directives.map(directive => {
const literal = setTextRange(factory.createStringLiteral(directive.expression.text), directive.expression);
const statement = setTextRange(factory.createExpressionStatement(literal), directive);
setParent(literal, statement);
return statement;
});
const eofToken = factory.createToken(SyntaxKind.EndOfFileToken);
const sourceFile = factory.createSourceFile(statements ?? [], eofToken, NodeFlags.None);
sourceFile.fileName = getRelativePathFromDirectory(
host.getCurrentDirectory(),
getNormalizedAbsolutePath(fileName, buildInfoDirectory),
!host.useCaseSensitiveFileNames()
);
sourceFile.text = "";
sourceFile.statements = createNodeArray();
sourceFile.text = prologueInfo?.text ?? "";
setTextRangePosWidth(sourceFile, 0, prologueInfo?.text.length ?? 0);
setEachParent(sourceFile.statements, sourceFile);
setTextRangePosWidth(eofToken, sourceFile.end, 0);
setParent(eofToken, sourceFile);
return sourceFile;
});
const jsBundle = Debug.checkDefined(bundle.js);
forEach(jsBundle.sources && jsBundle.sources.prologues, prologueInfo => {
const sourceFile = sourceFiles[prologueInfo.file];
sourceFile.text = prologueInfo.text;
sourceFile.end = prologueInfo.text.length;
sourceFile.statements = createNodeArray(prologueInfo.directives.map(directive => {
const statement = createNode(SyntaxKind.ExpressionStatement, directive.pos, directive.end) as PrologueDirective;
statement.expression = createNode(SyntaxKind.StringLiteral, directive.expression.pos, directive.expression.end) as StringLiteral;
statement.expression.text = directive.expression.text;
return statement;
}));
});
return sourceFiles;
}
/*@internal*/
@ -2292,7 +2292,7 @@ namespace ts {
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
const expression = cast(emitExpression(node.expression), isExpression);
const token = node.questionDotToken || createNode(SyntaxKind.DotToken, node.expression.end, node.name.pos) as DotToken;
const token = node.questionDotToken || setTextRangePosEnd(factory.createToken(SyntaxKind.DotToken) as DotToken, node.expression.end, node.name.pos);
const linesBeforeDot = getLinesBetweenNodes(node, node.expression, token);
const linesAfterDot = getLinesBetweenNodes(node, token, node.name);
@ -3559,15 +3559,15 @@ namespace ts {
}
function emitJSDocTypeLiteral(lit: JSDocTypeLiteral) {
emitList(lit, createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment);
emitList(lit, factory.createNodeArray(lit.jsDocPropertyTags), ListFormat.JSDocComment);
}
function emitJSDocSignature(sig: JSDocSignature) {
if (sig.typeParameters) {
emitList(sig, createNodeArray(sig.typeParameters), ListFormat.JSDocComment);
emitList(sig, factory.createNodeArray(sig.typeParameters), ListFormat.JSDocComment);
}
if (sig.parameters) {
emitList(sig, createNodeArray(sig.parameters), ListFormat.JSDocComment);
emitList(sig, factory.createNodeArray(sig.parameters), ListFormat.JSDocComment);
}
if (sig.type) {
writeLine();

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,56 @@
/* @internal */
namespace ts {
/**
* A `BaseNodeFactory` is an abstraction over an `ObjectAllocator` that handles caching `Node` constructors
* and allocating `Node` instances based on a set of predefined types.
*/
/* @internal */
export interface BaseNodeFactory {
createBaseSourceFileNode(kind: SyntaxKind): Node;
createBaseIdentifierNode(kind: SyntaxKind): Node;
createBasePrivateIdentifierNode(kind: SyntaxKind): Node;
createBaseTokenNode(kind: SyntaxKind): Node;
createBaseNode(kind: SyntaxKind): Node;
}
/**
* Creates a `BaseNodeFactory` which can be used to create `Node` instances from the constructors provided by the object allocator.
*/
export function createBaseNodeFactory(): BaseNodeFactory {
// tslint:disable variable-name
let NodeConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let TokenConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let IdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let PrivateIdentifierConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
let SourceFileConstructor: new (kind: SyntaxKind, pos?: number, end?: number) => Node;
// tslint:enable variable-name
return {
createBaseSourceFileNode,
createBaseIdentifierNode,
createBasePrivateIdentifierNode,
createBaseTokenNode,
createBaseNode
};
function createBaseSourceFileNode(kind: SyntaxKind): Node {
return new (SourceFileConstructor || (SourceFileConstructor = objectAllocator.getSourceFileConstructor()))(kind, /*pos*/ -1, /*end*/ -1);
}
function createBaseIdentifierNode(kind: SyntaxKind): Node {
return new (IdentifierConstructor || (IdentifierConstructor = objectAllocator.getIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1);
}
function createBasePrivateIdentifierNode(kind: SyntaxKind): Node {
return new (PrivateIdentifierConstructor || (PrivateIdentifierConstructor = objectAllocator.getPrivateIdentifierConstructor()))(kind, /*pos*/ -1, /*end*/ -1);
}
function createBaseTokenNode(kind: SyntaxKind): Node {
return new (TokenConstructor || (TokenConstructor = objectAllocator.getTokenConstructor()))(kind, /*pos*/ -1, /*end*/ -1);
}
function createBaseNode(kind: SyntaxKind): Node {
return new (NodeConstructor || (NodeConstructor = objectAllocator.getNodeConstructor()))(kind, /*pos*/ -1, /*end*/ -1);
}
}
}

View File

@ -0,0 +1,890 @@
/* @internal */
namespace ts {
export interface EmitHelperFactory {
getUnscopedHelperName(name: string): Identifier;
// TypeScript Helpers
createDecorateHelper(decoratorExpressions: readonly Expression[], target: Expression, memberName?: Expression, descriptor?: Expression): Expression;
createMetadataHelper(metadataKey: string, metadataValue: Expression): Expression;
createParamHelper(expression: Expression, parameterOffset: number): Expression;
// ES2018 Helpers
createAssignHelper(attributesSegments: readonly Expression[]): Expression;
createAwaitHelper(expression: Expression): Expression;
createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean): Expression;
createAsyncDelegatorHelper(expression: Expression): Expression;
createAsyncValuesHelper(expression: Expression): Expression;
// ES2018 Destructuring Helpers
createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression;
// ES2017 Helpers
createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block): Expression;
// ES2015 Helpers
createExtendsHelper(name: Identifier): Expression;
createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression): Expression;
createSpreadHelper(argumentList: readonly Expression[]): Expression;
createSpreadArraysHelper(argumentList: readonly Expression[]): Expression;
// ES2015 Destructuring Helpers
createValuesHelper(expression: Expression): Expression;
createReadHelper(iteratorRecord: Expression, count: number | undefined): Expression;
// ES2015 Generator Helpers
createGeneratorHelper(body: FunctionExpression): Expression;
// ES Module Helpers
createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined): Expression;
createImportStarHelper(expression: Expression): Expression;
createImportStarCallbackHelper(): Expression;
createImportDefaultHelper(expression: Expression): Expression;
// Class Fields Helpers
createClassPrivateFieldGetHelper(receiver: Expression, privateField: Identifier): Expression;
createClassPrivateFieldSetHelper(receiver: Expression, privateField: Identifier, value: Expression): Expression;
}
export function createEmitHelperFactory(context: TransformationContext): EmitHelperFactory {
const factory = context.factory;
return {
getUnscopedHelperName,
// TypeScript Helpers
createDecorateHelper,
createMetadataHelper,
createParamHelper,
// ES2018 Helpers
createAssignHelper,
createAwaitHelper,
createAsyncGeneratorHelper,
createAsyncDelegatorHelper,
createAsyncValuesHelper,
// ES2018 Destructuring Helpers
createRestHelper,
// ES2017 Helpers
createAwaiterHelper,
// ES2015 Helpers
createExtendsHelper,
createTemplateObjectHelper,
createSpreadHelper,
createSpreadArraysHelper,
// ES2015 Destructuring Helpers
createValuesHelper,
createReadHelper,
// ES2015 Generator Helpers
createGeneratorHelper,
// ES Module Helpers
createCreateBindingHelper,
createImportStarHelper,
createImportStarCallbackHelper,
createImportDefaultHelper,
// Class Fields Helpers
createClassPrivateFieldGetHelper,
createClassPrivateFieldSetHelper,
};
/**
* Gets an identifier for the name of an *unscoped* emit helper.
*/
function getUnscopedHelperName(name: string) {
return setEmitFlags(factory.createIdentifier(name), EmitFlags.HelperName | EmitFlags.AdviseOnEmitNode);
}
// TypeScript Helpers
function createDecorateHelper(decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression) {
context.requestEmitHelper(decorateHelper);
const argumentsArray: Expression[] = [];
argumentsArray.push(factory.createArrayLiteralExpression(decoratorExpressions, /*multiLine*/ true));
argumentsArray.push(target);
if (memberName) {
argumentsArray.push(memberName);
if (descriptor) {
argumentsArray.push(descriptor);
}
}
return factory.createCallExpression(
getUnscopedHelperName("__decorate"),
/*typeArguments*/ undefined,
argumentsArray
);
}
function createMetadataHelper(metadataKey: string, metadataValue: Expression) {
context.requestEmitHelper(metadataHelper);
return factory.createCallExpression(
getUnscopedHelperName("__metadata"),
/*typeArguments*/ undefined,
[
factory.createStringLiteral(metadataKey),
metadataValue
]
);
}
function createParamHelper(expression: Expression, parameterOffset: number, location?: TextRange) {
context.requestEmitHelper(paramHelper);
return setTextRange(
factory.createCallExpression(
getUnscopedHelperName("__param"),
/*typeArguments*/ undefined,
[
factory.createNumericLiteral(parameterOffset + ""),
expression
]
),
location
);
}
// ES2018 Helpers
function createAssignHelper(attributesSegments: Expression[]) {
if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) {
return factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier("Object"), "assign"),
/*typeArguments*/ undefined,
attributesSegments);
}
context.requestEmitHelper(assignHelper);
return factory.createCallExpression(
getUnscopedHelperName("__assign"),
/*typeArguments*/ undefined,
attributesSegments
);
}
function createAwaitHelper(expression: Expression) {
context.requestEmitHelper(awaitHelper);
return factory.createCallExpression(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]);
}
function createAsyncGeneratorHelper(generatorFunc: FunctionExpression, hasLexicalThis: boolean) {
context.requestEmitHelper(awaitHelper);
context.requestEmitHelper(asyncGeneratorHelper);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
return factory.createCallExpression(
getUnscopedHelperName("__asyncGenerator"),
/*typeArguments*/ undefined,
[
hasLexicalThis ? factory.createThis() : factory.createVoidZero(),
factory.createIdentifier("arguments"),
generatorFunc
]
);
}
function createAsyncDelegatorHelper(expression: Expression) {
context.requestEmitHelper(awaitHelper);
context.requestEmitHelper(asyncDelegator);
return factory.createCallExpression(
getUnscopedHelperName("__asyncDelegator"),
/*typeArguments*/ undefined,
[expression]
);
}
function createAsyncValuesHelper(expression: Expression) {
context.requestEmitHelper(asyncValues);
return factory.createCallExpression(
getUnscopedHelperName("__asyncValues"),
/*typeArguments*/ undefined,
[expression]
);
}
// ES2018 Destructuring Helpers
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
*/
function createRestHelper(value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[] | undefined, location: TextRange): Expression {
context.requestEmitHelper(restHelper);
const propertyNames: Expression[] = [];
let computedTempVariableOffset = 0;
for (let i = 0; i < elements.length - 1; i++) {
const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]);
if (propertyName) {
if (isComputedPropertyName(propertyName)) {
Debug.assertIsDefined(computedTempVariables, "Encountered computed property name but 'computedTempVariables' argument was not provided.");
const temp = computedTempVariables[computedTempVariableOffset];
computedTempVariableOffset++;
// typeof _tmp === "symbol" ? _tmp : _tmp + ""
propertyNames.push(
factory.createConditionalExpression(
factory.createTypeCheck(temp, "symbol"),
/*questionToken*/ undefined,
temp,
/*colonToken*/ undefined,
factory.createAdd(temp, factory.createStringLiteral(""))
)
);
}
else {
propertyNames.push(factory.createStringLiteralFromNode(propertyName));
}
}
}
return factory.createCallExpression(
getUnscopedHelperName("__rest"),
/*typeArguments*/ undefined,
[
value,
setTextRange(
factory.createArrayLiteralExpression(propertyNames),
location
)]
);
}
// ES2017 Helpers
function createAwaiterHelper(hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
context.requestEmitHelper(awaiterHelper);
const generatorFunc = factory.createFunctionExpression(
/*modifiers*/ undefined,
factory.createToken(SyntaxKind.AsteriskToken),
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
body
);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
return factory.createCallExpression(
getUnscopedHelperName("__awaiter"),
/*typeArguments*/ undefined,
[
hasLexicalThis ? factory.createThis() : factory.createVoidZero(),
hasLexicalArguments ? factory.createIdentifier("arguments") : factory.createVoidZero(),
promiseConstructor ? createExpressionFromEntityName(factory, promiseConstructor) : factory.createVoidZero(),
generatorFunc
]
);
}
// ES2015 Helpers
function createExtendsHelper(name: Identifier) {
context.requestEmitHelper(extendsHelper);
return factory.createCallExpression(
getUnscopedHelperName("__extends"),
/*typeArguments*/ undefined,
[name, factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel)]
);
}
function createTemplateObjectHelper(cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
context.requestEmitHelper(templateObjectHelper);
return factory.createCallExpression(
getUnscopedHelperName("__makeTemplateObject"),
/*typeArguments*/ undefined,
[cooked, raw]
);
}
function createSpreadHelper(argumentList: readonly Expression[]) {
context.requestEmitHelper(readHelper);
context.requestEmitHelper(spreadHelper);
return factory.createCallExpression(
getUnscopedHelperName("__spread"),
/*typeArguments*/ undefined,
argumentList
);
}
function createSpreadArraysHelper(argumentList: readonly Expression[]) {
context.requestEmitHelper(spreadArraysHelper);
return factory.createCallExpression(
getUnscopedHelperName("__spreadArrays"),
/*typeArguments*/ undefined,
argumentList
);
}
// ES2015 Destructuring Helpers
function createValuesHelper(expression: Expression) {
context.requestEmitHelper(valuesHelper);
return factory.createCallExpression(
getUnscopedHelperName("__values"),
/*typeArguments*/ undefined,
[expression]
);
}
function createReadHelper(iteratorRecord: Expression, count: number | undefined) {
context.requestEmitHelper(readHelper);
return factory.createCallExpression(
getUnscopedHelperName("__read"),
/*typeArguments*/ undefined,
count !== undefined
? [iteratorRecord, factory.createNumericLiteral(count + "")]
: [iteratorRecord]
);
}
// ES2015 Generator Helpers
function createGeneratorHelper(body: FunctionExpression) {
context.requestEmitHelper(generatorHelper);
return factory.createCallExpression(
getUnscopedHelperName("__generator"),
/*typeArguments*/ undefined,
[factory.createThis(), body]);
}
// ES Module Helpers
function createCreateBindingHelper(module: Expression, inputName: Expression, outputName: Expression | undefined) {
context.requestEmitHelper(createBindingHelper);
return factory.createCallExpression(
getUnscopedHelperName("__createBinding"),
/*typeArguments*/ undefined,
[factory.createIdentifier("exports"), module, inputName, ...(outputName ? [outputName] : [])]);
}
function createImportStarHelper(expression: Expression) {
context.requestEmitHelper(importStarHelper);
return factory.createCallExpression(
getUnscopedHelperName("__importStar"),
/*typeArguments*/ undefined,
[expression]
);
}
function createImportStarCallbackHelper() {
context.requestEmitHelper(importStarHelper);
return getUnscopedHelperName("__importStar");
}
function createImportDefaultHelper(expression: Expression) {
context.requestEmitHelper(importDefaultHelper);
return factory.createCallExpression(
getUnscopedHelperName("__importDefault"),
/*typeArguments*/ undefined,
[expression]
);
}
// Class Fields Helpers
function createClassPrivateFieldGetHelper(receiver: Expression, privateField: Identifier) {
context.requestEmitHelper(classPrivateFieldGetHelper);
return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldGet"), /*typeArguments*/ undefined, [receiver, privateField]);
}
function createClassPrivateFieldSetHelper(receiver: Expression, privateField: Identifier, value: Expression) {
context.requestEmitHelper(classPrivateFieldSetHelper);
return factory.createCallExpression(getUnscopedHelperName("__classPrivateFieldSet"), /*typeArguments*/ undefined, [receiver, privateField, value]);
}
}
/* @internal */
export function compareEmitHelpers(x: EmitHelper, y: EmitHelper) {
if (x === y) return Comparison.EqualTo;
if (x.priority === y.priority) return Comparison.EqualTo;
if (x.priority === undefined) return Comparison.GreaterThan;
if (y.priority === undefined) return Comparison.LessThan;
return compareValues(x.priority, y.priority);
}
/**
* @param input Template string input strings
* @param args Names which need to be made file-level unique
*/
export function helperString(input: TemplateStringsArray, ...args: string[]) {
return (uniqueName: EmitHelperUniqueNameCallback) => {
let result = "";
for (let i = 0; i < args.length; i++) {
result += input[i];
result += uniqueName(args[i]);
}
result += input[input.length - 1];
return result;
};
}
// TypeScript Helpers
export const decorateHelper: UnscopedEmitHelper = {
name: "typescript:decorate",
importName: "__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;
};`
};
export const metadataHelper: UnscopedEmitHelper = {
name: "typescript:metadata",
importName: "__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);
};`
};
export const paramHelper: UnscopedEmitHelper = {
name: "typescript:param",
importName: "__param",
scoped: false,
priority: 4,
text: `
var __param = (this && this.__param) || function (paramIndex, decorator) {
return function (target, key) { decorator(target, key, paramIndex); }
};`
};
// ES2018 Helpers
export const assignHelper: UnscopedEmitHelper = {
name: "typescript:assign",
importName: "__assign",
scoped: false,
priority: 1,
text: `
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};`
};
export const awaitHelper: UnscopedEmitHelper = {
name: "typescript:await",
importName: "__await",
scoped: false,
text: `
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`
};
export const asyncGeneratorHelper: UnscopedEmitHelper = {
name: "typescript:asyncGenerator",
importName: "__asyncGenerator",
scoped: false,
dependencies: [awaitHelper],
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 || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};`
};
export const asyncDelegator: UnscopedEmitHelper = {
name: "typescript:asyncDelegator",
importName: "__asyncDelegator",
scoped: false,
dependencies: [awaitHelper],
text: `
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
};`
};
export const asyncValues: UnscopedEmitHelper = {
name: "typescript:asyncValues",
importName: "__asyncValues",
scoped: false,
text: `
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};`
};
// ES2018 Destructuring Helpers
export const restHelper: UnscopedEmitHelper = {
name: "typescript:rest",
importName: "__rest",
scoped: false,
text: `
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};`
};
// ES2017 Helpers
export const awaiterHelper: UnscopedEmitHelper = {
name: "typescript:awaiter",
importName: "__awaiter",
scoped: false,
priority: 5,
text: `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};`
};
// ES2015 Helpers
export const extendsHelper: UnscopedEmitHelper = {
name: "typescript:extends",
importName: "__extends",
scoped: false,
priority: 0,
text: `
var __extends = (this && this.__extends) || (function () {
var extendStatics = function (d, b) {
extendStatics = Object.setPrototypeOf ||
({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) ||
function (d, b) { for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; };
return extendStatics(d, b);
};
return function (d, b) {
extendStatics(d, b);
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
})();`
};
export const templateObjectHelper: UnscopedEmitHelper = {
name: "typescript:makeTemplateObject",
importName: "__makeTemplateObject",
scoped: false,
priority: 0,
text: `
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};`
};
export const readHelper: UnscopedEmitHelper = {
name: "typescript:read",
importName: "__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 const spreadHelper: UnscopedEmitHelper = {
name: "typescript:spread",
importName: "__spread",
scoped: false,
dependencies: [readHelper],
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 const spreadArraysHelper: UnscopedEmitHelper = {
name: "typescript:spreadArrays",
importName: "__spreadArrays",
scoped: false,
text: `
var __spreadArrays = (this && this.__spreadArrays) || function () {
for (var s = 0, i = 0, il = arguments.length; i < il; i++) s += arguments[i].length;
for (var r = Array(s), k = 0, i = 0; i < il; i++)
for (var a = arguments[i], j = 0, jl = a.length; j < jl; j++, k++)
r[k] = a[j];
return r;
};`
};
// ES2015 Destructuring Helpers
export const valuesHelper: UnscopedEmitHelper = {
name: "typescript:values",
importName: "__values",
scoped: false,
text: `
var __values = (this && this.__values) || function(o) {
var s = typeof Symbol === "function" && Symbol.iterator, m = s && o[s], i = 0;
if (m) return m.call(o);
if (o && typeof o.length === "number") return {
next: function () {
if (o && i >= o.length) o = void 0;
return { value: o && o[i++], done: !o };
}
};
throw new TypeError(s ? "Object is not iterable." : "Symbol.iterator is not defined.");
};`
};
// ES2015 Generator Helpers
// The __generator helper is used by down-level transformations to emulate the runtime
// semantics of an ES2015 generator function. When called, this helper returns an
// object that implements the Iterator protocol, in that it has `next`, `return`, and
// `throw` methods that step through the generator when invoked.
//
// parameters:
// @param thisArg The value to use as the `this` binding for the transformed generator body.
// @param body A function that acts as the transformed generator body.
//
// variables:
// _ Persistent state for the generator that is shared between the helper and the
// generator body. The state object has the following members:
// sent() - A method that returns or throws the current completion value.
// label - The next point at which to resume evaluation of the generator body.
// trys - A stack of protected regions (try/catch/finally blocks).
// ops - A stack of pending instructions when inside of a finally block.
// f A value indicating whether the generator is executing.
// y An iterator to delegate for a yield*.
// t A temporary variable that holds one of the following values (note that these
// cases do not overlap):
// - The completion value when resuming from a `yield` or `yield*`.
// - The error value for a catch block.
// - The current protected region (array of try/catch/finally/end labels).
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
// of a `yield*`.
// - The result of evaluating the verb delegated to the expression of a `yield*`.
//
// functions:
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
// step(op) Evaluates opcodes in a generator body until execution is suspended or
// completed.
//
// The __generator helper understands a limited set of instructions:
// 0: next(value?) - Start or resume the generator with the specified value.
// 1: throw(error) - Resume the generator with an exception. If the generator is
// suspended inside of one or more protected regions, evaluates
// any intervening finally blocks between the current label and
// the nearest catch block or function boundary. If uncaught, the
// exception is thrown to the caller.
// 2: return(value?) - Resume the generator as if with a return. If the generator is
// suspended inside of one or more protected regions, evaluates any
// intervening finally blocks.
// 3: break(label) - Jump to the specified label. If the label is outside of the
// current protected region, evaluates any intervening finally
// blocks.
// 4: yield(value?) - Yield execution to the caller with an optional value. When
// resumed, the generator will continue at the next label.
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
// delegation completes, the generator will continue at the next
// label.
// 6: catch(error) - Handles an exception thrown from within the generator body. If
// the current label is inside of one or more protected regions,
// evaluates any intervening finally blocks between the current
// label and the nearest catch block or function boundary. If
// uncaught, the exception is thrown to the caller.
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
// entering a finally block.
//
// For examples of how these are used, see the comments in ./transformers/generators.ts
export const generatorHelper: UnscopedEmitHelper = {
name: "typescript:generator",
importName: "__generator",
scoped: false,
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, 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.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};`
};
// ES Module Helpers
export const createBindingHelper: UnscopedEmitHelper = {
name: "typescript:commonjscreatebinding",
importName: "__createBinding",
scoped: false,
priority: 1,
text: `
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));`
};
export const setModuleDefaultHelper: UnscopedEmitHelper = {
name: "typescript:commonjscreatevalue",
importName: "__setModuleDefault",
scoped: false,
priority: 1,
text: `
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});`
};
// emit helper for `import * as Name from "foo"`
export const importStarHelper: UnscopedEmitHelper = {
name: "typescript:commonjsimportstar",
importName: "__importStar",
scoped: false,
dependencies: [createBindingHelper, setModuleDefaultHelper],
priority: 2,
text: `
var __importStar = (this && this.__importStar) || function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k in mod) if (k !== "default" && Object.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
__setModuleDefault(result, mod);
return result;
};`
};
// emit helper for `import Name from "foo"`
export const importDefaultHelper: UnscopedEmitHelper = {
name: "typescript:commonjsimportdefault",
importName: "__importDefault",
scoped: false,
text: `
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};`
};
// Class fields helpers
export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
name: "typescript:classPrivateFieldGet",
scoped: false,
text: `
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
};`
};
export const classPrivateFieldSetHelper: UnscopedEmitHelper = {
name: "typescript:classPrivateFieldSet",
scoped: false,
text: `
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
};`
};
let allUnscopedEmitHelpers: ReadonlyMap<UnscopedEmitHelper> | undefined;
export function getAllUnscopedEmitHelpers() {
return allUnscopedEmitHelpers || (allUnscopedEmitHelpers = arrayToMap([
decorateHelper,
metadataHelper,
paramHelper,
assignHelper,
awaitHelper,
asyncGeneratorHelper,
asyncDelegator,
asyncValues,
restHelper,
awaiterHelper,
extendsHelper,
templateObjectHelper,
spreadHelper,
spreadArraysHelper,
valuesHelper,
readHelper,
generatorHelper,
importStarHelper,
importDefaultHelper,
classPrivateFieldGetHelper,
classPrivateFieldSetHelper,
createBindingHelper,
setModuleDefaultHelper
], helper => helper.name));
}
export const asyncSuperHelper: EmitHelper = {
name: "typescript:async-super",
scoped: true,
text: helperString`
const ${"_superIndex"} = name => super[name];`
};
export const advancedAsyncSuperHelper: EmitHelper = {
name: "typescript:advanced-async-super",
scoped: true,
text: helperString`
const ${"_superIndex"} = (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);`
};
}

View File

@ -0,0 +1,262 @@
namespace ts {
/**
* Associates a node with the current transformation, initializing
* various transient transformation properties.
* @internal
*/
export function getOrCreateEmitNode(node: Node): EmitNode {
if (!node.emitNode) {
if (isParseTreeNode(node)) {
// To avoid holding onto transformation artifacts, we keep track of any
// parse tree node we are annotating. This allows us to clean them up after
// all transformations have completed.
if (node.kind === SyntaxKind.SourceFile) {
return node.emitNode = { annotatedNodes: [node] } as EmitNode;
}
const sourceFile = getSourceFileOfNode(getParseTreeNode(getSourceFileOfNode(node))) ?? Debug.fail("Could not determine parsed source file.");
getOrCreateEmitNode(sourceFile).annotatedNodes!.push(node);
}
node.emitNode = {} as EmitNode;
}
return node.emitNode;
}
/**
* Clears any `EmitNode` entries from parse-tree nodes.
* @param sourceFile A source file.
*/
export function disposeEmitNodes(sourceFile: SourceFile | undefined) {
// During transformation we may need to annotate a parse tree node with transient
// transformation properties. As parse tree nodes live longer than transformation
// nodes, we need to make sure we reclaim any memory allocated for custom ranges
// from these nodes to ensure we do not hold onto entire subtrees just for position
// information. We also need to reset these nodes to a pre-transformation state
// for incremental parsing scenarios so that we do not impact later emit.
const annotatedNodes = getSourceFileOfNode(getParseTreeNode(sourceFile))?.emitNode?.annotatedNodes;
if (annotatedNodes) {
for (const node of annotatedNodes) {
node.emitNode = undefined;
}
}
}
/**
* Sets `EmitFlags.NoComments` on a node and removes any leading and trailing synthetic comments.
* @internal
*/
export function removeAllComments<T extends Node>(node: T): T {
const emitNode = getOrCreateEmitNode(node);
emitNode.flags |= EmitFlags.NoComments;
emitNode.leadingComments = undefined;
emitNode.trailingComments = undefined;
return node;
}
/**
* Sets flags that control emit behavior of a node.
*/
export function setEmitFlags<T extends Node>(node: T, emitFlags: EmitFlags) {
getOrCreateEmitNode(node).flags = emitFlags;
return node;
}
/**
* Sets flags that control emit behavior of a node.
*/
/* @internal */
export function addEmitFlags<T extends Node>(node: T, emitFlags: EmitFlags) {
const emitNode = getOrCreateEmitNode(node);
emitNode.flags = emitNode.flags | emitFlags;
return node;
}
/**
* Gets a custom text range to use when emitting source maps.
*/
export function getSourceMapRange(node: Node): SourceMapRange {
return node.emitNode?.sourceMapRange ?? node;
}
/**
* Sets a custom text range to use when emitting source maps.
*/
export function setSourceMapRange<T extends Node>(node: T, range: SourceMapRange | undefined) {
getOrCreateEmitNode(node).sourceMapRange = range;
return node;
}
/**
* Gets the TextRange to use for source maps for a token of a node.
*/
export function getTokenSourceMapRange(node: Node, token: SyntaxKind): SourceMapRange | undefined {
return node.emitNode?.tokenSourceMapRanges?.[token];
}
/**
* 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: SourceMapRange | undefined) {
const emitNode = getOrCreateEmitNode(node);
const tokenSourceMapRanges = emitNode.tokenSourceMapRanges ?? (emitNode.tokenSourceMapRanges = []);
tokenSourceMapRanges[token] = range;
return node;
}
/**
* Gets a custom text range to use when emitting comments.
*/
/*@internal*/
export function getStartsOnNewLine(node: Node) {
return node.emitNode?.startsOnNewLine;
}
/**
* Sets a custom text range to use when emitting comments.
*/
/*@internal*/
export function setStartsOnNewLine<T extends Node>(node: T, newLine: boolean) {
getOrCreateEmitNode(node).startsOnNewLine = newLine;
return node;
}
/**
* Gets a custom text range to use when emitting comments.
*/
export function getCommentRange(node: Node) {
return node.emitNode?.commentRange ?? node;
}
/**
* Sets a custom text range to use when emitting comments.
*/
export function setCommentRange<T extends Node>(node: T, range: TextRange) {
getOrCreateEmitNode(node).commentRange = range;
return node;
}
export function getSyntheticLeadingComments(node: Node): SynthesizedComment[] | undefined {
return node.emitNode?.leadingComments;
}
export function setSyntheticLeadingComments<T extends Node>(node: T, comments: SynthesizedComment[] | undefined) {
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<SynthesizedComment>(getSyntheticLeadingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text }));
}
export function getSyntheticTrailingComments(node: Node): SynthesizedComment[] | undefined {
return node.emitNode?.trailingComments;
}
export function setSyntheticTrailingComments<T extends Node>(node: T, comments: SynthesizedComment[] | undefined) {
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<SynthesizedComment>(getSyntheticTrailingComments(node), { kind, pos: -1, end: -1, hasTrailingNewLine, text }));
}
export function moveSyntheticComments<T extends Node>(node: T, original: Node): T {
setSyntheticLeadingComments(node, getSyntheticLeadingComments(original));
setSyntheticTrailingComments(node, getSyntheticTrailingComments(original));
const emit = getOrCreateEmitNode(original);
emit.leadingComments = undefined;
emit.trailingComments = undefined;
return node;
}
/**
* Gets the constant value to emit for an expression representing an enum.
*/
export function getConstantValue(node: AccessExpression): string | number | undefined {
return node.emitNode?.constantValue;
}
/**
* Sets the constant value to emit for an expression.
*/
export function setConstantValue(node: AccessExpression, value: string | number): AccessExpression {
const emitNode = getOrCreateEmitNode(node);
emitNode.constantValue = value;
return node;
}
/**
* Adds an EmitHelper to a node.
*/
export function addEmitHelper<T extends Node>(node: T, helper: EmitHelper): T {
const emitNode = getOrCreateEmitNode(node);
emitNode.helpers = append(emitNode.helpers, helper);
return node;
}
/**
* Add EmitHelpers to a node.
*/
export function addEmitHelpers<T extends Node>(node: T, helpers: EmitHelper[] | undefined): T {
if (some(helpers)) {
const emitNode = getOrCreateEmitNode(node);
for (const helper of helpers) {
emitNode.helpers = appendIfUnique(emitNode.helpers, helper);
}
}
return node;
}
/**
* Removes an EmitHelper from a node.
*/
export function removeEmitHelper(node: Node, helper: EmitHelper): boolean {
const helpers = node.emitNode?.helpers;
if (helpers) {
return orderedRemoveItem(helpers, helper);
}
return false;
}
/**
* Gets the EmitHelpers of a node.
*/
export function getEmitHelpers(node: Node): EmitHelper[] | undefined {
return node.emitNode?.helpers;
}
/**
* Moves matching emit helpers from a source node to a target node.
*/
export function moveEmitHelpers(source: Node, target: Node, predicate: (helper: EmitHelper) => boolean) {
const sourceEmitNode = source.emitNode;
const sourceEmitHelpers = sourceEmitNode && sourceEmitNode.helpers;
if (!some(sourceEmitHelpers)) return;
const targetEmitNode = getOrCreateEmitNode(target);
let helpersRemoved = 0;
for (let i = 0; i < sourceEmitHelpers.length; i++) {
const helper = sourceEmitHelpers[i];
if (predicate(helper)) {
helpersRemoved++;
targetEmitNode.helpers = appendIfUnique(targetEmitNode.helpers, helper);
}
else if (helpersRemoved > 0) {
sourceEmitHelpers[i - helpersRemoved] = helper;
}
}
if (helpersRemoved > 0) {
sourceEmitHelpers.length -= helpersRemoved;
}
}
/* @internal */
export function ignoreSourceNewlines<T extends Node>(node: T): T {
getOrCreateEmitNode(node).flags |= EmitFlags.IgnoreSourceNewlines;
return node;
}
}

View File

@ -0,0 +1,137 @@
/* @internal */
namespace ts {
export function createNodeConverters(factory: NodeFactory): NodeConverters {
return {
convertToFunctionBlock,
convertToFunctionExpression,
convertToArrayAssignmentElement,
convertToObjectAssignmentElement,
convertToAssignmentPattern,
convertToObjectAssignmentPattern,
convertToArrayAssignmentPattern,
convertToAssignmentElementTarget,
};
function convertToFunctionBlock(node: ConciseBody, multiLine?: boolean): Block {
if (isBlock(node)) return node;
const returnStatement = factory.createReturnStatement(node);
setTextRange(returnStatement, node);
const body = factory.createBlock([returnStatement], multiLine);
setTextRange(body, node);
return body;
}
function convertToFunctionExpression(node: FunctionDeclaration) {
if (!node.body) return Debug.fail(`Cannot convert a FunctionDeclaration without a body`);
const updated = factory.createFunctionExpression(
node.modifiers,
node.asteriskToken,
node.name,
node.typeParameters,
node.parameters,
node.type,
node.body
);
setOriginalNode(updated, node);
setTextRange(updated, node);
if (getStartsOnNewLine(node)) {
setStartsOnNewLine(updated, /*newLine*/ true);
}
return updated;
}
function convertToArrayAssignmentElement(element: ArrayBindingOrAssignmentElement) {
if (isBindingElement(element)) {
if (element.dotDotDotToken) {
Debug.assertNode(element.name, isIdentifier);
return setOriginalNode(setTextRange(factory.createSpreadElement(element.name), element), element);
}
const expression = convertToAssignmentElementTarget(element.name);
return element.initializer
? setOriginalNode(
setTextRange(
factory.createAssignment(expression, element.initializer),
element
),
element
)
: expression;
}
return cast(element, isExpression);
}
function convertToObjectAssignmentElement(element: ObjectBindingOrAssignmentElement) {
if (isBindingElement(element)) {
if (element.dotDotDotToken) {
Debug.assertNode(element.name, isIdentifier);
return setOriginalNode(setTextRange(factory.createSpreadAssignment(element.name), element), element);
}
if (element.propertyName) {
const expression = convertToAssignmentElementTarget(element.name);
return setOriginalNode(setTextRange(factory.createPropertyAssignment(element.propertyName, element.initializer ? factory.createAssignment(expression, element.initializer) : expression), element), element);
}
Debug.assertNode(element.name, isIdentifier);
return setOriginalNode(setTextRange(factory.createShorthandPropertyAssignment(element.name, element.initializer), element), element);
}
return cast(element, isObjectLiteralElementLike);
}
function convertToAssignmentPattern(node: BindingOrAssignmentPattern): AssignmentPattern {
switch (node.kind) {
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ArrayLiteralExpression:
return convertToArrayAssignmentPattern(node);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ObjectLiteralExpression:
return convertToObjectAssignmentPattern(node);
}
}
function convertToObjectAssignmentPattern(node: ObjectBindingOrAssignmentPattern) {
if (isObjectBindingPattern(node)) {
return setOriginalNode(
setTextRange(
factory.createObjectLiteralExpression(map(node.elements, convertToObjectAssignmentElement)),
node
),
node
);
}
return cast(node, isObjectLiteralExpression);
}
function convertToArrayAssignmentPattern(node: ArrayBindingOrAssignmentPattern) {
if (isArrayBindingPattern(node)) {
return setOriginalNode(
setTextRange(
factory.createArrayLiteralExpression(map(node.elements, convertToArrayAssignmentElement)),
node
),
node
);
}
return cast(node, isArrayLiteralExpression);
}
function convertToAssignmentElementTarget(node: BindingOrAssignmentElementTarget): Expression {
if (isBindingPattern(node)) {
return convertToAssignmentPattern(node);
}
return cast(node, isExpression);
}
}
export const nullNodeConverters: NodeConverters = {
convertToFunctionBlock: notImplemented,
convertToFunctionExpression: notImplemented,
convertToArrayAssignmentElement: notImplemented,
convertToObjectAssignmentElement: notImplemented,
convertToAssignmentPattern: notImplemented,
convertToObjectAssignmentPattern: notImplemented,
convertToArrayAssignmentPattern: notImplemented,
convertToAssignmentElementTarget: notImplemented,
};
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,818 @@
namespace ts {
// Literals
export function isNumericLiteral(node: Node): node is NumericLiteral {
return node.kind === SyntaxKind.NumericLiteral;
}
export function isBigIntLiteral(node: Node): node is BigIntLiteral {
return node.kind === SyntaxKind.BigIntLiteral;
}
export function isStringLiteral(node: Node): node is StringLiteral {
return node.kind === SyntaxKind.StringLiteral;
}
export function isJsxText(node: Node): node is JsxText {
return node.kind === SyntaxKind.JsxText;
}
export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral {
return node.kind === SyntaxKind.RegularExpressionLiteral;
}
export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral {
return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
// Pseudo-literals
export function isTemplateHead(node: Node): node is TemplateHead {
return node.kind === SyntaxKind.TemplateHead;
}
export function isTemplateMiddle(node: Node): node is TemplateMiddle {
return node.kind === SyntaxKind.TemplateMiddle;
}
export function isTemplateTail(node: Node): node is TemplateTail {
return node.kind === SyntaxKind.TemplateTail;
}
// Identifiers
export function isIdentifier(node: Node): node is Identifier {
return node.kind === SyntaxKind.Identifier;
}
// Names
export function isQualifiedName(node: Node): node is QualifiedName {
return node.kind === SyntaxKind.QualifiedName;
}
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
return node.kind === SyntaxKind.ComputedPropertyName;
}
export function isPrivateIdentifier(node: Node): node is PrivateIdentifier {
return node.kind === SyntaxKind.PrivateIdentifier;
}
// Tokens
/*@internal*/
export function isSuperKeyword(node: Node): node is Token<SyntaxKind.SuperKeyword> {
return node.kind === SyntaxKind.SuperKeyword;
}
/*@internal*/
export function isImportKeyword(node: Node): node is Token<SyntaxKind.ImportKeyword> {
return node.kind === SyntaxKind.ImportKeyword;
}
/*@internal*/
export function isCommaToken(node: Node): node is Token<SyntaxKind.CommaToken> {
return node.kind === SyntaxKind.CommaToken;
}
/*@internal*/
export function isQuestionToken(node: Node): node is Token<SyntaxKind.QuestionToken> {
return node.kind === SyntaxKind.QuestionToken;
}
/*@internal*/
export function isExclamationToken(node: Node): node is Token<SyntaxKind.ExclamationToken> {
return node.kind === SyntaxKind.ExclamationToken;
}
// Signature elements
export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration {
return node.kind === SyntaxKind.TypeParameter;
}
// TODO(rbuckton): Rename to 'isParameterDeclaration'
export function isParameter(node: Node): node is ParameterDeclaration {
return node.kind === SyntaxKind.Parameter;
}
export function isDecorator(node: Node): node is Decorator {
return node.kind === SyntaxKind.Decorator;
}
// TypeMember
export function isPropertySignature(node: Node): node is PropertySignature {
return node.kind === SyntaxKind.PropertySignature;
}
export function isPropertyDeclaration(node: Node): node is PropertyDeclaration {
return node.kind === SyntaxKind.PropertyDeclaration;
}
export function isMethodSignature(node: Node): node is MethodSignature {
return node.kind === SyntaxKind.MethodSignature;
}
export function isMethodDeclaration(node: Node): node is MethodDeclaration {
return node.kind === SyntaxKind.MethodDeclaration;
}
export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration {
return node.kind === SyntaxKind.Constructor;
}
export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration {
return node.kind === SyntaxKind.GetAccessor;
}
export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration {
return node.kind === SyntaxKind.SetAccessor;
}
export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration {
return node.kind === SyntaxKind.CallSignature;
}
export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration {
return node.kind === SyntaxKind.ConstructSignature;
}
export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration {
return node.kind === SyntaxKind.IndexSignature;
}
// Type
export function isTypePredicateNode(node: Node): node is TypePredicateNode {
return node.kind === SyntaxKind.TypePredicate;
}
export function isTypeReferenceNode(node: Node): node is TypeReferenceNode {
return node.kind === SyntaxKind.TypeReference;
}
export function isFunctionTypeNode(node: Node): node is FunctionTypeNode {
return node.kind === SyntaxKind.FunctionType;
}
export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode {
return node.kind === SyntaxKind.ConstructorType;
}
export function isTypeQueryNode(node: Node): node is TypeQueryNode {
return node.kind === SyntaxKind.TypeQuery;
}
export function isTypeLiteralNode(node: Node): node is TypeLiteralNode {
return node.kind === SyntaxKind.TypeLiteral;
}
export function isArrayTypeNode(node: Node): node is ArrayTypeNode {
return node.kind === SyntaxKind.ArrayType;
}
export function isTupleTypeNode(node: Node): node is TupleTypeNode {
return node.kind === SyntaxKind.TupleType;
}
export function isOptionalTypeNode(node: Node): node is OptionalTypeNode {
return node.kind === SyntaxKind.OptionalType;
}
export function isRestTypeNode(node: Node): node is RestTypeNode {
return node.kind === SyntaxKind.RestType;
}
export function isUnionTypeNode(node: Node): node is UnionTypeNode {
return node.kind === SyntaxKind.UnionType;
}
export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode {
return node.kind === SyntaxKind.IntersectionType;
}
export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode {
return node.kind === SyntaxKind.ConditionalType;
}
export function isInferTypeNode(node: Node): node is InferTypeNode {
return node.kind === SyntaxKind.InferType;
}
export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode {
return node.kind === SyntaxKind.ParenthesizedType;
}
export function isThisTypeNode(node: Node): node is ThisTypeNode {
return node.kind === SyntaxKind.ThisType;
}
export function isTypeOperatorNode(node: Node): node is TypeOperatorNode {
return node.kind === SyntaxKind.TypeOperator;
}
export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode {
return node.kind === SyntaxKind.IndexedAccessType;
}
export function isMappedTypeNode(node: Node): node is MappedTypeNode {
return node.kind === SyntaxKind.MappedType;
}
export function isLiteralTypeNode(node: Node): node is LiteralTypeNode {
return node.kind === SyntaxKind.LiteralType;
}
export function isImportTypeNode(node: Node): node is ImportTypeNode {
return node.kind === SyntaxKind.ImportType;
}
// Binding patterns
export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern {
return node.kind === SyntaxKind.ObjectBindingPattern;
}
export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern {
return node.kind === SyntaxKind.ArrayBindingPattern;
}
export function isBindingElement(node: Node): node is BindingElement {
return node.kind === SyntaxKind.BindingElement;
}
// Expression
export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
return node.kind === SyntaxKind.ArrayLiteralExpression;
}
export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression {
return node.kind === SyntaxKind.ObjectLiteralExpression;
}
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression;
}
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
return node.kind === SyntaxKind.ElementAccessExpression;
}
export function isCallExpression(node: Node): node is CallExpression {
return node.kind === SyntaxKind.CallExpression;
}
export function isNewExpression(node: Node): node is NewExpression {
return node.kind === SyntaxKind.NewExpression;
}
export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression {
return node.kind === SyntaxKind.TaggedTemplateExpression;
}
export function isTypeAssertionExpression(node: Node): node is TypeAssertion {
return node.kind === SyntaxKind.TypeAssertionExpression;
}
export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
return node.kind === SyntaxKind.ParenthesizedExpression;
}
export function isFunctionExpression(node: Node): node is FunctionExpression {
return node.kind === SyntaxKind.FunctionExpression;
}
export function isArrowFunction(node: Node): node is ArrowFunction {
return node.kind === SyntaxKind.ArrowFunction;
}
export function isDeleteExpression(node: Node): node is DeleteExpression {
return node.kind === SyntaxKind.DeleteExpression;
}
export function isTypeOfExpression(node: Node): node is TypeOfExpression {
return node.kind === SyntaxKind.TypeOfExpression;
}
export function isVoidExpression(node: Node): node is VoidExpression {
return node.kind === SyntaxKind.VoidExpression;
}
export function isAwaitExpression(node: Node): node is AwaitExpression {
return node.kind === SyntaxKind.AwaitExpression;
}
export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression {
return node.kind === SyntaxKind.PrefixUnaryExpression;
}
export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression {
return node.kind === SyntaxKind.PostfixUnaryExpression;
}
export function isBinaryExpression(node: Node): node is BinaryExpression {
return node.kind === SyntaxKind.BinaryExpression;
}
export function isConditionalExpression(node: Node): node is ConditionalExpression {
return node.kind === SyntaxKind.ConditionalExpression;
}
export function isTemplateExpression(node: Node): node is TemplateExpression {
return node.kind === SyntaxKind.TemplateExpression;
}
export function isYieldExpression(node: Node): node is YieldExpression {
return node.kind === SyntaxKind.YieldExpression;
}
export function isSpreadElement(node: Node): node is SpreadElement {
return node.kind === SyntaxKind.SpreadElement;
}
export function isClassExpression(node: Node): node is ClassExpression {
return node.kind === SyntaxKind.ClassExpression;
}
export function isOmittedExpression(node: Node): node is OmittedExpression {
return node.kind === SyntaxKind.OmittedExpression;
}
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
}
export function isAsExpression(node: Node): node is AsExpression {
return node.kind === SyntaxKind.AsExpression;
}
export function isNonNullExpression(node: Node): node is NonNullExpression {
return node.kind === SyntaxKind.NonNullExpression;
}
export function isMetaProperty(node: Node): node is MetaProperty {
return node.kind === SyntaxKind.MetaProperty;
}
export function isSyntheticExpression(node: Node): node is SyntheticExpression {
return node.kind === SyntaxKind.SyntheticExpression;
}
export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression {
return node.kind === SyntaxKind.PartiallyEmittedExpression;
}
export function isCommaListExpression(node: Node): node is CommaListExpression {
return node.kind === SyntaxKind.CommaListExpression;
}
// Misc
export function isTemplateSpan(node: Node): node is TemplateSpan {
return node.kind === SyntaxKind.TemplateSpan;
}
export function isSemicolonClassElement(node: Node): node is SemicolonClassElement {
return node.kind === SyntaxKind.SemicolonClassElement;
}
// Elements
export function isBlock(node: Node): node is Block {
return node.kind === SyntaxKind.Block;
}
export function isVariableStatement(node: Node): node is VariableStatement {
return node.kind === SyntaxKind.VariableStatement;
}
export function isEmptyStatement(node: Node): node is EmptyStatement {
return node.kind === SyntaxKind.EmptyStatement;
}
export function isExpressionStatement(node: Node): node is ExpressionStatement {
return node.kind === SyntaxKind.ExpressionStatement;
}
export function isIfStatement(node: Node): node is IfStatement {
return node.kind === SyntaxKind.IfStatement;
}
export function isDoStatement(node: Node): node is DoStatement {
return node.kind === SyntaxKind.DoStatement;
}
export function isWhileStatement(node: Node): node is WhileStatement {
return node.kind === SyntaxKind.WhileStatement;
}
export function isForStatement(node: Node): node is ForStatement {
return node.kind === SyntaxKind.ForStatement;
}
export function isForInStatement(node: Node): node is ForInStatement {
return node.kind === SyntaxKind.ForInStatement;
}
export function isForOfStatement(node: Node): node is ForOfStatement {
return node.kind === SyntaxKind.ForOfStatement;
}
export function isContinueStatement(node: Node): node is ContinueStatement {
return node.kind === SyntaxKind.ContinueStatement;
}
export function isBreakStatement(node: Node): node is BreakStatement {
return node.kind === SyntaxKind.BreakStatement;
}
export function isReturnStatement(node: Node): node is ReturnStatement {
return node.kind === SyntaxKind.ReturnStatement;
}
export function isWithStatement(node: Node): node is WithStatement {
return node.kind === SyntaxKind.WithStatement;
}
export function isSwitchStatement(node: Node): node is SwitchStatement {
return node.kind === SyntaxKind.SwitchStatement;
}
export function isLabeledStatement(node: Node): node is LabeledStatement {
return node.kind === SyntaxKind.LabeledStatement;
}
export function isThrowStatement(node: Node): node is ThrowStatement {
return node.kind === SyntaxKind.ThrowStatement;
}
export function isTryStatement(node: Node): node is TryStatement {
return node.kind === SyntaxKind.TryStatement;
}
export function isDebuggerStatement(node: Node): node is DebuggerStatement {
return node.kind === SyntaxKind.DebuggerStatement;
}
export function isVariableDeclaration(node: Node): node is VariableDeclaration {
return node.kind === SyntaxKind.VariableDeclaration;
}
export function isVariableDeclarationList(node: Node): node is VariableDeclarationList {
return node.kind === SyntaxKind.VariableDeclarationList;
}
export function isFunctionDeclaration(node: Node): node is FunctionDeclaration {
return node.kind === SyntaxKind.FunctionDeclaration;
}
export function isClassDeclaration(node: Node): node is ClassDeclaration {
return node.kind === SyntaxKind.ClassDeclaration;
}
export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration {
return node.kind === SyntaxKind.InterfaceDeclaration;
}
export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration {
return node.kind === SyntaxKind.TypeAliasDeclaration;
}
export function isEnumDeclaration(node: Node): node is EnumDeclaration {
return node.kind === SyntaxKind.EnumDeclaration;
}
export function isModuleDeclaration(node: Node): node is ModuleDeclaration {
return node.kind === SyntaxKind.ModuleDeclaration;
}
export function isModuleBlock(node: Node): node is ModuleBlock {
return node.kind === SyntaxKind.ModuleBlock;
}
export function isCaseBlock(node: Node): node is CaseBlock {
return node.kind === SyntaxKind.CaseBlock;
}
export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration {
return node.kind === SyntaxKind.NamespaceExportDeclaration;
}
export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
return node.kind === SyntaxKind.ImportEqualsDeclaration;
}
export function isImportDeclaration(node: Node): node is ImportDeclaration {
return node.kind === SyntaxKind.ImportDeclaration;
}
export function isImportClause(node: Node): node is ImportClause {
return node.kind === SyntaxKind.ImportClause;
}
export function isNamespaceImport(node: Node): node is NamespaceImport {
return node.kind === SyntaxKind.NamespaceImport;
}
export function isNamespaceExport(node: Node): node is NamespaceExport {
return node.kind === SyntaxKind.NamespaceExport;
}
export function isNamedImports(node: Node): node is NamedImports {
return node.kind === SyntaxKind.NamedImports;
}
export function isImportSpecifier(node: Node): node is ImportSpecifier {
return node.kind === SyntaxKind.ImportSpecifier;
}
export function isExportAssignment(node: Node): node is ExportAssignment {
return node.kind === SyntaxKind.ExportAssignment;
}
export function isExportDeclaration(node: Node): node is ExportDeclaration {
return node.kind === SyntaxKind.ExportDeclaration;
}
export function isNamedExports(node: Node): node is NamedExports {
return node.kind === SyntaxKind.NamedExports;
}
export function isExportSpecifier(node: Node): node is ExportSpecifier {
return node.kind === SyntaxKind.ExportSpecifier;
}
export function isMissingDeclaration(node: Node): node is MissingDeclaration {
return node.kind === SyntaxKind.MissingDeclaration;
}
export function isNotEmittedStatement(node: Node): node is NotEmittedStatement {
return node.kind === SyntaxKind.NotEmittedStatement;
}
/* @internal */
export function isSyntheticReference(node: Node): node is SyntheticReferenceExpression {
return node.kind === SyntaxKind.SyntheticReferenceExpression;
}
/* @internal */
export function isMergeDeclarationMarker(node: Node): node is MergeDeclarationMarker {
return node.kind === SyntaxKind.MergeDeclarationMarker;
}
/* @internal */
export function isEndOfDeclarationMarker(node: Node): node is EndOfDeclarationMarker {
return node.kind === SyntaxKind.EndOfDeclarationMarker;
}
// Module References
export function isExternalModuleReference(node: Node): node is ExternalModuleReference {
return node.kind === SyntaxKind.ExternalModuleReference;
}
// JSX
export function isJsxElement(node: Node): node is JsxElement {
return node.kind === SyntaxKind.JsxElement;
}
export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement {
return node.kind === SyntaxKind.JsxSelfClosingElement;
}
export function isJsxOpeningElement(node: Node): node is JsxOpeningElement {
return node.kind === SyntaxKind.JsxOpeningElement;
}
export function isJsxClosingElement(node: Node): node is JsxClosingElement {
return node.kind === SyntaxKind.JsxClosingElement;
}
export function isJsxFragment(node: Node): node is JsxFragment {
return node.kind === SyntaxKind.JsxFragment;
}
export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment {
return node.kind === SyntaxKind.JsxOpeningFragment;
}
export function isJsxClosingFragment(node: Node): node is JsxClosingFragment {
return node.kind === SyntaxKind.JsxClosingFragment;
}
export function isJsxAttribute(node: Node): node is JsxAttribute {
return node.kind === SyntaxKind.JsxAttribute;
}
export function isJsxAttributes(node: Node): node is JsxAttributes {
return node.kind === SyntaxKind.JsxAttributes;
}
export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute {
return node.kind === SyntaxKind.JsxSpreadAttribute;
}
export function isJsxExpression(node: Node): node is JsxExpression {
return node.kind === SyntaxKind.JsxExpression;
}
// Clauses
export function isCaseClause(node: Node): node is CaseClause {
return node.kind === SyntaxKind.CaseClause;
}
export function isDefaultClause(node: Node): node is DefaultClause {
return node.kind === SyntaxKind.DefaultClause;
}
export function isHeritageClause(node: Node): node is HeritageClause {
return node.kind === SyntaxKind.HeritageClause;
}
export function isCatchClause(node: Node): node is CatchClause {
return node.kind === SyntaxKind.CatchClause;
}
// Property assignments
export function isPropertyAssignment(node: Node): node is PropertyAssignment {
return node.kind === SyntaxKind.PropertyAssignment;
}
export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
}
export function isSpreadAssignment(node: Node): node is SpreadAssignment {
return node.kind === SyntaxKind.SpreadAssignment;
}
// Enum
export function isEnumMember(node: Node): node is EnumMember {
return node.kind === SyntaxKind.EnumMember;
}
// Unparsed
// TODO(rbuckton): isUnparsedPrologue
export function isUnparsedPrepend(node: Node): node is UnparsedPrepend {
return node.kind === SyntaxKind.UnparsedPrepend;
}
// TODO(rbuckton): isUnparsedText
// TODO(rbuckton): isUnparsedInternalText
// TODO(rbuckton): isUnparsedSyntheticReference
// Top-level nodes
export function isSourceFile(node: Node): node is SourceFile {
return node.kind === SyntaxKind.SourceFile;
}
export function isBundle(node: Node): node is Bundle {
return node.kind === SyntaxKind.Bundle;
}
export function isUnparsedSource(node: Node): node is UnparsedSource {
return node.kind === SyntaxKind.UnparsedSource;
}
// TODO(rbuckton): isInputFiles
// JSDoc Elements
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
return node.kind === SyntaxKind.JSDocTypeExpression;
}
export function isJSDocAllType(node: Node): node is JSDocAllType {
return node.kind === SyntaxKind.JSDocAllType;
}
export function isJSDocUnknownType(node: Node): node is JSDocUnknownType {
return node.kind === SyntaxKind.JSDocUnknownType;
}
export function isJSDocNullableType(node: Node): node is JSDocNullableType {
return node.kind === SyntaxKind.JSDocNullableType;
}
export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType {
return node.kind === SyntaxKind.JSDocNonNullableType;
}
export function isJSDocOptionalType(node: Node): node is JSDocOptionalType {
return node.kind === SyntaxKind.JSDocOptionalType;
}
export function isJSDocFunctionType(node: Node): node is JSDocFunctionType {
return node.kind === SyntaxKind.JSDocFunctionType;
}
export function isJSDocVariadicType(node: Node): node is JSDocVariadicType {
return node.kind === SyntaxKind.JSDocVariadicType;
}
export function isJSDocNamepathType(node: Node): node is JSDocNamepathType {
return node.kind === SyntaxKind.JSDocNamepathType;
}
export function isJSDoc(node: Node): node is JSDoc {
return node.kind === SyntaxKind.JSDocComment;
}
export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral {
return node.kind === SyntaxKind.JSDocTypeLiteral;
}
export function isJSDocSignature(node: Node): node is JSDocSignature {
return node.kind === SyntaxKind.JSDocSignature;
}
// JSDoc Tags
export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag {
return node.kind === SyntaxKind.JSDocAugmentsTag;
}
export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag {
return node.kind === SyntaxKind.JSDocAuthorTag;
}
export function isJSDocClassTag(node: Node): node is JSDocClassTag {
return node.kind === SyntaxKind.JSDocClassTag;
}
export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag {
return node.kind === SyntaxKind.JSDocCallbackTag;
}
export function isJSDocPublicTag(node: Node): node is JSDocPublicTag {
return node.kind === SyntaxKind.JSDocPublicTag;
}
export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag {
return node.kind === SyntaxKind.JSDocPrivateTag;
}
export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag {
return node.kind === SyntaxKind.JSDocProtectedTag;
}
export function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag {
return node.kind === SyntaxKind.JSDocReadonlyTag;
}
export function isJSDocEnumTag(node: Node): node is JSDocEnumTag {
return node.kind === SyntaxKind.JSDocEnumTag;
}
export function isJSDocParameterTag(node: Node): node is JSDocParameterTag {
return node.kind === SyntaxKind.JSDocParameterTag;
}
export function isJSDocReturnTag(node: Node): node is JSDocReturnTag {
return node.kind === SyntaxKind.JSDocReturnTag;
}
export function isJSDocThisTag(node: Node): node is JSDocThisTag {
return node.kind === SyntaxKind.JSDocThisTag;
}
export function isJSDocTypeTag(node: Node): node is JSDocTypeTag {
return node.kind === SyntaxKind.JSDocTypeTag;
}
export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag {
return node.kind === SyntaxKind.JSDocTemplateTag;
}
export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag {
return node.kind === SyntaxKind.JSDocTypedefTag;
}
export function isJSDocUnknownTag(node: Node): node is JSDocUnknownTag {
return node.kind === SyntaxKind.JSDocTag;
}
export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag {
return node.kind === SyntaxKind.JSDocPropertyTag;
}
export function isJSDocImplementsTag(node: Node): node is JSDocImplementsTag {
return node.kind === SyntaxKind.JSDocImplementsTag;
}
// Synthesized list
/* @internal */
export function isSyntaxList(n: Node): n is SyntaxList {
return n.kind === SyntaxKind.SyntaxList;
}
}

View File

@ -0,0 +1,426 @@
/* @internal */
namespace ts {
export function createParenthesizerRules(factory: NodeFactory): ParenthesizerRules {
interface BinaryPlusExpression extends BinaryExpression {
cachedLiteralKind: SyntaxKind;
}
return {
parenthesizeLeftSideOfBinary,
parenthesizeRightSideOfBinary,
parenthesizeExpressionOfComputedPropertyName,
parenthesizeConditionOfConditionalExpression,
parenthesizeBranchOfConditionalExpression,
parenthesizeExpressionOfExportDefault,
parenthesizeExpressionOfNew,
parenthesizeLeftSideOfAccess,
parenthesizeOperandOfPostfixUnary,
parenthesizeOperandOfPrefixUnary,
parenthesizeExpressionsOfCommaDelimitedList,
parenthesizeExpressionForDisallowedComma,
parenthesizeExpressionOfExpressionStatement,
parenthesizeConciseBodyOfArrowFunction,
parenthesizeMemberOfConditionalType,
parenthesizeMemberOfElementType,
parenthesizeElementTypeOfArrayType,
parenthesizeConstituentTypesOfUnionOrIntersectionType,
parenthesizeTypeArguments,
};
/**
* Determines whether the operand to a BinaryExpression needs to be parenthesized.
*
* @param binaryOperator The operator for the BinaryExpression.
* @param operand The operand for the BinaryExpression.
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
* BinaryExpression.
*/
function binaryOperandNeedsParentheses(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand: Expression | undefined) {
// If the operand has lower precedence, then it needs to be parenthesized to preserve the
// intent of the expression. For example, if the operand is `a + b` and the operator is
// `*`, then we need to parenthesize the operand to preserve the intended order of
// operations: `(a + b) * x`.
//
// If the operand has higher precedence, then it does not need to be parenthesized. For
// example, if the operand is `a * b` and the operator is `+`, then we do not need to
// parenthesize to preserve the intended order of operations: `a * b + x`.
//
// If the operand has the same precedence, then we need to check the associativity of
// the operator based on whether this is the left or right operand of the expression.
//
// For example, if `a / d` is on the right of operator `*`, we need to parenthesize
// to preserve the intended order of operations: `x * (a / d)`
//
// If `a ** d` is on the left of operator `**`, we need to parenthesize to preserve
// the intended order of operations: `(a ** b) ** c`
const binaryOperatorPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, binaryOperator);
const binaryOperatorAssociativity = getOperatorAssociativity(SyntaxKind.BinaryExpression, binaryOperator);
const emittedOperand = skipPartiallyEmittedExpressions(operand);
if (!isLeftSideOfBinary && operand.kind === SyntaxKind.ArrowFunction && binaryOperatorPrecedence > OperatorPrecedence.Assignment) {
// We need to parenthesize arrow functions on the right side to avoid it being
// parsed as parenthesized expression: `a && (() => {})`
return true;
}
const operandPrecedence = getExpressionPrecedence(emittedOperand);
switch (compareValues(operandPrecedence, binaryOperatorPrecedence)) {
case Comparison.LessThan:
// If the operand is the right side of a right-associative binary operation
// and is a yield expression, then we do not need parentheses.
if (!isLeftSideOfBinary
&& binaryOperatorAssociativity === Associativity.Right
&& operand.kind === SyntaxKind.YieldExpression) {
return false;
}
return true;
case Comparison.GreaterThan:
return false;
case Comparison.EqualTo:
if (isLeftSideOfBinary) {
// No need to parenthesize the left operand when the binary operator is
// left associative:
// (a*b)/x -> a*b/x
// (a**b)/x -> a**b/x
//
// Parentheses are needed for the left operand when the binary operator is
// right associative:
// (a/b)**x -> (a/b)**x
// (a**b)**x -> (a**b)**x
return binaryOperatorAssociativity === Associativity.Right;
}
else {
if (isBinaryExpression(emittedOperand)
&& emittedOperand.operatorToken.kind === binaryOperator) {
// No need to parenthesize the right operand when the binary operator and
// operand are the same and one of the following:
// x*(a*b) => x*a*b
// x|(a|b) => x|a|b
// x&(a&b) => x&a&b
// x^(a^b) => x^a^b
if (operatorHasAssociativeProperty(binaryOperator)) {
return false;
}
// No need to parenthesize the right operand when the binary operator
// is plus (+) if both the left and right operands consist solely of either
// literals of the same kind or binary plus (+) expressions for literals of
// the same kind (recursively).
// "a"+(1+2) => "a"+(1+2)
// "a"+("b"+"c") => "a"+"b"+"c"
if (binaryOperator === SyntaxKind.PlusToken) {
const leftKind = leftOperand ? getLiteralKindOfBinaryPlusOperand(leftOperand) : SyntaxKind.Unknown;
if (isLiteralKind(leftKind) && leftKind === getLiteralKindOfBinaryPlusOperand(emittedOperand)) {
return false;
}
}
}
// No need to parenthesize the right operand when the operand is right
// associative:
// x/(a**b) -> x/a**b
// x**(a**b) -> x**a**b
//
// Parentheses are needed for the right operand when the operand is left
// associative:
// x/(a*b) -> x/(a*b)
// x**(a/b) -> x**(a/b)
const operandAssociativity = getExpressionAssociativity(emittedOperand);
return operandAssociativity === Associativity.Left;
}
}
}
/**
* Determines whether a binary operator is mathematically associative.
*
* @param binaryOperator The binary operator.
*/
function operatorHasAssociativeProperty(binaryOperator: SyntaxKind) {
// The following operators are associative in JavaScript:
// (a*b)*c -> a*(b*c) -> a*b*c
// (a|b)|c -> a|(b|c) -> a|b|c
// (a&b)&c -> a&(b&c) -> a&b&c
// (a^b)^c -> a^(b^c) -> a^b^c
//
// While addition is associative in mathematics, JavaScript's `+` is not
// guaranteed to be associative as it is overloaded with string concatenation.
return binaryOperator === SyntaxKind.AsteriskToken
|| binaryOperator === SyntaxKind.BarToken
|| binaryOperator === SyntaxKind.AmpersandToken
|| binaryOperator === SyntaxKind.CaretToken;
}
/**
* This function determines whether an expression consists of a homogeneous set of
* literal expressions or binary plus expressions that all share the same literal kind.
* It is used to determine whether the right-hand operand of a binary plus expression can be
* emitted without parentheses.
*/
function getLiteralKindOfBinaryPlusOperand(node: Expression): SyntaxKind {
node = skipPartiallyEmittedExpressions(node);
if (isLiteralKind(node.kind)) {
return node.kind;
}
if (node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.PlusToken) {
if ((<BinaryPlusExpression>node).cachedLiteralKind !== undefined) {
return (<BinaryPlusExpression>node).cachedLiteralKind;
}
const leftKind = getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).left);
const literalKind = isLiteralKind(leftKind)
&& leftKind === getLiteralKindOfBinaryPlusOperand((<BinaryExpression>node).right)
? leftKind
: SyntaxKind.Unknown;
(<BinaryPlusExpression>node).cachedLiteralKind = literalKind;
return literalKind;
}
return SyntaxKind.Unknown;
}
/**
* Wraps the operand to a BinaryExpression in parentheses if they are needed to preserve the intended
* order of operations.
*
* @param binaryOperator The operator for the BinaryExpression.
* @param operand The operand for the BinaryExpression.
* @param isLeftSideOfBinary A value indicating whether the operand is the left side of the
* BinaryExpression.
*/
function parenthesizeBinaryOperand(binaryOperator: SyntaxKind, operand: Expression, isLeftSideOfBinary: boolean, leftOperand?: Expression) {
const skipped = skipPartiallyEmittedExpressions(operand);
// If the resulting expression is already parenthesized, we do not need to do any further processing.
if (skipped.kind === SyntaxKind.ParenthesizedExpression) {
return operand;
}
return binaryOperandNeedsParentheses(binaryOperator, operand, isLeftSideOfBinary, leftOperand)
? factory.createParenthesizedExpression(operand)
: operand;
}
function parenthesizeLeftSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression): Expression {
return parenthesizeBinaryOperand(binaryOperator, leftSide, /*isLeftSideOfBinary*/ true);
}
function parenthesizeRightSideOfBinary(binaryOperator: SyntaxKind, leftSide: Expression, rightSide: Expression): Expression {
return parenthesizeBinaryOperand(binaryOperator, rightSide, /*isLeftSideOfBinary*/ false, leftSide);
}
function parenthesizeExpressionOfComputedPropertyName(expression: Expression): Expression {
return isCommaSequence(expression) ? factory.createParenthesizedExpression(expression) : expression;
}
function parenthesizeConditionOfConditionalExpression(condition: Expression): Expression {
const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.QuestionToken);
const emittedCondition = skipPartiallyEmittedExpressions(condition);
const conditionPrecedence = getExpressionPrecedence(emittedCondition);
if (compareValues(conditionPrecedence, conditionalPrecedence) !== Comparison.GreaterThan) {
return factory.createParenthesizedExpression(condition);
}
return condition;
}
function parenthesizeBranchOfConditionalExpression(branch: Expression): Expression {
// per ES grammar both 'whenTrue' and 'whenFalse' parts of conditional expression are assignment expressions
// so in case when comma expression is introduced as a part of previous transformations
// if should be wrapped in parens since comma operator has the lowest precedence
const emittedExpression = skipPartiallyEmittedExpressions(branch);
return isCommaSequence(emittedExpression)
? factory.createParenthesizedExpression(branch)
: branch;
}
/**
* [Per the spec](https://tc39.github.io/ecma262/#prod-ExportDeclaration), `export default` accepts _AssigmentExpression_ but
* has a lookahead restriction for `function`, `async function`, and `class`.
*
* Basically, that means we need to parenthesize in the following cases:
*
* - BinaryExpression of CommaToken
* - CommaList (synthetic list of multiple comma expressions)
* - FunctionExpression
* - ClassExpression
*/
function parenthesizeExpressionOfExportDefault(expression: Expression): Expression {
const check = skipPartiallyEmittedExpressions(expression);
let needsParens = isCommaSequence(check);
if (!needsParens) {
switch (getLeftmostExpression(check, /*stopAtCallExpression*/ false).kind) {
case SyntaxKind.ClassExpression:
case SyntaxKind.FunctionExpression:
needsParens = true;
}
}
return needsParens ? factory.createParenthesizedExpression(expression) : expression;
}
/**
* Wraps an expression in parentheses if it is needed in order to use the expression
* as the expression of a `NewExpression` node.
*/
function parenthesizeExpressionOfNew(expression: Expression): LeftHandSideExpression {
const leftmostExpr = getLeftmostExpression(expression, /*stopAtCallExpressions*/ true);
switch (leftmostExpr.kind) {
case SyntaxKind.CallExpression:
return factory.createParenthesizedExpression(expression);
case SyntaxKind.NewExpression:
return !(leftmostExpr as NewExpression).arguments
? factory.createParenthesizedExpression(expression)
: expression as LeftHandSideExpression; // TODO(rbuckton): Verify this assertion holds
}
return parenthesizeLeftSideOfAccess(expression);
}
/**
* Wraps an expression in parentheses if it is needed in order to use the expression for
* property or element access.
*/
function parenthesizeLeftSideOfAccess(expression: Expression): LeftHandSideExpression {
// isLeftHandSideExpression is almost the correct criterion for when it is not necessary
// to parenthesize the expression before a dot. The known exception is:
//
// NewExpression:
// new C.x -> not the same as (new C).x
//
const emittedExpression = skipPartiallyEmittedExpressions(expression);
if (isLeftHandSideExpression(emittedExpression)
&& (emittedExpression.kind !== SyntaxKind.NewExpression || (<NewExpression>emittedExpression).arguments)) {
// TODO(rbuckton): Verify whether this assertion holds.
return expression as LeftHandSideExpression;
}
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return setTextRange(factory.createParenthesizedExpression(expression), expression);
}
function parenthesizeOperandOfPostfixUnary(operand: Expression): LeftHandSideExpression {
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return isLeftHandSideExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand);
}
function parenthesizeOperandOfPrefixUnary(operand: Expression): UnaryExpression {
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return isUnaryExpression(operand) ? operand : setTextRange(factory.createParenthesizedExpression(operand), operand);
}
function parenthesizeExpressionsOfCommaDelimitedList(elements: NodeArray<Expression>): NodeArray<Expression> {
const result = sameMap(elements, parenthesizeExpressionForDisallowedComma);
return setTextRange(factory.createNodeArray(result, elements.hasTrailingComma), elements);
}
function parenthesizeExpressionForDisallowedComma(expression: Expression): Expression {
const emittedExpression = skipPartiallyEmittedExpressions(expression);
const expressionPrecedence = getExpressionPrecedence(emittedExpression);
const commaPrecedence = getOperatorPrecedence(SyntaxKind.BinaryExpression, SyntaxKind.CommaToken);
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return expressionPrecedence > commaPrecedence ? expression : setTextRange(factory.createParenthesizedExpression(expression), expression);
}
function parenthesizeExpressionOfExpressionStatement(expression: Expression): Expression {
const emittedExpression = skipPartiallyEmittedExpressions(expression);
if (isCallExpression(emittedExpression)) {
const callee = emittedExpression.expression;
const kind = skipPartiallyEmittedExpressions(callee).kind;
if (kind === SyntaxKind.FunctionExpression || kind === SyntaxKind.ArrowFunction) {
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
const updated = factory.updateCallExpression(
emittedExpression,
setTextRange(factory.createParenthesizedExpression(callee), callee),
emittedExpression.typeArguments,
emittedExpression.arguments
);
return factory.restoreOuterExpressions(expression, updated, OuterExpressionKinds.PartiallyEmittedExpressions);
}
}
const leftmostExpressionKind = getLeftmostExpression(emittedExpression, /*stopAtCallExpressions*/ false).kind;
if (leftmostExpressionKind === SyntaxKind.ObjectLiteralExpression || leftmostExpressionKind === SyntaxKind.FunctionExpression) {
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return setTextRange(factory.createParenthesizedExpression(expression), expression);
}
return expression;
}
function parenthesizeConciseBodyOfArrowFunction(body: ConciseBody): ConciseBody {
if (!isBlock(body) && (isCommaSequence(body) || getLeftmostExpression(body, /*stopAtCallExpressions*/ false).kind === SyntaxKind.ObjectLiteralExpression)) {
// TODO(rbuckton): Verifiy whether `setTextRange` is needed.
return setTextRange(factory.createParenthesizedExpression(body), body);
}
return body;
}
function parenthesizeMemberOfConditionalType(member: TypeNode): TypeNode {
return member.kind === SyntaxKind.ConditionalType ? factory.createParenthesizedType(member) : member;
}
function parenthesizeMemberOfElementType(member: TypeNode): TypeNode {
switch (member.kind) {
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.FunctionType:
case SyntaxKind.ConstructorType:
return factory.createParenthesizedType(member);
}
return parenthesizeMemberOfConditionalType(member);
}
function parenthesizeElementTypeOfArrayType(member: TypeNode): TypeNode {
switch (member.kind) {
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeOperator:
case SyntaxKind.InferType:
return factory.createParenthesizedType(member);
}
return parenthesizeMemberOfElementType(member);
}
function parenthesizeConstituentTypesOfUnionOrIntersectionType(members: readonly TypeNode[]): NodeArray<TypeNode> {
return factory.createNodeArray(sameMap(members, parenthesizeMemberOfElementType));
}
function parenthesizeOrdinalTypeArgument(node: TypeNode, i: number) {
return i === 0 && isFunctionOrConstructorTypeNode(node) && node.typeParameters ? factory.createParenthesizedType(node) : node;
}
function parenthesizeTypeArguments(typeArguments: NodeArray<TypeNode> | undefined): NodeArray<TypeNode> | undefined {
if (some(typeArguments)) {
return factory.createNodeArray(sameMap(typeArguments, parenthesizeOrdinalTypeArgument));
}
}
}
export const nullParenthesizerRules: ParenthesizerRules = {
parenthesizeLeftSideOfBinary: (_binaryOperator, leftSide) => leftSide,
parenthesizeRightSideOfBinary: (_binaryOperator, _leftSide, rightSide) => rightSide,
parenthesizeExpressionOfComputedPropertyName: identity,
parenthesizeConditionOfConditionalExpression: identity,
parenthesizeBranchOfConditionalExpression: identity,
parenthesizeExpressionOfExportDefault: identity,
parenthesizeExpressionOfNew: expression => cast(expression, isLeftHandSideExpression),
parenthesizeLeftSideOfAccess: expression => cast(expression, isLeftHandSideExpression),
parenthesizeOperandOfPostfixUnary: operand => cast(operand, isLeftHandSideExpression),
parenthesizeOperandOfPrefixUnary: operand => cast(operand, isUnaryExpression),
parenthesizeExpressionsOfCommaDelimitedList: nodes => cast(nodes, isNodeArray),
parenthesizeExpressionForDisallowedComma: identity,
parenthesizeExpressionOfExpressionStatement: identity,
parenthesizeConciseBodyOfArrowFunction: identity,
parenthesizeMemberOfConditionalType: identity,
parenthesizeMemberOfElementType: identity,
parenthesizeElementTypeOfArrayType: identity,
parenthesizeConstituentTypesOfUnionOrIntersectionType: nodes => cast(nodes, isNodeArray),
parenthesizeTypeArguments: nodes => nodes && cast(nodes, isNodeArray),
};
}

View File

@ -0,0 +1,823 @@
/* @internal */
namespace ts {
// Compound nodes
export function createEmptyExports(factory: NodeFactory) {
return factory.createExportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*isTypeOnly*/ false, factory.createNamedExports([]), /*moduleSpecifier*/ undefined);
}
export function createMemberAccessForPropertyName(factory: NodeFactory, target: Expression, memberName: PropertyName, location?: TextRange): MemberExpression {
if (isComputedPropertyName(memberName)) {
return setTextRange(factory.createElementAccessExpression(target, memberName.expression), location);
}
else {
const expression = setTextRange(
isIdentifierOrPrivateIdentifier(memberName)
? factory.createPropertyAccessExpression(target, memberName)
: factory.createElementAccessExpression(target, memberName),
memberName
);
getOrCreateEmitNode(expression).flags |= EmitFlags.NoNestedSourceMaps;
return expression;
}
}
function createReactNamespace(reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment) {
// To ensure the emit resolver can properly resolve the namespace, we need to
// treat this identifier as if it were a source tree node by clearing the `Synthesized`
// flag and setting a parent node.
const react = parseNodeFactory.createIdentifier(reactNamespace || "React");
// Set the parent that is in parse tree
// this makes sure that parent chain is intact for checker to traverse complete scope tree
setParent(react, getParseTreeNode(parent));
return react;
}
function createJsxFactoryExpressionFromEntityName(factory: NodeFactory, jsxFactory: EntityName, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression {
if (isQualifiedName(jsxFactory)) {
const left = createJsxFactoryExpressionFromEntityName(factory, jsxFactory.left, parent);
const right = factory.createIdentifier(idText(jsxFactory.right)) as Mutable<Identifier>;
right.escapedText = jsxFactory.right.escapedText;
return factory.createPropertyAccessExpression(left, right);
}
else {
return createReactNamespace(idText(jsxFactory), parent);
}
}
function createJsxFactoryExpression(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, parent: JsxOpeningLikeElement | JsxOpeningFragment): Expression {
return jsxFactoryEntity ?
createJsxFactoryExpressionFromEntityName(factory, jsxFactoryEntity, parent) :
factory.createPropertyAccessExpression(
createReactNamespace(reactNamespace, parent),
"createElement"
);
}
export function createExpressionForJsxElement(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, tagName: Expression, props: Expression | undefined, children: readonly Expression[] | undefined, parentElement: JsxOpeningLikeElement, location: TextRange): LeftHandSideExpression {
const argumentsList = [tagName];
if (props) {
argumentsList.push(props);
}
if (children && children.length > 0) {
if (!props) {
argumentsList.push(factory.createNull());
}
if (children.length > 1) {
for (const child of children) {
startOnNewLine(child);
argumentsList.push(child);
}
}
else {
argumentsList.push(children[0]);
}
}
return setTextRange(
factory.createCallExpression(
createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement),
/*typeArguments*/ undefined,
argumentsList
),
location
);
}
export function createExpressionForJsxFragment(factory: NodeFactory, jsxFactoryEntity: EntityName | undefined, reactNamespace: string, children: readonly Expression[], parentElement: JsxOpeningFragment, location: TextRange): LeftHandSideExpression {
const tagName = factory.createPropertyAccessExpression(
createReactNamespace(reactNamespace, parentElement),
"Fragment"
);
const argumentsList = [<Expression>tagName];
argumentsList.push(factory.createNull());
if (children && children.length > 0) {
if (children.length > 1) {
for (const child of children) {
startOnNewLine(child);
argumentsList.push(child);
}
}
else {
argumentsList.push(children[0]);
}
}
return setTextRange(
factory.createCallExpression(
createJsxFactoryExpression(factory, jsxFactoryEntity, reactNamespace, parentElement),
/*typeArguments*/ undefined,
argumentsList
),
location
);
}
// Utilities
export function createForOfBindingStatement(factory: NodeFactory, node: ForInitializer, boundValue: Expression): Statement {
if (isVariableDeclarationList(node)) {
const firstDeclaration = first(node.declarations);
const updatedDeclaration = factory.updateVariableDeclaration(
firstDeclaration,
firstDeclaration.name,
/*exclamationToken*/ undefined,
/*type*/ undefined,
boundValue
);
return setTextRange(
factory.createVariableStatement(
/*modifiers*/ undefined,
factory.updateVariableDeclarationList(node, [updatedDeclaration])
),
/*location*/ node
);
}
else {
const updatedExpression = setTextRange(factory.createAssignment(node, boundValue), /*location*/ node);
return setTextRange(factory.createExpressionStatement(updatedExpression), /*location*/ node);
}
}
export function insertLeadingStatement(factory: NodeFactory, dest: Statement, source: Statement) {
if (isBlock(dest)) {
return factory.updateBlock(dest, setTextRange(factory.createNodeArray([source, ...dest.statements]), dest.statements));
}
else {
return factory.createBlock(factory.createNodeArray([dest, source]), /*multiLine*/ true);
}
}
export function createExpressionFromEntityName(factory: NodeFactory, node: EntityName | Expression): Expression {
if (isQualifiedName(node)) {
const left = createExpressionFromEntityName(factory, node.left);
// TODO(rbuckton): Does this need to be parented?
const right = setParent(setTextRange(factory.cloneNode(node.right), node.right), node.right.parent);
return setTextRange(factory.createPropertyAccessExpression(left, right), node);
}
else {
// TODO(rbuckton): Does this need to be parented?
return setParent(setTextRange(factory.cloneNode(node), node), node.parent);
}
}
export function createExpressionForPropertyName(factory: NodeFactory, memberName: Exclude<PropertyName, PrivateIdentifier>): Expression {
if (isIdentifier(memberName)) {
return factory.createStringLiteralFromNode(memberName);
}
else if (isComputedPropertyName(memberName)) {
// TODO(rbuckton): Does this need to be parented?
return setParent(setTextRange(factory.cloneNode(memberName.expression), memberName.expression), memberName.expression.parent);
}
else {
// TODO(rbuckton): Does this need to be parented?
return setParent(setTextRange(factory.cloneNode(memberName), memberName), memberName.parent);
}
}
function createExpressionForAccessorDeclaration(factory: NodeFactory, properties: NodeArray<Declaration>, property: AccessorDeclaration & { readonly name: Exclude<PropertyName, PrivateIdentifier>; }, receiver: Expression, multiLine: boolean) {
const { firstAccessor, getAccessor, setAccessor } = getAllAccessorDeclarations(properties, property);
if (property === firstAccessor) {
return setTextRange(
factory.createObjectDefinePropertyCall(
receiver,
createExpressionForPropertyName(factory, property.name),
factory.createPropertyDescriptor({
enumerable: factory.createFalse(),
configurable: true,
get: getAccessor && setTextRange(
setOriginalNode(
factory.createFunctionExpression(
getAccessor.modifiers,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
getAccessor.parameters,
/*type*/ undefined,
getAccessor.body! // TODO: GH#18217
),
getAccessor
),
getAccessor
),
set: setAccessor && setTextRange(
setOriginalNode(
factory.createFunctionExpression(
setAccessor.modifiers,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
setAccessor.parameters,
/*type*/ undefined,
setAccessor.body! // TODO: GH#18217
),
setAccessor
),
setAccessor
)
}, !multiLine)
),
firstAccessor
);
}
return undefined;
}
function createExpressionForPropertyAssignment(factory: NodeFactory, property: PropertyAssignment, receiver: Expression) {
return setOriginalNode(
setTextRange(
factory.createAssignment(
createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name),
property.initializer
),
property
),
property
);
}
function createExpressionForShorthandPropertyAssignment(factory: NodeFactory, property: ShorthandPropertyAssignment, receiver: Expression) {
return setOriginalNode(
setTextRange(
factory.createAssignment(
createMemberAccessForPropertyName(factory, receiver, property.name, /*location*/ property.name),
factory.cloneNode(property.name)
),
/*location*/ property
),
/*original*/ property
);
}
function createExpressionForMethodDeclaration(factory: NodeFactory, method: MethodDeclaration, receiver: Expression) {
return setOriginalNode(
setTextRange(
factory.createAssignment(
createMemberAccessForPropertyName(factory, receiver, method.name, /*location*/ method.name),
setOriginalNode(
setTextRange(
factory.createFunctionExpression(
method.modifiers,
method.asteriskToken,
/*name*/ undefined,
/*typeParameters*/ undefined,
method.parameters,
/*type*/ undefined,
method.body! // TODO: GH#18217
),
/*location*/ method
),
/*original*/ method
)
),
/*location*/ method
),
/*original*/ method
);
}
export function createExpressionForObjectLiteralElementLike(factory: NodeFactory, node: ObjectLiteralExpression, property: ObjectLiteralElementLike, receiver: Expression): Expression | undefined {
if (property.name && isPrivateIdentifier(property.name)) {
Debug.failBadSyntaxKind(property.name, "Private identifiers are not allowed in object literals.");
}
switch (property.kind) {
case SyntaxKind.GetAccessor:
case SyntaxKind.SetAccessor:
return createExpressionForAccessorDeclaration(factory, node.properties, property as typeof property & { readonly name: Exclude<PropertyName, PrivateIdentifier> }, receiver, !!node.multiLine);
case SyntaxKind.PropertyAssignment:
return createExpressionForPropertyAssignment(factory, property, receiver);
case SyntaxKind.ShorthandPropertyAssignment:
return createExpressionForShorthandPropertyAssignment(factory, property, receiver);
case SyntaxKind.MethodDeclaration:
return createExpressionForMethodDeclaration(factory, property, receiver);
}
}
/**
* Gets whether an identifier should only be referred to by its internal name.
*/
export function isInternalName(node: Identifier) {
return (getEmitFlags(node) & EmitFlags.InternalName) !== 0;
}
/**
* Gets whether an identifier should only be referred to by its local name.
*/
export function isLocalName(node: Identifier) {
return (getEmitFlags(node) & EmitFlags.LocalName) !== 0;
}
/**
* Gets whether an identifier should only be referred to by its export representation if the
* name points to an exported symbol.
*/
export function isExportName(node: Identifier) {
return (getEmitFlags(node) & EmitFlags.ExportName) !== 0;
}
function isUseStrictPrologue(node: ExpressionStatement): boolean {
return isStringLiteral(node.expression) && node.expression.text === "use strict";
}
export function findUseStrictPrologue(statements: readonly Statement[]): Statement | undefined {
for (const statement of statements) {
if (isPrologueDirective(statement)) {
if (isUseStrictPrologue(statement)) {
return statement;
}
}
else {
break;
}
}
return undefined;
}
export function startsWithUseStrict(statements: readonly Statement[]) {
const firstStatement = firstOrUndefined(statements);
return firstStatement !== undefined
&& isPrologueDirective(firstStatement)
&& isUseStrictPrologue(firstStatement);
}
export function isCommaSequence(node: Expression): node is BinaryExpression & {operatorToken: Token<SyntaxKind.CommaToken>} | CommaListExpression {
return node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.CommaToken ||
node.kind === SyntaxKind.CommaListExpression;
}
export function isOuterExpression(node: Node, kinds = OuterExpressionKinds.All): node is OuterExpression {
switch (node.kind) {
case SyntaxKind.ParenthesizedExpression:
return (kinds & OuterExpressionKinds.Parentheses) !== 0;
case SyntaxKind.TypeAssertionExpression:
case SyntaxKind.AsExpression:
return (kinds & OuterExpressionKinds.TypeAssertions) !== 0;
case SyntaxKind.NonNullExpression:
return (kinds & OuterExpressionKinds.NonNullAssertions) !== 0;
case SyntaxKind.PartiallyEmittedExpression:
return (kinds & OuterExpressionKinds.PartiallyEmittedExpressions) !== 0;
}
return false;
}
export function skipOuterExpressions(node: Expression, kinds?: OuterExpressionKinds): Expression;
export function skipOuterExpressions(node: Node, kinds?: OuterExpressionKinds): Node;
export function skipOuterExpressions(node: Node, kinds = OuterExpressionKinds.All) {
while (isOuterExpression(node, kinds)) {
node = node.expression;
}
return node;
}
export function skipAssertions(node: Expression): Expression;
export function skipAssertions(node: Node): Node;
export function skipAssertions(node: Node): Node {
return skipOuterExpressions(node, OuterExpressionKinds.Assertions);
}
export function startOnNewLine<T extends Node>(node: T): T {
return setStartsOnNewLine(node, /*newLine*/ true);
}
export function getExternalHelpersModuleName(node: SourceFile) {
const parseNode = getOriginalNode(node, isSourceFile);
const emitNode = parseNode && parseNode.emitNode;
return emitNode && emitNode.externalHelpersModuleName;
}
export function hasRecordedExternalHelpers(sourceFile: SourceFile) {
const parseNode = getOriginalNode(sourceFile, isSourceFile);
const emitNode = parseNode && parseNode.emitNode;
return !!emitNode && (!!emitNode.externalHelpersModuleName || !!emitNode.externalHelpers);
}
export function createExternalHelpersImportDeclarationIfNeeded(nodeFactory: NodeFactory, helperFactory: EmitHelperFactory, sourceFile: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStar?: boolean, hasImportDefault?: boolean) {
if (compilerOptions.importHelpers && isEffectiveExternalModule(sourceFile, compilerOptions)) {
let namedBindings: NamedImportBindings | undefined;
const moduleKind = getEmitModuleKind(compilerOptions);
if (moduleKind >= ModuleKind.ES2015 && moduleKind <= ModuleKind.ESNext) {
// use named imports
const helpers = getEmitHelpers(sourceFile);
if (helpers) {
const helperNames: string[] = [];
for (const helper of helpers) {
if (!helper.scoped) {
const importName = (helper as UnscopedEmitHelper).importName;
if (importName) {
pushIfUnique(helperNames, importName);
}
}
}
if (some(helperNames)) {
helperNames.sort(compareStringsCaseSensitive);
// Alias the imports if the names are used somewhere in the file.
// NOTE: We don't need to care about global import collisions as this is a module.
namedBindings = nodeFactory.createNamedImports(
map(helperNames, name => isFileLevelUniqueName(sourceFile, name)
? nodeFactory.createImportSpecifier(/*propertyName*/ undefined, nodeFactory.createIdentifier(name))
: nodeFactory.createImportSpecifier(nodeFactory.createIdentifier(name), helperFactory.getUnscopedHelperName(name))
)
);
const parseNode = getOriginalNode(sourceFile, isSourceFile);
const emitNode = getOrCreateEmitNode(parseNode);
emitNode.externalHelpers = true;
}
}
}
else {
// use a namespace import
const externalHelpersModuleName = getOrCreateExternalHelpersModuleNameIfNeeded(nodeFactory, sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar || hasImportDefault);
if (externalHelpersModuleName) {
namedBindings = nodeFactory.createNamespaceImport(externalHelpersModuleName);
}
}
if (namedBindings) {
const externalHelpersImportDeclaration = nodeFactory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
nodeFactory.createImportClause(/*isTypeOnly*/ false, /*name*/ undefined, namedBindings),
nodeFactory.createStringLiteral(externalHelpersModuleNameText)
);
addEmitFlags(externalHelpersImportDeclaration, EmitFlags.NeverApplyImportHelper);
return externalHelpersImportDeclaration;
}
}
}
export function getOrCreateExternalHelpersModuleNameIfNeeded(factory: NodeFactory, node: SourceFile, compilerOptions: CompilerOptions, hasExportStarsToExportValues?: boolean, hasImportStarOrImportDefault?: boolean) {
if (compilerOptions.importHelpers && isEffectiveExternalModule(node, compilerOptions)) {
const externalHelpersModuleName = getExternalHelpersModuleName(node);
if (externalHelpersModuleName) {
return externalHelpersModuleName;
}
const moduleKind = getEmitModuleKind(compilerOptions);
let create = (hasExportStarsToExportValues || (compilerOptions.esModuleInterop && hasImportStarOrImportDefault))
&& moduleKind !== ModuleKind.System
&& moduleKind < ModuleKind.ES2015;
if (!create) {
const helpers = getEmitHelpers(node);
if (helpers) {
for (const helper of helpers) {
if (!helper.scoped) {
create = true;
break;
}
}
}
}
if (create) {
const parseNode = getOriginalNode(node, isSourceFile);
const emitNode = getOrCreateEmitNode(parseNode);
return emitNode.externalHelpersModuleName || (emitNode.externalHelpersModuleName = factory.createUniqueName(externalHelpersModuleNameText));
}
}
}
/**
* Get the name of that target module from an import or export declaration
*/
export function getLocalNameForExternalImport(factory: NodeFactory, node: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile): Identifier | undefined {
const namespaceDeclaration = getNamespaceDeclarationNode(node);
if (namespaceDeclaration && !isDefaultImport(node)) {
const name = namespaceDeclaration.name;
return isGeneratedIdentifier(name) ? name : factory.createIdentifier(getSourceTextOfNodeFromSourceFile(sourceFile, name) || idText(name));
}
if (node.kind === SyntaxKind.ImportDeclaration && node.importClause) {
return factory.getGeneratedNameForNode(node);
}
if (node.kind === SyntaxKind.ExportDeclaration && node.moduleSpecifier) {
return factory.getGeneratedNameForNode(node);
}
return undefined;
}
/**
* Get the name of a target module from an import/export declaration as should be written in the emitted output.
* The emitted output name can be different from the input if:
* 1. The module has a /// <amd-module name="<new name>" />
* 2. --out or --outFile is used, making the name relative to the rootDir
* 3- The containing SourceFile has an entry in renamedDependencies for the import as requested by some module loaders (e.g. System).
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function getExternalModuleNameLiteral(factory: NodeFactory, importNode: ImportDeclaration | ExportDeclaration | ImportEqualsDeclaration, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, compilerOptions: CompilerOptions) {
const moduleName = getExternalModuleName(importNode)!; // TODO: GH#18217
if (moduleName.kind === SyntaxKind.StringLiteral) {
return tryGetModuleNameFromDeclaration(importNode, host, factory, resolver, compilerOptions)
|| tryRenameExternalModule(factory, <StringLiteral>moduleName, sourceFile)
|| factory.cloneNode(<StringLiteral>moduleName);
}
return undefined;
}
/**
* Some bundlers (SystemJS builder) sometimes want to rename dependencies.
* Here we check if alternative name was provided for a given moduleName and return it if possible.
*/
function tryRenameExternalModule(factory: NodeFactory, moduleName: LiteralExpression, sourceFile: SourceFile) {
const rename = sourceFile.renamedDependencies && sourceFile.renamedDependencies.get(moduleName.text);
return rename && factory.createStringLiteral(rename);
}
/**
* Get the name of a module as should be written in the emitted output.
* The emitted output name can be different from the input if:
* 1. The module has a /// <amd-module name="<new name>" />
* 2. --out or --outFile is used, making the name relative to the rootDir
* Otherwise, a new StringLiteral node representing the module name will be returned.
*/
export function tryGetModuleNameFromFile(factory: NodeFactory, file: SourceFile | undefined, host: EmitHost, options: CompilerOptions): StringLiteral | undefined {
if (!file) {
return undefined;
}
if (file.moduleName) {
return factory.createStringLiteral(file.moduleName);
}
if (!file.isDeclarationFile && outFile(options)) {
return factory.createStringLiteral(getExternalModuleNameFromPath(host, file.fileName));
}
return undefined;
}
function tryGetModuleNameFromDeclaration(declaration: ImportEqualsDeclaration | ImportDeclaration | ExportDeclaration, host: EmitHost, factory: NodeFactory, resolver: EmitResolver, compilerOptions: CompilerOptions) {
return tryGetModuleNameFromFile(factory, resolver.getExternalModuleFileFromDeclaration(declaration), host, compilerOptions);
}
/**
* Gets the initializer of an BindingOrAssignmentElement.
*/
export function getInitializerOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Expression | undefined {
if (isDeclarationBindingElement(bindingElement)) {
// `1` in `let { a = 1 } = ...`
// `1` in `let { a: b = 1 } = ...`
// `1` in `let { a: {b} = 1 } = ...`
// `1` in `let { a: [b] = 1 } = ...`
// `1` in `let [a = 1] = ...`
// `1` in `let [{a} = 1] = ...`
// `1` in `let [[a] = 1] = ...`
return bindingElement.initializer;
}
if (isPropertyAssignment(bindingElement)) {
// `1` in `({ a: b = 1 } = ...)`
// `1` in `({ a: {b} = 1 } = ...)`
// `1` in `({ a: [b] = 1 } = ...)`
const initializer = bindingElement.initializer;
return isAssignmentExpression(initializer, /*excludeCompoundAssignment*/ true)
? initializer.right
: undefined;
}
if (isShorthandPropertyAssignment(bindingElement)) {
// `1` in `({ a = 1 } = ...)`
return bindingElement.objectAssignmentInitializer;
}
if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) {
// `1` in `[a = 1] = ...`
// `1` in `[{a} = 1] = ...`
// `1` in `[[a] = 1] = ...`
return bindingElement.right;
}
if (isSpreadElement(bindingElement)) {
// Recovery consistent with existing emit.
return getInitializerOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.expression);
}
}
/**
* Gets the name of an BindingOrAssignmentElement.
*/
export function getTargetOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementTarget | undefined {
if (isDeclarationBindingElement(bindingElement)) {
// `a` in `let { a } = ...`
// `a` in `let { a = 1 } = ...`
// `b` in `let { a: b } = ...`
// `b` in `let { a: b = 1 } = ...`
// `a` in `let { ...a } = ...`
// `{b}` in `let { a: {b} } = ...`
// `{b}` in `let { a: {b} = 1 } = ...`
// `[b]` in `let { a: [b] } = ...`
// `[b]` in `let { a: [b] = 1 } = ...`
// `a` in `let [a] = ...`
// `a` in `let [a = 1] = ...`
// `a` in `let [...a] = ...`
// `{a}` in `let [{a}] = ...`
// `{a}` in `let [{a} = 1] = ...`
// `[a]` in `let [[a]] = ...`
// `[a]` in `let [[a] = 1] = ...`
return bindingElement.name;
}
if (isObjectLiteralElementLike(bindingElement)) {
switch (bindingElement.kind) {
case SyntaxKind.PropertyAssignment:
// `b` in `({ a: b } = ...)`
// `b` in `({ a: b = 1 } = ...)`
// `{b}` in `({ a: {b} } = ...)`
// `{b}` in `({ a: {b} = 1 } = ...)`
// `[b]` in `({ a: [b] } = ...)`
// `[b]` in `({ a: [b] = 1 } = ...)`
// `b.c` in `({ a: b.c } = ...)`
// `b.c` in `({ a: b.c = 1 } = ...)`
// `b[0]` in `({ a: b[0] } = ...)`
// `b[0]` in `({ a: b[0] = 1 } = ...)`
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.initializer);
case SyntaxKind.ShorthandPropertyAssignment:
// `a` in `({ a } = ...)`
// `a` in `({ a = 1 } = ...)`
return bindingElement.name;
case SyntaxKind.SpreadAssignment:
// `a` in `({ ...a } = ...)`
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.expression);
}
// no target
return undefined;
}
if (isAssignmentExpression(bindingElement, /*excludeCompoundAssignment*/ true)) {
// `a` in `[a = 1] = ...`
// `{a}` in `[{a} = 1] = ...`
// `[a]` in `[[a] = 1] = ...`
// `a.b` in `[a.b = 1] = ...`
// `a[0]` in `[a[0] = 1] = ...`
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.left);
}
if (isSpreadElement(bindingElement)) {
// `a` in `[...a] = ...`
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.expression);
}
// `a` in `[a] = ...`
// `{a}` in `[{a}] = ...`
// `[a]` in `[[a]] = ...`
// `a.b` in `[a.b] = ...`
// `a[0]` in `[a[0]] = ...`
return bindingElement;
}
/**
* Determines whether an BindingOrAssignmentElement is a rest element.
*/
export function getRestIndicatorOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): BindingOrAssignmentElementRestIndicator | undefined {
switch (bindingElement.kind) {
case SyntaxKind.Parameter:
case SyntaxKind.BindingElement:
// `...` in `let [...a] = ...`
return bindingElement.dotDotDotToken;
case SyntaxKind.SpreadElement:
case SyntaxKind.SpreadAssignment:
// `...` in `[...a] = ...`
return bindingElement;
}
return undefined;
}
/**
* Gets the property name of a BindingOrAssignmentElement
*/
export function getPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude<PropertyName, PrivateIdentifier> | undefined {
const propertyName = tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement);
Debug.assert(!!propertyName || isSpreadAssignment(bindingElement), "Invalid property name for binding element.");
return propertyName;
}
export function tryGetPropertyNameOfBindingOrAssignmentElement(bindingElement: BindingOrAssignmentElement): Exclude<PropertyName, PrivateIdentifier> | undefined {
switch (bindingElement.kind) {
case SyntaxKind.BindingElement:
// `a` in `let { a: b } = ...`
// `[a]` in `let { [a]: b } = ...`
// `"a"` in `let { "a": b } = ...`
// `1` in `let { 1: b } = ...`
if (bindingElement.propertyName) {
const propertyName = bindingElement.propertyName;
if (isPrivateIdentifier(propertyName)) {
return Debug.failBadSyntaxKind(propertyName);
}
return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression)
? propertyName.expression
: propertyName;
}
break;
case SyntaxKind.PropertyAssignment:
// `a` in `({ a: b } = ...)`
// `[a]` in `({ [a]: b } = ...)`
// `"a"` in `({ "a": b } = ...)`
// `1` in `({ 1: b } = ...)`
if (bindingElement.name) {
const propertyName = bindingElement.name;
if (isPrivateIdentifier(propertyName)) {
return Debug.failBadSyntaxKind(propertyName);
}
return isComputedPropertyName(propertyName) && isStringOrNumericLiteral(propertyName.expression)
? propertyName.expression
: propertyName;
}
break;
case SyntaxKind.SpreadAssignment:
// `a` in `({ ...a } = ...)`
if (bindingElement.name && isPrivateIdentifier(bindingElement.name)) {
return Debug.failBadSyntaxKind(bindingElement.name);
}
return bindingElement.name;
}
const target = getTargetOfBindingOrAssignmentElement(bindingElement);
if (target && isPropertyName(target)) {
return target;
}
}
function isStringOrNumericLiteral(node: Node): node is StringLiteral | NumericLiteral {
const kind = node.kind;
return kind === SyntaxKind.StringLiteral
|| kind === SyntaxKind.NumericLiteral;
}
/**
* Gets the elements of a BindingOrAssignmentPattern
*/
export function getElementsOfBindingOrAssignmentPattern(name: BindingOrAssignmentPattern): readonly BindingOrAssignmentElement[] {
switch (name.kind) {
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
case SyntaxKind.ArrayLiteralExpression:
// `a` in `{a}`
// `a` in `[a]`
return <readonly BindingOrAssignmentElement[]>name.elements;
case SyntaxKind.ObjectLiteralExpression:
// `a` in `{a}`
return <readonly BindingOrAssignmentElement[]>name.properties;
}
}
/* @internal */
export function getJSDocTypeAliasName(fullName: JSDocNamespaceBody | undefined) {
if (fullName) {
let rightNode = fullName;
while (true) {
if (isIdentifier(rightNode) || !rightNode.body) {
return isIdentifier(rightNode) ? rightNode : rightNode.name;
}
rightNode = rightNode.body;
}
}
}
export function canHaveModifiers(node: Node): node is HasModifiers {
const kind = node.kind;
return kind === SyntaxKind.Parameter
|| kind === SyntaxKind.PropertySignature
|| kind === SyntaxKind.PropertyDeclaration
|| kind === SyntaxKind.MethodSignature
|| kind === SyntaxKind.MethodDeclaration
|| kind === SyntaxKind.Constructor
|| kind === SyntaxKind.GetAccessor
|| kind === SyntaxKind.SetAccessor
|| kind === SyntaxKind.IndexSignature
|| kind === SyntaxKind.FunctionExpression
|| kind === SyntaxKind.ArrowFunction
|| kind === SyntaxKind.ClassExpression
|| kind === SyntaxKind.VariableStatement
|| kind === SyntaxKind.FunctionDeclaration
|| kind === SyntaxKind.ClassDeclaration
|| kind === SyntaxKind.InterfaceDeclaration
|| kind === SyntaxKind.TypeAliasDeclaration
|| kind === SyntaxKind.EnumDeclaration
|| kind === SyntaxKind.ModuleDeclaration
|| kind === SyntaxKind.ImportEqualsDeclaration
|| kind === SyntaxKind.ImportDeclaration
|| kind === SyntaxKind.ExportAssignment
|| kind === SyntaxKind.ExportDeclaration;
}
/* @internal */
export function isAsyncModifier(node: Modifier): node is AsyncKeyword {
return node.kind === SyntaxKind.AsyncKeyword;
}
/* @internal */
export function isStaticModifier(node: Modifier): node is StaticKeyword {
return node.kind === SyntaxKind.StaticKeyword;
}
}

View File

@ -0,0 +1,5 @@
namespace ts {
export function setTextRange<T extends TextRange>(range: T, location: TextRange | undefined): T {
return location ? setTextRangePosEnd(range, location.pos, location.end) : range;
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -2113,11 +2113,11 @@ namespace ts {
&& (options.isolatedModules || isExternalModuleFile)
&& !file.isDeclarationFile) {
// synthesize 'import "tslib"' declaration
const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText);
const importDecl = createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference);
const externalHelpersModuleReference = factory.createStringLiteral(externalHelpersModuleNameText);
const importDecl = factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*importClause*/ undefined, externalHelpersModuleReference);
addEmitFlags(importDecl, EmitFlags.NeverApplyImportHelper);
externalHelpersModuleReference.parent = importDecl;
importDecl.parent = file;
setParent(externalHelpersModuleReference, importDecl);
setParent(importDecl, file);
imports = [externalHelpersModuleReference];
}

View File

@ -21,10 +21,14 @@ namespace ts {
hasUnicodeEscape(): boolean;
hasExtendedUnicodeEscape(): boolean;
hasPrecedingLineBreak(): boolean;
/* @internal */
hasPrecedingJSDocComment(): boolean;
isIdentifier(): boolean;
isReservedWord(): boolean;
isUnterminated(): boolean;
/* @internal */
getNumericLiteralFlags(): TokenFlags;
/* @internal */
getCommentDirectives(): CommentDirective[] | undefined;
/* @internal */
getTokenFlags(): TokenFlags;
@ -942,10 +946,12 @@ namespace ts {
hasUnicodeEscape: () => (tokenFlags & TokenFlags.UnicodeEscape) !== 0,
hasExtendedUnicodeEscape: () => (tokenFlags & TokenFlags.ExtendedUnicodeEscape) !== 0,
hasPrecedingLineBreak: () => (tokenFlags & TokenFlags.PrecedingLineBreak) !== 0,
hasPrecedingJSDocComment: () => (tokenFlags & TokenFlags.PrecedingJSDocComment) !== 0,
isIdentifier: () => token === SyntaxKind.Identifier || token > SyntaxKind.LastReservedWord,
isReservedWord: () => token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord,
isUnterminated: () => (tokenFlags & TokenFlags.Unterminated) !== 0,
getCommentDirectives: () => commentDirectives,
getNumericLiteralFlags: () => tokenFlags & TokenFlags.NumericLiteralFlags,
getTokenFlags: () => tokenFlags,
reScanGreaterToken,
reScanSlashToken,

View File

@ -109,11 +109,11 @@ namespace ts {
/**
* Wrap a transformer factory that may return a custom script or declaration transformer object.
*/
function wrapCustomTransformerFactory<T extends SourceFile | Bundle>(transformer: TransformerFactory<T> | CustomTransformerFactory, handleDefault: (node: Transformer<T>) => Transformer<Bundle | SourceFile>): TransformerFactory<Bundle | SourceFile> {
function wrapCustomTransformerFactory<T extends SourceFile | Bundle>(transformer: TransformerFactory<T> | CustomTransformerFactory, handleDefault: (context: TransformationContext, tx: Transformer<T>) => Transformer<Bundle | SourceFile>): TransformerFactory<Bundle | SourceFile> {
return context => {
const customTransformer = transformer(context);
return typeof customTransformer === "function"
? handleDefault(customTransformer)
? handleDefault(context, customTransformer)
: wrapCustomTransformer(customTransformer);
};
}
@ -123,7 +123,7 @@ namespace ts {
}
function wrapDeclarationTransformerFactory(transformer: TransformerFactory<Bundle | SourceFile> | CustomTransformerFactory): TransformerFactory<Bundle | SourceFile> {
return wrapCustomTransformerFactory(transformer, identity);
return wrapCustomTransformerFactory(transformer, (_, node) => node);
}
export function noEmitSubstitution(_hint: EmitHint, node: Node) {
@ -144,7 +144,7 @@ namespace ts {
* @param transforms An array of `TransformerFactory` callbacks.
* @param allowDtsFiles A value indicating whether to allow the transformation of .d.ts files.
*/
export function transformNodes<T extends Node>(resolver: EmitResolver | undefined, host: EmitHost | undefined, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
export function transformNodes<T extends Node>(resolver: EmitResolver | undefined, host: EmitHost | undefined, factory: NodeFactory, options: CompilerOptions, nodes: readonly T[], transformers: readonly TransformerFactory<T>[], allowDtsFiles: boolean): TransformationResult<T> {
const enabledSyntaxKindFeatures = new Array<SyntaxKindFeatureFlags>(SyntaxKind.Count);
let lexicalEnvironmentVariableDeclarations: VariableDeclaration[];
let lexicalEnvironmentFunctionDeclarations: FunctionDeclaration[];
@ -165,9 +165,11 @@ namespace ts {
// The transformation context is provided to each transformer as part of transformer
// initialization.
const context: TransformationContext = {
factory,
getCompilerOptions: () => options,
getEmitResolver: () => resolver!, // TODO: GH#18217
getEmitHost: () => host!, // TODO: GH#18217
getEmitHelperFactory: memoize(() => createEmitHelperFactory(context)),
startLexicalEnvironment,
suspendLexicalEnvironment,
resumeLexicalEnvironment,
@ -313,7 +315,7 @@ namespace ts {
function hoistVariableDeclaration(name: Identifier): void {
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 = setEmitFlags(createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps);
const decl = setEmitFlags(factory.createVariableDeclaration(name), EmitFlags.NoNestedSourceMaps);
if (!lexicalEnvironmentVariableDeclarations) {
lexicalEnvironmentVariableDeclarations = [decl];
}
@ -413,9 +415,9 @@ namespace ts {
}
if (lexicalEnvironmentVariableDeclarations) {
const statement = createVariableStatement(
const statement = factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)
factory.createVariableDeclarationList(lexicalEnvironmentVariableDeclarations)
);
setEmitFlags(statement, EmitFlags.CustomPrologue);
@ -504,4 +506,30 @@ namespace ts {
}
}
}
export const nullTransformationContext: TransformationContext = {
get factory() { return factory; },
enableEmitNotification: noop,
enableSubstitution: noop,
endLexicalEnvironment: returnUndefined,
getCompilerOptions: () => ({}),
getEmitHost: notImplemented,
getEmitResolver: notImplemented,
getEmitHelperFactory: notImplemented,
setLexicalEnvironmentFlags: noop,
getLexicalEnvironmentFlags: () => 0,
hoistFunctionDeclaration: noop,
hoistVariableDeclaration: noop,
addInitializationStatement: noop,
isEmitNotificationEnabled: notImplemented,
isSubstitutionEnabled: notImplemented,
onEmitNode: noop,
onSubstituteNode: notImplemented,
readEmitHelpers: notImplemented,
requestEmitHelper: noop,
resumeLexicalEnvironment: noop,
startLexicalEnvironment: noop,
suspendLexicalEnvironment: noop,
addDiagnostic: noop,
};
}

View File

@ -33,6 +33,7 @@ namespace ts {
*/
export function transformClassFields(context: TransformationContext) {
const {
factory,
hoistVariableDeclaration,
endLexicalEnvironment,
resumeLexicalEnvironment
@ -65,7 +66,7 @@ namespace ts {
const privateIdentifierEnvironmentStack: (PrivateIdentifierEnvironment | undefined)[] = [];
let currentPrivateIdentifierEnvironment: PrivateIdentifierEnvironment | undefined;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
const options = context.getCompilerOptions();
@ -131,7 +132,7 @@ namespace ts {
if (!shouldTransformPrivateFields) {
return node;
}
return setOriginalNode(createIdentifier(""), node);
return setOriginalNode(factory.createIdentifier(""), node);
}
/**
@ -185,9 +186,9 @@ namespace ts {
const expressions = pendingExpressions;
expressions.push(name.expression);
pendingExpressions = [];
node = updateComputedPropertyName(
node = factory.updateComputedPropertyName(
node,
inlineExpressions(expressions)
factory.inlineExpressions(expressions)
);
}
return node;
@ -197,7 +198,7 @@ namespace ts {
Debug.assert(!some(node.decorators));
if (!shouldTransformPrivateFields && isPrivateIdentifier(node.name)) {
// Initializer is elided as the field is initialized in transformConstructor.
return updateProperty(
return factory.updatePropertyDeclaration(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
@ -212,7 +213,7 @@ namespace ts {
// the property name to the temporary variable.
const expr = getPropertyNameExpressionIfNeeded(node.name, !!node.initializer || !!context.getCompilerOptions().useDefineForClassFields);
if (expr && !isSimpleInlineableExpression(expr)) {
(pendingExpressions || (pendingExpressions = [])).push(expr);
getPendingExpressions().push(expr);
}
return undefined;
}
@ -221,9 +222,8 @@ namespace ts {
receiver = visitNode(receiver, visitor, isExpression);
switch (info.placement) {
case PrivateIdentifierPlacement.InstanceField:
return createClassPrivateFieldGetHelper(
context,
nodeIsSynthesized(receiver) ? receiver : getSynthesizedClone(receiver),
return context.getEmitHelperFactory().createClassPrivateFieldGetHelper(
nodeIsSynthesized(receiver) ? receiver : factory.cloneNode(receiver),
info.weakMapName
);
default: return Debug.fail("Unexpected private identifier placement");
@ -253,13 +253,13 @@ namespace ts {
const receiver = visitNode(node.operand.expression, visitor, isExpression);
const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver);
const existingValue = createPrefix(SyntaxKind.PlusToken, createPrivateIdentifierAccess(info, readExpression));
const existingValue = factory.createPrefixUnaryExpression(SyntaxKind.PlusToken, createPrivateIdentifierAccess(info, readExpression));
return setOriginalNode(
createPrivateIdentifierAssignment(
info,
initializeExpression || readExpression,
createBinary(existingValue, operator, createLiteral(1)),
factory.createBinaryExpression(existingValue, operator, factory.createNumericLiteral(1)),
SyntaxKind.EqualsToken
),
node
@ -279,20 +279,20 @@ namespace ts {
const receiver = visitNode(node.operand.expression, visitor, isExpression);
const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver);
const existingValue = createPrefix(SyntaxKind.PlusToken, createPrivateIdentifierAccess(info, readExpression));
const existingValue = factory.createPrefixUnaryExpression(SyntaxKind.PlusToken, createPrivateIdentifierAccess(info, readExpression));
// Create a temporary variable to store the value returned by the expression.
const returnValue = valueIsDiscarded ? undefined : createTempVariable(hoistVariableDeclaration);
const returnValue = valueIsDiscarded ? undefined : factory.createTempVariable(hoistVariableDeclaration);
return setOriginalNode(
inlineExpressions(compact<Expression>([
factory.inlineExpressions(compact<Expression>([
createPrivateIdentifierAssignment(
info,
initializeExpression || readExpression,
createBinary(
returnValue ? createAssignment(returnValue, existingValue) : existingValue,
factory.createBinaryExpression(
returnValue ? factory.createAssignment(returnValue, existingValue) : existingValue,
operator,
createLiteral(1)
factory.createNumericLiteral(1)
),
SyntaxKind.EqualsToken
),
@ -307,7 +307,7 @@ namespace ts {
function visitForStatement(node: ForStatement) {
if (node.incrementor && isPostfixUnaryExpression(node.incrementor)) {
return updateFor(
return factory.updateForStatement(
node,
visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
@ -320,28 +320,28 @@ namespace ts {
function visitExpressionStatement(node: ExpressionStatement) {
if (isPostfixUnaryExpression(node.expression)) {
return updateExpressionStatement(node, visitPostfixUnaryExpression(node.expression, /*valueIsDiscarded*/ true));
return factory.updateExpressionStatement(node, visitPostfixUnaryExpression(node.expression, /*valueIsDiscarded*/ true));
}
return visitEachChild(node, visitor, context);
}
function createCopiableReceiverExpr(receiver: Expression): { readExpression: Expression; initializeExpression: Expression | undefined } {
const clone = nodeIsSynthesized(receiver) ? receiver : getSynthesizedClone(receiver);
const clone = nodeIsSynthesized(receiver) ? receiver : factory.cloneNode(receiver);
if (isSimpleInlineableExpression(receiver)) {
return { readExpression: clone, initializeExpression: undefined };
}
const readExpression = createTempVariable(hoistVariableDeclaration);
const initializeExpression = createAssignment(readExpression, clone);
const readExpression = factory.createTempVariable(hoistVariableDeclaration);
const initializeExpression = factory.createAssignment(readExpression, clone);
return { readExpression, initializeExpression };
}
function visitCallExpression(node: CallExpression) {
if (shouldTransformPrivateFields && isPrivateIdentifierPropertyAccessExpression(node.expression)) {
// Transform call expressions of private names to properly bind the `this` parameter.
const { thisArg, target } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion);
return updateCall(
const { thisArg, target } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion);
return factory.updateCallExpression(
node,
createPropertyAccess(visitNode(target, visitor), "call"),
factory.createPropertyAccessExpression(visitNode(target, visitor), "call"),
/*typeArguments*/ undefined,
[visitNode(thisArg, visitor, isExpression), ...visitNodes(node.arguments, visitor, isExpression)]
);
@ -352,14 +352,15 @@ namespace ts {
function visitTaggedTemplateExpression(node: TaggedTemplateExpression) {
if (shouldTransformPrivateFields && isPrivateIdentifierPropertyAccessExpression(node.tag)) {
// Bind the `this` correctly for tagged template literals when the tag is a private identifier property access.
const { thisArg, target } = createCallBinding(node.tag, hoistVariableDeclaration, languageVersion);
return updateTaggedTemplate(
const { thisArg, target } = factory.createCallBinding(node.tag, hoistVariableDeclaration, languageVersion);
return factory.updateTaggedTemplateExpression(
node,
createCall(
createPropertyAccess(visitNode(target, visitor), "bind"),
factory.createCallExpression(
factory.createPropertyAccessExpression(visitNode(target, visitor), "bind"),
/*typeArguments*/ undefined,
[visitNode(thisArg, visitor, isExpression)]
),
/*typeArguments*/ undefined,
visitNode(node.template, visitor, isTemplateLiteral)
);
}
@ -371,14 +372,14 @@ namespace ts {
if (isDestructuringAssignment(node)) {
const savedPendingExpressions = pendingExpressions;
pendingExpressions = undefined!;
node = updateBinary(
node = factory.updateBinaryExpression(
node,
visitNode(node.left, visitorDestructuringTarget),
visitNode(node.right, visitor),
node.operatorToken
node.operatorToken,
visitNode(node.right, visitor)
);
const expr = some(pendingExpressions) ?
inlineExpressions(compact([...pendingExpressions!, node])) :
factory.inlineExpressions(compact([...pendingExpressions!, node])) :
node;
pendingExpressions = savedPendingExpressions;
return expr;
@ -410,19 +411,18 @@ namespace ts {
right = visitNode(right, visitor, isExpression);
if (isCompoundAssignment(operator)) {
const { readExpression, initializeExpression } = createCopiableReceiverExpr(receiver);
return createClassPrivateFieldSetHelper(
context,
return context.getEmitHelperFactory().createClassPrivateFieldSetHelper(
initializeExpression || readExpression,
info.weakMapName,
createBinary(
createClassPrivateFieldGetHelper(context, readExpression, info.weakMapName),
factory.createBinaryExpression(
context.getEmitHelperFactory().createClassPrivateFieldGetHelper(readExpression, info.weakMapName),
getNonAssignmentOperatorForCompoundAssignment(operator),
right
)
);
}
else {
return createClassPrivateFieldSetHelper(context, receiver, info.weakMapName, right);
return context.getEmitHelperFactory().createClassPrivateFieldSetHelper(receiver, info.weakMapName, right);
}
}
@ -460,7 +460,7 @@ namespace ts {
const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword);
const statements: Statement[] = [
updateClassDeclaration(
factory.updateClassDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
@ -473,7 +473,7 @@ namespace ts {
// Write any pending expressions from elided or moved computed property names
if (some(pendingExpressions)) {
statements.push(createExpressionStatement(inlineExpressions(pendingExpressions)));
statements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)));
}
// Emit static property assignment. Because classDeclaration is lexically evaluated,
@ -483,7 +483,7 @@ namespace ts {
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
const staticProperties = getProperties(node, /*requireInitializer*/ true, /*isStatic*/ true);
if (some(staticProperties)) {
addPropertyStatements(statements, staticProperties, getInternalName(node));
addPropertyStatements(statements, staticProperties, factory.getInternalName(node));
}
return statements;
@ -507,8 +507,9 @@ namespace ts {
const extendsClauseElement = getEffectiveBaseTypeNode(node);
const isDerivedClass = !!(extendsClauseElement && skipOuterExpressions(extendsClauseElement.expression).kind !== SyntaxKind.NullKeyword);
const classExpression = updateClassExpression(
const classExpression = factory.updateClassExpression(
node,
visitNodes(node.decorators, visitor, isDecorator),
node.modifiers,
node.name,
/*typeParameters*/ undefined,
@ -522,22 +523,22 @@ namespace ts {
// Write any pending expressions from elided or moved computed property names
if (pendingStatements && pendingExpressions && some(pendingExpressions)) {
pendingStatements.push(createExpressionStatement(inlineExpressions(pendingExpressions)));
pendingStatements.push(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)));
}
if (pendingStatements && some(staticProperties)) {
addPropertyStatements(pendingStatements, staticProperties, getInternalName(node));
addPropertyStatements(pendingStatements, staticProperties, factory.getInternalName(node));
}
return classExpression;
}
else {
const expressions: Expression[] = [];
const isClassWithConstructorReference = resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference;
const temp = createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference);
const temp = factory.createTempVariable(hoistVariableDeclaration, !!isClassWithConstructorReference);
if (isClassWithConstructorReference) {
// record an alias as the class name is not in scope for statics.
enableSubstitutionForClassAliases();
const alias = getSynthesizedClone(temp);
const alias = factory.cloneNode(temp) as GeneratedIdentifier;
alias.autoGenerateFlags &= ~GeneratedIdentifierFlags.ReservedInNestedScopes;
classAliases[getOriginalNodeId(node)] = alias;
}
@ -545,13 +546,13 @@ namespace ts {
// To preserve the behavior of the old emitter, we explicitly indent
// the body of a class with static initializers.
setEmitFlags(classExpression, EmitFlags.Indented | getEmitFlags(classExpression));
expressions.push(startOnNewLine(createAssignment(temp, classExpression)));
expressions.push(startOnNewLine(factory.createAssignment(temp, classExpression)));
// Add any pending expressions leftover from elided or relocated computed property names
addRange(expressions, map(pendingExpressions, startOnNewLine));
addRange(expressions, generateInitializedPropertyExpressions(staticProperties, temp));
expressions.push(startOnNewLine(temp));
return inlineExpressions(expressions);
return factory.inlineExpressions(expressions);
}
}
@ -574,7 +575,7 @@ namespace ts {
members.push(constructor);
}
addRange(members, visitNodes(node.members, classElementVisitor, isClassElement));
return setTextRange(createNodeArray(members), /*location*/ node.members);
return setTextRange(factory.createNodeArray(members), /*location*/ node.members);
}
function isPropertyDeclarationThatRequiresConstructorStatement(member: ClassElement): member is PropertyDeclaration {
@ -603,7 +604,7 @@ namespace ts {
return startOnNewLine(
setOriginalNode(
setTextRange(
createConstructor(
factory.createConstructorDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters ?? [],
@ -640,18 +641,18 @@ namespace ts {
// super(...arguments);
//
statements.push(
createExpressionStatement(
createCall(
createSuper(),
factory.createExpressionStatement(
factory.createCallExpression(
factory.createSuper(),
/*typeArguments*/ undefined,
[createSpread(createIdentifier("arguments"))]
[factory.createSpreadElement(factory.createIdentifier("arguments"))]
)
)
);
}
if (constructor) {
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(constructor, statements, visitor);
indexOfFirstStatement = addPrologueDirectivesAndInitialSuperCall(factory, constructor, statements, visitor);
}
// Add the property initializers. Transforms this:
//
@ -675,19 +676,19 @@ namespace ts {
indexOfFirstStatement = afterParameterProperties;
}
}
addPropertyStatements(statements, properties, createThis());
addPropertyStatements(statements, properties, factory.createThis());
// Add existing statements, skipping the initial super call.
if (constructor) {
addRange(statements, visitNodes(constructor.body!.statements, visitor, isStatement, indexOfFirstStatement));
}
statements = mergeLexicalEnvironment(statements, endLexicalEnvironment());
statements = factory.mergeLexicalEnvironment(statements, endLexicalEnvironment());
return setTextRange(
createBlock(
factory.createBlock(
setTextRange(
createNodeArray(statements),
factory.createNodeArray(statements),
/*location*/ constructor ? constructor.body!.statements : node.members
),
/*multiLine*/ true
@ -708,7 +709,7 @@ namespace ts {
if (!expression) {
continue;
}
const statement = createExpressionStatement(expression);
const statement = factory.createExpressionStatement(expression);
setSourceMapRange(statement, moveRangePastModifiers(property));
setCommentRange(statement, property);
setOriginalNode(statement, property);
@ -749,7 +750,7 @@ namespace ts {
// We generate a name here in order to reuse the value cached by the relocated computed name expression (which uses the same generated name)
const emitAssignment = !context.getCompilerOptions().useDefineForClassFields;
const propertyName = isComputedPropertyName(property.name) && !isSimpleInlineableExpression(property.name.expression)
? updateComputedPropertyName(property.name, getGeneratedNameForNode(property.name))
? factory.updateComputedPropertyName(property.name, factory.getGeneratedNameForNode(property.name))
: property.name;
if (shouldTransformPrivateFields && isPrivateIdentifier(propertyName)) {
@ -778,20 +779,20 @@ namespace ts {
}
const propertyOriginalNode = getOriginalNode(property);
const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression)
const initializer = property.initializer || emitAssignment ? visitNode(property.initializer, visitor, isExpression) ?? factory.createVoidZero()
: isParameterPropertyDeclaration(propertyOriginalNode, propertyOriginalNode.parent) && isIdentifier(propertyName) ? propertyName
: createVoidZero();
: factory.createVoidZero();
if (emitAssignment || isPrivateIdentifier(propertyName)) {
const memberAccess = createMemberAccessForPropertyName(receiver, propertyName, /*location*/ propertyName);
return createAssignment(memberAccess, initializer);
const memberAccess = createMemberAccessForPropertyName(factory, receiver, propertyName, /*location*/ propertyName);
return factory.createAssignment(memberAccess, initializer);
}
else {
const name = isComputedPropertyName(propertyName) ? propertyName.expression
: isIdentifier(propertyName) ? createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText))
: isIdentifier(propertyName) ? factory.createStringLiteral(unescapeLeadingUnderscores(propertyName.escapedText))
: propertyName;
const descriptor = createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true });
return createObjectDefinePropertyCall(receiver, name, descriptor);
const descriptor = factory.createPropertyDescriptor({ value: initializer, configurable: true, writable: true, enumerable: true });
return factory.createObjectDefinePropertyCall(receiver, name, descriptor);
}
}
@ -846,7 +847,7 @@ namespace ts {
if (declaration) {
const classAlias = classAliases[declaration.id!]; // TODO: GH#18217
if (classAlias) {
const clone = getSynthesizedClone(classAlias);
const clone = factory.cloneNode(classAlias);
setSourceMapRange(clone, node);
setCommentRange(clone, node);
return clone;
@ -871,9 +872,9 @@ namespace ts {
const inlinable = isSimpleInlineableExpression(innerExpression);
const alreadyTransformed = isAssignmentExpression(innerExpression) && isGeneratedIdentifier(innerExpression.left);
if (!alreadyTransformed && !inlinable && shouldHoist) {
const generatedName = getGeneratedNameForNode(name);
const generatedName = factory.getGeneratedNameForNode(name);
hoistVariableDeclaration(generatedName);
return createAssignment(generatedName, expression);
return factory.createAssignment(generatedName, expression);
}
return (inlinable || isIdentifier(innerExpression)) ? undefined : expression;
}
@ -888,18 +889,24 @@ namespace ts {
currentPrivateIdentifierEnvironment = privateIdentifierEnvironmentStack.pop();
}
function getPrivateIdentifierEnvironment() {
return currentPrivateIdentifierEnvironment || (currentPrivateIdentifierEnvironment = createUnderscoreEscapedMap());
}
function getPendingExpressions() {
return pendingExpressions || (pendingExpressions = []);
}
function addPrivateIdentifierToEnvironment(name: PrivateIdentifier) {
const text = getTextOfPropertyName(name) as string;
const weakMapName = createOptimisticUniqueName("_" + text.substring(1));
weakMapName.autoGenerateFlags |= GeneratedIdentifierFlags.ReservedInNestedScopes;
const weakMapName = factory.createUniqueName("_" + text.substring(1), GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.ReservedInNestedScopes);
hoistVariableDeclaration(weakMapName);
(currentPrivateIdentifierEnvironment || (currentPrivateIdentifierEnvironment = createUnderscoreEscapedMap()))
.set(name.escapedText, { placement: PrivateIdentifierPlacement.InstanceField, weakMapName });
(pendingExpressions || (pendingExpressions = [])).push(
createAssignment(
getPrivateIdentifierEnvironment().set(name.escapedText, { placement: PrivateIdentifierPlacement.InstanceField, weakMapName });
getPendingExpressions().push(
factory.createAssignment(
weakMapName,
createNew(
createIdentifier("WeakMap"),
factory.createNewExpression(
factory.createIdentifier("WeakMap"),
/*typeArguments*/ undefined,
[]
)
@ -929,7 +936,7 @@ namespace ts {
function wrapPrivateIdentifierForDestructuringTarget(node: PrivateIdentifierPropertyAccessExpression) {
const parameter = getGeneratedNameForNode(node);
const parameter = factory.getGeneratedNameForNode(node);
const info = accessPrivateIdentifier(node.name);
if (!info) {
return visitEachChild(node, visitor, context);
@ -938,19 +945,18 @@ namespace ts {
// We cannot copy `this` or `super` into the function because they will be bound
// differently inside the function.
if (isThisProperty(node) || isSuperProperty(node) || !isSimpleCopiableExpression(node.expression)) {
receiver = createTempVariable(hoistVariableDeclaration);
(receiver as Identifier).autoGenerateFlags! |= GeneratedIdentifierFlags.ReservedInNestedScopes;
(pendingExpressions || (pendingExpressions = [])).push(createBinary(receiver, SyntaxKind.EqualsToken, node.expression));
receiver = factory.createTempVariable(hoistVariableDeclaration, /*reservedInNestedScopes*/ true);
getPendingExpressions().push(factory.createBinaryExpression(receiver, SyntaxKind.EqualsToken, node.expression));
}
return createPropertyAccess(
return factory.createPropertyAccessExpression(
// Explicit parens required because of v8 regression (https://bugs.chromium.org/p/v8/issues/detail?id=9560)
createParen(
createObjectLiteral([
createSetAccessor(
factory.createParenthesizedExpression(
factory.createObjectLiteralExpression([
factory.createSetAccessorDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
"value",
[createParameter(
[factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
@ -959,8 +965,8 @@ namespace ts {
/*type*/ undefined,
/*initializer*/ undefined
)],
createBlock(
[createExpressionStatement(
factory.createBlock(
[factory.createExpressionStatement(
createPrivateIdentifierAssignment(
info,
receiver,
@ -981,15 +987,15 @@ namespace ts {
if (target && isPrivateIdentifierPropertyAccessExpression(target)) {
const wrapped = wrapPrivateIdentifierForDestructuringTarget(target);
if (isAssignmentExpression(node)) {
return updateBinary(
return factory.updateBinaryExpression(
node,
wrapped,
visitNode(node.right, visitor, isExpression),
node.operatorToken
node.operatorToken,
visitNode(node.right, visitor, isExpression)
);
}
else if (isSpreadElement(node)) {
return updateSpread(node, wrapped);
return factory.updateSpreadElement(node, wrapped);
}
else {
return wrapped;
@ -1004,13 +1010,13 @@ namespace ts {
if (target && isPrivateIdentifierPropertyAccessExpression(target)) {
const initializer = getInitializerOfBindingOrAssignmentElement(node);
const wrapped = wrapPrivateIdentifierForDestructuringTarget(target);
return updatePropertyAssignment(
return factory.updatePropertyAssignment(
node,
visitNode(node.name, visitor),
initializer ? createAssignment(wrapped, visitNode(initializer, visitor)) : wrapped,
initializer ? factory.createAssignment(wrapped, visitNode(initializer, visitor)) : wrapped,
);
}
return updatePropertyAssignment(
return factory.updatePropertyAssignment(
node,
visitNode(node.name, visitor),
visitNode(node.initializer, visitorDestructuringTarget)
@ -1029,7 +1035,7 @@ namespace ts {
//
// Transformation:
// [ { set value(x) { this.#myProp = x; } }.value ] = [ "hello" ];
return updateArrayLiteral(
return factory.updateArrayLiteralExpression(
node,
visitNodes(node.elements, visitArrayAssignmentTarget, isExpression)
);
@ -1042,7 +1048,7 @@ namespace ts {
//
// Transformation:
// ({ stringProperty: { set value(x) { this.#myProp = x; } }.value }) = { stringProperty: "hello" };
return updateObjectLiteral(
return factory.updateObjectLiteralExpression(
node,
visitNodes(node.properties, visitObjectAssignmentTarget, isObjectLiteralElementLike)
);
@ -1051,45 +1057,10 @@ namespace ts {
}
function createPrivateInstanceFieldInitializer(receiver: LeftHandSideExpression, initializer: Expression | undefined, weakMapName: Identifier) {
return createCall(
createPropertyAccess(weakMapName, "set"),
return factory.createCallExpression(
factory.createPropertyAccessExpression(weakMapName, "set"),
/*typeArguments*/ undefined,
[receiver, initializer || createVoidZero()]
[receiver, initializer || factory.createVoidZero()]
);
}
export const classPrivateFieldGetHelper: UnscopedEmitHelper = {
name: "typescript:classPrivateFieldGet",
scoped: false,
text: `
var __classPrivateFieldGet = (this && this.__classPrivateFieldGet) || function (receiver, privateMap) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to get private field on non-instance");
}
return privateMap.get(receiver);
};`
};
function createClassPrivateFieldGetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier) {
context.requestEmitHelper(classPrivateFieldGetHelper);
return createCall(getUnscopedHelperName("__classPrivateFieldGet"), /* typeArguments */ undefined, [receiver, privateField]);
}
export const classPrivateFieldSetHelper: UnscopedEmitHelper = {
name: "typescript:classPrivateFieldSet",
scoped: false,
text: `
var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (receiver, privateMap, value) {
if (!privateMap.has(receiver)) {
throw new TypeError("attempted to set private field on non-instance");
}
privateMap.set(receiver, value);
return value;
};`
};
function createClassPrivateFieldSetHelper(context: TransformationContext, receiver: Expression, privateField: Identifier, value: Expression) {
context.requestEmitHelper(classPrivateFieldSetHelper);
return createCall(getUnscopedHelperName("__classPrivateFieldSet"), /* typeArguments */ undefined, [receiver, privateField, value]);
}
}

View File

@ -1,11 +1,8 @@
/*@internal*/
namespace ts {
export function getDeclarationDiagnostics(host: EmitHost, resolver: EmitResolver, file: SourceFile | undefined): DiagnosticWithLocation[] | undefined {
if (file && isJsonSourceFile(file)) {
return []; // No declaration diagnostics for json for now
}
const compilerOptions = host.getCompilerOptions();
const result = transformNodes(resolver, host, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false);
const result = transformNodes(resolver, host, factory, compilerOptions, file ? [file] : filter(host.getSourceFiles(), isSourceFileNotJson), [transformDeclarations], /*allowDtsFiles*/ false);
return result.diagnostics;
}
@ -67,6 +64,7 @@ namespace ts {
let suppressNewDiagnosticContexts: boolean;
let exportedModulesFromDeclarationEmit: Symbol[] | undefined;
const { factory } = context;
const host = context.getEmitHost();
const symbolTracker: SymbolTracker = {
trackSymbol,
@ -236,7 +234,7 @@ namespace ts {
refs = createMap<SourceFile>();
libs = createMap<boolean>();
let hasNoDefaultLib = false;
const bundle = createBundle(map(node.sourceFiles,
const bundle = factory.createBundle(map(node.sourceFiles,
sourceFile => {
if (sourceFile.isDeclarationFile) return undefined!; // Omit declaration files from bundle results, too // TODO: GH#18217
hasNoDefaultLib = hasNoDefaultLib || sourceFile.hasNoDefaultLib;
@ -253,18 +251,18 @@ namespace ts {
if (isExternalOrCommonJsModule(sourceFile) || isJsonSourceFile(sourceFile)) {
resultHasExternalModuleIndicator = false; // unused in external module bundle emit (all external modules are within module blocks, therefore are known to be modules)
needsDeclare = false;
const statements = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
const newFile = updateSourceFileNode(sourceFile, [createModuleDeclaration(
const statements = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile, /*bundled*/ true)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
const newFile = factory.updateSourceFile(sourceFile, [factory.createModuleDeclaration(
[],
[createModifier(SyntaxKind.DeclareKeyword)],
createLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)),
createModuleBlock(setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements))
[factory.createModifier(SyntaxKind.DeclareKeyword)],
factory.createStringLiteral(getResolvedExternalModuleName(context.getEmitHost(), sourceFile)),
factory.createModuleBlock(setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), sourceFile.statements))
)], /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
return newFile;
}
needsDeclare = true;
const updated = isSourceFileJS(sourceFile) ? createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
return updateSourceFileNode(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
const updated = isSourceFileJS(sourceFile) ? factory.createNodeArray(transformDeclarationsForJS(sourceFile)) : visitNodes(sourceFile.statements, visitDeclarationStatements);
return factory.updateSourceFile(sourceFile, transformAndReplaceLatePaintedStatements(updated), /*isDeclarationFile*/ true, /*referencedFiles*/ [], /*typeReferences*/ [], /*hasNoDefaultLib*/ false, /*libReferences*/ []);
}
), mapDefined(node.prepends, prepend => {
if (prepend.kind === SyntaxKind.InputFiles) {
@ -307,20 +305,20 @@ namespace ts {
const referenceVisitor = mapReferencesIntoArray(references, outputFilePath);
let combinedStatements: NodeArray<Statement>;
if (isSourceFileJS(currentSourceFile)) {
combinedStatements = createNodeArray(transformDeclarationsForJS(node));
combinedStatements = factory.createNodeArray(transformDeclarationsForJS(node));
refs.forEach(referenceVisitor);
emittedImports = filter(combinedStatements, isAnyImportSyntax);
}
else {
const statements = visitNodes(node.statements, visitDeclarationStatements);
combinedStatements = setTextRange(createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
combinedStatements = setTextRange(factory.createNodeArray(transformAndReplaceLatePaintedStatements(statements)), node.statements);
refs.forEach(referenceVisitor);
emittedImports = filter(combinedStatements, isAnyImportSyntax);
if (isExternalModule(node) && (!resultHasExternalModuleIndicator || (needsScopeFixMarker && !resultHasScopeMarker))) {
combinedStatements = setTextRange(createNodeArray([...combinedStatements, createEmptyExports()]), combinedStatements);
combinedStatements = setTextRange(factory.createNodeArray([...combinedStatements, createEmptyExports(factory)]), combinedStatements);
}
}
const updated = updateSourceFileNode(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
const updated = factory.updateSourceFile(node, combinedStatements, /*isDeclarationFile*/ true, references, getFileReferencesForUsedTypeReferences(), node.hasNoDefaultLib, getLibReferences());
updated.exportedModulesFromDeclarationEmit = exportedModulesFromDeclarationEmit;
return updated;
@ -431,10 +429,10 @@ namespace ts {
}
else {
if (name.kind === SyntaxKind.ArrayBindingPattern) {
return updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement));
return factory.updateArrayBindingPattern(name, visitNodes(name.elements, visitBindingElement));
}
else {
return updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement));
return factory.updateObjectBindingPattern(name, visitNodes(name.elements, visitBindingElement));
}
}
@ -443,7 +441,7 @@ namespace ts {
if (elem.kind === SyntaxKind.OmittedExpression) {
return elem;
}
return updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined);
return factory.updateBindingElement(elem, elem.dotDotDotToken, elem.propertyName, filterBindingPatternInitializers(elem.name), shouldPrintWithInitializer(elem) ? elem.initializer : undefined);
}
}
@ -453,13 +451,13 @@ namespace ts {
oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(p);
}
const newParam = updateParameter(
const newParam = factory.updateParameterDeclaration(
p,
/*decorators*/ undefined,
maskModifiers(p, modifierMask),
p.dotDotDotToken,
filterBindingPatternInitializers(p.name),
resolver.isOptionalParameter(p) ? (p.questionToken || createToken(SyntaxKind.QuestionToken)) : undefined,
resolver.isOptionalParameter(p) ? (p.questionToken || factory.createToken(SyntaxKind.QuestionToken)) : undefined,
ensureType(p, type || p.type, /*ignorePrivate*/ true), // Ignore private param props, since this type is going straight back into a param
ensureNoInitializer(p)
);
@ -510,12 +508,12 @@ namespace ts {
return visitNode(type, visitDeclarationSubtree);
}
if (!getParseTreeNode(node)) {
return type ? visitNode(type, visitDeclarationSubtree) : createKeywordTypeNode(SyntaxKind.AnyKeyword);
return type ? visitNode(type, visitDeclarationSubtree) : factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
if (node.kind === SyntaxKind.SetAccessor) {
// Set accessors with no associated type node (from it's param or get accessor return) are `any` since they are never contextually typed right now
// (The inferred type here will be void, but the old declaration emitter printed `any`, so this replicates that)
return createKeywordTypeNode(SyntaxKind.AnyKeyword);
return factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
errorNameNode = node.name;
let oldDiag: typeof getSymbolAccessibilityDiagnostic;
@ -539,7 +537,7 @@ namespace ts {
if (!suppressNewDiagnosticContexts) {
getSymbolAccessibilityDiagnostic = oldDiag;
}
return returnValue || createKeywordTypeNode(SyntaxKind.AnyKeyword);
return returnValue || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
}
@ -586,7 +584,7 @@ namespace ts {
if (!newParams) {
return undefined!; // TODO: GH#18217
}
return createNodeArray(newParams, params.hasTrailingComma);
return factory.createNodeArray(newParams, params.hasTrailingComma);
}
function updateAccessorParamsList(input: AccessorDeclaration, isPrivate: boolean) {
@ -607,7 +605,7 @@ namespace ts {
}
}
if (!newValueParameter) {
newValueParameter = createParameter(
newValueParameter = factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
@ -616,7 +614,7 @@ namespace ts {
}
newParams = append(newParams, newValueParameter);
}
return createNodeArray(newParams || emptyArray) as NodeArray<ParameterDeclaration>;
return factory.createNodeArray(newParams || emptyArray);
}
function ensureTypeParams(node: Node, params: NodeArray<TypeParameterDeclaration> | undefined) {
@ -654,7 +652,7 @@ namespace ts {
if (isBundledEmit) {
const newName = getExternalModuleNameFromDeclaration(context.getEmitHost(), resolver, parent);
if (newName) {
return createLiteral(newName);
return factory.createStringLiteral(newName);
}
}
else {
@ -672,12 +670,12 @@ namespace ts {
if (decl.moduleReference.kind === SyntaxKind.ExternalModuleReference) {
// Rewrite external module names if necessary
const specifier = getExternalModuleImportEqualsDeclarationExpression(decl);
return updateImportEqualsDeclaration(
return factory.updateImportEqualsDeclaration(
decl,
/*decorators*/ undefined,
decl.modifiers,
decl.name,
updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))
factory.updateExternalModuleReference(decl.moduleReference, rewriteModuleSpecifier(decl, specifier))
);
}
else {
@ -692,7 +690,7 @@ namespace ts {
function transformImportDeclaration(decl: ImportDeclaration) {
if (!decl.importClause) {
// import "mod" - possibly needed for side effects? (global interface patches, module augmentations, etc)
return updateImportDeclaration(
return factory.updateImportDeclaration(
decl,
/*decorators*/ undefined,
decl.modifiers,
@ -704,42 +702,42 @@ namespace ts {
const visibleDefaultBinding = decl.importClause && decl.importClause.name && resolver.isDeclarationVisible(decl.importClause) ? decl.importClause.name : undefined;
if (!decl.importClause.namedBindings) {
// No named bindings (either namespace or list), meaning the import is just default or should be elided
return visibleDefaultBinding && updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause(
return visibleDefaultBinding && factory.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, factory.updateImportClause(
decl.importClause,
decl.importClause.isTypeOnly,
visibleDefaultBinding,
/*namedBindings*/ undefined,
decl.importClause.isTypeOnly,
), rewriteModuleSpecifier(decl, decl.moduleSpecifier));
}
if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) {
// Namespace import (optionally with visible default)
const namedBindings = resolver.isDeclarationVisible(decl.importClause.namedBindings) ? decl.importClause.namedBindings : /*namedBindings*/ undefined;
return visibleDefaultBinding || namedBindings ? updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, updateImportClause(
return visibleDefaultBinding || namedBindings ? factory.updateImportDeclaration(decl, /*decorators*/ undefined, decl.modifiers, factory.updateImportClause(
decl.importClause,
decl.importClause.isTypeOnly,
visibleDefaultBinding,
namedBindings,
decl.importClause.isTypeOnly,
), rewriteModuleSpecifier(decl, decl.moduleSpecifier)) : undefined;
}
// Named imports (optionally with visible default)
const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined);
if ((bindingList && bindingList.length) || visibleDefaultBinding) {
return updateImportDeclaration(
return factory.updateImportDeclaration(
decl,
/*decorators*/ undefined,
decl.modifiers,
updateImportClause(
factory.updateImportClause(
decl.importClause,
visibleDefaultBinding,
bindingList && bindingList.length ? updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined,
decl.importClause.isTypeOnly,
visibleDefaultBinding,
bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined,
),
rewriteModuleSpecifier(decl, decl.moduleSpecifier)
);
}
// Augmentation of export depends on import
if (resolver.isImportRequiredByAugmentation(decl)) {
return updateImportDeclaration(
return factory.updateImportDeclaration(
decl,
/*decorators*/ undefined,
decl.modifiers,
@ -835,7 +833,7 @@ namespace ts {
if (isMethodDeclaration(input) || isMethodSignature(input)) {
if (hasEffectiveModifier(input, ModifierFlags.Private)) {
if (input.symbol && input.symbol.declarations && input.symbol.declarations[0] !== input) return; // Elide all but the first overload
return cleanup(createProperty(/*decorators*/undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined));
return cleanup(factory.createPropertyDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name, /*questionToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined));
}
}
@ -859,15 +857,15 @@ namespace ts {
checkEntityNameVisibility(input.expression, enclosingDeclaration);
}
const node = visitEachChild(input, visitDeclarationSubtree, context);
return cleanup(updateExpressionWithTypeArguments(node, parenthesizeTypeParameters(node.typeArguments), node.expression));
return cleanup(factory.updateExpressionWithTypeArguments(node, node.expression, node.typeArguments));
}
case SyntaxKind.TypeReference: {
checkEntityNameVisibility(input.typeName, enclosingDeclaration);
const node = visitEachChild(input, visitDeclarationSubtree, context);
return cleanup(updateTypeReferenceNode(node, node.typeName, parenthesizeTypeParameters(node.typeArguments)));
return cleanup(factory.updateTypeReferenceNode(node, node.typeName, node.typeArguments));
}
case SyntaxKind.ConstructSignature:
return cleanup(updateConstructSignature(
return cleanup(factory.updateConstructSignature(
input,
ensureTypeParams(input, input.typeParameters),
updateParamsList(input, input.parameters),
@ -875,28 +873,29 @@ namespace ts {
));
case SyntaxKind.Constructor: {
// A constructor declaration may not have a type annotation
const ctor = createSignatureDeclaration(
SyntaxKind.Constructor,
ensureTypeParams(input, input.typeParameters),
const ctor = factory.createConstructorDeclaration(
/*decorators*/ undefined,
/*modifiers*/ ensureModifiers(input),
updateParamsList(input, input.parameters, ModifierFlags.None),
/*type*/ undefined
/*body*/ undefined
);
ctor.modifiers = createNodeArray(ensureModifiers(input));
return cleanup(ctor);
}
case SyntaxKind.MethodDeclaration: {
if (isPrivateIdentifier(input.name)) {
return cleanup(/*returnValue*/ undefined);
}
const sig = createSignatureDeclaration(
SyntaxKind.MethodSignature,
const sig = factory.createMethodDeclaration(
/*decorators*/ undefined,
ensureModifiers(input),
/*asteriskToken*/ undefined,
input.name,
input.questionToken,
ensureTypeParams(input, input.typeParameters),
updateParamsList(input, input.parameters),
ensureType(input, input.type)
) as MethodSignature;
sig.name = input.name;
sig.modifiers = createNodeArray(ensureModifiers(input));
sig.questionToken = input.questionToken;
ensureType(input, input.type),
/*body*/ undefined
);
return cleanup(sig);
}
case SyntaxKind.GetAccessor: {
@ -904,7 +903,7 @@ namespace ts {
return cleanup(/*returnValue*/ undefined);
}
const accessorType = getTypeAnnotationFromAllAccessorDeclarations(input, resolver.getAllAccessorDeclarations(input));
return cleanup(updateGetAccessor(
return cleanup(factory.updateGetAccessorDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -917,7 +916,7 @@ namespace ts {
if (isPrivateIdentifier(input.name)) {
return cleanup(/*returnValue*/ undefined);
}
return cleanup(updateSetAccessor(
return cleanup(factory.updateSetAccessorDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -929,7 +928,7 @@ namespace ts {
if (isPrivateIdentifier(input.name)) {
return cleanup(/*returnValue*/ undefined);
}
return cleanup(updateProperty(
return cleanup(factory.updatePropertyDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -942,29 +941,29 @@ namespace ts {
if (isPrivateIdentifier(input.name)) {
return cleanup(/*returnValue*/ undefined);
}
return cleanup(updatePropertySignature(
return cleanup(factory.updatePropertySignature(
input,
ensureModifiers(input),
input.name,
input.questionToken,
ensureType(input, input.type),
ensureNoInitializer(input)
ensureType(input, input.type)
));
case SyntaxKind.MethodSignature: {
if (isPrivateIdentifier(input.name)) {
return cleanup(/*returnValue*/ undefined);
}
return cleanup(updateMethodSignature(
return cleanup(factory.updateMethodSignature(
input,
ensureModifiers(input),
input.name,
input.questionToken,
ensureTypeParams(input, input.typeParameters),
updateParamsList(input, input.parameters),
ensureType(input, input.type),
input.name,
input.questionToken
ensureType(input, input.type)
));
}
case SyntaxKind.CallSignature: {
return cleanup(updateCallSignature(
return cleanup(factory.updateCallSignature(
input,
ensureTypeParams(input, input.typeParameters),
updateParamsList(input, input.parameters),
@ -972,12 +971,12 @@ namespace ts {
));
}
case SyntaxKind.IndexSignature: {
return cleanup(updateIndexSignature(
return cleanup(factory.updateIndexSignature(
input,
/*decorators*/ undefined,
ensureModifiers(input),
updateParamsList(input, input.parameters),
visitNode(input.type, visitDeclarationSubtree) || createKeywordTypeNode(SyntaxKind.AnyKeyword)
visitNode(input.type, visitDeclarationSubtree) || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword)
));
}
case SyntaxKind.VariableDeclaration: {
@ -986,11 +985,11 @@ namespace ts {
}
shouldEnterSuppressNewDiagnosticsContextContext = true;
suppressNewDiagnosticContexts = true; // Variable declaration types also suppress new diagnostic contexts, provided the contexts wouldn't be made for binding pattern types
return cleanup(updateTypeScriptVariableDeclaration(input, input.name, /*exclaimationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input)));
return cleanup(factory.updateVariableDeclaration(input, input.name, /*exclamationToken*/ undefined, ensureType(input, input.type), ensureNoInitializer(input)));
}
case SyntaxKind.TypeParameter: {
if (isPrivateMethodTypeParameter(input) && (input.default || input.constraint)) {
return cleanup(updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined));
return cleanup(factory.updateTypeParameterDeclaration(input, input.name, /*constraint*/ undefined, /*defaultType*/ undefined));
}
return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
}
@ -1004,19 +1003,19 @@ namespace ts {
const trueType = visitNode(input.trueType, visitDeclarationSubtree);
enclosingDeclaration = oldEnclosingDecl;
const falseType = visitNode(input.falseType, visitDeclarationSubtree);
return cleanup(updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType));
return cleanup(factory.updateConditionalTypeNode(input, checkType, extendsType, trueType, falseType));
}
case SyntaxKind.FunctionType: {
return cleanup(updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
return cleanup(factory.updateFunctionTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
}
case SyntaxKind.ConstructorType: {
return cleanup(updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
return cleanup(factory.updateConstructorTypeNode(input, visitNodes(input.typeParameters, visitDeclarationSubtree), updateParamsList(input, input.parameters), visitNode(input.type, visitDeclarationSubtree)));
}
case SyntaxKind.ImportType: {
if (!isLiteralImportTypeNode(input)) return cleanup(input);
return cleanup(updateImportTypeNode(
return cleanup(factory.updateImportTypeNode(
input,
updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)),
factory.updateLiteralTypeNode(input.argument, rewriteModuleSpecifier(input, input.argument.literal)),
input.qualifier,
visitNodes(input.typeArguments, visitDeclarationSubtree, isTypeNode),
input.isTypeOf
@ -1071,13 +1070,14 @@ namespace ts {
resultHasScopeMarker = true;
// Always visible if the parent node isn't dropped for being not visible
// Rewrite external module names if necessary
return updateExportDeclaration(
return factory.updateExportDeclaration(
input,
/*decorators*/ undefined,
input.modifiers,
input.isTypeOnly,
input.exportClause,
rewriteModuleSpecifier(input, input.moduleSpecifier),
input.isTypeOnly);
);
}
case SyntaxKind.ExportAssignment: {
// Always visible if the parent node isn't dropped for being not visible
@ -1089,14 +1089,14 @@ namespace ts {
return input;
}
else {
const newId = createOptimisticUniqueName("_default");
const newId = factory.createUniqueName("_default", GeneratedIdentifierFlags.Optimistic);
getSymbolAccessibilityDiagnostic = () => ({
diagnosticMessage: Diagnostics.Default_export_of_the_module_has_or_is_using_private_name_0,
errorNode: input
});
const varDecl = createVariableDeclaration(newId, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = createVariableStatement(needsDeclare ? [createModifier(SyntaxKind.DeclareKeyword)] : [], createVariableDeclarationList([varDecl], NodeFlags.Const));
return [statement, updateExportAssignment(input, input.decorators, input.modifiers, newId)];
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(input.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
return [statement, factory.updateExportAssignment(input, input.decorators, input.modifiers, newId)];
}
}
}
@ -1108,15 +1108,14 @@ namespace ts {
}
function stripExportModifiers(statement: Statement): Statement {
if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default)) {
if (isImportEqualsDeclaration(statement) || hasEffectiveModifier(statement, ModifierFlags.Default) || !canHaveModifiers(statement)) {
// `export import` statements should remain as-is, as imports are _not_ implicitly exported in an ambient namespace
// Likewise, `export default` classes and the like and just be `default`, so we preserve their `export` modifiers, too
return statement;
}
const clone = getMutableClone(statement);
const modifiers = createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export));
clone.modifiers = modifiers.length ? createNodeArray(modifiers) : undefined;
return clone;
const modifiers = factory.createModifiersFromModifierFlags(getEffectiveModifierFlags(statement) & (ModifierFlags.All ^ ModifierFlags.Export));
return factory.updateModifiers(statement, modifiers);
}
function transformTopLevelDeclaration(input: LateVisibilityPaintedStatement) {
@ -1149,7 +1148,7 @@ namespace ts {
const previousNeedsDeclare = needsDeclare;
switch (input.kind) {
case SyntaxKind.TypeAliasDeclaration: // Type aliases get `declare`d if need be (for legacy support), but that's all
return cleanup(updateTypeAliasDeclaration(
return cleanup(factory.updateTypeAliasDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -1158,7 +1157,7 @@ namespace ts {
visitNode(input.type, visitDeclarationSubtree, isTypeNode)
));
case SyntaxKind.InterfaceDeclaration: {
return cleanup(updateInterfaceDeclaration(
return cleanup(factory.updateInterfaceDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -1170,7 +1169,7 @@ namespace ts {
}
case SyntaxKind.FunctionDeclaration: {
// Generators lose their generator-ness, excepting their return type
const clean = cleanup(updateFunctionDeclaration(
const clean = cleanup(factory.updateFunctionDeclaration(
input,
/*decorators*/ undefined,
ensureModifiers(input),
@ -1183,13 +1182,13 @@ namespace ts {
));
if (clean && resolver.isExpandoFunctionDeclaration(input)) {
const props = resolver.getPropertiesOfContainerFunction(input);
const fakespace = createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || createIdentifier("_default"), createModuleBlock([]), NodeFlags.Namespace);
fakespace.flags ^= NodeFlags.Synthesized; // unset synthesized so it is usable as an enclosing declaration
fakespace.parent = enclosingDeclaration as SourceFile | NamespaceDeclaration;
// Use parseNodeFactory so it is usable as an enclosing declaration
const fakespace = parseNodeFactory.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, clean.name || factory.createIdentifier("_default"), factory.createModuleBlock([]), NodeFlags.Namespace);
setParent(fakespace, enclosingDeclaration as SourceFile | NamespaceDeclaration);
fakespace.locals = createSymbolTable(props);
fakespace.symbol = props[0].parent!;
const exportMappings: [Identifier, string][] = [];
const declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
let declarations: (VariableStatement | ExportDeclaration)[] = mapDefined(props, p => {
if (!isPropertyAccessExpression(p.valueDeclaration)) {
return undefined; // TODO GH#33569: Handle element access expressions that created late bound names (rather than silently omitting them)
}
@ -1198,32 +1197,33 @@ namespace ts {
getSymbolAccessibilityDiagnostic = oldDiag;
const nameStr = unescapeLeadingUnderscores(p.escapedName);
const isNonContextualKeywordName = isStringANonContextualKeyword(nameStr);
const name = isNonContextualKeywordName ? getGeneratedNameForNode(p.valueDeclaration) : createIdentifier(nameStr);
const name = isNonContextualKeywordName ? factory.getGeneratedNameForNode(p.valueDeclaration) : factory.createIdentifier(nameStr);
if (isNonContextualKeywordName) {
exportMappings.push([name, nameStr]);
}
const varDecl = createVariableDeclaration(name, type, /*initializer*/ undefined);
return createVariableStatement(isNonContextualKeywordName ? undefined : [createToken(SyntaxKind.ExportKeyword)], createVariableDeclarationList([varDecl]));
const varDecl = factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, type, /*initializer*/ undefined);
return factory.createVariableStatement(isNonContextualKeywordName ? undefined : [factory.createToken(SyntaxKind.ExportKeyword)], factory.createVariableDeclarationList([varDecl]));
});
if (!exportMappings.length) {
forEach(declarations, d => d.modifiers = undefined);
declarations = mapDefined(declarations, declaration => factory.updateModifiers(declaration, ModifierFlags.None));
}
else {
declarations.push(createExportDeclaration(
declarations.push(factory.createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports(map(exportMappings, ([gen, exp]) => {
return createExportSpecifier(gen, exp);
/*isTypeOnly*/ false,
factory.createNamedExports(map(exportMappings, ([gen, exp]) => {
return factory.createExportSpecifier(gen, exp);
}))
));
}
const namespaceDecl = createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, createModuleBlock(declarations), NodeFlags.Namespace);
const namespaceDecl = factory.createModuleDeclaration(/*decorators*/ undefined, ensureModifiers(input), input.name!, factory.createModuleBlock(declarations), NodeFlags.Namespace);
if (!hasEffectiveModifier(clean, ModifierFlags.Default)) {
return [clean, namespaceDecl];
}
const modifiers = createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient);
const cleanDeclaration = updateFunctionDeclaration(
const modifiers = factory.createModifiersFromModifierFlags((getEffectiveModifierFlags(clean) & ~ModifierFlags.ExportDefault) | ModifierFlags.Ambient);
const cleanDeclaration = factory.updateFunctionDeclaration(
clean,
/*decorators*/ undefined,
modifiers,
@ -1235,7 +1235,7 @@ namespace ts {
/*body*/ undefined
);
const namespaceDeclaration = updateModuleDeclaration(
const namespaceDeclaration = factory.updateModuleDeclaration(
namespaceDecl,
/*decorators*/ undefined,
modifiers,
@ -1243,7 +1243,7 @@ namespace ts {
namespaceDecl.body
);
const exportDefaultDeclaration = createExportAssignment(
const exportDefaultDeclaration = factory.createExportAssignment(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*isExportEquals*/ false,
@ -1280,18 +1280,18 @@ namespace ts {
// 3. Some things are exported, some are not, and there's no marker - add an empty marker
if (!isGlobalScopeAugmentation(input) && !hasScopeMarker(lateStatements) && !resultHasScopeMarker) {
if (needsScopeFixMarker) {
lateStatements = createNodeArray([...lateStatements, createEmptyExports()]);
lateStatements = factory.createNodeArray([...lateStatements, createEmptyExports(factory)]);
}
else {
lateStatements = visitNodes(lateStatements, stripExportModifiers);
}
}
const body = updateModuleBlock(inner, lateStatements);
const body = factory.updateModuleBlock(inner, lateStatements);
needsDeclare = previousNeedsDeclare;
needsScopeFixMarker = oldNeedsScopeFix;
resultHasScopeMarker = oldHasScopeFix;
const mods = ensureModifiers(input);
return cleanup(updateModuleDeclaration(
return cleanup(factory.updateModuleDeclaration(
input,
/*decorators*/ undefined,
mods,
@ -1308,7 +1308,7 @@ namespace ts {
const id = "" + getOriginalNodeId(inner!); // TODO: GH#18217
const body = lateStatementReplacementMap.get(id);
lateStatementReplacementMap.delete(id);
return cleanup(updateModuleDeclaration(
return cleanup(factory.updateModuleDeclaration(
input,
/*decorators*/ undefined,
mods,
@ -1318,7 +1318,7 @@ namespace ts {
}
}
case SyntaxKind.ClassDeclaration: {
const modifiers = createNodeArray(ensureModifiers(input));
const modifiers = factory.createNodeArray(ensureModifiers(input));
const typeParameters = ensureTypeParams(input, input.typeParameters);
const ctor = getFirstConstructorWithBody(input);
let parameterProperties: readonly PropertyDeclaration[] | undefined;
@ -1328,7 +1328,7 @@ namespace ts {
if (!hasSyntacticModifier(param, ModifierFlags.ParameterPropertyModifier) || shouldStripInternal(param)) return;
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(param);
if (param.name.kind === SyntaxKind.Identifier) {
return preserveJsDoc(createProperty(
return preserveJsDoc(factory.createPropertyDeclaration(
/*decorators*/ undefined,
ensureModifiers(param),
param.name,
@ -1349,7 +1349,7 @@ namespace ts {
elems = concatenate(elems, walkBindingPattern(elem.name));
}
elems = elems || [];
elems.push(createProperty(
elems.push(factory.createPropertyDeclaration(
/*decorators*/ undefined,
ensureModifiers(param),
elem.name as Identifier,
@ -1366,42 +1366,42 @@ namespace ts {
const hasPrivateIdentifier = some(input.members, member => !!member.name && isPrivateIdentifier(member.name));
const privateIdentifier = hasPrivateIdentifier ? [
createProperty(
factory.createPropertyDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createPrivateIdentifier("#private"),
factory.createPrivateIdentifier("#private"),
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined
)
] : undefined;
const memberNodes = concatenate(concatenate(privateIdentifier, parameterProperties), visitNodes(input.members, visitDeclarationSubtree));
const members = createNodeArray(memberNodes);
const members = factory.createNodeArray(memberNodes);
const extendsClause = getEffectiveBaseTypeNode(input);
if (extendsClause && !isEntityNameExpression(extendsClause.expression) && extendsClause.expression.kind !== SyntaxKind.NullKeyword) {
// We must add a temporary declaration for the extends clause expression
const oldId = input.name ? unescapeLeadingUnderscores(input.name.escapedText) : "default";
const newId = createOptimisticUniqueName(`${oldId}_base`);
const newId = factory.createUniqueName(`${oldId}_base`, GeneratedIdentifierFlags.Optimistic);
getSymbolAccessibilityDiagnostic = () => ({
diagnosticMessage: Diagnostics.extends_clause_of_exported_class_0_has_or_is_using_private_name_1,
errorNode: extendsClause,
typeName: input.name
});
const varDecl = createVariableDeclaration(newId, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = createVariableStatement(needsDeclare ? [createModifier(SyntaxKind.DeclareKeyword)] : [], createVariableDeclarationList([varDecl], NodeFlags.Const));
const heritageClauses = createNodeArray(map(input.heritageClauses, clause => {
const varDecl = factory.createVariableDeclaration(newId, /*exclamationToken*/ undefined, resolver.createTypeOfExpression(extendsClause.expression, input, declarationEmitNodeBuilderFlags, symbolTracker), /*initializer*/ undefined);
const statement = factory.createVariableStatement(needsDeclare ? [factory.createModifier(SyntaxKind.DeclareKeyword)] : [], factory.createVariableDeclarationList([varDecl], NodeFlags.Const));
const heritageClauses = factory.createNodeArray(map(input.heritageClauses, clause => {
if (clause.token === SyntaxKind.ExtendsKeyword) {
const oldDiag = getSymbolAccessibilityDiagnostic;
getSymbolAccessibilityDiagnostic = createGetSymbolAccessibilityDiagnosticForNode(clause.types[0]);
const newClause = updateHeritageClause(clause, map(clause.types, t => updateExpressionWithTypeArguments(t, visitNodes(t.typeArguments, visitDeclarationSubtree), newId)));
const newClause = factory.updateHeritageClause(clause, map(clause.types, t => factory.updateExpressionWithTypeArguments(t, newId, visitNodes(t.typeArguments, visitDeclarationSubtree))));
getSymbolAccessibilityDiagnostic = oldDiag;
return newClause;
}
return updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree));
return factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => isEntityNameExpression(t.expression) || t.expression.kind === SyntaxKind.NullKeyword)), visitDeclarationSubtree));
}));
return [statement, cleanup(updateClassDeclaration(
return [statement, cleanup(factory.updateClassDeclaration(
input,
/*decorators*/ undefined,
modifiers,
@ -1413,7 +1413,7 @@ namespace ts {
}
else {
const heritageClauses = transformHeritageClauses(input.heritageClauses);
return cleanup(updateClassDeclaration(
return cleanup(factory.updateClassDeclaration(
input,
/*decorators*/ undefined,
modifiers,
@ -1428,11 +1428,11 @@ namespace ts {
return cleanup(transformVariableStatement(input));
}
case SyntaxKind.EnumDeclaration: {
return cleanup(updateEnumDeclaration(input, /*decorators*/ undefined, createNodeArray(ensureModifiers(input)), input.name, createNodeArray(mapDefined(input.members, m => {
return cleanup(factory.updateEnumDeclaration(input, /*decorators*/ undefined, factory.createNodeArray(ensureModifiers(input)), input.name, factory.createNodeArray(mapDefined(input.members, m => {
if (shouldStripInternal(m)) return;
// Rewrite enum values to their constants, if available
const constValue = resolver.getConstantValue(m);
return preserveJsDoc(updateEnumMember(m, m.name, constValue !== undefined ? createLiteral(constValue) : undefined), m);
return preserveJsDoc(factory.updateEnumMember(m, m.name, constValue !== undefined ? typeof constValue === "string" ? factory.createStringLiteral(constValue) : factory.createNumericLiteral(constValue) : undefined), m);
}))));
}
}
@ -1460,7 +1460,7 @@ namespace ts {
if (!forEach(input.declarationList.declarations, getBindingNameVisible)) return;
const nodes = visitNodes(input.declarationList.declarations, visitDeclarationSubtree);
if (!length(nodes)) return;
return updateVariableStatement(input, createNodeArray(ensureModifiers(input)), updateVariableDeclarationList(input.declarationList, nodes));
return factory.updateVariableStatement(input, factory.createNodeArray(ensureModifiers(input)), factory.updateVariableDeclarationList(input.declarationList, nodes));
}
function recreateBindingPattern(d: BindingPattern): VariableDeclaration[] {
@ -1477,7 +1477,7 @@ namespace ts {
return recreateBindingPattern(e.name);
}
else {
return createVariableDeclaration(e.name, ensureType(e, /*type*/ undefined), /*initializer*/ undefined);
return factory.createVariableDeclaration(e.name, /*exclamationToken*/ undefined, ensureType(e, /*type*/ undefined), /*initializer*/ undefined);
}
}
}
@ -1517,7 +1517,7 @@ namespace ts {
if (currentFlags === newFlags) {
return node.modifiers;
}
return createModifiersFromModifierFlags(newFlags);
return factory.createModifiersFromModifierFlags(newFlags);
}
function ensureModifierFlags(node: Node): ModifierFlags {
@ -1547,7 +1547,7 @@ namespace ts {
}
function transformHeritageClauses(nodes: NodeArray<HeritageClause> | undefined) {
return createNodeArray(filter(map(nodes, clause => updateHeritageClause(clause, visitNodes(createNodeArray(filter(clause.types, t => {
return factory.createNodeArray(filter(map(nodes, clause => factory.updateHeritageClause(clause, visitNodes(factory.createNodeArray(filter(clause.types, t => {
return isEntityNameExpression(t.expression) || (clause.token === SyntaxKind.ExtendsKeyword && t.expression.kind === SyntaxKind.NullKeyword);
})), visitDeclarationSubtree))), clause => clause.types && !!clause.types.length));
}
@ -1562,7 +1562,7 @@ namespace ts {
// Elide "public" modifier, as it is the default
function maskModifiers(node: Node, modifierMask?: ModifierFlags, modifierAdditions?: ModifierFlags): Modifier[] {
return createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions));
return factory.createModifiersFromModifierFlags(maskModifierFlags(node, modifierMask, modifierAdditions));
}
function maskModifierFlags(node: Node, modifierMask: ModifierFlags = ModifierFlags.All ^ ModifierFlags.Public, modifierAdditions: ModifierFlags = ModifierFlags.None): ModifierFlags {

View File

@ -59,8 +59,8 @@ namespace ts {
hoistTempVariables: true,
emitExpression,
emitBindingOrAssignment,
createArrayBindingOrAssignmentPattern: makeArrayAssignmentPattern,
createObjectBindingOrAssignmentPattern: makeObjectAssignmentPattern,
createArrayBindingOrAssignmentPattern: elements => makeArrayAssignmentPattern(context.factory, elements),
createObjectBindingOrAssignmentPattern: elements => makeObjectAssignmentPattern(context.factory, elements),
createArrayBindingOrAssignmentElement: makeAssignmentElement,
visitor
};
@ -104,10 +104,9 @@ namespace ts {
expressions.push(value);
}
return aggregateTransformFlags(inlineExpressions(expressions!)) || createOmittedExpression();
return context.factory.inlineExpressions(expressions!) || context.factory.createOmittedExpression();
function emitExpression(expression: Expression) {
aggregateTransformFlags(expression);
expressions = append(expressions, expression);
}
@ -116,7 +115,7 @@ namespace ts {
const expression = createAssignmentCallback
? createAssignmentCallback(<Identifier>target, value, location)
: setTextRange(
createAssignment(visitNode(<Expression>target, visitor, isExpression), value),
context.factory.createAssignment(visitNode(<Expression>target, visitor, isExpression), value),
location
);
expression.original = original;
@ -187,9 +186,9 @@ namespace ts {
hoistTempVariables,
emitExpression,
emitBindingOrAssignment,
createArrayBindingOrAssignmentPattern: makeArrayBindingPattern,
createObjectBindingOrAssignmentPattern: makeObjectBindingPattern,
createArrayBindingOrAssignmentElement: makeBindingElement,
createArrayBindingOrAssignmentPattern: elements => makeArrayBindingPattern(context.factory, elements),
createObjectBindingOrAssignmentPattern: elements => makeObjectBindingPattern(context.factory, elements),
createArrayBindingOrAssignmentElement: name => makeBindingElement(context.factory, name),
visitor
};
@ -200,15 +199,15 @@ namespace ts {
// If the right-hand value of the assignment is also an assignment target then
// we need to cache the right-hand value.
initializer = ensureIdentifier(flattenContext, initializer, /*reuseIdentifierExpressions*/ false, initializer);
node = updateVariableDeclaration(node, node.name, node.type, initializer);
node = context.factory.updateVariableDeclaration(node, node.name, /*exclamationToken*/ undefined, /*type*/ undefined, initializer);
}
}
flattenBindingOrAssignmentElement(flattenContext, node, rval, node, skipInitializer);
if (pendingExpressions) {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const temp = context.factory.createTempVariable(/*recordTempVariable*/ undefined);
if (hoistTempVariables) {
const value = inlineExpressions(pendingExpressions);
const value = context.factory.inlineExpressions(pendingExpressions);
pendingExpressions = undefined;
emitBindingOrAssignment(temp, value, /*location*/ undefined, /*original*/ undefined);
}
@ -217,21 +216,21 @@ namespace ts {
const pendingDeclaration = last(pendingDeclarations);
pendingDeclaration.pendingExpressions = append(
pendingDeclaration.pendingExpressions,
createAssignment(temp, pendingDeclaration.value)
context.factory.createAssignment(temp, pendingDeclaration.value)
);
addRange(pendingDeclaration.pendingExpressions, pendingExpressions);
pendingDeclaration.value = temp;
}
}
for (const { pendingExpressions, name, value, location, original } of pendingDeclarations) {
const variable = createVariableDeclaration(
const variable = context.factory.createVariableDeclaration(
name,
/*exclamationToken*/ undefined,
/*type*/ undefined,
pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value
pendingExpressions ? context.factory.inlineExpressions(append(pendingExpressions, value)) : value
);
variable.original = original;
setTextRange(variable, location);
aggregateTransformFlags(variable);
declarations.push(variable);
}
return declarations;
@ -243,7 +242,7 @@ namespace ts {
function emitBindingOrAssignment(target: BindingOrAssignmentElementTarget, value: Expression, location: TextRange | undefined, original: Node | undefined) {
Debug.assertNode(target, isBindingName);
if (pendingExpressions) {
value = inlineExpressions(append(pendingExpressions, value));
value = context.factory.inlineExpressions(append(pendingExpressions, value));
pendingExpressions = undefined;
}
pendingDeclarations.push({ pendingExpressions, name: target, value, location, original });
@ -274,7 +273,7 @@ namespace ts {
}
else if (!value) {
// Use 'void 0' in absence of value and initializer
value = createVoidZero();
value = flattenContext.context.factory.createVoidZero();
}
}
const bindingTarget = getTargetOfBindingOrAssignmentElement(element)!; // TODO: GH#18217
@ -338,7 +337,7 @@ namespace ts {
flattenContext.emitBindingOrAssignment(flattenContext.createObjectBindingOrAssignmentPattern(bindingElements), value, location, pattern);
bindingElements = undefined;
}
const rhsValue = createRestCall(flattenContext.context, value, elements, computedTempVariables!, pattern); // TODO: GH#18217
const rhsValue = flattenContext.context.getEmitHelperFactory().createRestHelper(value, elements, computedTempVariables, pattern);
flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, element);
}
}
@ -363,12 +362,13 @@ namespace ts {
// Read the elements of the iterable into an array
value = ensureIdentifier(
flattenContext,
createReadHelper(
flattenContext.context,
value,
numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1])
? undefined
: numElements,
setTextRange(
flattenContext.context.getEmitHelperFactory().createReadHelper(
value,
numElements > 0 && getRestIndicatorOfBindingOrAssignmentElement(elements[numElements - 1])
? undefined
: numElements
),
location
),
/*reuseIdentifierExpressions*/ false,
@ -394,7 +394,7 @@ namespace ts {
// If an array pattern contains an ObjectRest, we must cache the result so that we
// can perform the ObjectRest destructuring in a different declaration
if (element.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined);
if (flattenContext.hoistTempVariables) {
flattenContext.context.hoistVariableDeclaration(temp);
}
@ -410,11 +410,11 @@ namespace ts {
continue;
}
else if (!getRestIndicatorOfBindingOrAssignmentElement(element)) {
const rhsValue = createElementAccess(value, i);
const rhsValue = flattenContext.context.factory.createElementAccessExpression(value, i);
flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element);
}
else if (i === numElements - 1) {
const rhsValue = createArraySlice(value, i);
const rhsValue = flattenContext.context.factory.createArraySliceCall(value, i);
flattenBindingOrAssignmentElement(flattenContext, element, rhsValue, /*location*/ element);
}
}
@ -438,7 +438,7 @@ namespace ts {
*/
function createDefaultValueCheck(flattenContext: FlattenContext, value: Expression, defaultValue: Expression, location: TextRange): Expression {
value = ensureIdentifier(flattenContext, value, /*reuseIdentifierExpressions*/ true, location);
return createConditional(createTypeCheck(value, "undefined"), defaultValue, value);
return flattenContext.context.factory.createConditionalExpression(flattenContext.context.factory.createTypeCheck(value, "undefined"), /*questionToken*/ undefined, defaultValue, /*colonToken*/ undefined, value);
}
/**
@ -454,16 +454,15 @@ namespace ts {
function createDestructuringPropertyAccess(flattenContext: FlattenContext, value: Expression, propertyName: PropertyName): LeftHandSideExpression {
if (isComputedPropertyName(propertyName)) {
const argumentExpression = ensureIdentifier(flattenContext, visitNode(propertyName.expression, flattenContext.visitor), /*reuseIdentifierExpressions*/ false, /*location*/ propertyName);
return createElementAccess(value, argumentExpression);
return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression);
}
else if (isStringOrNumericLiteralLike(propertyName)) {
const argumentExpression = getSynthesizedClone(propertyName);
argumentExpression.text = argumentExpression.text;
return createElementAccess(value, argumentExpression);
const argumentExpression = factory.cloneNode(propertyName);
return flattenContext.context.factory.createElementAccessExpression(value, argumentExpression);
}
else {
const name = createIdentifier(idText(propertyName));
return createPropertyAccess(value, name);
const name = flattenContext.context.factory.createIdentifier(idText(propertyName));
return flattenContext.context.factory.createPropertyAccessExpression(value, name);
}
}
@ -483,10 +482,10 @@ namespace ts {
return value;
}
else {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const temp = flattenContext.context.factory.createTempVariable(/*recordTempVariable*/ undefined);
if (flattenContext.hoistTempVariables) {
flattenContext.context.hoistVariableDeclaration(temp);
flattenContext.emitExpression(setTextRange(createAssignment(temp, value), location));
flattenContext.emitExpression(setTextRange(flattenContext.context.factory.createAssignment(temp, value), location));
}
else {
flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined);
@ -495,86 +494,29 @@ namespace ts {
}
}
function makeArrayBindingPattern(elements: BindingOrAssignmentElement[]) {
function makeArrayBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) {
Debug.assertEachNode(elements, isArrayBindingElement);
return createArrayBindingPattern(<ArrayBindingElement[]>elements);
return factory.createArrayBindingPattern(<ArrayBindingElement[]>elements);
}
function makeArrayAssignmentPattern(elements: BindingOrAssignmentElement[]) {
return createArrayLiteral(map(elements, convertToArrayAssignmentElement));
function makeArrayAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) {
return factory.createArrayLiteralExpression(map(elements, factory.converters.convertToArrayAssignmentElement));
}
function makeObjectBindingPattern(elements: BindingOrAssignmentElement[]) {
function makeObjectBindingPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) {
Debug.assertEachNode(elements, isBindingElement);
return createObjectBindingPattern(<BindingElement[]>elements);
return factory.createObjectBindingPattern(<BindingElement[]>elements);
}
function makeObjectAssignmentPattern(elements: BindingOrAssignmentElement[]) {
return createObjectLiteral(map(elements, convertToObjectAssignmentElement));
function makeObjectAssignmentPattern(factory: NodeFactory, elements: BindingOrAssignmentElement[]) {
return factory.createObjectLiteralExpression(map(elements, factory.converters.convertToObjectAssignmentElement));
}
function makeBindingElement(name: Identifier) {
return createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name);
function makeBindingElement(factory: NodeFactory, name: Identifier) {
return factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name);
}
function makeAssignmentElement(name: Identifier) {
return name;
}
export const restHelper: UnscopedEmitHelper = {
name: "typescript:rest",
importName: "__rest",
scoped: false,
text: `
var __rest = (this && this.__rest) || function (s, e) {
var t = {};
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0)
t[p] = s[p];
if (s != null && typeof Object.getOwnPropertySymbols === "function")
for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) {
if (e.indexOf(p[i]) < 0 && Object.prototype.propertyIsEnumerable.call(s, p[i]))
t[p[i]] = s[p[i]];
}
return t;
};`
};
/** Given value: o, propName: p, pattern: { a, b, ...p } from the original statement
* `{ a, b, ...p } = o`, create `p = __rest(o, ["a", "b"]);`
*/
function createRestCall(context: TransformationContext, value: Expression, elements: readonly BindingOrAssignmentElement[], computedTempVariables: readonly Expression[], location: TextRange): Expression {
context.requestEmitHelper(restHelper);
const propertyNames: Expression[] = [];
let computedTempVariableOffset = 0;
for (let i = 0; i < elements.length - 1; i++) {
const propertyName = getPropertyNameOfBindingOrAssignmentElement(elements[i]);
if (propertyName) {
if (isComputedPropertyName(propertyName)) {
const temp = computedTempVariables[computedTempVariableOffset];
computedTempVariableOffset++;
// typeof _tmp === "symbol" ? _tmp : _tmp + ""
propertyNames.push(
createConditional(
createTypeCheck(temp, "symbol"),
temp,
createAdd(temp, createLiteral(""))
)
);
}
else {
propertyNames.push(createLiteral(propertyName));
}
}
}
return createCall(
getUnscopedHelperName("__rest"),
/*typeArguments*/ undefined,
[
value,
setTextRange(
createArrayLiteral(propertyNames),
location
)
]);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,9 +1,12 @@
/*@internal*/
namespace ts {
export function transformES2016(context: TransformationContext) {
const { hoistVariableDeclaration } = context;
const {
factory,
hoistVariableDeclaration
} = context;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -43,17 +46,17 @@ namespace ts {
const right = visitNode(node.right, visitor, isExpression);
if (isElementAccessExpression(left)) {
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration);
const expressionTemp = factory.createTempVariable(hoistVariableDeclaration);
const argumentExpressionTemp = factory.createTempVariable(hoistVariableDeclaration);
target = setTextRange(
createElementAccess(
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)
factory.createElementAccessExpression(
setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression),
setTextRange(factory.createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)
),
left
);
value = setTextRange(
createElementAccess(
factory.createElementAccessExpression(
expressionTemp,
argumentExpressionTemp
),
@ -62,16 +65,16 @@ namespace ts {
}
else if (isPropertyAccessExpression(left)) {
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
const expressionTemp = factory.createTempVariable(hoistVariableDeclaration);
target = setTextRange(
createPropertyAccess(
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
factory.createPropertyAccessExpression(
setTextRange(factory.createAssignment(expressionTemp, left.expression), left.expression),
left.name
),
left
);
value = setTextRange(
createPropertyAccess(
factory.createPropertyAccessExpression(
expressionTemp,
left.name
),
@ -84,9 +87,9 @@ namespace ts {
value = left;
}
return setTextRange(
createAssignment(
factory.createAssignment(
target,
createMathPow(value, right, /*location*/ node)
setTextRange(factory.createGlobalMethodCall("Math", "pow", [value, right]), node)
),
node
);
@ -96,7 +99,7 @@ namespace ts {
// Transforms `a ** b` into `Math.pow(a, b)`
const left = visitNode(node.left, visitor, isExpression);
const right = visitNode(node.right, visitor, isExpression);
return createMathPow(left, right, /*location*/ node);
return setTextRange(factory.createGlobalMethodCall("Math", "pow", [left, right]), node);
}
}
}

View File

@ -14,6 +14,8 @@ namespace ts {
export function transformES2017(context: TransformationContext) {
const {
factory,
getEmitHelperFactory: emitHelpers,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration
@ -56,7 +58,7 @@ namespace ts {
context.onEmitNode = onEmitNode;
context.onSubstituteNode = onSubstituteNode;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -211,44 +213,44 @@ namespace ts {
function visitVariableStatementInAsyncBody(node: VariableStatement) {
if (isVariableDeclarationListWithCollidingName(node.declarationList)) {
const expression = visitVariableDeclarationListWithCollidingNames(node.declarationList, /*hasReceiver*/ false);
return expression ? createExpressionStatement(expression) : undefined;
return expression ? factory.createExpressionStatement(expression) : undefined;
}
return visitEachChild(node, visitor, context);
}
function visitForInStatementInAsyncBody(node: ForInStatement) {
return updateForIn(
return factory.updateForInStatement(
node,
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
);
}
function visitForOfStatementInAsyncBody(node: ForOfStatement) {
return updateForOf(
return factory.updateForOfStatement(
node,
visitNode(node.awaitModifier, visitor, isToken),
isVariableDeclarationListWithCollidingName(node.initializer)
? visitVariableDeclarationListWithCollidingNames(node.initializer, /*hasReceiver*/ true)!
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
);
}
function visitForStatementInAsyncBody(node: ForStatement) {
const initializer = node.initializer!; // TODO: GH#18217
return updateFor(
return factory.updateForStatement(
node,
isVariableDeclarationListWithCollidingName(initializer)
? visitVariableDeclarationListWithCollidingNames(initializer, /*hasReceiver*/ false)
: visitNode(node.initializer, visitor, isForInitializer),
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, asyncBodyVisitor, isStatement, liftToBlock)
visitNode(node.statement, asyncBodyVisitor, isStatement, factory.liftToBlock)
);
}
@ -266,7 +268,7 @@ namespace ts {
}
return setOriginalNode(
setTextRange(
createYield(
factory.createYieldExpression(
/*asteriskToken*/ undefined,
visitNode(node.expression, visitor, isExpression)
),
@ -285,7 +287,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitMethodDeclaration(node: MethodDeclaration) {
return updateMethod(
return factory.updateMethodDeclaration(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
@ -310,7 +312,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
return updateFunctionDeclaration(
return factory.updateFunctionDeclaration(
node,
/*decorators*/ undefined,
visitNodes(node.modifiers, visitor, isModifier),
@ -334,7 +336,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitFunctionExpression(node: FunctionExpression): Expression {
return updateFunctionExpression(
return factory.updateFunctionExpression(
node,
visitNodes(node.modifiers, visitor, isModifier),
node.asteriskToken,
@ -357,7 +359,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitArrowFunction(node: ArrowFunction) {
return updateArrowFunction(
return factory.updateArrowFunction(
node,
visitNodes(node.modifiers, visitor, isModifier),
/*typeParameters*/ undefined,
@ -396,12 +398,12 @@ namespace ts {
const variables = getInitializedVariables(node);
if (variables.length === 0) {
if (hasReceiver) {
return visitNode(convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression);
return visitNode(factory.converters.convertToAssignmentElementTarget(node.declarations[0].name), visitor, isExpression);
}
return undefined;
}
return inlineExpressions(map(variables, transformInitializedVariable));
return factory.inlineExpressions(map(variables, transformInitializedVariable));
}
function hoistVariableDeclarationList(node: VariableDeclarationList) {
@ -423,8 +425,8 @@ namespace ts {
function transformInitializedVariable(node: VariableDeclaration) {
const converted = setSourceMapRange(
createAssignment(
convertToAssignmentElementTarget(node.name),
factory.createAssignment(
factory.converters.convertToAssignmentElementTarget(node.name),
node.initializer!
),
node
@ -479,11 +481,10 @@ namespace ts {
let result: ConciseBody;
if (!isArrowFunction) {
const statements: Statement[] = [];
const statementOffset = addPrologue(statements, (<Block>node.body).statements, /*ensureUseStrict*/ false, visitor);
const statementOffset = factory.copyPrologue((<Block>node.body).statements, statements, /*ensureUseStrict*/ false, visitor);
statements.push(
createReturn(
createAwaiterHelper(
context,
factory.createReturnStatement(
emitHelpers().createAwaiterHelper(
inHasLexicalThisContext(),
hasLexicalArguments,
promiseConstructor,
@ -501,13 +502,13 @@ namespace ts {
if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
if (hasEntries(capturedSuperProperties)) {
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
}
}
const block = createBlock(statements, /*multiLine*/ true);
const block = factory.createBlock(statements, /*multiLine*/ true);
setTextRange(block, node.body);
if (emitSuperHelpers && hasSuperElementAccess) {
@ -523,8 +524,7 @@ namespace ts {
result = block;
}
else {
const expression = createAwaiterHelper(
context,
const expression = emitHelpers().createAwaiterHelper(
inHasLexicalThisContext(),
hasLexicalArguments,
promiseConstructor,
@ -533,8 +533,8 @@ namespace ts {
const declarations = endLexicalEnvironment();
if (some(declarations)) {
const block = convertToFunctionBody(expression);
result = updateBlock(block, setTextRange(createNodeArray(concatenate(declarations, block.statements)), block.statements));
const block = factory.converters.convertToFunctionBlock(expression);
result = factory.updateBlock(block, setTextRange(factory.createNodeArray(concatenate(declarations, block.statements)), block.statements));
}
else {
result = expression;
@ -551,10 +551,10 @@ namespace ts {
function transformAsyncFunctionBodyWorker(body: ConciseBody, start?: number) {
if (isBlock(body)) {
return updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start));
return factory.updateBlock(body, visitNodes(body.statements, asyncBodyVisitor, isStatement, start));
}
else {
return convertToFunctionBody(visitNode(body, asyncBodyVisitor, isConciseBody));
return factory.converters.convertToFunctionBlock(visitNode(body, asyncBodyVisitor, isConciseBody));
}
}
@ -653,8 +653,8 @@ namespace ts {
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return setTextRange(
createPropertyAccess(
createFileLevelUniqueName("_super"),
factory.createPropertyAccessExpression(
factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel),
node.name),
node
);
@ -678,11 +678,11 @@ namespace ts {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
return factory.createCallExpression(
factory.createPropertyAccessExpression(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
factory.createThis(),
...node.arguments
]
);
@ -702,9 +702,9 @@ namespace ts {
function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
createFileLevelUniqueName("_superIndex"),
factory.createPropertyAccessExpression(
factory.createCallExpression(
factory.createUniqueName("_superIndex", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel),
/*typeArguments*/ undefined,
[argumentExpression]
),
@ -715,8 +715,8 @@ namespace ts {
}
else {
return setTextRange(
createCall(
createFileLevelUniqueName("_superIndex"),
factory.createCallExpression(
factory.createUniqueName("_superIndex", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel),
/*typeArguments*/ undefined,
[argumentExpression]
),
@ -727,7 +727,7 @@ namespace ts {
}
/** Creates a variable named `_super` with accessor properties for the given property names. */
export function createSuperAccessVariableStatement(resolver: EmitResolver, node: FunctionLikeDeclaration, names: UnderscoreEscapedMap<true>) {
export function createSuperAccessVariableStatement(factory: NodeFactory, resolver: EmitResolver, node: FunctionLikeDeclaration, names: UnderscoreEscapedMap<true>) {
// Create a variable declaration with a getter/setter (if binding) definition for each name:
// const _super = Object.create(null, { x: { get: () => super.x, set: (v) => super.x = v }, ... });
const hasBinding = (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) !== 0;
@ -735,18 +735,18 @@ namespace ts {
names.forEach((_, key) => {
const name = unescapeLeadingUnderscores(key);
const getterAndSetter: PropertyAssignment[] = [];
getterAndSetter.push(createPropertyAssignment(
getterAndSetter.push(factory.createPropertyAssignment(
"get",
createArrowFunction(
factory.createArrowFunction(
/* modifiers */ undefined,
/* typeParameters */ undefined,
/* parameters */ [],
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
setEmitFlags(
createPropertyAccess(
factory.createPropertyAccessExpression(
setEmitFlags(
createSuper(),
factory.createSuper(),
EmitFlags.NoSubstitution
),
name
@ -757,13 +757,13 @@ namespace ts {
));
if (hasBinding) {
getterAndSetter.push(
createPropertyAssignment(
factory.createPropertyAssignment(
"set",
createArrowFunction(
factory.createArrowFunction(
/* modifiers */ undefined,
/* typeParameters */ undefined,
/* parameters */ [
createParameter(
factory.createParameterDeclaration(
/* decorators */ undefined,
/* modifiers */ undefined,
/* dotDotDotToken */ undefined,
@ -775,112 +775,51 @@ namespace ts {
],
/* type */ undefined,
/* equalsGreaterThanToken */ undefined,
createAssignment(
factory.createAssignment(
setEmitFlags(
createPropertyAccess(
factory.createPropertyAccessExpression(
setEmitFlags(
createSuper(),
factory.createSuper(),
EmitFlags.NoSubstitution
),
name
),
EmitFlags.NoSubstitution
),
createIdentifier("v")
factory.createIdentifier("v")
)
)
)
);
}
accessors.push(
createPropertyAssignment(
factory.createPropertyAssignment(
name,
createObjectLiteral(getterAndSetter),
factory.createObjectLiteralExpression(getterAndSetter),
)
);
});
return createVariableStatement(
return factory.createVariableStatement(
/* modifiers */ undefined,
createVariableDeclarationList(
factory.createVariableDeclarationList(
[
createVariableDeclaration(
createFileLevelUniqueName("_super"),
factory.createVariableDeclaration(
factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel),
/*exclamationToken*/ undefined,
/* type */ undefined,
createCall(
createPropertyAccess(
createIdentifier("Object"),
factory.createCallExpression(
factory.createPropertyAccessExpression(
factory.createIdentifier("Object"),
"create"
),
/* typeArguments */ undefined,
[
createNull(),
createObjectLiteral(accessors, /* multiline */ true)
factory.createNull(),
factory.createObjectLiteralExpression(accessors, /* multiline */ true)
]
)
)
],
NodeFlags.Const));
}
export const awaiterHelper: UnscopedEmitHelper = {
name: "typescript:awaiter",
importName: "__awaiter",
scoped: false,
priority: 5,
text: `
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
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) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};`
};
function createAwaiterHelper(context: TransformationContext, hasLexicalThis: boolean, hasLexicalArguments: boolean, promiseConstructor: EntityName | Expression | undefined, body: Block) {
context.requestEmitHelper(awaiterHelper);
const generatorFunc = createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
body
);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
return createCall(
getUnscopedHelperName("__awaiter"),
/*typeArguments*/ undefined,
[
hasLexicalThis ? createThis() : createVoidZero(),
hasLexicalArguments ? createIdentifier("arguments") : createVoidZero(),
promiseConstructor ? createExpressionFromEntityName(promiseConstructor) : createVoidZero(),
generatorFunc
]
);
}
export const asyncSuperHelper: EmitHelper = {
name: "typescript:async-super",
scoped: true,
text: helperString`
const ${"_superIndex"} = name => super[name];`
};
export const advancedAsyncSuperHelper: EmitHelper = {
name: "typescript:advanced-async-super",
scoped: true,
text: helperString`
const ${"_superIndex"} = (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);`
};
}

View File

@ -39,6 +39,8 @@ namespace ts {
export function transformES2018(context: TransformationContext) {
const {
factory,
getEmitHelperFactory: emitHelpers,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration
@ -70,7 +72,7 @@ namespace ts {
/** A set of node IDs for generated super accessors. */
const substitutedSuperAccessors: boolean[] = [];
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function affectsSubtree(excludeFacts: HierarchyFacts, includeFacts: HierarchyFacts) {
return hierarchyFacts !== (hierarchyFacts & ~excludeFacts | includeFacts);
@ -99,7 +101,7 @@ namespace ts {
function recordTaggedTemplateString(temp: Identifier) {
taggedTemplateStringDeclarations = append(
taggedTemplateStringDeclarations,
createVariableDeclaration(temp));
factory.createVariableDeclaration(temp));
}
function transformSourceFile(node: SourceFile) {
@ -262,7 +264,7 @@ namespace ts {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
return setOriginalNode(
setTextRange(
createYield(createAwaitHelper(context, visitNode(node.expression, visitor, isExpression))),
factory.createYieldExpression(/*asteriskToken*/ undefined, emitHelpers().createAwaitHelper(visitNode(node.expression, visitor, isExpression))),
/*location*/ node
),
node
@ -274,18 +276,23 @@ namespace ts {
function visitYieldExpression(node: YieldExpression) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
if (node.asteriskToken) {
const expression = visitNode(node.expression, visitor, isExpression);
const expression = visitNode(Debug.assertDefined(node.expression), visitor, isExpression);
return setOriginalNode(
setTextRange(
createYield(
createAwaitHelper(context,
updateYield(
factory.createYieldExpression(
/*asteriskToken*/ undefined,
emitHelpers().createAwaitHelper(
factory.updateYieldExpression(
node,
node.asteriskToken,
createAsyncDelegatorHelper(
context,
createAsyncValuesHelper(context, expression, expression),
setTextRange(
emitHelpers().createAsyncDelegatorHelper(
setTextRange(
emitHelpers().createAsyncValuesHelper(expression),
expression
)
),
expression
)
)
@ -299,11 +306,12 @@ namespace ts {
return setOriginalNode(
setTextRange(
createYield(
factory.createYieldExpression(
/*asteriskToken*/ undefined,
createDownlevelAwait(
node.expression
? visitNode(node.expression, visitor, isExpression)
: createVoidZero()
: factory.createVoidZero()
)
),
node
@ -317,8 +325,8 @@ namespace ts {
function visitReturnStatement(node: ReturnStatement) {
if (enclosingFunctionFlags & FunctionFlags.Async && enclosingFunctionFlags & FunctionFlags.Generator) {
return updateReturn(node, createDownlevelAwait(
node.expression ? visitNode(node.expression, visitor, isExpression) : createVoidZero()
return factory.updateReturnStatement(node, createDownlevelAwait(
node.expression ? visitNode(node.expression, visitor, isExpression) : factory.createVoidZero()
));
}
@ -331,7 +339,7 @@ namespace ts {
if (statement.kind === SyntaxKind.ForOfStatement && (<ForOfStatement>statement).awaitModifier) {
return visitForOfStatement(<ForOfStatement>statement, node);
}
return restoreEnclosingLabel(visitNode(statement, visitor, isStatement, liftToBlock), node);
return factory.restoreEnclosingLabel(visitNode(statement, visitor, isStatement, factory.liftToBlock), node);
}
return visitEachChild(node, visitor, context);
}
@ -342,7 +350,7 @@ namespace ts {
for (const e of elements) {
if (e.kind === SyntaxKind.SpreadAssignment) {
if (chunkObject) {
objects.push(createObjectLiteral(chunkObject));
objects.push(factory.createObjectLiteralExpression(chunkObject));
chunkObject = undefined;
}
const target = e.expression;
@ -350,12 +358,12 @@ namespace ts {
}
else {
chunkObject = append(chunkObject, e.kind === SyntaxKind.PropertyAssignment
? createPropertyAssignment(e.name, visitNode(e.initializer, visitor, isExpression))
? factory.createPropertyAssignment(e.name, visitNode(e.initializer, visitor, isExpression))
: visitNode(e, visitor, isObjectLiteralElementLike));
}
}
if (chunkObject) {
objects.push(createObjectLiteral(chunkObject));
objects.push(factory.createObjectLiteralExpression(chunkObject));
}
return objects;
@ -386,17 +394,17 @@ namespace ts {
// end up with `{ a: 1, b: 2, c: 3 }`
const objects = chunkObjectLiteralElements(node.properties);
if (objects.length && objects[0].kind !== SyntaxKind.ObjectLiteralExpression) {
objects.unshift(createObjectLiteral());
objects.unshift(factory.createObjectLiteralExpression());
}
let expression: Expression = objects[0];
if (objects.length > 1) {
for (let i = 1; i < objects.length; i++) {
expression = createAssignHelper(context, [expression, objects[i]]);
expression = emitHelpers().createAssignHelper([expression, objects[i]]);
}
return expression;
}
else {
return createAssignHelper(context, objects);
return emitHelpers().createAssignHelper(objects);
}
}
return visitEachChild(node, visitor, context);
@ -419,10 +427,10 @@ namespace ts {
exportedVariableStatement = false;
const visited = visitEachChild(node, visitor, context);
const statement = concatenate(visited.statements, taggedTemplateStringDeclarations && [
createVariableStatement(/*modifiers*/ undefined,
createVariableDeclarationList(taggedTemplateStringDeclarations))
factory.createVariableStatement(/*modifiers*/ undefined,
factory.createVariableDeclarationList(taggedTemplateStringDeclarations))
]);
const result = updateSourceFileNode(visited, setTextRange(createNodeArray(statement), node.statements));
const result = factory.updateSourceFile(visited, setTextRange(factory.createNodeArray(statement), node.statements));
exitSubtree(ancestorFacts);
return result;
}
@ -454,9 +462,10 @@ namespace ts {
);
}
else if (node.operatorToken.kind === SyntaxKind.CommaToken) {
return updateBinary(
return factory.updateBinaryExpression(
node,
visitNode(node.left, visitorNoDestructuringValue, isExpression),
node.operatorToken,
visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression)
);
}
@ -467,19 +476,19 @@ namespace ts {
if (node.variableDeclaration &&
isBindingPattern(node.variableDeclaration.name) &&
node.variableDeclaration.name.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
const name = getGeneratedNameForNode(node.variableDeclaration.name);
const updatedDecl = updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*type*/ undefined, name);
const name = factory.getGeneratedNameForNode(node.variableDeclaration.name);
const updatedDecl = factory.updateVariableDeclaration(node.variableDeclaration, node.variableDeclaration.name, /*exclamationToken*/ undefined, /*type*/ undefined, name);
const visitedBindings = flattenDestructuringBinding(updatedDecl, visitor, context, FlattenLevel.ObjectRest);
let block = visitNode(node.block, visitor, isBlock);
if (some(visitedBindings)) {
block = updateBlock(block, [
createVariableStatement(/*modifiers*/ undefined, visitedBindings),
block = factory.updateBlock(block, [
factory.createVariableStatement(/*modifiers*/ undefined, visitedBindings),
...block.statements,
]);
}
return updateCatchClause(
return factory.updateCatchClause(
node,
updateVariableDeclaration(node.variableDeclaration, name, /*type*/ undefined, /*initializer*/ undefined),
factory.updateVariableDeclaration(node.variableDeclaration, name, /*exclamationToken*/ undefined, /*type*/ undefined, /*initializer*/ undefined),
block);
}
return visitEachChild(node, visitor, context);
@ -528,7 +537,7 @@ namespace ts {
}
function visitForStatement(node: ForStatement): VisitResult<Statement> {
return updateFor(
return factory.updateForStatement(
node,
visitNode(node.initializer, visitorNoDestructuringValue, isForInitializer),
visitNode(node.condition, visitor, isExpression),
@ -553,7 +562,7 @@ namespace ts {
}
const result = node.awaitModifier ?
transformForAwaitOfStatement(node, outermostLabeledStatement, ancestorFacts) :
restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement);
factory.restoreEnclosingLabel(visitEachChild(node, visitor, context), outermostLabeledStatement);
exitSubtree(ancestorFacts);
return result;
}
@ -563,8 +572,8 @@ namespace ts {
if (isVariableDeclarationList(initializerWithoutParens) || isAssignmentPattern(initializerWithoutParens)) {
let bodyLocation: TextRange | undefined;
let statementsLocation: TextRange | undefined;
const temp = createTempVariable(/*recordTempVariable*/ undefined);
const statements: Statement[] = [createForOfBindingStatement(initializerWithoutParens, temp)];
const temp = factory.createTempVariable(/*recordTempVariable*/ undefined);
const statements: Statement[] = [createForOfBindingStatement(factory, initializerWithoutParens, temp)];
if (isBlock(node.statement)) {
addRange(statements, node.statement.statements);
bodyLocation = node.statement;
@ -575,13 +584,13 @@ namespace ts {
bodyLocation = node.statement;
statementsLocation = node.statement;
}
return updateForOf(
return factory.updateForOfStatement(
node,
node.awaitModifier,
setTextRange(
createVariableDeclarationList(
factory.createVariableDeclarationList(
[
setTextRange(createVariableDeclaration(temp), node.initializer)
setTextRange(factory.createVariableDeclaration(temp), node.initializer)
],
NodeFlags.Let
),
@ -589,8 +598,8 @@ namespace ts {
),
node.expression,
setTextRange(
createBlock(
setTextRange(createNodeArray(statements), statementsLocation),
factory.createBlock(
setTextRange(factory.createNodeArray(statements), statementsLocation),
/*multiLine*/ true
),
bodyLocation
@ -601,7 +610,7 @@ namespace ts {
}
function convertForOfStatementHead(node: ForOfStatement, boundValue: Expression) {
const binding = createForOfBindingStatement(node.initializer, boundValue);
const binding = createForOfBindingStatement(factory, node.initializer, boundValue);
let bodyLocation: TextRange | undefined;
let statementsLocation: TextRange | undefined;
@ -618,8 +627,8 @@ namespace ts {
return setEmitFlags(
setTextRange(
createBlock(
setTextRange(createNodeArray(statements), statementsLocation),
factory.createBlock(
setTextRange(factory.createNodeArray(statements), statementsLocation),
/*multiLine*/ true
),
bodyLocation
@ -630,47 +639,47 @@ namespace ts {
function createDownlevelAwait(expression: Expression) {
return enclosingFunctionFlags & FunctionFlags.Generator
? createYield(/*asteriskToken*/ undefined, createAwaitHelper(context, expression))
: createAwait(expression);
? factory.createYieldExpression(/*asteriskToken*/ undefined, emitHelpers().createAwaitHelper(expression))
: factory.createAwaitExpression(expression);
}
function transformForAwaitOfStatement(node: ForOfStatement, outermostLabeledStatement: LabeledStatement | undefined, ancestorFacts: HierarchyFacts) {
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 callValues = createAsyncValuesHelper(context, expression, /*location*/ node.expression);
const callNext = createCall(createPropertyAccess(iterator, "next"), /*typeArguments*/ undefined, []);
const getDone = createPropertyAccess(result, "done");
const getValue = createPropertyAccess(result, "value");
const callReturn = createFunctionCall(returnMethod, iterator, []);
const iterator = isIdentifier(expression) ? factory.getGeneratedNameForNode(expression) : factory.createTempVariable(/*recordTempVariable*/ undefined);
const result = isIdentifier(expression) ? factory.getGeneratedNameForNode(iterator) : factory.createTempVariable(/*recordTempVariable*/ undefined);
const errorRecord = factory.createUniqueName("e");
const catchVariable = factory.getGeneratedNameForNode(errorRecord);
const returnMethod = factory.createTempVariable(/*recordTempVariable*/ undefined);
const callValues = setTextRange(emitHelpers().createAsyncValuesHelper(expression), node.expression);
const callNext = factory.createCallExpression(factory.createPropertyAccessExpression(iterator, "next"), /*typeArguments*/ undefined, []);
const getDone = factory.createPropertyAccessExpression(result, "done");
const getValue = factory.createPropertyAccessExpression(result, "value");
const callReturn = factory.createFunctionCallCall(returnMethod, iterator, []);
hoistVariableDeclaration(errorRecord);
hoistVariableDeclaration(returnMethod);
// if we are enclosed in an outer loop ensure we reset 'errorRecord' per each iteration
const initializer = ancestorFacts & HierarchyFacts.IterationContainer ?
inlineExpressions([createAssignment(errorRecord, createVoidZero()), callValues]) :
factory.inlineExpressions([factory.createAssignment(errorRecord, factory.createVoidZero()), callValues]) :
callValues;
const forStatement = setEmitFlags(
setTextRange(
createFor(
factory.createForStatement(
/*initializer*/ setEmitFlags(
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(iterator, /*type*/ undefined, initializer), node.expression),
createVariableDeclaration(result)
factory.createVariableDeclarationList([
setTextRange(factory.createVariableDeclaration(iterator, /*exclamationToken*/ undefined, /*type*/ undefined, initializer), node.expression),
factory.createVariableDeclaration(result)
]),
node.expression
),
EmitFlags.NoHoisting
),
/*condition*/ createComma(
createAssignment(result, createDownlevelAwait(callNext)),
createLogicalNot(getDone)
/*condition*/ factory.createComma(
factory.createAssignment(result, createDownlevelAwait(callNext)),
factory.createLogicalNot(getDone)
),
/*incrementor*/ undefined,
/*statement*/ convertForOfStatementHead(node, getValue)
@ -680,22 +689,22 @@ namespace ts {
EmitFlags.NoTokenTrailingSourceMaps
);
return createTry(
createBlock([
restoreEnclosingLabel(
return factory.createTryStatement(
factory.createBlock([
factory.restoreEnclosingLabel(
forStatement,
outermostLabeledStatement
)
]),
createCatchClause(
createVariableDeclaration(catchVariable),
factory.createCatchClause(
factory.createVariableDeclaration(catchVariable),
setEmitFlags(
createBlock([
createExpressionStatement(
createAssignment(
factory.createBlock([
factory.createExpressionStatement(
factory.createAssignment(
errorRecord,
createObjectLiteral([
createPropertyAssignment("error", catchVariable)
factory.createObjectLiteralExpression([
factory.createPropertyAssignment("error", catchVariable)
])
)
)
@ -703,34 +712,34 @@ namespace ts {
EmitFlags.SingleLine
)
),
createBlock([
createTry(
/*tryBlock*/ createBlock([
factory.createBlock([
factory.createTryStatement(
/*tryBlock*/ factory.createBlock([
setEmitFlags(
createIf(
createLogicalAnd(
createLogicalAnd(
factory.createIfStatement(
factory.createLogicalAnd(
factory.createLogicalAnd(
result,
createLogicalNot(getDone)
factory.createLogicalNot(getDone)
),
createAssignment(
factory.createAssignment(
returnMethod,
createPropertyAccess(iterator, "return")
factory.createPropertyAccessExpression(iterator, "return")
)
),
createExpressionStatement(createDownlevelAwait(callReturn))
factory.createExpressionStatement(createDownlevelAwait(callReturn))
),
EmitFlags.SingleLine
)
]),
/*catchClause*/ undefined,
/*finallyBlock*/ setEmitFlags(
createBlock([
factory.createBlock([
setEmitFlags(
createIf(
factory.createIfStatement(
errorRecord,
createThrow(
createPropertyAccess(errorRecord, "error")
factory.createThrowStatement(
factory.createPropertyAccessExpression(errorRecord, "error")
)
),
EmitFlags.SingleLine
@ -747,12 +756,12 @@ namespace ts {
if (node.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
// Binding patterns are converted into a generated name and are
// evaluated inside the function body.
return updateParameter(
return factory.updateParameterDeclaration(
node,
/*decorators*/ undefined,
/*modifiers*/ undefined,
node.dotDotDotToken,
getGeneratedNameForNode(node),
factory.getGeneratedNameForNode(node),
/*questionToken*/ undefined,
/*type*/ undefined,
visitNode(node.initializer, visitor, isExpression)
@ -764,7 +773,7 @@ namespace ts {
function visitConstructorDeclaration(node: ConstructorDeclaration) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateConstructor(
const updated = factory.updateConstructorDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
@ -778,7 +787,7 @@ namespace ts {
function visitGetAccessorDeclaration(node: GetAccessorDeclaration) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateGetAccessor(
const updated = factory.updateGetAccessorDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
@ -794,7 +803,7 @@ namespace ts {
function visitSetAccessorDeclaration(node: SetAccessorDeclaration) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = FunctionFlags.Normal;
const updated = updateSetAccessor(
const updated = factory.updateSetAccessorDeclaration(
node,
/*decorators*/ undefined,
node.modifiers,
@ -809,7 +818,7 @@ namespace ts {
function visitMethodDeclaration(node: MethodDeclaration) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateMethod(
const updated = factory.updateMethodDeclaration(
node,
/*decorators*/ undefined,
enclosingFunctionFlags & FunctionFlags.Generator
@ -834,7 +843,7 @@ namespace ts {
function visitFunctionDeclaration(node: FunctionDeclaration) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateFunctionDeclaration(
const updated = factory.updateFunctionDeclaration(
node,
/*decorators*/ undefined,
enclosingFunctionFlags & FunctionFlags.Generator
@ -858,7 +867,7 @@ namespace ts {
function visitArrowFunction(node: ArrowFunction) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateArrowFunction(
const updated = factory.updateArrowFunction(
node,
node.modifiers,
/*typeParameters*/ undefined,
@ -874,7 +883,7 @@ namespace ts {
function visitFunctionExpression(node: FunctionExpression) {
const savedEnclosingFunctionFlags = enclosingFunctionFlags;
enclosingFunctionFlags = getFunctionFlags(node);
const updated = updateFunctionExpression(
const updated = factory.updateFunctionExpression(
node,
enclosingFunctionFlags & FunctionFlags.Generator
? visitNodes(node.modifiers, visitorNoAsyncModifier, isModifier)
@ -897,7 +906,7 @@ namespace ts {
function transformAsyncGeneratorFunctionBody(node: MethodDeclaration | AccessorDeclaration | FunctionDeclaration | FunctionExpression): FunctionBody {
resumeLexicalEnvironment();
const statements: Statement[] = [];
const statementOffset = addPrologue(statements, node.body!.statements, /*ensureUseStrict*/ false, visitor);
const statementOffset = factory.copyPrologue(node.body!.statements, statements, /*ensureUseStrict*/ false, visitor);
appendObjectRestAssignmentsIfNeeded(statements, node);
const savedCapturedSuperProperties = capturedSuperProperties;
@ -905,17 +914,16 @@ namespace ts {
capturedSuperProperties = createUnderscoreEscapedMap<true>();
hasSuperElementAccess = false;
const returnStatement = createReturn(
createAsyncGeneratorHelper(
context,
createFunctionExpression(
const returnStatement = factory.createReturnStatement(
emitHelpers().createAsyncGeneratorHelper(
factory.createFunctionExpression(
/*modifiers*/ undefined,
createToken(SyntaxKind.AsteriskToken),
node.name && getGeneratedNameForNode(node.name),
factory.createToken(SyntaxKind.AsteriskToken),
node.name && factory.getGeneratedNameForNode(node.name),
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
updateBlock(
factory.updateBlock(
node.body!,
visitLexicalEnvironment(node.body!.statements, visitor, context, statementOffset)
)
@ -930,7 +938,7 @@ namespace ts {
if (emitSuperHelpers) {
enableSubstitutionForAsyncMethodsWithSuper();
const variableStatement = createSuperAccessVariableStatement(resolver, node, capturedSuperProperties);
const variableStatement = createSuperAccessVariableStatement(factory, resolver, node, capturedSuperProperties);
substitutedSuperAccessors[getNodeId(variableStatement)] = true;
insertStatementsAfterStandardPrologue(statements, [variableStatement]);
}
@ -938,7 +946,7 @@ namespace ts {
statements.push(returnStatement);
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
const block = updateBlock(node.body!, statements);
const block = factory.updateBlock(node.body!, statements);
if (emitSuperHelpers && hasSuperElementAccess) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.AsyncMethodWithSuperBinding) {
@ -961,17 +969,17 @@ namespace ts {
resumeLexicalEnvironment();
let statementOffset = 0;
const statements: Statement[] = [];
const body = visitNode(node.body, visitor, isConciseBody);
const body = visitNode(node.body, visitor, isConciseBody) ?? factory.createBlock([]);
if (isBlock(body)) {
statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor);
statementOffset = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor);
}
addRange(statements, appendObjectRestAssignmentsIfNeeded(/*statements*/ undefined, node));
const leadingStatements = endLexicalEnvironment();
if (statementOffset > 0 || some(statements) || some(leadingStatements)) {
const block = convertToFunctionBody(body, /*multiLine*/ true);
const block = factory.converters.convertToFunctionBlock(body, /*multiLine*/ true);
insertStatementsAfterStandardPrologue(statements, leadingStatements);
addRange(statements, block.statements.slice(statementOffset));
return updateBlock(block, setTextRange(createNodeArray(statements), block.statements));
return factory.updateBlock(block, setTextRange(factory.createNodeArray(statements), block.statements));
}
return body;
}
@ -979,7 +987,7 @@ namespace ts {
function appendObjectRestAssignmentsIfNeeded(statements: Statement[] | undefined, node: FunctionLikeDeclaration): Statement[] | undefined {
for (const parameter of node.parameters) {
if (parameter.transformFlags & TransformFlags.ContainsObjectRestOrSpread) {
const temp = getGeneratedNameForNode(parameter);
const temp = factory.getGeneratedNameForNode(parameter);
const declarations = flattenDestructuringBinding(
parameter,
visitor,
@ -990,9 +998,9 @@ namespace ts {
/*skipInitializer*/ true,
);
if (some(declarations)) {
const statement = createVariableStatement(
const statement = factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
factory.createVariableDeclarationList(
declarations
)
);
@ -1086,8 +1094,8 @@ namespace ts {
function substitutePropertyAccessExpression(node: PropertyAccessExpression) {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return setTextRange(
createPropertyAccess(
createFileLevelUniqueName("_super"),
factory.createPropertyAccessExpression(
factory.createUniqueName("_super", GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel),
node.name),
node
);
@ -1111,11 +1119,11 @@ namespace ts {
const argumentExpression = isPropertyAccessExpression(expression)
? substitutePropertyAccessExpression(expression)
: substituteElementAccessExpression(expression);
return createCall(
createPropertyAccess(argumentExpression, "call"),
return factory.createCallExpression(
factory.createPropertyAccessExpression(argumentExpression, "call"),
/*typeArguments*/ undefined,
[
createThis(),
factory.createThis(),
...node.arguments
]
);
@ -1135,9 +1143,9 @@ namespace ts {
function createSuperElementAccessInAsyncMethod(argumentExpression: Expression, location: TextRange): LeftHandSideExpression {
if (enclosingSuperContainerFlags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return setTextRange(
createPropertyAccess(
createCall(
createIdentifier("_superIndex"),
factory.createPropertyAccessExpression(
factory.createCallExpression(
factory.createIdentifier("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
@ -1148,8 +1156,8 @@ namespace ts {
}
else {
return setTextRange(
createCall(
createIdentifier("_superIndex"),
factory.createCallExpression(
factory.createIdentifier("_superIndex"),
/*typeArguments*/ undefined,
[argumentExpression]
),
@ -1158,135 +1166,4 @@ namespace ts {
}
}
}
export const assignHelper: UnscopedEmitHelper = {
name: "typescript:assign",
importName: "__assign",
scoped: false,
priority: 1,
text: `
var __assign = (this && this.__assign) || function () {
__assign = Object.assign || function(t) {
for (var s, i = 1, n = arguments.length; i < n; i++) {
s = arguments[i];
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
t[p] = s[p];
}
return t;
};
return __assign.apply(this, arguments);
};`
};
export function createAssignHelper(context: TransformationContext, attributesSegments: Expression[]) {
if (context.getCompilerOptions().target! >= ScriptTarget.ES2015) {
return createCall(createPropertyAccess(createIdentifier("Object"), "assign"), /*typeArguments*/ undefined, attributesSegments);
}
context.requestEmitHelper(assignHelper);
return createCall(
getUnscopedHelperName("__assign"),
/*typeArguments*/ undefined,
attributesSegments
);
}
export const awaitHelper: UnscopedEmitHelper = {
name: "typescript:await",
importName: "__await",
scoped: false,
text: `
var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); }`
};
function createAwaitHelper(context: TransformationContext, expression: Expression) {
context.requestEmitHelper(awaitHelper);
return createCall(getUnscopedHelperName("__await"), /*typeArguments*/ undefined, [expression]);
}
export const asyncGeneratorHelper: UnscopedEmitHelper = {
name: "typescript:asyncGenerator",
importName: "__asyncGenerator",
scoped: false,
dependencies: [awaitHelper],
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 || []), i, q = [];
return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i;
function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; }
function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } }
function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); }
function fulfill(value) { resume("next", value); }
function reject(value) { resume("throw", value); }
function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
};`
};
function createAsyncGeneratorHelper(context: TransformationContext, generatorFunc: FunctionExpression, hasLexicalThis: boolean) {
context.requestEmitHelper(asyncGeneratorHelper);
// Mark this node as originally an async function
(generatorFunc.emitNode || (generatorFunc.emitNode = {} as EmitNode)).flags |= EmitFlags.AsyncFunctionBody | EmitFlags.ReuseTempVariableScope;
return createCall(
getUnscopedHelperName("__asyncGenerator"),
/*typeArguments*/ undefined,
[
hasLexicalThis ? createThis() : createVoidZero(),
createIdentifier("arguments"),
generatorFunc
]
);
}
export const asyncDelegator: UnscopedEmitHelper = {
name: "typescript:asyncDelegator",
importName: "__asyncDelegator",
scoped: false,
dependencies: [awaitHelper],
text: `
var __asyncDelegator = (this && this.__asyncDelegator) || function (o) {
var i, p;
return i = {}, verb("next"), verb("throw", function (e) { throw e; }), verb("return"), i[Symbol.iterator] = function () { return this; }, i;
function verb(n, f) { i[n] = o[n] ? function (v) { return (p = !p) ? { value: __await(o[n](v)), done: n === "return" } : f ? f(v) : v; } : f; }
};`
};
function createAsyncDelegatorHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
context.requestEmitHelper(asyncDelegator);
return setTextRange(
createCall(
getUnscopedHelperName("__asyncDelegator"),
/*typeArguments*/ undefined,
[expression]
),
location
);
}
export const asyncValues: UnscopedEmitHelper = {
name: "typescript:asyncValues",
importName: "__asyncValues",
scoped: false,
text: `
var __asyncValues = (this && this.__asyncValues) || function (o) {
if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined.");
var m = o[Symbol.asyncIterator], i;
return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i);
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
};`
};
function createAsyncValuesHelper(context: TransformationContext, expression: Expression, location?: TextRange) {
context.requestEmitHelper(asyncValues);
return setTextRange(
createCall(
getUnscopedHelperName("__asyncValues"),
/*typeArguments*/ undefined,
[expression]
),
location
);
}
}

View File

@ -1,7 +1,8 @@
/*@internal*/
namespace ts {
export function transformES2019(context: TransformationContext) {
return chainBundle(transformSourceFile);
const factory = context.factory;
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -25,9 +26,9 @@ namespace ts {
function visitCatchClause(node: CatchClause): CatchClause {
if (!node.variableDeclaration) {
return updateCatchClause(
return factory.updateCatchClause(
node,
createVariableDeclaration(createTempVariable(/*recordTempVariable*/ undefined)),
factory.createVariableDeclaration(factory.createTempVariable(/*recordTempVariable*/ undefined)),
visitNode(node.block, visitor, isBlock)
);
}

View File

@ -2,10 +2,11 @@
namespace ts {
export function transformES2020(context: TransformationContext) {
const {
factory,
hoistVariableDeclaration,
} = context;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -57,9 +58,9 @@ namespace ts {
if (isSyntheticReference(expression)) {
// `(a.b)` -> { expression `((_a = a).b)`, thisArg: `_a` }
// `(a[b])` -> { expression `((_a = a)[b])`, thisArg: `_a` }
return createSyntheticReferenceExpression(updateParen(node, expression.expression), expression.thisArg);
return factory.createSyntheticReferenceExpression(factory.updateParenthesizedExpression(node, expression.expression), expression.thisArg);
}
return updateParen(node, expression);
return factory.updateParenthesizedExpression(node, expression);
}
function visitNonOptionalPropertyOrElementAccessExpression(node: AccessExpression, captureThisArg: boolean, isDelete: boolean): Expression {
@ -74,8 +75,8 @@ namespace ts {
let thisArg: Expression | undefined;
if (captureThisArg) {
if (!isSimpleCopiableExpression(expression)) {
thisArg = createTempVariable(hoistVariableDeclaration);
expression = createAssignment(thisArg, expression);
thisArg = factory.createTempVariable(hoistVariableDeclaration);
expression = factory.createAssignment(thisArg, expression);
// if (inParameterInitializer) tempVariableInParameter = true;
}
else {
@ -84,9 +85,9 @@ namespace ts {
}
expression = node.kind === SyntaxKind.PropertyAccessExpression
? updatePropertyAccess(node, expression, visitNode(node.name, visitor, isIdentifier))
: updateElementAccess(node, expression, visitNode(node.argumentExpression, visitor, isExpression));
return thisArg ? createSyntheticReferenceExpression(expression, thisArg) : expression;
? factory.updatePropertyAccessExpression(node, expression, visitNode(node.name, visitor, isIdentifier))
: factory.updateElementAccessExpression(node, expression, visitNode(node.argumentExpression, visitor, isExpression));
return thisArg ? factory.createSyntheticReferenceExpression(expression, thisArg) : expression;
}
function visitNonOptionalCallExpression(node: CallExpression, captureThisArg: boolean): Expression {
@ -114,8 +115,8 @@ namespace ts {
let leftExpression = isSyntheticReference(left) ? left.expression : left;
let capturedLeft: Expression = leftExpression;
if (!isSimpleCopiableExpression(leftExpression)) {
capturedLeft = createTempVariable(hoistVariableDeclaration);
leftExpression = createAssignment(capturedLeft, leftExpression);
capturedLeft = factory.createTempVariable(hoistVariableDeclaration);
leftExpression = factory.createAssignment(capturedLeft, leftExpression);
// if (inParameterInitializer) tempVariableInParameter = true;
}
let rightExpression = capturedLeft;
@ -127,8 +128,8 @@ namespace ts {
case SyntaxKind.ElementAccessExpression:
if (i === chain.length - 1 && captureThisArg) {
if (!isSimpleCopiableExpression(rightExpression)) {
thisArg = createTempVariable(hoistVariableDeclaration);
rightExpression = createAssignment(thisArg, rightExpression);
thisArg = factory.createTempVariable(hoistVariableDeclaration);
rightExpression = factory.createAssignment(thisArg, rightExpression);
// if (inParameterInitializer) tempVariableInParameter = true;
}
else {
@ -136,19 +137,19 @@ namespace ts {
}
}
rightExpression = segment.kind === SyntaxKind.PropertyAccessExpression
? createPropertyAccess(rightExpression, visitNode(segment.name, visitor, isIdentifier))
: createElementAccess(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression));
? factory.createPropertyAccessExpression(rightExpression, visitNode(segment.name, visitor, isIdentifier))
: factory.createElementAccessExpression(rightExpression, visitNode(segment.argumentExpression, visitor, isExpression));
break;
case SyntaxKind.CallExpression:
if (i === 0 && leftThisArg) {
rightExpression = createFunctionCall(
rightExpression = factory.createFunctionCallCall(
rightExpression,
leftThisArg.kind === SyntaxKind.SuperKeyword ? createThis() : leftThisArg,
leftThisArg.kind === SyntaxKind.SuperKeyword ? factory.createThis() : leftThisArg,
visitNodes(segment.arguments, visitor, isExpression)
);
}
else {
rightExpression = createCall(
rightExpression = factory.createCallExpression(
rightExpression,
/*typeArguments*/ undefined,
visitNodes(segment.arguments, visitor, isExpression)
@ -160,23 +161,23 @@ namespace ts {
}
const target = isDelete
? createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createTrue(), createDelete(rightExpression))
: createConditional(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), createVoidZero(), rightExpression);
return thisArg ? createSyntheticReferenceExpression(target, thisArg) : target;
? factory.createConditionalExpression(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createTrue(), /*colonToken*/ undefined, factory.createDeleteExpression(rightExpression))
: factory.createConditionalExpression(createNotNullCondition(leftExpression, capturedLeft, /*invert*/ true), /*questionToken*/ undefined, factory.createVoidZero(), /*colonToken*/ undefined, rightExpression);
return thisArg ? factory.createSyntheticReferenceExpression(target, thisArg) : target;
}
function createNotNullCondition(left: Expression, right: Expression, invert?: boolean) {
return createBinary(
createBinary(
return factory.createBinaryExpression(
factory.createBinaryExpression(
left,
createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken),
createNull()
factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken),
factory.createNull()
),
createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken),
createBinary(
factory.createToken(invert ? SyntaxKind.BarBarToken : SyntaxKind.AmpersandAmpersandToken),
factory.createBinaryExpression(
right,
createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken),
createVoidZero()
factory.createToken(invert ? SyntaxKind.EqualsEqualsEqualsToken : SyntaxKind.ExclamationEqualsEqualsToken),
factory.createVoidZero()
)
);
}
@ -185,13 +186,15 @@ namespace ts {
let left = visitNode(node.left, visitor, isExpression);
let right = left;
if (!isSimpleCopiableExpression(left)) {
right = createTempVariable(hoistVariableDeclaration);
left = createAssignment(right, left);
right = factory.createTempVariable(hoistVariableDeclaration);
left = factory.createAssignment(right, left);
// if (inParameterInitializer) tempVariableInParameter = true;
}
return createConditional(
return factory.createConditionalExpression(
createNotNullCondition(left, right),
/*questionToken*/ undefined,
right,
/*colonToken*/ undefined,
visitNode(node.right, visitor, isExpression),
);
}
@ -199,7 +202,7 @@ namespace ts {
function visitDeleteExpression(node: DeleteExpression) {
return isOptionalChain(skipParentheses(node.expression))
? setOriginalNode(visitNonOptionalExpression(node.expression, /*captureThisArg*/ false, /*isDelete*/ true), node)
: updateDelete(node, visitNode(node.expression, visitor, isExpression));
: factory.updateDeleteExpression(node, visitNode(node.expression, visitor, isExpression));
}
}
}

View File

@ -6,6 +6,7 @@ namespace ts {
* @param context Context and state information for the transformation.
*/
export function transformES5(context: TransformationContext) {
const { factory } = context;
const compilerOptions = context.getCompilerOptions();
// enable emit notification only if using --jsx preserve or react-native
@ -24,7 +25,7 @@ namespace ts {
context.onSubstituteNode = onSubstituteNode;
context.enableSubstitution(SyntaxKind.PropertyAccessExpression);
context.enableSubstitution(SyntaxKind.PropertyAssignment);
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
/**
* Transforms an ES5 source file to ES3.
@ -87,7 +88,7 @@ namespace ts {
}
const literalName = trySubstituteReservedName(node.name);
if (literalName) {
return setTextRange(createElementAccess(node.expression, literalName), node);
return setTextRange(factory.createElementAccessExpression(node.expression, literalName), node);
}
return node;
}
@ -100,7 +101,7 @@ namespace ts {
function substitutePropertyAssignment(node: PropertyAssignment): PropertyAssignment {
const literalName = isIdentifier(node.name) && trySubstituteReservedName(node.name);
if (literalName) {
return updatePropertyAssignment(node, literalName, node.initializer);
return factory.updatePropertyAssignment(node, literalName, node.initializer);
}
return node;
}
@ -113,7 +114,7 @@ namespace ts {
function trySubstituteReservedName(name: Identifier) {
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(idText(name)) : undefined);
if (token !== undefined && token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
return setTextRange(createLiteral(name), name);
return setTextRange(factory.createStringLiteralFromNode(name), name);
}
return undefined;
}

View File

@ -2,9 +2,10 @@
namespace ts {
export function transformESNext(context: TransformationContext) {
const {
hoistVariableDeclaration
hoistVariableDeclaration,
factory
} = context;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -37,14 +38,14 @@ namespace ts {
let assignmentTarget = left;
const right = skipParentheses(visitNode(binaryExpression.right, visitor, isExpression));
if (isAccessExpression(left)) {
const tempVariable = createTempVariable(hoistVariableDeclaration);
const tempVariable = factory.createTempVariable(hoistVariableDeclaration);
if (isPropertyAccessExpression(left)) {
assignmentTarget = createPropertyAccess(
assignmentTarget = factory.createPropertyAccessExpression(
tempVariable,
left.name
);
left = createPropertyAccess(
createAssignment(
left = factory.createPropertyAccessExpression(
factory.createAssignment(
tempVariable,
left.expression
),
@ -52,12 +53,12 @@ namespace ts {
);
}
else {
assignmentTarget = createElementAccess(
assignmentTarget = factory.createElementAccessExpression(
tempVariable,
left.argumentExpression
);
left = createElementAccess(
createAssignment(
left = factory.createElementAccessExpression(
factory.createAssignment(
tempVariable,
left.expression
),
@ -66,11 +67,11 @@ namespace ts {
}
}
return createBinary(
return factory.createBinaryExpression(
left,
nonAssignmentOperator,
createParen(
createAssignment(
factory.createParenthesizedExpression(
factory.createAssignment(
assignmentTarget,
right
)

View File

@ -230,6 +230,8 @@ namespace ts {
export function transformGenerators(context: TransformationContext) {
const {
factory,
getEmitHelperFactory: emitHelpers,
resumeLexicalEnvironment,
endLexicalEnvironment,
hoistFunctionDeclaration,
@ -263,7 +265,7 @@ namespace ts {
// allocating objects to store the same information to avoid GC overhead.
//
let labelOffsets: number[] | undefined; // The operation offset at which the label is defined.
let labelExpressions: LiteralExpression[][] | undefined; // The NumericLiteral nodes bound to each label.
let labelExpressions: Mutable<LiteralExpression>[][] | undefined; // The NumericLiteral nodes bound to each label.
let nextLabelId = 1; // The next label id to use.
// Operations store information about generated code for the function body. This
@ -290,7 +292,7 @@ namespace ts {
let currentExceptionBlock: ExceptionBlock | undefined; // The current exception block.
let withBlockStack: WithBlock[] | undefined; // A stack containing `with` blocks.
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile || (node.transformFlags & TransformFlags.ContainsGenerator) === 0) {
@ -446,7 +448,7 @@ namespace ts {
if (node.asteriskToken) {
node = setOriginalNode(
setTextRange(
createFunctionDeclaration(
factory.createFunctionDeclaration(
/*decorators*/ undefined,
node.modifiers,
/*asteriskToken*/ undefined,
@ -496,7 +498,7 @@ namespace ts {
if (node.asteriskToken) {
node = setOriginalNode(
setTextRange(
createFunctionExpression(
factory.createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
node.name,
@ -577,18 +579,18 @@ namespace ts {
operations = undefined;
operationArguments = undefined;
operationLocations = undefined;
state = createTempVariable(/*recordTempVariable*/ undefined);
state = factory.createTempVariable(/*recordTempVariable*/ undefined);
// Build the generator
resumeLexicalEnvironment();
const statementOffset = addPrologue(statements, body.statements, /*ensureUseStrict*/ false, visitor);
const statementOffset = factory.copyPrologue(body.statements, statements, /*ensureUseStrict*/ false, visitor);
transformAndEmitStatements(body.statements, statementOffset);
const buildResult = build();
insertStatementsAfterStandardPrologue(statements, endLexicalEnvironment());
statements.push(createReturn(buildResult));
statements.push(factory.createReturnStatement(buildResult));
// Restore previous generator state
inGeneratorFunctionBody = savedInGeneratorFunctionBody;
@ -605,7 +607,7 @@ namespace ts {
operationLocations = savedOperationLocations;
state = savedState;
return setTextRange(createBlock(statements, body.multiLine), body);
return setTextRange(factory.createBlock(statements, body.multiLine), body);
}
/**
@ -637,8 +639,8 @@ namespace ts {
}
return setSourceMapRange(
createExpressionStatement(
inlineExpressions(
factory.createExpressionStatement(
factory.inlineExpressions(
map(variables, transformInitializedVariable)
)
),
@ -688,7 +690,7 @@ namespace ts {
// .mark resumeLabel
// _a.b = %sent%;
target = updatePropertyAccess(
target = factory.updatePropertyAccessExpression(
<PropertyAccessExpression>left,
cacheExpression(visitNode((<PropertyAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
(<PropertyAccessExpression>left).name
@ -707,7 +709,7 @@ namespace ts {
// .mark resumeLabel
// _a[_b] = %sent%;
target = updateElementAccess(<ElementAccessExpression>left,
target = factory.updateElementAccessExpression(<ElementAccessExpression>left,
cacheExpression(visitNode((<ElementAccessExpression>left).expression, visitor, isLeftHandSideExpression)),
cacheExpression(visitNode((<ElementAccessExpression>left).argumentExpression, visitor, isExpression))
);
@ -721,10 +723,10 @@ namespace ts {
const operator = node.operatorToken.kind;
if (isCompoundAssignment(operator)) {
return setTextRange(
createAssignment(
factory.createAssignment(
target,
setTextRange(
createBinary(
factory.createBinaryExpression(
cacheExpression(target),
getNonAssignmentOperatorForCompoundAssignment(operator),
visitNode(right, visitor, isExpression)
@ -736,7 +738,7 @@ namespace ts {
);
}
else {
return updateBinary(node, target, visitNode(right, visitor, isExpression));
return factory.updateBinaryExpression(node, target, node.operatorToken, visitNode(right, visitor, isExpression));
}
}
@ -761,10 +763,10 @@ namespace ts {
// .yield resumeLabel
// _a + %sent% + c()
const clone = getMutableClone(node);
clone.left = cacheExpression(visitNode(node.left, visitor, isExpression));
clone.right = visitNode(node.right, visitor, isExpression);
return clone;
return factory.updateBinaryExpression(node,
cacheExpression(visitNode(node.left, visitor, isExpression)),
node.operatorToken,
visitNode(node.right, visitor, isExpression));
}
return visitEachChild(node, visitor, context);
@ -841,7 +843,7 @@ namespace ts {
let pendingExpressions: Expression[] = [];
visit(node.left);
visit(node.right);
return inlineExpressions(pendingExpressions);
return factory.inlineExpressions(pendingExpressions);
function visit(node: Expression) {
if (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.CommaToken) {
@ -850,7 +852,7 @@ namespace ts {
}
else {
if (containsYield(node) && pendingExpressions.length > 0) {
emitWorker(OpCode.Statement, [createExpressionStatement(inlineExpressions(pendingExpressions))]);
emitWorker(OpCode.Statement, [factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions))]);
pendingExpressions = [];
}
@ -916,8 +918,9 @@ namespace ts {
const resumeLabel = defineLabel();
const expression = visitNode(node.expression, visitor, isExpression);
if (node.asteriskToken) {
// NOTE: `expression` must be defined for `yield*`.
const iterator = (getEmitFlags(node.expression!) & EmitFlags.Iterator) === 0
? createValuesHelper(context, expression, /*location*/ node)
? setTextRange(emitHelpers().createValuesHelper(expression!), node)
: expression;
emitYieldStar(iterator, /*location*/ node);
}
@ -963,7 +966,7 @@ namespace ts {
temp = declareLocal();
const initialElements = visitNodes(elements, visitor, isExpression, 0, numInitialElements);
emitAssignment(temp,
createArrayLiteral(
factory.createArrayLiteralExpression(
leadingElement
? [leadingElement, ...initialElements]
: initialElements
@ -974,9 +977,9 @@ namespace ts {
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
return temp
? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)])
? factory.createArrayConcatCall(temp, [factory.createArrayLiteralExpression(expressions, multiLine)])
: setTextRange(
createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine),
factory.createArrayLiteralExpression(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine),
location
);
@ -990,11 +993,11 @@ namespace ts {
emitAssignment(
temp,
hasAssignedTemp
? createArrayConcat(
? factory.createArrayConcatCall(
temp,
[createArrayLiteral(expressions, multiLine)]
[factory.createArrayLiteralExpression(expressions, multiLine)]
)
: createArrayLiteral(
: factory.createArrayLiteralExpression(
leadingElement ? [leadingElement, ...expressions] : expressions,
multiLine
)
@ -1033,23 +1036,24 @@ namespace ts {
const temp = declareLocal();
emitAssignment(temp,
createObjectLiteral(
factory.createObjectLiteralExpression(
visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties),
multiLine
)
);
const expressions = reduceLeft(properties, reduceProperty, <Expression[]>[], numInitialProperties);
expressions.push(multiLine ? startOnNewLine(getMutableClone(temp)) : temp);
return inlineExpressions(expressions);
// TODO(rbuckton): Does this need to be parented?
expressions.push(multiLine ? startOnNewLine(setParent(setTextRange(factory.cloneNode(temp), temp), temp.parent)) : temp);
return factory.inlineExpressions(expressions);
function reduceProperty(expressions: Expression[], property: ObjectLiteralElementLike) {
if (containsYield(property) && expressions.length > 0) {
emitStatement(createExpressionStatement(inlineExpressions(expressions)));
emitStatement(factory.createExpressionStatement(factory.inlineExpressions(expressions)));
expressions = [];
}
const expression = createExpressionForObjectLiteralElementLike(node, property, temp);
const expression = createExpressionForObjectLiteralElementLike(factory, node, property, temp);
const visited = visitNode(expression, visitor, isExpression);
if (visited) {
if (multiLine) {
@ -1078,10 +1082,9 @@ namespace ts {
// .mark resumeLabel
// a = _a[%sent%]
const clone = getMutableClone(node);
clone.expression = cacheExpression(visitNode(node.expression, visitor, isLeftHandSideExpression));
clone.argumentExpression = visitNode(node.argumentExpression, visitor, isExpression);
return clone;
return factory.updateElementAccessExpression(node,
cacheExpression(visitNode(node.expression, visitor, isLeftHandSideExpression)),
visitNode(node.argumentExpression, visitor, isExpression));
}
return visitEachChild(node, visitor, context);
@ -1099,13 +1102,15 @@ namespace ts {
// .yield resumeLabel
// .mark resumeLabel
// _b.apply(_a, _c.concat([%sent%, 2]));
const { target, thisArg } = createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true);
const { target, thisArg } = factory.createCallBinding(node.expression, hoistVariableDeclaration, languageVersion, /*cacheIdentifiers*/ true);
return setOriginalNode(
createFunctionApply(
cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
thisArg,
visitElements(node.arguments),
/*location*/ node
setTextRange(
factory.createFunctionApplyCall(
cacheExpression(visitNode(target, visitor, isLeftHandSideExpression)),
thisArg,
visitElements(node.arguments)
),
node
),
node
);
@ -1127,16 +1132,16 @@ namespace ts {
// .mark resumeLabel
// new (_b.apply(_a, _c.concat([%sent%, 2])));
const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration);
const { target, thisArg } = factory.createCallBinding(factory.createPropertyAccessExpression(node.expression, "bind"), hoistVariableDeclaration);
return setOriginalNode(
setTextRange(
createNew(
createFunctionApply(
factory.createNewExpression(
factory.createFunctionApplyCall(
cacheExpression(visitNode(target, visitor, isExpression)),
thisArg,
visitElements(
node.arguments!,
/*leadingElement*/ createVoidZero()
/*leadingElement*/ factory.createVoidZero()
)
),
/*typeArguments*/ undefined,
@ -1228,7 +1233,7 @@ namespace ts {
function transformAndEmitVariableDeclarationList(node: VariableDeclarationList): VariableDeclarationList | undefined {
for (const variable of node.declarations) {
const name = getSynthesizedClone(<Identifier>variable.name);
const name = factory.cloneNode(<Identifier>variable.name);
setCommentRange(name, variable.name);
hoistVariableDeclaration(name);
}
@ -1248,7 +1253,7 @@ namespace ts {
}
if (pendingExpressions.length) {
emitStatement(createExpressionStatement(inlineExpressions(pendingExpressions)));
emitStatement(factory.createExpressionStatement(factory.inlineExpressions(pendingExpressions)));
variablesWritten += pendingExpressions.length;
pendingExpressions = [];
}
@ -1257,10 +1262,10 @@ namespace ts {
return undefined;
}
function transformInitializedVariable(node: VariableDeclaration) {
function transformInitializedVariable(node: InitializedVariableDeclaration) {
return setSourceMapRange(
createAssignment(
setSourceMapRange(<Identifier>getSynthesizedClone(node.name), node.name),
factory.createAssignment(
setSourceMapRange(<Identifier>factory.cloneNode(node.name), node.name),
visitNode(node.initializer, visitor, isExpression)
),
node
@ -1419,7 +1424,7 @@ namespace ts {
else {
emitStatement(
setTextRange(
createExpressionStatement(
factory.createExpressionStatement(
visitNode(initializer, visitor, isExpression)
),
initializer
@ -1439,7 +1444,7 @@ namespace ts {
if (node.incrementor) {
emitStatement(
setTextRange(
createExpressionStatement(
factory.createExpressionStatement(
visitNode(node.incrementor, visitor, isExpression)
),
node.incrementor
@ -1466,13 +1471,13 @@ namespace ts {
}
const variables = getInitializedVariables(initializer);
node = updateFor(node,
node = factory.updateForStatement(node,
variables.length > 0
? inlineExpressions(map(variables, transformInitializedVariable))
? factory.inlineExpressions(map(variables, transformInitializedVariable))
: undefined,
visitNode(node.condition, visitor, isExpression),
visitNode(node.incrementor, visitor, isExpression),
visitNode(node.statement, visitor, isStatement, liftToBlock)
visitNode(node.statement, visitor, isStatement, factory.liftToBlock)
);
}
else {
@ -1512,18 +1517,18 @@ namespace ts {
const keysArray = declareLocal(); // _a
const key = declareLocal(); // _b
const keysIndex = createLoopVariable(); // _i
const keysIndex = factory.createLoopVariable(); // _i
const initializer = node.initializer;
hoistVariableDeclaration(keysIndex);
emitAssignment(keysArray, createArrayLiteral());
emitAssignment(keysArray, factory.createArrayLiteralExpression());
emitStatement(
createForIn(
factory.createForInStatement(
key,
visitNode(node.expression, visitor, isExpression),
createExpressionStatement(
createCall(
createPropertyAccess(keysArray, "push"),
factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(keysArray, "push"),
/*typeArguments*/ undefined,
[key]
)
@ -1531,14 +1536,14 @@ namespace ts {
)
);
emitAssignment(keysIndex, createLiteral(0));
emitAssignment(keysIndex, factory.createNumericLiteral(0));
const conditionLabel = defineLabel();
const incrementLabel = defineLabel();
const endLabel = beginLoopBlock(incrementLabel);
markLabel(conditionLabel);
emitBreakWhenFalse(endLabel, createLessThan(keysIndex, createPropertyAccess(keysArray, "length")));
emitBreakWhenFalse(endLabel, factory.createLessThan(keysIndex, factory.createPropertyAccessExpression(keysArray, "length")));
let variable: Expression;
if (isVariableDeclarationList(initializer)) {
@ -1546,18 +1551,18 @@ namespace ts {
hoistVariableDeclaration(<Identifier>variable.name);
}
variable = <Identifier>getSynthesizedClone(initializer.declarations[0].name);
variable = <Identifier>factory.cloneNode(initializer.declarations[0].name);
}
else {
variable = visitNode(initializer, visitor, isExpression);
Debug.assert(isLeftHandSideExpression(variable));
}
emitAssignment(variable, createElementAccess(keysArray, keysIndex));
emitAssignment(variable, factory.createElementAccessExpression(keysArray, keysIndex));
transformAndEmitEmbeddedStatement(node.statement);
markLabel(incrementLabel);
emitStatement(createExpressionStatement(createPostfixIncrement(keysIndex)));
emitStatement(factory.createExpressionStatement(factory.createPostfixIncrement(keysIndex)));
emitBreak(conditionLabel);
endLoopBlock();
@ -1591,10 +1596,10 @@ namespace ts {
hoistVariableDeclaration(<Identifier>variable.name);
}
node = updateForIn(node,
node = factory.updateForInStatement(node,
<Identifier>initializer.declarations[0].name,
visitNode(node.expression, visitor, isExpression),
visitNode(node.statement, visitor, isStatement, liftToBlock)
visitNode(node.statement, visitor, isStatement, factory.liftToBlock)
);
}
else {
@ -1752,7 +1757,7 @@ namespace ts {
}
pendingClauses.push(
createCaseClause(
factory.createCaseClause(
visitNode(clause.expression, visitor, isExpression),
[
createInlineBreak(clauseLabels[i], /*location*/ clause.expression)
@ -1766,7 +1771,7 @@ namespace ts {
}
if (pendingClauses.length) {
emitStatement(createSwitch(expression, createCaseBlock(pendingClauses)));
emitStatement(factory.createSwitchStatement(expression, factory.createCaseBlock(pendingClauses)));
clausesWritten += pendingClauses.length;
pendingClauses = [];
}
@ -1845,8 +1850,9 @@ namespace ts {
}
function transformAndEmitThrowStatement(node: ThrowStatement): void {
// TODO(rbuckton): `expression` should be required on `throw`.
emitThrow(
visitNode(node.expression, visitor, isExpression),
visitNode(node.expression ?? factory.createVoidZero(), visitor, isExpression),
/*location*/ node
);
}
@ -1940,7 +1946,8 @@ namespace ts {
if (declaration) {
const name = renamedCatchVariableDeclarations[getOriginalNodeId(declaration)];
if (name) {
const clone = getMutableClone(name);
// TODO(rbuckton): Does this need to be parented?
const clone = setParent(setTextRange(factory.cloneNode(name), name), name.parent);
setSourceMapRange(clone, node);
setCommentRange(clone, node);
return clone;
@ -1957,15 +1964,15 @@ namespace ts {
return <Identifier>node;
}
const temp = createTempVariable(hoistVariableDeclaration);
const temp = factory.createTempVariable(hoistVariableDeclaration);
emitAssignment(temp, node, /*location*/ node);
return temp;
}
function declareLocal(name?: string): Identifier {
const temp = name
? createUniqueName(name)
: createTempVariable(/*recordTempVariable*/ undefined);
? factory.createUniqueName(name)
: factory.createTempVariable(/*recordTempVariable*/ undefined);
hoistVariableDeclaration(temp);
return temp;
}
@ -2125,7 +2132,7 @@ namespace ts {
exception.catchVariable = name;
exception.catchLabel = catchLabel;
emitAssignment(name, createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, []));
emitAssignment(name, factory.createCallExpression(factory.createPropertyAccessExpression(state, "sent"), /*typeArguments*/ undefined, []));
emitNop();
}
@ -2392,7 +2399,7 @@ namespace ts {
labelExpressions = [];
}
const expression = createLiteral(-1);
const expression = factory.createNumericLiteral(-1);
if (labelExpressions[label] === undefined) {
labelExpressions[label] = [expression];
}
@ -2403,14 +2410,14 @@ namespace ts {
return expression;
}
return createOmittedExpression();
return factory.createOmittedExpression();
}
/**
* Creates a numeric literal for the provided instruction.
*/
function createInstruction(instruction: Instruction): NumericLiteral {
const literal = createLiteral(instruction);
const literal = factory.createNumericLiteral(instruction);
addSyntheticTrailingComment(literal, SyntaxKind.MultiLineCommentTrivia, getInstructionName(instruction));
return literal;
}
@ -2424,8 +2431,8 @@ namespace ts {
function createInlineBreak(label: Label, location?: TextRange): ReturnStatement {
Debug.assertLessThan(0, label, "Invalid label");
return setTextRange(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.Break),
createLabel(label)
])
@ -2442,8 +2449,8 @@ namespace ts {
*/
function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement {
return setTextRange(
createReturn(
createArrayLiteral(expression
factory.createReturnStatement(
factory.createArrayLiteralExpression(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
)
@ -2457,8 +2464,8 @@ namespace ts {
*/
function createGeneratorResume(location?: TextRange): LeftHandSideExpression {
return setTextRange(
createCall(
createPropertyAccess(state, "sent"),
factory.createCallExpression(
factory.createPropertyAccessExpression(state, "sent"),
/*typeArguments*/ undefined,
[]
),
@ -2619,17 +2626,16 @@ namespace ts {
withBlockStack = undefined;
const buildResult = buildStatements();
return createGeneratorHelper(
context,
return emitHelpers().createGeneratorHelper(
setEmitFlags(
createFunctionExpression(
factory.createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
[factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, state)],
/*type*/ undefined,
createBlock(
factory.createBlock(
buildResult,
/*multiLine*/ buildResult.length > 0
)
@ -2655,8 +2661,8 @@ namespace ts {
}
if (clauses) {
const labelExpression = createPropertyAccess(state, "label");
const switchStatement = createSwitch(labelExpression, createCaseBlock(clauses));
const labelExpression = factory.createPropertyAccessExpression(state, "label");
const switchStatement = factory.createSwitchStatement(labelExpression, factory.createCaseBlock(clauses));
return [startOnNewLine(switchStatement)];
}
@ -2745,7 +2751,7 @@ namespace ts {
// surround the statements in generated `with` blocks to create the same environment.
for (let i = withBlockStack.length - 1; i >= 0; i--) {
const withBlock = withBlockStack[i];
statements = [createWith(withBlock.expression, createBlock(statements))];
statements = [factory.createWithStatement(withBlock.expression, factory.createBlock(statements))];
}
}
@ -2755,12 +2761,12 @@ namespace ts {
// for each block in the protected region.
const { startLabel, catchLabel, finallyLabel, endLabel } = currentExceptionBlock;
statements.unshift(
createExpressionStatement(
createCall(
createPropertyAccess(createPropertyAccess(state, "trys"), "push"),
factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(factory.createPropertyAccessExpression(state, "trys"), "push"),
/*typeArguments*/ undefined,
[
createArrayLiteral([
factory.createArrayLiteralExpression([
createLabel(startLabel),
createLabel(catchLabel),
createLabel(finallyLabel),
@ -2778,10 +2784,10 @@ namespace ts {
// The case clause for the last label falls through to this label, so we
// add an assignment statement to reflect the change in labels.
statements.push(
createExpressionStatement(
createAssignment(
createPropertyAccess(state, "label"),
createLiteral(labelNumber + 1)
factory.createExpressionStatement(
factory.createAssignment(
factory.createPropertyAccessExpression(state, "label"),
factory.createNumericLiteral(labelNumber + 1)
)
)
);
@ -2789,8 +2795,8 @@ namespace ts {
}
clauses.push(
createCaseClause(
createLiteral(labelNumber),
factory.createCaseClause(
factory.createNumericLiteral(labelNumber),
statements || []
)
);
@ -2962,7 +2968,7 @@ namespace ts {
* @param operationLocation The source map location for the operation.
*/
function writeAssign(left: Expression, right: Expression, operationLocation: TextRange | undefined): void {
writeStatement(setTextRange(createExpressionStatement(createAssignment(left, right)), operationLocation));
writeStatement(setTextRange(factory.createExpressionStatement(factory.createAssignment(left, right)), operationLocation));
}
/**
@ -2974,7 +2980,7 @@ namespace ts {
function writeThrow(expression: Expression, operationLocation: TextRange | undefined): void {
lastOperationWasAbrupt = true;
lastOperationWasCompletion = true;
writeStatement(setTextRange(createThrow(expression), operationLocation));
writeStatement(setTextRange(factory.createThrowStatement(expression), operationLocation));
}
/**
@ -2989,8 +2995,8 @@ namespace ts {
writeStatement(
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral(expression
factory.createReturnStatement(
factory.createArrayLiteralExpression(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
)
@ -3013,8 +3019,8 @@ namespace ts {
writeStatement(
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.Break),
createLabel(label)
])
@ -3036,12 +3042,12 @@ namespace ts {
function writeBreakWhenTrue(label: Label, condition: Expression, operationLocation: TextRange | undefined): void {
writeStatement(
setEmitFlags(
createIf(
factory.createIfStatement(
condition,
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.Break),
createLabel(label)
])
@ -3066,12 +3072,12 @@ namespace ts {
function writeBreakWhenFalse(label: Label, condition: Expression, operationLocation: TextRange | undefined): void {
writeStatement(
setEmitFlags(
createIf(
createLogicalNot(condition),
factory.createIfStatement(
factory.createLogicalNot(condition),
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.Break),
createLabel(label)
])
@ -3097,8 +3103,8 @@ namespace ts {
writeStatement(
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral(
factory.createReturnStatement(
factory.createArrayLiteralExpression(
expression
? [createInstruction(Instruction.Yield), expression]
: [createInstruction(Instruction.Yield)]
@ -3122,8 +3128,8 @@ namespace ts {
writeStatement(
setEmitFlags(
setTextRange(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.YieldStar),
expression
])
@ -3141,114 +3147,12 @@ namespace ts {
function writeEndfinally(): void {
lastOperationWasAbrupt = true;
writeStatement(
createReturn(
createArrayLiteral([
factory.createReturnStatement(
factory.createArrayLiteralExpression([
createInstruction(Instruction.Endfinally)
])
)
);
}
}
function createGeneratorHelper(context: TransformationContext, body: FunctionExpression) {
context.requestEmitHelper(generatorHelper);
return createCall(
getUnscopedHelperName("__generator"),
/*typeArguments*/ undefined,
[createThis(), body]);
}
// The __generator helper is used by down-level transformations to emulate the runtime
// semantics of an ES2015 generator function. When called, this helper returns an
// object that implements the Iterator protocol, in that it has `next`, `return`, and
// `throw` methods that step through the generator when invoked.
//
// parameters:
// @param thisArg The value to use as the `this` binding for the transformed generator body.
// @param body A function that acts as the transformed generator body.
//
// variables:
// _ Persistent state for the generator that is shared between the helper and the
// generator body. The state object has the following members:
// sent() - A method that returns or throws the current completion value.
// label - The next point at which to resume evaluation of the generator body.
// trys - A stack of protected regions (try/catch/finally blocks).
// ops - A stack of pending instructions when inside of a finally block.
// f A value indicating whether the generator is executing.
// y An iterator to delegate for a yield*.
// t A temporary variable that holds one of the following values (note that these
// cases do not overlap):
// - The completion value when resuming from a `yield` or `yield*`.
// - The error value for a catch block.
// - The current protected region (array of try/catch/finally/end labels).
// - The verb (`next`, `throw`, or `return` method) to delegate to the expression
// of a `yield*`.
// - The result of evaluating the verb delegated to the expression of a `yield*`.
//
// functions:
// verb(n) Creates a bound callback to the `step` function for opcode `n`.
// step(op) Evaluates opcodes in a generator body until execution is suspended or
// completed.
//
// The __generator helper understands a limited set of instructions:
// 0: next(value?) - Start or resume the generator with the specified value.
// 1: throw(error) - Resume the generator with an exception. If the generator is
// suspended inside of one or more protected regions, evaluates
// any intervening finally blocks between the current label and
// the nearest catch block or function boundary. If uncaught, the
// exception is thrown to the caller.
// 2: return(value?) - Resume the generator as if with a return. If the generator is
// suspended inside of one or more protected regions, evaluates any
// intervening finally blocks.
// 3: break(label) - Jump to the specified label. If the label is outside of the
// current protected region, evaluates any intervening finally
// blocks.
// 4: yield(value?) - Yield execution to the caller with an optional value. When
// resumed, the generator will continue at the next label.
// 5: yield*(value) - Delegates evaluation to the supplied iterator. When
// delegation completes, the generator will continue at the next
// label.
// 6: catch(error) - Handles an exception thrown from within the generator body. If
// the current label is inside of one or more protected regions,
// evaluates any intervening finally blocks between the current
// label and the nearest catch block or function boundary. If
// uncaught, the exception is thrown to the caller.
// 7: endfinally - Ends a finally block, resuming the last instruction prior to
// entering a finally block.
//
// For examples of how these are used, see the comments in ./transformers/generators.ts
export const generatorHelper: UnscopedEmitHelper = {
name: "typescript:generator",
importName: "__generator",
scoped: false,
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, 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.");
while (_) try {
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
if (y = 0, t) op = [op[0] & 2, t.value];
switch (op[0]) {
case 0: case 1: t = op; break;
case 4: _.label++; return { value: op[1], done: false };
case 5: _.label++; y = op[1]; op = [0]; continue;
case 7: op = _.ops.pop(); _.trys.pop(); continue;
default:
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
if (t[2]) _.ops.pop();
_.trys.pop(); continue;
}
op = body.call(thisArg, _);
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
}
};`
};
}

View File

@ -1,10 +1,14 @@
/*@internal*/
namespace ts {
export function transformJsx(context: TransformationContext) {
const {
factory,
getEmitHelperFactory: emitHelpers,
} = context;
const compilerOptions = context.getCompilerOptions();
let currentSourceFile: SourceFile;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
/**
* Transform JSX-specific syntax in a SourceFile.
@ -89,8 +93,8 @@ namespace ts {
let objectProperties: Expression | undefined;
const attrs = node.attributes.properties;
if (attrs.length === 0) {
objectProperties = factory.createNull();
// When there are no attributes, React wants "null"
objectProperties = createNull();
}
else {
// Map spans of JsxAttribute nodes into object literals and spans
@ -98,25 +102,26 @@ namespace ts {
const segments = flatten<Expression | ObjectLiteralExpression>(
spanMap(attrs, isJsxSpreadAttribute, (attrs, isSpread) => isSpread
? map(attrs, transformJsxSpreadAttributeToExpression)
: createObjectLiteral(map(attrs, transformJsxAttributeToObjectLiteralElement))
: factory.createObjectLiteralExpression(map(attrs, transformJsxAttributeToObjectLiteralElement))
)
);
if (isJsxSpreadAttribute(attrs[0])) {
// We must always emit at least one object literal before a spread
// argument.
segments.unshift(createObjectLiteral());
// argument.factory.createObjectLiteral
segments.unshift(factory.createObjectLiteralExpression());
}
// Either emit one big object literal (no spread attribs), or
// a call to the __assign helper.
objectProperties = singleOrUndefined(segments);
if (!objectProperties) {
objectProperties = createAssignHelper(context, segments);
objectProperties = emitHelpers().createAssignHelper(segments);
}
}
const element = createExpressionForJsxElement(
factory,
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace!, // TODO: GH#18217
tagName,
@ -135,6 +140,7 @@ namespace ts {
function visitJsxOpeningFragment(node: JsxOpeningFragment, children: readonly JsxChild[], isChild: boolean, location: TextRange) {
const element = createExpressionForJsxFragment(
factory,
context.getEmitResolver().getJsxFactoryEntity(currentSourceFile),
compilerOptions.reactNamespace!, // TODO: GH#18217
mapDefined(children, transformJsxChildToExpression),
@ -156,25 +162,25 @@ namespace ts {
function transformJsxAttributeToObjectLiteralElement(node: JsxAttribute) {
const name = getAttributeName(node);
const expression = transformJsxAttributeInitializer(node.initializer);
return createPropertyAssignment(name, expression);
return factory.createPropertyAssignment(name, expression);
}
function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression | undefined): Expression {
if (node === undefined) {
return createTrue();
return factory.createTrue();
}
else if (node.kind === SyntaxKind.StringLiteral) {
// Always recreate the literal to escape any escape sequences or newlines which may be in the original jsx string and which
// Need to be escaped to be handled correctly in a normal string
const literal = createLiteral(tryDecodeEntities(node.text) || node.text);
literal.singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile);
const singleQuote = node.singleQuote !== undefined ? node.singleQuote : !isStringDoubleQuoted(node, currentSourceFile);
const literal = factory.createStringLiteral(tryDecodeEntities(node.text) || node.text, singleQuote);
return setTextRange(literal, node);
}
else if (node.kind === SyntaxKind.JsxExpression) {
if (node.expression === undefined) {
return createTrue();
return factory.createTrue();
}
return visitJsxExpression(node);
return visitNode(node.expression, visitor, isExpression);
}
else {
return Debug.failBadSyntaxKind(node);
@ -183,7 +189,7 @@ namespace ts {
function visitJsxText(node: JsxText): StringLiteral | undefined {
const fixed = fixupWhitespaceAndDecodeEntities(node.text);
return fixed === undefined ? undefined : createLiteral(fixed);
return fixed === undefined ? undefined : factory.createStringLiteral(fixed);
}
/**
@ -279,10 +285,10 @@ namespace ts {
else {
const name = node.tagName;
if (isIdentifier(name) && isIntrinsicJsxName(name.escapedText)) {
return createLiteral(idText(name));
return factory.createStringLiteral(idText(name));
}
else {
return createExpressionFromEntityName(name);
return createExpressionFromEntityName(factory, name);
}
}
}
@ -299,7 +305,7 @@ namespace ts {
return name;
}
else {
return createLiteral(text);
return factory.createStringLiteral(text);
}
}

View File

@ -1,6 +1,10 @@
/*@internal*/
namespace ts {
export function transformECMAScriptModule(context: TransformationContext) {
const {
factory,
getEmitHelperFactory: emitHelpers,
} = context;
const compilerOptions = context.getCompilerOptions();
const previousOnEmitNode = context.onEmitNode;
const previousOnSubstituteNode = context.onSubstituteNode;
@ -10,7 +14,7 @@ namespace ts {
context.enableSubstitution(SyntaxKind.Identifier);
let helperNameSubstitutions: Map<Identifier> | undefined;
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
function transformSourceFile(node: SourceFile) {
if (node.isDeclarationFile) {
@ -22,9 +26,9 @@ namespace ts {
if (!isExternalModule(node) || some(result.statements, isExternalModuleIndicator)) {
return result;
}
return updateSourceFileNode(
return factory.updateSourceFile(
result,
setTextRange(createNodeArray([...result.statements, createEmptyExports()]), result.statements),
setTextRange(factory.createNodeArray([...result.statements, createEmptyExports(factory)]), result.statements),
);
}
@ -32,16 +36,16 @@ namespace ts {
}
function updateExternalModule(node: SourceFile) {
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(node, compilerOptions);
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(factory, emitHelpers(), node, compilerOptions);
if (externalHelpersImportDeclaration) {
const statements: Statement[] = [];
const statementOffset = addPrologue(statements, node.statements);
const statementOffset = factory.copyPrologue(node.statements, statements);
append(statements, externalHelpersImportDeclaration);
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
return updateSourceFileNode(
return factory.updateSourceFile(
node,
setTextRange(createNodeArray(statements), node.statements));
setTextRange(factory.createNodeArray(statements), node.statements));
}
else {
return visitEachChild(node, visitor, context);
@ -80,12 +84,14 @@ namespace ts {
}
const oldIdentifier = node.exportClause.name;
const synthName = getGeneratedNameForNode(oldIdentifier);
const importDecl = createImportDeclaration(
const synthName = factory.getGeneratedNameForNode(oldIdentifier);
const importDecl = factory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(/*name*/ undefined,
createNamespaceImport(
factory.createImportClause(
/*isTypeOnly*/ false,
/*name*/ undefined,
factory.createNamespaceImport(
synthName
)
),
@ -93,10 +99,11 @@ namespace ts {
);
setOriginalNode(importDecl, node.exportClause);
const exportDecl = createExportDeclaration(
const exportDecl = factory.createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports([createExportSpecifier(synthName, oldIdentifier)]),
/*isTypeOnly*/ false,
factory.createNamedExports([factory.createExportSpecifier(synthName, oldIdentifier)]),
);
setOriginalNode(exportDecl, node);
@ -150,7 +157,7 @@ namespace ts {
const name = idText(node);
let substitution = helperNameSubstitutions!.get(name);
if (!substitution) {
helperNameSubstitutions!.set(name, substitution = createFileLevelUniqueName(name));
helperNameSubstitutions!.set(name, substitution = factory.createUniqueName(name, GeneratedIdentifierFlags.Optimistic | GeneratedIdentifierFlags.FileLevel));
}
return substitution;
}

File diff suppressed because it is too large Load Diff

View File

@ -7,6 +7,7 @@ namespace ts {
}
const {
factory,
startLexicalEnvironment,
endLexicalEnvironment,
hoistVariableDeclaration
@ -41,7 +42,7 @@ namespace ts {
let enclosingBlockScopedContainer: Node;
let noSubstitution: boolean[] | undefined; // Set of nodes for which substitution rules should be ignored.
return chainBundle(transformSourceFile);
return chainBundle(context, transformSourceFile);
/**
* Transforms the module aspects of a SourceFile.
@ -71,25 +72,25 @@ namespace ts {
// see comment to 'substitutePostfixUnaryExpression' for more details
// Collect information about the external module and dependency groups.
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(node, resolver, compilerOptions);
moduleInfo = moduleInfoMap[id] = collectExternalModuleInfo(context, node, resolver, compilerOptions);
// Make sure that the name of the 'exports' function does not conflict with
// existing identifiers.
exportFunction = createUniqueName("exports");
exportFunction = factory.createUniqueName("exports");
exportFunctionsMap[id] = exportFunction;
contextObject = contextObjectMap[id] = createUniqueName("context");
contextObject = contextObjectMap[id] = factory.createUniqueName("context");
// Add the body of the module.
const dependencyGroups = collectDependencyGroups(moduleInfo.externalImports);
const moduleBodyBlock = createSystemModuleBody(node, dependencyGroups);
const moduleBodyFunction = createFunctionExpression(
const moduleBodyFunction = factory.createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction),
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject)
factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, exportFunction),
factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, contextObject)
],
/*type*/ undefined,
moduleBodyBlock
@ -98,16 +99,16 @@ namespace ts {
// Write the call to `System.register`
// Clear the emit-helpers flag for later passes since we'll have already used it in the module body
// So the helper will be emit at the correct position instead of at the top of the source-file
const moduleName = tryGetModuleNameFromFile(node, host, compilerOptions);
const dependencies = createArrayLiteral(map(dependencyGroups, dependencyGroup => dependencyGroup.name));
const moduleName = tryGetModuleNameFromFile(factory, node, host, compilerOptions);
const dependencies = factory.createArrayLiteralExpression(map(dependencyGroups, dependencyGroup => dependencyGroup.name));
const updated = setEmitFlags(
updateSourceFileNode(
factory.updateSourceFile(
node,
setTextRange(
createNodeArray([
createExpressionStatement(
createCall(
createPropertyAccess(createIdentifier("System"), "register"),
factory.createNodeArray([
factory.createExpressionStatement(
factory.createCallExpression(
factory.createPropertyAccessExpression(factory.createIdentifier("System"), "register"),
/*typeArguments*/ undefined,
moduleName
? [moduleName, dependencies, moduleBodyFunction]
@ -134,7 +135,7 @@ namespace ts {
contextObject = undefined!;
hoistedStatements = undefined!;
enclosingBlockScopedContainer = undefined!;
return aggregateTransformFlags(updated);
return updated;
}
/**
@ -146,7 +147,7 @@ namespace ts {
const groupIndices = createMap<number>();
const dependencyGroups: DependencyGroup[] = [];
for (const externalImport of externalImports) {
const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions);
const externalModuleName = getExternalModuleNameLiteral(factory, externalImport, currentSourceFile, host, resolver, compilerOptions);
if (externalModuleName) {
const text = externalModuleName.text;
const groupIndex = groupIndices.get(text);
@ -224,19 +225,20 @@ namespace ts {
// Add any prologue directives.
const ensureUseStrict = getStrictOptionValue(compilerOptions, "alwaysStrict") || (!compilerOptions.noImplicitUseStrict && isExternalModule(currentSourceFile));
const statementOffset = addPrologue(statements, node.statements, ensureUseStrict, sourceElementVisitor);
const statementOffset = factory.copyPrologue(node.statements, statements, ensureUseStrict, sourceElementVisitor);
// var __moduleName = context_1 && context_1.id;
statements.push(
createVariableStatement(
factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
"__moduleName",
/*exclamationToken*/ undefined,
/*type*/ undefined,
createLogicalAnd(
factory.createLogicalAnd(
contextObject,
createPropertyAccess(contextObject, "id")
factory.createPropertyAccessExpression(contextObject, "id")
)
)
])
@ -263,28 +265,27 @@ namespace ts {
const exportStarFunction = addExportStarIfNeeded(statements)!; // TODO: GH#18217
const modifiers = node.transformFlags & TransformFlags.ContainsAwait ?
createModifiersFromModifierFlags(ModifierFlags.Async) :
factory.createModifiersFromModifierFlags(ModifierFlags.Async) :
undefined;
const moduleObject = createObjectLiteral([
createPropertyAssignment("setters",
const moduleObject = factory.createObjectLiteralExpression([
factory.createPropertyAssignment("setters",
createSettersArray(exportStarFunction, dependencyGroups)
),
createPropertyAssignment("execute",
createFunctionExpression(
factory.createPropertyAssignment("execute",
factory.createFunctionExpression(
modifiers,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
createBlock(executeStatements, /*multiLine*/ true)
factory.createBlock(executeStatements, /*multiLine*/ true)
)
)
]);
], /*multiLine*/ true);
moduleObject.multiLine = true;
statements.push(createReturn(moduleObject));
return createBlock(statements, /*multiLine*/ true);
statements.push(factory.createReturnStatement(moduleObject));
return factory.createBlock(statements, /*multiLine*/ true);
}
/**
@ -331,23 +332,24 @@ namespace ts {
// write name of exported declaration, i.e 'export var x...'
exportedNames.push(
createPropertyAssignment(
createLiteral(exportedLocalName),
createTrue()
factory.createPropertyAssignment(
factory.createStringLiteralFromNode(exportedLocalName),
factory.createTrue()
)
);
}
}
const exportedNamesStorageRef = createUniqueName("exportedNames");
const exportedNamesStorageRef = factory.createUniqueName("exportedNames");
statements.push(
createVariableStatement(
factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
exportedNamesStorageRef,
/*exclamationToken*/ undefined,
/*type*/ undefined,
createObjectLiteral(exportedNames, /*multiline*/ true)
factory.createObjectLiteralExpression(exportedNames, /*multiline*/ true)
)
])
)
@ -366,17 +368,17 @@ namespace ts {
* names.
*/
function createExportStarFunction(localNames: Identifier | undefined) {
const exportStarFunction = createUniqueName("exportStar");
const m = createIdentifier("m");
const n = createIdentifier("n");
const exports = createIdentifier("exports");
let condition: Expression = createStrictInequality(n, createLiteral("default"));
const exportStarFunction = factory.createUniqueName("exportStar");
const m = factory.createIdentifier("m");
const n = factory.createIdentifier("n");
const exports = factory.createIdentifier("exports");
let condition: Expression = factory.createStrictInequality(n, factory.createStringLiteral("default"));
if (localNames) {
condition = createLogicalAnd(
condition = factory.createLogicalAnd(
condition,
createLogicalNot(
createCall(
createPropertyAccess(localNames, "hasOwnProperty"),
factory.createLogicalNot(
factory.createCallExpression(
factory.createPropertyAccessExpression(localNames, "hasOwnProperty"),
/*typeArguments*/ undefined,
[n]
)
@ -384,38 +386,39 @@ namespace ts {
);
}
return createFunctionDeclaration(
return factory.createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
exportStarFunction,
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)],
[factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, m)],
/*type*/ undefined,
createBlock([
createVariableStatement(
factory.createBlock([
factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
exports,
/*exclamationToken*/ undefined,
/*type*/ undefined,
createObjectLiteral([])
factory.createObjectLiteralExpression([])
)
])
),
createForIn(
createVariableDeclarationList([
createVariableDeclaration(n, /*type*/ undefined)
factory.createForInStatement(
factory.createVariableDeclarationList([
factory.createVariableDeclaration(n)
]),
m,
createBlock([
factory.createBlock([
setEmitFlags(
createIf(
factory.createIfStatement(
condition,
createExpressionStatement(
createAssignment(
createElementAccess(exports, n),
createElementAccess(m, n)
factory.createExpressionStatement(
factory.createAssignment(
factory.createElementAccessExpression(exports, n),
factory.createElementAccessExpression(m, n)
)
)
),
@ -423,8 +426,8 @@ namespace ts {
)
])
),
createExpressionStatement(
createCall(
factory.createExpressionStatement(
factory.createCallExpression(
exportFunction,
/*typeArguments*/ undefined,
[exports]
@ -444,11 +447,11 @@ namespace ts {
const setters: Expression[] = [];
for (const group of dependencyGroups) {
// derive a unique name for parameter from the first named entry in the group
const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(i, currentSourceFile));
const parameterName = localName ? getGeneratedNameForNode(localName) : createUniqueName("");
const localName = forEach(group.externalImports, i => getLocalNameForExternalImport(factory, i, currentSourceFile));
const parameterName = localName ? factory.getGeneratedNameForNode(localName) : factory.createUniqueName("");
const statements: Statement[] = [];
for (const entry of group.externalImports) {
const importVariableName = getLocalNameForExternalImport(entry, currentSourceFile)!; // TODO: GH#18217
const importVariableName = getLocalNameForExternalImport(factory, entry, currentSourceFile)!; // TODO: GH#18217
switch (entry.kind) {
case SyntaxKind.ImportDeclaration:
if (!entry.importClause) {
@ -462,8 +465,8 @@ namespace ts {
Debug.assert(importVariableName !== undefined);
// save import into the local
statements.push(
createExpressionStatement(
createAssignment(importVariableName, parameterName)
factory.createExpressionStatement(
factory.createAssignment(importVariableName, parameterName)
)
);
break;
@ -483,34 +486,34 @@ namespace ts {
const properties: PropertyAssignment[] = [];
for (const e of entry.exportClause.elements) {
properties.push(
createPropertyAssignment(
createLiteral(idText(e.name)),
createElementAccess(
factory.createPropertyAssignment(
factory.createStringLiteral(idText(e.name)),
factory.createElementAccessExpression(
parameterName,
createLiteral(idText(e.propertyName || e.name))
factory.createStringLiteral(idText(e.propertyName || e.name))
)
)
);
}
statements.push(
createExpressionStatement(
createCall(
factory.createExpressionStatement(
factory.createCallExpression(
exportFunction,
/*typeArguments*/ undefined,
[createObjectLiteral(properties, /*multiline*/ true)]
[factory.createObjectLiteralExpression(properties, /*multiline*/ true)]
)
)
);
}
else {
statements.push(
createExpressionStatement(
createCall(
factory.createExpressionStatement(
factory.createCallExpression(
exportFunction,
/*typeArguments*/ undefined,
[
createLiteral(idText(entry.exportClause.name)),
factory.createStringLiteral(idText(entry.exportClause.name)),
parameterName
]
)
@ -525,8 +528,8 @@ namespace ts {
//
// exportStar(foo_1_1);
statements.push(
createExpressionStatement(
createCall(
factory.createExpressionStatement(
factory.createCallExpression(
exportStarFunction,
/*typeArguments*/ undefined,
[parameterName]
@ -539,19 +542,19 @@ namespace ts {
}
setters.push(
createFunctionExpression(
factory.createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
[factory.createParameterDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
/*type*/ undefined,
createBlock(statements, /*multiLine*/ true)
factory.createBlock(statements, /*multiLine*/ true)
)
);
}
return createArrayLiteral(setters, /*multiLine*/ true);
return factory.createArrayLiteralExpression(setters, /*multiLine*/ true);
}
//
@ -590,7 +593,7 @@ namespace ts {
function visitImportDeclaration(node: ImportDeclaration): VisitResult<Statement> {
let statements: Statement[] | undefined;
if (node.importClause) {
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217
hoistVariableDeclaration(getLocalNameForExternalImport(factory, node, currentSourceFile)!); // TODO: GH#18217
}
if (hasAssociatedEndOfDeclarationMarker(node)) {
@ -619,7 +622,7 @@ namespace ts {
Debug.assert(isExternalModuleImportEqualsDeclaration(node), "import= for internal module references should be handled in an earlier transformer.");
let statements: Statement[] | undefined;
hoistVariableDeclaration(getLocalNameForExternalImport(node, currentSourceFile)!); // TODO: GH#18217
hoistVariableDeclaration(getLocalNameForExternalImport(factory, node, currentSourceFile)!); // TODO: GH#18217
if (hasAssociatedEndOfDeclarationMarker(node)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
@ -649,10 +652,10 @@ namespace ts {
if (original && hasAssociatedEndOfDeclarationMarker(original)) {
// Defer exports until we encounter an EndOfDeclarationMarker node
const id = getOriginalNodeId(node);
deferredExports[id] = appendExportStatement(deferredExports[id], createIdentifier("default"), expression, /*allowComments*/ true);
deferredExports[id] = appendExportStatement(deferredExports[id], factory.createIdentifier("default"), expression, /*allowComments*/ true);
}
else {
return createExportStatement(createIdentifier("default"), expression, /*allowComments*/ true);
return createExportStatement(factory.createIdentifier("default"), expression, /*allowComments*/ true);
}
}
@ -664,12 +667,12 @@ namespace ts {
function visitFunctionDeclaration(node: FunctionDeclaration): VisitResult<Statement> {
if (hasSyntacticModifier(node, ModifierFlags.Export)) {
hoistedStatements = append(hoistedStatements,
updateFunctionDeclaration(
factory.updateFunctionDeclaration(
node,
node.decorators,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
factory.getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
visitNodes(node.parameters, destructuringAndImportCallVisitor, isParameterDeclaration),
/*type*/ undefined,
@ -700,17 +703,18 @@ namespace ts {
let statements: Statement[] | undefined;
// Hoist the name of the class declaration to the outer module body function.
const name = getLocalName(node);
const name = factory.getLocalName(node);
hoistVariableDeclaration(name);
// Rewrite the class declaration into an assignment of a class expression.
statements = append(statements,
setTextRange(
createExpressionStatement(
createAssignment(
factory.createExpressionStatement(
factory.createAssignment(
name,
setTextRange(
createClassExpression(
factory.createClassExpression(
visitNodes(node.decorators, destructuringAndImportCallVisitor, isDecorator),
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
@ -762,7 +766,7 @@ namespace ts {
let statements: Statement[] | undefined;
if (expressions) {
statements = append(statements, setTextRange(createExpressionStatement(inlineExpressions(expressions)), node));
statements = append(statements, setTextRange(factory.createExpressionStatement(factory.inlineExpressions(expressions)), node));
}
if (isMarkedDeclaration) {
@ -791,7 +795,7 @@ namespace ts {
}
}
else {
hoistVariableDeclaration(getSynthesizedClone(node.name));
hoistVariableDeclaration(factory.cloneNode(node.name));
}
}
@ -858,10 +862,10 @@ namespace ts {
* @param isExportedDeclaration A value indicating whether the variable is exported.
*/
function createVariableAssignment(name: Identifier, value: Expression, location: TextRange | undefined, isExportedDeclaration: boolean) {
hoistVariableDeclaration(getSynthesizedClone(name));
hoistVariableDeclaration(factory.cloneNode(name));
return isExportedDeclaration
? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location)))
: preventSubstitution(setTextRange(createAssignment(name, value), location));
? createExportExpression(name, preventSubstitution(setTextRange(factory.createAssignment(name, value), location)))
: preventSubstitution(setTextRange(factory.createAssignment(name, value), location));
}
/**
@ -1031,7 +1035,7 @@ namespace ts {
else if (!isGeneratedIdentifier(decl.name)) {
let excludeName: string | undefined;
if (exportSelf) {
statements = appendExportStatement(statements, decl.name, getLocalName(decl));
statements = appendExportStatement(statements, decl.name, factory.getLocalName(decl));
excludeName = idText(decl.name);
}
@ -1057,8 +1061,8 @@ namespace ts {
let excludeName: string | undefined;
if (hasSyntacticModifier(decl, ModifierFlags.Export)) {
const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) ? createLiteral("default") : decl.name!;
statements = appendExportStatement(statements, exportName, getLocalName(decl));
const exportName = hasSyntacticModifier(decl, ModifierFlags.Default) ? factory.createStringLiteral("default") : decl.name!;
statements = appendExportStatement(statements, exportName, factory.getLocalName(decl));
excludeName = getTextOfIdentifierOrLiteral(exportName);
}
@ -1083,7 +1087,7 @@ namespace ts {
return statements;
}
const name = getDeclarationName(decl);
const name = factory.getDeclarationName(decl);
const exportSpecifiers = moduleInfo.exportSpecifiers.get(idText(name));
if (exportSpecifiers) {
for (const exportSpecifier of exportSpecifiers) {
@ -1119,7 +1123,7 @@ namespace ts {
* @param allowComments An optional value indicating whether to emit comments for the statement.
*/
function createExportStatement(name: Identifier | StringLiteral, value: Expression, allowComments?: boolean) {
const statement = createExpressionStatement(createExportExpression(name, value));
const statement = factory.createExpressionStatement(createExportExpression(name, value));
startOnNewLine(statement);
if (!allowComments) {
setEmitFlags(statement, EmitFlags.NoComments);
@ -1135,9 +1139,9 @@ namespace ts {
* @param value The exported value.
*/
function createExportExpression(name: Identifier | StringLiteral, value: Expression) {
const exportName = isIdentifier(name) ? createLiteral(name) : name;
const exportName = isIdentifier(name) ? factory.createStringLiteralFromNode(name) : name;
setEmitFlags(value, getEmitFlags(value) | EmitFlags.NoComments);
return setCommentRange(createCall(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value);
return setCommentRange(factory.createCallExpression(exportFunction, /*typeArguments*/ undefined, [exportName, value]), value);
}
//
@ -1222,7 +1226,7 @@ namespace ts {
const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer;
enclosingBlockScopedContainer = node;
node = updateFor(
node = factory.updateForStatement(
node,
node.initializer && visitForInitializer(node.initializer),
visitNode(node.condition, destructuringAndImportCallVisitor, isExpression),
@ -1243,11 +1247,11 @@ namespace ts {
const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer;
enclosingBlockScopedContainer = node;
node = updateForIn(
node = factory.updateForInStatement(
node,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@ -1263,12 +1267,12 @@ namespace ts {
const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer;
enclosingBlockScopedContainer = node;
node = updateForOf(
node = factory.updateForOfStatement(
node,
node.awaitModifier,
visitForInitializer(node.initializer),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
);
enclosingBlockScopedContainer = savedEnclosingBlockScopedContainer;
@ -1301,7 +1305,7 @@ namespace ts {
}
}
return expressions ? inlineExpressions(expressions) : createOmittedExpression();
return expressions ? factory.inlineExpressions(expressions) : factory.createOmittedExpression();
}
else {
return visitEachChild(node, nestedElementVisitor, context);
@ -1314,9 +1318,9 @@ namespace ts {
* @param node The node to visit.
*/
function visitDoStatement(node: DoStatement): VisitResult<Statement> {
return updateDo(
return factory.updateDoStatement(
node,
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock),
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock),
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression)
);
}
@ -1327,10 +1331,10 @@ namespace ts {
* @param node The node to visit.
*/
function visitWhileStatement(node: WhileStatement): VisitResult<Statement> {
return updateWhile(
return factory.updateWhileStatement(
node,
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
);
}
@ -1340,10 +1344,10 @@ namespace ts {
* @param node The node to visit.
*/
function visitLabeledStatement(node: LabeledStatement): VisitResult<Statement> {
return updateLabel(
return factory.updateLabeledStatement(
node,
node.label,
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
);
}
@ -1353,10 +1357,10 @@ namespace ts {
* @param node The node to visit.
*/
function visitWithStatement(node: WithStatement): VisitResult<Statement> {
return updateWith(
return factory.updateWithStatement(
node,
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.statement, nestedElementVisitor, isStatement, liftToBlock)
visitNode(node.statement, nestedElementVisitor, isStatement, factory.liftToBlock)
);
}
@ -1366,7 +1370,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitSwitchStatement(node: SwitchStatement): VisitResult<Statement> {
return updateSwitch(
return factory.updateSwitchStatement(
node,
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNode(node.caseBlock, nestedElementVisitor, isCaseBlock)
@ -1382,7 +1386,7 @@ namespace ts {
const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer;
enclosingBlockScopedContainer = node;
node = updateCaseBlock(
node = factory.updateCaseBlock(
node,
visitNodes(node.clauses, nestedElementVisitor, isCaseOrDefaultClause)
);
@ -1397,7 +1401,7 @@ namespace ts {
* @param node The node to visit.
*/
function visitCaseClause(node: CaseClause): VisitResult<CaseOrDefaultClause> {
return updateCaseClause(
return factory.updateCaseClause(
node,
visitNode(node.expression, destructuringAndImportCallVisitor, isExpression),
visitNodes(node.statements, nestedElementVisitor, isStatement)
@ -1431,7 +1435,7 @@ namespace ts {
const savedEnclosingBlockScopedContainer = enclosingBlockScopedContainer;
enclosingBlockScopedContainer = node;
node = updateCatchClause(
node = factory.updateCatchClause(
node,
node.variableDeclaration,
visitNode(node.block, nestedElementVisitor, isBlock)
@ -1491,10 +1495,10 @@ namespace ts {
// }
// };
// });
return createCall(
createPropertyAccess(
return factory.createCallExpression(
factory.createPropertyAccessExpression(
contextObject,
createIdentifier("import")
factory.createIdentifier("import")
),
/*typeArguments*/ undefined,
some(node.arguments) ? [visitNode(node.arguments[0], destructuringAndImportCallVisitor)] : []
@ -1659,11 +1663,11 @@ namespace ts {
if (importDeclaration) {
if (isImportClause(importDeclaration)) {
return setTextRange(
createPropertyAssignment(
getSynthesizedClone(name),
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default")
factory.createPropertyAssignment(
factory.cloneNode(name),
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent),
factory.createIdentifier("default")
)
),
/*location*/ node
@ -1671,11 +1675,11 @@ namespace ts {
}
else if (isImportSpecifier(importDeclaration)) {
return setTextRange(
createPropertyAssignment(
getSynthesizedClone(name),
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)
factory.createPropertyAssignment(
factory.cloneNode(name),
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent),
factory.cloneNode(importDeclaration.propertyName || importDeclaration.name)
),
),
/*location*/ node
@ -1716,7 +1720,7 @@ namespace ts {
if (getEmitFlags(node) & EmitFlags.HelperName) {
const externalHelpersModuleName = getExternalHelpersModuleName(currentSourceFile);
if (externalHelpersModuleName) {
return createPropertyAccess(externalHelpersModuleName, node);
return factory.createPropertyAccessExpression(externalHelpersModuleName, node);
}
return node;
@ -1733,18 +1737,18 @@ namespace ts {
if (importDeclaration) {
if (isImportClause(importDeclaration)) {
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default")
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent),
factory.createIdentifier("default")
),
/*location*/ node
);
}
else if (isImportSpecifier(importDeclaration)) {
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)
factory.createPropertyAccessExpression(
factory.getGeneratedNameForNode(importDeclaration.parent.parent.parent),
factory.cloneNode(importDeclaration.propertyName || importDeclaration.name)
),
/*location*/ node
);
@ -1813,7 +1817,7 @@ namespace ts {
if (exportedNames) {
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
? setTextRange(
createPrefix(
factory.createPrefixUnaryExpression(
node.operator,
node.operand
),
@ -1827,8 +1831,8 @@ namespace ts {
if (node.kind === SyntaxKind.PostfixUnaryExpression) {
expression = node.operator === SyntaxKind.PlusPlusToken
? createSubtract(preventSubstitution(expression), createLiteral(1))
: createAdd(preventSubstitution(expression), createLiteral(1));
? factory.createSubtract(preventSubstitution(expression), factory.createNumericLiteral(1))
: factory.createAdd(preventSubstitution(expression), factory.createNumericLiteral(1));
}
return expression;
@ -1840,7 +1844,7 @@ namespace ts {
function substituteMetaProperty(node: MetaProperty) {
if (isImportMeta(node)) {
return createPropertyAccess(contextObject, createIdentifier("meta"));
return factory.createPropertyAccessExpression(contextObject, factory.createIdentifier("meta"));
}
return node;
}
@ -1859,7 +1863,7 @@ namespace ts {
if (valueDeclaration) {
const exportContainer = resolver.getReferencedExportContainer(name, /*prefixLocals*/ false);
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
exportedNames = append(exportedNames, getDeclarationName(valueDeclaration));
exportedNames = append(exportedNames, factory.getDeclarationName(valueDeclaration));
}
exportedNames = addRange(exportedNames, moduleInfo && moduleInfo.exportedBindings[getOriginalNodeId(valueDeclaration)]);

View File

@ -42,17 +42,19 @@ namespace ts {
}
}
const helperCall = createTemplateObjectHelper(context, createArrayLiteral(cookedStrings), createArrayLiteral(rawStrings));
const helperCall = context.getEmitHelperFactory().createTemplateObjectHelper(
factory.createArrayLiteralExpression(cookedStrings),
factory.createArrayLiteralExpression(rawStrings));
// Create a variable to cache the template object if we're in a module.
// Do not do this in the global scope, as any variable we currently generate could conflict with
// variables from outside of the current compilation. In the future, we can revisit this behavior.
if (isExternalModule(currentSourceFile)) {
const tempVar = createUniqueName("templateObject");
const tempVar = factory.createUniqueName("templateObject");
recordTaggedTemplateString(tempVar);
templateArguments[0] = createLogicalOr(
templateArguments[0] = factory.createLogicalOr(
tempVar,
createAssignment(
factory.createAssignment(
tempVar,
helperCall)
);
@ -61,11 +63,11 @@ namespace ts {
templateArguments[0] = helperCall;
}
return createCall(tag, /*typeArguments*/ undefined, templateArguments);
return factory.createCallExpression(tag, /*typeArguments*/ undefined, templateArguments);
}
function createTemplateCooked(template: TemplateHead | TemplateMiddle | TemplateTail | NoSubstitutionTemplateLiteral) {
return template.templateFlags ? createVoidZero() : createLiteral(template.text);
return template.templateFlags ? factory.createVoidZero() : factory.createStringLiteral(template.text);
}
/**
@ -93,30 +95,6 @@ namespace ts {
// ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
// <CR><LF> and <CR> LineTerminatorSequences are normalized to <LF> for both TV and TRV.
text = text.replace(/\r\n?/g, "\n");
return setTextRange(createLiteral(text), node);
return setTextRange(factory.createStringLiteral(text), node);
}
function createTemplateObjectHelper(context: TransformationContext, cooked: ArrayLiteralExpression, raw: ArrayLiteralExpression) {
context.requestEmitHelper(templateObjectHelper);
return createCall(
getUnscopedHelperName("__makeTemplateObject"),
/*typeArguments*/ undefined,
[
cooked,
raw
]
);
}
export const templateObjectHelper: UnscopedEmitHelper = {
name: "typescript:makeTemplateObject",
importName: "__makeTemplateObject",
scoped: false,
priority: 0,
text: `
var __makeTemplateObject = (this && this.__makeTemplateObject) || function (cooked, raw) {
if (Object.defineProperty) { Object.defineProperty(cooked, "raw", { value: raw }); } else { cooked.raw = raw; }
return cooked;
};`
};
}

File diff suppressed because it is too large Load Diff

View File

@ -25,7 +25,7 @@ namespace ts {
return e.propertyName !== undefined && e.propertyName.escapedText === InternalSymbolName.Default;
}
export function chainBundle(transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
export function chainBundle(context: CoreTransformationContext, transformSourceFile: (x: SourceFile) => SourceFile): (x: SourceFile | Bundle) => SourceFile | Bundle {
return transformSourceFileOrBundle;
function transformSourceFileOrBundle(node: SourceFile | Bundle) {
@ -33,7 +33,7 @@ namespace ts {
}
function transformBundle(node: Bundle) {
return createBundle(map(node.sourceFiles, transformSourceFile), node.prepends);
return context.factory.createBundle(map(node.sourceFiles, transformSourceFile), node.prepends);
}
}
@ -65,7 +65,7 @@ namespace ts {
return !getImportNeedsImportStarHelper(node) && (isDefaultImport(node) || (!!node.importClause && isNamedImports(node.importClause.namedBindings!) && containsDefaultReference(node.importClause.namedBindings))); // TODO: GH#18217
}
export function collectExternalModuleInfo(sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
export function collectExternalModuleInfo(context: TransformationContext, sourceFile: SourceFile, resolver: EmitResolver, compilerOptions: CompilerOptions): ExternalModuleInfo {
const externalImports: (ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration)[] = [];
const exportSpecifiers = createMultiMap<ExportSpecifier>();
const exportedBindings: Identifier[][] = [];
@ -151,7 +151,7 @@ namespace ts {
if (hasSyntacticModifier(node, ModifierFlags.Default)) {
// export default function() { }
if (!hasExportDefault) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<FunctionDeclaration>node));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(<FunctionDeclaration>node));
hasExportDefault = true;
}
}
@ -172,7 +172,7 @@ namespace ts {
if (hasSyntacticModifier(node, ModifierFlags.Default)) {
// export default class { }
if (!hasExportDefault) {
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), getDeclarationName(<ClassDeclaration>node));
multiMapSparseArrayAdd(exportedBindings, getOriginalNodeId(node), context.factory.getDeclarationName(<ClassDeclaration>node));
hasExportDefault = true;
}
}
@ -190,7 +190,7 @@ namespace ts {
}
}
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault);
const externalHelpersImportDeclaration = createExternalHelpersImportDeclarationIfNeeded(context.factory, context.getEmitHelperFactory(), sourceFile, compilerOptions, hasExportStarsToExportValues, hasImportStar, hasImportDefault);
if (externalHelpersImportDeclaration) {
externalImports.unshift(externalHelpersImportDeclaration);
}
@ -303,11 +303,11 @@ namespace ts {
* @param visitor The visitor to apply to each node added to the result array.
* @returns index of the statement that follows super call
*/
export function addPrologueDirectivesAndInitialSuperCall(ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number {
export function addPrologueDirectivesAndInitialSuperCall(factory: NodeFactory, ctor: ConstructorDeclaration, result: Statement[], visitor: Visitor): number {
if (ctor.body) {
const statements = ctor.body.statements;
// add prologue directives to the list (if any)
const index = addPrologue(result, statements, /*ensureUseStrict*/ false, visitor);
const index = factory.copyPrologue(statements, result, /*ensureUseStrict*/ false, visitor);
if (index === statements.length) {
// list contains nothing but prologue directives (or empty) - exit
return index;
@ -327,29 +327,14 @@ namespace ts {
return 0;
}
/**
* @param input Template string input strings
* @param args Names which need to be made file-level unique
*/
export function helperString(input: TemplateStringsArray, ...args: string[]) {
return (uniqueName: EmitHelperUniqueNameCallback) => {
let result = "";
for (let i = 0; i < args.length; i++) {
result += input[i];
result += uniqueName(args[i]);
}
result += input[input.length - 1];
return result;
};
}
/**
* Gets all the static or all the instance property declarations of a class
*
* @param node The class node.
* @param isStatic A value indicating whether to get properties from the static or instance side of the class.
*/
export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: true, isStatic: boolean): readonly InitializedPropertyDeclaration[];
export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[];
export function getProperties(node: ClassExpression | ClassDeclaration, requireInitializer: boolean, isStatic: boolean): readonly PropertyDeclaration[] {
return filter(node.members, m => isInitializedOrStaticProperty(m, requireInitializer, isStatic)) as PropertyDeclaration[];
}

View File

@ -24,6 +24,15 @@
"scanner.ts",
"utilitiesPublic.ts",
"utilities.ts",
"factory/baseNodeFactory.ts",
"factory/parenthesizerRules.ts",
"factory/nodeConverters.ts",
"factory/nodeFactory.ts",
"factory/emitNode.ts",
"factory/emitHelpers.ts",
"factory/nodeTests.ts",
"factory/utilities.ts",
"factory/utilitiesPublic.ts",
"parser.ts",
"commandLineParser.ts",
"moduleNameResolver.ts",
@ -31,10 +40,7 @@
"binder.ts",
"symbolWalker.ts",
"checker.ts",
"factoryPublic.ts",
"factory.ts",
"visitorPublic.ts",
"visitor.ts",
"sourcemap.ts",
"transformers/utilities.ts",
"transformers/destructuring.ts",

File diff suppressed because it is too large Load Diff

View File

@ -290,13 +290,13 @@ namespace ts {
// If so, mark ourselves accordingly.
if (thisNodeOrAnySubNodesHasError) {
node.flags |= NodeFlags.ThisNodeOrAnySubNodesHasError;
(node as Mutable<Node>).flags |= NodeFlags.ThisNodeOrAnySubNodesHasError;
}
// Also mark that we've propagated the child information to this node. This way we can
// always consult the bit directly on this node without needing to check its children
// again.
node.flags |= NodeFlags.HasAggregatedChildData;
(node as Mutable<Node>).flags |= NodeFlags.HasAggregatedChildData;
}
}
@ -1637,8 +1637,9 @@ namespace ts {
? <EntityNameExpression>(<ExpressionWithTypeArguments>node).expression
: undefined;
case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName:
// TODO(rbuckton): These aren't valid TypeNodes, but we treat them as such because of `isPartOfTypeNode`, which returns `true` for things that aren't `TypeNode`s.
case SyntaxKind.Identifier as TypeNodeSyntaxKind:
case SyntaxKind.QualifiedName as TypeNodeSyntaxKind:
return (<EntityName><Node>node);
}
@ -3104,7 +3105,6 @@ namespace ts {
}
}
export type PropertyNameLiteral = Identifier | StringLiteralLike | NumericLiteral;
export function isPropertyNameLiteral(node: Node): node is PropertyNameLiteral {
switch (node.kind) {
case SyntaxKind.Identifier:
@ -3253,24 +3253,217 @@ namespace ts {
}
}
export const enum OperatorPrecedence {
// Expression:
// AssignmentExpression
// Expression `,` AssignmentExpression
Comma,
// NOTE: `Spread` is higher than `Comma` due to how it is parsed in |ElementList|
// SpreadElement:
// `...` AssignmentExpression
Spread,
// AssignmentExpression:
// ConditionalExpression
// YieldExpression
// ArrowFunction
// AsyncArrowFunction
// LeftHandSideExpression `=` AssignmentExpression
// LeftHandSideExpression AssignmentOperator AssignmentExpression
//
// NOTE: AssignmentExpression is broken down into several precedences due to the requirements
// of the parenthesizer rules.
// AssignmentExpression: YieldExpression
// YieldExpression:
// `yield`
// `yield` AssignmentExpression
// `yield` `*` AssignmentExpression
Yield,
// AssignmentExpression: LeftHandSideExpression `=` AssignmentExpression
// AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression
// AssignmentOperator: one of
// `*=` `/=` `%=` `+=` `-=` `<<=` `>>=` `>>>=` `&=` `^=` `|=` `**=`
Assignment,
// NOTE: `Conditional` is considered higher than `Assignment` here, but in reality they have
// the same precedence.
// AssignmentExpression: ConditionalExpression
// ConditionalExpression:
// ShortCircuitExpression
// ShortCircuitExpression `?` AssignmentExpression `:` AssignmentExpression
// ShortCircuitExpression:
// LogicalORExpression
// CoalesceExpression
Conditional,
// CoalesceExpression:
// CoalesceExpressionHead `??` BitwiseORExpression
// CoalesceExpressionHead:
// CoalesceExpression
// BitwiseORExpression
Coalesce = Conditional, // NOTE: This is wrong
// LogicalORExpression:
// LogicalANDExpression
// LogicalORExpression `||` LogicalANDExpression
LogicalOR,
// LogicalANDExpression:
// BitwiseORExpression
// LogicalANDExprerssion `&&` BitwiseORExpression
LogicalAND,
// BitwiseORExpression:
// BitwiseXORExpression
// BitwiseORExpression `^` BitwiseXORExpression
BitwiseOR,
// BitwiseXORExpression:
// BitwiseANDExpression
// BitwiseXORExpression `^` BitwiseANDExpression
BitwiseXOR,
// BitwiseANDExpression:
// EqualityExpression
// BitwiseANDExpression `^` EqualityExpression
BitwiseAND,
// EqualityExpression:
// RelationalExpression
// EqualityExpression `==` RelationalExpression
// EqualityExpression `!=` RelationalExpression
// EqualityExpression `===` RelationalExpression
// EqualityExpression `!==` RelationalExpression
Equality,
// RelationalExpression:
// ShiftExpression
// RelationalExpression `<` ShiftExpression
// RelationalExpression `>` ShiftExpression
// RelationalExpression `<=` ShiftExpression
// RelationalExpression `>=` ShiftExpression
// RelationalExpression `instanceof` ShiftExpression
// RelationalExpression `in` ShiftExpression
// [+TypeScript] RelationalExpression `as` Type
Relational,
// ShiftExpression:
// AdditiveExpression
// ShiftExpression `<<` AdditiveExpression
// ShiftExpression `>>` AdditiveExpression
// ShiftExpression `>>>` AdditiveExpression
Shift,
// AdditiveExpression:
// MultiplicativeExpression
// AdditiveExpression `+` MultiplicativeExpression
// AdditiveExpression `-` MultiplicativeExpression
Additive,
// MultiplicativeExpression:
// ExponentiationExpression
// MultiplicativeExpression MultiplicativeOperator ExponentiationExpression
// MultiplicativeOperator: one of `*`, `/`, `%`
Multiplicative,
// ExponentiationExpression:
// UnaryExpression
// UpdateExpression `**` ExponentiationExpression
Exponentiation,
// UnaryExpression:
// UpdateExpression
// `delete` UnaryExpression
// `void` UnaryExpression
// `typeof` UnaryExpression
// `+` UnaryExpression
// `-` UnaryExpression
// `~` UnaryExpression
// `!` UnaryExpression
// AwaitExpression
// UpdateExpression: // TODO: Do we need to investigate the precedence here?
// `++` UnaryExpression
// `--` UnaryExpression
Unary,
// UpdateExpression:
// LeftHandSideExpression
// LeftHandSideExpression `++`
// LeftHandSideExpression `--`
Update,
// LeftHandSideExpression:
// NewExpression
// CallExpression
// NewExpression:
// MemberExpression
// `new` NewExpression
LeftHandSide,
// CallExpression:
// CoverCallExpressionAndAsyncArrowHead
// SuperCall
// ImportCall
// CallExpression Arguments
// CallExpression `[` Expression `]`
// CallExpression `.` IdentifierName
// CallExpression TemplateLiteral
// MemberExpression:
// PrimaryExpression
// MemberExpression `[` Expression `]`
// MemberExpression `.` IdentifierName
// MemberExpression TemplateLiteral
// SuperProperty
// MetaProperty
// `new` MemberExpression Arguments
Member,
// TODO: JSXElement?
// PrimaryExpression:
// `this`
// IdentifierReference
// Literal
// ArrayLiteral
// ObjectLiteral
// FunctionExpression
// ClassExpression
// GeneratorExpression
// AsyncFunctionExpression
// AsyncGeneratorExpression
// RegularExpressionLiteral
// TemplateLiteral
// CoverParenthesizedExpressionAndArrowParameterList
Primary,
Highest = Primary,
Lowest = Comma,
// -1 is lower than all other precedences. Returning it will cause binary expression
// parsing to stop.
Invalid = -1,
}
export function getOperatorPrecedence(nodeKind: SyntaxKind, operatorKind: SyntaxKind, hasArguments?: boolean) {
switch (nodeKind) {
case SyntaxKind.CommaListExpression:
return 0;
return OperatorPrecedence.Comma;
case SyntaxKind.SpreadElement:
return 1;
return OperatorPrecedence.Spread;
case SyntaxKind.YieldExpression:
return 2;
return OperatorPrecedence.Yield;
case SyntaxKind.ConditionalExpression:
return 4;
return OperatorPrecedence.Conditional;
case SyntaxKind.BinaryExpression:
switch (operatorKind) {
case SyntaxKind.CommaToken:
return 0;
return OperatorPrecedence.Comma;
case SyntaxKind.EqualsToken:
case SyntaxKind.PlusEqualsToken:
@ -3288,32 +3481,34 @@ namespace ts {
case SyntaxKind.BarBarEqualsToken:
case SyntaxKind.AmpersandAmpersandEqualsToken:
case SyntaxKind.QuestionQuestionEqualsToken:
return 3;
return OperatorPrecedence.Assignment;
default:
return getBinaryOperatorPrecedence(operatorKind);
}
// TODO: Should prefix `++` and `--` be moved to the `Update` precedence?
// TODO: We are missing `TypeAssertionExpression`
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.AwaitExpression:
return 16;
return OperatorPrecedence.Unary;
case SyntaxKind.PostfixUnaryExpression:
return 17;
return OperatorPrecedence.Update;
case SyntaxKind.CallExpression:
return 18;
return OperatorPrecedence.LeftHandSide;
case SyntaxKind.NewExpression:
return hasArguments ? 19 : 18;
return hasArguments ? OperatorPrecedence.Member : OperatorPrecedence.LeftHandSide;
case SyntaxKind.TaggedTemplateExpression:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.ElementAccessExpression:
return 19;
return OperatorPrecedence.Member;
case SyntaxKind.ThisKeyword:
case SyntaxKind.SuperKeyword:
@ -3329,40 +3524,40 @@ namespace ts {
case SyntaxKind.FunctionExpression:
case SyntaxKind.ArrowFunction:
case SyntaxKind.ClassExpression:
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxFragment:
case SyntaxKind.RegularExpressionLiteral:
case SyntaxKind.NoSubstitutionTemplateLiteral:
case SyntaxKind.TemplateExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.OmittedExpression:
return 20;
case SyntaxKind.JsxElement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxFragment:
return OperatorPrecedence.Primary;
default:
return -1;
return OperatorPrecedence.Invalid;
}
}
export function getBinaryOperatorPrecedence(kind: SyntaxKind): number {
export function getBinaryOperatorPrecedence(kind: SyntaxKind): OperatorPrecedence {
switch (kind) {
case SyntaxKind.QuestionQuestionToken:
return 4;
return OperatorPrecedence.Coalesce;
case SyntaxKind.BarBarToken:
return 5;
return OperatorPrecedence.LogicalOR;
case SyntaxKind.AmpersandAmpersandToken:
return 6;
return OperatorPrecedence.LogicalAND;
case SyntaxKind.BarToken:
return 7;
return OperatorPrecedence.BitwiseOR;
case SyntaxKind.CaretToken:
return 8;
return OperatorPrecedence.BitwiseXOR;
case SyntaxKind.AmpersandToken:
return 9;
return OperatorPrecedence.BitwiseAND;
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
return 10;
return OperatorPrecedence.Equality;
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
@ -3370,20 +3565,20 @@ namespace ts {
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.AsKeyword:
return 11;
return OperatorPrecedence.Relational;
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
return 12;
return OperatorPrecedence.Shift;
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
return 13;
return OperatorPrecedence.Additive;
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
return 14;
return OperatorPrecedence.Multiplicative;
case SyntaxKind.AsteriskAsteriskToken:
return 15;
return OperatorPrecedence.Exponentiation;
}
// -1 is lower than all other precedences. Returning it will cause binary expression
@ -4927,7 +5122,7 @@ namespace ts {
return filter(node.declarations, isInitializedVariable);
}
function isInitializedVariable(node: VariableDeclaration) {
function isInitializedVariable(node: VariableDeclaration): node is InitializedVariableDeclaration {
return node.initializer !== undefined;
}
@ -5195,7 +5390,7 @@ namespace ts {
return isClassLike(node) || isInterfaceDeclaration(node) || isTypeLiteralNode(node);
}
export function isTypeNodeKind(kind: SyntaxKind) {
export function isTypeNodeKind(kind: SyntaxKind): kind is TypeNodeSyntaxKind {
return (kind >= SyntaxKind.FirstTypeNode && kind <= SyntaxKind.LastTypeNode)
|| kind === SyntaxKind.AnyKeyword
|| kind === SyntaxKind.UnknownKeyword
@ -5205,10 +5400,8 @@ namespace ts {
|| kind === SyntaxKind.BooleanKeyword
|| kind === SyntaxKind.StringKeyword
|| kind === SyntaxKind.SymbolKeyword
|| kind === SyntaxKind.ThisKeyword
|| kind === SyntaxKind.VoidKeyword
|| kind === SyntaxKind.UndefinedKeyword
|| kind === SyntaxKind.NullKeyword
|| kind === SyntaxKind.NeverKeyword
|| kind === SyntaxKind.ExpressionWithTypeArguments
|| kind === SyntaxKind.JSDocAllType
@ -5246,6 +5439,43 @@ namespace ts {
return node.kind === SyntaxKind.NamedImports || node.kind === SyntaxKind.NamedExports;
}
export function getLeftmostExpression(node: Expression, stopAtCallExpressions: boolean) {
while (true) {
switch (node.kind) {
case SyntaxKind.PostfixUnaryExpression:
node = (<PostfixUnaryExpression>node).operand;
continue;
case SyntaxKind.BinaryExpression:
node = (<BinaryExpression>node).left;
continue;
case SyntaxKind.ConditionalExpression:
node = (<ConditionalExpression>node).condition;
continue;
case SyntaxKind.TaggedTemplateExpression:
node = (<TaggedTemplateExpression>node).tag;
continue;
case SyntaxKind.CallExpression:
if (stopAtCallExpressions) {
return node;
}
// falls through
case SyntaxKind.AsExpression:
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.NonNullExpression:
case SyntaxKind.PartiallyEmittedExpression:
node = (<CallExpression | PropertyAccessExpression | ElementAccessExpression | AsExpression | NonNullExpression | PartiallyEmittedExpression>node).expression;
continue;
}
return node;
}
}
export interface ObjectAllocator {
getNodeConstructor(): new (kind: SyntaxKind, pos?: number, end?: number) => Node;
getTokenConstructor(): new <TKind extends SyntaxKind>(kind: TKind, pos?: number, end?: number) => Token<TKind>;
@ -5282,7 +5512,7 @@ namespace ts {
}
}
function Node(this: Node, kind: SyntaxKind, pos: number, end: number) {
function Node(this: Mutable<Node>, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;
this.end = end;
this.kind = kind;
@ -5294,7 +5524,7 @@ namespace ts {
this.original = undefined;
}
function Token(this: Node, kind: SyntaxKind, pos: number, end: number) {
function Token(this: Mutable<Node>, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;
this.end = end;
this.kind = kind;
@ -5304,7 +5534,7 @@ namespace ts {
this.parent = undefined!;
}
function Identifier(this: Node, kind: SyntaxKind, pos: number, end: number) {
function Identifier(this: Mutable<Node>, kind: SyntaxKind, pos: number, end: number) {
this.pos = pos;
this.end = end;
this.kind = kind;
@ -5354,6 +5584,76 @@ namespace ts {
return localizedDiagnosticMessages && localizedDiagnosticMessages[message.key] || message.message;
}
export function createDetachedDiagnostic(fileName: string, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithDetachedLocation;
export function createDetachedDiagnostic(fileName: string, start: number, length: number, message: DiagnosticMessage): DiagnosticWithDetachedLocation {
Debug.assertGreaterThanOrEqual(start, 0);
Debug.assertGreaterThanOrEqual(length, 0);
let text = getLocaleSpecificMessage(message);
if (arguments.length > 4) {
text = formatStringFromArgs(text, arguments, 4);
}
return {
file: undefined,
start,
length,
messageText: text,
category: message.category,
code: message.code,
reportsUnnecessary: message.reportsUnnecessary,
fileName,
};
}
function isDiagnosticWithDetachedLocation(diagnostic: DiagnosticRelatedInformation | DiagnosticWithDetachedLocation): diagnostic is DiagnosticWithDetachedLocation {
return diagnostic.file === undefined
&& diagnostic.start !== undefined
&& diagnostic.length !== undefined
&& typeof (diagnostic as DiagnosticWithDetachedLocation).fileName === "string";
}
function attachFileToDiagnostic(diagnostic: DiagnosticWithDetachedLocation, file: SourceFile): DiagnosticWithLocation {
const fileName = file.fileName || "";
const length = file.text.length;
Debug.assertEqual(diagnostic.fileName, fileName);
Debug.assertLessThanOrEqual(diagnostic.start, length);
Debug.assertLessThanOrEqual(diagnostic.start + diagnostic.length, length);
const diagnosticWithLocation: DiagnosticWithLocation = {
file,
start: diagnostic.start,
length: diagnostic.length,
messageText: diagnostic.messageText,
category: diagnostic.category,
code: diagnostic.code,
reportsUnnecessary: diagnostic.reportsUnnecessary
};
if (diagnostic.relatedInformation) {
diagnosticWithLocation.relatedInformation = [];
for (const related of diagnostic.relatedInformation) {
if (isDiagnosticWithDetachedLocation(related) && related.fileName === fileName) {
Debug.assertLessThanOrEqual(related.start, length);
Debug.assertLessThanOrEqual(related.start + related.length, length);
diagnosticWithLocation.relatedInformation.push(attachFileToDiagnostic(related, file));
}
else {
diagnosticWithLocation.relatedInformation.push(related);
}
}
}
return diagnosticWithLocation;
}
export function attachFileToDiagnostics(diagnostics: DiagnosticWithDetachedLocation[], file: SourceFile): DiagnosticWithLocation[] {
const diagnosticsWithLocation: DiagnosticWithLocation[] = [];
for (const diagnostic of diagnostics) {
diagnosticsWithLocation.push(attachFileToDiagnostic(diagnostic, file));
}
return diagnosticsWithLocation;
}
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage, ...args: (string | number | undefined)[]): DiagnosticWithLocation;
export function createFileDiagnostic(file: SourceFile, start: number, length: number, message: DiagnosticMessage): DiagnosticWithLocation {
Debug.assertGreaterThanOrEqual(start, 0);
@ -5522,6 +5822,11 @@ namespace ts {
return Comparison.EqualTo;
}
export function getLanguageVariant(scriptKind: ScriptKind) {
// .tsx and .jsx files are treated as jsx language variant.
return scriptKind === ScriptKind.TSX || scriptKind === ScriptKind.JSX || scriptKind === ScriptKind.JS || scriptKind === ScriptKind.JSON ? LanguageVariant.JSX : LanguageVariant.Standard;
}
export function getEmitScriptTarget(compilerOptions: CompilerOptions) {
return compilerOptions.target || ScriptTarget.ES3;
}
@ -6479,4 +6784,119 @@ namespace ts {
}
return true;
}
/**
* Bypasses immutability and directly sets the `pos` property of a `TextRange` or `Node`.
*/
/* @internal */
export function setTextRangePos<T extends ReadonlyTextRange>(range: T, pos: number) {
(range as TextRange).pos = pos;
return range;
}
/**
* Bypasses immutability and directly sets the `end` property of a `TextRange` or `Node`.
*/
/* @internal */
export function setTextRangeEnd<T extends ReadonlyTextRange>(range: T, end: number) {
(range as TextRange).end = end;
return range;
}
/**
* Bypasses immutability and directly sets the `pos` and `end` properties of a `TextRange` or `Node`.
*/
/* @internal */
export function setTextRangePosEnd<T extends ReadonlyTextRange>(range: T, pos: number, end: number) {
return setTextRangeEnd(setTextRangePos(range, pos), end);
}
/**
* Bypasses immutability and directly sets the `pos` and `end` properties of a `TextRange` or `Node` from the
* provided position and width.
*/
/* @internal */
export function setTextRangePosWidth<T extends ReadonlyTextRange>(range: T, pos: number, width: number) {
return setTextRangePosEnd(range, pos, pos + width);
}
/**
* Bypasses immutability and directly sets the `flags` property of a `Node`.
*/
/* @internal */
export function setNodeFlags<T extends Node>(node: T, newFlags: NodeFlags): T;
/* @internal */
export function setNodeFlags<T extends Node>(node: T | undefined, newFlags: NodeFlags): T | undefined;
export function setNodeFlags<T extends Node>(node: T | undefined, newFlags: NodeFlags): T | undefined {
if (node) {
(node as Mutable<T>).flags = newFlags;
}
return node;
}
/**
* Bypasses immutability and directly sets the `parent` property of a `Node`.
*/
/* @internal */
export function setParent<T extends Node>(child: T, parent: T["parent"] | undefined): T;
/* @internal */
export function setParent<T extends Node>(child: T | undefined, parent: T["parent"] | undefined): T | undefined;
export function setParent<T extends Node>(child: T | undefined, parent: T["parent"] | undefined): T | undefined {
if (child && parent) {
(child as Mutable<T>).parent = parent;
}
return child;
}
/**
* Bypasses immutability and directly sets the `parent` property of each `Node` in an array of nodes, if is not already set.
*/
/* @internal */
export function setEachParent<T extends readonly Node[]>(children: T, parent: T[number]["parent"]): T;
/* @internal */
export function setEachParent<T extends readonly Node[]>(children: T | undefined, parent: T[number]["parent"]): T | undefined;
export function setEachParent<T extends readonly Node[]>(children: T | undefined, parent: T[number]["parent"]): T | undefined {
if (children) {
for (const child of children) {
setParent(child, parent);
}
}
return children;
}
/**
* Bypasses immutability and directly sets the `parent` property of each `Node` recursively.
* @param rootNode The root node from which to start the recursion.
* @param incremental When `true`, only recursively descends through nodes whose `parent` pointers are incorrect.
* This allows us to quickly bail out of setting `parent` for subtrees during incremental parsing.
*/
/* @internal */
export function setParentRecursive<T extends Node>(rootNode: T, incremental: boolean): T;
/* @internal */
export function setParentRecursive<T extends Node>(rootNode: T | undefined, incremental: boolean): T | undefined;
export function setParentRecursive<T extends Node>(rootNode: T | undefined, incremental: boolean): T | undefined {
if (!rootNode) return rootNode;
forEachChildRecursively(rootNode, isJSDocNode(rootNode) ? bindParentToChildIgnoringJSDoc : bindParentToChild);
return rootNode;
function bindParentToChildIgnoringJSDoc(child: Node, parent: Node): void | "skip" {
if (incremental && child.parent === parent) {
return "skip";
}
setParent(child, parent);
}
function bindJSDoc(child: Node) {
if (hasJSDocNodes(child)) {
for (const doc of child.jsDoc!) {
bindParentToChildIgnoringJSDoc(doc, child);
forEachChildRecursively(doc, bindParentToChildIgnoringJSDoc);
}
}
}
function bindParentToChild(child: Node, parent: Node) {
return bindParentToChildIgnoringJSDoc(child, parent) || bindJSDoc(child);
}
}
}

View File

@ -413,7 +413,7 @@ namespace ts {
* @param node The original node.
* @returns The original parse tree node if found; otherwise, undefined.
*/
export function getParseTreeNode(node: Node): Node;
export function getParseTreeNode(node: Node | undefined): Node | undefined;
/**
* Gets the original parse tree node for a node.
@ -422,19 +422,19 @@ namespace ts {
* @param nodeTest A callback used to ensure the correct type of parse tree node is returned.
* @returns The original parse tree node if found; otherwise, undefined.
*/
export function getParseTreeNode<T extends Node>(node: Node | undefined, nodeTest?: (node: Node) => node is T): T | undefined;
export function getParseTreeNode<T extends Node>(node: T | undefined, nodeTest?: (node: Node) => node is T): T | undefined;
export function getParseTreeNode(node: Node | undefined, nodeTest?: (node: Node) => boolean): Node | undefined {
if (node === undefined || isParseTreeNode(node)) {
return node;
}
node = getOriginalNode(node);
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
return node;
node = node.original;
while (node) {
if (isParseTreeNode(node)) {
return !nodeTest || nodeTest(node) ? node : undefined;
}
node = node.original;
}
return undefined;
}
/** Add an extra underscore to identifiers that start with two underscores to avoid issues with magic names like '__proto__' */
@ -888,251 +888,24 @@ namespace ts {
}
// #region
// Simple node tests of the form `node.kind === SyntaxKind.Foo`.
// Literals
export function isNumericLiteral(node: Node): node is NumericLiteral {
return node.kind === SyntaxKind.NumericLiteral;
}
export function isBigIntLiteral(node: Node): node is BigIntLiteral {
return node.kind === SyntaxKind.BigIntLiteral;
}
export function isStringLiteral(node: Node): node is StringLiteral {
return node.kind === SyntaxKind.StringLiteral;
}
export function isJsxText(node: Node): node is JsxText {
return node.kind === SyntaxKind.JsxText;
}
export function isRegularExpressionLiteral(node: Node): node is RegularExpressionLiteral {
return node.kind === SyntaxKind.RegularExpressionLiteral;
}
export function isNoSubstitutionTemplateLiteral(node: Node): node is NoSubstitutionTemplateLiteral {
return node.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
// Pseudo-literals
export function isTemplateHead(node: Node): node is TemplateHead {
return node.kind === SyntaxKind.TemplateHead;
}
export function isTemplateMiddle(node: Node): node is TemplateMiddle {
return node.kind === SyntaxKind.TemplateMiddle;
}
export function isTemplateTail(node: Node): node is TemplateTail {
return node.kind === SyntaxKind.TemplateTail;
}
export function isIdentifier(node: Node): node is Identifier {
return node.kind === SyntaxKind.Identifier;
}
// Names
export function isQualifiedName(node: Node): node is QualifiedName {
return node.kind === SyntaxKind.QualifiedName;
}
export function isComputedPropertyName(node: Node): node is ComputedPropertyName {
return node.kind === SyntaxKind.ComputedPropertyName;
}
export function isPrivateIdentifier(node: Node): node is PrivateIdentifier {
return node.kind === SyntaxKind.PrivateIdentifier;
}
export function isIdentifierOrPrivateIdentifier(node: Node): node is Identifier | PrivateIdentifier {
return node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.PrivateIdentifier;
}
// Signature elements
export function isTypeParameterDeclaration(node: Node): node is TypeParameterDeclaration {
return node.kind === SyntaxKind.TypeParameter;
}
export function isParameter(node: Node): node is ParameterDeclaration {
return node.kind === SyntaxKind.Parameter;
}
export function isDecorator(node: Node): node is Decorator {
return node.kind === SyntaxKind.Decorator;
}
// TypeMember
export function isPropertySignature(node: Node): node is PropertySignature {
return node.kind === SyntaxKind.PropertySignature;
}
export function isPropertyDeclaration(node: Node): node is PropertyDeclaration {
return node.kind === SyntaxKind.PropertyDeclaration;
}
export function isMethodSignature(node: Node): node is MethodSignature {
return node.kind === SyntaxKind.MethodSignature;
}
export function isMethodDeclaration(node: Node): node is MethodDeclaration {
return node.kind === SyntaxKind.MethodDeclaration;
}
export function isConstructorDeclaration(node: Node): node is ConstructorDeclaration {
return node.kind === SyntaxKind.Constructor;
}
export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration {
return node.kind === SyntaxKind.GetAccessor;
}
export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration {
return node.kind === SyntaxKind.SetAccessor;
}
export function isCallSignatureDeclaration(node: Node): node is CallSignatureDeclaration {
return node.kind === SyntaxKind.CallSignature;
}
export function isConstructSignatureDeclaration(node: Node): node is ConstructSignatureDeclaration {
return node.kind === SyntaxKind.ConstructSignature;
}
export function isIndexSignatureDeclaration(node: Node): node is IndexSignatureDeclaration {
return node.kind === SyntaxKind.IndexSignature;
}
/* @internal */
export function isGetOrSetAccessorDeclaration(node: Node): node is AccessorDeclaration {
return node.kind === SyntaxKind.SetAccessor || node.kind === SyntaxKind.GetAccessor;
}
// Type
export function isTypePredicateNode(node: Node): node is TypePredicateNode {
return node.kind === SyntaxKind.TypePredicate;
}
export function isTypeReferenceNode(node: Node): node is TypeReferenceNode {
return node.kind === SyntaxKind.TypeReference;
}
export function isFunctionTypeNode(node: Node): node is FunctionTypeNode {
return node.kind === SyntaxKind.FunctionType;
}
export function isConstructorTypeNode(node: Node): node is ConstructorTypeNode {
return node.kind === SyntaxKind.ConstructorType;
}
export function isTypeQueryNode(node: Node): node is TypeQueryNode {
return node.kind === SyntaxKind.TypeQuery;
}
export function isTypeLiteralNode(node: Node): node is TypeLiteralNode {
return node.kind === SyntaxKind.TypeLiteral;
}
export function isArrayTypeNode(node: Node): node is ArrayTypeNode {
return node.kind === SyntaxKind.ArrayType;
}
export function isTupleTypeNode(node: Node): node is TupleTypeNode {
return node.kind === SyntaxKind.TupleType;
}
export function isUnionTypeNode(node: Node): node is UnionTypeNode {
return node.kind === SyntaxKind.UnionType;
}
export function isIntersectionTypeNode(node: Node): node is IntersectionTypeNode {
return node.kind === SyntaxKind.IntersectionType;
}
export function isConditionalTypeNode(node: Node): node is ConditionalTypeNode {
return node.kind === SyntaxKind.ConditionalType;
}
export function isInferTypeNode(node: Node): node is InferTypeNode {
return node.kind === SyntaxKind.InferType;
}
export function isParenthesizedTypeNode(node: Node): node is ParenthesizedTypeNode {
return node.kind === SyntaxKind.ParenthesizedType;
}
export function isThisTypeNode(node: Node): node is ThisTypeNode {
return node.kind === SyntaxKind.ThisType;
}
export function isTypeOperatorNode(node: Node): node is TypeOperatorNode {
return node.kind === SyntaxKind.TypeOperator;
}
export function isIndexedAccessTypeNode(node: Node): node is IndexedAccessTypeNode {
return node.kind === SyntaxKind.IndexedAccessType;
}
export function isMappedTypeNode(node: Node): node is MappedTypeNode {
return node.kind === SyntaxKind.MappedType;
}
export function isLiteralTypeNode(node: Node): node is LiteralTypeNode {
return node.kind === SyntaxKind.LiteralType;
}
export function isImportTypeNode(node: Node): node is ImportTypeNode {
return node.kind === SyntaxKind.ImportType;
}
// Binding patterns
export function isObjectBindingPattern(node: Node): node is ObjectBindingPattern {
return node.kind === SyntaxKind.ObjectBindingPattern;
}
export function isArrayBindingPattern(node: Node): node is ArrayBindingPattern {
return node.kind === SyntaxKind.ArrayBindingPattern;
}
export function isBindingElement(node: Node): node is BindingElement {
return node.kind === SyntaxKind.BindingElement;
}
// Expression
export function isArrayLiteralExpression(node: Node): node is ArrayLiteralExpression {
return node.kind === SyntaxKind.ArrayLiteralExpression;
}
export function isObjectLiteralExpression(node: Node): node is ObjectLiteralExpression {
return node.kind === SyntaxKind.ObjectLiteralExpression;
}
export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression {
return node.kind === SyntaxKind.PropertyAccessExpression;
}
export function isPropertyAccessChain(node: Node): node is PropertyAccessChain {
return isPropertyAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
}
export function isElementAccessExpression(node: Node): node is ElementAccessExpression {
return node.kind === SyntaxKind.ElementAccessExpression;
}
export function isElementAccessChain(node: Node): node is ElementAccessChain {
return isElementAccessExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
}
export function isCallExpression(node: Node): node is CallExpression {
return node.kind === SyntaxKind.CallExpression;
}
export function isCallChain(node: Node): node is CallChain {
return isCallExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
}
@ -1181,408 +954,29 @@ namespace ts {
return node.kind === SyntaxKind.BinaryExpression && (<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken;
}
export function isNewExpression(node: Node): node is NewExpression {
return node.kind === SyntaxKind.NewExpression;
}
export function isTaggedTemplateExpression(node: Node): node is TaggedTemplateExpression {
return node.kind === SyntaxKind.TaggedTemplateExpression;
}
export function isTypeAssertion(node: Node): node is TypeAssertion {
return node.kind === SyntaxKind.TypeAssertionExpression;
}
export function isConstTypeReference(node: Node) {
return isTypeReferenceNode(node) && isIdentifier(node.typeName) &&
node.typeName.escapedText === "const" && !node.typeArguments;
}
export function isParenthesizedExpression(node: Node): node is ParenthesizedExpression {
return node.kind === SyntaxKind.ParenthesizedExpression;
}
export function skipPartiallyEmittedExpressions(node: Expression): Expression;
export function skipPartiallyEmittedExpressions(node: Node): Node;
export function skipPartiallyEmittedExpressions(node: Node) {
return skipOuterExpressions(node, OuterExpressionKinds.PartiallyEmittedExpressions);
}
export function isFunctionExpression(node: Node): node is FunctionExpression {
return node.kind === SyntaxKind.FunctionExpression;
}
export function isArrowFunction(node: Node): node is ArrowFunction {
return node.kind === SyntaxKind.ArrowFunction;
}
export function isDeleteExpression(node: Node): node is DeleteExpression {
return node.kind === SyntaxKind.DeleteExpression;
}
export function isTypeOfExpression(node: Node): node is TypeOfExpression {
return node.kind === SyntaxKind.TypeOfExpression;
}
export function isVoidExpression(node: Node): node is VoidExpression {
return node.kind === SyntaxKind.VoidExpression;
}
export function isAwaitExpression(node: Node): node is AwaitExpression {
return node.kind === SyntaxKind.AwaitExpression;
}
export function isPrefixUnaryExpression(node: Node): node is PrefixUnaryExpression {
return node.kind === SyntaxKind.PrefixUnaryExpression;
}
export function isPostfixUnaryExpression(node: Node): node is PostfixUnaryExpression {
return node.kind === SyntaxKind.PostfixUnaryExpression;
}
export function isBinaryExpression(node: Node): node is BinaryExpression {
return node.kind === SyntaxKind.BinaryExpression;
}
export function isConditionalExpression(node: Node): node is ConditionalExpression {
return node.kind === SyntaxKind.ConditionalExpression;
}
export function isTemplateExpression(node: Node): node is TemplateExpression {
return node.kind === SyntaxKind.TemplateExpression;
}
export function isYieldExpression(node: Node): node is YieldExpression {
return node.kind === SyntaxKind.YieldExpression;
}
export function isSpreadElement(node: Node): node is SpreadElement {
return node.kind === SyntaxKind.SpreadElement;
}
export function isClassExpression(node: Node): node is ClassExpression {
return node.kind === SyntaxKind.ClassExpression;
}
export function isOmittedExpression(node: Node): node is OmittedExpression {
return node.kind === SyntaxKind.OmittedExpression;
}
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
}
export function isAsExpression(node: Node): node is AsExpression {
return node.kind === SyntaxKind.AsExpression;
}
export function isNonNullExpression(node: Node): node is NonNullExpression {
return node.kind === SyntaxKind.NonNullExpression;
}
export function isNonNullChain(node: Node): node is NonNullChain {
return isNonNullExpression(node) && !!(node.flags & NodeFlags.OptionalChain);
}
export function isMetaProperty(node: Node): node is MetaProperty {
return node.kind === SyntaxKind.MetaProperty;
}
// Misc
export function isTemplateSpan(node: Node): node is TemplateSpan {
return node.kind === SyntaxKind.TemplateSpan;
}
export function isSemicolonClassElement(node: Node): node is SemicolonClassElement {
return node.kind === SyntaxKind.SemicolonClassElement;
}
// Block
export function isBlock(node: Node): node is Block {
return node.kind === SyntaxKind.Block;
}
export function isVariableStatement(node: Node): node is VariableStatement {
return node.kind === SyntaxKind.VariableStatement;
}
export function isEmptyStatement(node: Node): node is EmptyStatement {
return node.kind === SyntaxKind.EmptyStatement;
}
export function isExpressionStatement(node: Node): node is ExpressionStatement {
return node.kind === SyntaxKind.ExpressionStatement;
}
export function isIfStatement(node: Node): node is IfStatement {
return node.kind === SyntaxKind.IfStatement;
}
export function isDoStatement(node: Node): node is DoStatement {
return node.kind === SyntaxKind.DoStatement;
}
export function isWhileStatement(node: Node): node is WhileStatement {
return node.kind === SyntaxKind.WhileStatement;
}
export function isForStatement(node: Node): node is ForStatement {
return node.kind === SyntaxKind.ForStatement;
}
export function isForInStatement(node: Node): node is ForInStatement {
return node.kind === SyntaxKind.ForInStatement;
}
export function isForOfStatement(node: Node): node is ForOfStatement {
return node.kind === SyntaxKind.ForOfStatement;
}
export function isContinueStatement(node: Node): node is ContinueStatement {
return node.kind === SyntaxKind.ContinueStatement;
}
export function isBreakStatement(node: Node): node is BreakStatement {
return node.kind === SyntaxKind.BreakStatement;
}
export function isBreakOrContinueStatement(node: Node): node is BreakOrContinueStatement {
return node.kind === SyntaxKind.BreakStatement || node.kind === SyntaxKind.ContinueStatement;
}
export function isReturnStatement(node: Node): node is ReturnStatement {
return node.kind === SyntaxKind.ReturnStatement;
}
export function isWithStatement(node: Node): node is WithStatement {
return node.kind === SyntaxKind.WithStatement;
}
export function isSwitchStatement(node: Node): node is SwitchStatement {
return node.kind === SyntaxKind.SwitchStatement;
}
export function isLabeledStatement(node: Node): node is LabeledStatement {
return node.kind === SyntaxKind.LabeledStatement;
}
export function isThrowStatement(node: Node): node is ThrowStatement {
return node.kind === SyntaxKind.ThrowStatement;
}
export function isTryStatement(node: Node): node is TryStatement {
return node.kind === SyntaxKind.TryStatement;
}
export function isDebuggerStatement(node: Node): node is DebuggerStatement {
return node.kind === SyntaxKind.DebuggerStatement;
}
export function isVariableDeclaration(node: Node): node is VariableDeclaration {
return node.kind === SyntaxKind.VariableDeclaration;
}
export function isVariableDeclarationList(node: Node): node is VariableDeclarationList {
return node.kind === SyntaxKind.VariableDeclarationList;
}
export function isFunctionDeclaration(node: Node): node is FunctionDeclaration {
return node.kind === SyntaxKind.FunctionDeclaration;
}
export function isClassDeclaration(node: Node): node is ClassDeclaration {
return node.kind === SyntaxKind.ClassDeclaration;
}
export function isInterfaceDeclaration(node: Node): node is InterfaceDeclaration {
return node.kind === SyntaxKind.InterfaceDeclaration;
}
export function isTypeAliasDeclaration(node: Node): node is TypeAliasDeclaration {
return node.kind === SyntaxKind.TypeAliasDeclaration;
}
export function isEnumDeclaration(node: Node): node is EnumDeclaration {
return node.kind === SyntaxKind.EnumDeclaration;
}
export function isModuleDeclaration(node: Node): node is ModuleDeclaration {
return node.kind === SyntaxKind.ModuleDeclaration;
}
export function isModuleBlock(node: Node): node is ModuleBlock {
return node.kind === SyntaxKind.ModuleBlock;
}
export function isCaseBlock(node: Node): node is CaseBlock {
return node.kind === SyntaxKind.CaseBlock;
}
export function isNamespaceExportDeclaration(node: Node): node is NamespaceExportDeclaration {
return node.kind === SyntaxKind.NamespaceExportDeclaration;
}
export function isImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
return node.kind === SyntaxKind.ImportEqualsDeclaration;
}
export function isImportDeclaration(node: Node): node is ImportDeclaration {
return node.kind === SyntaxKind.ImportDeclaration;
}
export function isImportClause(node: Node): node is ImportClause {
return node.kind === SyntaxKind.ImportClause;
}
export function isNamespaceImport(node: Node): node is NamespaceImport {
return node.kind === SyntaxKind.NamespaceImport;
}
export function isNamespaceExport(node: Node): node is NamespaceExport {
return node.kind === SyntaxKind.NamespaceExport;
}
export function isNamedExportBindings(node: Node): node is NamedExportBindings {
return node.kind === SyntaxKind.NamespaceExport || node.kind === SyntaxKind.NamedExports;
}
export function isNamedImports(node: Node): node is NamedImports {
return node.kind === SyntaxKind.NamedImports;
}
export function isImportSpecifier(node: Node): node is ImportSpecifier {
return node.kind === SyntaxKind.ImportSpecifier;
}
export function isExportAssignment(node: Node): node is ExportAssignment {
return node.kind === SyntaxKind.ExportAssignment;
}
export function isExportDeclaration(node: Node): node is ExportDeclaration {
return node.kind === SyntaxKind.ExportDeclaration;
}
export function isNamedExports(node: Node): node is NamedExports {
return node.kind === SyntaxKind.NamedExports;
}
export function isExportSpecifier(node: Node): node is ExportSpecifier {
return node.kind === SyntaxKind.ExportSpecifier;
}
export function isMissingDeclaration(node: Node): node is MissingDeclaration {
return node.kind === SyntaxKind.MissingDeclaration;
}
// Module References
export function isExternalModuleReference(node: Node): node is ExternalModuleReference {
return node.kind === SyntaxKind.ExternalModuleReference;
}
// JSX
export function isJsxElement(node: Node): node is JsxElement {
return node.kind === SyntaxKind.JsxElement;
}
export function isJsxSelfClosingElement(node: Node): node is JsxSelfClosingElement {
return node.kind === SyntaxKind.JsxSelfClosingElement;
}
export function isJsxOpeningElement(node: Node): node is JsxOpeningElement {
return node.kind === SyntaxKind.JsxOpeningElement;
}
export function isJsxClosingElement(node: Node): node is JsxClosingElement {
return node.kind === SyntaxKind.JsxClosingElement;
}
export function isJsxFragment(node: Node): node is JsxFragment {
return node.kind === SyntaxKind.JsxFragment;
}
export function isJsxOpeningFragment(node: Node): node is JsxOpeningFragment {
return node.kind === SyntaxKind.JsxOpeningFragment;
}
export function isJsxClosingFragment(node: Node): node is JsxClosingFragment {
return node.kind === SyntaxKind.JsxClosingFragment;
}
export function isJsxAttribute(node: Node): node is JsxAttribute {
return node.kind === SyntaxKind.JsxAttribute;
}
export function isJsxAttributes(node: Node): node is JsxAttributes {
return node.kind === SyntaxKind.JsxAttributes;
}
export function isJsxSpreadAttribute(node: Node): node is JsxSpreadAttribute {
return node.kind === SyntaxKind.JsxSpreadAttribute;
}
export function isJsxExpression(node: Node): node is JsxExpression {
return node.kind === SyntaxKind.JsxExpression;
}
// Clauses
export function isCaseClause(node: Node): node is CaseClause {
return node.kind === SyntaxKind.CaseClause;
}
export function isDefaultClause(node: Node): node is DefaultClause {
return node.kind === SyntaxKind.DefaultClause;
}
export function isHeritageClause(node: Node): node is HeritageClause {
return node.kind === SyntaxKind.HeritageClause;
}
export function isCatchClause(node: Node): node is CatchClause {
return node.kind === SyntaxKind.CatchClause;
}
// Property assignments
export function isPropertyAssignment(node: Node): node is PropertyAssignment {
return node.kind === SyntaxKind.PropertyAssignment;
}
export function isShorthandPropertyAssignment(node: Node): node is ShorthandPropertyAssignment {
return node.kind === SyntaxKind.ShorthandPropertyAssignment;
}
export function isSpreadAssignment(node: Node): node is SpreadAssignment {
return node.kind === SyntaxKind.SpreadAssignment;
}
// Enum
export function isEnumMember(node: Node): node is EnumMember {
return node.kind === SyntaxKind.EnumMember;
}
// Top-level nodes
export function isSourceFile(node: Node): node is SourceFile {
return node.kind === SyntaxKind.SourceFile;
}
export function isBundle(node: Node): node is Bundle {
return node.kind === SyntaxKind.Bundle;
}
export function isUnparsedSource(node: Node): node is UnparsedSource {
return node.kind === SyntaxKind.UnparsedSource;
}
export function isUnparsedPrepend(node: Node): node is UnparsedPrepend {
return node.kind === SyntaxKind.UnparsedPrepend;
}
export function isUnparsedTextLike(node: Node): node is UnparsedTextLike {
switch (node.kind) {
case SyntaxKind.UnparsedText:
@ -1599,124 +993,10 @@ namespace ts {
node.kind === SyntaxKind.UnparsedSyntheticReference;
}
// JSDoc
export function isJSDocTypeExpression(node: Node): node is JSDocTypeExpression {
return node.kind === SyntaxKind.JSDocTypeExpression;
}
export function isJSDocAllType(node: Node): node is JSDocAllType {
return node.kind === SyntaxKind.JSDocAllType;
}
export function isJSDocUnknownType(node: Node): node is JSDocUnknownType {
return node.kind === SyntaxKind.JSDocUnknownType;
}
export function isJSDocNullableType(node: Node): node is JSDocNullableType {
return node.kind === SyntaxKind.JSDocNullableType;
}
export function isJSDocNonNullableType(node: Node): node is JSDocNonNullableType {
return node.kind === SyntaxKind.JSDocNonNullableType;
}
export function isJSDocOptionalType(node: Node): node is JSDocOptionalType {
return node.kind === SyntaxKind.JSDocOptionalType;
}
export function isJSDocFunctionType(node: Node): node is JSDocFunctionType {
return node.kind === SyntaxKind.JSDocFunctionType;
}
export function isJSDocVariadicType(node: Node): node is JSDocVariadicType {
return node.kind === SyntaxKind.JSDocVariadicType;
}
export function isJSDoc(node: Node): node is JSDoc {
return node.kind === SyntaxKind.JSDocComment;
}
export function isJSDocAuthorTag(node: Node): node is JSDocAuthorTag {
return node.kind === SyntaxKind.JSDocAuthorTag;
}
export function isJSDocAugmentsTag(node: Node): node is JSDocAugmentsTag {
return node.kind === SyntaxKind.JSDocAugmentsTag;
}
export function isJSDocImplementsTag(node: Node): node is JSDocImplementsTag {
return node.kind === SyntaxKind.JSDocImplementsTag;
}
export function isJSDocClassTag(node: Node): node is JSDocClassTag {
return node.kind === SyntaxKind.JSDocClassTag;
}
export function isJSDocPublicTag(node: Node): node is JSDocPublicTag {
return node.kind === SyntaxKind.JSDocPublicTag;
}
export function isJSDocPrivateTag(node: Node): node is JSDocPrivateTag {
return node.kind === SyntaxKind.JSDocPrivateTag;
}
export function isJSDocProtectedTag(node: Node): node is JSDocProtectedTag {
return node.kind === SyntaxKind.JSDocProtectedTag;
}
export function isJSDocReadonlyTag(node: Node): node is JSDocReadonlyTag {
return node.kind === SyntaxKind.JSDocReadonlyTag;
}
export function isJSDocEnumTag(node: Node): node is JSDocEnumTag {
return node.kind === SyntaxKind.JSDocEnumTag;
}
export function isJSDocThisTag(node: Node): node is JSDocThisTag {
return node.kind === SyntaxKind.JSDocThisTag;
}
export function isJSDocParameterTag(node: Node): node is JSDocParameterTag {
return node.kind === SyntaxKind.JSDocParameterTag;
}
export function isJSDocReturnTag(node: Node): node is JSDocReturnTag {
return node.kind === SyntaxKind.JSDocReturnTag;
}
export function isJSDocTypeTag(node: Node): node is JSDocTypeTag {
return node.kind === SyntaxKind.JSDocTypeTag;
}
export function isJSDocTemplateTag(node: Node): node is JSDocTemplateTag {
return node.kind === SyntaxKind.JSDocTemplateTag;
}
export function isJSDocTypedefTag(node: Node): node is JSDocTypedefTag {
return node.kind === SyntaxKind.JSDocTypedefTag;
}
export function isJSDocPropertyTag(node: Node): node is JSDocPropertyTag {
return node.kind === SyntaxKind.JSDocPropertyTag;
}
export function isJSDocPropertyLikeTag(node: Node): node is JSDocPropertyLikeTag {
return node.kind === SyntaxKind.JSDocPropertyTag || node.kind === SyntaxKind.JSDocParameterTag;
}
export function isJSDocTypeLiteral(node: Node): node is JSDocTypeLiteral {
return node.kind === SyntaxKind.JSDocTypeLiteral;
}
export function isJSDocCallbackTag(node: Node): node is JSDocCallbackTag {
return node.kind === SyntaxKind.JSDocCallbackTag;
}
export function isJSDocSignature(node: Node): node is JSDocSignature {
return node.kind === SyntaxKind.JSDocSignature;
}
// #endregion
// #region
@ -1724,11 +1004,6 @@ namespace ts {
//
// All node tests in the following list should *not* reference parent pointers so that
// they may be used with transformations.
/* @internal */
export function isSyntaxList(n: Node): n is SyntaxList {
return n.kind === SyntaxKind.SyntaxList;
}
/* @internal */
export function isNode(node: Node) {
return isNodeKind(node.kind);
@ -1758,7 +1033,7 @@ namespace ts {
// Literals
/* @internal */
export function isLiteralKind(kind: SyntaxKind): boolean {
export function isLiteralKind(kind: SyntaxKind): kind is LiteralToken["kind"] {
return SyntaxKind.FirstLiteralToken <= kind && kind <= SyntaxKind.LastLiteralToken;
}
@ -1769,11 +1044,10 @@ namespace ts {
// Pseudo-literals
/* @internal */
export function isTemplateLiteralKind(kind: SyntaxKind): boolean {
export function isTemplateLiteralKind(kind: SyntaxKind): kind is TemplateLiteralToken["kind"] {
return SyntaxKind.FirstTemplateToken <= kind && kind <= SyntaxKind.LastTemplateToken;
}
export type TemplateLiteralToken = NoSubstitutionTemplateLiteral | TemplateHead | TemplateMiddle | TemplateTail;
export function isTemplateLiteralToken(node: Node): node is TemplateLiteralToken {
return isTemplateLiteralKind(node.kind);
}
@ -2234,21 +1508,6 @@ namespace ts {
|| kind === SyntaxKind.AsExpression;
}
/* @internal */
export function isPartiallyEmittedExpression(node: Node): node is PartiallyEmittedExpression {
return node.kind === SyntaxKind.PartiallyEmittedExpression;
}
/* @internal */
export function isNotEmittedStatement(node: Node): node is NotEmittedStatement {
return node.kind === SyntaxKind.NotEmittedStatement;
}
/* @internal */
export function isSyntheticReference(node: Node): node is SyntheticReferenceExpression {
return node.kind === SyntaxKind.SyntheticReferenceExpression;
}
/* @internal */
export function isNotEmittedOrPartiallyEmittedNode(node: Node): node is NotEmittedStatement | PartiallyEmittedExpression {
return isNotEmittedStatement(node)
@ -2469,6 +1728,17 @@ namespace ts {
return !isFunctionBlock(node);
}
/**
* NOTE: This is similar to `isStatement` but does not access parent pointers.
*/
/* @internal */
export function isStatementOrBlock(node: Node): node is Statement | Block {
const kind = node.kind;
return isStatementKindButNotDeclarationKind(kind)
|| isDeclarationStatementKind(kind)
|| kind === SyntaxKind.Block;
}
// Module references
/* @internal */

View File

@ -1,706 +0,0 @@
/* @internal */
namespace ts {
function reduceNode<T>(node: Node | undefined, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
}
function reduceNodeArray<T>(nodes: NodeArray<Node> | undefined, f: (memo: T, nodes: NodeArray<Node>) => T, initial: T) {
return nodes ? f(initial, nodes) : initial;
}
/**
* Similar to `reduceLeft`, performs a reduction against each child of a node.
* NOTE: Unlike `forEachChild`, this does *not* visit every node.
*
* @param node The node containing the children to reduce.
* @param initial The initial value to supply to the reduction.
* @param f The callback function
*/
export function reduceEachChild<T>(node: Node | undefined, initial: T, cbNode: (memo: T, node: Node) => T, cbNodeArray?: (memo: T, nodes: NodeArray<Node>) => T): T {
if (node === undefined) {
return initial;
}
const reduceNodes: (nodes: NodeArray<Node> | undefined, f: ((memo: T, node: Node) => T) | ((memo: T, node: NodeArray<Node>) => T), initial: T) => T = cbNodeArray ? reduceNodeArray : reduceLeft;
const cbNodes = cbNodeArray || cbNode;
const kind = node.kind;
// No need to visit nodes with no children.
if ((kind > SyntaxKind.FirstToken && kind <= SyntaxKind.LastToken)) {
return initial;
}
// We do not yet support types.
if ((kind >= SyntaxKind.TypePredicate && kind <= SyntaxKind.LiteralType)) {
return initial;
}
let result = initial;
switch (node.kind) {
// Leaf nodes
case SyntaxKind.SemicolonClassElement:
case SyntaxKind.EmptyStatement:
case SyntaxKind.OmittedExpression:
case SyntaxKind.DebuggerStatement:
case SyntaxKind.NotEmittedStatement:
// No need to visit nodes with no children.
break;
// Names
case SyntaxKind.QualifiedName:
result = reduceNode((<QualifiedName>node).left, cbNode, result);
result = reduceNode((<QualifiedName>node).right, cbNode, result);
break;
case SyntaxKind.ComputedPropertyName:
result = reduceNode((<ComputedPropertyName>node).expression, cbNode, result);
break;
// Signature elements
case SyntaxKind.Parameter:
result = reduceNodes((<ParameterDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ParameterDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ParameterDeclaration>node).name, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).type, cbNode, result);
result = reduceNode((<ParameterDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.Decorator:
result = reduceNode((<Decorator>node).expression, cbNode, result);
break;
// Type member
case SyntaxKind.PropertySignature:
result = reduceNodes((<PropertySignature>node).modifiers, cbNodes, result);
result = reduceNode((<PropertySignature>node).name, cbNode, result);
result = reduceNode((<PropertySignature>node).questionToken, cbNode, result);
result = reduceNode((<PropertySignature>node).type, cbNode, result);
result = reduceNode((<PropertySignature>node).initializer, cbNode, result);
break;
case SyntaxKind.PropertyDeclaration:
result = reduceNodes((<PropertyDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<PropertyDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<PropertyDeclaration>node).name, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).type, cbNode, result);
result = reduceNode((<PropertyDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.MethodDeclaration:
result = reduceNodes((<MethodDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).name, cbNode, result);
result = reduceNodes((<MethodDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<MethodDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<MethodDeclaration>node).type, cbNode, result);
result = reduceNode((<MethodDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.Constructor:
result = reduceNodes((<ConstructorDeclaration>node).modifiers, cbNodes, result);
result = reduceNodes((<ConstructorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<ConstructorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.GetAccessor:
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).type, cbNode, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.SetAccessor:
result = reduceNodes((<GetAccessorDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<GetAccessorDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).name, cbNode, result);
result = reduceNodes((<GetAccessorDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<GetAccessorDeclaration>node).body, cbNode, result);
break;
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
result = reduceNodes((<BindingPattern>node).elements, cbNodes, result);
break;
case SyntaxKind.BindingElement:
result = reduceNode((<BindingElement>node).propertyName, cbNode, result);
result = reduceNode((<BindingElement>node).name, cbNode, result);
result = reduceNode((<BindingElement>node).initializer, cbNode, result);
break;
// Expression
case SyntaxKind.ArrayLiteralExpression:
result = reduceNodes((<ArrayLiteralExpression>node).elements, cbNodes, result);
break;
case SyntaxKind.ObjectLiteralExpression:
result = reduceNodes((<ObjectLiteralExpression>node).properties, cbNodes, result);
break;
case SyntaxKind.PropertyAccessExpression:
result = reduceNode((<PropertyAccessExpression>node).expression, cbNode, result);
result = reduceNode((<PropertyAccessExpression>node).name, cbNode, result);
break;
case SyntaxKind.ElementAccessExpression:
result = reduceNode((<ElementAccessExpression>node).expression, cbNode, result);
result = reduceNode((<ElementAccessExpression>node).argumentExpression, cbNode, result);
break;
case SyntaxKind.CallExpression:
result = reduceNode((<CallExpression>node).expression, cbNode, result);
result = reduceNodes((<CallExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<CallExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.NewExpression:
result = reduceNode((<NewExpression>node).expression, cbNode, result);
result = reduceNodes((<NewExpression>node).typeArguments, cbNodes, result);
result = reduceNodes((<NewExpression>node).arguments, cbNodes, result);
break;
case SyntaxKind.TaggedTemplateExpression:
result = reduceNode((<TaggedTemplateExpression>node).tag, cbNode, result);
result = reduceNodes((<TaggedTemplateExpression>node).typeArguments, cbNodes, result);
result = reduceNode((<TaggedTemplateExpression>node).template, cbNode, result);
break;
case SyntaxKind.TypeAssertionExpression:
result = reduceNode((<TypeAssertion>node).type, cbNode, result);
result = reduceNode((<TypeAssertion>node).expression, cbNode, result);
break;
case SyntaxKind.FunctionExpression:
result = reduceNodes((<FunctionExpression>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionExpression>node).name, cbNode, result);
result = reduceNodes((<FunctionExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionExpression>node).parameters, cbNodes, result);
result = reduceNode((<FunctionExpression>node).type, cbNode, result);
result = reduceNode((<FunctionExpression>node).body, cbNode, result);
break;
case SyntaxKind.ArrowFunction:
result = reduceNodes((<ArrowFunction>node).modifiers, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).typeParameters, cbNodes, result);
result = reduceNodes((<ArrowFunction>node).parameters, cbNodes, result);
result = reduceNode((<ArrowFunction>node).type, cbNode, result);
result = reduceNode((<ArrowFunction>node).body, cbNode, result);
break;
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.DeleteExpression:
case SyntaxKind.TypeOfExpression:
case SyntaxKind.VoidExpression:
case SyntaxKind.AwaitExpression:
case SyntaxKind.YieldExpression:
case SyntaxKind.SpreadElement:
case SyntaxKind.NonNullExpression:
result = reduceNode((<ParenthesizedExpression | DeleteExpression | TypeOfExpression | VoidExpression | AwaitExpression | YieldExpression | SpreadElement | NonNullExpression>node).expression, cbNode, result);
break;
case SyntaxKind.PrefixUnaryExpression:
case SyntaxKind.PostfixUnaryExpression:
result = reduceNode((<PrefixUnaryExpression | PostfixUnaryExpression>node).operand, cbNode, result);
break;
case SyntaxKind.BinaryExpression:
result = reduceNode((<BinaryExpression>node).left, cbNode, result);
result = reduceNode((<BinaryExpression>node).right, cbNode, result);
break;
case SyntaxKind.ConditionalExpression:
result = reduceNode((<ConditionalExpression>node).condition, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenTrue, cbNode, result);
result = reduceNode((<ConditionalExpression>node).whenFalse, cbNode, result);
break;
case SyntaxKind.TemplateExpression:
result = reduceNode((<TemplateExpression>node).head, cbNode, result);
result = reduceNodes((<TemplateExpression>node).templateSpans, cbNodes, result);
break;
case SyntaxKind.ClassExpression:
result = reduceNodes((<ClassExpression>node).modifiers, cbNodes, result);
result = reduceNode((<ClassExpression>node).name, cbNode, result);
result = reduceNodes((<ClassExpression>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassExpression>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassExpression>node).members, cbNodes, result);
break;
case SyntaxKind.ExpressionWithTypeArguments:
result = reduceNode((<ExpressionWithTypeArguments>node).expression, cbNode, result);
result = reduceNodes((<ExpressionWithTypeArguments>node).typeArguments, cbNodes, result);
break;
case SyntaxKind.AsExpression:
result = reduceNode((<AsExpression>node).expression, cbNode, result);
result = reduceNode((<AsExpression>node).type, cbNode, result);
break;
// Misc
case SyntaxKind.TemplateSpan:
result = reduceNode((<TemplateSpan>node).expression, cbNode, result);
result = reduceNode((<TemplateSpan>node).literal, cbNode, result);
break;
// Element
case SyntaxKind.Block:
result = reduceNodes((<Block>node).statements, cbNodes, result);
break;
case SyntaxKind.VariableStatement:
result = reduceNodes((<VariableStatement>node).modifiers, cbNodes, result);
result = reduceNode((<VariableStatement>node).declarationList, cbNode, result);
break;
case SyntaxKind.ExpressionStatement:
result = reduceNode((<ExpressionStatement>node).expression, cbNode, result);
break;
case SyntaxKind.IfStatement:
result = reduceNode((<IfStatement>node).expression, cbNode, result);
result = reduceNode((<IfStatement>node).thenStatement, cbNode, result);
result = reduceNode((<IfStatement>node).elseStatement, cbNode, result);
break;
case SyntaxKind.DoStatement:
result = reduceNode((<DoStatement>node).statement, cbNode, result);
result = reduceNode((<DoStatement>node).expression, cbNode, result);
break;
case SyntaxKind.WhileStatement:
case SyntaxKind.WithStatement:
result = reduceNode((<WhileStatement | WithStatement>node).expression, cbNode, result);
result = reduceNode((<WhileStatement | WithStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForStatement:
result = reduceNode((<ForStatement>node).initializer, cbNode, result);
result = reduceNode((<ForStatement>node).condition, cbNode, result);
result = reduceNode((<ForStatement>node).incrementor, cbNode, result);
result = reduceNode((<ForStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ForInStatement:
case SyntaxKind.ForOfStatement:
result = reduceNode((<ForInOrOfStatement>node).initializer, cbNode, result);
result = reduceNode((<ForInOrOfStatement>node).expression, cbNode, result);
result = reduceNode((<ForInOrOfStatement>node).statement, cbNode, result);
break;
case SyntaxKind.ReturnStatement:
case SyntaxKind.ThrowStatement:
result = reduceNode((<ReturnStatement>node).expression, cbNode, result);
break;
case SyntaxKind.SwitchStatement:
result = reduceNode((<SwitchStatement>node).expression, cbNode, result);
result = reduceNode((<SwitchStatement>node).caseBlock, cbNode, result);
break;
case SyntaxKind.LabeledStatement:
result = reduceNode((<LabeledStatement>node).label, cbNode, result);
result = reduceNode((<LabeledStatement>node).statement, cbNode, result);
break;
case SyntaxKind.TryStatement:
result = reduceNode((<TryStatement>node).tryBlock, cbNode, result);
result = reduceNode((<TryStatement>node).catchClause, cbNode, result);
result = reduceNode((<TryStatement>node).finallyBlock, cbNode, result);
break;
case SyntaxKind.VariableDeclaration:
result = reduceNode((<VariableDeclaration>node).name, cbNode, result);
result = reduceNode((<VariableDeclaration>node).type, cbNode, result);
result = reduceNode((<VariableDeclaration>node).initializer, cbNode, result);
break;
case SyntaxKind.VariableDeclarationList:
result = reduceNodes((<VariableDeclarationList>node).declarations, cbNodes, result);
break;
case SyntaxKind.FunctionDeclaration:
result = reduceNodes((<FunctionDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).name, cbNode, result);
result = reduceNodes((<FunctionDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<FunctionDeclaration>node).parameters, cbNodes, result);
result = reduceNode((<FunctionDeclaration>node).type, cbNode, result);
result = reduceNode((<FunctionDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ClassDeclaration:
result = reduceNodes((<ClassDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ClassDeclaration>node).name, cbNode, result);
result = reduceNodes((<ClassDeclaration>node).typeParameters, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).heritageClauses, cbNodes, result);
result = reduceNodes((<ClassDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.EnumDeclaration:
result = reduceNodes((<EnumDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<EnumDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<EnumDeclaration>node).name, cbNode, result);
result = reduceNodes((<EnumDeclaration>node).members, cbNodes, result);
break;
case SyntaxKind.ModuleDeclaration:
result = reduceNodes((<ModuleDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ModuleDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ModuleDeclaration>node).name, cbNode, result);
result = reduceNode((<ModuleDeclaration>node).body, cbNode, result);
break;
case SyntaxKind.ModuleBlock:
result = reduceNodes((<ModuleBlock>node).statements, cbNodes, result);
break;
case SyntaxKind.CaseBlock:
result = reduceNodes((<CaseBlock>node).clauses, cbNodes, result);
break;
case SyntaxKind.ImportEqualsDeclaration:
result = reduceNodes((<ImportEqualsDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportEqualsDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportEqualsDeclaration>node).name, cbNode, result);
result = reduceNode((<ImportEqualsDeclaration>node).moduleReference, cbNode, result);
break;
case SyntaxKind.ImportDeclaration:
result = reduceNodes((<ImportDeclaration>node).decorators, cbNodes, result);
result = reduceNodes((<ImportDeclaration>node).modifiers, cbNodes, result);
result = reduceNode((<ImportDeclaration>node).importClause, cbNode, result);
result = reduceNode((<ImportDeclaration>node).moduleSpecifier, cbNode, result);
break;
case SyntaxKind.ImportClause:
result = reduceNode((<ImportClause>node).name, cbNode, result);
result = reduceNode((<ImportClause>node).namedBindings, cbNode, result);
break;
case SyntaxKind.NamespaceImport:
result = reduceNode((<NamespaceImport>node).name, cbNode, result);
break;
case SyntaxKind.NamespaceExport:
result = reduceNode((<NamespaceExport>node).name, cbNode, result);
break;
case SyntaxKind.NamedImports:
case SyntaxKind.NamedExports:
result = reduceNodes((<NamedImports | NamedExports>node).elements, cbNodes, result);
break;
case SyntaxKind.ImportSpecifier:
case SyntaxKind.ExportSpecifier:
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).propertyName, cbNode, result);
result = reduceNode((<ImportSpecifier | ExportSpecifier>node).name, cbNode, result);
break;
case SyntaxKind.ExportAssignment:
result = reduceLeft((<ExportAssignment>node).decorators, cbNode, result);
result = reduceLeft((<ExportAssignment>node).modifiers, cbNode, result);
result = reduceNode((<ExportAssignment>node).expression, cbNode, result);
break;
case SyntaxKind.ExportDeclaration:
result = reduceLeft((<ExportDeclaration>node).decorators, cbNode, result);
result = reduceLeft((<ExportDeclaration>node).modifiers, cbNode, result);
result = reduceNode((<ExportDeclaration>node).exportClause, cbNode, result);
result = reduceNode((<ExportDeclaration>node).moduleSpecifier, cbNode, result);
break;
// Module references
case SyntaxKind.ExternalModuleReference:
result = reduceNode((<ExternalModuleReference>node).expression, cbNode, result);
break;
// JSX
case SyntaxKind.JsxElement:
result = reduceNode((<JsxElement>node).openingElement, cbNode, result);
result = reduceLeft((<JsxElement>node).children, cbNode, result);
result = reduceNode((<JsxElement>node).closingElement, cbNode, result);
break;
case SyntaxKind.JsxFragment:
result = reduceNode((<JsxFragment>node).openingFragment, cbNode, result);
result = reduceLeft((<JsxFragment>node).children, cbNode, result);
result = reduceNode((<JsxFragment>node).closingFragment, cbNode, result);
break;
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).tagName, cbNode, result);
result = reduceNodes((<JsxSelfClosingElement | JsxOpeningElement>node).typeArguments, cbNode, result);
result = reduceNode((<JsxSelfClosingElement | JsxOpeningElement>node).attributes, cbNode, result);
break;
case SyntaxKind.JsxAttributes:
result = reduceNodes((<JsxAttributes>node).properties, cbNodes, result);
break;
case SyntaxKind.JsxClosingElement:
result = reduceNode((<JsxClosingElement>node).tagName, cbNode, result);
break;
case SyntaxKind.JsxAttribute:
result = reduceNode((<JsxAttribute>node).name, cbNode, result);
result = reduceNode((<JsxAttribute>node).initializer, cbNode, result);
break;
case SyntaxKind.JsxSpreadAttribute:
result = reduceNode((<JsxSpreadAttribute>node).expression, cbNode, result);
break;
case SyntaxKind.JsxExpression:
result = reduceNode((<JsxExpression>node).expression, cbNode, result);
break;
// Clauses
case SyntaxKind.CaseClause:
result = reduceNode((<CaseClause>node).expression, cbNode, result);
// falls through
case SyntaxKind.DefaultClause:
result = reduceNodes((<CaseClause | DefaultClause>node).statements, cbNodes, result);
break;
case SyntaxKind.HeritageClause:
result = reduceNodes((<HeritageClause>node).types, cbNodes, result);
break;
case SyntaxKind.CatchClause:
result = reduceNode((<CatchClause>node).variableDeclaration, cbNode, result);
result = reduceNode((<CatchClause>node).block, cbNode, result);
break;
// Property assignments
case SyntaxKind.PropertyAssignment:
result = reduceNode((<PropertyAssignment>node).name, cbNode, result);
result = reduceNode((<PropertyAssignment>node).initializer, cbNode, result);
break;
case SyntaxKind.ShorthandPropertyAssignment:
result = reduceNode((<ShorthandPropertyAssignment>node).name, cbNode, result);
result = reduceNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, cbNode, result);
break;
case SyntaxKind.SpreadAssignment:
result = reduceNode((<SpreadAssignment>node).expression, cbNode, result);
break;
// Enum
case SyntaxKind.EnumMember:
result = reduceNode((<EnumMember>node).name, cbNode, result);
result = reduceNode((<EnumMember>node).initializer, cbNode, result);
break;
// Top-level nodes
case SyntaxKind.SourceFile:
result = reduceNodes((<SourceFile>node).statements, cbNodes, result);
break;
// Transformation nodes
case SyntaxKind.PartiallyEmittedExpression:
result = reduceNode((<PartiallyEmittedExpression>node).expression, cbNode, result);
break;
case SyntaxKind.CommaListExpression:
result = reduceNodes((<CommaListExpression>node).elements, cbNodes, result);
break;
default:
break;
}
return result;
}
function findSpanEnd<T>(array: readonly T[], test: (value: T) => boolean, start: number) {
let i = start;
while (i < array.length && test(array[i])) {
i++;
}
return i;
}
/**
* Merges generated lexical declarations into a new statement list.
*/
export function mergeLexicalEnvironment(statements: NodeArray<Statement>, declarations: readonly Statement[] | undefined): NodeArray<Statement>;
/**
* Appends generated lexical declarations to an array of statements.
*/
export function mergeLexicalEnvironment(statements: Statement[], declarations: readonly Statement[] | undefined): Statement[];
export function mergeLexicalEnvironment(statements: Statement[] | NodeArray<Statement>, declarations: readonly Statement[] | undefined) {
if (!some(declarations)) {
return statements;
}
// When we merge new lexical statements into an existing statement list, we merge them in the following manner:
//
// Given:
//
// | Left | Right |
// |------------------------------------|-------------------------------------|
// | [standard prologues (left)] | [standard prologues (right)] |
// | [hoisted functions (left)] | [hoisted functions (right)] |
// | [hoisted variables (left)] | [hoisted variables (right)] |
// | [lexical init statements (left)] | [lexical init statements (right)] |
// | [other statements (left)] | |
//
// The resulting statement list will be:
//
// | Result |
// |-------------------------------------|
// | [standard prologues (right)] |
// | [standard prologues (left)] |
// | [hoisted functions (right)] |
// | [hoisted functions (left)] |
// | [hoisted variables (right)] |
// | [hoisted variables (left)] |
// | [lexical init statements (right)] |
// | [lexical init statements (left)] |
// | [other statements (left)] |
//
// NOTE: It is expected that new lexical init statements must be evaluated before existing lexical init statements,
// as the prior transformation may depend on the evaluation of the lexical init statements to be in the correct state.
// find standard prologues on left in the following order: standard directives, hoisted functions, hoisted variables, other custom
const leftStandardPrologueEnd = findSpanEnd(statements, isPrologueDirective, 0);
const leftHoistedFunctionsEnd = findSpanEnd(statements, isHoistedFunction, leftStandardPrologueEnd);
const leftHoistedVariablesEnd = findSpanEnd(statements, isHoistedVariableStatement, leftHoistedFunctionsEnd);
// find standard prologues on right in the following order: standard directives, hoisted functions, hoisted variables, other custom
const rightStandardPrologueEnd = findSpanEnd(declarations, isPrologueDirective, 0);
const rightHoistedFunctionsEnd = findSpanEnd(declarations, isHoistedFunction, rightStandardPrologueEnd);
const rightHoistedVariablesEnd = findSpanEnd(declarations, isHoistedVariableStatement, rightHoistedFunctionsEnd);
const rightCustomPrologueEnd = findSpanEnd(declarations, isCustomPrologue, rightHoistedVariablesEnd);
Debug.assert(rightCustomPrologueEnd === declarations.length, "Expected declarations to be valid standard or custom prologues");
// splice prologues from the right into the left. We do this in reverse order
// so that we don't need to recompute the index on the left when we insert items.
const left = isNodeArray(statements) ? statements.slice() : statements;
// splice other custom prologues from right into left
if (rightCustomPrologueEnd > rightHoistedVariablesEnd) {
left.splice(leftHoistedVariablesEnd, 0, ...declarations.slice(rightHoistedVariablesEnd, rightCustomPrologueEnd));
}
// splice hoisted variables from right into left
if (rightHoistedVariablesEnd > rightHoistedFunctionsEnd) {
left.splice(leftHoistedFunctionsEnd, 0, ...declarations.slice(rightHoistedFunctionsEnd, rightHoistedVariablesEnd));
}
// splice hoisted functions from right into left
if (rightHoistedFunctionsEnd > rightStandardPrologueEnd) {
left.splice(leftStandardPrologueEnd, 0, ...declarations.slice(rightStandardPrologueEnd, rightHoistedFunctionsEnd));
}
// splice standard prologues from right into left (that are not already in left)
if (rightStandardPrologueEnd > 0) {
if (leftStandardPrologueEnd === 0) {
left.splice(0, 0, ...declarations.slice(0, rightStandardPrologueEnd));
}
else {
const leftPrologues = createMap<boolean>();
for (let i = 0; i < leftStandardPrologueEnd; i++) {
const leftPrologue = statements[i] as PrologueDirective;
leftPrologues.set(leftPrologue.expression.text, true);
}
for (let i = rightStandardPrologueEnd - 1; i >= 0; i--) {
const rightPrologue = declarations[i] as PrologueDirective;
if (!leftPrologues.has(rightPrologue.expression.text)) {
left.unshift(rightPrologue);
}
}
}
}
if (isNodeArray(statements)) {
return setTextRange(createNodeArray(left, statements.hasTrailingComma), statements);
}
return statements;
}
/**
* Lifts a NodeArray containing only Statement nodes to a block.
*
* @param nodes The NodeArray.
*/
export function liftToBlock(nodes: readonly Node[]): Statement {
Debug.assert(every(nodes, isStatement), "Cannot lift nodes to a Block.");
return <Statement>singleOrUndefined(nodes) || createBlock(<NodeArray<Statement>>nodes);
}
/**
* Aggregates the TransformFlags for a Node and its subtree.
*/
export function aggregateTransformFlags<T extends Node>(node: T): T {
aggregateTransformFlagsForNode(node);
return node;
}
/**
* Aggregates the TransformFlags for a Node and its subtree. The flags for the subtree are
* computed first, then the transform flags for the current node are computed from the subtree
* flags and the state of the current node. Finally, the transform flags of the node are
* returned, excluding any flags that should not be included in its parent node's subtree
* flags.
*/
function aggregateTransformFlagsForNode(node: Node): TransformFlags {
if (node === undefined) {
return TransformFlags.None;
}
if (node.transformFlags & TransformFlags.HasComputedFlags) {
return node.transformFlags & ~getTransformFlagsSubtreeExclusions(node.kind);
}
const subtreeFlags = aggregateTransformFlagsForSubtree(node);
return computeTransformFlagsForNode(node, subtreeFlags);
}
function aggregateTransformFlagsForNodeArray(nodes: NodeArray<Node>): TransformFlags {
if (nodes === undefined) {
return TransformFlags.None;
}
let subtreeFlags = TransformFlags.None;
let nodeArrayFlags = TransformFlags.None;
for (const node of nodes) {
subtreeFlags |= aggregateTransformFlagsForNode(node);
nodeArrayFlags |= node.transformFlags & ~TransformFlags.HasComputedFlags;
}
nodes.transformFlags = nodeArrayFlags | TransformFlags.HasComputedFlags;
return subtreeFlags;
}
/**
* Aggregates the transform flags for the subtree of a node.
*/
function aggregateTransformFlagsForSubtree(node: Node): TransformFlags {
// We do not transform ambient declarations or types, so there is no need to
// recursively aggregate transform flags.
if (hasSyntacticModifier(node, ModifierFlags.Ambient) || (isTypeNode(node) && node.kind !== SyntaxKind.ExpressionWithTypeArguments)) {
return TransformFlags.None;
}
// Aggregate the transform flags of each child.
return reduceEachChild(node, TransformFlags.None, aggregateTransformFlagsForChildNode, aggregateTransformFlagsForChildNodes);
}
/**
* Aggregates the TransformFlags of a child node with the TransformFlags of its
* siblings.
*/
function aggregateTransformFlagsForChildNode(transformFlags: TransformFlags, node: Node): TransformFlags {
return transformFlags | aggregateTransformFlagsForNode(node);
}
function aggregateTransformFlagsForChildNodes(transformFlags: TransformFlags, nodes: NodeArray<Node>): TransformFlags {
return transformFlags | aggregateTransformFlagsForNodeArray(nodes);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -3,6 +3,7 @@
// this will work in the browser via browserify
declare var assert: typeof _chai.assert;
declare var expect: typeof _chai.expect;
var _chai: typeof import("chai") = require("chai");
globalThis.assert = _chai.assert;
{
@ -28,6 +29,7 @@ globalThis.assert = _chai.assert;
}
};
}
globalThis.expect = _chai.expect;
/* eslint-enable no-var */
// empty ts namespace so this file is included in the `ts.ts` namespace file generated by the module swapover
// This way, everything that ends up importing `ts` downstream also imports this file and picks up its augmentation

View File

@ -1989,9 +1989,6 @@ namespace ts.server {
const configFileContent = tryReadFile(configFilename, fileName => this.host.readFile(fileName));
const result = parseJsonText(configFilename, isString(configFileContent) ? configFileContent : "");
if (!result.endOfFileToken) {
result.endOfFileToken = <EndOfFileToken>{ kind: SyntaxKind.EndOfFileToken };
}
const configFileErrors = result.parseDiagnostics as Diagnostic[];
if (!isString(configFileContent)) configFileErrors.push(configFileContent);
const parsedCommandLine = parseJsonSourceFileConfigFileContent(

View File

@ -685,7 +685,7 @@ namespace ts {
const docCommentAndDiagnostics = parseIsolatedJSDocComment(sourceFile.text, start, width);
if (docCommentAndDiagnostics && docCommentAndDiagnostics.jsDoc) {
// TODO: This should be predicated on `token["kind"]` being compatible with `HasJSDoc["kind"]`
docCommentAndDiagnostics.jsDoc.parent = token as HasJSDoc;
setParent(docCommentAndDiagnostics.jsDoc, token as HasJSDoc);
classifyJSDocComment(docCommentAndDiagnostics.jsDoc);
return;
}

View File

@ -14,10 +14,10 @@ namespace ts.codefix {
function makeChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, pos: number) {
const token = getTokenAtPosition(sourceFile, pos);
const assertion = Debug.checkDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertion(n)), "Expected to find an assertion expression");
const assertion = Debug.checkDefined(findAncestor(token, (n): n is AsExpression | TypeAssertion => isAsExpression(n) || isTypeAssertionExpression(n)), "Expected to find an assertion expression");
const replacement = isAsExpression(assertion)
? createAsExpression(assertion.expression, createKeywordTypeNode(SyntaxKind.UnknownKeyword))
: createTypeAssertion(createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression);
? factory.createAsExpression(assertion.expression, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword))
: factory.createTypeAssertion(factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword), assertion.expression);
changeTracker.replaceNode(sourceFile, assertion.expression, replacement);
}
}

View File

@ -5,12 +5,12 @@ namespace ts.codefix {
getCodeActions: context => {
const { sourceFile } = context;
const changes = textChanges.ChangeTracker.with(context, changes => {
const exportDeclaration = createExportDeclaration(
const exportDeclaration = factory.createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports([]),
/*moduleSpecifier*/ undefined,
/*isTypeOnly*/ false
/*isTypeOnly*/ false,
factory.createNamedExports([]),
/*moduleSpecifier*/ undefined
);
changes.insertNodeAtEndOfScope(sourceFile, sourceFile, exportDeclaration);
});

View File

@ -52,9 +52,9 @@ namespace ts.codefix {
}
}
fixedDeclarations?.set(getNodeId(insertionSite).toString(), true);
const cloneWithModifier = getSynthesizedDeepClone(insertionSite, /*includeTrivia*/ true);
cloneWithModifier.modifiers = createNodeArray(createModifiersFromModifierFlags(getSyntacticModifierFlags(insertionSite) | ModifierFlags.Async));
cloneWithModifier.modifierFlagsCache = 0;
const cloneWithModifier = factory.updateModifiers(
getSynthesizedDeepClone(insertionSite, /*includeTrivia*/ true),
factory.createNodeArray(factory.createModifiersFromModifierFlags(getSyntacticModifierFlags(insertionSite) | ModifierFlags.Async)));
changeTracker.replaceNode(
sourceFile,
insertionSite,

View File

@ -244,7 +244,7 @@ namespace ts.codefix {
}
}
const type = checker.getTypeAtLocation(side);
const newNode = checker.getPromisedTypeOfPromise(type) ? createAwait(side) : side;
const newNode = checker.getPromisedTypeOfPromise(type) ? factory.createAwaitExpression(side) : side;
changeTracker.replaceNode(sourceFile, side, newNode);
}
}
@ -258,7 +258,7 @@ namespace ts.codefix {
changeTracker.replaceNode(
sourceFile,
insertionSite.parent.expression,
createParen(createAwait(insertionSite.parent.expression)));
factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite.parent.expression)));
insertLeadingSemicolonIfNeeded(changeTracker, insertionSite.parent.expression, sourceFile);
}
else if (contains(callableConstructableErrorCodes, errorCode) && isCallOrNewExpression(insertionSite.parent)) {
@ -268,7 +268,7 @@ namespace ts.codefix {
return;
}
}
changeTracker.replaceNode(sourceFile, insertionSite, createParen(createAwait(insertionSite)));
changeTracker.replaceNode(sourceFile, insertionSite, factory.createParenthesizedExpression(factory.createAwaitExpression(insertionSite)));
insertLeadingSemicolonIfNeeded(changeTracker, insertionSite, sourceFile);
}
else {
@ -278,7 +278,7 @@ namespace ts.codefix {
return;
}
}
changeTracker.replaceNode(sourceFile, insertionSite, createAwait(insertionSite));
changeTracker.replaceNode(sourceFile, insertionSite, factory.createAwaitExpression(insertionSite));
}
}

View File

@ -16,7 +16,7 @@ namespace ts.codefix {
const token = getTokenAtPosition(sourceFile, pos);
const decorator = findAncestor(token, isDecorator)!;
Debug.assert(!!decorator, "Expected position to be owned by a decorator.");
const replacement = createCall(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
const replacement = factory.createCallExpression(decorator.expression, /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
changeTracker.replaceNode(sourceFile, decorator.expression, replacement);
}
}

View File

@ -24,13 +24,13 @@ namespace ts.codefix {
const i = param.parent.parameters.indexOf(param);
Debug.assert(!param.type, "Tried to add a parameter name to a parameter that already had one.");
Debug.assert(i > -1, "Parameter not found in parent parameter list.");
const replacement = createParameter(
const replacement = factory.createParameterDeclaration(
/*decorators*/ undefined,
param.modifiers,
param.dotDotDotToken,
"arg" + i,
param.questionToken,
createTypeReferenceNode(token, /*typeArguments*/ undefined),
factory.createTypeReferenceNode(token, /*typeArguments*/ undefined),
param.initializer);
changeTracker.replaceNode(sourceFile, token, replacement);
}

View File

@ -46,14 +46,14 @@ namespace ts.codefix {
if (typeParameters.length) changes.insertTypeParameters(sourceFile, decl, typeParameters);
}
const needParens = isArrowFunction(decl) && !findChildOfKind(decl, SyntaxKind.OpenParenToken, sourceFile);
if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), createToken(SyntaxKind.OpenParenToken));
if (needParens) changes.insertNodeBefore(sourceFile, first(decl.parameters), factory.createToken(SyntaxKind.OpenParenToken));
for (const param of decl.parameters) {
if (!param.type) {
const paramType = getJSDocType(param);
if (paramType) changes.tryInsertTypeAnnotation(sourceFile, param, transformJSDocType(paramType));
}
}
if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), createToken(SyntaxKind.CloseParenToken));
if (needParens) changes.insertNodeAfter(sourceFile, last(decl.parameters), factory.createToken(SyntaxKind.CloseParenToken));
if (!decl.type) {
const returnType = getJSDocReturnType(decl);
if (returnType) changes.tryInsertTypeAnnotation(sourceFile, decl, transformJSDocType(returnType));
@ -77,7 +77,7 @@ namespace ts.codefix {
switch (node.kind) {
case SyntaxKind.JSDocAllType:
case SyntaxKind.JSDocUnknownType:
return createTypeReferenceNode("any", emptyArray);
return factory.createTypeReferenceNode("any", emptyArray);
case SyntaxKind.JSDocOptionalType:
return transformJSDocOptionalType(node as JSDocOptionalType);
case SyntaxKind.JSDocNonNullableType:
@ -91,34 +91,36 @@ namespace ts.codefix {
case SyntaxKind.TypeReference:
return transformJSDocTypeReference(node as TypeReferenceNode);
default:
const visited = visitEachChild(node, transformJSDocType, /*context*/ undefined!); // TODO: GH#18217
const visited = visitEachChild(node, transformJSDocType, nullTransformationContext);
setEmitFlags(visited, EmitFlags.SingleLine);
return visited;
}
}
function transformJSDocOptionalType(node: JSDocOptionalType) {
return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("undefined", emptyArray)]);
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("undefined", emptyArray)]);
}
function transformJSDocNullableType(node: JSDocNullableType) {
return createUnionTypeNode([visitNode(node.type, transformJSDocType), createTypeReferenceNode("null", emptyArray)]);
return factory.createUnionTypeNode([visitNode(node.type, transformJSDocType), factory.createTypeReferenceNode("null", emptyArray)]);
}
function transformJSDocVariadicType(node: JSDocVariadicType) {
return createArrayTypeNode(visitNode(node.type, transformJSDocType));
return factory.createArrayTypeNode(visitNode(node.type, transformJSDocType));
}
function transformJSDocFunctionType(node: JSDocFunctionType) {
return createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type);
// TODO: This does not properly handle `function(new:C, string)` per https://github.com/google/closure-compiler/wiki/Types-in-the-Closure-Type-System#the-javascript-type-language
// however we do handle it correctly in `serializeTypeForDeclaration` in checker.ts
return factory.createFunctionTypeNode(emptyArray, node.parameters.map(transformJSDocParameter), node.type ?? factory.createKeywordTypeNode(SyntaxKind.AnyKeyword));
}
function transformJSDocParameter(node: ParameterDeclaration) {
const index = node.parent.parameters.indexOf(node);
const isRest = node.type!.kind === SyntaxKind.JSDocVariadicType && index === node.parent.parameters.length - 1; // TODO: GH#18217
const name = node.name || (isRest ? "rest" : "arg" + index);
const dotdotdot = isRest ? createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken;
return createParameter(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer);
const dotdotdot = isRest ? factory.createToken(SyntaxKind.DotDotDotToken) : node.dotDotDotToken;
return factory.createParameterDeclaration(node.decorators, node.modifiers, dotdotdot, name, node.questionToken, visitNode(node.type, transformJSDocType), node.initializer);
}
function transformJSDocTypeReference(node: TypeReferenceNode) {
@ -142,27 +144,27 @@ namespace ts.codefix {
text = text[0].toUpperCase() + text.slice(1);
break;
}
name = createIdentifier(text);
name = factory.createIdentifier(text);
if ((text === "Array" || text === "Promise") && !node.typeArguments) {
args = createNodeArray([createTypeReferenceNode("any", emptyArray)]);
args = factory.createNodeArray([factory.createTypeReferenceNode("any", emptyArray)]);
}
else {
args = visitNodes(node.typeArguments, transformJSDocType);
}
}
return createTypeReferenceNode(name, args);
return factory.createTypeReferenceNode(name, args);
}
function transformJSDocIndexSignature(node: TypeReferenceNode) {
const index = createParameter(
const index = factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "n" : "s",
/*questionToken*/ undefined,
createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []),
factory.createTypeReferenceNode(node.typeArguments![0].kind === SyntaxKind.NumberKeyword ? "number" : "string", []),
/*initializer*/ undefined);
const indexSignature = createTypeLiteralNode([createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]);
const indexSignature = factory.createTypeLiteralNode([factory.createIndexSignature(/*decorators*/ undefined, /*modifiers*/ undefined, [index], node.typeArguments![1])]);
setEmitFlags(indexSignature, EmitFlags.SingleLine);
return indexSignature;
}

View File

@ -93,7 +93,7 @@ namespace ts.codefix {
}
}
else {
const memberElement = createClassElement(member, [createToken(SyntaxKind.StaticKeyword)]);
const memberElement = createClassElement(member, [factory.createToken(SyntaxKind.StaticKeyword)]);
if (memberElement) {
memberElements.push(...memberElement);
}
@ -146,7 +146,7 @@ namespace ts.codefix {
changes.delete(sourceFile, nodeToDelete);
if (!assignmentExpr) {
members.push(createProperty([], modifiers, symbol.name, /*questionToken*/ undefined,
members.push(factory.createPropertyDeclaration([], modifiers, symbol.name, /*questionToken*/ undefined,
/*type*/ undefined, /*initializer*/ undefined));
return members;
}
@ -177,13 +177,13 @@ namespace ts.codefix {
// Don't try to declare members in JavaScript files
if (isSourceFileJS(sourceFile)) return members;
if (!isPropertyAccessExpression(memberDeclaration)) return members;
const prop = createProperty(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentExpr);
const prop = factory.createPropertyDeclaration(/*decorators*/ undefined, modifiers, memberDeclaration.name, /*questionToken*/ undefined, /*type*/ undefined, assignmentExpr);
copyLeadingComments(assignmentBinaryExpression.parent, prop, sourceFile);
members.push(prop);
return members;
}
type MethodName = Parameters<typeof createMethod>[3];
type MethodName = Parameters<typeof factory.createMethodDeclaration>[3];
function createFunctionLikeExpressionMember(members: readonly ClassElement[], expression: FunctionExpression | ArrowFunction, name: MethodName) {
if (isFunctionExpression(expression)) return createFunctionExpressionMember(members, expression, name);
@ -192,8 +192,8 @@ namespace ts.codefix {
function createFunctionExpressionMember(members: readonly ClassElement[], functionExpression: FunctionExpression, name: MethodName) {
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(functionExpression, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
const method = factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, functionExpression.parameters, /*type*/ undefined, functionExpression.body);
copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
return members.concat(method);
}
@ -208,10 +208,10 @@ namespace ts.codefix {
}
// case 2: () => [1,2,3]
else {
bodyBlock = createBlock([createReturn(arrowFunctionBody)]);
bodyBlock = factory.createBlock([factory.createReturnStatement(arrowFunctionBody)]);
}
const fullModifiers = concatenate(modifiers, getModifierKindFromSource(arrowFunction, SyntaxKind.AsyncKeyword));
const method = createMethod(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined,
const method = factory.createMethodDeclaration(/*decorators*/ undefined, fullModifiers, /*asteriskToken*/ undefined, name, /*questionToken*/ undefined,
/*typeParameters*/ undefined, arrowFunction.parameters, /*type*/ undefined, bodyBlock);
copyLeadingComments(assignmentBinaryExpression, method, sourceFile);
return members.concat(method);
@ -231,11 +231,11 @@ namespace ts.codefix {
const memberElements = createClassElementsFromSymbol(node.symbol);
if (initializer.body) {
memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body));
memberElements.unshift(factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, initializer.parameters, initializer.body));
}
const modifiers = getModifierKindFromSource(precedingNode!, SyntaxKind.ExportKeyword);
const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
const cls = factory.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
/*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
// Don't call copyComments here because we'll already leave them in place
return cls;
@ -244,11 +244,11 @@ namespace ts.codefix {
function createClassFromFunctionDeclaration(node: FunctionDeclaration): ClassDeclaration {
const memberElements = createClassElementsFromSymbol(ctorSymbol);
if (node.body) {
memberElements.unshift(createConstructor(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body));
memberElements.unshift(factory.createConstructorDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, node.parameters, node.body));
}
const modifiers = getModifierKindFromSource(node, SyntaxKind.ExportKeyword);
const cls = createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
const cls = factory.createClassDeclaration(/*decorators*/ undefined, modifiers, node.name,
/*typeParameters*/ undefined, /*heritageClauses*/ undefined, memberElements);
// Don't call copyComments here because we'll already leave them in place
return cls;

View File

@ -173,7 +173,7 @@ namespace ts.codefix {
// so we push an entry for 'response'.
if (lastCallSignature && !isFunctionLikeDeclaration(node.parent) && !synthNamesMap.has(symbolIdString)) {
const firstParameter = firstOrUndefined(lastCallSignature.parameters);
const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || createOptimisticUniqueName("result");
const ident = firstParameter && isParameter(firstParameter.valueDeclaration) && tryCast(firstParameter.valueDeclaration.name, isIdentifier) || factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic);
const synthName = getNewNameIfConflict(ident, collidingSymbolMap);
synthNamesMap.set(symbolIdString, synthName);
collidingSymbolMap.add(ident.text, symbol);
@ -204,7 +204,7 @@ namespace ts.codefix {
function getNewNameIfConflict(name: Identifier, originalNames: ReadonlyMap<Symbol[]>): SynthIdentifier {
const numVarsSameName = (originalNames.get(name.text) || emptyArray).length;
const identifier = numVarsSameName === 0 ? name : createIdentifier(name.text + "_" + numVarsSameName);
const identifier = numVarsSameName === 0 ? name : factory.createIdentifier(name.text + "_" + numVarsSameName);
return createSynthIdentifier(identifier);
}
@ -258,7 +258,7 @@ namespace ts.codefix {
});
}
else {
possibleNameForVarDecl = createSynthIdentifier(createOptimisticUniqueName("result"), prevArgName.types);
possibleNameForVarDecl = createSynthIdentifier(factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic), prevArgName.types);
}
// We are about to write a 'let' variable declaration, but `transformExpression` for both
@ -267,11 +267,11 @@ namespace ts.codefix {
possibleNameForVarDecl.hasBeenDeclared = true;
}
const tryBlock = createBlock(transformExpression(node.expression, transformer, possibleNameForVarDecl));
const tryBlock = factory.createBlock(transformExpression(node.expression, transformer, possibleNameForVarDecl));
const transformationBody = getTransformationBody(func, possibleNameForVarDecl, argName, node, transformer);
const catchArg = argName ? isSynthIdentifier(argName) ? argName.identifier.text : argName.bindingPattern : "e";
const catchVariableDeclaration = createVariableDeclaration(catchArg);
const catchClause = createCatchClause(catchVariableDeclaration, createBlock(transformationBody));
const catchVariableDeclaration = factory.createVariableDeclaration(catchArg);
const catchClause = factory.createCatchClause(catchVariableDeclaration, factory.createBlock(transformationBody));
/*
In order to avoid an implicit any, we will synthesize a type for the declaration using the unions of the types of both paths (try block and catch block)
@ -283,18 +283,18 @@ namespace ts.codefix {
const typeArray: Type[] = possibleNameForVarDecl.types;
const unionType = transformer.checker.getUnionType(typeArray, UnionReduction.Subtype);
const unionTypeNode = transformer.isInJSFile ? undefined : transformer.checker.typeToTypeNode(unionType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined);
const varDecl = [createVariableDeclaration(varDeclIdentifier, unionTypeNode)];
varDeclList = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList(varDecl, NodeFlags.Let));
const varDecl = [factory.createVariableDeclaration(varDeclIdentifier, /*exclamationToken*/ undefined, unionTypeNode)];
varDeclList = factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList(varDecl, NodeFlags.Let));
}
const tryStatement = createTry(tryBlock, catchClause, /*finallyBlock*/ undefined);
const tryStatement = factory.createTryStatement(tryBlock, catchClause, /*finallyBlock*/ undefined);
const destructuredResult = prevArgName && varDeclIdentifier && isSynthBindingPattern(prevArgName)
&& createVariableStatement(/* modifiers */ undefined, createVariableDeclarationList([createVariableDeclaration(getSynthesizedDeepCloneWithRenames(prevArgName.bindingPattern), /* type */ undefined, varDeclIdentifier)], NodeFlags.Const));
&& factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(getSynthesizedDeepCloneWithRenames(prevArgName.bindingPattern), /*exclamationToken*/ undefined, /*type*/ undefined, varDeclIdentifier)], NodeFlags.Const));
return compact([varDeclList, tryStatement, destructuredResult]);
}
function createUniqueSynthName(prevArgName: SynthIdentifier): SynthIdentifier {
const renamedPrevArg = createOptimisticUniqueName(prevArgName.identifier.text);
const renamedPrevArg = factory.createUniqueName(prevArgName.identifier.text, GeneratedIdentifierFlags.Optimistic);
return createSynthIdentifier(renamedPrevArg);
}
@ -305,13 +305,13 @@ namespace ts.codefix {
if (onRejected) {
const onRejectedArgumentName = getArgBindingName(onRejected, transformer);
const tryBlock = createBlock(transformExpression(node.expression, transformer, onFulfilledArgumentName).concat(transformationBody));
const tryBlock = factory.createBlock(transformExpression(node.expression, transformer, onFulfilledArgumentName).concat(transformationBody));
const transformationBody2 = getTransformationBody(onRejected, prevArgName, onRejectedArgumentName, node, transformer);
const catchArg = onRejectedArgumentName ? isSynthIdentifier(onRejectedArgumentName) ? onRejectedArgumentName.identifier.text : onRejectedArgumentName.bindingPattern : "e";
const catchVariableDeclaration = createVariableDeclaration(catchArg);
const catchClause = createCatchClause(catchVariableDeclaration, createBlock(transformationBody2));
const catchVariableDeclaration = factory.createVariableDeclaration(catchArg);
const catchClause = factory.createCatchClause(catchVariableDeclaration, factory.createBlock(transformationBody2));
return [createTry(tryBlock, catchClause, /* finallyBlock */ undefined)];
return [factory.createTryStatement(tryBlock, catchClause, /* finallyBlock */ undefined)];
}
return transformExpression(node.expression, transformer, onFulfilledArgumentName).concat(transformationBody);
@ -322,29 +322,30 @@ namespace ts.codefix {
*/
function transformPromiseExpressionOfPropertyAccess(node: Expression, transformer: Transformer, prevArgName?: SynthBindingName): readonly Statement[] {
if (shouldReturn(node, transformer)) {
return [createReturn(getSynthesizedDeepClone(node))];
return [factory.createReturnStatement(getSynthesizedDeepClone(node))];
}
return createVariableOrAssignmentOrExpressionStatement(prevArgName, createAwait(node), /*typeAnnotation*/ undefined);
return createVariableOrAssignmentOrExpressionStatement(prevArgName, factory.createAwaitExpression(node), /*typeAnnotation*/ undefined);
}
function createVariableOrAssignmentOrExpressionStatement(variableName: SynthBindingName | undefined, rightHandSide: Expression, typeAnnotation: TypeNode | undefined): readonly Statement[] {
if (!variableName || isEmptyBindingName(variableName)) {
// if there's no argName to assign to, there still might be side effects
return [createExpressionStatement(rightHandSide)];
return [factory.createExpressionStatement(rightHandSide)];
}
if (isSynthIdentifier(variableName) && variableName.hasBeenDeclared) {
// if the variable has already been declared, we don't need "let" or "const"
return [createExpressionStatement(createAssignment(getSynthesizedDeepClone(variableName.identifier), rightHandSide))];
return [factory.createExpressionStatement(factory.createAssignment(getSynthesizedDeepClone(variableName.identifier), rightHandSide))];
}
return [
createVariableStatement(
factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
getSynthesizedDeepClone(getNode(variableName)),
/*exclamationToken*/ undefined,
typeAnnotation,
rightHandSide)],
NodeFlags.Const))];
@ -352,13 +353,13 @@ namespace ts.codefix {
function maybeAnnotateAndReturn(expressionToReturn: Expression | undefined, typeAnnotation: TypeNode | undefined): readonly Statement[] {
if (typeAnnotation && expressionToReturn) {
const name = createOptimisticUniqueName("result");
const name = factory.createUniqueName("result", GeneratedIdentifierFlags.Optimistic);
return [
...createVariableOrAssignmentOrExpressionStatement(createSynthIdentifier(name), expressionToReturn, typeAnnotation),
createReturn(name)
factory.createReturnStatement(name)
];
}
return [createReturn(expressionToReturn)];
return [factory.createReturnStatement(expressionToReturn)];
}
// should be kept up to date with isFixablePromiseArgument in suggestionDiagnostics.ts
@ -373,7 +374,7 @@ namespace ts.codefix {
break;
}
const synthCall = createCall(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, isSynthIdentifier(argName) ? [argName.identifier] : []);
const synthCall = factory.createCallExpression(getSynthesizedDeepClone(func as Identifier), /*typeArguments*/ undefined, isSynthIdentifier(argName) ? [argName.identifier] : []);
if (shouldReturn(parent, transformer)) {
return maybeAnnotateAndReturn(synthCall, parent.typeArguments?.[0]);
}
@ -385,7 +386,7 @@ namespace ts.codefix {
return silentFail();
}
const returnType = callSignatures[0].getReturnType();
const varDeclOrAssignment = createVariableOrAssignmentOrExpressionStatement(prevArgName, createAwait(synthCall), parent.typeArguments?.[0]);
const varDeclOrAssignment = createVariableOrAssignmentOrExpressionStatement(prevArgName, factory.createAwaitExpression(synthCall), parent.typeArguments?.[0]);
if (prevArgName) {
prevArgName.types.push(returnType);
}
@ -423,7 +424,7 @@ namespace ts.codefix {
seenReturnStatement);
}
else {
const innerRetStmts = isFixablePromiseHandler(funcBody) ? [createReturn(funcBody)] : emptyArray;
const innerRetStmts = isFixablePromiseHandler(funcBody) ? [factory.createReturnStatement(funcBody)] : emptyArray;
const innerCbBody = getInnerTransformationBody(transformer, innerRetStmts, prevArgName);
if (innerCbBody.length > 0) {
@ -433,7 +434,7 @@ namespace ts.codefix {
const type = transformer.checker.getTypeAtLocation(func);
const returnType = getLastCallSignature(type, transformer.checker)!.getReturnType();
const rightHandSide = getSynthesizedDeepClone(funcBody);
const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? createAwait(rightHandSide) : rightHandSide;
const possiblyAwaitedRightHandSide = !!transformer.checker.getPromisedTypeOfPromise(returnType) ? factory.createAwaitExpression(rightHandSide) : rightHandSide;
if (!shouldReturn(parent, transformer)) {
const transformedStatement = createVariableOrAssignmentOrExpressionStatement(prevArgName, possiblyAwaitedRightHandSide, /*typeAnnotation*/ undefined);
if (prevArgName) {
@ -464,13 +465,13 @@ namespace ts.codefix {
for (const stmt of stmts) {
if (isReturnStatement(stmt)) {
if (stmt.expression) {
const possiblyAwaitedExpression = isPromiseTypedExpression(stmt.expression, transformer.checker) ? createAwait(stmt.expression) : stmt.expression;
const possiblyAwaitedExpression = isPromiseTypedExpression(stmt.expression, transformer.checker) ? factory.createAwaitExpression(stmt.expression) : stmt.expression;
if (prevArgName === undefined) {
ret.push(createExpressionStatement(possiblyAwaitedExpression));
ret.push(factory.createExpressionStatement(possiblyAwaitedExpression));
}
else {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, possiblyAwaitedExpression)], NodeFlags.Const))));
ret.push(factory.createVariableStatement(/*modifiers*/ undefined,
(factory.createVariableDeclarationList([factory.createVariableDeclaration(getNode(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, possiblyAwaitedExpression)], NodeFlags.Const))));
}
}
}
@ -481,8 +482,8 @@ namespace ts.codefix {
// if block has no return statement, need to define prevArgName as undefined to prevent undeclared variables
if (!seenReturnStatement && prevArgName !== undefined) {
ret.push(createVariableStatement(/*modifiers*/ undefined,
(createVariableDeclarationList([createVariableDeclaration(getNode(prevArgName), /*type*/ undefined, createIdentifier("undefined"))], NodeFlags.Const))));
ret.push(factory.createVariableStatement(/*modifiers*/ undefined,
(factory.createVariableDeclarationList([factory.createVariableDeclaration(getNode(prevArgName), /*exclamationToken*/ undefined, /*type*/ undefined, factory.createIdentifier("undefined"))], NodeFlags.Const))));
}
return ret;

View File

@ -31,7 +31,7 @@ namespace ts.codefix {
break;
case SyntaxKind.CallExpression:
if (isRequireCall(importNode, /*checkArgumentIsStringLiteralLike*/ false)) {
changes.replaceNode(importingFile, importNode, createPropertyAccess(getSynthesizedDeepClone(importNode), "default"));
changes.replaceNode(importingFile, importNode, factory.createPropertyAccessExpression(getSynthesizedDeepClone(importNode), "default"));
}
break;
}
@ -81,7 +81,7 @@ namespace ts.codefix {
return;
}
const { text } = node.name;
changes.replaceNode(sourceFile, node, createIdentifier(exports.get(text) || text));
changes.replaceNode(sourceFile, node, factory.createIdentifier(exports.get(text) || text));
});
}
@ -154,7 +154,7 @@ namespace ts.codefix {
}
}
// Move it out to its own variable statement. (This will not be used if `!foundImport`)
return createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([decl], declarationList.flags));
return factory.createVariableStatement(/*modifiers*/ undefined, factory.createVariableDeclarationList([decl], declarationList.flags));
});
if (foundImport) {
// useNonAdjustedEndPosition to ensure we don't eat the newline after the statement.
@ -171,7 +171,7 @@ namespace ts.codefix {
const tmp = makeUniqueName(propertyName, identifiers);
return [
makeSingleImport(tmp, propertyName, moduleSpecifier, quotePreference),
makeConst(/*modifiers*/ undefined, name, createIdentifier(tmp)),
makeConst(/*modifiers*/ undefined, name, factory.createIdentifier(tmp)),
];
}
case SyntaxKind.Identifier:
@ -237,7 +237,7 @@ namespace ts.codefix {
case SyntaxKind.PropertyAssignment:
return !isIdentifier(prop.name) ? undefined : convertExportsDotXEquals_replaceNode(prop.name.text, prop.initializer);
case SyntaxKind.MethodDeclaration:
return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [createToken(SyntaxKind.ExportKeyword)], prop);
return !isIdentifier(prop.name) ? undefined : functionExpressionToDeclaration(prop.name.text, [factory.createToken(SyntaxKind.ExportKeyword)], prop);
default:
Debug.assertNever(prop, `Convert to ES6 got invalid prop kind ${(prop as ObjectLiteralElementLike).kind}`);
}
@ -261,7 +261,7 @@ namespace ts.codefix {
*/
const newNodes = [
makeConst(/*modifiers*/ undefined, rename, assignment.right),
makeExportDeclaration([createExportSpecifier(rename, text)]),
makeExportDeclaration([factory.createExportSpecifier(rename, text)]),
];
changes.replaceNodeWithNodes(sourceFile, assignment.parent, newNodes);
}
@ -284,14 +284,14 @@ namespace ts.codefix {
return makeExportDeclaration(/*exportClause*/ undefined, moduleSpecifier);
}
function reExportDefault(moduleSpecifier: string): ExportDeclaration {
return makeExportDeclaration([createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier);
return makeExportDeclaration([factory.createExportSpecifier(/*propertyName*/ undefined, "default")], moduleSpecifier);
}
function convertExportsPropertyAssignment({ left, right, parent }: BinaryExpression & { left: PropertyAccessExpression }, sourceFile: SourceFile, changes: textChanges.ChangeTracker): void {
const name = left.name.text;
if ((isFunctionExpression(right) || isArrowFunction(right) || isClassExpression(right)) && (!right.name || right.name.text === name)) {
// `exports.f = function() {}` -> `export function f() {}` -- Replace `exports.f = ` with `export `, and insert the name after `function`.
changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, createToken(SyntaxKind.ExportKeyword), { suffix: " " });
changes.replaceRange(sourceFile, { pos: left.getStart(sourceFile), end: right.getStart(sourceFile) }, factory.createToken(SyntaxKind.ExportKeyword), { suffix: " " });
if (!right.name) changes.insertName(sourceFile, right, name);
@ -301,14 +301,14 @@ namespace ts.codefix {
else {
// `exports.f = function g() {}` -> `export const f = function g() {}` -- just replace `exports.` with `export const `
changes.replaceNodeRangeWithNodes(sourceFile, left.expression, findChildOfKind(left, SyntaxKind.DotToken, sourceFile)!,
[createToken(SyntaxKind.ExportKeyword), createToken(SyntaxKind.ConstKeyword)],
[factory.createToken(SyntaxKind.ExportKeyword), factory.createToken(SyntaxKind.ConstKeyword)],
{ joiner: " ", suffix: " " });
}
}
// TODO: GH#22492 this will cause an error if a change has been made inside the body of the node.
function convertExportsDotXEquals_replaceNode(name: string | undefined, exported: Expression): Statement {
const modifiers = [createToken(SyntaxKind.ExportKeyword)];
const modifiers = [factory.createToken(SyntaxKind.ExportKeyword)];
switch (exported.kind) {
case SyntaxKind.FunctionExpression: {
const { name: expressionName } = exported as FunctionExpression;
@ -331,7 +331,7 @@ namespace ts.codefix {
function exportConst() {
// `exports.x = 0;` --> `export const x = 0;`
return makeConst(modifiers, createIdentifier(name!), exported); // TODO: GH#18217
return makeConst(modifiers, factory.createIdentifier(name!), exported); // TODO: GH#18217
}
}
@ -370,8 +370,8 @@ namespace ts.codefix {
*/
const tmp = makeUniqueName(moduleSpecifierToValidIdentifier(moduleSpecifier.text, target), identifiers);
return [
makeImport(createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference),
makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), createIdentifier(tmp)),
makeImport(factory.createIdentifier(tmp), /*namedImports*/ undefined, moduleSpecifier, quotePreference),
makeConst(/*modifiers*/ undefined, getSynthesizedDeepClone(name), factory.createIdentifier(tmp)),
];
}
case SyntaxKind.Identifier:
@ -407,7 +407,7 @@ namespace ts.codefix {
idName = makeUniqueName(propertyName, identifiers);
namedBindingsNames.set(propertyName, idName);
}
changes.replaceNode(file, parent, createIdentifier(idName));
changes.replaceNode(file, parent, factory.createIdentifier(idName));
}
else {
needDefaultImport = true;
@ -415,7 +415,7 @@ namespace ts.codefix {
}
const namedBindings = namedBindingsNames.size === 0 ? undefined : arrayFrom(mapIterator(namedBindingsNames.entries(), ([propertyName, idName]) =>
createImportSpecifier(propertyName === idName ? undefined : createIdentifier(propertyName), createIdentifier(idName))));
factory.createImportSpecifier(propertyName === idName ? undefined : factory.createIdentifier(propertyName), factory.createIdentifier(idName))));
if (!namedBindings) {
// If it was unused, ensure that we at least import *something*.
needDefaultImport = true;
@ -477,7 +477,7 @@ namespace ts.codefix {
// Node helpers
function functionExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], fn: FunctionExpression | ArrowFunction | MethodDeclaration): FunctionDeclaration {
return createFunctionDeclaration(
return factory.createFunctionDeclaration(
getSynthesizedDeepClones(fn.decorators), // TODO: GH#19915 Don't think this is even legal.
concatenate(additionalModifiers, getSynthesizedDeepClones(fn.modifiers)),
getSynthesizedDeepClone(fn.asteriskToken),
@ -485,11 +485,11 @@ namespace ts.codefix {
getSynthesizedDeepClones(fn.typeParameters),
getSynthesizedDeepClones(fn.parameters),
getSynthesizedDeepClone(fn.type),
convertToFunctionBody(getSynthesizedDeepClone(fn.body!)));
factory.converters.convertToFunctionBlock(getSynthesizedDeepClone(fn.body!)));
}
function classExpressionToDeclaration(name: string | undefined, additionalModifiers: readonly Modifier[], cls: ClassExpression): ClassDeclaration {
return createClassDeclaration(
return factory.createClassDeclaration(
getSynthesizedDeepClones(cls.decorators), // TODO: GH#19915 Don't think this is even legal.
concatenate(additionalModifiers, getSynthesizedDeepClones(cls.modifiers)),
name,
@ -500,27 +500,28 @@ namespace ts.codefix {
function makeSingleImport(localName: string, propertyName: string, moduleSpecifier: StringLiteralLike, quotePreference: QuotePreference): ImportDeclaration {
return propertyName === "default"
? makeImport(createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference)
? makeImport(factory.createIdentifier(localName), /*namedImports*/ undefined, moduleSpecifier, quotePreference)
: makeImport(/*name*/ undefined, [makeImportSpecifier(propertyName, localName)], moduleSpecifier, quotePreference);
}
function makeImportSpecifier(propertyName: string | undefined, name: string): ImportSpecifier {
return createImportSpecifier(propertyName !== undefined && propertyName !== name ? createIdentifier(propertyName) : undefined, createIdentifier(name));
return factory.createImportSpecifier(propertyName !== undefined && propertyName !== name ? factory.createIdentifier(propertyName) : undefined, factory.createIdentifier(name));
}
function makeConst(modifiers: readonly Modifier[] | undefined, name: string | BindingName, init: Expression): VariableStatement {
return createVariableStatement(
return factory.createVariableStatement(
modifiers,
createVariableDeclarationList(
[createVariableDeclaration(name, /*type*/ undefined, init)],
factory.createVariableDeclarationList(
[factory.createVariableDeclaration(name, /*exclamationToken*/ undefined, /*type*/ undefined, init)],
NodeFlags.Const));
}
function makeExportDeclaration(exportSpecifiers: ExportSpecifier[] | undefined, moduleSpecifier?: string): ExportDeclaration {
return createExportDeclaration(
return factory.createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
exportSpecifiers && createNamedExports(exportSpecifiers),
moduleSpecifier === undefined ? undefined : createLiteral(moduleSpecifier));
/*isTypeOnly*/ false,
exportSpecifiers && factory.createNamedExports(exportSpecifiers),
moduleSpecifier === undefined ? undefined : factory.createStringLiteral(moduleSpecifier));
}
}

View File

@ -33,23 +33,23 @@ namespace ts.codefix {
}
function createTypeAliasFromInterface(declaration: FixableDeclaration, type: TypeNode): TypeAliasDeclaration {
return createTypeAliasDeclaration(declaration.decorators, declaration.modifiers, declaration.name, declaration.typeParameters, type);
return factory.createTypeAliasDeclaration(declaration.decorators, declaration.modifiers, declaration.name, declaration.typeParameters, type);
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { indexSignature, container }: Info): void {
const members = isInterfaceDeclaration(container) ? container.members : (<TypeLiteralNode>container.type).members;
const otherMembers = members.filter(member => !isIndexSignatureDeclaration(member));
const parameter = first(indexSignature.parameters);
const mappedTypeParameter = createTypeParameterDeclaration(cast(parameter.name, isIdentifier), parameter.type);
const mappedIntersectionType = createMappedTypeNode(
hasEffectiveReadonlyModifier(indexSignature) ? createModifier(SyntaxKind.ReadonlyKeyword) : undefined,
const mappedTypeParameter = factory.createTypeParameterDeclaration(cast(parameter.name, isIdentifier), parameter.type);
const mappedIntersectionType = factory.createMappedTypeNode(
hasEffectiveReadonlyModifier(indexSignature) ? factory.createModifier(SyntaxKind.ReadonlyKeyword) : undefined,
mappedTypeParameter,
indexSignature.questionToken,
indexSignature.type);
const intersectionType = createIntersectionTypeNode([
const intersectionType = factory.createIntersectionTypeNode([
...getAllSuperTypeNodes(container),
mappedIntersectionType,
...(otherMembers.length ? [createTypeLiteralNode(otherMembers)] : emptyArray),
...(otherMembers.length ? [factory.createTypeLiteralNode(otherMembers)] : emptyArray),
]);
changes.replaceNode(sourceFile, container, createTypeAliasFromInterface(container, intersectionType));
}

View File

@ -38,28 +38,28 @@ namespace ts.codefix {
changes.replaceNode(
context.sourceFile,
exportDeclaration,
updateExportDeclaration(
factory.updateExportDeclaration(
exportDeclaration,
exportDeclaration.decorators,
exportDeclaration.modifiers,
/*isTypeOnly*/ true,
exportClause,
exportDeclaration.moduleSpecifier,
/*isTypeOnly*/ true));
exportDeclaration.moduleSpecifier));
}
else {
const valueExportDeclaration = updateExportDeclaration(
const valueExportDeclaration = factory.updateExportDeclaration(
exportDeclaration,
exportDeclaration.decorators,
exportDeclaration.modifiers,
updateNamedExports(exportClause, filter(exportClause.elements, e => !contains(typeExportSpecifiers, e))),
exportDeclaration.moduleSpecifier,
/*isTypeOnly*/ false);
const typeExportDeclaration = createExportDeclaration(
/*isTypeOnly*/ false,
factory.updateNamedExports(exportClause, filter(exportClause.elements, e => !contains(typeExportSpecifiers, e))),
exportDeclaration.moduleSpecifier);
const typeExportDeclaration = factory.createExportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createNamedExports(typeExportSpecifiers),
exportDeclaration.moduleSpecifier,
/*isTypeOnly*/ true);
/*isTypeOnly*/ true,
factory.createNamedExports(typeExportSpecifiers),
exportDeclaration.moduleSpecifier);
changes.replaceNode(context.sourceFile, exportDeclaration, valueExportDeclaration);
changes.insertNodeAfter(context.sourceFile, exportDeclaration, typeExportDeclaration);

View File

@ -38,14 +38,14 @@ namespace ts.codefix {
// `import type foo, { Bar }` is not allowed, so move `foo` to new declaration
if (importClause.name && importClause.namedBindings) {
changes.deleteNodeRangeExcludingEnd(context.sourceFile, importClause.name, importDeclaration.importClause.namedBindings);
changes.insertNodeBefore(context.sourceFile, importDeclaration, updateImportDeclaration(
changes.insertNodeBefore(context.sourceFile, importDeclaration, factory.updateImportDeclaration(
importDeclaration,
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(
factory.createImportClause(
/*isTypeOnly*/ true,
importClause.name,
/*namedBindings*/ undefined,
/*isTypeOnly*/ true),
/*namedBindings*/ undefined),
importDeclaration.moduleSpecifier));
}
}

View File

@ -28,9 +28,9 @@ namespace ts.codefix {
function doChange(changeTracker: textChanges.ChangeTracker, sourceFile: SourceFile, qualifiedName: QualifiedName): void {
const rightText = qualifiedName.right.text;
const replacement = createIndexedAccessTypeNode(
createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined),
createLiteralTypeNode(createLiteral(rightText)));
const replacement = factory.createIndexedAccessTypeNode(
factory.createTypeReferenceNode(qualifiedName.left, /*typeArguments*/ undefined),
factory.createLiteralTypeNode(factory.createStringLiteral(rightText)));
changeTracker.replaceNode(sourceFile, qualifiedName, replacement);
}
}

View File

@ -167,11 +167,11 @@ namespace ts.codefix {
return;
}
const className = classDeclaration.name!.getText();
const staticInitialization = initializePropertyToUndefined(createIdentifier(className), tokenName);
const staticInitialization = initializePropertyToUndefined(factory.createIdentifier(className), tokenName);
changeTracker.insertNodeAfter(declSourceFile, classDeclaration, staticInitialization);
}
else if (isPrivateIdentifier(token)) {
const property = createProperty(
const property = factory.createPropertyDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
tokenName,
@ -192,13 +192,13 @@ namespace ts.codefix {
if (!classConstructor) {
return;
}
const propertyInitialization = initializePropertyToUndefined(createThis(), tokenName);
const propertyInitialization = initializePropertyToUndefined(factory.createThis(), tokenName);
changeTracker.insertNodeAtConstructorEnd(declSourceFile, classConstructor, propertyInitialization);
}
}
function initializePropertyToUndefined(obj: Expression, propertyName: string) {
return createStatement(createAssignment(createPropertyAccess(obj, propertyName), createIdentifier("undefined")));
return factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression(obj, propertyName), factory.createIdentifier("undefined")));
}
function createActionsForAddMissingMemberInTypeScriptFile(context: CodeFixContext, { parentDeclaration, declSourceFile, modifierFlags, token }: ClassOrInterfaceInfo): CodeFixAction[] | undefined {
@ -232,13 +232,13 @@ namespace ts.codefix {
const contextualType = checker.getContextualType(token.parent as Expression);
typeNode = contextualType ? checker.typeToTypeNode(contextualType, /*enclosingDeclaration*/ undefined, /*flags*/ undefined) : undefined;
}
return typeNode || createKeywordTypeNode(SyntaxKind.AnyKeyword);
return typeNode || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword);
}
function addPropertyDeclaration(changeTracker: textChanges.ChangeTracker, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode, modifierFlags: ModifierFlags): void {
const property = createProperty(
const property = factory.createPropertyDeclaration(
/*decorators*/ undefined,
/*modifiers*/ modifierFlags ? createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined,
/*modifiers*/ modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined,
tokenName,
/*questionToken*/ undefined,
typeNode,
@ -265,8 +265,8 @@ namespace ts.codefix {
function createAddIndexSignatureAction(context: CodeFixContext, declSourceFile: SourceFile, classDeclaration: ClassOrInterface, tokenName: string, typeNode: TypeNode): CodeFixAction {
// Index signatures cannot have the static modifier.
const stringTypeNode = createKeywordTypeNode(SyntaxKind.StringKeyword);
const indexingParameter = createParameter(
const stringTypeNode = factory.createKeywordTypeNode(SyntaxKind.StringKeyword);
const indexingParameter = factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
@ -274,7 +274,7 @@ namespace ts.codefix {
/*questionToken*/ undefined,
stringTypeNode,
/*initializer*/ undefined);
const indexSignature = createIndexSignature(
const indexSignature = factory.createIndexSignature(
/*decorators*/ undefined,
/*modifiers*/ undefined,
[indexingParameter],
@ -338,8 +338,8 @@ namespace ts.codefix {
return !!(type && type.flags & TypeFlags.StringLike);
});
const enumMember = createEnumMember(token, hasStringInitializer ? createStringLiteral(token.text) : undefined);
changes.replaceNode(enumDeclaration.getSourceFile(), enumDeclaration, updateEnumDeclaration(
const enumMember = factory.createEnumMember(token, hasStringInitializer ? factory.createStringLiteral(token.text) : undefined);
changes.replaceNode(enumDeclaration.getSourceFile(), enumDeclaration, factory.updateEnumDeclaration(
enumDeclaration,
enumDeclaration.decorators,
enumDeclaration.modifiers,

View File

@ -16,7 +16,7 @@ namespace ts.codefix {
function addMissingNewOperator(changes: textChanges.ChangeTracker, sourceFile: SourceFile, span: TextSpan): void {
const call = cast(findAncestorMatchingSpan(sourceFile, span), isCallExpression);
const newExpression = createNew(call.expression, call.typeArguments, call.arguments);
const newExpression = factory.createNewExpression(call.expression, call.typeArguments, call.arguments);
changes.replaceNode(sourceFile, call, newExpression);
}

View File

@ -25,7 +25,7 @@ namespace ts.codefix {
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, importType: ImportTypeNode) {
const newTypeNode = updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true);
const newTypeNode = factory.updateImportTypeNode(importType, importType.argument, importType.qualifier, importType.typeArguments, /* isTypeOf */ true);
changes.replaceNode(sourceFile, importType, newTypeNode);
}
}

View File

@ -73,7 +73,7 @@ namespace ts.codefix {
if (returnType) {
const entityName = getEntityNameFromTypeNode(returnType);
if (!entityName || entityName.kind !== SyntaxKind.Identifier || entityName.text !== "Promise") {
changes.replaceNode(sourceFile, returnType, createTypeReferenceNode("Promise", createNodeArray([returnType])));
changes.replaceNode(sourceFile, returnType, factory.createTypeReferenceNode("Promise", factory.createNodeArray([returnType])));
}
}
changes.insertModifierBefore(sourceFile, SyntaxKind.AsyncKeyword, insertBefore);

View File

@ -22,7 +22,7 @@ namespace ts.codefix {
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, ctr: ConstructorDeclaration) {
const superCall = createStatement(createCall(createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
const superCall = factory.createExpressionStatement(factory.createCallExpression(factory.createSuper(), /*typeArguments*/ undefined, /*argumentsArray*/ emptyArray));
changes.insertNodeAtConstructorStart(sourceFile, ctr, superCall);
}
}

View File

@ -26,6 +26,6 @@ namespace ts.codefix {
});
function doChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) {
setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", createTrue());
setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", factory.createTrue());
}
}

View File

@ -30,6 +30,6 @@ namespace ts.codefix {
});
function doChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) {
setJsonCompilerOptionValue(changeTracker, configFile, "jsx", createStringLiteral("react"));
setJsonCompilerOptionValue(changeTracker, configFile, "jsx", factory.createStringLiteral("react"));
}
}

View File

@ -40,7 +40,7 @@ namespace ts.codefix {
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node }: Info): void {
const newNode = createNode(SyntaxKind.CommaToken);
const newNode = factory.createToken(SyntaxKind.CommaToken);
changes.replaceNode(sourceFile, node, newNode);
}
}

View File

@ -27,7 +27,7 @@ namespace ts.codefix {
}
function doChanges(changes: textChanges.ChangeTracker, sourceFile: SourceFile, extendsToken: Node, heritageClauses: readonly HeritageClause[]): void {
changes.replaceNode(sourceFile, extendsToken, createToken(SyntaxKind.ImplementsKeyword));
changes.replaceNode(sourceFile, extendsToken, factory.createToken(SyntaxKind.ImplementsKeyword));
// If there is already an implements clause, replace the implements keyword with a comma.
if (heritageClauses.length === 2 &&
@ -36,7 +36,7 @@ namespace ts.codefix {
const implementsToken = heritageClauses[1].getFirstToken()!;
const implementsFullStart = implementsToken.getFullStart();
changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, createToken(SyntaxKind.CommaToken));
changes.replaceRange(sourceFile, { pos: implementsFullStart, end: implementsFullStart }, factory.createToken(SyntaxKind.CommaToken));
// Rough heuristic: delete trailing whitespace after keyword so that it's not excessive.
// (Trailing because leading might be indentation, which is more sensitive.)

View File

@ -40,6 +40,6 @@ namespace ts.codefix {
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, { node, className }: Info): void {
// TODO (https://github.com/Microsoft/TypeScript/issues/21246): use shared helper
suppressLeadingAndTrailingTrivia(node);
changes.replaceNode(sourceFile, node, createPropertyAccess(className ? createIdentifier(className) : createThis(), node));
changes.replaceNode(sourceFile, node, factory.createPropertyAccessExpression(className ? factory.createIdentifier(className) : factory.createThis(), node));
}
}

View File

@ -46,7 +46,7 @@ namespace ts.codefix {
else {
// `function f() {}` => `const f = () => {}`
// `name` should be defined because we only do this in inner contexts, and name is only undefined for `export default function() {}`.
changes.replaceNode(sourceFile, fnKeyword, createToken(SyntaxKind.ConstKeyword));
changes.replaceNode(sourceFile, fnKeyword, factory.createToken(SyntaxKind.ConstKeyword));
changes.insertText(sourceFile, name!.end, " = ");
changes.insertText(sourceFile, body.pos, " =>");
return [Diagnostics.Convert_function_declaration_0_to_arrow_function, name!.text];
@ -54,7 +54,7 @@ namespace ts.codefix {
}
// No outer 'this', add a @class tag if in a JS constructor function
else if (isSourceFileJS(sourceFile) && isPropertyAccessExpression(token.parent) && isAssignmentExpression(token.parent.parent)) {
addJSDocTags(changes, sourceFile, fn, [createJSDocClassTag()]);
addJSDocTags(changes, sourceFile, fn, [factory.createJSDocClassTag(/*tagName*/ undefined)]);
return Diagnostics.Add_class_tag;
}
}

View File

@ -37,11 +37,11 @@ namespace ts.codefix {
}
unwrappedType = (unwrappedType as OptionalTypeNode | RestTypeNode | ParenthesizedTypeNode).type;
}
const updated = updateNamedTupleMember(
const updated = factory.updateNamedTupleMember(
namedTupleMember,
namedTupleMember.dotDotDotToken || (sawRest ? createToken(SyntaxKind.DotDotDotToken) : undefined),
namedTupleMember.dotDotDotToken || (sawRest ? factory.createToken(SyntaxKind.DotDotDotToken) : undefined),
namedTupleMember.name,
namedTupleMember.questionToken || (sawOptional ? createToken(SyntaxKind.QuestionToken) : undefined),
namedTupleMember.questionToken || (sawOptional ? factory.createToken(SyntaxKind.QuestionToken) : undefined),
unwrappedType
);
if (updated === namedTupleMember) {

View File

@ -13,11 +13,11 @@ namespace ts.codefix {
if (getEmitModuleKind(opts) === ModuleKind.CommonJS) {
// import Bluebird = require("bluebird");
variations.push(createAction(context, sourceFile, node, createImportEqualsDeclaration(
variations.push(createAction(context, sourceFile, node, factory.createImportEqualsDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
namespace.name,
createExternalModuleReference(node.moduleSpecifier)
factory.createExternalModuleReference(node.moduleSpecifier)
)));
}
@ -88,7 +88,7 @@ namespace ts.codefix {
}
if (isExpression(expr) && !(isNamedDeclaration(expr.parent) && expr.parent.name === expr)) {
const sourceFile = context.sourceFile;
const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, createPropertyAccess(expr, "default"), {}));
const changes = textChanges.ChangeTracker.with(context, t => t.replaceNode(sourceFile, expr, factory.createPropertyAccessExpression(expr, "default"), {}));
fixes.push(createCodeFixActionWithoutFixAll(fixName, changes, Diagnostics.Use_synthetic_default_member));
}
return fixes;

View File

@ -14,7 +14,7 @@ namespace ts.codefix {
const moduleOutOfRange = moduleKind >= ModuleKind.ES2015 && moduleKind < ModuleKind.ESNext;
if (moduleOutOfRange) {
const changes = textChanges.ChangeTracker.with(context, changes => {
setJsonCompilerOptionValue(changes, configFile, "module", createStringLiteral("esnext"));
setJsonCompilerOptionValue(changes, configFile, "module", factory.createStringLiteral("esnext"));
});
codeFixes.push(createCodeFixActionWithoutFixAll("fixModuleOption", changes, [Diagnostics.Set_the_module_option_in_your_configuration_file_to_0, "esnext"]));
}
@ -26,10 +26,10 @@ namespace ts.codefix {
const configObject = getTsConfigObjectLiteralExpression(configFile);
if (!configObject) return;
const options: [string, Expression][] = [["target", createStringLiteral("es2017")]];
const options: [string, Expression][] = [["target", factory.createStringLiteral("es2017")]];
if (moduleKind === ModuleKind.CommonJS) {
// Ensure we preserve the default module kind (commonjs), as targets >= ES2015 have a default module kind of es2015.
options.push(["module", createStringLiteral("commonjs")]);
options.push(["module", factory.createStringLiteral("commonjs")]);
}
setJsonCompilerOptionValues(tracker, configFile, options);

View File

@ -59,6 +59,6 @@ namespace ts.codefix {
}
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, returnTypeNode: TypeNode, promisedTypeNode: TypeNode): void {
changes.replaceNode(sourceFile, returnTypeNode, createTypeReferenceNode("Promise", [promisedTypeNode]));
changes.replaceNode(sourceFile, returnTypeNode, factory.createTypeReferenceNode("Promise", [promisedTypeNode]));
}
}

View File

@ -67,14 +67,14 @@ namespace ts.codefix {
if (!isIdentifierText(suggestion, target) && isPropertyAccessExpression(node.parent)) {
const valDecl = suggestedSymbol.valueDeclaration;
if (isNamedDeclaration(valDecl) && isPrivateIdentifier(valDecl.name)) {
changes.replaceNode(sourceFile, node, createIdentifier(suggestion));
changes.replaceNode(sourceFile, node, factory.createIdentifier(suggestion));
}
else {
changes.replaceNode(sourceFile, node.parent, createElementAccess(node.parent.expression, createLiteral(suggestion)));
changes.replaceNode(sourceFile, node.parent, factory.createElementAccessExpression(node.parent.expression, factory.createStringLiteral(suggestion)));
}
}
else {
changes.replaceNode(sourceFile, node, createIdentifier(suggestion));
changes.replaceNode(sourceFile, node, factory.createIdentifier(suggestion));
}
}

View File

@ -58,12 +58,12 @@ namespace ts.codefix {
}
function addDefiniteAssignmentAssertion(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void {
const property = updateProperty(
const property = factory.updatePropertyDeclaration(
propertyDeclaration,
propertyDeclaration.decorators,
propertyDeclaration.modifiers,
propertyDeclaration.name,
createToken(SyntaxKind.ExclamationToken),
factory.createToken(SyntaxKind.ExclamationToken),
propertyDeclaration.type,
propertyDeclaration.initializer
);
@ -76,10 +76,10 @@ namespace ts.codefix {
}
function addUndefinedType(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration): void {
const undefinedTypeNode = createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
const undefinedTypeNode = factory.createKeywordTypeNode(SyntaxKind.UndefinedKeyword);
const type = propertyDeclaration.type!; // TODO: GH#18217
const types = isUnionTypeNode(type) ? type.types.concat(undefinedTypeNode) : [type, undefinedTypeNode];
changeTracker.replaceNode(propertyDeclarationSourceFile, type, createUnionTypeNode(types));
changeTracker.replaceNode(propertyDeclarationSourceFile, type, factory.createUnionTypeNode(types));
}
function getActionForAddMissingInitializer(context: CodeFixContext, propertyDeclaration: PropertyDeclaration): CodeFixAction | undefined {
@ -92,7 +92,7 @@ namespace ts.codefix {
}
function addInitializer(changeTracker: textChanges.ChangeTracker, propertyDeclarationSourceFile: SourceFile, propertyDeclaration: PropertyDeclaration, initializer: Expression): void {
const property = updateProperty(
const property = factory.updatePropertyDeclaration(
propertyDeclaration,
propertyDeclaration.decorators,
propertyDeclaration.modifiers,
@ -110,10 +110,16 @@ namespace ts.codefix {
function getDefaultValueFromType(checker: TypeChecker, type: Type): Expression | undefined {
if (type.flags & TypeFlags.BooleanLiteral) {
return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? createFalse() : createTrue();
return (type === checker.getFalseType() || type === checker.getFalseType(/*fresh*/ true)) ? factory.createFalse() : factory.createTrue();
}
else if (type.isLiteral()) {
return createLiteral(type.value);
else if (type.isStringLiteral()) {
return factory.createStringLiteral(type.value);
}
else if (type.isNumberLiteral()) {
return factory.createNumericLiteral(type.value);
}
else if (type.flags & TypeFlags.BigIntLiteral) {
return factory.createBigIntLiteral((type as BigIntLiteralType).value);
}
else if (type.isUnion()) {
return firstDefined(type.types, t => getDefaultValueFromType(checker, t));
@ -125,10 +131,10 @@ namespace ts.codefix {
const constructorDeclaration = getFirstConstructorWithBody(classDeclaration);
if (constructorDeclaration && constructorDeclaration.parameters.length) return undefined;
return createNew(createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
return factory.createNewExpression(factory.createIdentifier(type.symbol.name), /*typeArguments*/ undefined, /*argumentsArray*/ undefined);
}
else if (checker.isArrayLikeType(type)) {
return createArrayLiteral();
return factory.createArrayLiteralExpression();
}
return undefined;
}

View File

@ -35,7 +35,7 @@ namespace ts.codefix {
break;
}
else {
changes.replaceNode(sourceFile, statement, createBlock(emptyArray));
changes.replaceNode(sourceFile, statement, factory.createBlock(emptyArray));
}
return;
}

View File

@ -109,7 +109,7 @@ namespace ts.codefix {
});
function changeInferToUnknown(changes: textChanges.ChangeTracker, sourceFile: SourceFile, token: Node): void {
changes.replaceNode(sourceFile, token.parent, createKeywordTypeNode(SyntaxKind.UnknownKeyword));
changes.replaceNode(sourceFile, token.parent, factory.createKeywordTypeNode(SyntaxKind.UnknownKeyword));
}
function createDeleteFix(changes: FileTextChanges[], diag: DiagnosticAndArguments): CodeFixAction {
@ -153,11 +153,11 @@ namespace ts.codefix {
token = cast(token.parent, isInferTypeNode).typeParameter.name;
}
if (isIdentifier(token) && canPrefix(token)) {
changes.replaceNode(sourceFile, token, createIdentifier(`_${token.text}`));
changes.replaceNode(sourceFile, token, factory.createIdentifier(`_${token.text}`));
if (isParameter(token.parent)) {
getJSDocParameterTags(token.parent).forEach((tag) => {
if (isIdentifier(tag.name)) {
changes.replaceNode(sourceFile, tag.name, createIdentifier(`_${tag.name.text}`));
changes.replaceNode(sourceFile, tag.name, factory.createIdentifier(`_${tag.name.text}`));
}
});
}

View File

@ -74,16 +74,16 @@ namespace ts.codefix {
}
function createPropertyName(name: string, originalName: AcceptedNameType) {
return isIdentifier(originalName) ? createIdentifier(name) : createLiteral(name);
return isIdentifier(originalName) ? factory.createIdentifier(name) : factory.createStringLiteral(name);
}
function createAccessorAccessExpression(fieldName: AcceptedNameType, isStatic: boolean, container: ContainerDeclaration) {
const leftHead = isStatic ? (<ClassLikeDeclaration>container).name! : createThis(); // TODO: GH#18217
return isIdentifier(fieldName) ? createPropertyAccess(leftHead, fieldName) : createElementAccess(leftHead, createLiteral(fieldName));
const leftHead = isStatic ? (<ClassLikeDeclaration>container).name! : factory.createThis(); // TODO: GH#18217
return isIdentifier(fieldName) ? factory.createPropertyAccessExpression(leftHead, fieldName) : factory.createElementAccessExpression(leftHead, factory.createStringLiteralFromNode(fieldName));
}
function createModifiers(modifierFlags: ModifierFlags): ModifiersArray | undefined {
return modifierFlags ? createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined;
return modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined;
}
function prepareModifierFlagsForAccessor(modifierFlags: ModifierFlags): ModifierFlags {
@ -131,14 +131,14 @@ namespace ts.codefix {
}
function generateGetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
return createGetAccessor(
return factory.createGetAccessorDeclaration(
/*decorators*/ undefined,
modifiers,
accessorName,
/*parameters*/ undefined!, // TODO: GH#18217
type,
createBlock([
createReturn(
factory.createBlock([
factory.createReturnStatement(
createAccessorAccessExpression(fieldName, isStatic, container)
)
], /*multiLine*/ true)
@ -146,23 +146,23 @@ namespace ts.codefix {
}
function generateSetAccessor(fieldName: AcceptedNameType, accessorName: AcceptedNameType, type: TypeNode | undefined, modifiers: ModifiersArray | undefined, isStatic: boolean, container: ContainerDeclaration) {
return createSetAccessor(
return factory.createSetAccessorDeclaration(
/*decorators*/ undefined,
modifiers,
accessorName,
[createParameter(
[factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
createIdentifier("value"),
factory.createIdentifier("value"),
/*questionToken*/ undefined,
type
)],
createBlock([
createStatement(
createAssignment(
factory.createBlock([
factory.createExpressionStatement(
factory.createAssignment(
createAccessorAccessExpression(fieldName, isStatic, container),
createIdentifier("value")
factory.createIdentifier("value")
)
)
], /*multiLine*/ true)
@ -170,7 +170,7 @@ namespace ts.codefix {
}
function updatePropertyDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyDeclaration, fieldName: AcceptedNameType, modifiers: ModifiersArray | undefined) {
const property = updateProperty(
const property = factory.updatePropertyDeclaration(
declaration,
declaration.decorators,
modifiers,
@ -183,7 +183,7 @@ namespace ts.codefix {
}
function updatePropertyAssignmentDeclaration(changeTracker: textChanges.ChangeTracker, file: SourceFile, declaration: PropertyAssignment, fieldName: AcceptedNameType) {
const assignment = updatePropertyAssignment(declaration, fieldName, declaration.initializer);
const assignment = factory.updatePropertyAssignment(declaration, fieldName, declaration.initializer);
changeTracker.replacePropertyAssignment(file, declaration, assignment);
}
@ -196,7 +196,7 @@ namespace ts.codefix {
}
else {
changeTracker.replaceNode(file, declaration,
updateParameter(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer));
factory.updateParameterDeclaration(declaration, declaration.decorators, modifiers, declaration.dotDotDotToken, cast(fieldName, isIdentifier), declaration.questionToken, declaration.type, declaration.initializer));
}
}
@ -214,10 +214,10 @@ namespace ts.codefix {
isStringLiteral(node.argumentExpression) &&
node.argumentExpression.text === originalName &&
isWriteAccess(node)) {
changeTracker.replaceNode(file, node.argumentExpression, createStringLiteral(fieldName));
changeTracker.replaceNode(file, node.argumentExpression, factory.createStringLiteral(fieldName));
}
if (isPropertyAccessExpression(node) && node.expression.kind === SyntaxKind.ThisKeyword && node.name.text === originalName && isWriteAccess(node)) {
changeTracker.replaceNode(file, node.name, createIdentifier(fieldName));
changeTracker.replaceNode(file, node.name, factory.createIdentifier(fieldName));
}
if (!isFunctionLike(node) && !isClassLike(node)) {
node.forEachChild(recur);

View File

@ -41,7 +41,7 @@ namespace ts.codefix {
const declaration = declarations[0];
const name = getSynthesizedDeepClone(getNameOfDeclaration(declaration), /*includeTrivia*/ false) as PropertyName;
const visibilityModifier = createVisibilityModifier(getEffectiveModifierFlags(declaration));
const modifiers = visibilityModifier ? createNodeArray([visibilityModifier]) : undefined;
const modifiers = visibilityModifier ? factory.createNodeArray([visibilityModifier]) : undefined;
const type = checker.getWidenedType(checker.getTypeOfSymbolAtLocation(symbol, enclosingDeclaration));
const optional = !!(symbol.flags & SymbolFlags.Optional);
const ambient = !!(enclosingDeclaration.flags & NodeFlags.Ambient);
@ -58,11 +58,11 @@ namespace ts.codefix {
importSymbols(importAdder, importableReference.symbols);
}
}
addClassElement(createProperty(
/*decorators*/undefined,
addClassElement(factory.createPropertyDeclaration(
/*decorators*/ undefined,
modifiers,
name,
optional ? createToken(SyntaxKind.QuestionToken) : undefined,
optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
typeNode,
/*initializer*/ undefined));
break;
@ -82,7 +82,7 @@ namespace ts.codefix {
}
for (const accessor of orderedAccessors) {
if (isGetAccessorDeclaration(accessor)) {
addClassElement(createGetAccessor(
addClassElement(factory.createGetAccessorDeclaration(
/*decorators*/ undefined,
modifiers,
name,
@ -94,7 +94,7 @@ namespace ts.codefix {
Debug.assertNode(accessor, isSetAccessorDeclaration, "The counterpart to a getter should be a setter");
const parameter = getSetAccessorValueParameter(accessor);
const parameterName = parameter && isIdentifier(parameter.name) ? idText(parameter.name) : undefined;
addClassElement(createSetAccessor(
addClassElement(factory.createSetAccessorDeclaration(
/*decorators*/ undefined,
modifiers,
name,
@ -167,49 +167,83 @@ namespace ts.codefix {
return undefined;
}
let typeParameters = signatureDeclaration.typeParameters;
let parameters = signatureDeclaration.parameters;
let type = signatureDeclaration.type;
if (importAdder) {
if (signatureDeclaration.typeParameters) {
forEach(signatureDeclaration.typeParameters, (typeParameterDecl, i) => {
if (typeParameters) {
const newTypeParameters = sameMap(typeParameters, (typeParameterDecl, i) => {
const typeParameter = signature.typeParameters![i];
if (typeParameterDecl.constraint) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeParameterDecl.constraint, typeParameter.constraint, scriptTarget);
let constraint = typeParameterDecl.constraint;
let defaultType = typeParameterDecl.default;
if (constraint) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(constraint, typeParameter.constraint, scriptTarget);
if (importableReference) {
typeParameterDecl.constraint = importableReference.typeReference;
constraint = importableReference.typeReference;
importSymbols(importAdder, importableReference.symbols);
}
}
if (typeParameterDecl.default) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(typeParameterDecl.default, typeParameter.default, scriptTarget);
if (defaultType) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(defaultType, typeParameter.default, scriptTarget);
if (importableReference) {
typeParameterDecl.default = importableReference.typeReference;
defaultType = importableReference.typeReference;
importSymbols(importAdder, importableReference.symbols);
}
}
return factory.updateTypeParameterDeclaration(
typeParameterDecl,
typeParameterDecl.name,
constraint,
defaultType
);
});
if (typeParameters !== newTypeParameters) {
typeParameters = setTextRange(factory.createNodeArray(newTypeParameters, typeParameters.hasTrailingComma), typeParameters);
}
}
forEach(signatureDeclaration.parameters, (parameterDecl, i) => {
const newParameters = sameMap(parameters, (parameterDecl, i) => {
const parameter = signature.parameters[i];
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(parameterDecl.type, checker.getTypeAtLocation(parameter.valueDeclaration), scriptTarget);
let type = parameterDecl.type;
if (importableReference) {
parameterDecl.type = importableReference.typeReference;
type = importableReference.typeReference;
importSymbols(importAdder, importableReference.symbols);
}
return factory.updateParameterDeclaration(
parameterDecl,
parameterDecl.decorators,
parameterDecl.modifiers,
parameterDecl.dotDotDotToken,
parameterDecl.name,
parameterDecl.questionToken,
type,
parameterDecl.initializer
);
});
if (signatureDeclaration.type) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(signatureDeclaration.type, signature.resolvedReturnType, scriptTarget);
if (parameters !== newParameters) {
parameters = setTextRange(factory.createNodeArray(newParameters, parameters.hasTrailingComma), parameters);
}
if (type) {
const importableReference = tryGetAutoImportableReferenceFromImportTypeNode(type, signature.resolvedReturnType, scriptTarget);
if (importableReference) {
signatureDeclaration.type = importableReference.typeReference;
type = importableReference.typeReference;
importSymbols(importAdder, importableReference.symbols);
}
}
}
signatureDeclaration.decorators = undefined;
signatureDeclaration.modifiers = modifiers;
signatureDeclaration.name = name;
signatureDeclaration.questionToken = optional ? createToken(SyntaxKind.QuestionToken) : undefined;
signatureDeclaration.body = body;
return signatureDeclaration;
return factory.updateMethodDeclaration(
signatureDeclaration,
/*decorators*/ undefined,
modifiers,
signatureDeclaration.asteriskToken,
name,
optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
typeParameters,
parameters,
type,
body
);
}
export function createMethodFromCallExpression(
@ -232,14 +266,14 @@ namespace ts.codefix {
isIdentifier(arg) ? arg.text : isPropertyAccessExpression(arg) && isIdentifier(arg.name) ? arg.name.text : undefined);
const contextualType = checker.getContextualType(call);
const returnType = (inJs || !contextualType) ? undefined : checker.typeToTypeNode(contextualType, contextNode, /*flags*/ undefined, tracker);
return createMethod(
return factory.createMethodDeclaration(
/*decorators*/ undefined,
/*modifiers*/ modifierFlags ? createNodeArray(createModifiersFromModifierFlags(modifierFlags)) : undefined,
/*asteriskToken*/ isYieldExpression(parent) ? createToken(SyntaxKind.AsteriskToken) : undefined,
/*modifiers*/ modifierFlags ? factory.createNodeArray(factory.createModifiersFromModifierFlags(modifierFlags)) : undefined,
/*asteriskToken*/ isYieldExpression(parent) ? factory.createToken(SyntaxKind.AsteriskToken) : undefined,
methodName,
/*questionToken*/ undefined,
/*typeParameters*/ inJs ? undefined : map(typeArguments, (_, i) =>
createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)),
factory.createTypeParameterDeclaration(CharacterCodes.T + typeArguments!.length - 1 <= CharacterCodes.Z ? String.fromCharCode(CharacterCodes.T + i) : `T${i}`)),
/*parameters*/ createDummyParameters(args.length, names, types, /*minArgumentCount*/ undefined, inJs),
/*type*/ returnType,
body ? createStubbedMethodBody(context.preferences) : undefined);
@ -260,13 +294,13 @@ namespace ts.codefix {
function createDummyParameters(argCount: number, names: (string | undefined)[] | undefined, types: (TypeNode | undefined)[] | undefined, minArgumentCount: number | undefined, inJs: boolean): ParameterDeclaration[] {
const parameters: ParameterDeclaration[] = [];
for (let i = 0; i < argCount; i++) {
const newParameter = createParameter(
const newParameter = factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
/*name*/ names && names[i] || `arg${i}`,
/*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
/*type*/ inJs ? undefined : types && types[i] || createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*questionToken*/ minArgumentCount !== undefined && i >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
/*type*/ inJs ? undefined : types && types[i] || factory.createKeywordTypeNode(SyntaxKind.AnyKeyword),
/*initializer*/ undefined);
parameters.push(newParameter);
}
@ -302,13 +336,13 @@ namespace ts.codefix {
const parameters = createDummyParameters(maxNonRestArgs, maxArgsParameterSymbolNames, /* types */ undefined, minArgumentCount, /*inJs*/ false);
if (someSigHasRestParameter) {
const anyArrayType = createArrayTypeNode(createKeywordTypeNode(SyntaxKind.AnyKeyword));
const restParameter = createParameter(
const anyArrayType = factory.createArrayTypeNode(factory.createKeywordTypeNode(SyntaxKind.AnyKeyword));
const restParameter = factory.createParameterDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createToken(SyntaxKind.DotDotDotToken),
factory.createToken(SyntaxKind.DotDotDotToken),
maxArgsParameterSymbolNames[maxNonRestArgs] || "rest",
/*questionToken*/ maxNonRestArgs >= minArgumentCount ? createToken(SyntaxKind.QuestionToken) : undefined,
/*questionToken*/ maxNonRestArgs >= minArgumentCount ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
anyArrayType,
/*initializer*/ undefined);
parameters.push(restParameter);
@ -333,12 +367,12 @@ namespace ts.codefix {
returnType: TypeNode | undefined,
preferences: UserPreferences
): MethodDeclaration {
return createMethod(
return factory.createMethodDeclaration(
/*decorators*/ undefined,
modifiers,
/*asteriskToken*/ undefined,
name,
optional ? createToken(SyntaxKind.QuestionToken) : undefined,
optional ? factory.createToken(SyntaxKind.QuestionToken) : undefined,
typeParameters,
parameters,
returnType,
@ -346,22 +380,22 @@ namespace ts.codefix {
}
function createStubbedMethodBody(preferences: UserPreferences): Block {
return createBlock(
[createThrow(
createNew(
createIdentifier("Error"),
return factory.createBlock(
[factory.createThrowStatement(
factory.createNewExpression(
factory.createIdentifier("Error"),
/*typeArguments*/ undefined,
// TODO Handle auto quote preference.
[createLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))],
[factory.createStringLiteral("Method not implemented.", /*isSingleQuote*/ preferences.quotePreference === "single")]))],
/*multiline*/ true);
}
function createVisibilityModifier(flags: ModifierFlags): Modifier | undefined {
if (flags & ModifierFlags.Public) {
return createToken(SyntaxKind.PublicKeyword);
return factory.createToken(SyntaxKind.PublicKeyword);
}
else if (flags & ModifierFlags.Protected) {
return createToken(SyntaxKind.ProtectedKeyword);
return factory.createToken(SyntaxKind.ProtectedKeyword);
}
return undefined;
}
@ -378,7 +412,7 @@ namespace ts.codefix {
if (compilerOptionsProperty === undefined) {
changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment(
"compilerOptions",
createObjectLiteral(options.map(([optionName, optionValue]) => createJsonPropertyAssignment(optionName, optionValue)), /*multiLine*/ true)));
factory.createObjectLiteralExpression(options.map(([optionName, optionValue]) => createJsonPropertyAssignment(optionName, optionValue)), /*multiLine*/ true)));
return;
}
@ -408,7 +442,7 @@ namespace ts.codefix {
}
export function createJsonPropertyAssignment(name: string, initializer: Expression) {
return createPropertyAssignment(createStringLiteral(name), initializer);
return factory.createPropertyAssignment(factory.createStringLiteral(name), initializer);
}
export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined {
@ -426,7 +460,7 @@ namespace ts.codefix {
const firstIdentifier = getFirstIdentifier(importTypeNode.qualifier);
const name = getNameForExportedSymbol(firstIdentifier.symbol, scriptTarget);
const qualifier = name !== firstIdentifier.text
? replaceFirstIdentifierOfEntityName(importTypeNode.qualifier, createIdentifier(name))
? replaceFirstIdentifierOfEntityName(importTypeNode.qualifier, factory.createIdentifier(name))
: importTypeNode.qualifier;
const symbols = [firstIdentifier.symbol];
@ -446,7 +480,7 @@ namespace ts.codefix {
return {
symbols,
typeReference: createTypeReferenceNode(qualifier, typeArguments)
typeReference: factory.createTypeReferenceNode(qualifier, typeArguments)
};
}
}
@ -455,7 +489,7 @@ namespace ts.codefix {
if (name.kind === SyntaxKind.Identifier) {
return newIdentifier;
}
return createQualifiedName(replaceFirstIdentifierOfEntityName(name.left, newIdentifier), name.right);
return factory.createQualifiedName(replaceFirstIdentifierOfEntityName(name.left, newIdentifier), name.right);
}
export function importSymbols(importAdder: ImportAdder, symbols: readonly Symbol[]) {

View File

@ -660,11 +660,11 @@ namespace ts.codefix {
const convertTypeOnlyToRegular = !canUseTypeOnlyImport && clause.isTypeOnly;
if (defaultImport) {
Debug.assert(!clause.name, "Cannot add a default import to an import clause that already has one");
changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), createIdentifier(defaultImport), { suffix: ", " });
changes.insertNodeAt(sourceFile, clause.getStart(sourceFile), factory.createIdentifier(defaultImport), { suffix: ", " });
}
if (namedImports.length) {
const specifiers = namedImports.map(name => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(name)));
const specifiers = namedImports.map(name => factory.createImportSpecifier(/*propertyName*/ undefined, factory.createIdentifier(name)));
if (clause.namedBindings && cast(clause.namedBindings, isNamedImports).elements.length) {
for (const spec of specifiers) {
changes.insertNodeInListAfter(sourceFile, last(cast(clause.namedBindings, isNamedImports).elements), spec);
@ -672,7 +672,7 @@ namespace ts.codefix {
}
else {
if (specifiers.length) {
const namedImports = createNamedImports(specifiers);
const namedImports = factory.createNamedImports(specifiers);
if (clause.namedBindings) {
changes.replaceNode(sourceFile, clause.namedBindings, namedImports);
}
@ -688,12 +688,12 @@ namespace ts.codefix {
}
function addElementToBindingPattern(bindingPattern: ObjectBindingPattern, name: string, propertyName: string | undefined) {
const element = createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name);
const element = factory.createBindingElement(/*dotDotDotToken*/ undefined, propertyName, name);
if (bindingPattern.elements.length) {
changes.insertNodeInListAfter(sourceFile, last(bindingPattern.elements), element);
}
else {
changes.replaceNode(sourceFile, bindingPattern, createObjectBindingPattern([element]));
changes.replaceNode(sourceFile, bindingPattern, factory.createObjectBindingPattern([element]));
}
}
}
@ -725,24 +725,24 @@ namespace ts.codefix {
let statements: Statement | readonly Statement[] | undefined;
if (imports.defaultImport !== undefined || imports.namedImports?.length) {
statements = combine(statements, makeImport(
imports.defaultImport === undefined ? undefined : createIdentifier(imports.defaultImport),
imports.namedImports?.map(n => createImportSpecifier(/*propertyName*/ undefined, createIdentifier(n))), moduleSpecifier, quotePreference, imports.typeOnly));
imports.defaultImport === undefined ? undefined : factory.createIdentifier(imports.defaultImport),
imports.namedImports?.map(n => factory.createImportSpecifier(/*propertyName*/ undefined, factory.createIdentifier(n))), moduleSpecifier, quotePreference, imports.typeOnly));
}
const { namespaceLikeImport, typeOnly } = imports;
if (namespaceLikeImport) {
const declaration = namespaceLikeImport.importKind === ImportKind.CommonJS
? createImportEqualsDeclaration(
? factory.createImportEqualsDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createIdentifier(namespaceLikeImport.name),
createExternalModuleReference(quotedModuleSpecifier))
: createImportDeclaration(
factory.createIdentifier(namespaceLikeImport.name),
factory.createExternalModuleReference(quotedModuleSpecifier))
: factory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
createImportClause(
factory.createImportClause(
typeOnly,
/*name*/ undefined,
createNamespaceImport(createIdentifier(namespaceLikeImport.name)),
typeOnly),
factory.createNamespaceImport(factory.createIdentifier(namespaceLikeImport.name))),
quotedModuleSpecifier);
statements = combine(statements, declaration);
}
@ -754,11 +754,11 @@ namespace ts.codefix {
let statements: Statement | readonly Statement[] | undefined;
// const { default: foo, bar, etc } = require('./mod');
if (imports.defaultImport || imports.namedImports?.length) {
const bindingElements = imports.namedImports?.map(name => createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name)) || [];
const bindingElements = imports.namedImports?.map(name => factory.createBindingElement(/*dotDotDotToken*/ undefined, /*propertyName*/ undefined, name)) || [];
if (imports.defaultImport) {
bindingElements.unshift(createBindingElement(/*dotDotDotToken*/ undefined, "default", imports.defaultImport));
bindingElements.unshift(factory.createBindingElement(/*dotDotDotToken*/ undefined, "default", imports.defaultImport));
}
const declaration = createConstEqualsRequireDeclaration(createObjectBindingPattern(bindingElements), quotedModuleSpecifier);
const declaration = createConstEqualsRequireDeclaration(factory.createObjectBindingPattern(bindingElements), quotedModuleSpecifier);
statements = combine(statements, declaration);
}
// const foo = require('./mod');
@ -770,13 +770,14 @@ namespace ts.codefix {
}
function createConstEqualsRequireDeclaration(name: string | ObjectBindingPattern, quotedModuleSpecifier: StringLiteral): VariableStatement {
return createVariableStatement(
return factory.createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
typeof name === "string" ? createIdentifier(name) : name,
factory.createVariableDeclarationList([
factory.createVariableDeclaration(
typeof name === "string" ? factory.createIdentifier(name) : name,
/*exclamationToken*/ undefined,
/*type*/ undefined,
createCall(createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]))],
factory.createCallExpression(factory.createIdentifier("require"), /*typeArguments*/ undefined, [quotedModuleSpecifier]))],
NodeFlags.Const));
}

View File

@ -128,7 +128,7 @@ namespace ts.codefix {
const typeNode = getTypeNodeIfAccessible(type, parent, program, host);
if (typeNode) {
// Note that the codefix will never fire with an existing `@type` tag, so there is no need to merge tags
const typeTag = createJSDocTypeTag(createJSDocTypeExpression(typeNode), /*comment*/ "");
const typeTag = factory.createJSDocTypeTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode), /*comment*/ "");
addJSDocTags(changes, sourceFile, cast(parent.parent.parent, isExpressionStatement), [typeTag]);
}
importAdder.writeFixes(changes);
@ -239,13 +239,13 @@ namespace ts.codefix {
}
else {
const needParens = isArrowFunction(containingFunction) && !findChildOfKind(containingFunction, SyntaxKind.OpenParenToken, sourceFile);
if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), createToken(SyntaxKind.OpenParenToken));
if (needParens) changes.insertNodeBefore(sourceFile, first(containingFunction.parameters), factory.createToken(SyntaxKind.OpenParenToken));
for (const { declaration, type } of parameterInferences) {
if (declaration && !declaration.type && !declaration.initializer) {
annotate(changes, importAdder, sourceFile, declaration, type, program, host);
}
}
if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), createToken(SyntaxKind.CloseParenToken));
if (needParens) changes.insertNodeAfter(sourceFile, last(containingFunction.parameters), factory.createToken(SyntaxKind.CloseParenToken));
}
}
@ -270,7 +270,7 @@ namespace ts.codefix {
function annotateJSDocThis(changes: textChanges.ChangeTracker, sourceFile: SourceFile, containingFunction: FunctionLike, typeNode: TypeNode) {
addJSDocTags(changes, sourceFile, containingFunction, [
createJSDocThisTag(createJSDocTypeExpression(typeNode)),
factory.createJSDocThisTag(/*tagName*/ undefined, factory.createJSDocTypeExpression(typeNode)),
]);
}
@ -306,8 +306,8 @@ namespace ts.codefix {
if (!parent) {
return;
}
const typeExpression = createJSDocTypeExpression(typeNode);
const typeTag = isGetAccessorDeclaration(declaration) ? createJSDocReturnTag(typeExpression, "") : createJSDocTypeTag(typeExpression, "");
const typeExpression = factory.createJSDocTypeExpression(typeNode);
const typeTag = isGetAccessorDeclaration(declaration) ? factory.createJSDocReturnTag(/*tagName*/ undefined, typeExpression, "") : factory.createJSDocTypeTag(/*tagName*/ undefined, typeExpression, "");
addJSDocTags(changes, sourceFile, parent, [typeTag]);
}
else if (!tryReplaceImportTypeNodeWithAutoImport(typeNode, declaration, type, sourceFile, changes, importAdder, getEmitScriptTarget(program.getCompilerOptions()))) {
@ -344,9 +344,9 @@ namespace ts.codefix {
if (param.initializer || getJSDocType(param) || !isIdentifier(param.name)) return;
const typeNode = inference.type && getTypeNodeIfAccessible(inference.type, param, program, host);
const name = getSynthesizedClone(param.name);
const name = factory.cloneNode(param.name);
setEmitFlags(name, EmitFlags.NoComments | EmitFlags.NoNestedComments);
return typeNode && createJSDocParameterTag(createJSDocTypeExpression(typeNode), name, /* isNameFirst */ false, !!inference.isOptional, "");
return typeNode && factory.createJSDocParameterTag(/*tagName*/ undefined, name, /*isBracketed*/ !!inference.isOptional, factory.createJSDocTypeExpression(typeNode), /* isNameFirst */ false, "");
});
addJSDocTags(changes, sourceFile, signature, paramTags);
}
@ -359,7 +359,7 @@ namespace ts.codefix {
if (merged) oldTags[i] = merged;
return !!merged;
}));
const tag = createJSDocComment(comments.join("\n"), createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags]));
const tag = factory.createJSDocComment(comments.join("\n"), factory.createNodeArray([...(oldTags || emptyArray), ...unmergedNewTags]));
const jsDocNode = parent.kind === SyntaxKind.ArrowFunction ? getJsDocNodeForArrowFunction(parent) : parent;
jsDocNode.jsDoc = parent.jsDoc;
jsDocNode.jsDocCache = parent.jsDocCache;
@ -382,11 +382,11 @@ namespace ts.codefix {
const oldParam = oldTag as JSDocParameterTag;
const newParam = newTag as JSDocParameterTag;
return isIdentifier(oldParam.name) && isIdentifier(newParam.name) && oldParam.name.escapedText === newParam.name.escapedText
? createJSDocParameterTag(newParam.typeExpression, newParam.name, newParam.isNameFirst, newParam.isBracketed, oldParam.comment)
? factory.createJSDocParameterTag(/*tagName*/ undefined, newParam.name, /*isBracketed*/ false, newParam.typeExpression, newParam.isNameFirst, oldParam.comment)
: undefined;
}
case SyntaxKind.JSDocReturnTag:
return createJSDocReturnTag((newTag as JSDocReturnTag).typeExpression, oldTag.comment);
return factory.createJSDocReturnTag(/*tagName*/ undefined, (newTag as JSDocReturnTag).typeExpression, oldTag.comment);
}
}

View File

@ -24,8 +24,8 @@ namespace ts.codefix {
function doChange(changes: textChanges.ChangeTracker, sourceFile: SourceFile, info: Info) {
const { allowSyntheticDefaults, defaultImportName, namedImports, statement, required } = info;
changes.replaceNode(sourceFile, statement, defaultImportName && !allowSyntheticDefaults
? createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, defaultImportName, createExternalModuleReference(required))
: createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createImportClause(defaultImportName, namedImports), required));
? factory.createImportEqualsDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, defaultImportName, factory.createExternalModuleReference(required))
: factory.createImportDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, factory.createImportClause(/*isTypeOnly*/ false, defaultImportName, namedImports), required));
}
interface Info {
@ -62,11 +62,11 @@ namespace ts.codefix {
if (!isIdentifier(element.name) || element.initializer) {
return undefined;
}
importSpecifiers.push(createImportSpecifier(tryCast(element.propertyName, isIdentifier), element.name));
importSpecifiers.push(factory.createImportSpecifier(tryCast(element.propertyName, isIdentifier), element.name));
}
if (importSpecifiers.length) {
return createNamedImports(importSpecifiers);
return factory.createNamedImports(importSpecifiers);
}
}
}

View File

@ -72,11 +72,18 @@ namespace ts.codefix {
}),
});
function createObjectTypeFromLabeledExpression(checker: TypeChecker, label: Identifier, expression: Expression) {
const member = checker.createSymbol(SymbolFlags.Property, label.escapedText);
member.type = checker.getTypeAtLocation(expression);
const members = createSymbolTable([member]);
return checker.createAnonymousType(/*symbol*/ undefined, members, [], [], /*stringIndexInfo*/ undefined, /*numberIndexInfo*/ undefined);
}
function getFixInfo(checker: TypeChecker, declaration: FunctionLikeDeclaration, expectType: Type, isFunctionType: boolean): Info | undefined {
if (!declaration.body || !isBlock(declaration.body) || length(declaration.body.statements) !== 1) return undefined;
const firstStatement = first(declaration.body.statements);
if (isExpressionStatement(firstStatement) && checkFixedAssignableTo(checker, declaration, firstStatement.expression, expectType, isFunctionType)) {
if (isExpressionStatement(firstStatement) && checkFixedAssignableTo(checker, declaration, checker.getTypeAtLocation(firstStatement.expression), expectType, isFunctionType)) {
return {
declaration,
kind: ProblemKind.MissingReturnStatement,
@ -86,8 +93,9 @@ namespace ts.codefix {
};
}
else if (isLabeledStatement(firstStatement) && isExpressionStatement(firstStatement.statement)) {
const node = createObjectLiteral([createPropertyAssignment(firstStatement.label, firstStatement.statement.expression)]);
if (checkFixedAssignableTo(checker, declaration, node, expectType, isFunctionType)) {
const node = factory.createObjectLiteralExpression([factory.createPropertyAssignment(firstStatement.label, firstStatement.statement.expression)]);
const nodeType = createObjectTypeFromLabeledExpression(checker, firstStatement.label, firstStatement.statement.expression);
if (checkFixedAssignableTo(checker, declaration, nodeType, expectType, isFunctionType)) {
return isArrowFunction(declaration) ? {
declaration,
kind: ProblemKind.MissingParentheses,
@ -106,8 +114,9 @@ namespace ts.codefix {
else if (isBlock(firstStatement) && length(firstStatement.statements) === 1) {
const firstBlockStatement = first(firstStatement.statements);
if (isLabeledStatement(firstBlockStatement) && isExpressionStatement(firstBlockStatement.statement)) {
const node = createObjectLiteral([createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression)]);
if (checkFixedAssignableTo(checker, declaration, node, expectType, isFunctionType)) {
const node = factory.createObjectLiteralExpression([factory.createPropertyAssignment(firstBlockStatement.label, firstBlockStatement.statement.expression)]);
const nodeType = createObjectTypeFromLabeledExpression(checker, firstBlockStatement.label, firstBlockStatement.statement.expression);
if (checkFixedAssignableTo(checker, declaration, nodeType, expectType, isFunctionType)) {
return {
declaration,
kind: ProblemKind.MissingReturnStatement,
@ -122,8 +131,35 @@ namespace ts.codefix {
return undefined;
}
function checkFixedAssignableTo(checker: TypeChecker, declaration: FunctionLikeDeclaration, expr: Expression, type: Type, isFunctionType: boolean) {
return checker.isTypeAssignableTo(checker.getTypeAtLocation(isFunctionType ? updateFunctionLikeBody(declaration, createBlock([createReturn(expr)])) : expr), type);
function checkFixedAssignableTo(checker: TypeChecker, declaration: FunctionLikeDeclaration, exprType: Type, type: Type, isFunctionType: boolean) {
if (isFunctionType) {
const sig = checker.getSignatureFromDeclaration(declaration);
if (sig) {
if (hasSyntacticModifier(declaration, ModifierFlags.Async)) {
exprType = checker.createPromiseType(exprType);
}
const newSig = checker.createSignature(
declaration,
sig.typeParameters,
sig.thisParameter,
sig.parameters,
exprType,
/*typePredicate*/ undefined,
sig.minArgumentCount,
sig.flags);
exprType = checker.createAnonymousType(
/*symbol*/ undefined,
createSymbolTable(),
[newSig],
[],
/*stringIndexInfo*/ undefined,
/*numberIndexInfo*/ undefined);
}
else {
exprType = checker.getAnyType();
}
}
return checker.isTypeAssignableTo(exprType, type);
}
function getInfo(checker: TypeChecker, sourceFile: SourceFile, position: number, errorCode: number): Info | undefined {
@ -172,7 +208,7 @@ namespace ts.codefix {
function addReturnStatement(changes: textChanges.ChangeTracker, sourceFile: SourceFile, expression: Expression, statement: Statement) {
suppressLeadingAndTrailingTrivia(expression);
const probablyNeedSemi = probablyUsesSemicolons(sourceFile);
changes.replaceNode(sourceFile, statement, createReturn(expression), {
changes.replaceNode(sourceFile, statement, factory.createReturnStatement(expression), {
leadingTriviaOption: textChanges.LeadingTriviaOption.Exclude,
trailingTriviaOption: textChanges.TrailingTriviaOption.Exclude,
suffix: probablyNeedSemi ? ";" : undefined
@ -180,7 +216,7 @@ namespace ts.codefix {
}
function removeBlockBodyBrace(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression, commentSource: Node, withParen: boolean) {
const newBody = (withParen || needsParentheses(expression)) ? createParen(expression) : expression;
const newBody = (withParen || needsParentheses(expression)) ? factory.createParenthesizedExpression(expression) : expression;
suppressLeadingAndTrailingTrivia(commentSource);
copyComments(commentSource, newBody);
@ -188,7 +224,7 @@ namespace ts.codefix {
}
function wrapBlockWithParen(changes: textChanges.ChangeTracker, sourceFile: SourceFile, declaration: ArrowFunction, expression: Expression) {
changes.replaceNode(sourceFile, declaration.body, createParen(expression));
changes.replaceNode(sourceFile, declaration.body, factory.createParenthesizedExpression(expression));
}
function getActionForfixAddReturnStatement(context: CodeFixContext, expression: Expression, statement: Statement) {

View File

@ -27,17 +27,17 @@ namespace ts.codefix {
return;
}
const importClause = Debug.checkDefined(importDeclaration.importClause);
changes.replaceNode(context.sourceFile, importDeclaration, updateImportDeclaration(
changes.replaceNode(context.sourceFile, importDeclaration, factory.updateImportDeclaration(
importDeclaration,
importDeclaration.decorators,
importDeclaration.modifiers,
updateImportClause(importClause, importClause.name, /*namedBindings*/ undefined, importClause.isTypeOnly),
factory.updateImportClause(importClause, importClause.isTypeOnly, importClause.name, /*namedBindings*/ undefined),
importDeclaration.moduleSpecifier));
changes.insertNodeAfter(context.sourceFile, importDeclaration, createImportDeclaration(
changes.insertNodeAfter(context.sourceFile, importDeclaration, factory.createImportDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
updateImportClause(importClause, /*name*/ undefined, importClause.namedBindings, importClause.isTypeOnly),
factory.updateImportClause(importClause, importClause.isTypeOnly, /*name*/ undefined, importClause.namedBindings),
importDeclaration.moduleSpecifier));
}
}

View File

@ -28,6 +28,6 @@ namespace ts.codefix {
// We use .getText to overcome parser inaccuracies: https://github.com/microsoft/TypeScript/issues/33298
const newText = numericLiteral.getText(sourceFile) + "n";
changeTracker.replaceNode(sourceFile, numericLiteral, createBigIntLiteral(newText));
changeTracker.replaceNode(sourceFile, numericLiteral, factory.createBigIntLiteral(newText));
}
}

View File

@ -40,7 +40,7 @@ namespace ts.codefix {
function doChange(changeTracker: textChanges.ChangeTracker, sf: SourceFile, node: Node) {
const jsx = flattenInvalidBinaryExpr(node);
if (jsx) changeTracker.replaceNode(sf, node, createJsxFragment(createJsxOpeningFragment(), jsx, createJsxJsxClosingFragment()));
if (jsx) changeTracker.replaceNode(sf, node, factory.createJsxFragment(factory.createJsxOpeningFragment(), jsx, factory.createJsxJsxClosingFragment()));
}
// The invalid syntax is constructed as
// InvalidJsxTree :: One of

View File

@ -65,7 +65,7 @@ namespace ts {
// If there isn't some include for this, add a new one.
if (getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(oldFileOrDirPath) &&
!getRegexFromPattern(Debug.checkDefined(matchers.includeFilePattern), useCaseSensitiveFileNames).test(newFileOrDirPath)) {
changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), createStringLiteral(relativePath(newFileOrDirPath)));
changeTracker.insertNodeAfter(configFile, last(property.initializer.elements), factory.createStringLiteral(relativePath(newFileOrDirPath)));
}
}
break;

View File

@ -389,7 +389,7 @@ namespace ts.NavigationBar {
const memberName = defineCall.arguments[1];
const [depth, classNameIdentifier] = startNestedNodes(node, className);
startNode(node, classNameIdentifier);
startNode(node, setTextRange(createIdentifier(memberName.text), memberName));
startNode(node, setTextRange(factory.createIdentifier(memberName.text), memberName));
addChildrenRecursively((node as CallExpression).arguments[2]);
endNode();
endNode();
@ -521,7 +521,7 @@ namespace ts.NavigationBar {
if (ctorFunction !== undefined) {
const ctorNode = setTextRange(
createConstructor(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined),
factory.createConstructorDeclaration(/* decorators */ undefined, /* modifiers */ undefined, [], /* body */ undefined),
ctorFunction);
const ctor = emptyNavigationBarNode(ctorNode);
ctor.indent = a.indent + 1;
@ -538,10 +538,10 @@ namespace ts.NavigationBar {
}
}
lastANode = a.node = setTextRange(createClassDeclaration(
lastANode = a.node = setTextRange(factory.createClassDeclaration(
/* decorators */ undefined,
/* modifiers */ undefined,
a.name as Identifier || createIdentifier("__class__"),
a.name as Identifier || factory.createIdentifier("__class__"),
/* typeParameters */ undefined,
/* heritageClauses */ undefined,
[]
@ -566,10 +566,10 @@ namespace ts.NavigationBar {
}
else {
if (!a.additionalNodes) a.additionalNodes = [];
a.additionalNodes.push(setTextRange(createClassDeclaration(
a.additionalNodes.push(setTextRange(factory.createClassDeclaration(
/* decorators */ undefined,
/* modifiers */ undefined,
a.name as Identifier || createIdentifier("__class__"),
a.name as Identifier || factory.createIdentifier("__class__"),
/* typeParameters */ undefined,
/* heritageClauses */ undefined,
[]

View File

@ -116,7 +116,7 @@ namespace ts.OrganizeImports {
const newElements = namedBindings.elements.filter(e => isDeclarationUsed(e.name));
if (newElements.length < namedBindings.elements.length) {
namedBindings = newElements.length
? updateNamedImports(namedBindings, newElements)
? factory.updateNamedImports(namedBindings, newElements)
: undefined;
}
}
@ -129,7 +129,7 @@ namespace ts.OrganizeImports {
else if (hasModuleDeclarationMatchingSpecifier(sourceFile, moduleSpecifier)) {
// If were in a declaration file, its safe to remove the import clause from it
if (sourceFile.isDeclarationFile) {
usedImports.push(createImportDeclaration(
usedImports.push(factory.createImportDeclaration(
importDecl.decorators,
importDecl.modifiers,
/*importClause*/ undefined,
@ -217,7 +217,7 @@ namespace ts.OrganizeImports {
else {
for (const defaultImport of defaultImports) {
newImportSpecifiers.push(
createImportSpecifier(createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217
factory.createImportSpecifier(factory.createIdentifier("default"), defaultImport.importClause!.name!)); // TODO: GH#18217
}
}
@ -232,10 +232,10 @@ namespace ts.OrganizeImports {
const newNamedImports = sortedImportSpecifiers.length === 0
? newDefaultImport
? undefined
: createNamedImports(emptyArray)
: factory.createNamedImports(emptyArray)
: namedImports.length === 0
? createNamedImports(sortedImportSpecifiers)
: updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217
? factory.createNamedImports(sortedImportSpecifiers)
: factory.updateNamedImports(namedImports[0].importClause!.namedBindings as NamedImports, sortedImportSpecifiers); // TODO: GH#18217
// Type-only imports are not allowed to mix default, namespace, and named imports in any combination.
// We could rewrite a default import as a named import (`import { default as name }`), but we currently
@ -334,17 +334,17 @@ namespace ts.OrganizeImports {
const exportDecl = exportGroup[0];
coalescedExports.push(
updateExportDeclaration(
factory.updateExportDeclaration(
exportDecl,
exportDecl.decorators,
exportDecl.modifiers,
exportDecl.isTypeOnly,
exportDecl.exportClause && (
isNamedExports(exportDecl.exportClause) ?
updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) :
updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name)
factory.updateNamedExports(exportDecl.exportClause, sortedExportSpecifiers) :
factory.updateNamespaceExport(exportDecl.exportClause, exportDecl.exportClause.name)
),
exportDecl.moduleSpecifier,
exportDecl.isTypeOnly));
exportDecl.moduleSpecifier));
}
return coalescedExports;
@ -386,11 +386,11 @@ namespace ts.OrganizeImports {
name: Identifier | undefined,
namedBindings: NamedImportBindings | undefined) {
return updateImportDeclaration(
return factory.updateImportDeclaration(
importDeclaration,
importDeclaration.decorators,
importDeclaration.modifiers,
updateImportClause(importDeclaration.importClause!, name, namedBindings, importDeclaration.importClause!.isTypeOnly), // TODO: GH#18217
factory.updateImportClause(importDeclaration.importClause!, importDeclaration.importClause!.isTypeOnly, name, namedBindings), // TODO: GH#18217
importDeclaration.moduleSpecifier);
}

View File

@ -46,14 +46,14 @@ namespace ts.refactor.addOrRemoveBracesToArrowFunction {
let body: ConciseBody;
if (actionName === addBracesActionName) {
const returnStatement = createReturn(expression);
body = createBlock([returnStatement], /* multiLine */ true);
const returnStatement = factory.createReturnStatement(expression);
body = factory.createBlock([returnStatement], /* multiLine */ true);
suppressLeadingAndTrailingTrivia(body);
copyLeadingComments(expression!, returnStatement, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ true);
}
else if (actionName === removeBracesActionName && returnStatement) {
const actualExpression = expression || createVoidZero();
body = needsParentheses(actualExpression) ? createParen(actualExpression) : actualExpression;
const actualExpression = expression || factory.createVoidZero();
body = needsParentheses(actualExpression) ? factory.createParenthesizedExpression(actualExpression) : actualExpression;
suppressLeadingAndTrailingTrivia(body);
copyTrailingAsLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);
copyLeadingComments(returnStatement, body, file, SyntaxKind.MultiLineCommentTrivia, /* hasTrailingNewLine */ false);

View File

@ -147,7 +147,7 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
function convertToBlock(body: ConciseBody): Block {
if (isExpression(body)) {
return createBlock([createReturn(body)], /* multiLine */ true);
return factory.createBlock([factory.createReturnStatement(body)], /* multiLine */ true);
}
else {
return body;
@ -168,7 +168,7 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
function getEditInfoForConvertToAnonymousFunction(context: RefactorContext, func: FunctionExpression | ArrowFunction): FileTextChanges[] {
const { file } = context;
const body = convertToBlock(func.body);
const newNode = createFunctionExpression(func.modifiers, func.asteriskToken, /* name */ undefined, func.typeParameters, func.parameters, func.type, body);
const newNode = factory.createFunctionExpression(func.modifiers, func.asteriskToken, /* name */ undefined, func.typeParameters, func.parameters, func.type, body);
return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode));
}
@ -178,7 +178,7 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
const { variableDeclaration, variableDeclarationList, statement, name } = variableInfo;
suppressLeadingTrivia(statement);
const newNode = createFunctionDeclaration(func.decorators, statement.modifiers, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body);
const newNode = factory.createFunctionDeclaration(func.decorators, statement.modifiers, func.asteriskToken, name, func.typeParameters, func.parameters, func.type, body);
if (variableDeclarationList.declarations.length === 1) {
return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, statement, newNode));
@ -206,7 +206,7 @@ namespace ts.refactor.convertArrowFunctionOrFunctionExpression {
body = func.body;
}
const newNode = createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, createToken(SyntaxKind.EqualsGreaterThanToken), body);
const newNode = factory.createArrowFunction(func.modifiers, func.typeParameters, func.parameters, func.type, factory.createToken(SyntaxKind.EqualsGreaterThanToken), body);
return textChanges.ChangeTracker.with(context, t => t.replaceNode(file, func, newNode));
}

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