Merge branch 'master' into typeof-string-literal-union-type

This commit is contained in:
Nathan Shively-Sanders
2017-02-07 12:59:39 -08:00
64 changed files with 6200 additions and 3228 deletions
+13 -1
View File
@@ -8,11 +8,14 @@ Alexander Rusakov <a_s_rusakov@mail.ru>
Alex Eagle <alexeagle@google.com>
Anatoly Ressin <anatoly.ressin@icloud.com>
Anders Hejlsberg <andersh@microsoft.com> unknown <andersh@AndersX1.NOE.Nokia.com> unknown <andersh@andersh-yoga.redmond.corp.microsoft.com>
about-code <about-code@users.noreply.github.com> # Andreas Martin
Andrej Baran <andrej.baran@gmail.com>
Andrew Ochsner <andrew.ochsner@wipro.com>
Andrew Z Allen <me@andrewzallen.com>
Andy Hanson <anhans@microsoft.com> Andy <anhans@microsoft.com>
Anil Anar <anilanar@hotmail.com>
Anton Tolmachev <myste@mail.ru>
Anubha Mathur <anubmat@microsoft.com> anubmat <anubmat@microsoft.com>
Arnavion <arnavion@gmail.com> # Arnav Singh
Arthur Ozga <aozgaa@umich.edu> Arthur Ozga <t-arthoz@microsoft.com> Arthur Ozga <aozgaa-ms@outlook.com> Arthur Ozga <aozgaa@users.noreply.github.com> Arthur Ozga <arozga@microsoft.com>
Asad Saeeduddin <masaeedu@gmail.com>
@@ -37,6 +40,7 @@ Dan Corder <dev@dancorder.com>
Dan Quirk <danquirk@microsoft.com> Dan Quirk <danquirk@users.noreply.github.com> nknown <danquirk@DANQUIRK1.redmond.corp.microsoft.com>
Daniel Rosenwasser <drosen@microsoft.com> Daniel Rosenwasser <DanielRosenwasser@users.noreply.github.com> Daniel Rosenwasser <DanielRosenwasser@gmail.com> Daniel Rosenwasser <Daniel.Rosenwasser@microsoft.com> Daniel Rosenwasser <DanielRosenwasser@microsoft.com>
David Li <jiawei.davidli@gmail.com>
David Sheldrick <david@futurice.com>
David Souther <davidsouther@gmail.com>
Denis Nedelyaev <denvned@gmail.com>
Dick van den Brink <d_vandenbrink@outlook.com> unknown <d_vandenbrink@outlook.com> unknown <d_vandenbrink@live.com>
@@ -52,6 +56,7 @@ Evan Sebastian <evanlhoini@gmail.com>
Eyas <eyas.sharaiha@gmail.com> # Eyas Sharaiha
Fabian Cook <faybecook@gmail.com>
falsandtru <falsandtru@users.noreply.github.com> # @falsandtru
flowmemo <flowmemo@outlook.com> # @flowmemo
Frank Wallis <fwallis@outlook.com>
František Žiacik <fziacik@gratex.com> František Žiacik <ziacik@gmail.com>
Gabe Moothart <gmoothart@gmail.com>
@@ -62,6 +67,7 @@ Graeme Wicksted <graeme.wicksted@gmail.com>
Guillaume Salles <guillaume.salles@me.com>
Guy Bedford <guybedford@gmail.com> guybedford <guybedford@gmail.com>
Harald Niesche <harald@niesche.de>
Homa Wong <homawong@gmail.com>
Iain Monro <iain.monro@softwire.com>
Ingvar Stepanyan <me@rreverser.com>
impinball <impinball@gmail.com> # Isiah Meadows
@@ -81,6 +87,7 @@ Jonathan Park <jpark@daptiv.com>
Jonathan Turner <jont@microsoft.com> Jonathan Turner <probata@hotmail.com>
Jonathan Toland <toland@dnalot.com>
Jesse Schalken <me@jesseschalken.com>
Joel Day <joelday@gmail.com>
Josh Abernathy <joshaber@gmail.com> joshaber <joshaber@gmail.com>
Josh Kalderimis <josh.kalderimis@gmail.com>
Josh Soref <jsoref@users.noreply.github.com>
@@ -95,10 +102,12 @@ Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui T <yuisu@microsoft.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuit@users.noreply.github.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> Yui <yuisu@microsoft.com>
Kanchalai Tanglertsampan <yuisu@microsoft.com> yui T <yuisu@microsoft.com>
Kārlis Gaņģis <Knagis@users.noreply.github.com>
Keith Mashinter <kmashint@yahoo.com> kmashint <kmashint@yahoo.com>
Ken Howard <ken@simplicatedweb.com>
Kevin Lang <klang2012@gmail.com>
kimamula <kenji.imamula@gmail.com> # Kenji Imamula
Klaus Meinhardt <klaus.meinhardt1@gmail.com>
Kyle Kelley <rgbkrk@gmail.com>
Lorant Pinter <lorant.pinter@prezi.com>
Lucien Greathouse <me@lpghatguy.com>
@@ -107,6 +116,7 @@ Martin Vseticka <vseticka.martin@gmail.com> Martin Všeticka <vseticka.martin@gm
gcnew <gcnew@abv.bg> # Marin Marinov
vvakame <vvakame+dev@gmail.com> # Masahiro Wakame
Matt McCutchen <rmccutch@mit.edu>
MANISH-GIRI <manish.giri.me@gmail.com> # Manish Giri
Max Deepfield <maxdeepfield@absolutefreakout.com>
Micah Zoltu <micah@zoltu.net>
Michael <maykelchiche@gmail.com>
@@ -213,4 +223,6 @@ Tim Perry <tim.perry@softwire.com>
Vidar Tonaas Fauske <vidartf@gmail.com>
Viktor Zozulyak <zozulyakviktor@gmail.com>
rix <rix@rixs-MacBook-Pro.local> # Richard Sentino
rohitverma007 <rohitverma@live.ca> # Rohit Verma
rohitverma007 <rohitverma@live.ca> # Rohit Verma
rdosanjh <me@rajdeep.io> # Raj Dosanjh
gdh1995 <gdh1995@qq.com> # Dahan Gong
+12
View File
@@ -12,13 +12,16 @@ TypeScript is authored by:
* Aliaksandr Radzivanovich
* Anatoly Ressin
* Anders Hejlsberg
* Andreas Martin
* Andrej Baran
* Andrew Ochsner
* Andrew Z Allen
* András Parditka
* Andy Hanson
* Anil Anar
* Anton Khlynovskiy
* Anton Tolmachev
* Anubha Mathur
* Arnav Singh
* Arthur Ozga
* Asad Saeeduddin
@@ -42,12 +45,14 @@ TypeScript is authored by:
* Cotton Hou
* Cyrus Najmabadi
* Dafrok Zhang
* Dahan Gong
* Dan Corder
* Dan Quirk
* Daniel Hollocher
* Daniel Rosenwasser
* David Kmenta
* David Li
* David Sheldrick
* David Souther
* Denis Nedelyaev
* Dick van den Brink
@@ -66,6 +71,7 @@ TypeScript is authored by:
* Eyas Sharaiha
* Fabian Cook
* @falsandtru
* @flowmemo
* Frank Wallis
* Franklin Tse
* František Žiacik
@@ -79,6 +85,7 @@ TypeScript is authored by:
* Guy Bedford
* Harald Niesche
* Herrington Darkholme
* Homa Wong
* Iain Monro
* Ingvar Stepanyan
* Isiah Meadows
@@ -93,6 +100,7 @@ TypeScript is authored by:
* Jeffrey Morlan
* Jesse Schalken
* Jiri Tobisek
* Joel Day
* Joey Wilson
* Johannes Rieken
* John Vilk
@@ -114,10 +122,13 @@ TypeScript is authored by:
* Ken Howard
* Kenji Imamula
* Kevin Lang
* Klaus Meinhardt
* Kyle Kelley
* Kārlis Gaņģis
* Lorant Pinter
* Lucien Greathouse
* Lukas Elmer
* Manish Giri
* Marin Marinov
* Marius Schulz
* Martin Vseticka
@@ -155,6 +166,7 @@ TypeScript is authored by:
* @progre
* Punya Biswal
* Rado Kirov
* Raj Dosanjh
* Richard Knoll
* Richard Sentino
* Robert Coie
+1
View File
@@ -269,6 +269,7 @@ var harnessSources = harnessCoreSources.concat([
"projectErrors.ts",
"matchFiles.ts",
"initializeTSConfig.ts",
"printer.ts",
].map(function (f) {
return path.join(unittestsDirectory, f);
})).concat([
+32 -15
View File
@@ -640,7 +640,7 @@ namespace ts {
}
// declaration is after usage
// can be legal if usage is deferred (i.e. inside function or in initializer of instance property)
if (isUsedInFunctionOrNonStaticProperty(usage)) {
if (isUsedInFunctionOrInstanceProperty(usage)) {
return true;
}
const sourceFiles = host.getSourceFiles();
@@ -667,10 +667,12 @@ namespace ts {
}
// declaration is after usage
// can be legal if usage is deferred (i.e. inside function or in initializer of instance property)
// declaration is after usage, but it can still be legal if usage is deferred:
// 1. inside a function
// 2. inside an instance property initializer, a reference to a non-instance property
const container = getEnclosingBlockScopeContainer(declaration);
return isUsedInFunctionOrNonStaticProperty(usage, container);
const isInstanceProperty = declaration.kind === SyntaxKind.PropertyDeclaration && !(getModifierFlags(declaration) & ModifierFlags.Static);
return isUsedInFunctionOrInstanceProperty(usage, isInstanceProperty, container);
function isImmediatelyUsedInInitializerOfBlockScopedVariable(declaration: VariableDeclaration, usage: Node): boolean {
const container = getEnclosingBlockScopeContainer(declaration);
@@ -699,7 +701,7 @@ namespace ts {
return false;
}
function isUsedInFunctionOrNonStaticProperty(usage: Node, container?: Node): boolean {
function isUsedInFunctionOrInstanceProperty(usage: Node, isDeclarationInstanceProperty?: boolean, container?: Node): boolean {
let current = usage;
while (current) {
if (current === container) {
@@ -710,13 +712,13 @@ namespace ts {
return true;
}
const initializerOfNonStaticProperty = current.parent &&
const initializerOfInstanceProperty = current.parent &&
current.parent.kind === SyntaxKind.PropertyDeclaration &&
(getModifierFlags(current.parent) & ModifierFlags.Static) === 0 &&
(<PropertyDeclaration>current.parent).initializer === current;
if (initializerOfNonStaticProperty) {
return true;
if (initializerOfInstanceProperty) {
return !isDeclarationInstanceProperty;
}
current = current.parent;
@@ -985,10 +987,10 @@ namespace ts {
// interface bar {}
// }
// const foo/*1*/: foo/*2*/.bar;
// The foo at /*1*/ and /*2*/ will share same symbol with two meaning
// block - scope variable and namespace module. However, only when we
// The foo at /*1*/ and /*2*/ will share same symbol with two meanings:
// block-scoped variable and namespace module. However, only when we
// try to resolve name in /*1*/ which is used in variable position,
// we want to check for block- scoped
// we want to check for block-scoped
if (meaning & SymbolFlags.BlockScopedVariable) {
const exportOrLocalSymbol = getExportSymbolOfValueSymbolIfExported(result);
if (exportOrLocalSymbol.flags & SymbolFlags.BlockScopedVariable) {
@@ -1012,7 +1014,7 @@ namespace ts {
return false;
}
const container = getThisContainer(errorLocation, /* includeArrowFunctions */ true);
const container = getThisContainer(errorLocation, /*includeArrowFunctions*/ true);
let location = container;
while (location) {
if (isClassLike(location.parent)) {
@@ -3994,7 +3996,7 @@ namespace ts {
// A valid base type is any non-generic object type or intersection of non-generic
// object types.
function isValidBaseType(type: Type): boolean {
return type.flags & TypeFlags.Object && !isGenericMappedType(type) ||
return type.flags & (TypeFlags.Object | TypeFlags.NonPrimitive) && !isGenericMappedType(type) ||
type.flags & TypeFlags.Intersection && !forEach((<IntersectionType>type).types, t => !isValidBaseType(t));
}
@@ -4932,7 +4934,7 @@ namespace ts {
}
function getApparentTypeOfIntersectionType(type: IntersectionType) {
return type.resolvedIndexType || (type.resolvedApparentType = getTypeWithThisArgument(type, type));
return type.resolvedApparentType || (type.resolvedApparentType = getTypeWithThisArgument(type, type));
}
/**
@@ -4947,7 +4949,7 @@ namespace ts {
t.flags & TypeFlags.NumberLike ? globalNumberType :
t.flags & TypeFlags.BooleanLike ? globalBooleanType :
t.flags & TypeFlags.ESSymbol ? getGlobalESSymbolType() :
t.flags & TypeFlags.NonPrimitive ? globalObjectType :
t.flags & TypeFlags.NonPrimitive ? emptyObjectType :
t;
}
@@ -12546,6 +12548,16 @@ namespace ts {
}
}
function isInPropertyInitializer(node: Node): boolean {
while (node) {
if (node.parent && node.parent.kind === SyntaxKind.PropertyDeclaration && (node.parent as PropertyDeclaration).initializer === node) {
return true;
}
node = node.parent;
}
return false;
}
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
const type = checkNonNullExpression(left);
if (isTypeAny(type) || type === silentNeverType) {
@@ -12568,6 +12580,11 @@ namespace ts {
}
return unknownType;
}
if (prop.valueDeclaration &&
isInPropertyInitializer(node) &&
!isBlockScopedNameDeclaredBeforeUse(prop.valueDeclaration, right)) {
error(right, Diagnostics.Block_scoped_variable_0_used_before_its_declaration, right.text);
}
markPropertyAsReferenced(prop);
+26 -22
View File
@@ -5,17 +5,16 @@ namespace ts {
export interface CommentWriter {
reset(): void;
setSourceFile(sourceFile: SourceFile): void;
emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
setWriter(writer: EmitTextWriter): void;
emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
emitBodyWithDetachedComments(node: Node, detachedRange: TextRange, emitCallback: (node: Node) => void): void;
emitTrailingCommentsOfPosition(pos: number): void;
}
export function createCommentWriter(host: EmitHost, writer: EmitTextWriter, sourceMap: SourceMapWriter): CommentWriter {
const compilerOptions = host.getCompilerOptions();
const extendedDiagnostics = compilerOptions.extendedDiagnostics;
const newLine = host.getNewLine();
const { emitPos } = sourceMap;
export function createCommentWriter(printerOptions: PrinterOptions, emitPos: ((pos: number) => void) | undefined): CommentWriter {
const extendedDiagnostics = printerOptions.extendedDiagnostics;
const newLine = getNewLineCharacter(printerOptions);
let writer: EmitTextWriter;
let containerPos = -1;
let containerEnd = -1;
let declarationListContainerEnd = -1;
@@ -24,19 +23,20 @@ namespace ts {
let currentLineMap: number[];
let detachedCommentsInfo: { nodePos: number, detachedCommentEndPos: number}[];
let hasWrittenComment = false;
let disabled: boolean = compilerOptions.removeComments;
let disabled: boolean = printerOptions.removeComments;
return {
reset,
setWriter,
setSourceFile,
emitNodeWithComments,
emitBodyWithDetachedComments,
emitTrailingCommentsOfPosition,
};
function emitNodeWithComments(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function emitNodeWithComments(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (disabled) {
emitCallback(emitContext, node);
emitCallback(hint, node);
return;
}
@@ -47,11 +47,11 @@ namespace ts {
// Both pos and end are synthesized, so just emit the node without comments.
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(emitContext, node);
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(emitContext, node);
emitCallback(hint, node);
}
}
else {
@@ -94,11 +94,11 @@ namespace ts {
if (emitFlags & EmitFlags.NoNestedComments) {
disabled = true;
emitCallback(emitContext, node);
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(emitContext, node);
emitCallback(hint, node);
}
if (extendedDiagnostics) {
@@ -198,9 +198,9 @@ namespace ts {
}
// Leading comments are emitted at /*leading comment1 */space/*leading comment*/space
emitPos(commentPos);
if (emitPos) emitPos(commentPos);
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
if (emitPos) emitPos(commentEnd);
if (hasTrailingNewLine) {
writer.writeLine();
@@ -220,9 +220,9 @@ namespace ts {
writer.write(" ");
}
emitPos(commentPos);
if (emitPos) emitPos(commentPos);
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
if (emitPos) emitPos(commentEnd);
if (hasTrailingNewLine) {
writer.writeLine();
@@ -248,9 +248,9 @@ namespace ts {
function emitTrailingCommentOfPosition(commentPos: number, commentEnd: number, _kind: SyntaxKind, hasTrailingNewLine: boolean) {
// trailing comments of a position are emitted at /*trailing comment1 */space/*trailing comment*/space
emitPos(commentPos);
if (emitPos) emitPos(commentPos);
writeCommentRange(currentText, currentLineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
if (emitPos) emitPos(commentEnd);
if (hasTrailingNewLine) {
writer.writeLine();
@@ -286,6 +286,10 @@ namespace ts {
detachedCommentsInfo = undefined;
}
function setWriter(output: EmitTextWriter): void {
writer = output;
}
function setSourceFile(sourceFile: SourceFile) {
currentSourceFile = sourceFile;
currentText = currentSourceFile.text;
@@ -323,9 +327,9 @@ namespace ts {
}
function writeComment(text: string, lineMap: number[], writer: EmitTextWriter, commentPos: number, commentEnd: number, newLine: string) {
emitPos(commentPos);
if (emitPos) emitPos(commentPos);
writeCommentRange(text, lineMap, writer, commentPos, commentEnd, newLine);
emitPos(commentEnd);
if (emitPos) emitPos(commentEnd);
}
/**
+1 -1
View File
@@ -1455,7 +1455,7 @@ namespace ts {
return /^\.\.?($|[\\/])/.test(moduleName);
}
export function getEmitScriptTarget(compilerOptions: CompilerOptions) {
export function getEmitScriptTarget(compilerOptions: CompilerOptions | PrinterOptions) {
return compilerOptions.target || ScriptTarget.ES3;
}
+10 -6
View File
@@ -35,13 +35,15 @@ namespace ts {
forEachEmittedFile(host, getDeclarationDiagnosticsFromFile, targetSourceFile);
return declarationDiagnostics.getDiagnostics(targetSourceFile ? targetSourceFile.fileName : undefined);
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sources: SourceFile[], isBundledEmit: boolean) {
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sources, isBundledEmit, /*emitOnlyDtsFiles*/ false);
function getDeclarationDiagnosticsFromFile({ declarationFilePath }: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
emitDeclarations(host, resolver, declarationDiagnostics, declarationFilePath, sourceFileOrBundle, /*emitOnlyDtsFiles*/ false);
}
}
function emitDeclarations(host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, declarationFilePath: string,
sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean): DeclarationEmit {
sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean): DeclarationEmit {
const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle];
const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle;
const newLine = host.getNewLine();
const compilerOptions = host.getCompilerOptions();
@@ -1803,8 +1805,9 @@ namespace ts {
}
return addedBundledEmitReference;
function getDeclFileName(emitFileNames: EmitFileNames, _sourceFiles: SourceFile[], isBundledEmit: boolean) {
function getDeclFileName(emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle) {
// Dont add reference path to this file if it is a bundled emit and caller asked not emit bundled file path
const isBundledEmit = sourceFileOrBundle.kind === SyntaxKind.Bundle;
if (isBundledEmit && !addBundledFileReference) {
return;
}
@@ -1817,10 +1820,11 @@ namespace ts {
}
/* @internal */
export function writeDeclarationFile(declarationFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFiles, isBundledEmit, emitOnlyDtsFiles);
export function writeDeclarationFile(declarationFilePath: string, sourceFileOrBundle: SourceFile | Bundle, host: EmitHost, resolver: EmitResolver, emitterDiagnostics: DiagnosticCollection, emitOnlyDtsFiles: boolean) {
const emitDeclarationResult = emitDeclarations(host, resolver, emitterDiagnostics, declarationFilePath, sourceFileOrBundle, emitOnlyDtsFiles);
const emitSkipped = emitDeclarationResult.reportedDeclarationError || host.isEmitBlocked(declarationFilePath) || host.getCompilerOptions().noEmit;
if (!emitSkipped) {
const sourceFiles = sourceFileOrBundle.kind === SyntaxKind.Bundle ? sourceFileOrBundle.sourceFiles : [sourceFileOrBundle];
const declarationOutput = emitDeclarationResult.referencesOutput
+ getDeclarationOutput(emitDeclarationResult.synchronousDeclarationOutput, emitDeclarationResult.moduleElementDeclarationEmitInfo);
writeFile(host, emitterDiagnostics, declarationFilePath, declarationOutput, host.getCompilerOptions().emitBOM, sourceFiles);
+528 -459
View File
File diff suppressed because it is too large Load Diff
+1288 -1080
View File
File diff suppressed because it is too large Load Diff
+3 -6
View File
@@ -1152,13 +1152,10 @@ namespace ts {
&& (options.isolatedModules || isExternalModuleFile)
&& !file.isDeclarationFile) {
// synthesize 'import "tslib"' declaration
const externalHelpersModuleReference = <StringLiteral>createSynthesizedNode(SyntaxKind.StringLiteral);
externalHelpersModuleReference.text = externalHelpersModuleNameText;
const importDecl = createSynthesizedNode(SyntaxKind.ImportDeclaration);
importDecl.parent = file;
const externalHelpersModuleReference = createLiteral(externalHelpersModuleNameText);
const importDecl = createImportDeclaration(undefined, undefined, undefined);
externalHelpersModuleReference.parent = importDecl;
importDecl.parent = file;
imports = [externalHelpersModuleReference];
}
+13 -15
View File
@@ -8,10 +8,9 @@ namespace ts {
*
* @param filePath The path to the generated output file.
* @param sourceMapFilePath The path to the output source map file.
* @param sourceFiles The input source files for the program.
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
* @param sourceFileOrBundle The input source file or bundle for the program.
*/
initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean): void;
initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle): void;
/**
* Reset the SourceMapWriter to an empty state.
@@ -38,11 +37,11 @@ namespace ts {
/**
* Emits a node with possible leading and trailing source maps.
*
* @param emitContext The current emit context
* @param hint The current emit context
* @param node The node to emit.
* @param emitCallback The callback used to emit the node.
*/
emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
/**
* Emits a token of a node node with possible leading and trailing source maps.
@@ -115,10 +114,9 @@ namespace ts {
*
* @param filePath The path to the generated output file.
* @param sourceMapFilePath The path to the output source map file.
* @param sourceFiles The input source files for the program.
* @param isBundledEmit A value indicating whether the generated output file is a bundle.
* @param sourceFileOrBundle The input source file or bundle for the program.
*/
function initialize(filePath: string, sourceMapFilePath: string, sourceFiles: SourceFile[], isBundledEmit: boolean) {
function initialize(filePath: string, sourceMapFilePath: string, sourceFileOrBundle: SourceFile | Bundle) {
if (disabled) {
return;
}
@@ -161,11 +159,10 @@ namespace ts {
if (compilerOptions.mapRoot) {
sourceMapDir = normalizeSlashes(compilerOptions.mapRoot);
if (!isBundledEmit) { // emitting single module file
Debug.assert(sourceFiles.length === 1);
if (sourceFileOrBundle.kind === SyntaxKind.SourceFile) { // emitting single module file
// For modules or multiple emit files the mapRoot will have directory structure like the sources
// So if src\a.ts and src\lib\b.ts are compiled together user would be moving the maps into mapRoot\a.js.map and mapRoot\lib\b.js.map
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFiles[0], host, sourceMapDir));
sourceMapDir = getDirectoryPath(getSourceFilePathInNewDir(sourceFileOrBundle, host, sourceMapDir));
}
if (!isRootedDiskPath(sourceMapDir) && !isUrl(sourceMapDir)) {
@@ -311,12 +308,13 @@ namespace ts {
/**
* Emits a node with possible leading and trailing source maps.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emitCallback The callback used to emit the node.
*/
function emitNodeWithSourceMap(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function emitNodeWithSourceMap(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (disabled) {
return emitCallback(emitContext, node);
return emitCallback(hint, node);
}
if (node) {
@@ -332,11 +330,11 @@ namespace ts {
if (emitFlags & EmitFlags.NoNestedSourceMaps) {
disabled = true;
emitCallback(emitContext, node);
emitCallback(hint, node);
disabled = false;
}
else {
emitCallback(emitContext, node);
emitCallback(hint, node);
}
if (node.kind !== SyntaxKind.NotEmittedStatement
+15 -15
View File
@@ -105,14 +105,16 @@ namespace ts {
hoistFunctionDeclaration,
requestEmitHelper,
readEmitHelpers,
onSubstituteNode: (_emitContext, node) => node,
onSubstituteNode: (_, node) => node,
enableSubstitution,
isSubstitutionEnabled,
onEmitNode: (node, emitContext, emitCallback) => emitCallback(node, emitContext),
onEmitNode: (hint, node, callback) => callback(hint, node),
enableEmitNotification,
isEmitNotificationEnabled
};
performance.mark("beforeTransform");
// Chain together and initialize each transformer.
const transformation = chain(...transformers)(context);
@@ -122,6 +124,9 @@ namespace ts {
// Disable modification of the lexical environment.
lexicalEnvironmentDisabled = true;
performance.mark("afterTransform");
performance.measure("transformTime", "beforeTransform", "afterTransform");
return {
transformed,
emitNodeWithSubstitution,
@@ -159,21 +164,16 @@ namespace ts {
/**
* Emits a node with possible substitution.
*
* @param emitContext The current emit context.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emitCallback The callback used to emit the node or its substitute.
*/
function emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (node) {
if (isSubstitutionEnabled(node)) {
const substitute = context.onSubstituteNode(emitContext, node);
if (substitute && substitute !== node) {
emitCallback(emitContext, substitute);
return;
}
node = context.onSubstituteNode(hint, node) || node;
}
emitCallback(emitContext, node);
emitCallback(hint, node);
}
}
@@ -196,17 +196,17 @@ namespace ts {
/**
* Emits a node with possible emit notification.
*
* @param emitContext The current emit context.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emitCallback The callback used to emit the node.
*/
function emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (node) {
if (isEmitNotificationEnabled(node)) {
context.onEmitNode(emitContext, node, emitCallback);
context.onEmitNode(hint, node, emitCallback);
}
else {
emitCallback(emitContext, node);
emitCallback(hint, node);
}
}
}
+18 -5
View File
@@ -112,7 +112,10 @@ namespace ts {
Debug.assertNode(target, createAssignmentCallback ? isIdentifier : isExpression);
const expression = createAssignmentCallback
? createAssignmentCallback(<Identifier>target, value, location)
: createAssignment(visitNode(<Expression>target, visitor, isExpression), value, location);
: setTextRange(
createAssignment(visitNode(<Expression>target, visitor, isExpression), value),
location
);
expression.original = original;
emitExpression(expression);
}
@@ -174,9 +177,10 @@ namespace ts {
const variable = createVariableDeclaration(
name,
/*type*/ undefined,
pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value,
location);
pendingExpressions ? inlineExpressions(append(pendingExpressions, value)) : value
);
variable.original = original;
setTextRange(variable, location);
if (isIdentifier(name)) {
setEmitFlags(variable, EmitFlags.NoNestedSourceMaps);
}
@@ -416,7 +420,7 @@ namespace ts {
const temp = createTempVariable(/*recordTempVariable*/ undefined);
if (flattenContext.hoistTempVariables) {
flattenContext.context.hoistVariableDeclaration(temp);
flattenContext.emitExpression(createAssignment(temp, value, location));
flattenContext.emitExpression(setTextRange(createAssignment(temp, value), location));
}
else {
flattenContext.emitBindingOrAssignment(temp, value, location, /*original*/ undefined);
@@ -492,6 +496,15 @@ namespace ts {
}
}
}
return createCall(getHelperName("__rest"), undefined, [value, createArrayLiteral(propertyNames, location)]);
return createCall(
getHelperName("__rest"),
undefined,
[
value,
setTextRange(
createArrayLiteral(propertyNames),
location
)
]);
}
}
+211 -172
View File
@@ -514,7 +514,7 @@ namespace ts {
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
return updateSourceFileNode(
node,
createNodeArray(statements, node.statements)
setTextRange(createNodeArray(statements), node.statements)
);
}
@@ -671,9 +671,10 @@ namespace ts {
setOriginalNode(variable, node);
const statements: Statement[] = [];
const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable]), /*location*/ node);
const statement = createVariableStatement(/*modifiers*/ undefined, createVariableDeclarationList([variable]));
setOriginalNode(statement, node);
setTextRange(statement, node);
startOnNewLine(statement);
statements.push(statement);
@@ -818,7 +819,7 @@ namespace ts {
addRange(statements, endLexicalEnvironment());
const block = createBlock(createNodeArray(statements, /*location*/ node.members), /*location*/ undefined, /*multiLine*/ true);
const block = createBlock(setTextRange(createNodeArray(statements), /*location*/ node.members), /*multiLine*/ true);
setEmitFlags(block, EmitFlags.NoComments);
return block;
}
@@ -833,8 +834,10 @@ namespace ts {
function addExtendsHelperIfNeeded(statements: Statement[], node: ClassExpression | ClassDeclaration, extendsClauseElement: ExpressionWithTypeArguments): void {
if (extendsClauseElement) {
statements.push(
createStatement(
createExtendsHelper(context, getLocalName(node)),
setTextRange(
createStatement(
createExtendsHelper(context, getLocalName(node))
),
/*location*/ extendsClauseElement
)
);
@@ -854,19 +857,18 @@ namespace ts {
const ancestorFacts = enterSubtree(HierarchyFacts.ConstructorExcludes, HierarchyFacts.ConstructorIncludes);
const constructor = getFirstConstructorWithBody(node);
const hasSynthesizedSuper = hasSynthesizedDefaultSuperCall(constructor, extendsClauseElement !== undefined);
const constructorFunction =
createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
getDeclarationName(node),
/*typeParameters*/ undefined,
transformConstructorParameters(constructor, hasSynthesizedSuper),
/*type*/ undefined,
transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper),
/*location*/ constructor || node
);
const constructorFunction = createFunctionDeclaration(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
getDeclarationName(node),
/*typeParameters*/ undefined,
transformConstructorParameters(constructor, hasSynthesizedSuper),
/*type*/ undefined,
transformConstructorBody(constructor, node, extendsClauseElement, hasSynthesizedSuper)
);
setTextRange(constructorFunction, constructor || node);
if (extendsClauseElement) {
setEmitFlags(constructorFunction, EmitFlags.CapturesThis);
}
@@ -962,14 +964,16 @@ namespace ts {
}
const block = createBlock(
createNodeArray(
statements,
setTextRange(
createNodeArray(
statements
),
/*location*/ constructor ? constructor.body.statements : node.members
),
/*location*/ constructor ? constructor.body : node,
/*multiLine*/ true
);
setTextRange(block, constructor ? constructor.body : node);
if (!constructor) {
setEmitFlags(block, EmitFlags.NoComments);
}
@@ -1139,14 +1143,16 @@ namespace ts {
// Binding patterns are converted into a generated name and are
// evaluated inside the function body.
return setOriginalNode(
createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
getGeneratedNameForNode(node),
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined,
setTextRange(
createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
getGeneratedNameForNode(node),
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined
),
/*location*/ node
),
/*original*/ node
@@ -1155,14 +1161,16 @@ namespace ts {
else if (node.initializer) {
// Initializers are elided
return setOriginalNode(
createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
node.name,
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined,
setTextRange(
createParameter(
/*decorators*/ undefined,
/*modifiers*/ undefined,
/*dotDotDotToken*/ undefined,
node.name,
/*questionToken*/ undefined,
/*type*/ undefined,
/*initializer*/ undefined
),
/*location*/ node
),
/*original*/ node
@@ -1274,21 +1282,25 @@ namespace ts {
const statement = createIf(
createTypeCheck(getSynthesizedClone(name), "undefined"),
setEmitFlags(
createBlock([
createStatement(
createAssignment(
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer)),
/*location*/ parameter
setTextRange(
createBlock([
createStatement(
setTextRange(
createAssignment(
setEmitFlags(getMutableClone(name), EmitFlags.NoSourceMap),
setEmitFlags(initializer, EmitFlags.NoSourceMap | getEmitFlags(initializer))
),
parameter
)
)
)
], /*location*/ parameter),
]),
parameter
),
EmitFlags.SingleLine | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTokenSourceMaps
),
/*elseStatement*/ undefined,
/*location*/ parameter
)
);
statement.startsOnNewLine = true;
setTextRange(statement, parameter);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.CustomPrologue);
statements.push(statement);
}
@@ -1332,15 +1344,17 @@ namespace ts {
// var param = [];
statements.push(
setEmitFlags(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
declarationName,
/*type*/ undefined,
createArrayLiteral([])
)
]),
setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
declarationName,
/*type*/ undefined,
createArrayLiteral([])
)
])
),
/*location*/ parameter
),
EmitFlags.CustomPrologue
@@ -1351,26 +1365,33 @@ namespace ts {
// param[_i - restIndex] = arguments[_i];
// }
const forStatement = createFor(
createVariableDeclarationList([
createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex))
], /*location*/ parameter),
createLessThan(
temp,
createPropertyAccess(createIdentifier("arguments"), "length"),
/*location*/ parameter
setTextRange(
createVariableDeclarationList([
createVariableDeclaration(temp, /*type*/ undefined, createLiteral(restIndex))
]),
parameter
),
createPostfixIncrement(temp, /*location*/ parameter),
setTextRange(
createLessThan(
temp,
createPropertyAccess(createIdentifier("arguments"), "length")
),
parameter
),
setTextRange(createPostfixIncrement(temp), parameter),
createBlock([
startOnNewLine(
createStatement(
createAssignment(
createElementAccess(
expressionName,
restIndex === 0
? temp
: createSubtract(temp, createLiteral(restIndex))
),
createElementAccess(createIdentifier("arguments"), temp)
setTextRange(
createStatement(
createAssignment(
createElementAccess(
expressionName,
restIndex === 0
? temp
: createSubtract(temp, createLiteral(restIndex))
),
createElementAccess(createIdentifier("arguments"), temp)
)
),
/*location*/ parameter
)
@@ -1405,11 +1426,10 @@ namespace ts {
/*type*/ undefined,
initializer
)
]),
originalStatement
])
);
setEmitFlags(captureThisStatement, EmitFlags.NoComments | EmitFlags.CustomPrologue);
setTextRange(captureThisStatement, originalStatement);
setSourceMapRange(captureThisStatement, node);
statements.push(captureThisStatement);
}
@@ -1529,7 +1549,7 @@ namespace ts {
* @param member The SemicolonClassElement node.
*/
function transformSemicolonClassElementToStatement(member: SemicolonClassElement) {
return createEmptyStatement(/*location*/ member);
return setTextRange(createEmptyStatement(), member);
}
/**
@@ -1547,8 +1567,10 @@ namespace ts {
setEmitFlags(memberFunction, EmitFlags.NoComments);
setSourceMapRange(memberFunction, sourceMapRange);
const statement = createStatement(
createAssignment(memberName, memberFunction),
const statement = setTextRange(
createStatement(
createAssignment(memberName, memberFunction)
),
/*location*/ member
);
@@ -1571,15 +1593,12 @@ namespace ts {
* @param accessors The set of related get/set accessors.
*/
function transformAccessorsToStatement(receiver: LeftHandSideExpression, accessors: AllAccessorDeclarations, container: Node): Statement {
const statement = createStatement(
transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false),
/*location*/ getSourceMapRange(accessors.firstAccessor)
);
const statement = createStatement(transformAccessorsToExpression(receiver, accessors, container, /*startsOnNewLine*/ false));
// The location for the statement is used to emit source maps only.
// No comments should be emitted for this statement to align with the
// old emitter.
setEmitFlags(statement, EmitFlags.NoComments);
setSourceMapRange(statement, getSourceMapRange(accessors.firstAccessor));
return statement;
}
@@ -1622,8 +1641,8 @@ namespace ts {
}
properties.push(
createPropertyAssignment("enumerable", createLiteral(true)),
createPropertyAssignment("configurable", createLiteral(true))
createPropertyAssignment("enumerable", createTrue()),
createPropertyAssignment("configurable", createTrue())
);
const call = createCall(
@@ -1632,7 +1651,7 @@ namespace ts {
[
target,
propertyName,
createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)
createObjectLiteral(properties, /*multiLine*/ true)
]
);
if (startsOnNewLine) {
@@ -1662,9 +1681,9 @@ namespace ts {
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformFunctionBody(node),
node
transformFunctionBody(node)
);
setTextRange(func, node);
setOriginalNode(func, node);
setEmitFlags(func, EmitFlags.CapturesThis);
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
@@ -1758,14 +1777,16 @@ namespace ts {
exitSubtree(ancestorFacts, HierarchyFacts.PropagateNewTargetMask, HierarchyFacts.None);
convertedLoopState = savedConvertedLoopState;
return setOriginalNode(
createFunctionExpression(
/*modifiers*/ undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body,
setTextRange(
createFunctionExpression(
/*modifiers*/ undefined,
node.asteriskToken,
name,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
body
),
location
),
/*original*/ node
@@ -1832,7 +1853,8 @@ namespace ts {
}
const expression = visitNode(body, visitor, isExpression);
const returnStatement = createReturn(expression, /*location*/ body);
const returnStatement = createReturn(expression);
setTextRange(returnStatement, body);
setEmitFlags(returnStatement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoTrailingSourceMap | EmitFlags.NoTrailingComments);
statements.push(returnStatement);
@@ -1851,7 +1873,8 @@ namespace ts {
multiLine = true;
}
const block = createBlock(createNodeArray(statements, statementsLocation), node.body, multiLine);
const block = createBlock(setTextRange(createNodeArray(statements), statementsLocation), multiLine);
setTextRange(block, node.body);
if (!multiLine && singleLine) {
setEmitFlags(block, EmitFlags.SingleLine);
}
@@ -1868,8 +1891,10 @@ namespace ts {
const updated = visitFunctionBody(node.body, functionBodyVisitor, context);
return updateBlock(
updated,
createNodeArray(
prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true),
setTextRange(
createNodeArray(
prependCaptureNewTargetIfNeeded(updated.statements, node, /*copyOnWrite*/ true)
),
/*location*/ updated.statements
)
);
@@ -1969,7 +1994,7 @@ namespace ts {
}
}
if (assignments) {
updated = createStatement(reduceLeft(assignments, (acc, v) => createBinary(v, SyntaxKind.CommaToken, acc)), node);
updated = setTextRange(createStatement(reduceLeft(assignments, (acc, v) => createBinary(v, SyntaxKind.CommaToken, acc))), node);
}
else {
// none of declarations has initializer - the entire variable statement can be deleted
@@ -1999,8 +2024,9 @@ namespace ts {
? visitVariableDeclarationInLetDeclarationList
: visitVariableDeclaration));
const declarationList = createVariableDeclarationList(declarations, /*location*/ node);
const declarationList = createVariableDeclarationList(declarations);
setOriginalNode(declarationList, node);
setTextRange(declarationList, node);
setCommentRange(declarationList, node);
if (node.transformFlags & TransformFlags.ContainsBindingPattern
@@ -2225,7 +2251,7 @@ namespace ts {
// we don't want to emit a temporary variable for the RHS, just use it directly.
const counter = createLoopVariable();
const rhsReference = expression.kind === SyntaxKind.Identifier
? createUniqueName((<Identifier>expression).text)
? createUniqueName(unescapeIdentifier((<Identifier>expression).text))
: createTempVariable(/*recordTempVariable*/ undefined);
const elementAccess = createElementAccess(rhsReference, counter);
@@ -2248,8 +2274,9 @@ namespace ts {
elementAccess
);
const declarationList = createVariableDeclarationList(declarations, /*location*/ initializer);
const declarationList = createVariableDeclarationList(declarations);
setOriginalNode(declarationList, initializer);
setTextRange(declarationList, initializer);
// Adjust the source map range for the first declaration to align with the old
// emitter.
@@ -2268,19 +2295,24 @@ namespace ts {
// The following call does not include the initializer, so we have
// to emit it separately.
statements.push(
createVariableStatement(
/*modifiers*/ undefined,
setOriginalNode(
createVariableDeclarationList([
createVariableDeclaration(
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
/*type*/ undefined,
createElementAccess(rhsReference, counter)
)
], /*location*/ moveRangePos(initializer, -1)),
initializer
setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
setOriginalNode(
setTextRange(
createVariableDeclarationList([
createVariableDeclaration(
firstOriginalDeclaration ? firstOriginalDeclaration.name : createTempVariable(/*recordTempVariable*/ undefined),
/*type*/ undefined,
createElementAccess(rhsReference, counter)
)
]),
moveRangePos(initializer, -1)
),
initializer
)
),
/*location*/ moveRangeEnd(initializer, -1)
moveRangeEnd(initializer, -1)
)
);
}
@@ -2306,7 +2338,7 @@ namespace ts {
// Currently there is not way to check that assignment is binary expression of destructing assignment
// so we have to cast never type to binaryExpression
(<BinaryExpression>assignment).end = initializer.end;
statements.push(createStatement(assignment, /*location*/ moveRangeEnd(initializer, -1)));
statements.push(setTextRange(createStatement(assignment), moveRangeEnd(initializer, -1)));
}
}
@@ -2332,33 +2364,38 @@ namespace ts {
// The old emitter does not emit source maps for the block.
// We add the location to preserve comments.
const body = createBlock(
createNodeArray(statements, /*location*/ statementsLocation),
/*location*/ bodyLocation
);
const body = createBlock(setTextRange(createNodeArray(statements), /*location*/ statementsLocation));
setTextRange(body, bodyLocation);
setEmitFlags(body, EmitFlags.NoSourceMap | EmitFlags.NoTokenSourceMaps);
const forStatement = createFor(
setEmitFlags(
createVariableDeclarationList([
createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0), /*location*/ moveRangePos(node.expression, -1)),
createVariableDeclaration(rhsReference, /*type*/ undefined, expression, /*location*/ node.expression)
], /*location*/ node.expression),
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(counter, /*type*/ undefined, createLiteral(0)), moveRangePos(node.expression, -1)),
setTextRange(createVariableDeclaration(rhsReference, /*type*/ undefined, expression), node.expression)
]),
node.expression
),
EmitFlags.NoHoisting
),
createLessThan(
counter,
createPropertyAccess(rhsReference, "length"),
/*location*/ node.expression
setTextRange(
createLessThan(
counter,
createPropertyAccess(rhsReference, "length")
),
node.expression
),
createPostfixIncrement(counter, /*location*/ node.expression),
body,
/*location*/ node
setTextRange(
createPostfixIncrement(counter),
node.expression
),
body
);
// Disable trailing source maps for the OpenParenToken to align source map emit with the old emitter.
setEmitFlags(forStatement, EmitFlags.NoTokenTrailingSourceMaps);
setTextRange(forStatement, node);
return restoreEnclosingLabel(forStatement, outermostLabeledStatement, convertedLoopState && resetLabel);
}
@@ -2418,7 +2455,6 @@ namespace ts {
setEmitFlags(
createObjectLiteral(
visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties),
/*location*/ undefined,
node.multiLine
),
EmitFlags.Indented
@@ -2546,14 +2582,14 @@ namespace ts {
copyOutParameters(loopOutParameters, CopyDirection.ToOutParameter, statements);
}
addRange(statements, lexicalEnvironment)
loopBody = createBlock(statements, /*location*/ undefined, /*multiline*/ true);
loopBody = createBlock(statements, /*multiline*/ true);
}
if (isBlock(loopBody)) {
loopBody.multiLine = true;
}
else {
loopBody = createBlock([loopBody], /*location*/ undefined, /*multiline*/ true);
loopBody = createBlock([loopBody], /*multiline*/ true);
}
const isAsyncBlockContainingAwait =
@@ -2687,12 +2723,7 @@ namespace ts {
// visit childnodes to transform initializer/condition/incrementor parts
clone = visitEachChild(clone, visitor, context);
// set loop statement
clone.statement = createBlock(
convertedLoopBodyStatements,
/*location*/ undefined,
/*multiline*/ true
);
clone.statement = createBlock(convertedLoopBodyStatements, /*multiline*/ true);
// reset and re-aggregate the transform flags
clone.transformFlags = 0;
aggregateTransformFlags(clone);
@@ -2841,7 +2872,7 @@ namespace ts {
else {
loopParameters.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, name));
if (resolver.getNodeCheckFlags(decl) & NodeCheckFlags.NeedsLoopOutParameter) {
const outParamName = createUniqueName("out_" + name.text);
const outParamName = createUniqueName("out_" + unescapeIdentifier(name.text));
loopOutParameters.push({ originalName: name, outParamName });
}
}
@@ -2903,9 +2934,9 @@ namespace ts {
receiver,
visitNode(property.name, visitor, isPropertyName)
),
visitNode(property.initializer, visitor, isExpression),
/*location*/ property
visitNode(property.initializer, visitor, isExpression)
);
setTextRange(expression, property);
if (startsOnNewLine) {
expression.startsOnNewLine = true;
}
@@ -2925,9 +2956,9 @@ namespace ts {
receiver,
visitNode(property.name, visitor, isPropertyName)
),
getSynthesizedClone(property.name),
/*location*/ property
getSynthesizedClone(property.name)
);
setTextRange(expression, property);
if (startsOnNewLine) {
expression.startsOnNewLine = true;
}
@@ -2948,9 +2979,9 @@ namespace ts {
receiver,
visitNode(method.name, visitor, isPropertyName)
),
transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container),
/*location*/ method
transformFunctionLikeToExpression(method, /*location*/ method, /*name*/ undefined, container)
);
setTextRange(expression, method);
if (startsOnNewLine) {
expression.startsOnNewLine = true;
}
@@ -2963,7 +2994,8 @@ namespace ts {
let updated: CatchClause;
if (isBindingPattern(node.variableDeclaration.name)) {
const temp = createTempVariable(undefined);
const newVariableDeclaration = createVariableDeclaration(temp, undefined, undefined, node.variableDeclaration);
const newVariableDeclaration = createVariableDeclaration(temp);
setTextRange(newVariableDeclaration, node.variableDeclaration);
const vars = flattenDestructuringBinding(
node.variableDeclaration,
visitor,
@@ -2971,8 +3003,9 @@ namespace ts {
FlattenLevel.All,
temp
);
const list = createVariableDeclarationList(vars, /*location*/node.variableDeclaration, /*flags*/node.variableDeclaration.flags);
const destructure = createVariableStatement(undefined, list);
const list = createVariableDeclarationList(vars);
setTextRange(list, node.variableDeclaration);
const destructure = createVariableStatement(/*modifiers*/ undefined, list);
updated = updateCatchClause(node, newVariableDeclaration, addStatementToStartOfBlock(node.block, destructure));
}
else {
@@ -3001,9 +3034,11 @@ namespace ts {
Debug.assert(!isComputedPropertyName(node.name));
const functionExpression = transformFunctionLikeToExpression(node, /*location*/ moveRangePos(node, -1), /*name*/ undefined, /*container*/ undefined);
setEmitFlags(functionExpression, EmitFlags.NoLeadingComments | getEmitFlags(functionExpression));
return createPropertyAssignment(
node.name,
functionExpression,
return setTextRange(
createPropertyAssignment(
node.name,
functionExpression
),
/*location*/ node
);
}
@@ -3030,9 +3065,11 @@ namespace ts {
* @param node A ShorthandPropertyAssignment node.
*/
function visitShorthandPropertyAssignment(node: ShorthandPropertyAssignment): ObjectLiteralElementLike {
return createPropertyAssignment(
node.name,
getSynthesizedClone(node.name),
return setTextRange(
createPropertyAssignment(
node.name,
getSynthesizedClone(node.name)
),
/*location*/ node
);
}
@@ -3225,8 +3262,7 @@ namespace ts {
function visitSpanOfNonSpreads(chunk: Expression[], multiLine: boolean, hasTrailingComma: boolean): VisitResult<Expression> {
return createArrayLiteral(
visitNodes(createNodeArray(chunk, /*location*/ undefined, hasTrailingComma), visitor, isExpression),
/*location*/ undefined,
visitNodes(createNodeArray(chunk, hasTrailingComma), visitor, isExpression),
multiLine
);
}
@@ -3250,7 +3286,7 @@ namespace ts {
* @param node A template literal.
*/
function visitTemplateLiteral(node: LiteralExpression): LeftHandSideExpression {
return createLiteral(node.text, /*location*/ node);
return setTextRange(createLiteral(node.text), node);
}
/**
@@ -3318,7 +3354,7 @@ 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 createLiteral(text, /*location*/ node);
return setTextRange(createLiteral(text), node);
}
/**
@@ -3342,7 +3378,8 @@ namespace ts {
// "abc" + (1 << 2) + ""
const expression = reduceLeft(expressions, createAdd);
if (nodeIsSynthesized(expression)) {
setTextRange(expression, node);
expression.pos = node.pos;
expression.end = node.end;
}
return expression;
@@ -3435,9 +3472,11 @@ namespace ts {
/**
* Called by the printer just before a node is printed.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to be printed.
* @param emitCallback The callback used to emit the node.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) {
if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis && isFunctionLike(node)) {
// If we are tracking a captured `this`, keep track of the enclosing function.
const ancestorFacts = enterSubtree(
@@ -3445,11 +3484,11 @@ namespace ts {
getEmitFlags(node) & EmitFlags.CapturesThis
? HierarchyFacts.FunctionIncludes | HierarchyFacts.CapturesThis
: HierarchyFacts.FunctionIncludes);
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
exitSubtree(ancestorFacts, HierarchyFacts.None, HierarchyFacts.None);
return;
}
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
/**
@@ -3484,13 +3523,13 @@ namespace ts {
/**
* Hooks node substitutions.
*
* @param emitContext The context for the emitter.
* @param hint The context for the emitter.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (emitContext === EmitContext.Expression) {
if (hint === EmitHint.Expression) {
return substituteExpression(node);
}
@@ -3578,7 +3617,7 @@ namespace ts {
function substituteThisKeyword(node: PrimaryExpression): PrimaryExpression {
if (enabledSubstitutions & ES2015SubstitutionFlags.CapturedThis
&& hierarchyFacts & HierarchyFacts.CapturesThis) {
return createIdentifier("_this", /*location*/ node);
return setTextRange(createIdentifier("_this"), node);
}
return node;
}
+31 -17
View File
@@ -48,29 +48,37 @@ namespace ts {
// Transforms `a[x] **= b` into `(_a = a)[_x = x] = Math.pow(_a[_x], b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
const argumentExpressionTemp = createTempVariable(hoistVariableDeclaration);
target = createElementAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
createAssignment(argumentExpressionTemp, left.argumentExpression, /*location*/ left.argumentExpression),
/*location*/ left
target = setTextRange(
createElementAccess(
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
setTextRange(createAssignment(argumentExpressionTemp, left.argumentExpression), left.argumentExpression)
),
left
);
value = createElementAccess(
expressionTemp,
argumentExpressionTemp,
/*location*/ left
value = setTextRange(
createElementAccess(
expressionTemp,
argumentExpressionTemp
),
left
);
}
else if (isPropertyAccessExpression(left)) {
// Transforms `a.x **= b` into `(_a = a).x = Math.pow(_a.x, b)`
const expressionTemp = createTempVariable(hoistVariableDeclaration);
target = createPropertyAccess(
createAssignment(expressionTemp, left.expression, /*location*/ left.expression),
left.name,
/*location*/ left
target = setTextRange(
createPropertyAccess(
setTextRange(createAssignment(expressionTemp, left.expression), left.expression),
left.name
),
left
);
value = createPropertyAccess(
expressionTemp,
left.name,
/*location*/ left
value = setTextRange(
createPropertyAccess(
expressionTemp,
left.name
),
left
);
}
else {
@@ -78,7 +86,13 @@ namespace ts {
target = left;
value = left;
}
return createAssignment(target, createMathPow(value, right, /*location*/ node), /*location*/ node);
return setTextRange(
createAssignment(
target,
createMathPow(value, right, /*location*/ node)
),
node
);
}
function visitExponentiationExpression(node: BinaryExpression) {
+32 -25
View File
@@ -104,10 +104,12 @@ namespace ts {
*/
function visitAwaitExpression(node: AwaitExpression): Expression {
return setOriginalNode(
createYield(
/*asteriskToken*/ undefined,
visitNode(node.expression, visitor, isExpression),
/*location*/ node
setTextRange(
createYield(
/*asteriskToken*/ undefined,
visitNode(node.expression, visitor, isExpression)
),
node
),
node
);
@@ -238,7 +240,8 @@ namespace ts {
addRange(statements, endLexicalEnvironment());
const block = createBlock(statements, /*location*/ node.body, /*multiLine*/ true);
const block = createBlock(statements, /*multiLine*/ true);
setTextRange(block, node.body);
// Minor optimization, emit `_super` helper to capture `super` access in an arrow.
// This step isn't needed if we eventually transform this to ES5.
@@ -266,7 +269,7 @@ namespace ts {
const declarations = endLexicalEnvironment();
if (some(declarations)) {
const block = convertToFunctionBody(expression);
return updateBlock(block, createNodeArray(concatenate(block.statements, declarations), block.statements));
return updateBlock(block, setTextRange(createNodeArray(concatenate(block.statements, declarations)), block.statements));
}
return expression;
@@ -281,7 +284,7 @@ namespace ts {
startLexicalEnvironment();
const visited = convertToFunctionBody(visitNode(body, visitor, isConciseBody));
const declarations = endLexicalEnvironment();
return updateBlock(visited, createNodeArray(concatenate(visited.statements, declarations), visited.statements));
return updateBlock(visited, setTextRange(createNodeArray(concatenate(visited.statements, declarations)), visited.statements));
}
}
@@ -396,33 +399,33 @@ namespace ts {
/**
* Hook for node emit.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
// If we need to support substitutions for `super` in an async method,
// we should track it here.
if (enabledSubstitutions & ES2017SubstitutionFlags.AsyncMethodsWithSuper && isSuperContainer(node)) {
const savedCurrentSuperContainer = currentSuperContainer;
currentSuperContainer = node;
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
currentSuperContainer = savedCurrentSuperContainer;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
}
/**
* Hooks node substitutions.
*
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
* @param isExpression A value indicating whether the node is to be used in an expression
* position.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (emitContext === EmitContext.Expression) {
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
@@ -431,21 +434,25 @@ namespace ts {
function createSuperAccessInAsyncMethod(argumentExpression: Expression, flags: NodeCheckFlags, location: TextRange): LeftHandSideExpression {
if (flags & NodeCheckFlags.AsyncMethodWithSuperBinding) {
return createPropertyAccess(
return setTextRange(
createPropertyAccess(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
"value"
),
location
);
}
else {
return setTextRange(
createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression]
),
"value",
location
);
}
else {
return createCall(
createIdentifier("_super"),
/*typeArguments*/ undefined,
[argumentExpression],
location
);
}
+12 -10
View File
@@ -12,7 +12,7 @@ namespace ts {
const compilerOptions = context.getCompilerOptions();
// enable emit notification only if using --jsx preserve or react-native
let previousOnEmitNode: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
let previousOnEmitNode: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
let noSubstitution: boolean[];
if (compilerOptions.jsx === JsxEmit.Preserve || compilerOptions.jsx === JsxEmit.ReactNative) {
previousOnEmitNode = context.onEmitNode;
@@ -41,9 +41,11 @@ namespace ts {
/**
* Called by the printer just before a node is printed.
*
* @param node The node to be printed.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emitCallback A callback used to emit the node.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (emitContext: EmitHint, node: Node) => void) {
switch (node.kind) {
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxClosingElement:
@@ -53,21 +55,21 @@ namespace ts {
break;
}
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
/**
* Hooks node substitutions.
*
* @param emitContext The context for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
function onSubstituteNode(hint: EmitHint, node: Node) {
if (node.id && noSubstitution && noSubstitution[node.id]) {
return previousOnSubstituteNode(emitContext, node);
return previousOnSubstituteNode(hint, node);
}
node = previousOnSubstituteNode(emitContext, node);
node = previousOnSubstituteNode(hint, node);
if (isPropertyAccessExpression(node)) {
return substitutePropertyAccessExpression(node);
}
@@ -85,7 +87,7 @@ namespace ts {
function substitutePropertyAccessExpression(node: PropertyAccessExpression): Expression {
const literalName = trySubstituteReservedName(node.name);
if (literalName) {
return createElementAccess(node.expression, literalName, /*location*/ node);
return setTextRange(createElementAccess(node.expression, literalName), node);
}
return node;
}
@@ -111,7 +113,7 @@ namespace ts {
function trySubstituteReservedName(name: Identifier) {
const token = name.originalKeywordKind || (nodeIsSynthesized(name) ? stringToToken(name.text) : undefined);
if (token >= SyntaxKind.FirstReservedWord && token <= SyntaxKind.LastReservedWord) {
return createLiteral(name, /*location*/ name);
return setTextRange(createLiteral(name), name);
}
return undefined;
}
+16 -12
View File
@@ -210,36 +210,40 @@ namespace ts {
const statement = createVariableStatement(
/*modifiers*/ undefined,
updateVariableDeclarationList(initializer, declarations),
/*location*/ initializer
);
setTextRange(statement, initializer);
leadingStatements = append(leadingStatements, statement);
}
}
else if (isAssignmentPattern(initializer)) {
temp = createTempVariable(/*recordTempVariable*/ undefined);
const expression = flattenDestructuringAssignment(
aggregateTransformFlags(createAssignment(initializer, temp, /*location*/ node.initializer)),
aggregateTransformFlags(
setTextRange(
createAssignment(initializer, temp),
node.initializer
)
),
visitor,
context,
FlattenLevel.ObjectRest
);
leadingStatements = append(leadingStatements, createStatement(expression, /*location*/ node.initializer));
leadingStatements = append(leadingStatements, setTextRange(createStatement(expression), node.initializer));
}
}
if (temp) {
const expression = visitNode(node.expression, visitor, isExpression);
const statement = visitNode(node.statement, visitor, isStatement);
const block = isBlock(statement)
? updateBlock(statement, createNodeArray(concatenate(leadingStatements, statement.statements), statement.statements))
: createBlock(append(leadingStatements, statement), statement, /*multiLine*/ true);
? updateBlock(statement, setTextRange(createNodeArray(concatenate(leadingStatements, statement.statements)), statement.statements))
: setTextRange(createBlock(append(leadingStatements, statement), /*multiLine*/ true), statement);
return updateForOf(
node,
createVariableDeclarationList(
[
createVariableDeclaration(temp, /*type*/ undefined, /*initializer*/ undefined, node.initializer)
],
node.initializer,
NodeFlags.Let
setTextRange(
createVariableDeclarationList([
setTextRange(createVariableDeclaration(temp), node.initializer)
], NodeFlags.Let),
node.initializer
),
expression,
block
@@ -380,7 +384,7 @@ namespace ts {
const trailingStatements = endLexicalEnvironment();
if (some(leadingStatements) || some(trailingStatements)) {
const block = convertToFunctionBody(body, /*multiLine*/ true);
return updateBlock(block, createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements), block.statements));
return updateBlock(block, setTextRange(createNodeArray(concatenate(concatenate(leadingStatements, block.statements), trailingStatements)), block.statements));
}
return body;
}
+129 -93
View File
@@ -450,15 +450,17 @@ namespace ts {
// Currently, we only support generators that were originally async functions.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
node = setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
node.modifiers,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body),
setTextRange(
createFunctionDeclaration(
/*decorators*/ undefined,
node.modifiers,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body)
),
/*location*/ node
),
node
@@ -498,14 +500,16 @@ namespace ts {
// Currently, we only support generators that were originally async functions.
if (node.asteriskToken && getEmitFlags(node) & EmitFlags.AsyncFunctionBody) {
node = setOriginalNode(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body),
setTextRange(
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitParameterList(node.parameters, visitor, context),
/*type*/ undefined,
transformGeneratorFunctionBody(node.body)
),
/*location*/ node
),
node
@@ -606,7 +610,7 @@ namespace ts {
operationLocations = savedOperationLocations;
state = savedState;
return createBlock(statements, /*location*/ body, body.multiLine);
return setTextRange(createBlock(statements, body.multiLine), body);
}
/**
@@ -739,14 +743,17 @@ namespace ts {
const operator = node.operatorToken.kind;
if (isCompoundAssignment(operator)) {
return createBinary(
target,
SyntaxKind.EqualsToken,
createBinary(
cacheExpression(target),
getOperatorForCompoundAssignment(operator),
visitNode(right, visitor, isExpression),
node
return setTextRange(
createAssignment(
target,
setTextRange(
createBinary(
cacheExpression(target),
getOperatorForCompoundAssignment(operator),
visitNode(right, visitor, isExpression)
),
node
)
),
node
);
@@ -988,8 +995,11 @@ namespace ts {
const expressions = reduceLeft(elements, reduceElement, <Expression[]>[], numInitialElements);
return hasAssignedTemp
? createArrayConcat(temp, [createArrayLiteral(expressions, /*location*/ undefined, multiLine)])
: createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, location, multiLine);
? createArrayConcat(temp, [createArrayLiteral(expressions, multiLine)])
: setTextRange(
createArrayLiteral(leadingElement ? [leadingElement, ...expressions] : expressions, multiLine),
location
);
function reduceElement(expressions: Expression[], element: Expression) {
if (containsYield(element) && expressions.length > 0) {
@@ -998,11 +1008,10 @@ namespace ts {
hasAssignedTemp
? createArrayConcat(
temp,
[createArrayLiteral(expressions, /*location*/ undefined, multiLine)]
[createArrayLiteral(expressions, multiLine)]
)
: createArrayLiteral(
leadingElement ? [leadingElement, ...expressions] : expressions,
/*location*/ undefined,
multiLine
)
);
@@ -1043,7 +1052,6 @@ namespace ts {
emitAssignment(temp,
createObjectLiteral(
visitNodes(properties, visitor, isObjectLiteralElementLike, 0, numInitialProperties),
/*location*/ undefined,
multiLine
)
);
@@ -1139,18 +1147,20 @@ namespace ts {
const { target, thisArg } = createCallBinding(createPropertyAccess(node.expression, "bind"), hoistVariableDeclaration);
return setOriginalNode(
createNew(
createFunctionApply(
cacheExpression(visitNode(target, visitor, isExpression)),
thisArg,
visitElements(
node.arguments,
/*leadingElement*/ createVoidZero()
)
setTextRange(
createNew(
createFunctionApply(
cacheExpression(visitNode(target, visitor, isExpression)),
thisArg,
visitElements(
node.arguments,
/*leadingElement*/ createVoidZero()
)
),
/*typeArguments*/ undefined,
[]
),
/*typeArguments*/ undefined,
[],
/*location*/ node
node
),
node
);
@@ -1423,9 +1433,11 @@ namespace ts {
}
else {
emitStatement(
createStatement(
visitNode(initializer, visitor, isExpression),
/*location*/ initializer
setTextRange(
createStatement(
visitNode(initializer, visitor, isExpression)
),
initializer
)
);
}
@@ -1441,9 +1453,11 @@ namespace ts {
markLabel(incrementLabel);
if (node.incrementor) {
emitStatement(
createStatement(
visitNode(node.incrementor, visitor, isExpression),
/*location*/ node.incrementor
setTextRange(
createStatement(
visitNode(node.incrementor, visitor, isExpression)
),
node.incrementor
)
);
}
@@ -1909,9 +1923,9 @@ namespace ts {
return -1;
}
function onSubstituteNode(emitContext: EmitContext, node: Node): Node {
node = previousOnSubstituteNode(emitContext, node);
if (emitContext === EmitContext.Expression) {
function onSubstituteNode(hint: EmitHint, node: Node): Node {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
return node;
@@ -2417,11 +2431,13 @@ namespace ts {
*/
function createInlineBreak(label: Label, location?: TextRange): ReturnStatement {
Debug.assert(label > 0, `Invalid label: ${label}`);
return createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
]),
return setTextRange(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
])
),
location
);
}
@@ -2433,10 +2449,12 @@ namespace ts {
* @param location An optional source map location for the statement.
*/
function createInlineReturn(expression?: Expression, location?: TextRange): ReturnStatement {
return createReturn(
createArrayLiteral(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
return setTextRange(
createReturn(
createArrayLiteral(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
)
),
location
);
@@ -2446,7 +2464,14 @@ namespace ts {
* Creates an expression that can be used to resume from a Yield operation.
*/
function createGeneratorResume(location?: TextRange): LeftHandSideExpression {
return createCall(createPropertyAccess(state, "sent"), /*typeArguments*/ undefined, [], location);
return setTextRange(
createCall(
createPropertyAccess(state, "sent"),
/*typeArguments*/ undefined,
[]
),
location
);
}
/**
@@ -2614,7 +2639,6 @@ namespace ts {
/*type*/ undefined,
createBlock(
buildResult,
/*location*/ undefined,
/*multiLine*/ buildResult.length > 0
)
),
@@ -2944,7 +2968,7 @@ namespace ts {
* @param operationLocation The source map location for the operation.
*/
function writeAssign(left: Expression, right: Expression, operationLocation: TextRange): void {
writeStatement(createStatement(createAssignment(left, right), operationLocation));
writeStatement(setTextRange(createStatement(createAssignment(left, right)), operationLocation));
}
/**
@@ -2956,7 +2980,7 @@ namespace ts {
function writeThrow(expression: Expression, operationLocation: TextRange): void {
lastOperationWasAbrupt = true;
lastOperationWasCompletion = true;
writeStatement(createThrow(expression, operationLocation));
writeStatement(setTextRange(createThrow(expression), operationLocation));
}
/**
@@ -2970,10 +2994,12 @@ namespace ts {
lastOperationWasCompletion = true;
writeStatement(
setEmitFlags(
createReturn(
createArrayLiteral(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
setTextRange(
createReturn(
createArrayLiteral(expression
? [createInstruction(Instruction.Return), expression]
: [createInstruction(Instruction.Return)]
)
),
operationLocation
),
@@ -2992,11 +3018,13 @@ namespace ts {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
]),
setTextRange(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
])
),
operationLocation
),
EmitFlags.NoTokenSourceMaps
@@ -3017,11 +3045,13 @@ namespace ts {
createIf(
condition,
setEmitFlags(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
]),
setTextRange(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
])
),
operationLocation
),
EmitFlags.NoTokenSourceMaps
@@ -3045,11 +3075,13 @@ namespace ts {
createIf(
createLogicalNot(condition),
setEmitFlags(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
]),
setTextRange(
createReturn(
createArrayLiteral([
createInstruction(Instruction.Break),
createLabel(label)
])
),
operationLocation
),
EmitFlags.NoTokenSourceMaps
@@ -3070,11 +3102,13 @@ namespace ts {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
createReturn(
createArrayLiteral(
expression
? [createInstruction(Instruction.Yield), expression]
: [createInstruction(Instruction.Yield)]
setTextRange(
createReturn(
createArrayLiteral(
expression
? [createInstruction(Instruction.Yield), expression]
: [createInstruction(Instruction.Yield)]
)
),
operationLocation
),
@@ -3093,11 +3127,13 @@ namespace ts {
lastOperationWasAbrupt = true;
writeStatement(
setEmitFlags(
createReturn(
createArrayLiteral([
createInstruction(Instruction.YieldStar),
expression
]),
setTextRange(
createReturn(
createArrayLiteral([
createInstruction(Instruction.YieldStar),
expression
])
),
operationLocation
),
EmitFlags.NoTokenSourceMaps
+3 -3
View File
@@ -143,15 +143,15 @@ namespace ts {
function transformJsxAttributeInitializer(node: StringLiteral | JsxExpression) {
if (node === undefined) {
return createLiteral(true);
return createTrue();
}
else if (node.kind === SyntaxKind.StringLiteral) {
const decoded = tryDecodeEntities((<StringLiteral>node).text);
return decoded ? createLiteral(decoded, /*location*/ node) : node;
return decoded ? setTextRange(createLiteral(decoded), node) : node;
}
else if (node.kind === SyntaxKind.JsxExpression) {
if (node.expression === undefined) {
return createLiteral(true);
return createTrue();
}
return visitJsxExpression(<JsxExpression>node);
}
+9 -9
View File
@@ -37,7 +37,7 @@ namespace ts {
addRange(statements, visitNodes(node.statements, visitor, isStatement, statementOffset));
return updateSourceFileNode(
node,
createNodeArray(statements, node.statements));
setTextRange(createNodeArray(statements), node.statements));
}
else {
return visitEachChild(node, visitor, context);
@@ -71,18 +71,18 @@ namespace ts {
/**
* Hook for node emit.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (isSourceFile(node)) {
currentSourceFile = node;
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
currentSourceFile = undefined;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
}
@@ -93,12 +93,12 @@ namespace ts {
/**
* Hooks node substitutions.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (isIdentifier(node) && emitContext === EmitContext.Expression) {
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (isIdentifier(node) && hint === EmitHint.Expression) {
return substituteExpressionIdentifier(node);
}
return node;
+248 -218
View File
@@ -88,7 +88,7 @@ namespace ts {
addRange(statements, endLexicalEnvironment());
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ false);
const updated = updateSourceFileNode(node, createNodeArray(statements, node.statements));
const updated = updateSourceFileNode(node, setTextRange(createNodeArray(statements), node.statements));
if (currentModuleInfo.hasExportStarsToExportValues) {
addEmitHelper(updated, exportStarHelper);
}
@@ -131,47 +131,49 @@ namespace ts {
// Create an updated SourceFile:
//
// define(moduleName?, ["module1", "module2"], function ...
return updateSourceFileNode(node, createNodeArray(
[
createStatement(
createCall(
define,
/*typeArguments*/ undefined,
[
// Add the module name (if provided).
...(moduleName ? [moduleName] : []),
return updateSourceFileNode(node,
setTextRange(
createNodeArray([
createStatement(
createCall(
define,
/*typeArguments*/ undefined,
[
// Add the module name (if provided).
...(moduleName ? [moduleName] : []),
// Add the dependency array argument:
//
// ["require", "exports", module1", "module2", ...]
createArrayLiteral([
createLiteral("require"),
createLiteral("exports"),
...aliasedModuleNames,
...unaliasedModuleNames
]),
// Add the dependency array argument:
//
// ["require", "exports", module1", "module2", ...]
createArrayLiteral([
createLiteral("require"),
createLiteral("exports"),
...aliasedModuleNames,
...unaliasedModuleNames
]),
// Add the module body function argument:
//
// function (require, exports, module1, module2) ...
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"),
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"),
...importAliasNames
],
/*type*/ undefined,
transformAsynchronousModuleBody(node)
)
]
// Add the module body function argument:
//
// function (require, exports, module1, module2) ...
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
[
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "require"),
createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "exports"),
...importAliasNames
],
/*type*/ undefined,
transformAsynchronousModuleBody(node)
)
]
)
)
)
],
/*location*/ node.statements)
]),
/*location*/ node.statements
)
);
}
@@ -189,74 +191,76 @@ namespace ts {
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, "factory")],
/*type*/ undefined,
createBlock(
[
createIf(
createLogicalAnd(
createTypeCheck(createIdentifier("module"), "object"),
createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object")
),
createBlock([
createVariableStatement(
/*modifiers*/ undefined,
[
createVariableDeclaration(
"v",
/*type*/ undefined,
setTextRange(
createBlock(
[
createIf(
createLogicalAnd(
createTypeCheck(createIdentifier("module"), "object"),
createTypeCheck(createPropertyAccess(createIdentifier("module"), "exports"), "object")
),
createBlock([
createVariableStatement(
/*modifiers*/ undefined,
[
createVariableDeclaration(
"v",
/*type*/ undefined,
createCall(
createIdentifier("factory"),
/*typeArguments*/ undefined,
[
createIdentifier("require"),
createIdentifier("exports")
]
)
)
]
),
setEmitFlags(
createIf(
createStrictInequality(
createIdentifier("v"),
createIdentifier("undefined")
),
createStatement(
createAssignment(
createPropertyAccess(createIdentifier("module"), "exports"),
createIdentifier("v")
)
)
),
EmitFlags.SingleLine
)
]),
createIf(
createLogicalAnd(
createTypeCheck(createIdentifier("define"), "function"),
createPropertyAccess(createIdentifier("define"), "amd")
),
createBlock([
createStatement(
createCall(
createIdentifier("factory"),
createIdentifier("define"),
/*typeArguments*/ undefined,
[
createIdentifier("require"),
createIdentifier("exports")
createArrayLiteral([
createLiteral("require"),
createLiteral("exports"),
...aliasedModuleNames,
...unaliasedModuleNames
]),
createIdentifier("factory")
]
)
)
]
),
setEmitFlags(
createIf(
createStrictInequality(
createIdentifier("v"),
createIdentifier("undefined")
),
createStatement(
createAssignment(
createPropertyAccess(createIdentifier("module"), "exports"),
createIdentifier("v")
)
)
),
EmitFlags.SingleLine
])
)
]),
createIf(
createLogicalAnd(
createTypeCheck(createIdentifier("define"), "function"),
createPropertyAccess(createIdentifier("define"), "amd")
),
createBlock([
createStatement(
createCall(
createIdentifier("define"),
/*typeArguments*/ undefined,
[
createArrayLiteral([
createLiteral("require"),
createLiteral("exports"),
...aliasedModuleNames,
...unaliasedModuleNames
]),
createIdentifier("factory")
]
)
)
])
)
)
],
/*location*/ undefined,
/*multiLine*/ true
],
/*multiLine*/ true
),
/*location*/ undefined
)
);
@@ -274,8 +278,8 @@ namespace ts {
return updateSourceFileNode(
node,
createNodeArray(
[
setTextRange(
createNodeArray([
createStatement(
createCall(
umdHeader,
@@ -300,7 +304,7 @@ namespace ts {
]
)
)
],
]),
/*location*/ node.statements
)
);
@@ -378,7 +382,7 @@ namespace ts {
// Append the 'export =' statement if provided.
addExportEqualsIfNeeded(statements, /*emitAsReturn*/ true);
const body = createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
const body = createBlock(statements, /*multiLine*/ true);
if (currentModuleInfo.hasExportStarsToExportValues) {
// If we have any `export * from ...` declarations
// we need to inform the emitter to add the __export helper.
@@ -399,11 +403,8 @@ namespace ts {
function addExportEqualsIfNeeded(statements: Statement[], emitAsReturn: boolean) {
if (currentModuleInfo.exportEquals) {
if (emitAsReturn) {
const statement = createReturn(
currentModuleInfo.exportEquals.expression,
/*location*/ currentModuleInfo.exportEquals
);
const statement = createReturn(currentModuleInfo.exportEquals.expression);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoTokenSourceMaps | EmitFlags.NoComments);
statements.push(statement);
}
@@ -415,10 +416,10 @@ namespace ts {
"exports"
),
currentModuleInfo.exportEquals.expression
),
/*location*/ currentModuleInfo.exportEquals
)
);
setTextRange(statement, currentModuleInfo.exportEquals);
setEmitFlags(statement, EmitFlags.NoComments);
statements.push(statement);
}
@@ -481,7 +482,7 @@ namespace ts {
if (moduleKind !== ModuleKind.AMD) {
if (!node.importClause) {
// import "mod";
return createStatement(createRequireCall(node), /*location*/ node);
return setTextRange(createStatement(createRequireCall(node)), node);
}
else {
const variables: VariableDeclaration[] = [];
@@ -520,12 +521,13 @@ namespace ts {
}
statements = append(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
variables,
/*location*/ undefined,
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
variables,
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
)
),
/*location*/ node
)
@@ -539,14 +541,15 @@ namespace ts {
/*modifiers*/ undefined,
createVariableDeclarationList(
[
createVariableDeclaration(
getSynthesizedClone(namespaceDeclaration.name),
/*type*/ undefined,
getGeneratedNameForNode(node),
setTextRange(
createVariableDeclaration(
getSynthesizedClone(namespaceDeclaration.name),
/*type*/ undefined,
getGeneratedNameForNode(node)
),
/*location*/ node
)
],
/*location*/ undefined,
languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
)
)
@@ -592,31 +595,34 @@ namespace ts {
if (moduleKind !== ModuleKind.AMD) {
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
createStatement(
createExportExpression(
node.name,
createRequireCall(node)
setTextRange(
createStatement(
createExportExpression(
node.name,
createRequireCall(node)
)
),
/*location*/ node
node
)
);
}
else {
statements = append(statements,
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
[
createVariableDeclaration(
getSynthesizedClone(node.name),
/*type*/ undefined,
createRequireCall(node)
)
],
/*location*/ undefined,
/*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList(
[
createVariableDeclaration(
getSynthesizedClone(node.name),
/*type*/ undefined,
createRequireCall(node)
)
],
/*flags*/ languageVersion >= ScriptTarget.ES2015 ? NodeFlags.Const : NodeFlags.None
)
),
/*location*/ node
node
)
);
}
@@ -624,9 +630,11 @@ namespace ts {
else {
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
createStatement(
createExportExpression(getExportName(node), getLocalName(node)),
/*location*/ node
setTextRange(
createStatement(
createExportExpression(getExportName(node), getLocalName(node))
),
node
)
);
}
@@ -662,15 +670,17 @@ namespace ts {
// export { x, y } from "mod";
if (moduleKind !== ModuleKind.AMD) {
statements.push(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
generatedName,
/*type*/ undefined,
createRequireCall(node)
)
]),
setTextRange(
createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
generatedName,
/*type*/ undefined,
createRequireCall(node)
)
])
),
/*location*/ node
)
);
@@ -681,9 +691,11 @@ namespace ts {
specifier.propertyName || specifier.name
);
statements.push(
createStatement(
createExportExpression(getExportName(specifier), exportedValue),
/*location*/ specifier
setTextRange(
createStatement(
createExportExpression(getExportName(specifier), exportedValue)
),
specifier
)
);
}
@@ -692,17 +704,19 @@ namespace ts {
}
else {
// export * from "mod";
return createStatement(
createCall(
createIdentifier("__export"),
/*typeArguments*/ undefined,
[
moduleKind !== ModuleKind.AMD
? createRequireCall(node)
: generatedName
]
return setTextRange(
createStatement(
createCall(
createIdentifier("__export"),
/*typeArguments*/ undefined,
[
moduleKind !== ModuleKind.AMD
? createRequireCall(node)
: generatedName
]
)
),
/*location*/ node
node
);
}
}
@@ -741,15 +755,17 @@ namespace ts {
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
setOriginalNode(
createFunctionDeclaration(
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
node.parameters,
/*type*/ undefined,
node.body,
setTextRange(
createFunctionDeclaration(
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
node.asteriskToken,
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
node.parameters,
/*type*/ undefined,
node.body
),
/*location*/ node
),
/*original*/ node
@@ -782,16 +798,18 @@ namespace ts {
if (hasModifier(node, ModifierFlags.Export)) {
statements = append(statements,
setOriginalNode(
createClassDeclaration(
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
node.heritageClauses,
node.members,
/*location*/ node
setTextRange(
createClassDeclaration(
/*decorators*/ undefined,
visitNodes(node.modifiers, modifierVisitor, isModifier),
getDeclarationName(node, /*allowComments*/ true, /*allowSourceMaps*/ true),
/*typeParameters*/ undefined,
node.heritageClauses,
node.members
),
node
),
/*original*/ node
node
)
);
}
@@ -843,7 +861,7 @@ namespace ts {
}
if (expressions) {
statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node));
statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node));
}
}
else {
@@ -880,9 +898,11 @@ namespace ts {
}
else {
return createAssignment(
createPropertyAccess(
createIdentifier("exports"),
node.name,
setTextRange(
createPropertyAccess(
createIdentifier("exports"),
node.name
),
/*location*/ node.name
),
node.initializer
@@ -1115,7 +1135,7 @@ namespace ts {
createStatement(
createExportExpression(
createIdentifier("__esModule"),
createLiteral(true)
createTrue()
)
)
);
@@ -1130,7 +1150,7 @@ namespace ts {
createIdentifier("exports"),
createLiteral("__esModule"),
createObjectLiteral([
createPropertyAssignment("value", createLiteral(true))
createPropertyAssignment("value", createTrue())
])
]
)
@@ -1153,7 +1173,7 @@ namespace ts {
* @param allowComments An optional value indicating whether to emit comments for the statement.
*/
function createExportStatement(name: Identifier, value: Expression, location?: TextRange, allowComments?: boolean) {
const statement = createStatement(createExportExpression(name, value), location);
const statement = setTextRange(createStatement(createExportExpression(name, value)), location);
startOnNewLine(statement);
if (!allowComments) {
setEmitFlags(statement, EmitFlags.NoComments);
@@ -1170,12 +1190,14 @@ namespace ts {
* @param location The location to use for source maps and comments for the export.
*/
function createExportExpression(name: Identifier, value: Expression, location?: TextRange) {
return createAssignment(
createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(name)
return setTextRange(
createAssignment(
createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(name)
),
value
),
value,
location
);
}
@@ -1207,24 +1229,24 @@ namespace ts {
/**
* Hook for node emit notifications.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
currentSourceFile = <SourceFile>node;
currentModuleInfo = moduleInfoMap[getOriginalNodeId(currentSourceFile)];
noSubstitution = [];
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
currentSourceFile = undefined;
currentModuleInfo = undefined;
noSubstitution = undefined;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
}
@@ -1235,16 +1257,16 @@ namespace ts {
/**
* Hooks node substitutions.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (node.id && noSubstitution[node.id]) {
return node;
}
if (emitContext === EmitContext.Expression) {
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
else if (isShorthandPropertyAssignment(node)) {
@@ -1268,9 +1290,9 @@ namespace ts {
// destructuring assignment
if (node.objectAssignmentInitializer) {
const initializer = createAssignment(exportedOrImportedName, node.objectAssignmentInitializer);
return createPropertyAssignment(name, initializer, /*location*/ node);
return setTextRange(createPropertyAssignment(name, initializer), node);
}
return createPropertyAssignment(name, exportedOrImportedName, /*location*/ node);
return setTextRange(createPropertyAssignment(name, exportedOrImportedName), node);
}
return node;
}
@@ -1312,9 +1334,11 @@ namespace ts {
if (!isGeneratedIdentifier(node) && !isLocalName(node)) {
const exportContainer = resolver.getReferencedExportContainer(node, isExportName(node));
if (exportContainer && exportContainer.kind === SyntaxKind.SourceFile) {
return createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(node),
return setTextRange(
createPropertyAccess(
createIdentifier("exports"),
getSynthesizedClone(node)
),
/*location*/ node
);
}
@@ -1322,17 +1346,21 @@ namespace ts {
const importDeclaration = resolver.getReferencedImportDeclaration(node);
if (importDeclaration) {
if (isImportClause(importDeclaration)) {
return createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default"),
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default")
),
/*location*/ node
);
}
else if (isImportSpecifier(importDeclaration)) {
const name = importDeclaration.propertyName || importDeclaration.name;
return createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(name),
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(name)
),
/*location*/ node
);
}
@@ -1400,10 +1428,12 @@ namespace ts {
const exportedNames = getExports(node.operand);
if (exportedNames) {
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
? createBinary(
node.operand,
createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
createLiteral(1),
? setTextRange(
createBinary(
node.operand,
createToken(node.operator === SyntaxKind.PlusPlusToken ? SyntaxKind.PlusEqualsToken : SyntaxKind.MinusEqualsToken),
createLiteral(1)
),
/*location*/ node)
: node;
for (const exportName of exportedNames) {
+81 -78
View File
@@ -105,17 +105,20 @@ namespace ts {
const updated = setEmitFlags(
updateSourceFileNode(
node,
createNodeArray([
createStatement(
createCall(
createPropertyAccess(createIdentifier("System"), "register"),
/*typeArguments*/ undefined,
moduleName
? [moduleName, dependencies, moduleBodyFunction]
: [dependencies, moduleBodyFunction]
setTextRange(
createNodeArray([
createStatement(
createCall(
createPropertyAccess(createIdentifier("System"), "register"),
/*typeArguments*/ undefined,
moduleName
? [moduleName, dependencies, moduleBodyFunction]
: [dependencies, moduleBodyFunction]
)
)
)
], node.statements)
]),
node.statements
)
), EmitFlags.NoTrailingComments);
if (!(compilerOptions.outFile || compilerOptions.out)) {
@@ -260,35 +263,26 @@ namespace ts {
addRange(statements, endLexicalEnvironment());
const exportStarFunction = addExportStarIfNeeded(statements);
statements.push(
createReturn(
setMultiLine(
createObjectLiteral([
createPropertyAssignment("setters",
createSettersArray(exportStarFunction, dependencyGroups)
),
createPropertyAssignment("execute",
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
createBlock(
executeStatements,
/*location*/ undefined,
/*multiLine*/ true
)
)
)
]),
/*multiLine*/ true
const moduleObject = createObjectLiteral([
createPropertyAssignment("setters",
createSettersArray(exportStarFunction, dependencyGroups)
),
createPropertyAssignment("execute",
createFunctionExpression(
/*modifiers*/ undefined,
/*asteriskToken*/ undefined,
/*name*/ undefined,
/*typeParameters*/ undefined,
/*parameters*/ [],
/*type*/ undefined,
createBlock(executeStatements, /*multiLine*/ true)
)
)
);
]);
return createBlock(statements, /*location*/ undefined, /*multiLine*/ true);
moduleObject.multiLine = true;
statements.push(createReturn(moduleObject));
return createBlock(statements, /*multiLine*/ true);
}
/**
@@ -337,7 +331,7 @@ namespace ts {
exportedNames.push(
createPropertyAssignment(
createLiteral(exportedLocalName),
createLiteral(true)
createTrue()
)
);
}
@@ -359,7 +353,7 @@ namespace ts {
exportedNames.push(
createPropertyAssignment(
createLiteral((element.name || element.propertyName).text),
createLiteral(true)
createTrue()
)
);
}
@@ -373,7 +367,7 @@ namespace ts {
createVariableDeclaration(
exportedNamesStorageRef,
/*type*/ undefined,
createObjectLiteral(exportedNames, /*location*/ undefined, /*multiline*/ true)
createObjectLiteral(exportedNames, /*multiline*/ true)
)
])
)
@@ -456,9 +450,7 @@ namespace ts {
[exports]
)
)
],
/*location*/ undefined,
/*multiline*/ true)
], /*multiline*/ true)
);
}
@@ -525,7 +517,7 @@ namespace ts {
createCall(
exportFunction,
/*typeArguments*/ undefined,
[createObjectLiteral(properties, /*location*/ undefined, /*multiline*/ true)]
[createObjectLiteral(properties, /*multiline*/ true)]
)
)
);
@@ -558,12 +550,12 @@ namespace ts {
/*typeParameters*/ undefined,
[createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, parameterName)],
/*type*/ undefined,
createBlock(statements, /*location*/ undefined, /*multiLine*/ true)
createBlock(statements, /*multiLine*/ true)
)
);
}
return createArrayLiteral(setters, /*location*/ undefined, /*multiLine*/ true);
return createArrayLiteral(setters, /*multiLine*/ true);
}
//
@@ -713,19 +705,23 @@ namespace ts {
// Rewrite the class declaration into an assignment of a class expression.
statements = append(statements,
createStatement(
createAssignment(
name,
createClassExpression(
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause),
visitNodes(node.members, destructuringVisitor, isClassElement),
/*location*/ node
setTextRange(
createStatement(
createAssignment(
name,
setTextRange(
createClassExpression(
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
visitNodes(node.heritageClauses, destructuringVisitor, isHeritageClause),
visitNodes(node.members, destructuringVisitor, isClassElement)
),
node
)
)
),
/*location*/ node
node
)
);
@@ -766,7 +762,7 @@ namespace ts {
let statements: Statement[];
if (expressions) {
statements = append(statements, createStatement(inlineExpressions(expressions), /*location*/ node));
statements = append(statements, setTextRange(createStatement(inlineExpressions(expressions)), node));
}
if (isMarkedDeclaration) {
@@ -864,8 +860,8 @@ namespace ts {
function createVariableAssignment(name: Identifier, value: Expression, location: TextRange, isExportedDeclaration: boolean) {
hoistVariableDeclaration(getSynthesizedClone(name));
return isExportedDeclaration
? createExportExpression(name, preventSubstitution(createAssignment(name, value, location)))
: preventSubstitution(createAssignment(name, value, location));
? createExportExpression(name, preventSubstitution(setTextRange(createAssignment(name, value), location)))
: preventSubstitution(setTextRange(createAssignment(name, value), location));
}
/**
@@ -1548,11 +1544,11 @@ namespace ts {
/**
* Hook for node emit notifications.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
* @param emitCallback A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
if (node.kind === SyntaxKind.SourceFile) {
const id = getOriginalNodeId(node);
currentSourceFile = <SourceFile>node;
@@ -1564,7 +1560,7 @@ namespace ts {
delete noSubstitutionMap[id];
}
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
currentSourceFile = undefined;
moduleInfo = undefined;
@@ -1572,7 +1568,7 @@ namespace ts {
noSubstitution = undefined;
}
else {
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
}
}
@@ -1583,16 +1579,16 @@ namespace ts {
/**
* Hooks node substitutions.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (isSubstitutionPrevented(node)) {
return node;
}
if (emitContext === EmitContext.Expression) {
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
@@ -1642,16 +1638,20 @@ namespace ts {
const importDeclaration = resolver.getReferencedImportDeclaration(node);
if (importDeclaration) {
if (isImportClause(importDeclaration)) {
return createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default"),
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent),
createIdentifier("default")
),
/*location*/ node
);
}
else if (isImportSpecifier(importDeclaration)) {
return createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name),
return setTextRange(
createPropertyAccess(
getGeneratedNameForNode(importDeclaration.parent.parent.parent),
getSynthesizedClone(importDeclaration.propertyName || importDeclaration.name)
),
/*location*/ node
);
}
@@ -1718,10 +1718,13 @@ namespace ts {
const exportedNames = getExports(node.operand);
if (exportedNames) {
let expression: Expression = node.kind === SyntaxKind.PostfixUnaryExpression
? createPrefix(
node.operator,
node.operand,
/*location*/ node)
? setTextRange(
createPrefix(
node.operator,
node.operand
),
node
)
: node;
for (const exportName of exportedNames) {
+156 -117
View File
@@ -588,17 +588,17 @@ namespace ts {
name,
/*typeParameters*/ undefined,
visitNodes(node.heritageClauses, visitor, isHeritageClause),
transformClassMembers(node, hasExtendsClause),
node);
let emitFlags = getEmitFlags(node);
transformClassMembers(node, hasExtendsClause)
);
// To better align with the old emitter, we should not emit a trailing source map
// entry if the class has static properties.
let emitFlags = getEmitFlags(node);
if (hasStaticProperties) {
emitFlags |= EmitFlags.NoTrailingSourceMap;
}
setTextRange(classDeclaration, node);
setOriginalNode(classDeclaration, node);
setEmitFlags(classDeclaration, emitFlags);
return classDeclaration;
@@ -709,13 +709,24 @@ namespace ts {
// }
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
const members = transformClassMembers(node, hasExtendsClause);
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members, location);
const classExpression = createClassExpression(/*modifiers*/ undefined, name, /*typeParameters*/ undefined, heritageClauses, members);
setOriginalNode(classExpression, node);
setTextRange(classExpression, location);
// let ${name} = ${classExpression} where name is either declaredName if the class doesn't contain self-reference
// or decoratedClassAlias if the class contain self-reference.
const statement = createLetStatement(declName, classAlias ? createAssignment(classAlias, classExpression) : classExpression, location);
const statement = createVariableStatement(
/*modifiers*/ undefined,
createVariableDeclarationList([
createVariableDeclaration(
declName,
/*type*/ undefined,
classAlias ? createAssignment(classAlias, classExpression) : classExpression
)
], NodeFlags.Let)
);
setOriginalNode(statement, node);
setTextRange(statement, location);
setCommentRange(statement, node);
return statement;
}
@@ -734,18 +745,17 @@ namespace ts {
const heritageClauses = visitNodes(node.heritageClauses, visitor, isHeritageClause);
const members = transformClassMembers(node, some(heritageClauses, c => c.token === SyntaxKind.ExtendsKeyword));
const classExpression = setOriginalNode(
createClassExpression(
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
heritageClauses,
members,
/*location*/ node
),
node
const classExpression = createClassExpression(
/*modifiers*/ undefined,
node.name,
/*typeParameters*/ undefined,
heritageClauses,
members
);
setOriginalNode(classExpression, node);
setTextRange(classExpression, node);
if (staticProperties.length > 0) {
const expressions: Expression[] = [];
const temp = createTempVariable(hoistVariableDeclaration);
@@ -781,7 +791,7 @@ namespace ts {
}
addRange(members, visitNodes(node.members, classElementVisitor, isClassElement));
return createNodeArray(members, /*location*/ node.members);
return setTextRange(createNodeArray(members), /*location*/ node.members);
}
/**
@@ -812,12 +822,14 @@ namespace ts {
// }
return startOnNewLine(
setOriginalNode(
createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
body,
/*location*/ constructor || node
setTextRange(
createConstructor(
/*decorators*/ undefined,
/*modifiers*/ undefined,
parameters,
body
),
constructor || node
),
constructor
)
@@ -919,13 +931,15 @@ namespace ts {
// End the lexical environment.
addRange(statements, endLexicalEnvironment());
return createBlock(
createNodeArray(
statements,
/*location*/ constructor ? constructor.body.statements : node.members
return setTextRange(
createBlock(
setTextRange(
createNodeArray(statements),
/*location*/ constructor ? constructor.body.statements : node.members
),
/*multiLine*/ true
),
/*location*/ constructor ? constructor.body : /*location*/ undefined,
/*multiLine*/ true
/*location*/ constructor ? constructor.body : undefined
);
}
@@ -991,16 +1005,20 @@ namespace ts {
setEmitFlags(localName, EmitFlags.NoComments);
return startOnNewLine(
createStatement(
createAssignment(
createPropertyAccess(
createThis(),
propertyName,
/*location*/ node.name
),
localName
setTextRange(
createStatement(
createAssignment(
setTextRange(
createPropertyAccess(
createThis(),
propertyName
),
node.name
),
localName
)
),
/*location*/ moveRangePos(node, -1)
moveRangePos(node, -1)
)
);
}
@@ -1504,7 +1522,7 @@ namespace ts {
(properties || (properties = [])).push(createPropertyAssignment("returnType", createArrowFunction(/*modifiers*/ undefined, /*typeParameters*/ undefined, [], /*type*/ undefined, createToken(SyntaxKind.EqualsGreaterThanToken), serializeReturnTypeOfNode(node))));
}
if (properties) {
decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*location*/ undefined, /*multiLine*/ true)));
decoratorExpressions.push(createMetadataHelper(context, "design:typeinfo", createObjectLiteral(properties, /*multiLine*/ true)));
}
}
}
@@ -1939,10 +1957,7 @@ namespace ts {
expression = createAssignment(generatedName, expression);
}
return setOriginalNode(
createComputedPropertyName(expression, /*location*/ name),
name
);
return updateComputedPropertyName(name, expression);
}
else {
return name;
@@ -1961,9 +1976,11 @@ namespace ts {
function visitHeritageClause(node: HeritageClause): HeritageClause {
if (node.token === SyntaxKind.ExtendsKeyword) {
const types = visitNodes(node.types, visitor, isExpressionWithTypeArguments, 0, 1);
return createHeritageClause(
SyntaxKind.ExtendsKeyword,
types,
return setTextRange(
createHeritageClause(
SyntaxKind.ExtendsKeyword,
types
),
node
);
}
@@ -1980,11 +1997,10 @@ namespace ts {
* @param node The ExpressionWithTypeArguments to transform.
*/
function visitExpressionWithTypeArguments(node: ExpressionWithTypeArguments): ExpressionWithTypeArguments {
const expression = visitNode(node.expression, visitor, isLeftHandSideExpression);
return createExpressionWithTypeArguments(
return updateExpressionWithTypeArguments(
node,
/*typeArguments*/ undefined,
expression,
node
visitNode(node.expression, visitor, isLeftHandSideExpression)
);
}
@@ -2205,13 +2221,13 @@ namespace ts {
visitNode(node.name, visitor, isBindingName),
/*questionToken*/ undefined,
/*type*/ undefined,
visitNode(node.initializer, visitor, isExpression),
/*location*/ moveRangePastModifiers(node)
visitNode(node.initializer, visitor, isExpression)
);
// While we emit the source map for the node after skipping decorators and modifiers,
// we need to emit the comments for the original range.
setOriginalNode(parameter, node);
setTextRange(parameter, moveRangePastModifiers(node));
setCommentRange(parameter, node);
setSourceMapRange(parameter, moveRangePastModifiers(node));
setEmitFlags(parameter.name, EmitFlags.NoTrailingSourceMap);
@@ -2233,11 +2249,13 @@ namespace ts {
return undefined;
}
return createStatement(
inlineExpressions(
map(variables, transformInitializedVariable)
return setTextRange(
createStatement(
inlineExpressions(
map(variables, transformInitializedVariable)
)
),
/*location*/ node
node
);
}
else {
@@ -2258,9 +2276,11 @@ namespace ts {
);
}
else {
return createAssignment(
getNamespaceMemberNameWithSourceMapsAndWithoutComments(name),
visitNode(node.initializer, visitor, isExpression),
return setTextRange(
createAssignment(
getNamespaceMemberNameWithSourceMapsAndWithoutComments(name),
visitNode(node.initializer, visitor, isExpression)
),
/*location*/ node
);
}
@@ -2418,11 +2438,11 @@ namespace ts {
),
/*typeArguments*/ undefined,
[moduleArg]
),
/*location*/ node
)
);
setOriginalNode(enumStatement, node);
setTextRange(enumStatement, node);
setEmitFlags(enumStatement, emitFlags);
statements.push(enumStatement);
@@ -2448,8 +2468,7 @@ namespace ts {
currentNamespaceContainerName = savedCurrentNamespaceLocalName;
return createBlock(
createNodeArray(statements, /*location*/ node.members),
/*location*/ undefined,
setTextRange(createNodeArray(statements), /*location*/ node.members),
/*multiLine*/ true
);
}
@@ -2464,22 +2483,26 @@ namespace ts {
// we pass false as 'generateNameForComputedPropertyName' for a backward compatibility purposes
// old emitter always generate 'expression' part of the name as-is.
const name = getExpressionForPropertyName(member, /*generateNameForComputedPropertyName*/ false);
return createStatement(
createAssignment(
createElementAccess(
currentNamespaceContainerName,
return setTextRange(
createStatement(
setTextRange(
createAssignment(
createElementAccess(
currentNamespaceContainerName,
name
createAssignment(
createElementAccess(
currentNamespaceContainerName,
name
),
transformEnumMemberDeclarationValue(member)
)
),
transformEnumMemberDeclarationValue(member)
)
),
name,
/*location*/ member
name
),
member
)
),
/*location*/ member
member
);
}
@@ -2697,11 +2720,11 @@ namespace ts {
),
/*typeArguments*/ undefined,
[moduleArg]
),
/*location*/ node
)
);
setOriginalNode(moduleStatement, node);
setTextRange(moduleStatement, node);
setEmitFlags(moduleStatement, emitFlags);
statements.push(moduleStatement);
@@ -2756,13 +2779,13 @@ namespace ts {
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
const block = createBlock(
createNodeArray(
statements,
setTextRange(
createNodeArray(statements),
/*location*/ statementsLocation
),
/*location*/ blockLocation,
/*multiLine*/ true
);
setTextRange(block, blockLocation);
// namespace hello.hi.world {
// function foo() {}
@@ -2962,18 +2985,20 @@ namespace ts {
// export var ${name} = ${moduleReference};
// var ${name} = ${moduleReference};
return setOriginalNode(
createVariableStatement(
visitNodes(node.modifiers, modifierVisitor, isModifier),
createVariableDeclarationList([
setOriginalNode(
createVariableDeclaration(
node.name,
/*type*/ undefined,
moduleReference
),
node
)
]),
setTextRange(
createVariableStatement(
visitNodes(node.modifiers, modifierVisitor, isModifier),
createVariableDeclarationList([
setOriginalNode(
createVariableDeclaration(
node.name,
/*type*/ undefined,
moduleReference
),
node
)
])
),
node
),
node
@@ -3034,7 +3059,7 @@ namespace ts {
* Creates a statement for the provided expression. This is used in calls to `map`.
*/
function expressionToStatement(expression: Expression) {
return createStatement(expression, /*location*/ undefined);
return createStatement(expression);
}
function addExportMemberAssignment(statements: Statement[], node: ClassDeclaration | FunctionDeclaration) {
@@ -3050,17 +3075,19 @@ namespace ts {
}
function createNamespaceExport(exportName: Identifier, exportValue: Expression, location?: TextRange) {
return createStatement(
createAssignment(
getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
exportValue
return setTextRange(
createStatement(
createAssignment(
getNamespaceMemberName(currentNamespaceContainerName, exportName, /*allowComments*/ false, /*allowSourceMaps*/ true),
exportValue
)
),
location
);
}
function createNamespaceExportExpression(exportName: Identifier, exportValue: Expression, location?: TextRange) {
return createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue, location);
return setTextRange(createAssignment(getNamespaceMemberNameWithSourceMapsAndWithoutComments(exportName), exportValue), location);
}
function getNamespaceMemberNameWithSourceMapsAndWithoutComments(name: Identifier) {
@@ -3092,7 +3119,7 @@ namespace ts {
function getClassAliasIfNeeded(node: ClassDeclaration) {
if (resolver.getNodeCheckFlags(node) & NodeCheckFlags.ClassWithConstructorReference) {
enableSubstitutionForClassAliases();
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? node.name.text : "default");
const classAlias = createUniqueName(node.name && !isGeneratedIdentifier(node.name) ? unescapeIdentifier(node.name.text) : "default");
classAliases[getOriginalNodeId(node)] = classAlias;
hoistVariableDeclaration(classAlias);
return classAlias;
@@ -3154,11 +3181,11 @@ namespace ts {
/**
* Hook for node emit.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emit A callback used to emit the node in the printer.
*/
function onEmitNode(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void {
function onEmitNode(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void {
const savedApplicableSubstitutions = applicableSubstitutions;
if (enabledSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && isTransformedModuleDeclaration(node)) {
@@ -3169,7 +3196,7 @@ namespace ts {
applicableSubstitutions |= TypeScriptSubstitutionFlags.NonQualifiedEnumMembers;
}
previousOnEmitNode(emitContext, node, emitCallback);
previousOnEmitNode(hint, node, emitCallback);
applicableSubstitutions = savedApplicableSubstitutions;
}
@@ -3177,12 +3204,12 @@ namespace ts {
/**
* Hooks node substitutions.
*
* @param emitContext A context hint for the emitter.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
*/
function onSubstituteNode(emitContext: EmitContext, node: Node) {
node = previousOnSubstituteNode(emitContext, node);
if (emitContext === EmitContext.Expression) {
function onSubstituteNode(hint: EmitHint, node: Node) {
node = previousOnSubstituteNode(hint, node);
if (hint === EmitHint.Expression) {
return substituteExpression(<Expression>node);
}
else if (isShorthandPropertyAssignment(node)) {
@@ -3201,9 +3228,9 @@ namespace ts {
// destructuring assignment
if (node.objectAssignmentInitializer) {
const initializer = createAssignment(exportedName, node.objectAssignmentInitializer);
return createPropertyAssignment(name, initializer, /*location*/ node);
return setTextRange(createPropertyAssignment(name, initializer), node);
}
return createPropertyAssignment(name, exportedName, /*location*/ node);
return setTextRange(createPropertyAssignment(name, exportedName), node);
}
}
return node;
@@ -3263,7 +3290,10 @@ namespace ts {
(applicableSubstitutions & TypeScriptSubstitutionFlags.NamespaceExports && container.kind === SyntaxKind.ModuleDeclaration) ||
(applicableSubstitutions & TypeScriptSubstitutionFlags.NonQualifiedEnumMembers && container.kind === SyntaxKind.EnumDeclaration);
if (substitute) {
return createPropertyAccess(getGeneratedNameForNode(container), node, /*location*/ node);
return setTextRange(
createPropertyAccess(getGeneratedNameForNode(container), node),
/*location*/ node
);
}
}
}
@@ -3322,13 +3352,15 @@ namespace ts {
function createParamHelper(context: TransformationContext, expression: Expression, parameterOffset: number, location?: TextRange) {
context.requestEmitHelper(paramHelper);
return createCall(
getHelperName("__param"),
/*typeArguments*/ undefined,
[
createLiteral(parameterOffset),
expression
],
return setTextRange(
createCall(
getHelperName("__param"),
/*typeArguments*/ undefined,
[
createLiteral(parameterOffset),
expression
]
),
location
);
}
@@ -3371,7 +3403,7 @@ namespace ts {
function createDecorateHelper(context: TransformationContext, decoratorExpressions: Expression[], target: Expression, memberName?: Expression, descriptor?: Expression, location?: TextRange) {
context.requestEmitHelper(decorateHelper);
const argumentsArray: Expression[] = [];
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*location*/ undefined, /*multiLine*/ true));
argumentsArray.push(createArrayLiteral(decoratorExpressions, /*multiLine*/ true));
argumentsArray.push(target);
if (memberName) {
argumentsArray.push(memberName);
@@ -3380,6 +3412,13 @@ namespace ts {
}
}
return createCall(getHelperName("__decorate"), /*typeArguments*/ undefined, argumentsArray, location);
return setTextRange(
createCall(
getHelperName("__decorate"),
/*typeArguments*/ undefined,
argumentsArray
),
location
);
}
}
+130 -18
View File
@@ -348,6 +348,7 @@
EnumMember,
// Top-level nodes
SourceFile,
Bundle,
// JSDoc nodes
JSDocTypeExpression,
@@ -957,8 +958,7 @@
}
// Represents an expression that is elided as part of a transformation to emit comments on a
// not-emitted node. The 'expression' property of a NotEmittedExpression should be emitted.
// @internal
// not-emitted node. The 'expression' property of a PartiallyEmittedExpression should be emitted.
export interface PartiallyEmittedExpression extends LeftHandSideExpression {
kind: SyntaxKind.PartiallyEmittedExpression;
expression: Expression;
@@ -1537,7 +1537,6 @@
// Represents a statement that is elided as part of a transformation to emit comments on a
// not-emitted node.
// @internal
export interface NotEmittedStatement extends Statement {
kind: SyntaxKind.NotEmittedStatement;
}
@@ -1772,24 +1771,28 @@
members: NodeArray<EnumMember>;
}
export type ModuleBody = ModuleBlock | ModuleDeclaration;
export type ModuleName = Identifier | StringLiteral;
export type ModuleBody = NamespaceBody | JSDocNamespaceBody;
export interface ModuleDeclaration extends DeclarationStatement {
kind: SyntaxKind.ModuleDeclaration;
name: Identifier | StringLiteral;
body?: ModuleBlock | NamespaceDeclaration | JSDocNamespaceDeclaration | Identifier;
body?: ModuleBody | JSDocNamespaceDeclaration | Identifier;
}
export type NamespaceBody = ModuleBlock | NamespaceDeclaration;
export interface NamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: ModuleBlock | NamespaceDeclaration;
body: NamespaceBody;
}
export type JSDocNamespaceBody = Identifier | JSDocNamespaceDeclaration;
export interface JSDocNamespaceDeclaration extends ModuleDeclaration {
name: Identifier;
body: JSDocNamespaceDeclaration | Identifier;
body: JSDocNamespaceBody;
}
export interface ModuleBlock extends Node, Statement {
@@ -2201,6 +2204,11 @@
/* @internal */ ambientModuleNames: string[];
}
export interface Bundle extends Node {
kind: SyntaxKind.Bundle;
sourceFiles: SourceFile[];
}
export interface ScriptReferenceHost {
getCompilerOptions(): CompilerOptions;
getSourceFile(fileName: string): SourceFile;
@@ -3724,7 +3732,6 @@
helpers?: EmitHelper[]; // Emit helpers for the node
}
/* @internal */
export const enum EmitFlags {
SingleLine = 1 << 0, // The contents of this node should be emitted on a single line.
AdviseOnEmitNode = 1 << 1, // The printer should invoke the onEmitNode callback when printing this node.
@@ -3753,7 +3760,6 @@
HasEndOfDeclarationMarker = 1 << 21, // Declaration has an associated NotEmittedStatement to mark the end of the declaration
}
/* @internal */
export interface EmitHelper {
readonly name: string; // A unique name for this helper.
readonly scoped: boolean; // Indicates whether ther helper MUST be emitted in the current scope.
@@ -3780,8 +3786,7 @@
LastEmitHelper = Generator
}
/* @internal */
export const enum EmitContext {
export const enum EmitHint {
SourceFile, // Emitting a SourceFile
Expression, // Emitting an Expression
IdentifierName, // Emitting an IdentifierName
@@ -3856,7 +3861,7 @@
* Hook used by transformers to substitute expressions just before they
* are emitted by the pretty printer.
*/
onSubstituteNode?: (emitContext: EmitContext, node: Node) => Node;
onSubstituteNode?: (hint: EmitHint, node: Node) => Node;
/**
* Enables before/after emit notifications in the pretty printer for the provided
@@ -3874,7 +3879,7 @@
* Hook used to allow transformers to capture state before or after
* the printer emits a node.
*/
onEmitNode?: (emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void) => void;
onEmitNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
}
/* @internal */
@@ -3887,25 +3892,132 @@
/**
* Emits the substitute for a node, if one is available; otherwise, emits the node.
*
* @param emitContext The current emit context.
* @param hint A hint as to the intended usage of the node.
* @param node The node to substitute.
* @param emitCallback A callback used to emit the node or its substitute.
*/
emitNodeWithSubstitution(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
emitNodeWithSubstitution(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
/**
* Emits a node with possible notification.
*
* @param emitContext The current emit context.
* @param hint A hint as to the intended usage of the node.
* @param node The node to emit.
* @param emitCallback A callback used to emit the node.
*/
emitNodeWithNotification(emitContext: EmitContext, node: Node, emitCallback: (emitContext: EmitContext, node: Node) => void): void;
emitNodeWithNotification(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
}
/* @internal */
export type Transformer = (context: TransformationContext) => (node: SourceFile) => SourceFile;
export interface Printer {
/**
* Print a node and its subtree as-is, without any emit transformations.
* @param hint A value indicating the purpose of a node. This is primarily used to
* distinguish between an `Identifier` used in an expression position, versus an
* `Identifier` used as an `IdentifierName` as part of a declaration. For most nodes you
* should just pass `Unspecified`.
* @param node The node to print. The node and its subtree are printed as-is, without any
* emit transformations.
* @param sourceFile A source file that provides context for the node. The source text of
* the file is used to emit the original source content for literals and identifiers, while
* the identifiers of the source file are used when generating unique names to avoid
* collisions.
*/
printNode(hint: EmitHint, node: Node, sourceFile: SourceFile): string;
/**
* Prints a source file as-is, without any emit transformations.
*/
printFile(sourceFile: SourceFile): string;
/**
* Prints a bundle of source files as-is, without any emit transformations.
*/
printBundle(bundle: Bundle): string;
/*@internal*/ writeNode(hint: EmitHint, node: Node, sourceFile: SourceFile, writer: EmitTextWriter): void;
/*@internal*/ writeFile(sourceFile: SourceFile, writer: EmitTextWriter): void;
/*@internal*/ writeBundle(bundle: Bundle, writer: EmitTextWriter): void;
}
export interface PrintHandlers {
/**
* A hook used by the Printer when generating unique names to avoid collisions with
* globally defined names that exist outside of the current source file.
*/
hasGlobalName?(name: string): boolean;
/**
* A hook used by the Printer to provide notifications prior to emitting a node. A
* compatible implementation **must** invoke `emitCallback` with the provided `hint` and
* `node` values.
* @param hint A hint indicating the intended purpose of the node.
* @param node The node to emit.
* @param emitCallback A callback that, when invoked, will emit the node.
* @example
* ```ts
* var printer = createPrinter(printerOptions, {
* onEmitNode(hint, node, emitCallback) {
* // set up or track state prior to emitting the node...
* emitCallback(hint, node);
* // restore state after emitting the node...
* }
* });
* ```
*/
onEmitNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
/**
* A hook used by the Printer to perform just-in-time substitution of a node. This is
* primarily used by node transformations that need to substitute one node for another,
* such as replacing `myExportedVar` with `exports.myExportedVar`. A compatible
* implementation **must** invoke `emitCallback` eith the provided `hint` and either
* the provided `node`, or its substitute.
* @param hint A hint indicating the intended purpose of the node.
* @param node The node to emit.
* @param emitCallback A callback that, when invoked, will emit the node.
* @example
* ```ts
* var printer = createPrinter(printerOptions, {
* onSubstituteNode(hint, node, emitCallback) {
* // perform substitution if necessary...
* emitCallback(hint, node);
* }
* });
* ```
*/
onSubstituteNode?(hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void): void;
/*@internal*/ onEmitSourceMapOfNode?: (hint: EmitHint, node: Node, emitCallback: (hint: EmitHint, node: Node) => void) => void;
/*@internal*/ onEmitSourceMapOfToken?: (node: Node, token: SyntaxKind, pos: number, emitCallback: (token: SyntaxKind, pos: number) => number) => number;
/*@internal*/ onEmitSourceMapOfPosition?: (pos: number) => void;
/*@internal*/ onEmitHelpers?: (node: Node, writeLines: (text: string) => void) => void;
/*@internal*/ onSetSourceFile?: (node: SourceFile) => void;
}
export interface PrinterOptions {
target?: ScriptTarget;
removeComments?: boolean;
newLine?: NewLineKind;
/*@internal*/ sourceMap?: boolean;
/*@internal*/ inlineSourceMap?: boolean;
/*@internal*/ extendedDiagnostics?: boolean;
}
/*@internal*/
export interface EmitTextWriter {
write(s: string): void;
writeTextOfNode(text: string, node: Node): void;
writeLine(): void;
increaseIndent(): void;
decreaseIndent(): void;
getText(): string;
rawWrite(s: string): void;
writeLiteral(s: string): void;
getTextPos(): number;
getLine(): number;
getColumn(): number;
getIndent(): number;
isAtStartOfLine(): boolean;
reset(): void;
}
export interface TextSpan {
start: number;
length: number;
+83 -76
View File
@@ -2042,67 +2042,19 @@ namespace ts {
|| positionIsSynthesized(node.end);
}
export function getOriginalNode(node: Node): Node;
export function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
if (node) {
while (node.original !== undefined) {
node = node.original;
}
export function getOriginalSourceFileOrBundle(sourceFileOrBundle: SourceFile | Bundle) {
if (sourceFileOrBundle.kind === SyntaxKind.Bundle) {
return updateBundle(sourceFileOrBundle, sameMap(sourceFileOrBundle.sourceFiles, getOriginalSourceFile));
}
return !nodeTest || nodeTest(node) ? node : undefined;
return getOriginalSourceFile(sourceFileOrBundle);
}
/**
* Gets a value indicating whether a node originated in the parse tree.
*
* @param node The node to test.
*/
export function isParseTreeNode(node: Node): boolean {
return (node.flags & NodeFlags.Synthesized) === 0;
}
/**
* Gets the original parse tree node for a node.
*
* @param node The original node.
* @returns The original parse tree node if found; otherwise, undefined.
*/
export function getParseTreeNode(node: Node): Node;
/**
* Gets the original parse tree node for a node.
*
* @param node The original node.
* @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, nodeTest?: (node: Node) => node is T): T;
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
if (isParseTreeNode(node)) {
return node;
}
node = getOriginalNode(node);
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
return node;
}
return undefined;
function getOriginalSourceFile(sourceFile: SourceFile) {
return getParseTreeNode(sourceFile, isSourceFile) || sourceFile;
}
export function getOriginalSourceFiles(sourceFiles: SourceFile[]) {
const originalSourceFiles: SourceFile[] = [];
for (const sourceFile of sourceFiles) {
const originalSourceFile = getParseTreeNode(sourceFile, isSourceFile);
if (originalSourceFile) {
originalSourceFiles.push(originalSourceFile);
}
}
return originalSourceFiles;
return sameMap(sourceFiles, getOriginalSourceFile);
}
export function getOriginalNodeId(node: Node) {
@@ -2441,23 +2393,6 @@ namespace ts {
s;
}
export interface EmitTextWriter {
write(s: string): void;
writeTextOfNode(text: string, node: Node): void;
writeLine(): void;
increaseIndent(): void;
decreaseIndent(): void;
getText(): string;
rawWrite(s: string): void;
writeLiteral(s: string): void;
getTextPos(): number;
getLine(): number;
getColumn(): number;
getIndent(): number;
isAtStartOfLine(): boolean;
reset(): void;
}
const indentStrings: string[] = ["", " "];
export function getIndentString(level: number) {
if (indentStrings[level] === undefined) {
@@ -2640,7 +2575,7 @@ namespace ts {
* Else, calls `getSourceFilesToEmit` with the (optional) target source file to determine the list of source files to emit.
*/
export function forEachEmittedFile(
host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFiles: SourceFile[], isBundledEmit: boolean, emitOnlyDtsFiles: boolean) => void,
host: EmitHost, action: (emitFileNames: EmitFileNames, sourceFileOrBundle: SourceFile | Bundle, emitOnlyDtsFiles: boolean) => void,
sourceFilesOrTargetSourceFile?: SourceFile[] | SourceFile,
emitOnlyDtsFiles?: boolean) {
@@ -2651,7 +2586,7 @@ namespace ts {
const jsFilePath = options.outFile || options.out;
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = options.declaration ? removeFileExtension(jsFilePath) + ".d.ts" : undefined;
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFiles, /*isBundledEmit*/true, emitOnlyDtsFiles);
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, createBundle(sourceFiles), emitOnlyDtsFiles);
}
}
else {
@@ -2659,7 +2594,7 @@ namespace ts {
const jsFilePath = getOwnEmitOutputFilePath(sourceFile, host, getOutputExtension(sourceFile, options));
const sourceMapFilePath = getSourceMapFilePath(jsFilePath, options);
const declarationFilePath = !isSourceFileJavaScript(sourceFile) && (emitOnlyDtsFiles || options.declaration) ? getDeclarationEmitOutputFilePath(sourceFile, host) : undefined;
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, [sourceFile], /*isBundledEmit*/false, emitOnlyDtsFiles);
action({ jsFilePath, sourceMapFilePath, declarationFilePath }, sourceFile, emitOnlyDtsFiles);
}
}
}
@@ -3234,7 +3169,7 @@ namespace ts {
const carriageReturnLineFeed = "\r\n";
const lineFeed = "\n";
export function getNewLineCharacter(options: CompilerOptions): string {
export function getNewLineCharacter(options: CompilerOptions | PrinterOptions): string {
if (options.newLine === NewLineKind.CarriageReturnLineFeed) {
return carriageReturnLineFeed;
}
@@ -3345,6 +3280,14 @@ namespace ts {
}
}
export function getRangePos(range: TextRange | undefined) {
return range ? range.pos : -1;
}
export function getRangeEnd(range: TextRange | undefined) {
return range ? range.end : -1;
}
/**
* Increases (or decreases) a position by the provided amount.
*
@@ -3944,6 +3887,19 @@ namespace ts {
export function isModuleBody(node: Node): node is ModuleBody {
const kind = node.kind;
return kind === SyntaxKind.ModuleBlock
|| kind === SyntaxKind.ModuleDeclaration
|| kind === SyntaxKind.Identifier;
}
export function isNamespaceBody(node: Node): node is NamespaceBody {
const kind = node.kind;
return kind === SyntaxKind.ModuleBlock
|| kind === SyntaxKind.ModuleDeclaration;
}
export function isJSDocNamespaceBody(node: Node): node is JSDocNamespaceBody {
const kind = node.kind;
return kind === SyntaxKind.Identifier
|| kind === SyntaxKind.ModuleDeclaration;
}
@@ -4536,4 +4492,55 @@ namespace ts {
return true;
}
}
export function getOriginalNode(node: Node): Node;
export function getOriginalNode<T extends Node>(node: Node, nodeTest: (node: Node) => node is T): T;
export function getOriginalNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
if (node) {
while (node.original !== undefined) {
node = node.original;
}
}
return !nodeTest || nodeTest(node) ? node : undefined;
}
/**
* Gets a value indicating whether a node originated in the parse tree.
*
* @param node The node to test.
*/
export function isParseTreeNode(node: Node): boolean {
return (node.flags & NodeFlags.Synthesized) === 0;
}
/**
* Gets the original parse tree node for a node.
*
* @param node The original node.
* @returns The original parse tree node if found; otherwise, undefined.
*/
export function getParseTreeNode(node: Node): Node;
/**
* Gets the original parse tree node for a node.
*
* @param node The original node.
* @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, nodeTest?: (node: Node) => node is T): T;
export function getParseTreeNode(node: Node, nodeTest?: (node: Node) => boolean): Node {
if (isParseTreeNode(node)) {
return node;
}
node = getOriginalNode(node);
if (isParseTreeNode(node) && (!nodeTest || nodeTest(node))) {
return node;
}
return undefined;
}
}
+147 -166
View File
@@ -6,97 +6,6 @@
namespace ts {
export type VisitResult<T extends Node> = T | T[];
/**
* Describes an edge of a Node, used when traversing a syntax tree.
*/
interface NodeEdge {
/** The property name for the edge. */
name: string;
/** Indicates that the result is optional. */
optional?: boolean;
/** A callback used to test whether a node is valid. */
test?: (node: Node) => node is Node;
/** A callback used to lift a NodeArrayNode into a valid node. */
lift?: (nodes: NodeArray<Node>) => Node;
/** A callback used to parenthesize a node to preserve the intended order of operations. */
parenthesize?: (value: Node, parentNode: Node) => Node;
};
/**
* Describes the shape of a Node.
*/
type NodeTraversalPath = NodeEdge[];
/**
* This map contains information about the shape of each Node in "types.ts" pertaining to how
* each node should be traversed during a transformation.
*
* Each edge corresponds to a property in a Node subtype that should be traversed when visiting
* each child. The properties are assigned in the order in which traversal should occur.
*
* We only add entries for nodes that do not have a create/update pair defined in factory.ts
*
* NOTE: This needs to be kept up to date with changes to nodes in "types.ts". Currently, this
* map is not comprehensive. Only node edges relevant to tree transformation are
* currently defined. We may extend this to be more comprehensive, and eventually
* supplant the existing `forEachChild` implementation if performance is not
* significantly impacted.
*/
function getNodeEdgeTraversal(kind: SyntaxKind): NodeTraversalPath {
switch (kind) {
case SyntaxKind.QualifiedName: return [
{ name: "left", test: isEntityName },
{ name: "right", test: isIdentifier }
];
case SyntaxKind.Decorator: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.TypeAssertionExpression: return [
{ name: "type", test: isTypeNode },
{ name: "expression", test: isUnaryExpression }
];
case SyntaxKind.AsExpression: return [
{ name: "expression", test: isExpression },
{ name: "type", test: isTypeNode }
];
case SyntaxKind.NonNullExpression: return [
{ name: "expression", test: isLeftHandSideExpression }
];
case SyntaxKind.EnumDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "members", test: isEnumMember }
];
case SyntaxKind.ModuleDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isModuleName },
{ name: "body", test: isModuleBody }
];
case SyntaxKind.ModuleBlock: return [
{ name: "statements", test: isStatement }
];
case SyntaxKind.ImportEqualsDeclaration: return [
{ name: "decorators", test: isDecorator },
{ name: "modifiers", test: isModifier },
{ name: "name", test: isIdentifier },
{ name: "moduleReference", test: isModuleReference }
];
case SyntaxKind.ExternalModuleReference: return [
{ name: "expression", test: isExpression, optional: true }
];
case SyntaxKind.EnumMember: return [
{ name: "name", test: isPropertyName },
{ name: "initializer", test: isExpression, optional: true, parenthesize: parenthesizeExpressionForList }
];
}
}
function reduceNode<T>(node: Node, f: (memo: T, node: Node) => T, initial: T) {
return node ? f(initial, node) : initial;
}
@@ -107,8 +16,7 @@ namespace ts {
/**
* Similar to `reduceLeft`, performs a reduction against each child of a node.
* NOTE: Unlike `forEachChild`, this does *not* visit every node. Only nodes added to the
* `nodeEdgeTraversalMap` above will be visited.
* 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.
@@ -145,6 +53,11 @@ namespace ts {
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;
@@ -252,6 +165,11 @@ namespace ts {
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);
@@ -314,6 +232,15 @@ namespace ts {
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;
case SyntaxKind.NonNullExpression:
result = reduceNode((<NonNullExpression>node).expression, cbNode, result);
break;
// Misc
case SyntaxKind.TemplateSpan:
result = reduceNode((<TemplateSpan>node).expression, cbNode, result);
@@ -415,10 +342,35 @@ namespace ts {
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);
@@ -459,6 +411,11 @@ namespace ts {
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);
@@ -519,30 +476,25 @@ namespace ts {
break;
case SyntaxKind.SpreadAssignment:
result = reduceNode((node as SpreadAssignment).expression, cbNode, result);
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);
// 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;
default:
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = (<MapLike<any>>node)[edge.name];
if (value !== undefined) {
result = isArray(value)
? reduceNodes(<NodeArray<Node>>value, cbNodes, result)
: cbNode(result, <Node>value);
}
}
}
break;
}
@@ -556,11 +508,9 @@ namespace ts {
* @param visitor The callback used to visit the Node.
* @param test A callback to execute to verify the Node is valid.
* @param optional An optional value indicating whether the Node is itself optional.
* @param lift An optional callback to execute to lift a NodeArrayNode into a valid Node.
* @param lift An optional callback to execute to lift a NodeArray into a valid Node.
*/
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T;
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional: boolean, lift: (node: NodeArray<Node>) => T, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): T;
export function visitNode(node: Node, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: Node[]) => Node, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): Node {
export function visitNode<T extends Node>(node: T, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, optional?: boolean, lift?: (node: NodeArray<Node>) => T): T {
if (node === undefined || visitor === undefined) {
return node;
}
@@ -586,13 +536,9 @@ namespace ts {
visitedNode = visited;
}
if (parenthesize !== undefined) {
visitedNode = parenthesize(visitedNode, parentNode);
}
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
return visitedNode;
return <T>visitedNode;
}
/**
@@ -604,14 +550,12 @@ namespace ts {
* @param start An optional value indicating the starting offset at which to start visiting.
* @param count An optional value indicating the maximum number of nodes to visit.
*/
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number): NodeArray<T>;
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start: number, count: number, parenthesize: (node: Node, parentNode: Node) => Node, parentNode: Node): NodeArray<T>;
export function visitNodes(nodes: NodeArray<Node>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number, parenthesize?: (node: Node, parentNode: Node) => Node, parentNode?: Node): NodeArray<Node> {
export function visitNodes<T extends Node>(nodes: NodeArray<T>, visitor: (node: Node) => VisitResult<Node>, test: (node: Node) => boolean, start?: number, count?: number): NodeArray<T> {
if (nodes === undefined) {
return undefined;
}
let updated: NodeArray<Node>;
let updated: NodeArray<T>;
// Ensure start and count have valid values
const length = nodes.length;
@@ -627,8 +571,7 @@ namespace ts {
// If we are not visiting all of the original nodes, we must always create a new array.
// Since this is a fragment of a node array, we do not copy over the previous location
// and will only copy over `hasTrailingComma` if we are including the last element.
updated = createNodeArray<Node>([], /*location*/ undefined,
/*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
updated = createNodeArray<T>([], /*hasTrailingComma*/ nodes.hasTrailingComma && start + count === length);
}
// Visit each original node.
@@ -639,26 +582,21 @@ namespace ts {
if (updated !== undefined || visited === undefined || visited !== node) {
if (updated === undefined) {
// Ensure we have a copy of `nodes`, up to the current index.
updated = createNodeArray(nodes.slice(0, i), /*location*/ nodes, nodes.hasTrailingComma);
updated = createNodeArray(nodes.slice(0, i), nodes.hasTrailingComma);
setTextRange(updated, nodes);
}
if (visited) {
if (isArray(visited)) {
for (let visitedNode of visited) {
visitedNode = parenthesize
? parenthesize(visitedNode, parentNode)
: visitedNode;
for (const visitedNode of visited) {
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
updated.push(visitedNode);
updated.push(<T>visitedNode);
}
}
else {
const visitedNode = parenthesize
? parenthesize(visited, parentNode)
: visited;
Debug.assertNode(visitedNode, test);
aggregateTransformFlags(visitedNode);
updated.push(visitedNode);
Debug.assertNode(visited, test);
aggregateTransformFlags(visited);
updated.push(<T>visited);
}
}
}
@@ -675,10 +613,10 @@ namespace ts {
context.startLexicalEnvironment();
statements = visitNodes(statements, visitor, isStatement, start);
if (ensureUseStrict && !startsWithUseStrict(statements)) {
statements = createNodeArray([createStatement(createLiteral("use strict")), ...statements], statements);
statements = setTextRange(createNodeArray([createStatement(createLiteral("use strict")), ...statements]), statements);
}
const declarations = context.endLexicalEnvironment();
return createNodeArray(concatenate(statements, declarations), statements);
return setTextRange(createNodeArray(concatenate(statements, declarations)), statements);
}
/**
@@ -747,6 +685,11 @@ namespace ts {
return node;
// Names
case SyntaxKind.QualifiedName:
return updateQualifiedName(<QualifiedName>node,
visitNode((<QualifiedName>node).left, visitor, isEntityName),
visitNode((<QualifiedName>node).right, visitor, isIdentifier));
case SyntaxKind.ComputedPropertyName:
return updateComputedPropertyName(<ComputedPropertyName>node,
visitNode((<ComputedPropertyName>node).expression, visitor, isExpression));
@@ -761,6 +704,10 @@ namespace ts {
visitNode((<ParameterDeclaration>node).type, visitor, isTypeNode, /*optional*/ true),
visitNode((<ParameterDeclaration>node).initializer, visitor, isExpression, /*optional*/ true));
case SyntaxKind.Decorator:
return updateDecorator(<Decorator>node,
visitNode((<Decorator>node).expression, visitor, isExpression));
// Type member
case SyntaxKind.PropertyDeclaration:
return updateProperty(<PropertyDeclaration>node,
@@ -856,6 +803,11 @@ namespace ts {
visitNode((<TaggedTemplateExpression>node).tag, visitor, isExpression),
visitNode((<TaggedTemplateExpression>node).template, visitor, isTemplateLiteral));
case SyntaxKind.TypeAssertionExpression:
return updateTypeAssertion(<TypeAssertion>node,
visitNode((<TypeAssertion>node).type, visitor, isTypeNode),
visitNode((<TypeAssertion>node).expression, visitor, isExpression));
case SyntaxKind.ParenthesizedExpression:
return updateParen(<ParenthesizedExpression>node,
visitNode((<ParenthesizedExpression>node).expression, visitor, isExpression));
@@ -938,6 +890,15 @@ namespace ts {
visitNodes((<ExpressionWithTypeArguments>node).typeArguments, visitor, isTypeNode),
visitNode((<ExpressionWithTypeArguments>node).expression, visitor, isExpression));
case SyntaxKind.AsExpression:
return updateAsExpression(<AsExpression>node,
visitNode((<AsExpression>node).expression, visitor, isExpression),
visitNode((<AsExpression>node).type, visitor, isTypeNode));
case SyntaxKind.NonNullExpression:
return updateNonNullExpression(<NonNullExpression>node,
visitNode((<NonNullExpression>node).expression, visitor, isExpression));
// Misc
case SyntaxKind.TemplateSpan:
return updateTemplateSpan(<TemplateSpan>node,
@@ -1059,10 +1020,35 @@ namespace ts {
visitNodes((<ClassDeclaration>node).heritageClauses, visitor, isHeritageClause),
visitNodes((<ClassDeclaration>node).members, visitor, isClassElement));
case SyntaxKind.EnumDeclaration:
return updateEnumDeclaration(<EnumDeclaration>node,
visitNodes((<EnumDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<EnumDeclaration>node).modifiers, visitor, isModifier),
visitNode((<EnumDeclaration>node).name, visitor, isIdentifier),
visitNodes((<EnumDeclaration>node).members, visitor, isEnumMember));
case SyntaxKind.ModuleDeclaration:
return updateModuleDeclaration(<ModuleDeclaration>node,
visitNodes((<ModuleDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ModuleDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ModuleDeclaration>node).name, visitor, isIdentifier),
visitNode((<ModuleDeclaration>node).body, visitor, isModuleBody));
case SyntaxKind.ModuleBlock:
return updateModuleBlock(<ModuleBlock>node,
visitNodes((<ModuleBlock>node).statements, visitor, isStatement));
case SyntaxKind.CaseBlock:
return updateCaseBlock(<CaseBlock>node,
visitNodes((<CaseBlock>node).clauses, visitor, isCaseOrDefaultClause));
case SyntaxKind.ImportEqualsDeclaration:
return updateImportEqualsDeclaration(<ImportEqualsDeclaration>node,
visitNodes((<ImportEqualsDeclaration>node).decorators, visitor, isDecorator),
visitNodes((<ImportEqualsDeclaration>node).modifiers, visitor, isModifier),
visitNode((<ImportEqualsDeclaration>node).name, visitor, isIdentifier),
visitNode((<ImportEqualsDeclaration>node).moduleReference, visitor, isModuleReference));
case SyntaxKind.ImportDeclaration:
return updateImportDeclaration(<ImportDeclaration>node,
visitNodes((<ImportDeclaration>node).decorators, visitor, isDecorator),
@@ -1110,6 +1096,11 @@ namespace ts {
visitNode((<ExportSpecifier>node).propertyName, visitor, isIdentifier, /*optional*/ true),
visitNode((<ExportSpecifier>node).name, visitor, isIdentifier));
// Module references
case SyntaxKind.ExternalModuleReference:
return updateExternalModuleReference(<ExternalModuleReference>node,
visitNode((<ExternalModuleReference>node).expression, visitor, isExpression));
// JSX
case SyntaxKind.JsxElement:
return updateJsxElement(<JsxElement>node,
@@ -1175,10 +1166,16 @@ namespace ts {
visitNode((<ShorthandPropertyAssignment>node).objectAssignmentInitializer, visitor, isExpression));
case SyntaxKind.SpreadAssignment:
return updateSpreadAssignment(node as SpreadAssignment,
visitNode((node as SpreadAssignment).expression, visitor, isExpression));
return updateSpreadAssignment(<SpreadAssignment>node,
visitNode((<SpreadAssignment>node).expression, visitor, isExpression));
// Top-level nodes
// Enum
case SyntaxKind.EnumMember:
return updateEnumMember(<EnumMember>node,
visitNode((<EnumMember>node).name, visitor, isPropertyName),
visitNode((<EnumMember>node).initializer, visitor, isExpression, /*optional*/ true));
// Top-level nodes
case SyntaxKind.SourceFile:
return updateSourceFileNode(<SourceFile>node,
visitLexicalEnvironment((<SourceFile>node).statements, visitor, context));
@@ -1189,30 +1186,8 @@ namespace ts {
visitNode((<PartiallyEmittedExpression>node).expression, visitor, isExpression));
default:
let updated: Node & MapLike<any>;
const edgeTraversalPath = getNodeEdgeTraversal(kind);
if (edgeTraversalPath) {
for (const edge of edgeTraversalPath) {
const value = <Node | NodeArray<Node>>(<Node & MapLike<any>>node)[edge.name];
if (value !== undefined) {
const visited = isArray(value)
? visitNodes(value, visitor, edge.test, 0, value.length, edge.parenthesize, node)
: visitNode(value, visitor, edge.test, edge.optional, edge.lift, edge.parenthesize, node);
if (updated !== undefined || visited !== value) {
if (updated === undefined) {
updated = getMutableClone(node);
}
if (visited !== value) {
updated[edge.name] = visited;
}
}
}
}
}
return updated ? updateNode(updated, node) : node;
return node;
}
// return node;
}
/**
@@ -1228,7 +1203,7 @@ namespace ts {
return statements;
}
return isNodeArray(statements)
? createNodeArray(concatenate(statements, declarations), statements)
? setTextRange(createNodeArray(concatenate(statements, declarations)), statements)
: addRange(statements, declarations);
}
@@ -1252,13 +1227,19 @@ namespace ts {
export function mergeFunctionBodyLexicalEnvironment(body: ConciseBody, declarations: Statement[]): ConciseBody {
if (body && declarations !== undefined && declarations.length > 0) {
if (isBlock(body)) {
return updateBlock(body, createNodeArray(concatenate(body.statements, declarations), body.statements));
return updateBlock(body, setTextRange(createNodeArray(concatenate(body.statements, declarations)), body.statements));
}
else {
return createBlock(
createNodeArray([createReturn(body, /*location*/ body), ...declarations], body),
/*location*/ body,
/*multiLine*/ true);
return setTextRange(
createBlock(
setTextRange(
createNodeArray([setTextRange(createReturn(body), body), ...declarations]),
body
),
/*multiLine*/ true
),
/*location*/ body
);
}
}
return body;
+2 -1
View File
@@ -118,6 +118,7 @@
"./unittests/initializeTSConfig.ts",
"./unittests/compileOnSave.ts",
"./unittests/typingsInstaller.ts",
"./unittests/projectErrors.ts"
"./unittests/projectErrors.ts",
"./unittests/printer.ts"
]
}
+97
View File
@@ -0,0 +1,97 @@
/// <reference path="..\..\compiler\emitter.ts" />
/// <reference path="..\harness.ts" />
namespace ts {
describe("PrinterAPI", () => {
function makePrintsCorrectly(prefix: string) {
return function printsCorrectly(name: string, options: PrinterOptions, printCallback: (printer: Printer) => string) {
it(name, () => {
Harness.Baseline.runBaseline(`printerApi/${prefix}.${name}.js`, () =>
printCallback(createPrinter({ newLine: NewLineKind.CarriageReturnLineFeed, ...options })));
});
}
}
describe("printFile", () => {
const printsCorrectly = makePrintsCorrectly("printsFileCorrectly");
const sourceFile = createSourceFile("source.ts", `
interface A<T> {
// comment1
readonly prop?: T;
// comment2
method(): void;
// comment3
new <T>(): A<T>;
// comment4
<T>(): A<T>;
}
// comment5
type B = number | string | object;
type C = A<number> & { x: string; }; // comment6
// comment7
enum E1 {
// comment8
first
}
const enum E2 {
second
}
// comment9
console.log(1 + 2);
`, ScriptTarget.ES2015);
printsCorrectly("default", {}, printer => printer.printFile(sourceFile));
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printFile(sourceFile));
});
describe("printBundle", () => {
const printsCorrectly = makePrintsCorrectly("printsBundleCorrectly");
const bundle = createBundle([
createSourceFile("a.ts", `
/*! [a.ts] */
// comment0
const a = 1;
`, ScriptTarget.ES2015),
createSourceFile("b.ts", `
/*! [b.ts] */
// comment1
const b = 2;
`, ScriptTarget.ES2015)
]);
printsCorrectly("default", {}, printer => printer.printBundle(bundle));
printsCorrectly("removeComments", { removeComments: true }, printer => printer.printBundle(bundle));
});
describe("printNode", () => {
const printsCorrectly = makePrintsCorrectly("printsNodeCorrectly");
const sourceFile = createSourceFile("source.ts", "", ScriptTarget.ES2015);
const syntheticNode = createClassDeclaration(
undefined,
undefined,
/*name*/ createIdentifier("C"),
undefined,
undefined,
createNodeArray([
createProperty(
undefined,
createNodeArray([createToken(SyntaxKind.PublicKeyword)]),
createIdentifier("prop"),
undefined,
undefined,
undefined
)
])
);
printsCorrectly("class", {}, printer => printer.printNode(EmitHint.Unspecified, syntheticNode, sourceFile));
});
});
}
+10 -8
View File
@@ -44,6 +44,8 @@ namespace ts.projectSystem {
});
}
import typingsName = server.typingsInstaller.typingsName;
describe("typingsInstaller", () => {
it("configured projects (typings installed) 1", () => {
const file1 = {
@@ -519,32 +521,32 @@ namespace ts.projectSystem {
const commander = {
path: "/a/data/node_modules/@types/commander/index.d.ts",
content: "declare const commander: { x: number }",
typings: "@types/commander"
typings: typingsName("commander")
};
const jquery = {
path: "/a/data/node_modules/@types/jquery/index.d.ts",
content: "declare const jquery: { x: number }",
typings: "@types/jquery"
typings: typingsName("jquery")
};
const lodash = {
path: "/a/data/node_modules/@types/lodash/index.d.ts",
content: "declare const lodash: { x: number }",
typings: "@types/lodash"
typings: typingsName("lodash")
};
const cordova = {
path: "/a/data/node_modules/@types/cordova/index.d.ts",
content: "declare const cordova: { x: number }",
typings: "@types/cordova"
typings: typingsName("cordova")
};
const grunt = {
path: "/a/data/node_modules/@types/grunt/index.d.ts",
content: "declare const grunt: { x: number }",
typings: "@types/grunt"
typings: typingsName("grunt")
};
const gulp = {
path: "/a/data/node_modules/@types/gulp/index.d.ts",
content: "declare const gulp: { x: number }",
typings: "@types/gulp"
typings: typingsName("gulp")
};
const host = createServerHost([lodashJs, commanderJs, file3]);
@@ -554,7 +556,7 @@ namespace ts.projectSystem {
}
installWorker(_requestId: number, args: string[], _cwd: string, cb: TI.RequestCompletedAction): void {
let typingFiles: (FileOrFolder & { typings: string })[] = [];
if (args.indexOf("@types/commander") >= 0) {
if (args.indexOf(typingsName("commander")) >= 0) {
typingFiles = [commander, jquery, lodash, cordova];
}
else {
@@ -982,7 +984,7 @@ namespace ts.projectSystem {
return;
}
if (response.kind === server.EventEndInstallTypes) {
assert.deepEqual(response.packagesToInstall, ["@types/commander"]);
assert.deepEqual(response.packagesToInstall, [typingsName("commander")]);
seenTelemetryEvent = true;
return;
}
+1564 -365
View File
File diff suppressed because it is too large Load Diff
+636 -161
View File
File diff suppressed because it is too large Load Diff
@@ -295,8 +295,7 @@ namespace ts.server.typingsInstaller {
this.log.writeLine(`Installing typings ${JSON.stringify(typingsToInstall)}`);
}
const filteredTypings = this.filterTypings(typingsToInstall);
const scopedTypings = filteredTypings.map(x => `@types/${x}`);
if (scopedTypings.length === 0) {
if (filteredTypings.length === 0) {
if (this.log.isEnabled()) {
this.log.writeLine(`All typings are known to be missing or invalid - no need to go any further`);
}
@@ -316,6 +315,7 @@ namespace ts.server.typingsInstaller {
projectName: req.projectName
});
const scopedTypings = filteredTypings.map(typingsName);
this.installTypingsAsync(requestId, scopedTypings, cachePath, ok => {
try {
if (!ok) {
@@ -429,4 +429,10 @@ namespace ts.server.typingsInstaller {
protected abstract installWorker(requestId: number, args: string[], cwd: string, onRequestCompleted: RequestCompletedAction): void;
protected abstract sendResponse(response: SetTypings | InvalidateCachedTypings | BeginInstallTypes | EndInstallTypes): void;
}
/* @internal */
export function typingsName(packageName: string): string {
return `@types/${packageName}@ts${versionMajorMinor}`;
}
const versionMajorMinor = version.split(".").slice(0, 2).join(".");
}
+13 -19
View File
@@ -115,6 +115,7 @@ namespace ts.codefix {
registerCodeFix({
errorCodes: [
Diagnostics.Cannot_find_name_0.code,
Diagnostics.Cannot_find_namespace_0.code,
Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead.code
],
getCodeActions: (context: CodeFixContext) => {
@@ -416,8 +417,8 @@ namespace ts.codefix {
);
function getModuleSpecifierForNewImport() {
const fileName = sourceFile.path;
const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().path;
const fileName = sourceFile.fileName;
const moduleFileName = moduleSymbol.valueDeclaration.getSourceFile().fileName;
const sourceDirectory = getDirectoryPath(fileName);
const options = context.program.getCompilerOptions();
@@ -439,8 +440,7 @@ namespace ts.codefix {
return undefined;
}
const normalizedBaseUrl = toPath(options.baseUrl, getDirectoryPath(options.baseUrl), getCanonicalFileName);
let relativeName = tryRemoveParentDirectoryName(moduleFileName, normalizedBaseUrl);
let relativeName = getRelativePathIfInDirectory(moduleFileName, options.baseUrl);
if (!relativeName) {
return undefined;
}
@@ -477,9 +477,8 @@ namespace ts.codefix {
function tryGetModuleNameFromRootDirs() {
if (options.rootDirs) {
const normalizedRootDirs = map(options.rootDirs, rootDir => toPath(rootDir, /*basePath*/ undefined, getCanonicalFileName));
const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, normalizedRootDirs);
const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, normalizedRootDirs);
const normalizedTargetPath = getPathRelativeToRootDirs(moduleFileName, options.rootDirs);
const normalizedSourcePath = getPathRelativeToRootDirs(sourceDirectory, options.rootDirs);
if (normalizedTargetPath !== undefined) {
const relativePath = normalizedSourcePath !== undefined ? getRelativePath(normalizedTargetPath, normalizedSourcePath) : normalizedTargetPath;
return removeFileExtension(relativePath);
@@ -546,9 +545,9 @@ namespace ts.codefix {
}
}
function getPathRelativeToRootDirs(path: Path, rootDirs: Path[]) {
function getPathRelativeToRootDirs(path: string, rootDirs: string[]) {
for (const rootDir of rootDirs) {
const relativeName = tryRemoveParentDirectoryName(path, rootDir);
const relativeName = getRelativePathIfInDirectory(path, rootDir);
if (relativeName !== undefined) {
return relativeName;
}
@@ -564,20 +563,15 @@ namespace ts.codefix {
return fileName;
}
function getRelativePathIfInDirectory(path: string, directoryPath: string) {
const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false);
return isRootedDiskPath(relativePath) || startsWith(relativePath, "..") ? undefined : relativePath;
}
function getRelativePath(path: string, directoryPath: string) {
const relativePath = getRelativePathToDirectoryOrUrl(directoryPath, path, directoryPath, getCanonicalFileName, false);
return moduleHasNonRelativeName(relativePath) ? "./" + relativePath : relativePath;
}
function tryRemoveParentDirectoryName(path: Path, parentDirectory: Path) {
const index = path.indexOf(parentDirectory);
if (index === 0) {
return endsWith(parentDirectory, directorySeparator)
? path.substring(parentDirectory.length)
: path.substring(parentDirectory.length + 1);
}
return undefined;
}
}
}
+32 -16
View File
@@ -25,7 +25,7 @@ namespace ts.codefix {
const forStatement = <ForStatement>token.parent.parent.parent;
const forInitializer = <VariableDeclarationList>forStatement.initializer;
if (forInitializer.declarations.length === 1) {
return createCodeFix("", forInitializer.pos, forInitializer.end - forInitializer.pos);
return createCodeFixToRemoveNode(forInitializer);
}
else {
return removeSingleItem(forInitializer.declarations, token);
@@ -35,7 +35,7 @@ namespace ts.codefix {
const forOfStatement = <ForOfStatement>token.parent.parent.parent;
if (forOfStatement.initializer.kind === SyntaxKind.VariableDeclarationList) {
const forOfInitializer = <VariableDeclarationList>forOfStatement.initializer;
return createCodeFix("{}", forOfInitializer.declarations[0].pos, forOfInitializer.declarations[0].end - forOfInitializer.declarations[0].pos);
return createCodeFix("{}", forOfInitializer.declarations[0].getStart(), forOfInitializer.declarations[0].getWidth());
}
break;
@@ -47,12 +47,12 @@ namespace ts.codefix {
case SyntaxKind.CatchClause:
const catchClause = <CatchClause>token.parent.parent;
const parameter = catchClause.variableDeclaration.getChildren()[0];
return createCodeFix("", parameter.pos, parameter.end - parameter.pos);
return createCodeFixToRemoveNode(parameter);
default:
const variableStatement = <VariableStatement>token.parent.parent.parent;
if (variableStatement.declarationList.declarations.length === 1) {
return createCodeFix("", variableStatement.pos, variableStatement.end - variableStatement.pos);
return createCodeFixToRemoveNode(variableStatement);
}
else {
const declarations = variableStatement.declarationList.declarations;
@@ -72,7 +72,7 @@ namespace ts.codefix {
case ts.SyntaxKind.Parameter:
const functionDeclaration = <FunctionDeclaration>token.parent.parent;
if (functionDeclaration.parameters.length === 1) {
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
return createCodeFixToRemoveNode(token.parent);
}
else {
return removeSingleItem(functionDeclaration.parameters, token);
@@ -81,14 +81,14 @@ namespace ts.codefix {
// handle case where 'import a = A;'
case SyntaxKind.ImportEqualsDeclaration:
const importEquals = findImportDeclaration(token);
return createCodeFix("", importEquals.pos, importEquals.end - importEquals.pos);
return createCodeFixToRemoveNode(importEquals);
case SyntaxKind.ImportSpecifier:
const namedImports = <NamedImports>token.parent.parent;
if (namedImports.elements.length === 1) {
// Only 1 import and it is unused. So the entire declaration should be removed.
const importSpec = findImportDeclaration(token);
return createCodeFix("", importSpec.pos, importSpec.end - importSpec.pos);
return createCodeFixToRemoveNode(importSpec);
}
else {
return removeSingleItem(namedImports.elements, token);
@@ -100,17 +100,24 @@ namespace ts.codefix {
const importClause = <ImportClause>token.parent;
if (!importClause.namedBindings) { // |import d from './file'| or |import * as ns from './file'|
const importDecl = findImportDeclaration(importClause);
return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos);
return createCodeFixToRemoveNode(importDecl);
}
else { // import |d,| * as ns from './file'
return createCodeFix("", importClause.name.pos, importClause.namedBindings.pos - importClause.name.pos);
else {
// import |d,| * as ns from './file'
const start = importClause.name.getStart();
let end = findFirstNonSpaceCharPosStarting(importClause.name.end);
if (sourceFile.text.charCodeAt(end) === CharacterCodes.comma) {
end = findFirstNonSpaceCharPosStarting(end + 1);
}
return createCodeFix("", start, end - start);
}
case SyntaxKind.NamespaceImport:
const namespaceImport = <NamespaceImport>token.parent;
if (namespaceImport.name == token && !(<ImportClause>namespaceImport.parent).name) {
const importDecl = findImportDeclaration(namespaceImport);
return createCodeFix("", importDecl.pos, importDecl.end - importDecl.pos);
return createCodeFixToRemoveNode(importDecl);
}
else {
const start = (<ImportClause>namespaceImport.parent).name.end;
@@ -120,16 +127,14 @@ namespace ts.codefix {
break;
case SyntaxKind.PropertyDeclaration:
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
case SyntaxKind.NamespaceImport:
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
return createCodeFixToRemoveNode(token.parent);
}
if (isDeclarationName(token)) {
return createCodeFix("", token.parent.pos, token.parent.end - token.parent.pos);
return createCodeFixToRemoveNode(token.parent);
}
else if (isLiteralComputedPropertyDeclarationName(token)) {
return createCodeFix("", token.parent.parent.pos, token.parent.parent.end - token.parent.parent.pos);
return createCodeFixToRemoveNode(token.parent.parent);
}
else {
return undefined;
@@ -144,6 +149,17 @@ namespace ts.codefix {
return importDecl;
}
function createCodeFixToRemoveNode(node: Node) {
return createCodeFix("", node.getStart(), node.getWidth());
}
function findFirstNonSpaceCharPosStarting(start: number) {
while (isWhiteSpace(sourceFile.text.charCodeAt(start))) {
start += 1;
}
return start;
}
function createCodeFix(newText: string, start: number, length: number): CodeAction[] {
return [{
description: formatStringFromArgs(getLocaleSpecificMessage(Diagnostics.Remove_declaration_for_Colon_0), { 0: token.getText() }),
+25 -3
View File
@@ -173,6 +173,18 @@ namespace ts.Completions {
// var y = require("/*completion position*/");
return getStringLiteralCompletionEntriesFromModuleNames(<StringLiteral>node, compilerOptions, host, typeChecker);
}
else if (isEqualityExpression(node.parent)) {
// Get completions from the type of the other operand
// i.e. switch (a) {
// case '/*completion position*/'
// }
return getStringLiteralCompletionEntriesFromType(typeChecker.getTypeAtLocation(node.parent.left === node ? node.parent.right : node.parent.left), typeChecker);
}
else if (isCaseOrDefaultClause(node.parent)) {
// Get completions from the type of the switch expression
// i.e. x === '/*completion position'
return getStringLiteralCompletionEntriesFromType(typeChecker.getTypeAtLocation((<SwitchStatement>node.parent.parent.parent).expression), typeChecker);
}
else {
const argumentInfo = SignatureHelp.getImmediatelyContainingArgumentInfo(node, position, sourceFile);
if (argumentInfo) {
@@ -184,7 +196,7 @@ namespace ts.Completions {
// Get completion for string literal from string literal type
// i.e. var x: "hi" | "hello" = "/*completion position*/"
return getStringLiteralCompletionEntriesFromContextualType(<StringLiteral>node, typeChecker);
return getStringLiteralCompletionEntriesFromType(typeChecker.getContextualType(<StringLiteral>node), typeChecker);
}
}
@@ -228,8 +240,7 @@ namespace ts.Completions {
return undefined;
}
function getStringLiteralCompletionEntriesFromContextualType(node: StringLiteral, typeChecker: TypeChecker): CompletionInfo | undefined {
const type = typeChecker.getContextualType(node);
function getStringLiteralCompletionEntriesFromType(type: Type, typeChecker: TypeChecker): CompletionInfo | undefined {
if (type) {
const entries: CompletionEntry[] = [];
addStringLiteralCompletionsFromType(type, entries, typeChecker);
@@ -1756,4 +1767,15 @@ namespace ts.Completions {
catch (e) {}
return undefined;
}
function isEqualityExpression(node: Node): node is BinaryExpression {
return isBinaryExpression(node) && isEqualityOperatorKind(node.operatorToken.kind);
}
function isEqualityOperatorKind(kind: SyntaxKind) {
return kind == SyntaxKind.EqualsEqualsToken ||
kind === SyntaxKind.ExclamationEqualsToken ||
kind === SyntaxKind.EqualsEqualsEqualsToken ||
kind === SyntaxKind.ExclamationEqualsEqualsToken;
}
}
+29
View File
@@ -0,0 +1,29 @@
/// <reference path="..\compiler\transformer.ts"/>
/// <reference path="transpile.ts"/>
namespace ts {
/**
* Transform one or more source files using the supplied transformers.
* @param source A `SourceFile` or an array of `SourceFiles`.
* @param transformers An array of `Transformer` callbacks used to process the transformation.
*/
export function transform(source: SourceFile | SourceFile[], transformers: Transformer[]) {
const diagnostics: Diagnostic[] = [];
const compilerOptions: CompilerOptions = {};
const sourceFiles = isArray(source) ? source : [source];
const fileMap = arrayToMap(sourceFiles, sourceFile => sourceFile.fileName);
const emitHost: EmitHost = {
getCompilerOptions: () => compilerOptions,
getCanonicalFileName: fileName => fileName,
getCommonSourceDirectory: () => "",
getCurrentDirectory: () => "",
getNewLine: () => "\n",
getSourceFile: fileName => fileMap.get(fileName),
getSourceFileByPath: fileName => fileMap.get(fileName),
getSourceFiles: () => sourceFiles,
isSourceFileFromExternalLibrary: () => false,
isEmitBlocked: () => false,
writeFile: () => Debug.fail("'writeFile()' is not supported during transformation.")
};
return transformFiles(/*resolver*/ undefined, emitHost, sourceFiles, transformers);
}
}
@@ -0,0 +1,27 @@
tests/cases/compiler/forwardRefInClassProperties.ts(3,15): error TS2448: Block-scoped variable '_a' used before its declaration.
tests/cases/compiler/forwardRefInClassProperties.ts(6,22): error TS2448: Block-scoped variable '_A' used before its declaration.
tests/cases/compiler/forwardRefInClassProperties.ts(11,17): error TS2448: Block-scoped variable 'b' used before its declaration.
==== tests/cases/compiler/forwardRefInClassProperties.ts (3 errors) ====
class Test
{
_b = this._a; // undefined, no error/warning
~~
!!! error TS2448: Block-scoped variable '_a' used before its declaration.
_a = 3;
static _B = Test._A; // undefined, no error/warning
~~
!!! error TS2448: Block-scoped variable '_A' used before its declaration.
static _A = 3;
method()
{
let a = b; // Block-scoped variable 'b' used before its declaration
~
!!! error TS2448: Block-scoped variable 'b' used before its declaration.
let b = 3;
}
}
@@ -0,0 +1,31 @@
//// [forwardRefInClassProperties.ts]
class Test
{
_b = this._a; // undefined, no error/warning
_a = 3;
static _B = Test._A; // undefined, no error/warning
static _A = 3;
method()
{
let a = b; // Block-scoped variable 'b' used before its declaration
let b = 3;
}
}
//// [forwardRefInClassProperties.js]
var Test = (function () {
function Test() {
this._b = this._a; // undefined, no error/warning
this._a = 3;
}
Test.prototype.method = function () {
var a = b; // Block-scoped variable 'b' used before its declaration
var b = 3;
};
return Test;
}());
Test._B = Test._A; // undefined, no error/warning
Test._A = 3;
@@ -526,6 +526,33 @@ class Form<T> {
this.childFormFactories[prop](value)
}
}
// Repro from #13787
class SampleClass<P> {
public props: Readonly<P>;
constructor(props: P) {
this.props = Object.freeze(props);
}
}
interface Foo {
foo: string;
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
constructor(props: T) {
const foo: Foo = { foo: "bar" };
super(merge(props, foo));
}
public brokenMethod() {
this.props.foo.concat;
}
}
new AnotherSampleClass({});
//// [keyofAndIndexedAccess.js]
@@ -881,6 +908,27 @@ var Form = (function () {
};
return Form;
}());
// Repro from #13787
var SampleClass = (function () {
function SampleClass(props) {
this.props = Object.freeze(props);
}
return SampleClass;
}());
var AnotherSampleClass = (function (_super) {
__extends(AnotherSampleClass, _super);
function AnotherSampleClass(props) {
var _this = this;
var foo = { foo: "bar" };
_this = _super.call(this, merge(props, foo)) || this;
return _this;
}
AnotherSampleClass.prototype.brokenMethod = function () {
this.props.foo.concat;
};
return AnotherSampleClass;
}(SampleClass));
new AnotherSampleClass({});
//// [keyofAndIndexedAccess.d.ts]
@@ -1127,3 +1175,15 @@ declare class Form<T> {
private childFormFactories;
set<K extends keyof T>(prop: K, value: T[K]): void;
}
declare class SampleClass<P> {
props: Readonly<P>;
constructor(props: P);
}
interface Foo {
foo: string;
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
declare class AnotherSampleClass<T> extends SampleClass<T & Foo> {
constructor(props: T);
brokenMethod(): void;
}
@@ -1880,3 +1880,86 @@ class Form<T> {
}
}
// Repro from #13787
class SampleClass<P> {
>SampleClass : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1))
>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18))
public props: Readonly<P>;
>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22))
>Readonly : Symbol(Readonly, Decl(lib.d.ts, --, --))
>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18))
constructor(props: P) {
>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 532, 16))
>P : Symbol(P, Decl(keyofAndIndexedAccess.ts, 530, 18))
this.props = Object.freeze(props);
>this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22))
>this : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1))
>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22))
>Object.freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>freeze : Symbol(ObjectConstructor.freeze, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 532, 16))
}
}
interface Foo {
>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1))
foo: string;
>foo : Symbol(Foo.foo, Decl(keyofAndIndexedAccess.ts, 537, 15))
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
>merge : Symbol(merge, Decl(keyofAndIndexedAccess.ts, 539, 1))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25))
>obj1 : Symbol(obj1, Decl(keyofAndIndexedAccess.ts, 541, 29))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23))
>obj2 : Symbol(obj2, Decl(keyofAndIndexedAccess.ts, 541, 37))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 541, 23))
>U : Symbol(U, Decl(keyofAndIndexedAccess.ts, 541, 25))
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25))
>SampleClass : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25))
>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1))
constructor(props: T) {
>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 544, 16))
>T : Symbol(T, Decl(keyofAndIndexedAccess.ts, 543, 25))
const foo: Foo = { foo: "bar" };
>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 13))
>Foo : Symbol(Foo, Decl(keyofAndIndexedAccess.ts, 535, 1))
>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 26))
super(merge(props, foo));
>super : Symbol(SampleClass, Decl(keyofAndIndexedAccess.ts, 526, 1))
>merge : Symbol(merge, Decl(keyofAndIndexedAccess.ts, 539, 1))
>props : Symbol(props, Decl(keyofAndIndexedAccess.ts, 544, 16))
>foo : Symbol(foo, Decl(keyofAndIndexedAccess.ts, 545, 13))
}
public brokenMethod() {
>brokenMethod : Symbol(AnotherSampleClass.brokenMethod, Decl(keyofAndIndexedAccess.ts, 547, 5))
this.props.foo.concat;
>this.props.foo.concat : Symbol(String.concat, Decl(lib.d.ts, --, --))
>this.props.foo : Symbol(foo)
>this.props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22))
>this : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54))
>props : Symbol(SampleClass.props, Decl(keyofAndIndexedAccess.ts, 530, 22))
>foo : Symbol(foo)
>concat : Symbol(String.concat, Decl(lib.d.ts, --, --))
}
}
new AnotherSampleClass({});
>AnotherSampleClass : Symbol(AnotherSampleClass, Decl(keyofAndIndexedAccess.ts, 541, 54))
@@ -2204,3 +2204,94 @@ class Form<T> {
}
}
// Repro from #13787
class SampleClass<P> {
>SampleClass : SampleClass<P>
>P : P
public props: Readonly<P>;
>props : Readonly<P>
>Readonly : Readonly<T>
>P : P
constructor(props: P) {
>props : P
>P : P
this.props = Object.freeze(props);
>this.props = Object.freeze(props) : Readonly<P>
>this.props : Readonly<P>
>this : this
>props : Readonly<P>
>Object.freeze(props) : Readonly<P>
>Object.freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>Object : ObjectConstructor
>freeze : { <T>(a: T[]): ReadonlyArray<T>; <T extends Function>(f: T): T; <T>(o: T): Readonly<T>; }
>props : P
}
}
interface Foo {
>Foo : Foo
foo: string;
>foo : string
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
>merge : <T, U>(obj1: T, obj2: U) => T & U
>T : T
>U : U
>obj1 : T
>T : T
>obj2 : U
>U : U
>T : T
>U : U
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
>AnotherSampleClass : AnotherSampleClass<T>
>T : T
>SampleClass : SampleClass<T & Foo>
>T : T
>Foo : Foo
constructor(props: T) {
>props : T
>T : T
const foo: Foo = { foo: "bar" };
>foo : Foo
>Foo : Foo
>{ foo: "bar" } : { foo: string; }
>foo : string
>"bar" : "bar"
super(merge(props, foo));
>super(merge(props, foo)) : void
>super : typeof SampleClass
>merge(props, foo) : T & Foo
>merge : <T, U>(obj1: T, obj2: U) => T & U
>props : T
>foo : Foo
}
public brokenMethod() {
>brokenMethod : () => void
this.props.foo.concat;
>this.props.foo.concat : (...strings: string[]) => string
>this.props.foo : (T & Foo)["foo"]
>this.props : Readonly<T & Foo>
>this : this
>props : Readonly<T & Foo>
>foo : (T & Foo)["foo"]
>concat : (...strings: string[]) => string
}
}
new AnotherSampleClass({});
>new AnotherSampleClass({}) : AnotherSampleClass<{}>
>AnotherSampleClass : typeof AnotherSampleClass
>{} : {}
@@ -55,6 +55,14 @@ class Thing3 extends Thing2 {
this.print();
}
}
// Repro from #13805
const Timestamped = <CT extends Constructor<object>>(Base: CT) => {
return class extends Base {
timestamp = new Date();
};
}
//// [mixinClassesAnonymous.js]
@@ -138,3 +146,15 @@ var Thing3 = (function (_super) {
};
return Thing3;
}(Thing2));
// Repro from #13805
var Timestamped = function (Base) {
return (function (_super) {
__extends(class_2, _super);
function class_2() {
var _this = _super !== null && _super.apply(this, arguments) || this;
_this.timestamp = new Date();
return _this;
}
return class_2;
}(Base));
};
@@ -167,3 +167,22 @@ class Thing3 extends Thing2 {
}
}
// Repro from #13805
const Timestamped = <CT extends Constructor<object>>(Base: CT) => {
>Timestamped : Symbol(Timestamped, Decl(mixinClassesAnonymous.ts, 59, 5))
>CT : Symbol(CT, Decl(mixinClassesAnonymous.ts, 59, 21))
>Constructor : Symbol(Constructor, Decl(mixinClassesAnonymous.ts, 0, 0))
>Base : Symbol(Base, Decl(mixinClassesAnonymous.ts, 59, 53))
>CT : Symbol(CT, Decl(mixinClassesAnonymous.ts, 59, 21))
return class extends Base {
>Base : Symbol(Base, Decl(mixinClassesAnonymous.ts, 59, 53))
timestamp = new Date();
>timestamp : Symbol((Anonymous class).timestamp, Decl(mixinClassesAnonymous.ts, 60, 31))
>Date : Symbol(Date, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
};
}
@@ -198,3 +198,25 @@ class Thing3 extends Thing2 {
}
}
// Repro from #13805
const Timestamped = <CT extends Constructor<object>>(Base: CT) => {
>Timestamped : <CT extends Constructor<object>>(Base: CT) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & CT
><CT extends Constructor<object>>(Base: CT) => { return class extends Base { timestamp = new Date(); };} : <CT extends Constructor<object>>(Base: CT) => { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & CT
>CT : CT
>Constructor : Constructor<T>
>Base : CT
>CT : CT
return class extends Base {
>class extends Base { timestamp = new Date(); } : { new (...args: any[]): (Anonymous class); prototype: <any>.(Anonymous class); } & CT
>Base : object
timestamp = new Date();
>timestamp : Date
>new Date() : Date
>Date : DateConstructor
};
}
@@ -3,9 +3,9 @@
for (const element of document.getElementsByTagName("a")) {
>element : HTMLAnchorElement
>document.getElementsByTagName("a") : NodeListOf<HTMLAnchorElement>
>document.getElementsByTagName : { <K extends "symbol" | "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "circle" | "cite" | "clippath" | "code" | "col" | "colgroup" | "datalist" | "dd" | "defs" | "del" | "desc" | "dfn" | "dir" | "div" | "dl" | "dt" | "ellipse" | "em" | "embed" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "fieldset" | "figcaption" | "figure" | "filter" | "font" | "footer" | "foreignobject" | "form" | "frame" | "frameset" | "g" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "image" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "line" | "lineargradient" | "link" | "listing" | "map" | "mark" | "marker" | "marquee" | "mask" | "menu" | "meta" | "metadata" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "p" | "param" | "path" | "pattern" | "picture" | "plaintext" | "polygon" | "polyline" | "pre" | "progress" | "q" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "stop" | "strike" | "strong" | "style" | "sub" | "sup" | "svg" | "switch" | "table" | "tbody" | "td" | "template" | "text" | "textpath" | "textarea" | "tfoot" | "th" | "thead" | "title" | "tr" | "track" | "tspan" | "tt" | "u" | "ul" | "use" | "var" | "video" | "view" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>document.getElementsByTagName : { <K extends "symbol" | "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "circle" | "cite" | "clippath" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "defs" | "del" | "desc" | "dfn" | "dir" | "div" | "dl" | "dt" | "ellipse" | "em" | "embed" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "fieldset" | "figcaption" | "figure" | "filter" | "font" | "footer" | "foreignobject" | "form" | "frame" | "frameset" | "g" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "image" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "line" | "lineargradient" | "link" | "listing" | "map" | "mark" | "marker" | "marquee" | "mask" | "menu" | "meta" | "metadata" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "path" | "pattern" | "picture" | "plaintext" | "polygon" | "polyline" | "pre" | "progress" | "q" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "stop" | "strike" | "strong" | "style" | "sub" | "sup" | "svg" | "switch" | "table" | "tbody" | "td" | "template" | "text" | "textpath" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tspan" | "tt" | "u" | "ul" | "use" | "var" | "video" | "view" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>document : Document
>getElementsByTagName : { <K extends "symbol" | "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "circle" | "cite" | "clippath" | "code" | "col" | "colgroup" | "datalist" | "dd" | "defs" | "del" | "desc" | "dfn" | "dir" | "div" | "dl" | "dt" | "ellipse" | "em" | "embed" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "fieldset" | "figcaption" | "figure" | "filter" | "font" | "footer" | "foreignobject" | "form" | "frame" | "frameset" | "g" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "image" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "line" | "lineargradient" | "link" | "listing" | "map" | "mark" | "marker" | "marquee" | "mask" | "menu" | "meta" | "metadata" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "p" | "param" | "path" | "pattern" | "picture" | "plaintext" | "polygon" | "polyline" | "pre" | "progress" | "q" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "stop" | "strike" | "strong" | "style" | "sub" | "sup" | "svg" | "switch" | "table" | "tbody" | "td" | "template" | "text" | "textpath" | "textarea" | "tfoot" | "th" | "thead" | "title" | "tr" | "track" | "tspan" | "tt" | "u" | "ul" | "use" | "var" | "video" | "view" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>getElementsByTagName : { <K extends "symbol" | "object" | "a" | "abbr" | "acronym" | "address" | "applet" | "area" | "article" | "aside" | "audio" | "b" | "base" | "basefont" | "bdo" | "big" | "blockquote" | "body" | "br" | "button" | "canvas" | "caption" | "center" | "circle" | "cite" | "clippath" | "code" | "col" | "colgroup" | "data" | "datalist" | "dd" | "defs" | "del" | "desc" | "dfn" | "dir" | "div" | "dl" | "dt" | "ellipse" | "em" | "embed" | "feblend" | "fecolormatrix" | "fecomponenttransfer" | "fecomposite" | "feconvolvematrix" | "fediffuselighting" | "fedisplacementmap" | "fedistantlight" | "feflood" | "fefunca" | "fefuncb" | "fefuncg" | "fefuncr" | "fegaussianblur" | "feimage" | "femerge" | "femergenode" | "femorphology" | "feoffset" | "fepointlight" | "fespecularlighting" | "fespotlight" | "fetile" | "feturbulence" | "fieldset" | "figcaption" | "figure" | "filter" | "font" | "footer" | "foreignobject" | "form" | "frame" | "frameset" | "g" | "h1" | "h2" | "h3" | "h4" | "h5" | "h6" | "head" | "header" | "hgroup" | "hr" | "html" | "i" | "iframe" | "image" | "img" | "input" | "ins" | "isindex" | "kbd" | "keygen" | "label" | "legend" | "li" | "line" | "lineargradient" | "link" | "listing" | "map" | "mark" | "marker" | "marquee" | "mask" | "menu" | "meta" | "metadata" | "meter" | "nav" | "nextid" | "nobr" | "noframes" | "noscript" | "ol" | "optgroup" | "option" | "output" | "p" | "param" | "path" | "pattern" | "picture" | "plaintext" | "polygon" | "polyline" | "pre" | "progress" | "q" | "radialgradient" | "rect" | "rt" | "ruby" | "s" | "samp" | "script" | "section" | "select" | "small" | "source" | "span" | "stop" | "strike" | "strong" | "style" | "sub" | "sup" | "svg" | "switch" | "table" | "tbody" | "td" | "template" | "text" | "textpath" | "textarea" | "tfoot" | "th" | "thead" | "time" | "title" | "tr" | "track" | "tspan" | "tt" | "u" | "ul" | "use" | "var" | "video" | "view" | "wbr" | "x-ms-webview" | "xmp">(tagname: K): ElementListTagNameMap[K]; (tagname: string): NodeListOf<Element>; }
>"a" : "a"
element.href;
@@ -1,5 +1,5 @@
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(5,1): error TS2322: Type 'object' is not assignable to type '{ foo: string; }'.
Property 'foo' is missing in type 'Object'.
Property 'foo' is missing in type '{}'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(13,1): error TS2322: Type 'number' is not assignable to type 'object'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(14,1): error TS2322: Type 'true' is not assignable to type 'object'.
tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(15,1): error TS2322: Type 'string' is not assignable to type 'object'.
@@ -16,7 +16,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveAssignError.ts(19,1): err
y = a; // expect error
~
!!! error TS2322: Type 'object' is not assignable to type '{ foo: string; }'.
!!! error TS2322: Property 'foo' is missing in type 'Object'.
!!! error TS2322: Property 'foo' is missing in type '{}'.
a = x;
a = y;
@@ -0,0 +1,6 @@
/*! [a.ts] */
// comment0
const a = 1;
/*! [b.ts] */
// comment1
const b = 2;
@@ -0,0 +1,4 @@
/*! [a.ts] */
const a = 1;
/*! [b.ts] */
const b = 2;
@@ -0,0 +1,25 @@
interface A<T> {
// comment1
readonly prop?: T;
// comment2
method(): void;
// comment3
new <T>(): A<T>;
// comment4
<T>(): A<T>;
}
// comment5
type B = number | string | object;
type C = A<number> & {
x: string;
}; // comment6
// comment7
enum E1 {
// comment8
first
}
const enum E2 {
second
}
// comment9
console.log(1 + 2);
@@ -0,0 +1,17 @@
interface A<T> {
readonly prop?: T;
method(): void;
new <T>(): A<T>;
<T>(): A<T>;
}
type B = number | string | object;
type C = A<number> & {
x: string;
};
enum E1 {
first
}
const enum E2 {
second
}
console.log(1 + 2);
@@ -0,0 +1,3 @@
class C {
public prop;
}
@@ -0,0 +1,14 @@
class Test
{
_b = this._a; // undefined, no error/warning
_a = 3;
static _B = Test._A; // undefined, no error/warning
static _A = 3;
method()
{
let a = b; // Block-scoped variable 'b' used before its declaration
let b = 3;
}
}
@@ -54,3 +54,11 @@ class Thing3 extends Thing2 {
this.print();
}
}
// Repro from #13805
const Timestamped = <CT extends Constructor<object>>(Base: CT) => {
return class extends Base {
timestamp = new Date();
};
}
@@ -527,3 +527,30 @@ class Form<T> {
this.childFormFactories[prop](value)
}
}
// Repro from #13787
class SampleClass<P> {
public props: Readonly<P>;
constructor(props: P) {
this.props = Object.freeze(props);
}
}
interface Foo {
foo: string;
}
declare function merge<T, U>(obj1: T, obj2: U): T & U;
class AnotherSampleClass<T> extends SampleClass<T & Foo> {
constructor(props: T) {
const foo: Foo = { foo: "bar" };
super(merge(props, foo));
}
public brokenMethod() {
this.props.foo.concat;
}
}
new AnotherSampleClass({});
@@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
////type As = 'arf' | 'abacus' | 'abaddon';
////let a: As;
////if ('/**/' != a
goTo.marker();
verify.completionListContains("arf");
verify.completionListContains("abacus");
verify.completionListContains("abaddon");
verify.completionListCount(3);
@@ -0,0 +1,14 @@
/// <reference path='fourslash.ts'/>
////type As = 'arf' | 'abacus' | 'abaddon';
////let a: As;
////switch (a) {
//// case '/**/
////}
goTo.marker();
verify.completionListContains("arf");
verify.completionListContains("abacus");
verify.completionListContains("abaddon");
verify.completionListCount(3);
@@ -0,0 +1,12 @@
/// <reference path='fourslash.ts'/>
////type As = 'arf' | 'abacus' | 'abaddon';
////let a: As;
////if (a === '/**/
goTo.marker();
verify.completionListContains("arf");
verify.completionListContains("abacus");
verify.completionListContains("abaddon");
verify.completionListCount(3);
@@ -1,6 +0,0 @@
/// <reference path='fourslash.ts' />
////function /*def*/f() {}
/////*use*/f(123);
verify.goToDefinition("use", "def");
@@ -3,7 +3,7 @@
//// [|/// <reference path="./tripleSlashReference.ts" />
//// f1/*0*/();|]
// @Filename: module.ts
// @Filename: Module.ts
//// export function f1() {}
//// export var v1 = 5;
@@ -12,7 +12,7 @@
verify.importFixAtPosition([
`/// <reference path="./tripleSlashReference.ts" />
import { f1 } from "./module";
import { f1 } from "./Module";
f1();`
]);
@@ -0,0 +1,15 @@
/// <reference path="fourslash.ts" />
//// [|let t: XXX/*0*/.I;|]
// @Filename: ./module.ts
//// export module XXX {
//// export interface I {
//// }
//// }
verify.importFixAtPosition([
`import { XXX } from "./module";
let t: XXX.I;`
]);
@@ -0,0 +1,16 @@
/// <reference path="fourslash.ts" />
//// [|let t: A/*0*/.B.I;|]
// @Filename: ./module.ts
//// export namespace A {
//// export namespace B {
//// export interface I { }
//// }
//// }
verify.importFixAtPosition([
`import { A } from "./module";
let t: A.B.I;`
]);
@@ -2,9 +2,11 @@
// @noUnusedLocals: true
//// [| namespace greeter {
//// // some legit comments
//// function function1() {
//// }/*1*/
//// } |]
verify.rangeAfterCodeFix(`namespace greeter {
// some legit comments
}`);
+2 -2
View File
@@ -2,7 +2,7 @@
// @noUnusedLocals: true
// @Filename: file2.ts
////[| import {Calculator, test, test2} from "./file1" |]
////[| import {Calculator, /*some comments*/ test, test2} from "./file1" |]
//// test();
//// test2();
@@ -20,5 +20,5 @@
////
//// }
verify.rangeAfterCodeFix(`import {test, test2} from "./file1"`);
verify.rangeAfterCodeFix(`import {/*some comments*/ test, test2} from "./file1"`);