@@ -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 }`. */
0 commit comments