diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2b98d80a7e883..0c5807f75197e 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -28274,7 +28274,8 @@ namespace ts { return true; } const target = getSymbolLinks(symbol!).target; // TODO: GH#18217 - if (target && getModifierFlags(node) & ModifierFlags.Export && target.flags & SymbolFlags.Value) { + if (target && getModifierFlags(node) & ModifierFlags.Export && + target.flags & SymbolFlags.Value && (compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target))) { // An `export import ... =` of a value symbol is always considered referenced return true; } diff --git a/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.js b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.js new file mode 100644 index 0000000000000..961d3ccd500b9 --- /dev/null +++ b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.js @@ -0,0 +1,128 @@ +//// [exportImportCanSubstituteConstEnumForValue.ts] +module MsPortalFx.ViewModels.Dialogs { + + export const enum DialogResult { + Abort, + Cancel, + Ignore, + No, + Ok, + Retry, + Yes, + } + + export interface DialogResultCallback { + (result: MsPortalFx.ViewModels.Dialogs.DialogResult): void; + } + + export function someExportedFunction() { + } + + export const enum MessageBoxButtons { + AbortRetryIgnore, + OK, + OKCancel, + RetryCancel, + YesNo, + YesNoCancel, + } +} + + +module MsPortalFx.ViewModels { + + /** + * For some reason javascript code is emitted for this re-exported const enum. + */ + export import ReExportedEnum = Dialogs.DialogResult; + + /** + * Not exported to show difference. No javascript is emmitted (as expected) + */ + import DialogButtons = Dialogs.MessageBoxButtons; + + /** + * Re-exporting a function type to show difference. No javascript is emmitted (as expected) + */ + export import Callback = Dialogs.DialogResultCallback; + + export class SomeUsagesOfTheseConsts { + constructor() { + // these do get replaced by the const value + const value1 = ReExportedEnum.Cancel; + console.log(value1); + const value2 = DialogButtons.OKCancel; + console.log(value2); + } + } +} + + +//// [exportImportCanSubstituteConstEnumForValue.js] +var MsPortalFx; +(function (MsPortalFx) { + var ViewModels; + (function (ViewModels) { + var Dialogs; + (function (Dialogs) { + function someExportedFunction() { + } + Dialogs.someExportedFunction = someExportedFunction; + })(Dialogs = ViewModels.Dialogs || (ViewModels.Dialogs = {})); + })(ViewModels = MsPortalFx.ViewModels || (MsPortalFx.ViewModels = {})); +})(MsPortalFx || (MsPortalFx = {})); +(function (MsPortalFx) { + var ViewModels; + (function (ViewModels) { + var SomeUsagesOfTheseConsts = /** @class */ (function () { + function SomeUsagesOfTheseConsts() { + // these do get replaced by the const value + var value1 = 1 /* Cancel */; + console.log(value1); + var value2 = 2 /* OKCancel */; + console.log(value2); + } + return SomeUsagesOfTheseConsts; + }()); + ViewModels.SomeUsagesOfTheseConsts = SomeUsagesOfTheseConsts; + })(ViewModels = MsPortalFx.ViewModels || (MsPortalFx.ViewModels = {})); +})(MsPortalFx || (MsPortalFx = {})); + + +//// [exportImportCanSubstituteConstEnumForValue.d.ts] +declare module MsPortalFx.ViewModels.Dialogs { + const enum DialogResult { + Abort = 0, + Cancel = 1, + Ignore = 2, + No = 3, + Ok = 4, + Retry = 5, + Yes = 6 + } + interface DialogResultCallback { + (result: MsPortalFx.ViewModels.Dialogs.DialogResult): void; + } + function someExportedFunction(): void; + const enum MessageBoxButtons { + AbortRetryIgnore = 0, + OK = 1, + OKCancel = 2, + RetryCancel = 3, + YesNo = 4, + YesNoCancel = 5 + } +} +declare module MsPortalFx.ViewModels { + /** + * For some reason javascript code is emitted for this re-exported const enum. + */ + export import ReExportedEnum = Dialogs.DialogResult; + /** + * Re-exporting a function type to show difference. No javascript is emmitted (as expected) + */ + export import Callback = Dialogs.DialogResultCallback; + class SomeUsagesOfTheseConsts { + constructor(); + } +} diff --git a/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.symbols b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.symbols new file mode 100644 index 0000000000000..ee21ab5b3b1dc --- /dev/null +++ b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.symbols @@ -0,0 +1,130 @@ +=== tests/cases/compiler/exportImportCanSubstituteConstEnumForValue.ts === +module MsPortalFx.ViewModels.Dialogs { +>MsPortalFx : Symbol(MsPortalFx, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 0), Decl(exportImportCanSubstituteConstEnumForValue.ts, 27, 1)) +>ViewModels : Symbol(ViewModels, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 18), Decl(exportImportCanSubstituteConstEnumForValue.ts, 30, 18)) +>Dialogs : Symbol(Dialogs, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 29)) + + export const enum DialogResult { +>DialogResult : Symbol(DialogResult, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 38)) + + Abort, +>Abort : Symbol(ReExportedEnum.Abort, Decl(exportImportCanSubstituteConstEnumForValue.ts, 2, 36)) + + Cancel, +>Cancel : Symbol(ReExportedEnum.Cancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 3, 14)) + + Ignore, +>Ignore : Symbol(ReExportedEnum.Ignore, Decl(exportImportCanSubstituteConstEnumForValue.ts, 4, 15)) + + No, +>No : Symbol(ReExportedEnum.No, Decl(exportImportCanSubstituteConstEnumForValue.ts, 5, 15)) + + Ok, +>Ok : Symbol(ReExportedEnum.Ok, Decl(exportImportCanSubstituteConstEnumForValue.ts, 6, 11)) + + Retry, +>Retry : Symbol(ReExportedEnum.Retry, Decl(exportImportCanSubstituteConstEnumForValue.ts, 7, 11)) + + Yes, +>Yes : Symbol(ReExportedEnum.Yes, Decl(exportImportCanSubstituteConstEnumForValue.ts, 8, 14)) + } + + export interface DialogResultCallback { +>DialogResultCallback : Symbol(DialogResultCallback, Decl(exportImportCanSubstituteConstEnumForValue.ts, 10, 5)) + + (result: MsPortalFx.ViewModels.Dialogs.DialogResult): void; +>result : Symbol(result, Decl(exportImportCanSubstituteConstEnumForValue.ts, 13, 9)) +>MsPortalFx : Symbol(MsPortalFx, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 0), Decl(exportImportCanSubstituteConstEnumForValue.ts, 27, 1)) +>ViewModels : Symbol(ViewModels, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 18), Decl(exportImportCanSubstituteConstEnumForValue.ts, 30, 18)) +>Dialogs : Symbol(Dialogs, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 29)) +>DialogResult : Symbol(DialogResult, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 38)) + } + + export function someExportedFunction() { +>someExportedFunction : Symbol(someExportedFunction, Decl(exportImportCanSubstituteConstEnumForValue.ts, 14, 5)) + } + + export const enum MessageBoxButtons { +>MessageBoxButtons : Symbol(MessageBoxButtons, Decl(exportImportCanSubstituteConstEnumForValue.ts, 17, 5)) + + AbortRetryIgnore, +>AbortRetryIgnore : Symbol(MessageBoxButtons.AbortRetryIgnore, Decl(exportImportCanSubstituteConstEnumForValue.ts, 19, 41)) + + OK, +>OK : Symbol(MessageBoxButtons.OK, Decl(exportImportCanSubstituteConstEnumForValue.ts, 20, 25)) + + OKCancel, +>OKCancel : Symbol(MessageBoxButtons.OKCancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 21, 11)) + + RetryCancel, +>RetryCancel : Symbol(MessageBoxButtons.RetryCancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 22, 17)) + + YesNo, +>YesNo : Symbol(MessageBoxButtons.YesNo, Decl(exportImportCanSubstituteConstEnumForValue.ts, 23, 20)) + + YesNoCancel, +>YesNoCancel : Symbol(MessageBoxButtons.YesNoCancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 24, 14)) + } +} + + +module MsPortalFx.ViewModels { +>MsPortalFx : Symbol(MsPortalFx, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 0), Decl(exportImportCanSubstituteConstEnumForValue.ts, 27, 1)) +>ViewModels : Symbol(ViewModels, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 18), Decl(exportImportCanSubstituteConstEnumForValue.ts, 30, 18)) + + /** + * For some reason javascript code is emitted for this re-exported const enum. + */ + export import ReExportedEnum = Dialogs.DialogResult; +>ReExportedEnum : Symbol(ReExportedEnum, Decl(exportImportCanSubstituteConstEnumForValue.ts, 30, 30)) +>Dialogs : Symbol(Dialogs, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 29)) +>DialogResult : Symbol(ReExportedEnum, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 38)) + + /** + * Not exported to show difference. No javascript is emmitted (as expected) + */ + import DialogButtons = Dialogs.MessageBoxButtons; +>DialogButtons : Symbol(DialogButtons, Decl(exportImportCanSubstituteConstEnumForValue.ts, 35, 56)) +>Dialogs : Symbol(Dialogs, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 29)) +>MessageBoxButtons : Symbol(DialogButtons, Decl(exportImportCanSubstituteConstEnumForValue.ts, 17, 5)) + + /** + * Re-exporting a function type to show difference. No javascript is emmitted (as expected) + */ + export import Callback = Dialogs.DialogResultCallback; +>Callback : Symbol(Callback, Decl(exportImportCanSubstituteConstEnumForValue.ts, 40, 53)) +>Dialogs : Symbol(Dialogs, Decl(exportImportCanSubstituteConstEnumForValue.ts, 0, 29)) +>DialogResultCallback : Symbol(Callback, Decl(exportImportCanSubstituteConstEnumForValue.ts, 10, 5)) + + export class SomeUsagesOfTheseConsts { +>SomeUsagesOfTheseConsts : Symbol(SomeUsagesOfTheseConsts, Decl(exportImportCanSubstituteConstEnumForValue.ts, 45, 58)) + + constructor() { + // these do get replaced by the const value + const value1 = ReExportedEnum.Cancel; +>value1 : Symbol(value1, Decl(exportImportCanSubstituteConstEnumForValue.ts, 50, 17)) +>ReExportedEnum.Cancel : Symbol(ReExportedEnum.Cancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 3, 14)) +>ReExportedEnum : Symbol(ReExportedEnum, Decl(exportImportCanSubstituteConstEnumForValue.ts, 30, 30)) +>Cancel : Symbol(ReExportedEnum.Cancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 3, 14)) + + console.log(value1); +>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, --, --)) +>value1 : Symbol(value1, Decl(exportImportCanSubstituteConstEnumForValue.ts, 50, 17)) + + const value2 = DialogButtons.OKCancel; +>value2 : Symbol(value2, Decl(exportImportCanSubstituteConstEnumForValue.ts, 52, 17)) +>DialogButtons.OKCancel : Symbol(DialogButtons.OKCancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 21, 11)) +>DialogButtons : Symbol(DialogButtons, Decl(exportImportCanSubstituteConstEnumForValue.ts, 35, 56)) +>OKCancel : Symbol(DialogButtons.OKCancel, Decl(exportImportCanSubstituteConstEnumForValue.ts, 21, 11)) + + console.log(value2); +>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, --, --)) +>value2 : Symbol(value2, Decl(exportImportCanSubstituteConstEnumForValue.ts, 52, 17)) + } + } +} + diff --git a/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.types b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.types new file mode 100644 index 0000000000000..b35ca9384f7bb --- /dev/null +++ b/tests/baselines/reference/exportImportCanSubstituteConstEnumForValue.types @@ -0,0 +1,129 @@ +=== tests/cases/compiler/exportImportCanSubstituteConstEnumForValue.ts === +module MsPortalFx.ViewModels.Dialogs { +>MsPortalFx : typeof MsPortalFx +>ViewModels : typeof ViewModels +>Dialogs : typeof Dialogs + + export const enum DialogResult { +>DialogResult : DialogResult + + Abort, +>Abort : DialogResult.Abort + + Cancel, +>Cancel : DialogResult.Cancel + + Ignore, +>Ignore : DialogResult.Ignore + + No, +>No : DialogResult.No + + Ok, +>Ok : DialogResult.Ok + + Retry, +>Retry : DialogResult.Retry + + Yes, +>Yes : DialogResult.Yes + } + + export interface DialogResultCallback { + (result: MsPortalFx.ViewModels.Dialogs.DialogResult): void; +>result : DialogResult +>MsPortalFx : any +>ViewModels : any +>Dialogs : any + } + + export function someExportedFunction() { +>someExportedFunction : () => void + } + + export const enum MessageBoxButtons { +>MessageBoxButtons : MessageBoxButtons + + AbortRetryIgnore, +>AbortRetryIgnore : MessageBoxButtons.AbortRetryIgnore + + OK, +>OK : MessageBoxButtons.OK + + OKCancel, +>OKCancel : MessageBoxButtons.OKCancel + + RetryCancel, +>RetryCancel : MessageBoxButtons.RetryCancel + + YesNo, +>YesNo : MessageBoxButtons.YesNo + + YesNoCancel, +>YesNoCancel : MessageBoxButtons.YesNoCancel + } +} + + +module MsPortalFx.ViewModels { +>MsPortalFx : typeof MsPortalFx +>ViewModels : typeof ViewModels + + /** + * For some reason javascript code is emitted for this re-exported const enum. + */ + export import ReExportedEnum = Dialogs.DialogResult; +>ReExportedEnum : typeof ReExportedEnum +>Dialogs : typeof Dialogs +>DialogResult : ReExportedEnum + + /** + * Not exported to show difference. No javascript is emmitted (as expected) + */ + import DialogButtons = Dialogs.MessageBoxButtons; +>DialogButtons : typeof DialogButtons +>Dialogs : typeof Dialogs +>MessageBoxButtons : DialogButtons + + /** + * Re-exporting a function type to show difference. No javascript is emmitted (as expected) + */ + export import Callback = Dialogs.DialogResultCallback; +>Callback : any +>Dialogs : typeof Dialogs +>DialogResultCallback : Callback + + export class SomeUsagesOfTheseConsts { +>SomeUsagesOfTheseConsts : SomeUsagesOfTheseConsts + + constructor() { + // these do get replaced by the const value + const value1 = ReExportedEnum.Cancel; +>value1 : ReExportedEnum.Cancel +>ReExportedEnum.Cancel : ReExportedEnum.Cancel +>ReExportedEnum : typeof ReExportedEnum +>Cancel : ReExportedEnum.Cancel + + console.log(value1); +>console.log(value1) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>value1 : ReExportedEnum.Cancel + + const value2 = DialogButtons.OKCancel; +>value2 : DialogButtons.OKCancel +>DialogButtons.OKCancel : DialogButtons.OKCancel +>DialogButtons : typeof DialogButtons +>OKCancel : DialogButtons.OKCancel + + console.log(value2); +>console.log(value2) : void +>console.log : (message?: any, ...optionalParams: any[]) => void +>console : Console +>log : (message?: any, ...optionalParams: any[]) => void +>value2 : DialogButtons.OKCancel + } + } +} + diff --git a/tests/cases/compiler/exportImportCanSubstituteConstEnumForValue.ts b/tests/cases/compiler/exportImportCanSubstituteConstEnumForValue.ts new file mode 100644 index 0000000000000..71c8a29df2625 --- /dev/null +++ b/tests/cases/compiler/exportImportCanSubstituteConstEnumForValue.ts @@ -0,0 +1,60 @@ +// @module: amd +// @declaration: true +// @target: es5 +module MsPortalFx.ViewModels.Dialogs { + + export const enum DialogResult { + Abort, + Cancel, + Ignore, + No, + Ok, + Retry, + Yes, + } + + export interface DialogResultCallback { + (result: MsPortalFx.ViewModels.Dialogs.DialogResult): void; + } + + export function someExportedFunction() { + } + + export const enum MessageBoxButtons { + AbortRetryIgnore, + OK, + OKCancel, + RetryCancel, + YesNo, + YesNoCancel, + } +} + + +module MsPortalFx.ViewModels { + + /** + * For some reason javascript code is emitted for this re-exported const enum. + */ + export import ReExportedEnum = Dialogs.DialogResult; + + /** + * Not exported to show difference. No javascript is emmitted (as expected) + */ + import DialogButtons = Dialogs.MessageBoxButtons; + + /** + * Re-exporting a function type to show difference. No javascript is emmitted (as expected) + */ + export import Callback = Dialogs.DialogResultCallback; + + export class SomeUsagesOfTheseConsts { + constructor() { + // these do get replaced by the const value + const value1 = ReExportedEnum.Cancel; + console.log(value1); + const value2 = DialogButtons.OKCancel; + console.log(value2); + } + } +}