Skip to content

Commit 545a7f2

Browse files
committed
Merge branch 'master' into fixTypeRelationStackOverflow
# Conflicts: # tests/baselines/reference/mappedTypeRelationships.errors.txt
2 parents 0f0a8a1 + 9c9b659 commit 545a7f2

File tree

4,951 files changed

+30886
-32403
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

4,951 files changed

+30886
-32403
lines changed

src/compiler/checker.ts

Lines changed: 107 additions & 30 deletions
Large diffs are not rendered by default.

src/compiler/emitter.ts

Lines changed: 70 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ namespace ts {
276276
function writeBundle(bundle: Bundle, output: EmitTextWriter) {
277277
const previousWriter = writer;
278278
setWriter(output);
279+
emitShebangIfNeeded(bundle);
280+
emitPrologueDirectivesIfNeeded(bundle);
279281
emitHelpersIndirect(bundle);
280282
for (const sourceFile of bundle.sourceFiles) {
281283
print(EmitHint.SourceFile, sourceFile, sourceFile);
@@ -287,6 +289,8 @@ namespace ts {
287289
function writeFile(sourceFile: SourceFile, output: EmitTextWriter) {
288290
const previousWriter = writer;
289291
setWriter(output);
292+
emitShebangIfNeeded(sourceFile);
293+
emitPrologueDirectivesIfNeeded(sourceFile);
290294
print(EmitHint.SourceFile, sourceFile, sourceFile);
291295
reset();
292296
writer = previousWriter;
@@ -737,15 +741,6 @@ namespace ts {
737741
return node && substituteNode && substituteNode(hint, node) || node;
738742
}
739743

740-
function emitBodyIndirect(node: Node, elements: NodeArray<Node>, emitCallback: (node: Node) => void): void {
741-
if (emitBodyWithDetachedComments) {
742-
emitBodyWithDetachedComments(node, elements, emitCallback);
743-
}
744-
else {
745-
emitCallback(node);
746-
}
747-
}
748-
749744
function emitHelpersIndirect(node: Node) {
750745
if (onEmitHelpers) {
751746
onEmitHelpers(node, writeLines);
@@ -1663,7 +1658,12 @@ namespace ts {
16631658
? emitBlockFunctionBodyOnSingleLine
16641659
: emitBlockFunctionBodyWorker;
16651660

1666-
emitBodyIndirect(body, body.statements, emitBlockFunctionBody);
1661+
if (emitBodyWithDetachedComments) {
1662+
emitBodyWithDetachedComments(body, body.statements, emitBlockFunctionBody);
1663+
}
1664+
else {
1665+
emitBlockFunctionBody(body);
1666+
}
16671667

16681668
decreaseIndent();
16691669
writeToken(SyntaxKind.CloseBraceToken, body.statements.end, body);
@@ -2072,16 +2072,27 @@ namespace ts {
20722072

20732073
function emitSourceFile(node: SourceFile) {
20742074
writeLine();
2075-
emitShebang();
2076-
emitBodyIndirect(node, node.statements, emitSourceFileWorker);
2075+
const statements = node.statements;
2076+
if (emitBodyWithDetachedComments) {
2077+
// Emit detached comment if there are no prologue directives or if the first node is synthesized.
2078+
// The synthesized node will have no leading comment so some comments may be missed.
2079+
const shouldEmitDetachedComment = statements.length === 0 ||
2080+
!isPrologueDirective(statements[0]) ||
2081+
nodeIsSynthesized(statements[0]);
2082+
if (shouldEmitDetachedComment) {
2083+
emitBodyWithDetachedComments(node, statements, emitSourceFileWorker);
2084+
return;
2085+
}
2086+
}
2087+
emitSourceFileWorker(node);
20772088
}
20782089

20792090
function emitSourceFileWorker(node: SourceFile) {
20802091
const statements = node.statements;
2081-
const statementOffset = emitPrologueDirectives(statements);
20822092
pushNameGenerationScope();
20832093
emitHelpersIndirect(node);
2084-
emitList(node, statements, ListFormat.MultiLine, statementOffset);
2094+
const index = findIndex(statements, statement => !isPrologueDirective(statement));
2095+
emitList(node, statements, ListFormat.MultiLine, index === -1 ? statements.length : index);
20852096
popNameGenerationScope();
20862097
}
20872098

@@ -2095,13 +2106,20 @@ namespace ts {
20952106
* Emits any prologue directives at the start of a Statement list, returning the
20962107
* number of prologue directives written to the output.
20972108
*/
2098-
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean): number {
2109+
function emitPrologueDirectives(statements: Node[], startWithNewLine?: boolean, seenPrologueDirectives?: Map<String>): number {
20992110
for (let i = 0; i < statements.length; i++) {
2100-
if (isPrologueDirective(statements[i])) {
2101-
if (startWithNewLine || i > 0) {
2102-
writeLine();
2111+
const statement = statements[i];
2112+
if (isPrologueDirective(statement)) {
2113+
const shouldEmitPrologueDirective = seenPrologueDirectives ? !seenPrologueDirectives.has(statement.expression.text) : true;
2114+
if (shouldEmitPrologueDirective) {
2115+
if (startWithNewLine || i > 0) {
2116+
writeLine();
2117+
}
2118+
emit(statement);
2119+
if (seenPrologueDirectives) {
2120+
seenPrologueDirectives.set(statement.expression.text, statement.expression.text);
2121+
}
21032122
}
2104-
emit(statements[i]);
21052123
}
21062124
else {
21072125
// return index of the first non prologue directive
@@ -2112,18 +2130,43 @@ namespace ts {
21122130
return statements.length;
21132131
}
21142132

2115-
//
2116-
// Helpers
2117-
//
2133+
function emitPrologueDirectivesIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
2134+
if (isSourceFile(sourceFileOrBundle)) {
2135+
setSourceFile(sourceFileOrBundle as SourceFile);
2136+
emitPrologueDirectives((sourceFileOrBundle as SourceFile).statements);
2137+
}
2138+
else {
2139+
const seenPrologueDirectives = createMap<String>();
2140+
for (const sourceFile of (sourceFileOrBundle as Bundle).sourceFiles) {
2141+
setSourceFile(sourceFile);
2142+
emitPrologueDirectives(sourceFile.statements, /*startWithNewLine*/ true, seenPrologueDirectives);
2143+
}
2144+
}
2145+
}
21182146

2119-
function emitShebang() {
2120-
const shebang = getShebang(currentSourceFile.text);
2121-
if (shebang) {
2122-
write(shebang);
2123-
writeLine();
2147+
function emitShebangIfNeeded(sourceFileOrBundle: Bundle | SourceFile) {
2148+
if (isSourceFile(sourceFileOrBundle)) {
2149+
const shebang = getShebang(sourceFileOrBundle.text);
2150+
if (shebang) {
2151+
write(shebang);
2152+
writeLine();
2153+
return true;
2154+
}
2155+
}
2156+
else {
2157+
for (const sourceFile of sourceFileOrBundle.sourceFiles) {
2158+
// Emit only the first encountered shebang
2159+
if (emitShebangIfNeeded(sourceFile)) {
2160+
break;
2161+
}
2162+
}
21242163
}
21252164
}
21262165

2166+
//
2167+
// Helpers
2168+
//
2169+
21272170
function emitModifiers(node: Node, modifiers: NodeArray<Modifier>) {
21282171
if (modifiers && modifiers.length) {
21292172
emitList(node, modifiers, ListFormat.Modifiers);

src/compiler/parser.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1267,6 +1267,7 @@ namespace ts {
12671267
function nextTokenIsClassOrFunctionOrAsync(): boolean {
12681268
nextToken();
12691269
return token() === SyntaxKind.ClassKeyword || token() === SyntaxKind.FunctionKeyword ||
1270+
(token() === SyntaxKind.AbstractKeyword && lookAhead(nextTokenIsClassKeywordOnSameLine)) ||
12701271
(token() === SyntaxKind.AsyncKeyword && lookAhead(nextTokenIsFunctionKeywordOnSameLine));
12711272
}
12721273

@@ -4661,6 +4662,11 @@ namespace ts {
46614662
return tokenIsIdentifierOrKeyword(token()) && !scanner.hasPrecedingLineBreak();
46624663
}
46634664

4665+
function nextTokenIsClassKeywordOnSameLine() {
4666+
nextToken();
4667+
return token() === SyntaxKind.ClassKeyword && !scanner.hasPrecedingLineBreak();
4668+
}
4669+
46644670
function nextTokenIsFunctionKeywordOnSameLine() {
46654671
nextToken();
46664672
return token() === SyntaxKind.FunctionKeyword && !scanner.hasPrecedingLineBreak();
@@ -6528,7 +6534,7 @@ namespace ts {
65286534

65296535
function parseTagComments(indent: number) {
65306536
const comments: string[] = [];
6531-
let state = JSDocState.SawAsterisk;
6537+
let state = JSDocState.BeginningOfLine;
65326538
let margin: number | undefined;
65336539
function pushComment(text: string) {
65346540
if (!margin) {

src/compiler/transformers/generators.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1478,7 +1478,7 @@ namespace ts {
14781478
}
14791479

14801480
const initializer = node.initializer;
1481-
if (isVariableDeclarationList(initializer)) {
1481+
if (initializer && isVariableDeclarationList(initializer)) {
14821482
for (const variable of initializer.declarations) {
14831483
hoistVariableDeclaration(<Identifier>variable.name);
14841484
}

src/compiler/transformers/module/module.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -359,15 +359,20 @@ namespace ts {
359359

360360
// Find the name of the module alias, if there is one
361361
const importAliasName = getLocalNameForExternalImport(importNode, currentSourceFile);
362-
if (includeNonAmdDependencies && importAliasName) {
363-
// Set emitFlags on the name of the classDeclaration
364-
// This is so that when printer will not substitute the identifier
365-
setEmitFlags(importAliasName, EmitFlags.NoSubstitution);
366-
aliasedModuleNames.push(externalModuleName);
367-
importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName));
368-
}
369-
else {
370-
unaliasedModuleNames.push(externalModuleName);
362+
// It is possible that externalModuleName is undefined if it is not string literal.
363+
// This can happen in the invalid import syntax.
364+
// E.g : "import * from alias from 'someLib';"
365+
if (externalModuleName) {
366+
if (includeNonAmdDependencies && importAliasName) {
367+
// Set emitFlags on the name of the classDeclaration
368+
// This is so that when printer will not substitute the identifier
369+
setEmitFlags(importAliasName, EmitFlags.NoSubstitution);
370+
aliasedModuleNames.push(externalModuleName);
371+
importAliasNames.push(createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, /*dotDotDotToken*/ undefined, importAliasName));
372+
}
373+
else {
374+
unaliasedModuleNames.push(externalModuleName);
375+
}
371376
}
372377
}
373378

src/compiler/transformers/module/system.ts

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -151,18 +151,20 @@ namespace ts {
151151
for (let i = 0; i < externalImports.length; i++) {
152152
const externalImport = externalImports[i];
153153
const externalModuleName = getExternalModuleNameLiteral(externalImport, currentSourceFile, host, resolver, compilerOptions);
154-
const text = externalModuleName.text;
155-
const groupIndex = groupIndices.get(text);
156-
if (groupIndex !== undefined) {
157-
// deduplicate/group entries in dependency list by the dependency name
158-
dependencyGroups[groupIndex].externalImports.push(externalImport);
159-
}
160-
else {
161-
groupIndices.set(text, dependencyGroups.length);
162-
dependencyGroups.push({
163-
name: externalModuleName,
164-
externalImports: [externalImport]
165-
});
154+
if (externalModuleName) {
155+
const text = externalModuleName.text;
156+
const groupIndex = groupIndices.get(text);
157+
if (groupIndex !== undefined) {
158+
// deduplicate/group entries in dependency list by the dependency name
159+
dependencyGroups[groupIndex].externalImports.push(externalImport);
160+
}
161+
else {
162+
groupIndices.set(text, dependencyGroups.length);
163+
dependencyGroups.push({
164+
name: externalModuleName,
165+
externalImports: [externalImport]
166+
});
167+
}
166168
}
167169
}
168170

@@ -1287,6 +1289,10 @@ namespace ts {
12871289
* @param node The node to visit.
12881290
*/
12891291
function visitForInitializer(node: ForInitializer): ForInitializer {
1292+
if (!node) {
1293+
return node;
1294+
}
1295+
12901296
if (shouldHoistForInitializer(node)) {
12911297
let expressions: Expression[];
12921298
for (const variable of node.declarations) {

src/compiler/types.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1402,7 +1402,7 @@ namespace ts {
14021402
multiLine?: boolean;
14031403
}
14041404

1405-
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression;
1405+
export type EntityNameExpression = Identifier | PropertyAccessEntityNameExpression | ParenthesizedExpression;
14061406
export type EntityNameOrEntityNameExpression = EntityName | EntityNameExpression;
14071407

14081408
export interface PropertyAccessExpression extends MemberExpression, Declaration {
@@ -2870,6 +2870,7 @@ namespace ts {
28702870
/* @internal */
28712871
export interface TransientSymbol extends Symbol, SymbolLinks {
28722872
checkFlags: CheckFlags;
2873+
isRestParameter?: boolean;
28732874
}
28742875

28752876
export type SymbolTable = Map<Symbol>;
@@ -2899,7 +2900,7 @@ namespace ts {
28992900
ContextChecked = 0x00000400, // Contextual types have been assigned
29002901
AsyncMethodWithSuper = 0x00000800, // An async method that reads a value from a member of 'super'.
29012902
AsyncMethodWithSuperBinding = 0x00001000, // An async method that assigns a value to a member of 'super'.
2902-
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body (for async functions)
2903+
CaptureArguments = 0x00002000, // Lexical 'arguments' used in body
29032904
EnumValuesComputed = 0x00004000, // Values for enum members have been computed, and any errors have been reported for them.
29042905
LexicalModuleMergesWithClass = 0x00008000, // Instantiated lexical module declaration is merged with a previous class declaration.
29052906
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
@@ -2923,6 +2924,7 @@ namespace ts {
29232924
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
29242925
enumMemberValue?: number; // Constant value of enum member
29252926
isVisible?: boolean; // Is this node visible
2927+
containsArgumentsReference?: boolean; // Whether a function-like declaration contains an 'arguments' reference
29262928
hasReportedStatementInAmbientContext?: boolean; // Cache boolean if we report statements in ambient context
29272929
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
29282930
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element

src/compiler/utilities.ts

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1404,17 +1404,24 @@ namespace ts {
14041404

14051405
/**
14061406
* Returns true if the node is a CallExpression to the identifier 'require' with
1407-
* exactly one argument.
1407+
* exactly one argument (of the form 'require("name")').
14081408
* This function does not test if the node is in a JavaScript file or not.
1409-
*/
1410-
export function isRequireCall(expression: Node, checkArgumentIsStringLiteral: boolean): expression is CallExpression {
1411-
// of the form 'require("name")'
1412-
const isRequire = expression.kind === SyntaxKind.CallExpression &&
1413-
(<CallExpression>expression).expression.kind === SyntaxKind.Identifier &&
1414-
(<Identifier>(<CallExpression>expression).expression).text === "require" &&
1415-
(<CallExpression>expression).arguments.length === 1;
1409+
*/
1410+
export function isRequireCall(callExpression: Node, checkArgumentIsStringLiteral: boolean): callExpression is CallExpression {
1411+
if (callExpression.kind !== SyntaxKind.CallExpression) {
1412+
return false;
1413+
}
1414+
const { expression, arguments } = callExpression as CallExpression;
1415+
1416+
if (expression.kind !== SyntaxKind.Identifier || (expression as Identifier).text !== "require") {
1417+
return false;
1418+
}
14161419

1417-
return isRequire && (!checkArgumentIsStringLiteral || (<CallExpression>expression).arguments[0].kind === SyntaxKind.StringLiteral);
1420+
if (arguments.length !== 1) {
1421+
return false;
1422+
}
1423+
const arg = arguments[0];
1424+
return !checkArgumentIsStringLiteral || arg.kind === SyntaxKind.StringLiteral || arg.kind === SyntaxKind.NoSubstitutionTemplateLiteral;
14181425
}
14191426

14201427
export function isSingleOrDoubleQuote(charCode: number) {
@@ -1588,7 +1595,7 @@ namespace ts {
15881595
return node && firstOrUndefined(getJSDocTags(node, kind));
15891596
}
15901597

1591-
function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
1598+
export function getJSDocs(node: Node): (JSDoc | JSDocTag)[] {
15921599
let cache: (JSDoc | JSDocTag)[] = node.jsDocCache;
15931600
if (!cache) {
15941601
getJSDocsWorker(node);

0 commit comments

Comments
 (0)