mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-22 16:52:14 -06:00
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:
parent
0232d4ae8e
commit
eb3645f16b
2
.vscode/launch.template.json
vendored
2
.vscode/launch.template.json
vendored
@ -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
43
.vscode/tasks.json
vendored
@ -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
1324
src/compat/deprecations.ts
Normal file
File diff suppressed because it is too large
Load Diff
12
src/compat/tsconfig.json
Normal file
12
src/compat/tsconfig.json
Normal 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
@ -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))`.
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
56
src/compiler/factory/baseNodeFactory.ts
Normal file
56
src/compiler/factory/baseNodeFactory.ts
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
890
src/compiler/factory/emitHelpers.ts
Normal file
890
src/compiler/factory/emitHelpers.ts
Normal 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);`
|
||||
};
|
||||
}
|
||||
262
src/compiler/factory/emitNode.ts
Normal file
262
src/compiler/factory/emitNode.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
137
src/compiler/factory/nodeConverters.ts
Normal file
137
src/compiler/factory/nodeConverters.ts
Normal 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,
|
||||
};
|
||||
}
|
||||
6216
src/compiler/factory/nodeFactory.ts
Normal file
6216
src/compiler/factory/nodeFactory.ts
Normal file
File diff suppressed because it is too large
Load Diff
818
src/compiler/factory/nodeTests.ts
Normal file
818
src/compiler/factory/nodeTests.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
426
src/compiler/factory/parenthesizerRules.ts
Normal file
426
src/compiler/factory/parenthesizerRules.ts
Normal 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),
|
||||
};
|
||||
}
|
||||
823
src/compiler/factory/utilities.ts
Normal file
823
src/compiler/factory/utilities.ts
Normal 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;
|
||||
}
|
||||
}
|
||||
5
src/compiler/factory/utilitiesPublic.ts
Normal file
5
src/compiler/factory/utilitiesPublic.ts
Normal 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
@ -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];
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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,
|
||||
};
|
||||
}
|
||||
|
||||
@ -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]);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 {
|
||||
|
||||
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);`
|
||||
};
|
||||
}
|
||||
|
||||
@ -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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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)
|
||||
);
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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
|
||||
)
|
||||
|
||||
@ -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 };
|
||||
}
|
||||
};`
|
||||
};
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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
@ -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)]);
|
||||
|
||||
@ -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
@ -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[];
|
||||
}
|
||||
|
||||
@ -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
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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
@ -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
|
||||
|
||||
@ -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(
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
});
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
@ -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"));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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.)
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -35,7 +35,7 @@ namespace ts.codefix {
|
||||
break;
|
||||
}
|
||||
else {
|
||||
changes.replaceNode(sourceFile, statement, createBlock(emptyArray));
|
||||
changes.replaceNode(sourceFile, statement, factory.createBlock(emptyArray));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
@ -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}`));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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[]) {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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));
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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,
|
||||
[]
|
||||
|
||||
@ -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 we’re in a declaration file, it’s 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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user