From 3126112fadf002b021eca1dc5edb7f98ea14d1cf Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 6 May 2022 14:51:02 -0700 Subject: [PATCH 1/2] Flag resolution mode assertions in non-nightly builds --- src/compiler/diagnosticMessages.json | 4 ++++ src/compiler/program.ts | 2 +- src/compiler/transformers/declarations.ts | 21 ++++++++++++++++----- src/compiler/utilities.ts | 4 ++++ 4 files changed, 25 insertions(+), 6 deletions(-) diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 2382a16cf1de4..bae97eb537518 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3880,6 +3880,10 @@ "category": "Error", "code": 4124 }, + "Resolution mode assertions are unstable. Use nightly TypeScript to silence this error. Try updating with 'npm install -D typescript@next'.": { + "category": "Error", + "code": 4125 + }, "The current host does not support the '{0}' option.": { "category": "Error", diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 2d7777e7631a4..7044953fee6be 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -593,7 +593,7 @@ namespace ts { } /* @internal */ - export function getResolutionModeOverrideForClause(clause: AssertClause | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => boolean) { + export function getResolutionModeOverrideForClause(clause: AssertClause | undefined, grammarErrorOnNode?: (node: Node, diagnostic: DiagnosticMessage) => void) { if (!clause) return undefined; if (length(clause.elements) !== 1) { grammarErrorOnNode?.(clause, Diagnostics.Type_import_assertions_should_have_exactly_one_key_resolution_mode_with_value_import_or_require); diff --git a/src/compiler/transformers/declarations.ts b/src/compiler/transformers/declarations.ts index 0667cf386f73f..b855fd4b8dab5 100644 --- a/src/compiler/transformers/declarations.ts +++ b/src/compiler/transformers/declarations.ts @@ -733,7 +733,7 @@ namespace ts { decl.modifiers, decl.importClause, rewriteModuleSpecifier(decl, decl.moduleSpecifier), - getResolutionModeOverrideForClause(decl.assertClause) ? decl.assertClause : undefined + getResolutionModeOverrideForClauseInNightly(decl.assertClause) ); } // The `importClause` visibility corresponds to the default's visibility. @@ -745,7 +745,7 @@ namespace ts { decl.importClause.isTypeOnly, visibleDefaultBinding, /*namedBindings*/ undefined, - ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClause(decl.assertClause) ? decl.assertClause : undefined); + ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)); } if (decl.importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { // Namespace import (optionally with visible default) @@ -755,7 +755,7 @@ namespace ts { decl.importClause.isTypeOnly, visibleDefaultBinding, namedBindings, - ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClause(decl.assertClause) ? decl.assertClause : undefined) : undefined; + ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), getResolutionModeOverrideForClauseInNightly(decl.assertClause)) : undefined; } // Named imports (optionally with visible default) const bindingList = mapDefined(decl.importClause.namedBindings.elements, b => resolver.isDeclarationVisible(b) ? b : undefined); @@ -771,7 +771,7 @@ namespace ts { bindingList && bindingList.length ? factory.updateNamedImports(decl.importClause.namedBindings, bindingList) : undefined, ), rewriteModuleSpecifier(decl, decl.moduleSpecifier), - getResolutionModeOverrideForClause(decl.assertClause) ? decl.assertClause : undefined + getResolutionModeOverrideForClauseInNightly(decl.assertClause) ); } // Augmentation of export depends on import @@ -782,12 +782,23 @@ namespace ts { decl.modifiers, /*importClause*/ undefined, rewriteModuleSpecifier(decl, decl.moduleSpecifier), - getResolutionModeOverrideForClause(decl.assertClause) ? decl.assertClause : undefined + getResolutionModeOverrideForClauseInNightly(decl.assertClause) ); } // Nothing visible } + function getResolutionModeOverrideForClauseInNightly(assertClause: AssertClause | undefined) { + const mode = getResolutionModeOverrideForClause(assertClause); + if (mode !== undefined) { + if (!isNightly()) { + context.addDiagnostic(createDiagnosticForNode(assertClause!, Diagnostics.Resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next)); + } + return assertClause; + } + return undefined; + } + function transformAndReplaceLatePaintedStatements(statements: NodeArray): NodeArray { // This is a `while` loop because `handleSymbolAccessibilityError` can see additional import aliases marked as visible during // error handling which must now be included in the output and themselves checked for errors. diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3c38df36b4470..6036f516bb025 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -4121,6 +4121,10 @@ namespace ts { return indentStrings[1].length; } + export function isNightly() { + return stringContains(version, "-dev") || stringContains(version, "-insiders"); + } + export function createTextWriter(newLine: string): EmitTextWriter { let output: string; let indent: number; From 95763962e91b7105bfa60a038dee2efa2d8b76e8 Mon Sep 17 00:00:00 2001 From: Ryan Cavanaugh Date: Fri, 6 May 2022 16:18:01 -0700 Subject: [PATCH 2/2] Add checker check --- src/compiler/checker.ts | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ae1ded9d0d8df..6370dddf49f52 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -40718,6 +40718,10 @@ namespace ts { const validForTypeAssertions = isExclusivelyTypeOnlyImportOrExport(declaration); const override = getResolutionModeOverrideForClause(declaration.assertClause, validForTypeAssertions ? grammarErrorOnNode : undefined); if (validForTypeAssertions && override) { + if (!isNightly()) { + grammarErrorOnNode(declaration.assertClause, Diagnostics.Resolution_mode_assertions_are_unstable_Use_nightly_TypeScript_to_silence_this_error_Try_updating_with_npm_install_D_typescript_next); + } + if (getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.Node16 && getEmitModuleResolutionKind(compilerOptions) !== ModuleResolutionKind.NodeNext) { return grammarErrorOnNode(declaration.assertClause, Diagnostics.Resolution_modes_are_only_supported_when_moduleResolution_is_node16_or_nodenext); }