From 2c7b39aa4467eaeaa28d5650d286ff7e49e3f9f8 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Thu, 5 Jul 2018 11:04:04 +0300 Subject: [PATCH 01/22] Change message for import *-ing an export=. Update baselines --- src/compiler/checker.ts | 3 +- src/compiler/diagnosticMessages.json | 2 +- .../reference/api/tsserverlibrary.d.ts | 2 +- .../es6ExportEqualsInterop.errors.txt | 36 +++++++++---------- 4 files changed, 22 insertions(+), 21 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 207d7317078..669938b597d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2269,7 +2269,8 @@ namespace ts { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); if (!dontResolveAlias && symbol) { if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable))) { - error(referencingLocation, Diagnostics.Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct, symbolToString(moduleSymbol!)); + error(referencingLocation, Diagnostics.ECMAScript_imports_can_only_reference_an_export_declaration_with_the_esModuleInterop_flag_enabled_and_by_using_default_imports); + return symbol; } if (compilerOptions.esModuleInterop) { diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 40a4c4d09d4..75e2d35c471 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1744,7 +1744,7 @@ "category": "Error", "code": 2496 }, - "Module '{0}' resolves to a non-module entity and cannot be imported using this construct.": { + "ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports.": { "category": "Error", "code": 2497 }, diff --git a/tests/baselines/reference/api/tsserverlibrary.d.ts b/tests/baselines/reference/api/tsserverlibrary.d.ts index 99452b93d47..a251e4d9361 100644 --- a/tests/baselines/reference/api/tsserverlibrary.d.ts +++ b/tests/baselines/reference/api/tsserverlibrary.d.ts @@ -5266,7 +5266,7 @@ declare namespace ts { Using_a_string_in_a_for_of_statement_is_only_supported_in_ECMAScript_5_and_higher: DiagnosticMessage; Type_0_is_not_an_array_type_or_a_string_type: DiagnosticMessage; The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression: DiagnosticMessage; - Module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: DiagnosticMessage; + ECMAScript_imports_can_only_reference_an_export_declaration_with_the_esModuleInterop_flag_enabled_and_by_using_default_imports: DiagnosticMessage; Module_0_uses_export_and_cannot_be_used_with_export_Asterisk: DiagnosticMessage; An_interface_can_only_extend_an_identifier_Slashqualified_name_with_optional_type_arguments: DiagnosticMessage; A_class_can_only_implement_an_identifier_Slashqualified_name_with_optional_type_arguments: DiagnosticMessage; diff --git a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt index 4675136d081..2d29884065c 100644 --- a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt +++ b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt @@ -11,24 +11,24 @@ tests/cases/compiler/main.ts(33,8): error TS1192: Module '"function"' has no def tests/cases/compiler/main.ts(34,8): error TS1192: Module '"function-module"' has no default export. tests/cases/compiler/main.ts(35,8): error TS1192: Module '"class"' has no default export. tests/cases/compiler/main.ts(36,8): error TS1192: Module '"class-module"' has no default export. -tests/cases/compiler/main.ts(39,21): error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. -tests/cases/compiler/main.ts(45,21): error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. -tests/cases/compiler/main.ts(47,21): error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(39,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(45,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(47,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(50,1): error TS2693: 'y1' only refers to a type, but is being used as a value here. tests/cases/compiler/main.ts(56,4): error TS2339: Property 'a' does not exist on type '() => any'. tests/cases/compiler/main.ts(58,4): error TS2339: Property 'a' does not exist on type 'typeof Foo'. tests/cases/compiler/main.ts(62,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(62,25): error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(62,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(68,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(68,25): error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(68,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(70,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(70,25): error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(70,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(85,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(85,25): error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(85,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(91,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(91,25): error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(91,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(93,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(93,25): error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +tests/cases/compiler/main.ts(93,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. tests/cases/compiler/main.ts(97,15): error TS2498: Module '"interface"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(98,15): error TS2498: Module '"variable"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(99,15): error TS2498: Module '"interface-variable"' uses 'export =' and cannot be used with 'export *'. @@ -108,7 +108,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses // namespace import import * as y1 from "interface"; ~~~~~~~~~~~ -!!! error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import * as y2 from "variable"; import * as y3 from "interface-variable"; import * as y4 from "module"; @@ -116,11 +116,11 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses import * as y6 from "variable-module"; import * as y7 from "function"; ~~~~~~~~~~ -!!! error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import * as y8 from "function-module"; import * as y9 from "class"; ~~~~~~~ -!!! error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import * as y0 from "class-module"; y1.a; @@ -145,7 +145,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import { a as a2 } from "variable"; import { a as a3 } from "interface-variable"; import { a as a4 } from "module"; @@ -155,13 +155,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import { a as a8 } from "function-module"; import { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. import { a as a0 } from "class-module"; a1; @@ -180,7 +180,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: Module '"interface"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. export { a as a2 } from "variable"; export { a as a3 } from "interface-variable"; export { a as a4 } from "module"; @@ -190,13 +190,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: Module '"function"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. export { a as a8 } from "function-module"; export { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: Module '"class"' resolves to a non-module entity and cannot be imported using this construct. +!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. export { a as a0 } from "class-module"; // export-star From 312a5f9951bc1402daa09a81bb00c13a9bae42dd Mon Sep 17 00:00:00 2001 From: Alexander T Date: Wed, 11 Jul 2018 14:55:11 +0300 Subject: [PATCH 02/22] Change message for import *-ing an export= based on module type. Update tests/baselines --- src/compiler/checker.ts | 8 ++++- src/compiler/diagnosticMessages.json | 2 +- .../es6ExportEqualsInterop.errors.txt | 36 +++++++++---------- ...EqualsExportModuleCommonJsError.errors.txt | 15 ++++++++ ...s6ImportEqualsExportModuleCommonJsError.js | 26 ++++++++++++++ ...ortEqualsExportModuleCommonJsError.symbols | 16 +++++++++ ...mportEqualsExportModuleCommonJsError.types | 16 +++++++++ ...rtEqualsExportModuleEs2015Error.errors.txt | 18 ++++++++++ .../es6ImportEqualsExportModuleEs2015Error.js | 22 ++++++++++++ ...mportEqualsExportModuleEs2015Error.symbols | 16 +++++++++ ...6ImportEqualsExportModuleEs2015Error.types | 16 +++++++++ ...s6ImportEqualsExportModuleCommonJsError.ts | 11 ++++++ .../es6ImportEqualsExportModuleEs2015Error.ts | 11 ++++++ 13 files changed, 193 insertions(+), 20 deletions(-) create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.js create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.symbols create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.types create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.js create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.symbols create mode 100644 tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.types create mode 100644 tests/cases/compiler/es6ImportEqualsExportModuleCommonJsError.ts create mode 100644 tests/cases/compiler/es6ImportEqualsExportModuleEs2015Error.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7561255c25b..02efec7ba13 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2281,9 +2281,15 @@ namespace ts { // combine other declarations with the module or variable (e.g. a class/module, function/module, interface/variable). function resolveESModuleSymbol(moduleSymbol: Symbol | undefined, referencingLocation: Node, dontResolveAlias: boolean): Symbol | undefined { const symbol = resolveExternalModuleSymbol(moduleSymbol, dontResolveAlias); + if (!dontResolveAlias && symbol) { if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Variable)) && !getDeclarationOfKind(symbol, SyntaxKind.SourceFile)) { - error(referencingLocation, Diagnostics.ECMAScript_imports_can_only_reference_an_export_declaration_with_the_esModuleInterop_flag_enabled_and_by_using_default_imports); + const compilerOptionName = moduleKind >= ModuleKind.ES2015 + ? "allowSyntheticDefaultImports" + : "esModuleInterop"; + + error(referencingLocation, Diagnostics.When_writing_ECMAScript_imports_callable_export_style_modules_can_only_be_imported_by_turning_on_the_0_flag_and_using_a_default_import, compilerOptionName); + return symbol; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index da818948870..365014ab318 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1744,7 +1744,7 @@ "category": "Error", "code": 2496 }, - "ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports.": { + "When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the '{0}' flag and using a default import.": { "category": "Error", "code": 2497 }, diff --git a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt index 2d29884065c..bebe3f45940 100644 --- a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt +++ b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt @@ -11,24 +11,24 @@ tests/cases/compiler/main.ts(33,8): error TS1192: Module '"function"' has no def tests/cases/compiler/main.ts(34,8): error TS1192: Module '"function-module"' has no default export. tests/cases/compiler/main.ts(35,8): error TS1192: Module '"class"' has no default export. tests/cases/compiler/main.ts(36,8): error TS1192: Module '"class-module"' has no default export. -tests/cases/compiler/main.ts(39,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. -tests/cases/compiler/main.ts(45,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. -tests/cases/compiler/main.ts(47,21): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(39,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(45,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(47,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(50,1): error TS2693: 'y1' only refers to a type, but is being used as a value here. tests/cases/compiler/main.ts(56,4): error TS2339: Property 'a' does not exist on type '() => any'. tests/cases/compiler/main.ts(58,4): error TS2339: Property 'a' does not exist on type 'typeof Foo'. tests/cases/compiler/main.ts(62,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(62,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(62,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(68,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(68,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(68,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(70,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(70,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(70,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(85,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(85,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(85,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(91,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(91,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(91,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(93,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(93,25): error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +tests/cases/compiler/main.ts(93,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(97,15): error TS2498: Module '"interface"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(98,15): error TS2498: Module '"variable"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(99,15): error TS2498: Module '"interface-variable"' uses 'export =' and cannot be used with 'export *'. @@ -108,7 +108,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses // namespace import import * as y1 from "interface"; ~~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import * as y2 from "variable"; import * as y3 from "interface-variable"; import * as y4 from "module"; @@ -116,11 +116,11 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses import * as y6 from "variable-module"; import * as y7 from "function"; ~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import * as y8 from "function-module"; import * as y9 from "class"; ~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import * as y0 from "class-module"; y1.a; @@ -145,7 +145,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import { a as a2 } from "variable"; import { a as a3 } from "interface-variable"; import { a as a4 } from "module"; @@ -155,13 +155,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import { a as a8 } from "function-module"; import { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. import { a as a0 } from "class-module"; a1; @@ -180,7 +180,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. export { a as a2 } from "variable"; export { a as a3 } from "interface-variable"; export { a as a4 } from "module"; @@ -190,13 +190,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. export { a as a8 } from "function-module"; export { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: ECMAScript imports can only reference an 'export =' declaration with the 'esModuleInterop' flag enabled and by using default imports. +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. export { a as a0 } from "class-module"; // export-star diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt new file mode 100644 index 00000000000..96d2f55ed27 --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt @@ -0,0 +1,15 @@ +tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. + + +==== tests/cases/compiler/a.ts (0 errors) ==== + class a { } + export = a; + +==== tests/cases/compiler/main.ts (1 errors) ==== + import * as a from "./a"; + ~~~~~ +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. + a; + + + \ No newline at end of file diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.js b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.js new file mode 100644 index 00000000000..37f127721ce --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.js @@ -0,0 +1,26 @@ +//// [tests/cases/compiler/es6ImportEqualsExportModuleCommonJsError.ts] //// + +//// [a.ts] +class a { } +export = a; + +//// [main.ts] +import * as a from "./a"; +a; + + + + +//// [a.js] +"use strict"; +var a = /** @class */ (function () { + function a() { + } + return a; +}()); +module.exports = a; +//// [main.js] +"use strict"; +exports.__esModule = true; +var a = require("./a"); +a; diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.symbols b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.symbols new file mode 100644 index 00000000000..071f2fb5725 --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/a.ts === +class a { } +>a : Symbol(a, Decl(a.ts, 0, 0)) + +export = a; +>a : Symbol(a, Decl(a.ts, 0, 0)) + +=== tests/cases/compiler/main.ts === +import * as a from "./a"; +>a : Symbol(a, Decl(main.ts, 0, 6)) + +a; +>a : Symbol(a, Decl(main.ts, 0, 6)) + + + diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.types b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.types new file mode 100644 index 00000000000..652d7d6241b --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/a.ts === +class a { } +>a : a + +export = a; +>a : a + +=== tests/cases/compiler/main.ts === +import * as a from "./a"; +>a : typeof a + +a; +>a : typeof a + + + diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt new file mode 100644 index 00000000000..ee3e9cfff17 --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt @@ -0,0 +1,18 @@ +tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. +tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'allowSyntheticDefaultImports' flag and using a default import. + + +==== tests/cases/compiler/a.ts (1 errors) ==== + class a { } + export = a; + ~~~~~~~~~~~ +!!! error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. + +==== tests/cases/compiler/main.ts (1 errors) ==== + import * as a from "./a"; + ~~~~~ +!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'allowSyntheticDefaultImports' flag and using a default import. + a; + + + \ No newline at end of file diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.js b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.js new file mode 100644 index 00000000000..603f158946e --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.js @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/es6ImportEqualsExportModuleEs2015Error.ts] //// + +//// [a.ts] +class a { } +export = a; + +//// [main.ts] +import * as a from "./a"; +a; + + + + +//// [a.js] +var a = /** @class */ (function () { + function a() { + } + return a; +}()); +//// [main.js] +import * as a from "./a"; +a; diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.symbols b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.symbols new file mode 100644 index 00000000000..071f2fb5725 --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.symbols @@ -0,0 +1,16 @@ +=== tests/cases/compiler/a.ts === +class a { } +>a : Symbol(a, Decl(a.ts, 0, 0)) + +export = a; +>a : Symbol(a, Decl(a.ts, 0, 0)) + +=== tests/cases/compiler/main.ts === +import * as a from "./a"; +>a : Symbol(a, Decl(main.ts, 0, 6)) + +a; +>a : Symbol(a, Decl(main.ts, 0, 6)) + + + diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.types b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.types new file mode 100644 index 00000000000..652d7d6241b --- /dev/null +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.types @@ -0,0 +1,16 @@ +=== tests/cases/compiler/a.ts === +class a { } +>a : a + +export = a; +>a : a + +=== tests/cases/compiler/main.ts === +import * as a from "./a"; +>a : typeof a + +a; +>a : typeof a + + + diff --git a/tests/cases/compiler/es6ImportEqualsExportModuleCommonJsError.ts b/tests/cases/compiler/es6ImportEqualsExportModuleCommonJsError.ts new file mode 100644 index 00000000000..577e606c249 --- /dev/null +++ b/tests/cases/compiler/es6ImportEqualsExportModuleCommonJsError.ts @@ -0,0 +1,11 @@ +// @module: commonjs + +// @filename: a.ts +class a { } +export = a; + +// @filename: main.ts +import * as a from "./a"; +a; + + diff --git a/tests/cases/compiler/es6ImportEqualsExportModuleEs2015Error.ts b/tests/cases/compiler/es6ImportEqualsExportModuleEs2015Error.ts new file mode 100644 index 00000000000..a5505b0e90e --- /dev/null +++ b/tests/cases/compiler/es6ImportEqualsExportModuleEs2015Error.ts @@ -0,0 +1,11 @@ +// @module: es2015 + +// @filename: a.ts +class a { } +export = a; + +// @filename: main.ts +import * as a from "./a"; +a; + + From 332c88e57db6a5450b2aae3ef0465d134daffdbc Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 18 Dec 2018 10:39:32 +0200 Subject: [PATCH 03/22] PR feedback: change error #2497 message --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f451c91046b..b70d5cf876b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2381,7 +2381,7 @@ namespace ts { ? "allowSyntheticDefaultImports" : "esModuleInterop"; - error(referencingLocation, Diagnostics.When_writing_ECMAScript_imports_callable_export_style_modules_can_only_be_imported_by_turning_on_the_0_flag_and_using_a_default_import, compilerOptionName); + error(referencingLocation, Diagnostics.This_module_can_only_be_imported_with_ECMAScript_imports_by_turning_on_the_0_flag_and_using_a_default_import, compilerOptionName); return symbol; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 907940c4f6a..a27aa17efb9 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1768,7 +1768,7 @@ "category": "Error", "code": 2496 }, - "When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the '{0}' flag and using a default import.": { + "This module can only be imported with ECMAScript imports by turning on the '{0}' flag and using a default import.": { "category": "Error", "code": 2497 }, From 4e46f4b95a7773b290aa8c8e56a01d505d33a4b9 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 18 Dec 2018 10:41:04 +0200 Subject: [PATCH 04/22] update baseline --- .../es6ExportEqualsInterop.errors.txt | 36 +++++++++---------- ...EqualsExportModuleCommonJsError.errors.txt | 4 +-- ...rtEqualsExportModuleEs2015Error.errors.txt | 4 +-- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt index bebe3f45940..986aae2245f 100644 --- a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt +++ b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt @@ -11,24 +11,24 @@ tests/cases/compiler/main.ts(33,8): error TS1192: Module '"function"' has no def tests/cases/compiler/main.ts(34,8): error TS1192: Module '"function-module"' has no default export. tests/cases/compiler/main.ts(35,8): error TS1192: Module '"class"' has no default export. tests/cases/compiler/main.ts(36,8): error TS1192: Module '"class-module"' has no default export. -tests/cases/compiler/main.ts(39,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. -tests/cases/compiler/main.ts(45,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. -tests/cases/compiler/main.ts(47,21): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(39,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(45,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(47,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(50,1): error TS2693: 'y1' only refers to a type, but is being used as a value here. tests/cases/compiler/main.ts(56,4): error TS2339: Property 'a' does not exist on type '() => any'. tests/cases/compiler/main.ts(58,4): error TS2339: Property 'a' does not exist on type 'typeof Foo'. tests/cases/compiler/main.ts(62,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(62,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(62,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(68,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(68,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(68,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(70,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(70,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(70,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(85,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(85,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(85,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(91,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(91,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(91,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(93,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(93,25): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(93,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. tests/cases/compiler/main.ts(97,15): error TS2498: Module '"interface"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(98,15): error TS2498: Module '"variable"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(99,15): error TS2498: Module '"interface-variable"' uses 'export =' and cannot be used with 'export *'. @@ -108,7 +108,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses // namespace import import * as y1 from "interface"; ~~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import * as y2 from "variable"; import * as y3 from "interface-variable"; import * as y4 from "module"; @@ -116,11 +116,11 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses import * as y6 from "variable-module"; import * as y7 from "function"; ~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import * as y8 from "function-module"; import * as y9 from "class"; ~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import * as y0 from "class-module"; y1.a; @@ -145,7 +145,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import { a as a2 } from "variable"; import { a as a3 } from "interface-variable"; import { a as a4 } from "module"; @@ -155,13 +155,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import { a as a8 } from "function-module"; import { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. import { a as a0 } from "class-module"; a1; @@ -180,7 +180,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. export { a as a2 } from "variable"; export { a as a3 } from "interface-variable"; export { a as a4 } from "module"; @@ -190,13 +190,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. export { a as a8 } from "function-module"; export { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. export { a as a0 } from "class-module"; // export-star diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt index 96d2f55ed27..1c19b4c3104 100644 --- a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. ==== tests/cases/compiler/a.ts (0 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript import ==== tests/cases/compiler/main.ts (1 errors) ==== import * as a from "./a"; ~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. a; diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt index ee3e9cfff17..4aa467f8b6a 100644 --- a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. -tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'allowSyntheticDefaultImports' flag and using a default import. +tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'allowSyntheticDefaultImports' flag and using a default import. ==== tests/cases/compiler/a.ts (1 errors) ==== @@ -11,7 +11,7 @@ tests/cases/compiler/main.ts(1,20): error TS2497: When writing ECMAScript import ==== tests/cases/compiler/main.ts (1 errors) ==== import * as a from "./a"; ~~~~~ -!!! error TS2497: When writing ECMAScript imports, callable 'export ='-style modules can only be imported by turning on the 'allowSyntheticDefaultImports' flag and using a default import. +!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'allowSyntheticDefaultImports' flag and using a default import. a; From 945eed8d9bfd8fd5c2c218c6cb92720bef61e971 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Tue, 8 Jan 2019 10:54:08 +0200 Subject: [PATCH 05/22] PR feedback: change error #2497 message --- src/compiler/checker.ts | 2 +- src/compiler/diagnosticMessages.json | 2 +- .../es6ExportEqualsInterop.errors.txt | 36 +++++++++---------- ...EqualsExportModuleCommonJsError.errors.txt | 4 +-- ...rtEqualsExportModuleEs2015Error.errors.txt | 4 +-- 5 files changed, 24 insertions(+), 24 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d213e4e01bf..061a6110afc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2415,7 +2415,7 @@ namespace ts { ? "allowSyntheticDefaultImports" : "esModuleInterop"; - error(referencingLocation, Diagnostics.This_module_can_only_be_imported_with_ECMAScript_imports_by_turning_on_the_0_flag_and_using_a_default_import, compilerOptionName); + error(referencingLocation, Diagnostics.This_module_can_only_be_referenced_with_ECMAScript_imports_Slashexports_by_turning_on_the_0_flag_and_referencing_its_default_export, compilerOptionName); return symbol; } diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index cccb3dcb983..136e601dbe8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -1776,7 +1776,7 @@ "category": "Error", "code": 2496 }, - "This module can only be imported with ECMAScript imports by turning on the '{0}' flag and using a default import.": { + "This module can only be referenced with ECMAScript imports/exports by turning on the '{0}' flag and referencing its default export.": { "category": "Error", "code": 2497 }, diff --git a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt index 986aae2245f..5b8e83b3cca 100644 --- a/tests/baselines/reference/es6ExportEqualsInterop.errors.txt +++ b/tests/baselines/reference/es6ExportEqualsInterop.errors.txt @@ -11,24 +11,24 @@ tests/cases/compiler/main.ts(33,8): error TS1192: Module '"function"' has no def tests/cases/compiler/main.ts(34,8): error TS1192: Module '"function-module"' has no default export. tests/cases/compiler/main.ts(35,8): error TS1192: Module '"class"' has no default export. tests/cases/compiler/main.ts(36,8): error TS1192: Module '"class-module"' has no default export. -tests/cases/compiler/main.ts(39,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. -tests/cases/compiler/main.ts(45,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. -tests/cases/compiler/main.ts(47,21): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(39,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. +tests/cases/compiler/main.ts(45,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. +tests/cases/compiler/main.ts(47,21): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(50,1): error TS2693: 'y1' only refers to a type, but is being used as a value here. tests/cases/compiler/main.ts(56,4): error TS2339: Property 'a' does not exist on type '() => any'. tests/cases/compiler/main.ts(58,4): error TS2339: Property 'a' does not exist on type 'typeof Foo'. tests/cases/compiler/main.ts(62,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(62,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(62,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(68,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(68,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(68,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(70,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(70,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(70,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(85,10): error TS2305: Module '"interface"' has no exported member 'a'. -tests/cases/compiler/main.ts(85,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(85,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(91,10): error TS2305: Module '"function"' has no exported member 'a'. -tests/cases/compiler/main.ts(91,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(91,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(93,10): error TS2305: Module '"class"' has no exported member 'a'. -tests/cases/compiler/main.ts(93,25): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(93,25): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. tests/cases/compiler/main.ts(97,15): error TS2498: Module '"interface"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(98,15): error TS2498: Module '"variable"' uses 'export =' and cannot be used with 'export *'. tests/cases/compiler/main.ts(99,15): error TS2498: Module '"interface-variable"' uses 'export =' and cannot be used with 'export *'. @@ -108,7 +108,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses // namespace import import * as y1 from "interface"; ~~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import * as y2 from "variable"; import * as y3 from "interface-variable"; import * as y4 from "module"; @@ -116,11 +116,11 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses import * as y6 from "variable-module"; import * as y7 from "function"; ~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import * as y8 from "function-module"; import * as y9 from "class"; ~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import * as y0 from "class-module"; y1.a; @@ -145,7 +145,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import { a as a2 } from "variable"; import { a as a3 } from "interface-variable"; import { a as a4 } from "module"; @@ -155,13 +155,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import { a as a8 } from "function-module"; import { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. import { a as a0 } from "class-module"; a1; @@ -180,7 +180,7 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"interface"' has no exported member 'a'. ~~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. export { a as a2 } from "variable"; export { a as a3 } from "interface-variable"; export { a as a4 } from "module"; @@ -190,13 +190,13 @@ tests/cases/compiler/main.ts(106,15): error TS2498: Module '"class-module"' uses ~ !!! error TS2305: Module '"function"' has no exported member 'a'. ~~~~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. export { a as a8 } from "function-module"; export { a as a9 } from "class"; ~ !!! error TS2305: Module '"class"' has no exported member 'a'. ~~~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. export { a as a0 } from "class-module"; // export-star diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt index 1c19b4c3104..3d8301d3ca1 100644 --- a/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt +++ b/tests/baselines/reference/es6ImportEqualsExportModuleCommonJsError.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. ==== tests/cases/compiler/a.ts (0 errors) ==== @@ -8,7 +8,7 @@ tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be import ==== tests/cases/compiler/main.ts (1 errors) ==== import * as a from "./a"; ~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'esModuleInterop' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'esModuleInterop' flag and referencing its default export. a; diff --git a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt index 4aa467f8b6a..94c05e068f5 100644 --- a/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt +++ b/tests/baselines/reference/es6ImportEqualsExportModuleEs2015Error.errors.txt @@ -1,5 +1,5 @@ tests/cases/compiler/a.ts(2,1): error TS1203: Export assignment cannot be used when targeting ECMAScript modules. Consider using 'export default' or another module format instead. -tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be imported with ECMAScript imports by turning on the 'allowSyntheticDefaultImports' flag and using a default import. +tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export. ==== tests/cases/compiler/a.ts (1 errors) ==== @@ -11,7 +11,7 @@ tests/cases/compiler/main.ts(1,20): error TS2497: This module can only be import ==== tests/cases/compiler/main.ts (1 errors) ==== import * as a from "./a"; ~~~~~ -!!! error TS2497: This module can only be imported with ECMAScript imports by turning on the 'allowSyntheticDefaultImports' flag and using a default import. +!!! error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export. a; From 46482e14a46bfe1f5fb27255369ccd378aa41da9 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Tue, 8 Jan 2019 16:21:46 -0800 Subject: [PATCH 06/22] Verify that completion with new identifier location returns isNewIdentifierLocation: true Fixes #24009 Signed-off-by: Sheetal Nandi --- completionAtDottedNamespace.ts | 5 +++++ src/services/completions.ts | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 completionAtDottedNamespace.ts diff --git a/completionAtDottedNamespace.ts b/completionAtDottedNamespace.ts new file mode 100644 index 00000000000..cbf16435a91 --- /dev/null +++ b/completionAtDottedNamespace.ts @@ -0,0 +1,5 @@ +/// + +////namespace wwer./**/w + +verify.completions({ marker: "", exact: [], isNewIdentifierLocation: true }); diff --git a/src/services/completions.ts b/src/services/completions.ts index bbcee4dd47e..8203b66549b 100644 --- a/src/services/completions.ts +++ b/src/services/completions.ts @@ -104,7 +104,7 @@ namespace ts.Completions { getJSCompletionEntries(sourceFile, location!.pos, uniqueNames, compilerOptions.target!, entries); // TODO: GH#18217 } else { - if ((!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { + if (!isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === KeywordCompletionFilters.None) { return undefined; } From 3f5c0b81a3b641d14c13bd27187f44ff637c270a Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 9 Jan 2019 10:28:53 -0800 Subject: [PATCH 07/22] Fix existing test --- tests/cases/fourslash/completionListBuilderLocations_Modules.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/cases/fourslash/completionListBuilderLocations_Modules.ts b/tests/cases/fourslash/completionListBuilderLocations_Modules.ts index a98d65e255d..29530ccbdef 100644 --- a/tests/cases/fourslash/completionListBuilderLocations_Modules.ts +++ b/tests/cases/fourslash/completionListBuilderLocations_Modules.ts @@ -7,5 +7,5 @@ verify.completions( { marker: "moduleName1", exact: completion.globals, isNewIdentifierLocation: true }, - { marker: "moduleName2", exact: undefined }, + { marker: "moduleName2", exact: [], isNewIdentifierLocation: true }, ); From b52a7fc3eaea93574626b8cf5e47f205dae2a428 Mon Sep 17 00:00:00 2001 From: Klaus Meinhardt Date: Wed, 9 Jan 2019 19:35:22 +0100 Subject: [PATCH 08/22] Exclude JSDoc @extends from 'super()' checks (#29308) * Exclude JSDoc @extends from 'super()' checks This fixes a similar problem as #29244 where JSDoc `@extends` * fix check 'super can only be referenced in a derived class' --- src/compiler/checker.ts | 6 ++-- ...ckSuperCallBeforeThisAccessing9.errors.txt | 22 ++++++++++++ ...checkSuperCallBeforeThisAccessing9.symbols | 31 ++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.types | 35 +++++++++++++++++++ .../checkSuperCallBeforeThisAccessing9.ts | 21 +++++++++++ 5 files changed, 112 insertions(+), 3 deletions(-) create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols create mode 100644 tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types create mode 100644 tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 86822e24878..41f4d8bef68 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -16625,7 +16625,7 @@ namespace ts { function checkThisBeforeSuper(node: Node, container: Node, diagnosticMessage: DiagnosticMessage) { const containingClassDecl = container.parent; - const baseTypeNode = getEffectiveBaseTypeNode(containingClassDecl); + const baseTypeNode = getClassExtendsHeritageElement(containingClassDecl); // If a containing class does not have extends clause or the class extends null // skip checking whether super statement is called before "this" accessing. @@ -16974,7 +16974,7 @@ namespace ts { // at this point the only legal case for parent is ClassLikeDeclaration const classLikeDeclaration = container.parent; - if (!getEffectiveBaseTypeNode(classLikeDeclaration)) { + if (!getClassExtendsHeritageElement(classLikeDeclaration)) { error(node, Diagnostics.super_can_only_be_referenced_in_a_derived_class); return errorType; } @@ -23575,7 +23575,7 @@ namespace ts { // Constructors of classes with no extends clause may not contain super calls, whereas // constructors of derived classes must contain at least one super call somewhere in their function body. const containingClassDecl = node.parent; - if (getEffectiveBaseTypeNode(containingClassDecl)) { + if (getClassExtendsHeritageElement(containingClassDecl)) { captureLexicalThis(node.parent, containingClassDecl); const classExtendsNull = classDeclarationExtendsNull(containingClassDecl); const superCall = getSuperCallInConstructor(node); diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt new file mode 100644 index 00000000000..5d67f88c847 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.errors.txt @@ -0,0 +1,22 @@ +tests/cases/compiler/noSuperInJSDocExtends.js(14,9): error TS2335: 'super' can only be referenced in a derived class. + + +==== tests/cases/compiler/noSuperInJSDocExtends.js (1 errors) ==== + class Based { } + /** @extends {Based} */ + class Derived { + constructor() { + this; + this.x = 10; + var that = this; + } + } + + /** @extends {Based} */ + class Derived2 { + constructor() { + super(); + ~~~~~ +!!! error TS2335: 'super' can only be referenced in a derived class. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols new file mode 100644 index 00000000000..f900a4986eb --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.symbols @@ -0,0 +1,31 @@ +=== tests/cases/compiler/noSuperInJSDocExtends.js === +class Based { } +>Based : Symbol(Based, Decl(noSuperInJSDocExtends.js, 0, 0)) + +/** @extends {Based} */ +class Derived { +>Derived : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + + constructor() { + this; +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + + this.x = 10; +>this.x : Symbol(Derived.x, Decl(noSuperInJSDocExtends.js, 4, 13)) +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) +>x : Symbol(Derived.x, Decl(noSuperInJSDocExtends.js, 4, 13)) + + var that = this; +>that : Symbol(that, Decl(noSuperInJSDocExtends.js, 6, 11)) +>this : Symbol(Derived, Decl(noSuperInJSDocExtends.js, 0, 15)) + } +} + +/** @extends {Based} */ +class Derived2 { +>Derived2 : Symbol(Derived2, Decl(noSuperInJSDocExtends.js, 8, 1)) + + constructor() { + super(); + } +} diff --git a/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types new file mode 100644 index 00000000000..577256400b2 --- /dev/null +++ b/tests/baselines/reference/checkSuperCallBeforeThisAccessing9.types @@ -0,0 +1,35 @@ +=== tests/cases/compiler/noSuperInJSDocExtends.js === +class Based { } +>Based : Based + +/** @extends {Based} */ +class Derived { +>Derived : Derived + + constructor() { + this; +>this : this + + this.x = 10; +>this.x = 10 : 10 +>this.x : number +>this : this +>x : number +>10 : 10 + + var that = this; +>that : this +>this : this + } +} + +/** @extends {Based} */ +class Derived2 { +>Derived2 : Derived2 + + constructor() { + super(); +>super() : void +>super : any + } +} diff --git a/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts b/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts new file mode 100644 index 00000000000..a6b7102b2a5 --- /dev/null +++ b/tests/cases/compiler/checkSuperCallBeforeThisAccessing9.ts @@ -0,0 +1,21 @@ +// @allowJs: true +// @checkJs: true +// @noEmit: true + +// @filename: noSuperInJSDocExtends.js +class Based { } +/** @extends {Based} */ +class Derived { + constructor() { + this; + this.x = 10; + var that = this; + } +} + +/** @extends {Based} */ +class Derived2 { + constructor() { + super(); + } +} \ No newline at end of file From d0aff9bdcd95ee5ed260a6ab21137e9e220c9895 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Wed, 9 Jan 2019 14:23:57 -0800 Subject: [PATCH 09/22] Fix crash (#29333) --- src/compiler/transformers/ts.ts | 1 + ...decoratorWithNegativeLiteralTypeNoCrash.js | 28 +++++++++++++++++++ ...atorWithNegativeLiteralTypeNoCrash.symbols | 15 ++++++++++ ...oratorWithNegativeLiteralTypeNoCrash.types | 19 +++++++++++++ ...decoratorWithNegativeLiteralTypeNoCrash.ts | 8 ++++++ 5 files changed, 71 insertions(+) create mode 100644 tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.js create mode 100644 tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.symbols create mode 100644 tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.types create mode 100644 tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 700c0c8af25..a22c6df8d06 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1898,6 +1898,7 @@ namespace ts { case SyntaxKind.StringLiteral: return createIdentifier("String"); + case SyntaxKind.PrefixUnaryExpression: case SyntaxKind.NumericLiteral: return createIdentifier("Number"); diff --git a/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.js b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.js new file mode 100644 index 00000000000..57b548cdf99 --- /dev/null +++ b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.js @@ -0,0 +1,28 @@ +//// [decoratorWithNegativeLiteralTypeNoCrash.ts] +class A { + @decorator + public field1: -1 = -1; +} +function decorator(target: any, field: any) {} + +//// [decoratorWithNegativeLiteralTypeNoCrash.js] +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var A = /** @class */ (function () { + function A() { + this.field1 = -1; + } + __decorate([ + decorator, + __metadata("design:type", Number) + ], A.prototype, "field1", void 0); + return A; +}()); +function decorator(target, field) { } diff --git a/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.symbols b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.symbols new file mode 100644 index 00000000000..e89854249a0 --- /dev/null +++ b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.symbols @@ -0,0 +1,15 @@ +=== tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts === +class A { +>A : Symbol(A, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 0, 0)) + + @decorator +>decorator : Symbol(decorator, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 3, 1)) + + public field1: -1 = -1; +>field1 : Symbol(A.field1, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 0, 9)) +} +function decorator(target: any, field: any) {} +>decorator : Symbol(decorator, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 3, 1)) +>target : Symbol(target, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 4, 19)) +>field : Symbol(field, Decl(decoratorWithNegativeLiteralTypeNoCrash.ts, 4, 31)) + diff --git a/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.types b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.types new file mode 100644 index 00000000000..45f4ff03451 --- /dev/null +++ b/tests/baselines/reference/decoratorWithNegativeLiteralTypeNoCrash.types @@ -0,0 +1,19 @@ +=== tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts === +class A { +>A : A + + @decorator +>decorator : (target: any, field: any) => void + + public field1: -1 = -1; +>field1 : -1 +>-1 : -1 +>1 : 1 +>-1 : -1 +>1 : 1 +} +function decorator(target: any, field: any) {} +>decorator : (target: any, field: any) => void +>target : any +>field : any + diff --git a/tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts b/tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts new file mode 100644 index 00000000000..720b68a7c16 --- /dev/null +++ b/tests/cases/compiler/decoratorWithNegativeLiteralTypeNoCrash.ts @@ -0,0 +1,8 @@ +// @target: es5 +// @experimentalDecorators: true +// @emitDecoratorMetadata: true +class A { + @decorator + public field1: -1 = -1; +} +function decorator(target: any, field: any) {} \ No newline at end of file From 7174e6a39d9e1238ab1c76efd055bac1deb58d1d Mon Sep 17 00:00:00 2001 From: TypeScript Bot Date: Wed, 9 Jan 2019 15:50:50 -0800 Subject: [PATCH 10/22] Update user baselines (#29336) --- tests/baselines/reference/user/puppeteer.log | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/baselines/reference/user/puppeteer.log b/tests/baselines/reference/user/puppeteer.log index 9d6c2b26482..30875ee5560 100644 --- a/tests/baselines/reference/user/puppeteer.log +++ b/tests/baselines/reference/user/puppeteer.log @@ -62,9 +62,9 @@ lib/Page.js(936,3): error TS2322: Type '{ width: number; height: number; }' is n lib/Page.js(937,3): error TS2322: Type '{ width: number; height: number; }' is not assignable to type 'string'. lib/Page.js(938,3): error TS2322: Type '{ width: number; height: number; }' is not assignable to type 'string'. lib/TaskQueue.js(7,14): error TS7014: Function type, which lacks return-type annotation, implicitly has an 'any' return type. -lib/externs.d.ts(3,29): error TS2497: Module '"/puppeteer/puppeteer/lib/Target"' resolves to a non-module entity and cannot be imported using this construct. -lib/externs.d.ts(5,32): error TS2497: Module '"/puppeteer/puppeteer/lib/TaskQueue"' resolves to a non-module entity and cannot be imported using this construct. -lib/externs.d.ts(9,37): error TS2497: Module '"/puppeteer/puppeteer/lib/ElementHandle"' resolves to a non-module entity and cannot be imported using this construct. +lib/externs.d.ts(3,29): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export. +lib/externs.d.ts(5,32): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export. +lib/externs.d.ts(9,37): error TS2497: This module can only be referenced with ECMAScript imports/exports by turning on the 'allowSyntheticDefaultImports' flag and referencing its default export. lib/externs.d.ts(16,26): error TS2503: Cannot find namespace 'Protocol'. lib/externs.d.ts(16,69): error TS2503: Cannot find namespace 'Protocol'. lib/externs.d.ts(17,28): error TS2503: Cannot find namespace 'Protocol'. From 70148a4b5514175f7bd3ee51cfa208e6d2c7a95d Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 9 Jan 2019 16:10:28 -0800 Subject: [PATCH 11/22] Improve logic that determines when to resolve conditional types --- src/compiler/checker.ts | 134 ++++++++++++++++++++-------------------- src/compiler/types.ts | 4 +- 2 files changed, 71 insertions(+), 67 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index de44e8bb37c..44cc7478e13 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -444,10 +444,10 @@ namespace ts { const circularConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); const resolvingDefaultType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined); - const markerSuperType = createType(TypeFlags.TypeParameter); - const markerSubType = createType(TypeFlags.TypeParameter); + const markerSuperType = createTypeParameter(); + const markerSubType = createTypeParameter(); markerSubType.constraint = markerSuperType; - const markerOtherType = createType(TypeFlags.TypeParameter); + const markerOtherType = createTypeParameter(); const noTypePredicate = createIdentifierTypePredicate("<>", 0, anyType); @@ -663,7 +663,6 @@ namespace ts { const subtypeRelation = createMap(); const assignableRelation = createMap(); - const definitelyAssignableRelation = createMap(); const comparableRelation = createMap(); const identityRelation = createMap(); const enumRelation = createMap(); @@ -2745,6 +2744,12 @@ namespace ts { return getUnionType(arrayFrom(typeofEQFacts.keys(), getLiteralType)); } + function createTypeParameter(symbol?: Symbol) { + const type = createType(TypeFlags.TypeParameter); + if (symbol) type.symbol = symbol; + return type; + } + // A reserved member name starts with two underscores, but the third character cannot be an underscore // or the @ symbol. A third underscore indicates an escaped form of an identifer that started // with at least two underscores. The @ character indicates that the name is denoted by a well known ES @@ -6085,9 +6090,8 @@ namespace ts { (type).instantiations.set(getTypeListId(type.typeParameters), type); (type).target = type; (type).typeArguments = type.typeParameters; - type.thisType = createType(TypeFlags.TypeParameter); + type.thisType = createTypeParameter(symbol); type.thisType.isThisType = true; - type.thisType.symbol = symbol; type.thisType.constraint = type; } } @@ -6228,20 +6232,12 @@ namespace ts { function getDeclaredTypeOfTypeParameter(symbol: Symbol): TypeParameter { const links = getSymbolLinks(symbol); - if (!links.declaredType) { - const type = createType(TypeFlags.TypeParameter); - type.symbol = symbol; - links.declaredType = type; - } - return links.declaredType; + return links.declaredType || (links.declaredType = createTypeParameter(symbol)); } function getDeclaredTypeOfAlias(symbol: Symbol): Type { const links = getSymbolLinks(symbol); - if (!links.declaredType) { - links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol)); - } - return links.declaredType; + return links.declaredType || (links.declaredType = getDeclaredTypeOfSymbol(resolveAlias(symbol))); } function getDeclaredTypeOfSymbol(symbol: Symbol): Type { @@ -7413,7 +7409,7 @@ namespace ts { if (type.root.isDistributive) { const simplified = getSimplifiedType(type.checkType); const constraint = simplified === type.checkType ? getConstraintOfType(simplified) : simplified; - if (constraint) { + if (constraint && constraint !== type.checkType) { const mapper = makeUnaryTypeMapper(type.root.checkType, constraint); const instantiated = getConditionalTypeInstantiation(type, combineTypeMappers(mapper, type.mapper)); if (!(instantiated.flags & TypeFlags.Never)) { @@ -9049,7 +9045,7 @@ namespace ts { if (arity) { typeParameters = new Array(arity); for (let i = 0; i < arity; i++) { - const typeParameter = typeParameters[i] = createType(TypeFlags.TypeParameter); + const typeParameter = typeParameters[i] = createTypeParameter(); if (i < maxLength) { const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0), "" + i as __String); property.type = typeParameter; @@ -9070,7 +9066,7 @@ namespace ts { type.instantiations.set(getTypeListId(type.typeParameters), type); type.target = type; type.typeArguments = type.typeParameters; - type.thisType = createType(TypeFlags.TypeParameter); + type.thisType = createTypeParameter(); type.thisType.isThisType = true; type.thisType.constraint = type; type.declaredProperties = properties; @@ -9971,7 +9967,7 @@ namespace ts { if (checkType === wildcardType || extendsType === wildcardType) { return wildcardType; } - const checkTypeInstantiable = maybeTypeOfKind(checkType, TypeFlags.Instantiable); + const checkTypeInstantiable = maybeTypeOfKind(checkType, TypeFlags.Instantiable | TypeFlags.GenericMappedType); let combinedMapper: TypeMapper | undefined; if (root.inferTypeParameters) { const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None); @@ -9986,7 +9982,7 @@ namespace ts { // Instantiate the extends type including inferences for 'infer T' type parameters const inferredExtendsType = combinedMapper ? instantiateType(root.extendsType, combinedMapper) : extendsType; // We attempt to resolve the conditional type only when the check and extends types are non-generic - if (!checkTypeInstantiable && !maybeTypeOfKind(inferredExtendsType, TypeFlags.Instantiable)) { + if (!checkTypeInstantiable && !maybeTypeOfKind(inferredExtendsType, TypeFlags.Instantiable | TypeFlags.GenericMappedType)) { if (inferredExtendsType.flags & TypeFlags.AnyOrUnknown) { return instantiateType(root.trueType, mapper); } @@ -9998,14 +9994,15 @@ namespace ts { // types with type parameters mapped to the wildcard type, the most permissive instantiations // possible (the wildcard type is assignable to and from all types). If those are not related, // then no instatiations will be and we can just return the false branch type. - if (!isTypeAssignableTo(getWildcardInstantiation(checkType), getWildcardInstantiation(inferredExtendsType))) { + if (!isTypeAssignableTo(getPermissiveInstantiation(checkType), getPermissiveInstantiation(inferredExtendsType))) { return instantiateType(root.falseType, mapper); } - // Return trueType for a definitely true extends check. The definitely assignable relation excludes - // type variable constraints from consideration. Without the definitely assignable relation, the type + // Return trueType for a definitely true extends check. We check instantiations of the two + // types with type parameters mapped to their restrictive form, i.e. a form of the type parameter + // that has no constraint. This ensures that, for example, the type // type Foo = T extends { x: string } ? string : number - // would immediately resolve to 'string' instead of being deferred. - if (checkTypeRelatedTo(checkType, inferredExtendsType, definitelyAssignableRelation, /*errorNode*/ undefined)) { + // doesn't immediately resolve to 'string' instead of being deferred. + if (isTypeAssignableTo(getRestrictiveInstantiation(checkType), getRestrictiveInstantiation(inferredExtendsType))) { return instantiateType(root.trueType, combinedMapper || mapper); } } @@ -10611,13 +10608,20 @@ namespace ts { return t => t === source ? target : baseMapper(t); } - function wildcardMapper(type: Type) { + function permissiveMapper(type: Type) { return type.flags & TypeFlags.TypeParameter ? wildcardType : type; } + function getRestrictiveTypeParameter(tp: TypeParameter) { + return !tp.constraint ? tp : tp.restrictiveInstantiation || (tp.restrictiveInstantiation = createTypeParameter(tp.symbol)); + } + + function restrictiveMapper(type: Type) { + return type.flags & TypeFlags.TypeParameter ? getRestrictiveTypeParameter(type) : type; + } + function cloneTypeParameter(typeParameter: TypeParameter): TypeParameter { - const result = createType(TypeFlags.TypeParameter); - result.symbol = typeParameter.symbol; + const result = createTypeParameter(typeParameter.symbol); result.target = typeParameter; return result; } @@ -10969,9 +10973,14 @@ namespace ts { return type; } - function getWildcardInstantiation(type: Type) { + function getPermissiveInstantiation(type: Type) { return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type : - type.wildcardInstantiation || (type.wildcardInstantiation = instantiateType(type, wildcardMapper)); + type.permissiveInstantiation || (type.permissiveInstantiation = instantiateType(type, permissiveMapper)); + } + + function getRestrictiveInstantiation(type: Type) { + return type.flags & (TypeFlags.Primitive | TypeFlags.AnyOrUnknown | TypeFlags.Never) ? type : + type.restrictiveInstantiation || (type.restrictiveInstantiation = instantiateType(type, restrictiveMapper)); } function instantiateIndexInfo(info: IndexInfo | undefined, mapper: TypeMapper): IndexInfo | undefined { @@ -11644,7 +11653,7 @@ namespace ts { if (s & TypeFlags.Null && (!strictNullChecks || t & TypeFlags.Null)) return true; if (s & TypeFlags.Object && t & TypeFlags.NonPrimitive) return true; if (s & TypeFlags.UniqueESSymbol || t & TypeFlags.UniqueESSymbol) return false; - if (relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) { + if (relation === assignableRelation || relation === comparableRelation) { if (s & TypeFlags.Any) return true; // Type number or any numeric literal type is assignable to any numeric enum type or any // numeric enum literal type. This rule exists for backwards compatibility reasons because @@ -11836,7 +11845,7 @@ namespace ts { target = (target).regularType; } if (source.flags & TypeFlags.Substitution) { - source = relation === definitelyAssignableRelation ? (source).typeVariable : (source).substitute; + source = (source).substitute; } if (target.flags & TypeFlags.Substitution) { target = (target).typeVariable; @@ -12022,7 +12031,7 @@ namespace ts { } if (isExcessPropertyCheckTarget(target)) { const isComparingJsxAttributes = !!(getObjectFlags(source) & ObjectFlags.JsxAttributes); - if ((relation === assignableRelation || relation === definitelyAssignableRelation || relation === comparableRelation) && + if ((relation === assignableRelation || relation === comparableRelation) && (isTypeSubsetOf(globalObjectType, target) || (!isComparingJsxAttributes && isEmptyObjectType(target)))) { return false; } @@ -12425,24 +12434,22 @@ namespace ts { } // A type S is assignable to keyof T if S is assignable to keyof C, where C is the // simplified form of T or, if T doesn't simplify, the constraint of T. - if (relation !== definitelyAssignableRelation) { - const simplified = getSimplifiedType((target).type); - const constraint = simplified !== (target).type ? simplified : getConstraintOfType((target).type); - if (constraint) { - // We require Ternary.True here such that circular constraints don't cause - // false positives. For example, given 'T extends { [K in keyof T]: string }', - // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when - // related to other types. - if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors) === Ternary.True) { - return Ternary.True; - } + const simplified = getSimplifiedType((target).type); + const constraint = simplified !== (target).type ? simplified : getConstraintOfType((target).type); + if (constraint) { + // We require Ternary.True here such that circular constraints don't cause + // false positives. For example, given 'T extends { [K in keyof T]: string }', + // 'keyof T' has itself as its constraint and produces a Ternary.Maybe when + // related to other types. + if (isRelatedTo(source, getIndexType(constraint, (target as IndexType).stringsOnly), reportErrors) === Ternary.True) { + return Ternary.True; } } } else if (target.flags & TypeFlags.IndexedAccess) { // A type S is related to a type T[K], where T and K aren't both type variables, if S is related to C, // where C is the base constraint of T[K] - if (relation !== identityRelation && relation !== definitelyAssignableRelation && + if (relation !== identityRelation && !(isGenericObjectType((target).objectType) && isGenericIndexType((target).indexType))) { const constraint = getBaseConstraintOfType(target); if (constraint && constraint !== target) { @@ -12485,26 +12492,24 @@ namespace ts { return result; } } - if (relation !== definitelyAssignableRelation) { - const constraint = getConstraintOfType(source); - if (!constraint || (source.flags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) { - // A type variable with no constraint is not related to the non-primitive object type. - if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) { - errorInfo = saveErrorInfo; - return result; - } - } - // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed - else if (result = isRelatedTo(constraint, target, /*reportErrors*/ false, /*headMessage*/ undefined, isIntersectionConstituent)) { - errorInfo = saveErrorInfo; - return result; - } - // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example - else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, reportErrors, /*headMessage*/ undefined, isIntersectionConstituent)) { + const constraint = getConstraintOfType(source); + if (!constraint || (source.flags & TypeFlags.TypeParameter && constraint.flags & TypeFlags.Any)) { + // A type variable with no constraint is not related to the non-primitive object type. + if (result = isRelatedTo(emptyObjectType, extractTypesOfKind(target, ~TypeFlags.NonPrimitive))) { errorInfo = saveErrorInfo; return result; } } + // hi-speed no-this-instantiation check (less accurate, but avoids costly `this`-instantiation when the constraint will suffice), see #28231 for report on why this is needed + else if (result = isRelatedTo(constraint, target, /*reportErrors*/ false, /*headMessage*/ undefined, isIntersectionConstituent)) { + errorInfo = saveErrorInfo; + return result; + } + // slower, fuller, this-instantiated check (necessary when comparing raw `this` types from base classes), see `subclassWithPolymorphicThisIsAssignable.ts` test for example + else if (result = isRelatedTo(getTypeWithThisArgument(constraint, source), target, reportErrors, /*headMessage*/ undefined, isIntersectionConstituent)) { + errorInfo = saveErrorInfo; + return result; + } } else if (source.flags & TypeFlags.Index) { if (result = isRelatedTo(keyofConstraintType, target, reportErrors)) { @@ -12528,7 +12533,7 @@ namespace ts { } } } - else if (relation !== definitelyAssignableRelation) { + else { const distributiveConstraint = getConstraintOfDistributiveConditionalType(source); if (distributiveConstraint) { if (result = isRelatedTo(distributiveConstraint, target, reportErrors)) { @@ -12559,9 +12564,6 @@ namespace ts { } return Ternary.False; } - if (relation === definitelyAssignableRelation && isGenericMappedType(source)) { - return Ternary.False; - } const sourceIsPrimitive = !!(source.flags & TypeFlags.Primitive); if (relation !== identityRelation) { source = getApparentType(source); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 5c42d3eb510..e46a3d70403 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3916,7 +3916,9 @@ namespace ts { aliasTypeArguments?: ReadonlyArray; // Alias type arguments (if any) /* @internal */ aliasTypeArgumentsContainsMarker?: boolean; // Alias type arguments (if any) /* @internal */ - wildcardInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type + permissiveInstantiation?: Type; // Instantiation with type parameters mapped to wildcard type + /* @internal */ + restrictiveInstantiation?: Type; // Instantiation with type parameters mapped to unconstrained form /* @internal */ immediateBaseConstraint?: Type; // Immediate base constraint cache } From 9fda7014cac88cd0885af42fccfb113ef289aadc Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 9 Jan 2019 16:16:24 -0800 Subject: [PATCH 12/22] Add regression tests --- .../conformance/types/conditional/conditionalTypes1.ts | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/cases/conformance/types/conditional/conditionalTypes1.ts b/tests/cases/conformance/types/conditional/conditionalTypes1.ts index f5c67f678eb..2e8690a228b 100644 --- a/tests/cases/conformance/types/conditional/conditionalTypes1.ts +++ b/tests/cases/conformance/types/conditional/conditionalTypes1.ts @@ -353,3 +353,11 @@ declare function assign(o: T, a: RecursivePartial): void; var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]} assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) + +// Repros from #23843 + +type Weird1 = ((a: U) => never) extends + ((a: U) => never) ? never : never; + +type Weird2 = ((a: U) => U) extends + ((a: U) => infer T) ? T : never; From 0c1c97e5013e957da26e15390e5268cb63c1884e Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Wed, 9 Jan 2019 16:16:31 -0800 Subject: [PATCH 13/22] Accept new baselines --- .../reference/conditionalTypes1.errors.txt | 8 ++++++ .../baselines/reference/conditionalTypes1.js | 10 +++++++ .../reference/conditionalTypes1.symbols | 27 +++++++++++++++++++ .../reference/conditionalTypes1.types | 18 +++++++++++++ 4 files changed, 63 insertions(+) diff --git a/tests/baselines/reference/conditionalTypes1.errors.txt b/tests/baselines/reference/conditionalTypes1.errors.txt index 8bf05c043ce..62239eca7b8 100644 --- a/tests/baselines/reference/conditionalTypes1.errors.txt +++ b/tests/baselines/reference/conditionalTypes1.errors.txt @@ -471,4 +471,12 @@ tests/cases/conformance/types/conditional/conditionalTypes1.ts(288,43): error TS var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]} assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) + + // Repros from #23843 + + type Weird1 = ((a: U) => never) extends + ((a: U) => never) ? never : never; + + type Weird2 = ((a: U) => U) extends + ((a: U) => infer T) ? T : never; \ No newline at end of file diff --git a/tests/baselines/reference/conditionalTypes1.js b/tests/baselines/reference/conditionalTypes1.js index 552a80d58a5..7ce19ce17e7 100644 --- a/tests/baselines/reference/conditionalTypes1.js +++ b/tests/baselines/reference/conditionalTypes1.js @@ -351,6 +351,14 @@ declare function assign(o: T, a: RecursivePartial): void; var a = {o: 1, b: 2, c: [{a: 1, c: '213'}]} assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) + +// Repros from #23843 + +type Weird1 = ((a: U) => never) extends + ((a: U) => never) ? never : never; + +type Weird2 = ((a: U) => U) extends + ((a: U) => infer T) ? T : never; //// [conditionalTypes1.js] @@ -715,3 +723,5 @@ declare var a: { c: string; }[]; }; +declare type Weird1 = ((a: U) => never) extends ((a: U) => never) ? never : never; +declare type Weird2 = ((a: U) => U) extends ((a: U) => infer T) ? T : never; diff --git a/tests/baselines/reference/conditionalTypes1.symbols b/tests/baselines/reference/conditionalTypes1.symbols index 19f0ae83890..e5c6ae3d6c7 100644 --- a/tests/baselines/reference/conditionalTypes1.symbols +++ b/tests/baselines/reference/conditionalTypes1.symbols @@ -1371,3 +1371,30 @@ assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) >a : Symbol(a, Decl(conditionalTypes1.ts, 351, 25)) >c : Symbol(c, Decl(conditionalTypes1.ts, 351, 30)) +// Repros from #23843 + +type Weird1 = ((a: U) => never) extends +>Weird1 : Symbol(Weird1, Decl(conditionalTypes1.ts, 351, 46)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 355, 16)) +>a : Symbol(a, Decl(conditionalTypes1.ts, 355, 35)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 355, 16)) + + ((a: U) => never) ? never : never; +>U : Symbol(U, Decl(conditionalTypes1.ts, 356, 6)) +>a : Symbol(a, Decl(conditionalTypes1.ts, 356, 22)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 356, 6)) + +type Weird2 = ((a: U) => U) extends +>Weird2 : Symbol(Weird2, Decl(conditionalTypes1.ts, 356, 54)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 358, 16)) +>a : Symbol(a, Decl(conditionalTypes1.ts, 358, 35)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 358, 16)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 358, 16)) + + ((a: U) => infer T) ? T : never; +>U : Symbol(U, Decl(conditionalTypes1.ts, 359, 6)) +>a : Symbol(a, Decl(conditionalTypes1.ts, 359, 22)) +>U : Symbol(U, Decl(conditionalTypes1.ts, 359, 6)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 359, 36)) +>T : Symbol(T, Decl(conditionalTypes1.ts, 359, 36)) + diff --git a/tests/baselines/reference/conditionalTypes1.types b/tests/baselines/reference/conditionalTypes1.types index 00d1965eea4..08fdb4b2f29 100644 --- a/tests/baselines/reference/conditionalTypes1.types +++ b/tests/baselines/reference/conditionalTypes1.types @@ -1054,3 +1054,21 @@ assign(a, {o: 2, c: {0: {a: 2, c: '213123'}}}) >c : string >'213123' : "213123" +// Repros from #23843 + +type Weird1 = ((a: U) => never) extends +>Weird1 : never +>a : U + + ((a: U) => never) ? never : never; +>true : true +>a : U + +type Weird2 = ((a: U) => U) extends +>Weird2 : boolean +>a : U + + ((a: U) => infer T) ? T : never; +>true : true +>a : U + From 76f444e338218b9496d0c3ee5df7901dfe8dce6a Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 10 Jan 2019 14:45:19 -0800 Subject: [PATCH 14/22] Allow nonnull assertions in references (#29351) --- src/compiler/binder.ts | 2 +- src/compiler/checker.ts | 11 + .../reference/nonNullReferenceMatching.js | 54 ++++ .../nonNullReferenceMatching.symbols | 193 +++++++++++++ .../reference/nonNullReferenceMatching.types | 262 ++++++++++++++++++ .../compiler/nonNullReferenceMatching.ts | 34 +++ 6 files changed, 555 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/nonNullReferenceMatching.js create mode 100644 tests/baselines/reference/nonNullReferenceMatching.symbols create mode 100644 tests/baselines/reference/nonNullReferenceMatching.types create mode 100644 tests/cases/compiler/nonNullReferenceMatching.ts diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7216af4e817..f0e17261810 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -753,7 +753,7 @@ namespace ts { function isNarrowableReference(expr: Expression): boolean { return expr.kind === SyntaxKind.Identifier || expr.kind === SyntaxKind.ThisKeyword || expr.kind === SyntaxKind.SuperKeyword || - isPropertyAccessExpression(expr) && isNarrowableReference(expr.expression) || + (isPropertyAccessExpression(expr) || isNonNullExpression(expr) || isParenthesizedExpression(expr)) && isNarrowableReference(expr.expression) || isElementAccessExpression(expr) && expr.argumentExpression && (isStringLiteral(expr.argumentExpression) || isNumericLiteral(expr.argumentExpression)) && isNarrowableReference(expr.expression); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 92e3b10842b..3bb26e83dd8 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14773,6 +14773,9 @@ namespace ts { return symbol !== unknownSymbol ? (isConstraintPosition(node) ? "@" : "") + getSymbolId(symbol) : undefined; case SyntaxKind.ThisKeyword: return "0"; + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + return getFlowCacheKey((node).expression); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: const propName = getAccessedPropertyName(node); @@ -14785,6 +14788,11 @@ namespace ts { } function isMatchingReference(source: Node, target: Node): boolean { + switch (target.kind) { + case SyntaxKind.ParenthesizedExpression: + case SyntaxKind.NonNullExpression: + return isMatchingReference(source, (target as NonNullExpression | ParenthesizedExpression).expression); + } switch (source.kind) { case SyntaxKind.Identifier: return target.kind === SyntaxKind.Identifier && getResolvedSymbol(source) === getResolvedSymbol(target) || @@ -14794,6 +14802,9 @@ namespace ts { return target.kind === SyntaxKind.ThisKeyword; case SyntaxKind.SuperKeyword: return target.kind === SyntaxKind.SuperKeyword; + case SyntaxKind.NonNullExpression: + case SyntaxKind.ParenthesizedExpression: + return isMatchingReference((source as NonNullExpression | ParenthesizedExpression).expression, target); case SyntaxKind.PropertyAccessExpression: case SyntaxKind.ElementAccessExpression: return isAccessExpression(target) && diff --git a/tests/baselines/reference/nonNullReferenceMatching.js b/tests/baselines/reference/nonNullReferenceMatching.js new file mode 100644 index 00000000000..abb0d5a96db --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.js @@ -0,0 +1,54 @@ +//// [nonNullReferenceMatching.ts] +type ElementRef = (element: HTMLElement | null) => void; + +type ThumbProps = { + elementRef?: ElementRef; +} + +type ComponentProps = { + thumbYProps?: ThumbProps; + thumbXProps: ThumbProps; +} + +class Component { + props!: ComponentProps; + public thumbYElementRef = (ref: HTMLElement | null) => { + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + + typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + + typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + }; +} + +//// [nonNullReferenceMatching.js] +"use strict"; +var Component = /** @class */ (function () { + function Component() { + var _this = this; + this.thumbYElementRef = function (ref) { + typeof _this.props.thumbYProps.elementRef === 'function' && _this.props.thumbYProps.elementRef(ref); + typeof (_this.props.thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref); + typeof ((_this.props).thumbYProps.elementRef) === 'function' && _this.props.thumbYProps.elementRef(ref); + typeof _this.props.thumbXProps.elementRef === 'function' && _this.props.thumbXProps.elementRef(ref); + typeof _this.props.thumbXProps.elementRef === 'function' && (_this.props).thumbXProps.elementRef(ref); + typeof _this.props.thumbXProps.elementRef === 'function' && (_this.props.thumbXProps).elementRef(ref); + typeof _this.props.thumbXProps.elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref); + typeof (_this.props.thumbXProps).elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref); + typeof _this.props.thumbXProps.elementRef === 'function' && ((_this.props).thumbXProps).elementRef(ref); + }; + } + return Component; +}()); diff --git a/tests/baselines/reference/nonNullReferenceMatching.symbols b/tests/baselines/reference/nonNullReferenceMatching.symbols new file mode 100644 index 00000000000..ee9c608cea4 --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.symbols @@ -0,0 +1,193 @@ +=== tests/cases/compiler/nonNullReferenceMatching.ts === +type ElementRef = (element: HTMLElement | null) => void; +>ElementRef : Symbol(ElementRef, Decl(nonNullReferenceMatching.ts, 0, 0)) +>element : Symbol(element, Decl(nonNullReferenceMatching.ts, 0, 19)) +>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + +type ThumbProps = { +>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56)) + + elementRef?: ElementRef; +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ElementRef : Symbol(ElementRef, Decl(nonNullReferenceMatching.ts, 0, 0)) +} + +type ComponentProps = { +>ComponentProps : Symbol(ComponentProps, Decl(nonNullReferenceMatching.ts, 4, 1)) + + thumbYProps?: ThumbProps; +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56)) + + thumbXProps: ThumbProps; +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>ThumbProps : Symbol(ThumbProps, Decl(nonNullReferenceMatching.ts, 0, 56)) +} + +class Component { +>Component : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) + + props!: ComponentProps; +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>ComponentProps : Symbol(ComponentProps, Decl(nonNullReferenceMatching.ts, 4, 1)) + + public thumbYElementRef = (ref: HTMLElement | null) => { +>thumbYElementRef : Symbol(Component.thumbYElementRef, Decl(nonNullReferenceMatching.ts, 12, 27)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) +>HTMLElement : Symbol(HTMLElement, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --)) + + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); +>(this.props).thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props).thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbYProps : Symbol(thumbYProps, Decl(nonNullReferenceMatching.ts, 6, 23)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); +>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); +>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props).thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props).thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); +>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>this.props.thumbXProps.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>(this.props.thumbXProps).elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>this.props!.thumbXProps!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>this.props!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>((this.props)!.thumbXProps)!.elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>(this.props)!.thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>this.props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>this : Symbol(Component, Decl(nonNullReferenceMatching.ts, 9, 1)) +>props : Symbol(Component.props, Decl(nonNullReferenceMatching.ts, 11, 17)) +>thumbXProps : Symbol(thumbXProps, Decl(nonNullReferenceMatching.ts, 7, 29)) +>elementRef : Symbol(elementRef, Decl(nonNullReferenceMatching.ts, 2, 19)) +>ref : Symbol(ref, Decl(nonNullReferenceMatching.ts, 13, 31)) + + }; +} diff --git a/tests/baselines/reference/nonNullReferenceMatching.types b/tests/baselines/reference/nonNullReferenceMatching.types new file mode 100644 index 00000000000..03ef70177c0 --- /dev/null +++ b/tests/baselines/reference/nonNullReferenceMatching.types @@ -0,0 +1,262 @@ +=== tests/cases/compiler/nonNullReferenceMatching.ts === +type ElementRef = (element: HTMLElement | null) => void; +>ElementRef : ElementRef +>element : HTMLElement | null +>null : null + +type ThumbProps = { +>ThumbProps : ThumbProps + + elementRef?: ElementRef; +>elementRef : ElementRef | undefined +} + +type ComponentProps = { +>ComponentProps : ComponentProps + + thumbYProps?: ThumbProps; +>thumbYProps : ThumbProps | undefined + + thumbXProps: ThumbProps; +>thumbXProps : ThumbProps +} + +class Component { +>Component : Component + + props!: ComponentProps; +>props : ComponentProps + + public thumbYElementRef = (ref: HTMLElement | null) => { +>thumbYElementRef : (ref: HTMLElement | null) => void +>(ref: HTMLElement | null) => { typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); } : (ref: HTMLElement | null) => void +>ref : HTMLElement | null +>null : null + + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof this.props.thumbYProps!.elementRef === 'function' : boolean +>typeof this.props.thumbYProps!.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbYProps!.elementRef : ElementRef | undefined +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof (this.props.thumbYProps!.elementRef) === 'function' : boolean +>typeof (this.props.thumbYProps!.elementRef) : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>(this.props.thumbYProps!.elementRef) : ElementRef | undefined +>this.props.thumbYProps!.elementRef : ElementRef | undefined +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); +>typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref) : false | void +>typeof ((this.props).thumbYProps!.elementRef)! === 'function' : boolean +>typeof ((this.props).thumbYProps!.elementRef)! : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>((this.props).thumbYProps!.elementRef)! : ElementRef +>((this.props).thumbYProps!.elementRef) : ElementRef | undefined +>(this.props).thumbYProps!.elementRef : ElementRef | undefined +>(this.props).thumbYProps! : ThumbProps +>(this.props).thumbYProps : ThumbProps | undefined +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbYProps!.elementRef(ref) : void +>this.props.thumbYProps!.elementRef : ElementRef +>this.props.thumbYProps! : ThumbProps +>this.props.thumbYProps : ThumbProps | undefined +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbYProps : ThumbProps | undefined +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>this.props.thumbXProps.elementRef(ref) : void +>this.props.thumbXProps.elementRef : ElementRef +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>(this.props).thumbXProps.elementRef(ref) : void +>(this.props).thumbXProps.elementRef : ElementRef +>(this.props).thumbXProps : ThumbProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>(this.props.thumbXProps).elementRef(ref) : void +>(this.props.thumbXProps).elementRef : ElementRef +>(this.props.thumbXProps) : ThumbProps +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof this.props.thumbXProps.elementRef === 'function' : boolean +>typeof this.props.thumbXProps.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props.thumbXProps.elementRef : ElementRef | undefined +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof (this.props.thumbXProps).elementRef === 'function' : boolean +>typeof (this.props.thumbXProps).elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>(this.props.thumbXProps).elementRef : ElementRef | undefined +>(this.props.thumbXProps) : ThumbProps +>this.props.thumbXProps : ThumbProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); +>typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref) : false | void +>typeof this.props!.thumbXProps!.elementRef === 'function' : boolean +>typeof this.props!.thumbXProps!.elementRef : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function" +>this.props!.thumbXProps!.elementRef : ElementRef | undefined +>this.props!.thumbXProps! : ThumbProps +>this.props!.thumbXProps : ThumbProps +>this.props! : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef | undefined +>'function' : "function" +>((this.props)!.thumbXProps)!.elementRef(ref) : void +>((this.props)!.thumbXProps)!.elementRef : ElementRef +>((this.props)!.thumbXProps)! : ThumbProps +>((this.props)!.thumbXProps) : ThumbProps +>(this.props)!.thumbXProps : ThumbProps +>(this.props)! : ComponentProps +>(this.props) : ComponentProps +>this.props : ComponentProps +>this : this +>props : ComponentProps +>thumbXProps : ThumbProps +>elementRef : ElementRef +>ref : HTMLElement | null + + }; +} diff --git a/tests/cases/compiler/nonNullReferenceMatching.ts b/tests/cases/compiler/nonNullReferenceMatching.ts new file mode 100644 index 00000000000..1295c3ce9a7 --- /dev/null +++ b/tests/cases/compiler/nonNullReferenceMatching.ts @@ -0,0 +1,34 @@ +// @strict: true +type ElementRef = (element: HTMLElement | null) => void; + +type ThumbProps = { + elementRef?: ElementRef; +} + +type ComponentProps = { + thumbYProps?: ThumbProps; + thumbXProps: ThumbProps; +} + +class Component { + props!: ComponentProps; + public thumbYElementRef = (ref: HTMLElement | null) => { + typeof this.props.thumbYProps!.elementRef === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof (this.props.thumbYProps!.elementRef) === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof ((this.props).thumbYProps!.elementRef)! === 'function' && this.props.thumbYProps!.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && this.props.thumbXProps.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props).thumbXProps.elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && (this.props.thumbXProps).elementRef(ref); + + typeof this.props.thumbXProps.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + + typeof (this.props.thumbXProps).elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + + typeof this.props!.thumbXProps!.elementRef === 'function' && ((this.props)!.thumbXProps)!.elementRef(ref); + }; +} \ No newline at end of file From aba0b700b638498a7774003b053074193c890103 Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Thu, 10 Jan 2019 14:48:15 -0800 Subject: [PATCH 15/22] Allow circular umd-merged-with-augmentation refs to resolve to the module as intended (#29335) --- src/compiler/checker.ts | 8 ++++ ...rgedWithGlobalAugmentationIsNotCircular.js | 31 +++++++++++++ ...ithGlobalAugmentationIsNotCircular.symbols | 42 ++++++++++++++++++ ...dWithGlobalAugmentationIsNotCircular.types | 44 +++++++++++++++++++ ...rgedWithGlobalAugmentationIsNotCircular.ts | 26 +++++++++++ 5 files changed, 151 insertions(+) create mode 100644 tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.js create mode 100644 tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.symbols create mode 100644 tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.types create mode 100644 tests/cases/compiler/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3bb26e83dd8..b1f73584c49 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -5431,6 +5431,10 @@ namespace ts { // Handle variable, parameter or property if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) { + // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` + if (symbol.flags & SymbolFlags.ValueModule) { + return getTypeOfFuncClassEnumModule(symbol); + } return errorType; } let type: Type | undefined; @@ -5486,6 +5490,10 @@ namespace ts { } if (!popTypeResolution()) { + // Symbol is property of some kind that is merged with something - should use `getTypeOfFuncClassEnumModule` and not `getTypeOfVariableOrParameterOrProperty` + if (symbol.flags & SymbolFlags.ValueModule) { + return getTypeOfFuncClassEnumModule(symbol); + } type = reportCircularityError(symbol); } return type; diff --git a/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.js b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.js new file mode 100644 index 00000000000..377082fa5d5 --- /dev/null +++ b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.js @@ -0,0 +1,31 @@ +//// [tests/cases/compiler/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.ts] //// + +//// [global.d.ts] +declare global { + const React: typeof import("./module"); +} + +export { }; + +//// [module.d.ts] +export = React; +export as namespace React; + +declare namespace React { + function createRef(): any; +} + +//// [some_module.ts] +export { }; +React.createRef; + +//// [emits.ts] +console.log("hello"); +React.createRef; + +//// [some_module.js] +React.createRef; +//// [emits.js] +"use strict"; +console.log("hello"); +React.createRef; diff --git a/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.symbols b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.symbols new file mode 100644 index 00000000000..24a9885b294 --- /dev/null +++ b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.symbols @@ -0,0 +1,42 @@ +=== tests/cases/compiler/global.d.ts === +declare global { +>global : Symbol(global, Decl(global.d.ts, 0, 0)) + + const React: typeof import("./module"); +>React : Symbol(React, Decl(module.d.ts, 1, 26), Decl(global.d.ts, 1, 9)) +} + +export { }; + +=== tests/cases/compiler/module.d.ts === +export = React; +>React : Symbol(React, Decl(module.d.ts, 1, 26)) + +export as namespace React; +>React : Symbol(React, Decl(module.d.ts, 0, 15)) + +declare namespace React { +>React : Symbol(React, Decl(module.d.ts, 1, 26), Decl(global.d.ts, 1, 9)) + + function createRef(): any; +>createRef : Symbol(createRef, Decl(module.d.ts, 3, 25)) +} + +=== tests/cases/compiler/some_module.ts === +export { }; +React.createRef; +>React.createRef : Symbol(React.createRef, Decl(module.d.ts, 3, 25)) +>React : Symbol(React, Decl(module.d.ts, 1, 26), Decl(global.d.ts, 1, 9)) +>createRef : Symbol(React.createRef, Decl(module.d.ts, 3, 25)) + +=== tests/cases/compiler/emits.ts === +console.log("hello"); +>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) +>console : Symbol(console, Decl(lib.dom.d.ts, --, --)) +>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --)) + +React.createRef; +>React.createRef : Symbol(React.createRef, Decl(module.d.ts, 3, 25)) +>React : Symbol(React, Decl(module.d.ts, 1, 26), Decl(global.d.ts, 1, 9)) +>createRef : Symbol(React.createRef, Decl(module.d.ts, 3, 25)) + diff --git a/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.types b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.types new file mode 100644 index 00000000000..2c0ce91aec8 --- /dev/null +++ b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.types @@ -0,0 +1,44 @@ +=== tests/cases/compiler/global.d.ts === +declare global { +>global : typeof global + + const React: typeof import("./module"); +>React : typeof React +} + +export { }; + +=== tests/cases/compiler/module.d.ts === +export = React; +>React : typeof React + +export as namespace React; +>React : typeof React + +declare namespace React { +>React : typeof React + + function createRef(): any; +>createRef : () => any +} + +=== tests/cases/compiler/some_module.ts === +export { }; +React.createRef; +>React.createRef : () => any +>React : typeof React +>createRef : () => any + +=== tests/cases/compiler/emits.ts === +console.log("hello"); +>console.log("hello") : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>"hello" : "hello" + +React.createRef; +>React.createRef : () => any +>React : typeof React +>createRef : () => any + diff --git a/tests/cases/compiler/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.ts b/tests/cases/compiler/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.ts new file mode 100644 index 00000000000..81346aca1b4 --- /dev/null +++ b/tests/cases/compiler/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.ts @@ -0,0 +1,26 @@ +// @strict: true +// @module: esnext +// @moduleResolution: node +// @target: es2018 +// @filename: global.d.ts +declare global { + const React: typeof import("./module"); +} + +export { }; + +// @filename: module.d.ts +export = React; +export as namespace React; + +declare namespace React { + function createRef(): any; +} + +// @filename: some_module.ts +export { }; +React.createRef; + +// @filename: emits.ts +console.log("hello"); +React.createRef; \ No newline at end of file From 9d16225bc2c96a06589f8e9b5f8a60d79a82d31e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Fri, 11 Jan 2019 13:34:18 +0800 Subject: [PATCH 16/22] emit jsx type arguments --- src/compiler/emitter.ts | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 9c09ed79a77..62aba51afec 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -2561,6 +2561,7 @@ namespace ts { function emitJsxSelfClosingElement(node: JsxSelfClosingElement) { writePunctuation("<"); emitJsxTagName(node.tagName); + emitTypeArguments(node, node.typeArguments); writeSpace(); emit(node.attributes); writePunctuation("/>"); @@ -2577,6 +2578,7 @@ namespace ts { if (isJsxOpeningElement(node)) { emitJsxTagName(node.tagName); + emitTypeArguments(node, node.typeArguments); if (node.attributes.properties && node.attributes.properties.length > 0) { writeSpace(); } From 11b150129a988fe43bd74f6d349f19edb799f19b Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Fri, 14 Dec 2018 14:26:32 +0100 Subject: [PATCH 17/22] Do not process library reference directives with noLib set. When a user sets `noLib`, this indicates that they will supply their own list of `lib*.d.ts` files as part of input sources. In this situation, TypeScript should not try to resolve library reference directives. This avoids a problem where TypeScript loads a file that e.g. contains `/// `. Previously, TypeScript would use its builtin ts.libMap and attempt to load builtin libraries from the TypeScript installation, instead of respecting the user-supplied set of libraries. --- src/compiler/program.ts | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 080b17b8cbe..271bdab976e 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2227,8 +2227,9 @@ namespace ts { processReferencedFiles(file, isDefaultLib); processTypeReferenceDirectives(file); } - - processLibReferenceDirectives(file); + if (!options.noLib) { + processLibReferenceDirectives(file); + } modulesWithElidedImports.set(file.path, false); processImportedModules(file); @@ -2315,8 +2316,10 @@ namespace ts { processReferencedFiles(file, isDefaultLib); processTypeReferenceDirectives(file); } + if (!options.noLib) { + processLibReferenceDirectives(file); + } - processLibReferenceDirectives(file); // always process imported modules to record module name resolutions processImportedModules(file); From cc7ddaed281f9ab72586fd4028d6f11f3459fd5f Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Sat, 15 Dec 2018 16:43:37 +0100 Subject: [PATCH 18/22] Add tests for noLib with . --- .../baselines/reference/libReferenceNoLib.js | 51 +++++++++++++++++++ .../reference/libReferenceNoLib.symbols | 40 +++++++++++++++ .../reference/libReferenceNoLib.types | 24 +++++++++ .../declarationEmit/libReferenceNoLib.ts | 21 ++++++++ 4 files changed, 136 insertions(+) create mode 100644 tests/baselines/reference/libReferenceNoLib.js create mode 100644 tests/baselines/reference/libReferenceNoLib.symbols create mode 100644 tests/baselines/reference/libReferenceNoLib.types create mode 100644 tests/cases/conformance/declarationEmit/libReferenceNoLib.ts diff --git a/tests/baselines/reference/libReferenceNoLib.js b/tests/baselines/reference/libReferenceNoLib.js new file mode 100644 index 00000000000..21d1cbbe177 --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLib.js @@ -0,0 +1,51 @@ +//// [tests/cases/conformance/declarationEmit/libReferenceNoLib.ts] //// + +//// [fakelib.ts] +// Test that passing noLib disables resolution. + +interface Object { } +interface Array { } +interface String { } +interface Boolean { } +interface Number { } +interface Function { } +interface RegExp { } +interface IArguments { } + + +//// [file1.ts] +/// +export declare interface HTMLElement { field: string; } +export const elem: HTMLElement = { field: 'a' }; + + +//// [fakelib.js] +// Test that passing noLib disables resolution. +//// [file1.js] +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.elem = { field: 'a' }; + + +//// [fakelib.d.ts] +interface Object { +} +interface Array { +} +interface String { +} +interface Boolean { +} +interface Number { +} +interface Function { +} +interface RegExp { +} +interface IArguments { +} +//// [file1.d.ts] +export declare interface HTMLElement { + field: string; +} +export declare const elem: HTMLElement; diff --git a/tests/baselines/reference/libReferenceNoLib.symbols b/tests/baselines/reference/libReferenceNoLib.symbols new file mode 100644 index 00000000000..5f180fd1eed --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLib.symbols @@ -0,0 +1,40 @@ +=== tests/cases/conformance/declarationEmit/fakelib.ts === +// Test that passing noLib disables resolution. + +interface Object { } +>Object : Symbol(Object, Decl(fakelib.ts, 0, 0)) + +interface Array { } +>Array : Symbol(Array, Decl(fakelib.ts, 2, 20)) +>T : Symbol(T, Decl(fakelib.ts, 3, 16)) + +interface String { } +>String : Symbol(String, Decl(fakelib.ts, 3, 22)) + +interface Boolean { } +>Boolean : Symbol(Boolean, Decl(fakelib.ts, 4, 20)) + +interface Number { } +>Number : Symbol(Number, Decl(fakelib.ts, 5, 21)) + +interface Function { } +>Function : Symbol(Function, Decl(fakelib.ts, 6, 20)) + +interface RegExp { } +>RegExp : Symbol(RegExp, Decl(fakelib.ts, 7, 22)) + +interface IArguments { } +>IArguments : Symbol(IArguments, Decl(fakelib.ts, 8, 20)) + + +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare interface HTMLElement { field: string; } +>HTMLElement : Symbol(HTMLElement, Decl(file1.ts, 0, 0)) +>field : Symbol(HTMLElement.field, Decl(file1.ts, 1, 38)) + +export const elem: HTMLElement = { field: 'a' }; +>elem : Symbol(elem, Decl(file1.ts, 2, 12)) +>HTMLElement : Symbol(HTMLElement, Decl(file1.ts, 0, 0)) +>field : Symbol(field, Decl(file1.ts, 2, 34)) + diff --git a/tests/baselines/reference/libReferenceNoLib.types b/tests/baselines/reference/libReferenceNoLib.types new file mode 100644 index 00000000000..0b2733c2265 --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLib.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/declarationEmit/fakelib.ts === +// Test that passing noLib disables resolution. +No type information for this code. +No type information for this code.interface Object { } +No type information for this code.interface Array { } +No type information for this code.interface String { } +No type information for this code.interface Boolean { } +No type information for this code.interface Number { } +No type information for this code.interface Function { } +No type information for this code.interface RegExp { } +No type information for this code.interface IArguments { } +No type information for this code. +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare interface HTMLElement { field: string; } +>field : string + +export const elem: HTMLElement = { field: 'a' }; +>elem : HTMLElement +>{ field: 'a' } : { field: string; } +>field : string +>'a' : "a" + diff --git a/tests/cases/conformance/declarationEmit/libReferenceNoLib.ts b/tests/cases/conformance/declarationEmit/libReferenceNoLib.ts new file mode 100644 index 00000000000..d29da9a5bc5 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/libReferenceNoLib.ts @@ -0,0 +1,21 @@ +// @target: esnext +// @module: commonjs +// @noLib: true +// @declaration: true +// Test that passing noLib disables resolution. + +// @filename: fakelib.ts +interface Object { } +interface Array { } +interface String { } +interface Boolean { } +interface Number { } +interface Function { } +interface RegExp { } +interface IArguments { } + + +// @filename: file1.ts +/// +export declare interface HTMLElement { field: string; } +export const elem: HTMLElement = { field: 'a' }; From f3f5877c5f7659851fc7494b6c15bc5cb12834af Mon Sep 17 00:00:00 2001 From: Martin Probst Date: Fri, 11 Jan 2019 08:36:16 +0100 Subject: [PATCH 19/22] Add tests for noLib with and bundling. --- .../reference/libReferenceNoLibBundle.js | 53 +++++++++++++++++++ .../reference/libReferenceNoLibBundle.symbols | 40 ++++++++++++++ .../reference/libReferenceNoLibBundle.types | 24 +++++++++ .../libReferenceNoLibBundle.ts | 23 ++++++++ 4 files changed, 140 insertions(+) create mode 100644 tests/baselines/reference/libReferenceNoLibBundle.js create mode 100644 tests/baselines/reference/libReferenceNoLibBundle.symbols create mode 100644 tests/baselines/reference/libReferenceNoLibBundle.types create mode 100644 tests/cases/conformance/declarationEmit/libReferenceNoLibBundle.ts diff --git a/tests/baselines/reference/libReferenceNoLibBundle.js b/tests/baselines/reference/libReferenceNoLibBundle.js new file mode 100644 index 00000000000..a881f11a8a1 --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLibBundle.js @@ -0,0 +1,53 @@ +//// [tests/cases/conformance/declarationEmit/libReferenceNoLibBundle.ts] //// + +//// [fakelib.ts] +// Test that passing noLib disables resolution. + +interface Object { } +interface Array { } +interface String { } +interface Boolean { } +interface Number { } +interface Function { } +interface RegExp { } +interface IArguments { } + + +//// [file1.ts] +/// +export declare interface HTMLElement { field: string; } +export const elem: HTMLElement = { field: 'a' }; + + +//// [bundle.js] +// Test that passing noLib disables resolution. +define("file1", ["require", "exports"], function (require, exports) { + "use strict"; + Object.defineProperty(exports, "__esModule", { value: true }); + exports.elem = { field: 'a' }; +}); + + +//// [bundle.d.ts] +interface Object { +} +interface Array { +} +interface String { +} +interface Boolean { +} +interface Number { +} +interface Function { +} +interface RegExp { +} +interface IArguments { +} +declare module "file1" { + export interface HTMLElement { + field: string; + } + export const elem: HTMLElement; +} diff --git a/tests/baselines/reference/libReferenceNoLibBundle.symbols b/tests/baselines/reference/libReferenceNoLibBundle.symbols new file mode 100644 index 00000000000..5f180fd1eed --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLibBundle.symbols @@ -0,0 +1,40 @@ +=== tests/cases/conformance/declarationEmit/fakelib.ts === +// Test that passing noLib disables resolution. + +interface Object { } +>Object : Symbol(Object, Decl(fakelib.ts, 0, 0)) + +interface Array { } +>Array : Symbol(Array, Decl(fakelib.ts, 2, 20)) +>T : Symbol(T, Decl(fakelib.ts, 3, 16)) + +interface String { } +>String : Symbol(String, Decl(fakelib.ts, 3, 22)) + +interface Boolean { } +>Boolean : Symbol(Boolean, Decl(fakelib.ts, 4, 20)) + +interface Number { } +>Number : Symbol(Number, Decl(fakelib.ts, 5, 21)) + +interface Function { } +>Function : Symbol(Function, Decl(fakelib.ts, 6, 20)) + +interface RegExp { } +>RegExp : Symbol(RegExp, Decl(fakelib.ts, 7, 22)) + +interface IArguments { } +>IArguments : Symbol(IArguments, Decl(fakelib.ts, 8, 20)) + + +=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare interface HTMLElement { field: string; } +>HTMLElement : Symbol(HTMLElement, Decl(file1.ts, 0, 0)) +>field : Symbol(HTMLElement.field, Decl(file1.ts, 1, 38)) + +export const elem: HTMLElement = { field: 'a' }; +>elem : Symbol(elem, Decl(file1.ts, 2, 12)) +>HTMLElement : Symbol(HTMLElement, Decl(file1.ts, 0, 0)) +>field : Symbol(field, Decl(file1.ts, 2, 34)) + diff --git a/tests/baselines/reference/libReferenceNoLibBundle.types b/tests/baselines/reference/libReferenceNoLibBundle.types new file mode 100644 index 00000000000..0b2733c2265 --- /dev/null +++ b/tests/baselines/reference/libReferenceNoLibBundle.types @@ -0,0 +1,24 @@ +=== tests/cases/conformance/declarationEmit/fakelib.ts === +// Test that passing noLib disables resolution. +No type information for this code. +No type information for this code.interface Object { } +No type information for this code.interface Array { } +No type information for this code.interface String { } +No type information for this code.interface Boolean { } +No type information for this code.interface Number { } +No type information for this code.interface Function { } +No type information for this code.interface RegExp { } +No type information for this code.interface IArguments { } +No type information for this code. +No type information for this code. +No type information for this code.=== tests/cases/conformance/declarationEmit/file1.ts === +/// +export declare interface HTMLElement { field: string; } +>field : string + +export const elem: HTMLElement = { field: 'a' }; +>elem : HTMLElement +>{ field: 'a' } : { field: string; } +>field : string +>'a' : "a" + diff --git a/tests/cases/conformance/declarationEmit/libReferenceNoLibBundle.ts b/tests/cases/conformance/declarationEmit/libReferenceNoLibBundle.ts new file mode 100644 index 00000000000..18f0b5387c5 --- /dev/null +++ b/tests/cases/conformance/declarationEmit/libReferenceNoLibBundle.ts @@ -0,0 +1,23 @@ +// @target: esnext +// @module: amd +// @noLib: true +// @declaration: true +// @outFile: bundle.js + +// Test that passing noLib disables resolution. + +// @filename: fakelib.ts +interface Object { } +interface Array { } +interface String { } +interface Boolean { } +interface Number { } +interface Function { } +interface RegExp { } +interface IArguments { } + + +// @filename: file1.ts +/// +export declare interface HTMLElement { field: string; } +export const elem: HTMLElement = { field: 'a' }; From 8d28f9230cb3b4e032218b8019da22e61dd9abdd Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 11 Jan 2019 09:20:12 -0500 Subject: [PATCH 20/22] Added codefix to enable experimentalDecorators in the user's config file Starts on #29035 by creating a codefix to enable the `experimentalDecorators` setting in a user's config file, if one exists. The issue's discussion also mentions giving a more precise error message if the user has a jsconfig or tsconfig or creating one if not; I'd rather tackle those in separate PRs to keep this one small. Doesn't create the code action if no config file is present. Otherwise keeps to the precedent of returning without action when the config file contents aren't the expected JSON structure (looking at `fixCannotFindModule.ts`). Moves a couple JSON helpers from that file into the sibling `helpers.ts` so both codefixes can use them. --- src/compiler/diagnosticMessages.json | 4 ++ src/services/codefixes/fixCannotFindModule.ts | 14 +---- .../fixEnableExperimentalDecorators.ts | 60 +++++++++++++++++++ src/services/codefixes/helpers.ts | 8 +++ src/services/tsconfig.json | 1 + ...rimentalDecorators_blankCompilerOptions.ts | 26 ++++++++ ...talDecorators_disabledInCompilerOptions.ts | 27 +++++++++ ...mentalDecorators_missingCompilerOptions.ts | 22 +++++++ ...EnableExperimentalDecorators_noTsconfig.ts | 10 ++++ 9 files changed, 161 insertions(+), 11 deletions(-) create mode 100644 src/services/codefixes/fixEnableExperimentalDecorators.ts create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts create mode 100644 tests/cases/fourslash/codefixEnableExperimentalDecorators_noTsconfig.ts diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 9a918507dc4..5bcaf448599 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -4811,5 +4811,9 @@ "Add names to all parameters without names": { "category": "Message", "code": 95073 + }, + "Enable the 'experimentalDecorators' option in your configuration file": { + "category": "Message", + "code": 95074 } } diff --git a/src/services/codefixes/fixCannotFindModule.ts b/src/services/codefixes/fixCannotFindModule.ts index 1c7070c74bf..1baaa9714f2 100644 --- a/src/services/codefixes/fixCannotFindModule.ts +++ b/src/services/codefixes/fixCannotFindModule.ts @@ -74,7 +74,7 @@ namespace ts.codefix { const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); if (!tsconfigObjectLiteral) return undefined; - const compilerOptionsProperty = findProperty(tsconfigObjectLiteral, "compilerOptions"); + const compilerOptionsProperty = findJsonProperty(tsconfigObjectLiteral, "compilerOptions"); if (!compilerOptionsProperty) { const newCompilerOptions = createObjectLiteral([makeDefaultBaseUrl(), makeDefaultPaths()]); changes.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment("compilerOptions", newCompilerOptions)); @@ -94,7 +94,7 @@ namespace ts.codefix { return createJsonPropertyAssignment("baseUrl", createStringLiteral(defaultBaseUrl)); } function getOrAddBaseUrl(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression): string { - const baseUrlProp = findProperty(compilerOptions, "baseUrl"); + const baseUrlProp = findJsonProperty(compilerOptions, "baseUrl"); if (baseUrlProp) { return isStringLiteral(baseUrlProp.initializer) ? baseUrlProp.initializer.text : defaultBaseUrl; } @@ -112,7 +112,7 @@ namespace ts.codefix { return createJsonPropertyAssignment("paths", createObjectLiteral([makeDefaultPathMapping()])); } function getOrAddPathMapping(changes: textChanges.ChangeTracker, tsconfig: TsConfigSourceFile, compilerOptions: ObjectLiteralExpression) { - const paths = findProperty(compilerOptions, "paths"); + const paths = findJsonProperty(compilerOptions, "paths"); if (!paths || !isObjectLiteralExpression(paths.initializer)) { changes.insertNodeAtObjectStart(tsconfig, compilerOptions, makeDefaultPaths()); return defaultTypesDirectoryName; @@ -129,14 +129,6 @@ namespace ts.codefix { return defaultTypesDirectoryName; } - function createJsonPropertyAssignment(name: string, initializer: Expression) { - return createPropertyAssignment(createStringLiteral(name), initializer); - } - - function findProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { - return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); - } - function getInstallCommand(fileName: string, packageName: string): InstallPackageAction { return { type: "install package", file: fileName, packageName }; } diff --git a/src/services/codefixes/fixEnableExperimentalDecorators.ts b/src/services/codefixes/fixEnableExperimentalDecorators.ts new file mode 100644 index 00000000000..8179abdfd1d --- /dev/null +++ b/src/services/codefixes/fixEnableExperimentalDecorators.ts @@ -0,0 +1,60 @@ +/* @internal */ +namespace ts.codefix { + const fixId = "enableExperimentalDecorators"; + const errorCodes = [ + Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning.code + ]; + registerCodeFix({ + errorCodes, + getCodeActions: (context) => { + const { configFile } = context.program.getCompilerOptions(); + if (configFile === undefined) { + return undefined; + } + + const changes = textChanges.ChangeTracker.with(context, changeTracker => makeChange(changeTracker, configFile)); + return [createCodeFixActionNoFixId(fixId, changes, Diagnostics.Enable_the_experimentalDecorators_option_in_your_configuration_file)]; + }, + fixIds: [fixId], + }); + + function makeChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { + const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); + if (tsconfigObjectLiteral === undefined) { + return; + } + + const compilerOptionsProperty = findJsonProperty(tsconfigObjectLiteral, "compilerOptions"); + if (compilerOptionsProperty === undefined) { + changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createCompilerOptionsAssignment()); + return; + } + + const compilerOptions = compilerOptionsProperty.initializer; + if (!isObjectLiteralExpression(compilerOptions)) { + return; + } + + const experimentalDecoratorsProperty = findJsonProperty(compilerOptions, "experimentalDecorators"); + + if (experimentalDecoratorsProperty === undefined) { + changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createExperimentalDecoratorsAssignment()); + } + else { + changeTracker.replaceNodeWithText(configFile, experimentalDecoratorsProperty.initializer, "true"); + } + } + + function createCompilerOptionsAssignment() { + return createJsonPropertyAssignment( + "compilerOptions", + createObjectLiteral([ + createExperimentalDecoratorsAssignment(), + ]), + ); + } + + function createExperimentalDecoratorsAssignment() { + return createJsonPropertyAssignment("experimentalDecorators", createTrue()); + } +} diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 461771c0b5e..0344f51a854 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -1,5 +1,13 @@ /* @internal */ namespace ts.codefix { + export function createJsonPropertyAssignment(name: string, initializer: Expression) { + return createPropertyAssignment(createStringLiteral(name), initializer); + } + + export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { + return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); + } + /** * Finds members of the resolved type that are missing in the class pointed to by class decl * and generates source code for the missing members. diff --git a/src/services/tsconfig.json b/src/services/tsconfig.json index 15044416f84..21be663055a 100644 --- a/src/services/tsconfig.json +++ b/src/services/tsconfig.json @@ -61,6 +61,7 @@ "codefixes/fixClassDoesntImplementInheritedAbstractMember.ts", "codefixes/fixClassSuperMustPrecedeThisAccess.ts", "codefixes/fixConstructorForDerivedNeedSuperCall.ts", + "codefixes/fixEnableExperimentalDecorators.ts", "codefixes/fixExtendsInterfaceBecomesImplements.ts", "codefixes/fixForgottenThisPropertyAccess.ts", "codefixes/fixUnusedIdentifier.ts", diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts new file mode 100644 index 00000000000..0e19b42d921 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_blankCompilerOptions.ts @@ -0,0 +1,26 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// } +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "experimentalDecorators": true, + } +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts new file mode 100644 index 00000000000..056e7e15a48 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_disabledInCompilerOptions.ts @@ -0,0 +1,27 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/tsconfig.json +////{ +//// "compilerOptions": { +//// "experimentalDecorators": false, +//// } +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { + "experimentalDecorators": true, + } +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts new file mode 100644 index 00000000000..6d7006f3ce1 --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_missingCompilerOptions.ts @@ -0,0 +1,22 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +// @Filename: /dir/tsconfig.json +////{ +////} + +goTo.file("/dir/a.ts"); +verify.codeFix({ + description: "Enable the 'experimentalDecorators' option in your configuration file", + newFileContent: { + "/dir/tsconfig.json": +`{ + "compilerOptions": { "experimentalDecorators": true }, +}`, + }, +}); diff --git a/tests/cases/fourslash/codefixEnableExperimentalDecorators_noTsconfig.ts b/tests/cases/fourslash/codefixEnableExperimentalDecorators_noTsconfig.ts new file mode 100644 index 00000000000..8430fd0734b --- /dev/null +++ b/tests/cases/fourslash/codefixEnableExperimentalDecorators_noTsconfig.ts @@ -0,0 +1,10 @@ +/// + +// @Filename: /dir/a.ts +////declare const decorator: any; +////class A { +//// @decorator method() {}; +////}; + +goTo.file("/dir/a.ts"); +verify.not.codeFixAvailable(); From 7b6adae6dd438e2393d55f8b8a932c82ad67a10a Mon Sep 17 00:00:00 2001 From: Josh Goldberg Date: Fri, 11 Jan 2019 15:05:24 -0500 Subject: [PATCH 21/22] Extracted compilerOptions setting to helper function --- .../fixEnableExperimentalDecorators.ts | 38 +------------- src/services/codefixes/helpers.ts | 50 ++++++++++++++++--- 2 files changed, 43 insertions(+), 45 deletions(-) diff --git a/src/services/codefixes/fixEnableExperimentalDecorators.ts b/src/services/codefixes/fixEnableExperimentalDecorators.ts index 8179abdfd1d..8aeefe48a47 100644 --- a/src/services/codefixes/fixEnableExperimentalDecorators.ts +++ b/src/services/codefixes/fixEnableExperimentalDecorators.ts @@ -19,42 +19,6 @@ namespace ts.codefix { }); function makeChange(changeTracker: textChanges.ChangeTracker, configFile: TsConfigSourceFile) { - const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); - if (tsconfigObjectLiteral === undefined) { - return; - } - - const compilerOptionsProperty = findJsonProperty(tsconfigObjectLiteral, "compilerOptions"); - if (compilerOptionsProperty === undefined) { - changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createCompilerOptionsAssignment()); - return; - } - - const compilerOptions = compilerOptionsProperty.initializer; - if (!isObjectLiteralExpression(compilerOptions)) { - return; - } - - const experimentalDecoratorsProperty = findJsonProperty(compilerOptions, "experimentalDecorators"); - - if (experimentalDecoratorsProperty === undefined) { - changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createExperimentalDecoratorsAssignment()); - } - else { - changeTracker.replaceNodeWithText(configFile, experimentalDecoratorsProperty.initializer, "true"); - } - } - - function createCompilerOptionsAssignment() { - return createJsonPropertyAssignment( - "compilerOptions", - createObjectLiteral([ - createExperimentalDecoratorsAssignment(), - ]), - ); - } - - function createExperimentalDecoratorsAssignment() { - return createJsonPropertyAssignment("experimentalDecorators", createTrue()); + setJsonCompilerOptionValue(changeTracker, configFile, "experimentalDecorators", createTrue()); } } diff --git a/src/services/codefixes/helpers.ts b/src/services/codefixes/helpers.ts index 0344f51a854..66488d5d697 100644 --- a/src/services/codefixes/helpers.ts +++ b/src/services/codefixes/helpers.ts @@ -1,13 +1,5 @@ /* @internal */ namespace ts.codefix { - export function createJsonPropertyAssignment(name: string, initializer: Expression) { - return createPropertyAssignment(createStringLiteral(name), initializer); - } - - export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { - return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); - } - /** * Finds members of the resolved type that are missing in the class pointed to by class decl * and generates source code for the missing members. @@ -257,4 +249,46 @@ namespace ts.codefix { } return undefined; } + + export function setJsonCompilerOptionValue( + changeTracker: textChanges.ChangeTracker, + configFile: TsConfigSourceFile, + optionName: string, + optionValue: Expression, + ) { + const tsconfigObjectLiteral = getTsConfigObjectLiteralExpression(configFile); + if (!tsconfigObjectLiteral) return undefined; + + const compilerOptionsProperty = findJsonProperty(tsconfigObjectLiteral, "compilerOptions"); + if (compilerOptionsProperty === undefined) { + changeTracker.insertNodeAtObjectStart(configFile, tsconfigObjectLiteral, createJsonPropertyAssignment( + "compilerOptions", + createObjectLiteral([ + createJsonPropertyAssignment(optionName, optionValue), + ]))); + return; + } + + const compilerOptions = compilerOptionsProperty.initializer; + if (!isObjectLiteralExpression(compilerOptions)) { + return; + } + + const optionProperty = findJsonProperty(compilerOptions, optionName); + + if (optionProperty === undefined) { + changeTracker.insertNodeAtObjectStart(configFile, compilerOptions, createJsonPropertyAssignment(optionName, optionValue)); + } + else { + changeTracker.replaceNode(configFile, optionProperty.initializer, optionValue); + } + } + + export function createJsonPropertyAssignment(name: string, initializer: Expression) { + return createPropertyAssignment(createStringLiteral(name), initializer); + } + + export function findJsonProperty(obj: ObjectLiteralExpression, name: string): PropertyAssignment | undefined { + return find(obj.properties, (p): p is PropertyAssignment => isPropertyAssignment(p) && !!p.name && isStringLiteral(p.name) && p.name.text === name); + } } From fadd95f72b5ad7f7f1cffa2b6ac82f612694462c Mon Sep 17 00:00:00 2001 From: Wesley Wigham Date: Fri, 11 Jan 2019 14:24:49 -0800 Subject: [PATCH 22/22] Fix unneeded cast lints (#29383) --- src/compiler/builder.ts | 3 ++- src/compiler/parser.ts | 13 +++++++------ src/harness/compiler.ts | 5 +++-- 3 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/compiler/builder.ts b/src/compiler/builder.ts index 62dd670fbc5..06615b3a97f 100644 --- a/src/compiler/builder.ts +++ b/src/compiler/builder.ts @@ -78,7 +78,8 @@ namespace ts { if (useOldState) { // Verify the sanity of old state if (!oldState!.currentChangedFilePath) { - Debug.assert(!oldState!.affectedFiles && (!oldState!.currentAffectedFilesSignatures || !oldState!.currentAffectedFilesSignatures!.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); + const affectedSignatures = oldState!.currentAffectedFilesSignatures; + Debug.assert(!oldState!.affectedFiles && (!affectedSignatures || !affectedSignatures.size), "Cannot reuse if only few affected files of currentChangedFile were iterated"); } if (canCopySemanticDiagnostics) { Debug.assert(!forEachKey(oldState!.changedFilesSet, path => oldState!.semanticDiagnosticsPerFile!.has(path)), "Semantic diagnostics shouldnt be available for changed files"); diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index f976f77ea98..53e45505014 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -7774,17 +7774,18 @@ namespace ts { const libReferenceDirectives = context.libReferenceDirectives; forEach(toArray(entryOrList), (arg: PragmaPseudoMap["reference"]) => { // TODO: GH#18217 + const { types, lib, path } = arg!.arguments; if (arg!.arguments["no-default-lib"]) { context.hasNoDefaultLib = true; } - else if (arg!.arguments.types) { - typeReferenceDirectives.push({ pos: arg!.arguments.types!.pos, end: arg!.arguments.types!.end, fileName: arg!.arguments.types!.value }); + else if (types) { + typeReferenceDirectives.push({ pos: types.pos, end: types.end, fileName: types.value }); } - else if (arg!.arguments.lib) { - libReferenceDirectives.push({ pos: arg!.arguments.lib!.pos, end: arg!.arguments.lib!.end, fileName: arg!.arguments.lib!.value }); + else if (lib) { + libReferenceDirectives.push({ pos: lib.pos, end: lib.end, fileName: lib.value }); } - else if (arg!.arguments.path) { - referencedFiles.push({ pos: arg!.arguments.path!.pos, end: arg!.arguments.path!.end, fileName: arg!.arguments.path!.value }); + else if (path) { + referencedFiles.push({ pos: path.pos, end: path.end, fileName: path.value }); } else { reportDiagnostic(arg!.range.pos, arg!.range.end - arg!.range.pos, Diagnostics.Invalid_reference_directive_syntax); diff --git a/src/harness/compiler.ts b/src/harness/compiler.ts index 532a2d65578..70bda90ef32 100644 --- a/src/harness/compiler.ts +++ b/src/harness/compiler.ts @@ -183,8 +183,9 @@ namespace compiler { } public getSourceMapRecord(): string | undefined { - if (this.result!.sourceMaps && this.result!.sourceMaps!.length > 0) { - return Harness.SourceMapRecorder.getSourceMapRecord(this.result!.sourceMaps!, this.program!, Array.from(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), Array.from(this.dts.values())); + const maps = this.result!.sourceMaps; + if (maps && maps.length > 0) { + return Harness.SourceMapRecorder.getSourceMapRecord(maps, this.program!, Array.from(this.js.values()).filter(d => !ts.fileExtensionIs(d.file, ts.Extension.Json)), Array.from(this.dts.values())); } }