Skip to content

Commit 98a5c9b

Browse files
committed
Merge branch 'master' into contextualGenericTypes
2 parents 34710a3 + 52e867c commit 98a5c9b

File tree

303 files changed

+7670
-2439
lines changed

Some content is hidden

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

303 files changed

+7670
-2439
lines changed

scripts/tslint/nextLineRule.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ export class Rule extends Lint.Rules.AbstractRule {
1818

1919
function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boolean): void {
2020
const { sourceFile } = ctx;
21-
function recur(node: ts.Node): void {
21+
ts.forEachChild(sourceFile, function recur(node) {
2222
switch (node.kind) {
2323
case ts.SyntaxKind.IfStatement:
2424
checkIf(node as ts.IfStatement);
@@ -28,7 +28,7 @@ function walk(ctx: Lint.WalkContext<void>, checkCatch: boolean, checkElse: boole
2828
break;
2929
}
3030
ts.forEachChild(node, recur);
31-
}
31+
});
3232

3333
function checkIf(node: ts.IfStatement): void {
3434
const { thenStatement, elseStatement } = node;

src/compiler/binder.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2333,7 +2333,7 @@ namespace ts {
23332333
// A common practice in node modules is to set 'export = module.exports = {}', this ensures that 'exports'
23342334
// is still pointing to 'module.exports'.
23352335
// We do not want to consider this as 'export=' since a module can have only one of these.
2336-
// Similarlly we do not want to treat 'module.exports = exports' as an 'export='.
2336+
// Similarly we do not want to treat 'module.exports = exports' as an 'export='.
23372337
const assignedExpression = getRightMostAssignedExpression(node.right);
23382338
if (isEmptyObjectLiteral(assignedExpression) || isExportsOrModuleExportsOrAlias(assignedExpression)) {
23392339
// Mark it as a module in case there are no other exports in the file
@@ -2741,6 +2741,10 @@ namespace ts {
27412741
transformFlags |= TransformFlags.AssertES2015;
27422742
}
27432743

2744+
if (expression.kind === SyntaxKind.ImportKeyword) {
2745+
transformFlags |= TransformFlags.ContainsDynamicImport;
2746+
}
2747+
27442748
node.transformFlags = transformFlags | TransformFlags.HasComputedFlags;
27452749
return transformFlags & ~TransformFlags.ArrayLiteralOrCallOrNewExcludes;
27462750
}

src/compiler/checker.ts

Lines changed: 88 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -210,6 +210,11 @@ namespace ts {
210210
getSuggestionForNonexistentProperty,
211211
getSuggestionForNonexistentSymbol,
212212
getBaseConstraintOfType,
213+
getJsxNamespace,
214+
resolveNameAtLocation(location: Node, name: string, meaning: SymbolFlags): Symbol | undefined {
215+
location = getParseTreeNode(location);
216+
return resolveName(location, name, meaning, /*nameNotFoundMessage*/ undefined, name);
217+
},
213218
};
214219

215220
const tupleTypes: GenericType[] = [];
@@ -735,6 +740,7 @@ namespace ts {
735740
if (declarationFile !== useFile) {
736741
if ((modulekind && (declarationFile.externalModuleIndicator || useFile.externalModuleIndicator)) ||
737742
(!compilerOptions.outFile && !compilerOptions.out) ||
743+
isInTypeQuery(usage) ||
738744
isInAmbientContext(declaration)) {
739745
// nodes are in different files and order cannot be determined
740746
return true;
@@ -847,7 +853,7 @@ namespace ts {
847853
location: Node | undefined,
848854
name: string,
849855
meaning: SymbolFlags,
850-
nameNotFoundMessage: DiagnosticMessage,
856+
nameNotFoundMessage: DiagnosticMessage | undefined,
851857
nameArg: string | Identifier,
852858
suggestedNameNotFoundMessage?: DiagnosticMessage): Symbol {
853859
return resolveNameHelper(location, name, meaning, nameNotFoundMessage, nameArg, getSymbol, suggestedNameNotFoundMessage);
@@ -1364,6 +1370,9 @@ namespace ts {
13641370
// An 'import { Point } from "graphics"' needs to create a symbol that combines the value side 'Point'
13651371
// property with the type/namespace side interface 'Point'.
13661372
function combineValueAndTypeSymbols(valueSymbol: Symbol, typeSymbol: Symbol): Symbol {
1373+
if (valueSymbol === unknownSymbol && typeSymbol === unknownSymbol) {
1374+
return unknownSymbol;
1375+
}
13671376
if (valueSymbol.flags & (SymbolFlags.Type | SymbolFlags.Namespace)) {
13681377
return valueSymbol;
13691378
}
@@ -2282,7 +2291,7 @@ namespace ts {
22822291

22832292
function typeToString(type: Type, enclosingDeclaration?: Node, flags?: TypeFormatFlags): string {
22842293
const typeNode = nodeBuilder.typeToTypeNode(type, enclosingDeclaration, toNodeBuilderFlags(flags) | NodeBuilderFlags.IgnoreErrors | NodeBuilderFlags.WriteTypeParametersInQualifiedName);
2285-
Debug.assert(typeNode !== undefined, "should always get typenode?");
2294+
Debug.assert(typeNode !== undefined, "should always get typenode");
22862295
const options = { removeComments: true };
22872296
const writer = createTextWriter("");
22882297
const printer = createPrinter(options);
@@ -5841,7 +5850,8 @@ namespace ts {
58415850
}
58425851
}
58435852
return arrayFrom(props.values());
5844-
} else {
5853+
}
5854+
else {
58455855
return getPropertiesOfType(type);
58465856
}
58475857
}
@@ -8356,6 +8366,12 @@ namespace ts {
83568366
/**
83578367
* This is *not* a bi-directional relationship.
83588368
* If one needs to check both directions for comparability, use a second call to this function or 'checkTypeComparableTo'.
8369+
*
8370+
* A type S is comparable to a type T if some (but not necessarily all) of the possible values of S are also possible values of T.
8371+
* It is used to check following cases:
8372+
* - the types of the left and right sides of equality/inequality operators (`===`, `!==`, `==`, `!=`).
8373+
* - the types of `case` clause expressions and their respective `switch` expressions.
8374+
* - the type of an expression in a type assertion with the type being asserted.
83598375
*/
83608376
function isTypeComparableTo(source: Type, target: Type): boolean {
83618377
return isTypeRelatedTo(source, target, comparableRelation);
@@ -8583,6 +8599,7 @@ namespace ts {
85838599

85848600
function isEmptyObjectType(type: Type): boolean {
85858601
return type.flags & TypeFlags.Object ? isEmptyResolvedType(resolveStructuredTypeMembers(<ObjectType>type)) :
8602+
type.flags & TypeFlags.NonPrimitive ? true :
85868603
type.flags & TypeFlags.Union ? forEach((<UnionType>type).types, isEmptyObjectType) :
85878604
type.flags & TypeFlags.Intersection ? !forEach((<UnionType>type).types, t => !isEmptyObjectType(t)) :
85888605
false;
@@ -14151,7 +14168,7 @@ namespace ts {
1415114168
checkJsxPreconditions(node);
1415214169
// The reactNamespace/jsxFactory's root symbol should be marked as 'used' so we don't incorrectly elide its import.
1415314170
// And if there is no reactNamespace/jsxFactory's symbol in scope when targeting React emit, we should issue an error.
14154-
const reactRefErr = compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
14171+
const reactRefErr = diagnostics && compilerOptions.jsx === JsxEmit.React ? Diagnostics.Cannot_find_name_0 : undefined;
1415514172
const reactNamespace = getJsxNamespace();
1415614173
const reactSym = resolveName(node.tagName, reactNamespace, SymbolFlags.Value, reactRefErr, reactNamespace);
1415714174
if (reactSym) {
@@ -14522,6 +14539,7 @@ namespace ts {
1452214539
const maximumLengthDifference = Math.min(3, name.length * 0.34);
1452314540
let bestDistance = Number.MAX_VALUE;
1452414541
let bestCandidate = undefined;
14542+
let justCheckExactMatches = false;
1452514543
if (name.length > 30) {
1452614544
return undefined;
1452714545
}
@@ -14534,6 +14552,9 @@ namespace ts {
1453414552
if (candidateName === name) {
1453514553
return candidate;
1453614554
}
14555+
if (justCheckExactMatches) {
14556+
continue;
14557+
}
1453714558
if (candidateName.length < 3 ||
1453814559
name.length < 3 ||
1453914560
candidateName === "eval" ||
@@ -14549,7 +14570,8 @@ namespace ts {
1454914570
continue;
1455014571
}
1455114572
if (distance < 3) {
14552-
return candidate;
14573+
justCheckExactMatches = true;
14574+
bestCandidate = candidate;
1455314575
}
1455414576
else if (distance < bestDistance) {
1455514577
bestDistance = distance;
@@ -16168,6 +16190,35 @@ namespace ts {
1616816190
return getReturnTypeOfSignature(signature);
1616916191
}
1617016192

16193+
function checkImportCallExpression(node: ImportCall): Type {
16194+
// Check grammar of dynamic import
16195+
checkGrammarArguments(node, node.arguments) || checkGrammarImportCallExpression(node);
16196+
16197+
if (node.arguments.length === 0) {
16198+
return createPromiseReturnType(node, anyType);
16199+
}
16200+
const specifier = node.arguments[0];
16201+
const specifierType = checkExpressionCached(specifier);
16202+
// Even though multiple arugments is grammatically incorrect, type-check extra arguments for completion
16203+
for (let i = 1; i < node.arguments.length; ++i) {
16204+
checkExpressionCached(node.arguments[i]);
16205+
}
16206+
16207+
if (specifierType.flags & TypeFlags.Undefined || specifierType.flags & TypeFlags.Null || !isTypeAssignableTo(specifierType, stringType)) {
16208+
error(specifier, Diagnostics.Dynamic_import_s_specifier_must_be_of_type_string_but_here_has_type_0, typeToString(specifierType));
16209+
}
16210+
16211+
// resolveExternalModuleName will return undefined if the moduleReferenceExpression is not a string literal
16212+
const moduleSymbol = resolveExternalModuleName(node, specifier);
16213+
if (moduleSymbol) {
16214+
const esModuleSymbol = resolveESModuleSymbol(moduleSymbol, specifier, /*dontRecursivelyResolve*/ true);
16215+
if (esModuleSymbol) {
16216+
return createPromiseReturnType(node, getTypeOfSymbol(esModuleSymbol));
16217+
}
16218+
}
16219+
return createPromiseReturnType(node, anyType);
16220+
}
16221+
1617116222
function isCommonJsRequire(node: Node) {
1617216223
if (!isRequireCall(node, /*checkArgumentIsStringLiteral*/ true)) {
1617316224
return false;
@@ -16374,14 +16425,18 @@ namespace ts {
1637416425
return emptyObjectType;
1637516426
}
1637616427

16377-
function createPromiseReturnType(func: FunctionLikeDeclaration, promisedType: Type) {
16428+
function createPromiseReturnType(func: FunctionLikeDeclaration | ImportCall, promisedType: Type) {
1637816429
const promiseType = createPromiseType(promisedType);
1637916430
if (promiseType === emptyObjectType) {
16380-
error(func, Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
16431+
error(func, isImportCall(func) ?
16432+
Diagnostics.A_dynamic_import_call_returns_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option :
16433+
Diagnostics.An_async_function_or_method_must_return_a_Promise_Make_sure_you_have_a_declaration_for_Promise_or_include_ES2015_in_your_lib_option);
1638116434
return unknownType;
1638216435
}
1638316436
else if (!getGlobalPromiseConstructorSymbol(/*reportErrors*/ true)) {
16384-
error(func, Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
16437+
error(func, isImportCall(func) ?
16438+
Diagnostics.A_dynamic_import_call_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option :
16439+
Diagnostics.An_async_function_or_method_in_ES5_SlashES3_requires_the_Promise_constructor_Make_sure_you_have_a_declaration_for_the_Promise_constructor_or_include_ES2015_in_your_lib_option);
1638516440
}
1638616441

1638716442
return promiseType;
@@ -17740,6 +17795,10 @@ namespace ts {
1774017795
case SyntaxKind.ElementAccessExpression:
1774117796
return checkIndexedAccess(<ElementAccessExpression>node);
1774217797
case SyntaxKind.CallExpression:
17798+
if ((<CallExpression>node).expression.kind === SyntaxKind.ImportKeyword) {
17799+
return checkImportCallExpression(<ImportCall>node);
17800+
}
17801+
/* falls through */
1774317802
case SyntaxKind.NewExpression:
1774417803
return checkCallExpression(<CallExpression>node);
1774517804
case SyntaxKind.TaggedTemplateExpression:
@@ -24665,6 +24724,27 @@ namespace ts {
2466524724
});
2466624725
return result;
2466724726
}
24727+
24728+
function checkGrammarImportCallExpression(node: ImportCall): boolean {
24729+
if (modulekind === ModuleKind.ES2015) {
24730+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_be_used_when_targeting_ECMAScript_2015_modules);
24731+
}
24732+
24733+
if (node.typeArguments) {
24734+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_cannot_have_type_arguments);
24735+
}
24736+
24737+
const arguments = node.arguments;
24738+
if (arguments.length !== 1) {
24739+
return grammarErrorOnNode(node, Diagnostics.Dynamic_import_must_have_one_specifier_as_an_argument);
24740+
}
24741+
24742+
// see: parseArgumentOrArrayLiteralElement...we use this function which parse arguments of callExpression to parse specifier for dynamic import.
24743+
// parseArgumentOrArrayLiteralElement allows spread element to be in an argument list which is not allowed as specifier in dynamic import.
24744+
if (isSpreadElement(arguments[0])) {
24745+
return grammarErrorOnNode(arguments[0], Diagnostics.Specifier_of_dynamic_import_cannot_be_spread_element);
24746+
}
24747+
}
2466824748
}
2466924749

2467024750
/** Like 'isDeclarationName', but returns true for LHS of `import { x as y }` or `export { x as y }`. */

src/compiler/commandLineParser.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ namespace ts {
100100
"umd": ModuleKind.UMD,
101101
"es6": ModuleKind.ES2015,
102102
"es2015": ModuleKind.ES2015,
103+
"esnext": ModuleKind.ESNext
103104
}),
104105
paramType: Diagnostics.KIND,
105106
showInSimplifiedHelpView: true,
106107
category: Diagnostics.Basic_Options,
107-
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_or_es2015,
108+
description: Diagnostics.Specify_module_code_generation_Colon_commonjs_amd_system_umd_es2015_or_ESNext,
108109
},
109110
{
110111
name: "lib",

src/compiler/core.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -473,7 +473,7 @@ namespace ts {
473473
* @param array The array to map.
474474
* @param mapfn The callback used to map the result into one or more values.
475475
*/
476-
export function flatMap<T, U>(array: T[], mapfn: (x: T, i: number) => U | U[]): U[] {
476+
export function flatMap<T, U>(array: T[] | undefined, mapfn: (x: T, i: number) => U | U[] | undefined): U[] | undefined {
477477
let result: U[];
478478
if (array) {
479479
result = [];

src/compiler/diagnosticMessages.json

Lines changed: 42 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -883,6 +883,23 @@
883883
"category": "Error",
884884
"code": 1322
885885
},
886+
"Dynamic import cannot be used when targeting ECMAScript 2015 modules.": {
887+
"category": "Error",
888+
"code": 1323
889+
},
890+
"Dynamic import must have one specifier as an argument.": {
891+
"category": "Error",
892+
"code": 1324
893+
},
894+
"Specifier of dynamic import cannot be spread element.": {
895+
"category": "Error",
896+
"code": 1325
897+
},
898+
"Dynamic import cannot have type arguments": {
899+
"category": "Error",
900+
"code": 1326
901+
},
902+
886903
"Duplicate identifier '{0}'.": {
887904
"category": "Error",
888905
"code": 2300
@@ -1927,10 +1944,6 @@
19271944
"category": "Error",
19281945
"code": 2649
19291946
},
1930-
"Cannot emit namespaced JSX elements in React.": {
1931-
"category": "Error",
1932-
"code": 2650
1933-
},
19341947
"A member initializer in a enum declaration cannot reference members declared after it, including members defined in other enums.": {
19351948
"category": "Error",
19361949
"code": 2651
@@ -2163,6 +2176,14 @@
21632176
"category": "Error",
21642177
"code": 2710
21652178
},
2179+
"A dynamic import call returns a 'Promise'. Make sure you have a declaration for 'Promise' or include 'ES2015' in your `--lib` option.": {
2180+
"category": "Error",
2181+
"code": 2711
2182+
},
2183+
"A dynamic import call in ES5/ES3 requires the 'Promise' constructor. Make sure you have a declaration for the 'Promise' constructor or include 'ES2015' in your `--lib` option.": {
2184+
"category": "Error",
2185+
"code": 2712
2186+
},
21662187

21672188
"Import declaration '{0}' is using private name '{1}'.": {
21682189
"category": "Error",
@@ -2629,7 +2650,7 @@
26292650
"category": "Message",
26302651
"code": 6015
26312652
},
2632-
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd' or 'es2015'.": {
2653+
"Specify module code generation: 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'.": {
26332654
"category": "Message",
26342655
"code": 6016
26352656
},
@@ -3365,6 +3386,11 @@
33653386
"category": "Error",
33663387
"code": 7035
33673388
},
3389+
"Dynamic import's specifier must be of type 'string', but here has type '{0}'.": {
3390+
"category": "Error",
3391+
"code": 7036
3392+
},
3393+
33683394
"You cannot rename this element.": {
33693395
"category": "Error",
33703396
"code": 8000
@@ -3559,11 +3585,11 @@
35593585
"category": "Message",
35603586
"code": 90015
35613587
},
3562-
"Add declaration for missing property '{0}'.": {
3588+
"Declare property '{0}'.": {
35633589
"category": "Message",
35643590
"code": 90016
35653591
},
3566-
"Add index signature for missing property '{0}'.": {
3592+
"Add index signature for property '{0}'.": {
35673593
"category": "Message",
35683594
"code": 90017
35693595
},
@@ -3587,7 +3613,15 @@
35873613
"category": "Message",
35883614
"code": 90022
35893615
},
3590-
3616+
"Declare method '{0}'.": {
3617+
"category": "Message",
3618+
"code": 90023
3619+
},
3620+
"Declare static method '{0}'.": {
3621+
"category": "Message",
3622+
"code": 90024
3623+
},
3624+
35913625
"Convert function to an ES2015 class": {
35923626
"category": "Message",
35933627
"code": 95001

src/compiler/emitter.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -676,6 +676,7 @@ namespace ts {
676676
case SyntaxKind.SuperKeyword:
677677
case SyntaxKind.TrueKeyword:
678678
case SyntaxKind.ThisKeyword:
679+
case SyntaxKind.ImportKeyword:
679680
writeTokenNode(node);
680681
return;
681682

src/compiler/factory.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2503,6 +2503,7 @@ namespace ts {
25032503
helpers
25042504
} = sourceEmitNode;
25052505
if (!destEmitNode) destEmitNode = {};
2506+
// We are using `.slice()` here in case `destEmitNode.leadingComments` is pushed to later.
25062507
if (leadingComments) destEmitNode.leadingComments = addRange(leadingComments.slice(), destEmitNode.leadingComments);
25072508
if (trailingComments) destEmitNode.trailingComments = addRange(trailingComments.slice(), destEmitNode.trailingComments);
25082509
if (flags) destEmitNode.flags = flags;

0 commit comments

Comments
 (0)