mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-04 12:32:08 -06:00
Investigate enum namespace declaration issue in declarations transformer
Co-authored-by: RyanCavanaugh <6685088+RyanCavanaugh@users.noreply.github.com>
This commit is contained in:
parent
67ff5e337a
commit
e47e4b8f78
@ -50962,9 +50962,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
|
||||
return false;
|
||||
}
|
||||
|
||||
function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
|
||||
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, /*internalFlags*/ undefined, tracker)
|
||||
: type === trueType ? factory.createTrue() : type === falseType && factory.createFalse();
|
||||
function literalTypeToNode(type: FreshableType, enclosing: Node, tracker: SymbolTracker): Expression {
|
||||
const enumResult = type.flags & TypeFlags.EnumLike ? nodeBuilder.symbolToExpression(type.symbol, SymbolFlags.Value, enclosing, /*flags*/ undefined, /*internalFlags*/ undefined, tracker)
|
||||
: type === trueType ? factory.createTrue() : type === falseType && factory.createFalse();
|
||||
if (enumResult) return enumResult;
|
||||
const literalValue = (type as LiteralType).value;
|
||||
return typeof literalValue === "object" ? factory.createBigIntLiteral(literalValue) :
|
||||
|
||||
@ -103,7 +103,8 @@ import {
|
||||
isExpandoPropertyDeclaration,
|
||||
isExportAssignment,
|
||||
isExportDeclaration,
|
||||
isExpressionWithTypeArguments,
|
||||
isExpressionWithTypeArguments,
|
||||
isExpression,
|
||||
isExternalModule,
|
||||
isExternalModuleAugmentation,
|
||||
isExternalModuleIndicator,
|
||||
@ -128,8 +129,9 @@ import {
|
||||
isObjectLiteralExpression,
|
||||
isOmittedExpression,
|
||||
isParameter,
|
||||
isPrimitiveLiteralValue,
|
||||
isPrivateIdentifier,
|
||||
isPrimitiveLiteralValue,
|
||||
isPrivateIdentifier,
|
||||
isPropertyAccessExpression,
|
||||
isSemicolonClassElement,
|
||||
isSetAccessorDeclaration,
|
||||
isSourceFile,
|
||||
@ -200,8 +202,8 @@ import {
|
||||
TransformationContext,
|
||||
Transformer,
|
||||
transformNodes,
|
||||
tryCast,
|
||||
TypeAliasDeclaration,
|
||||
tryCast,
|
||||
TypeAliasDeclaration,
|
||||
TypeNode,
|
||||
TypeParameterDeclaration,
|
||||
TypeReferenceNode,
|
||||
@ -654,21 +656,46 @@ export function transformDeclarations(context: TransformationContext): Transform
|
||||
return newParam;
|
||||
}
|
||||
|
||||
function shouldPrintWithInitializer(node: Node): node is CanHaveLiteralInitializer & { initializer: Expression; } {
|
||||
return canHaveLiteralInitializer(node)
|
||||
&& !!node.initializer
|
||||
&& resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer); // TODO: Make safea
|
||||
function shouldPrintWithInitializer(node: Node): node is CanHaveLiteralInitializer & { initializer: Expression; } {
|
||||
if (!canHaveLiteralInitializer(node) || !node.initializer || !resolver.isLiteralConstDeclaration(getParseTreeNode(node) as CanHaveLiteralInitializer)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check if the initializer is a property access to an enum member (e.g., Foo.bar)
|
||||
// In this case, don't print with initializer - let it get a type annotation instead
|
||||
const unwrappedInitializer = unwrapParenthesizedExpression(node.initializer);
|
||||
if (isPropertyAccessExpression(unwrappedInitializer)) {
|
||||
const constantValue = resolver.getConstantValue(unwrappedInitializer);
|
||||
// If it has a constant value (meaning it's an enum member reference), use type instead of initializer
|
||||
if (constantValue !== undefined) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function ensureNoInitializer(node: CanHaveLiteralInitializer) {
|
||||
if (shouldPrintWithInitializer(node)) {
|
||||
const unwrappedInitializer = unwrapParenthesizedExpression(node.initializer);
|
||||
if (!isPrimitiveLiteralValue(unwrappedInitializer)) {
|
||||
reportInferenceFallback(node);
|
||||
}
|
||||
return resolver.createLiteralConstValue(getParseTreeNode(node, canHaveLiteralInitializer)!, symbolTracker);
|
||||
}
|
||||
return undefined;
|
||||
function ensureNoInitializer(node: CanHaveLiteralInitializer) {
|
||||
if (shouldPrintWithInitializer(node)) {
|
||||
const unwrappedInitializer = unwrapParenthesizedExpression(node.initializer);
|
||||
if (!isPrimitiveLiteralValue(unwrappedInitializer)) {
|
||||
reportInferenceFallback(node);
|
||||
}
|
||||
|
||||
// Check if the initializer is a property access to an enum member (e.g., Foo.bar)
|
||||
// In this case, don't print with initializer - let it fall back to type annotation
|
||||
if (isPropertyAccessExpression(unwrappedInitializer)) {
|
||||
const constantValue = resolver.getConstantValue(unwrappedInitializer);
|
||||
// If it has a constant value (meaning it's an enum member reference),
|
||||
// don't use initializer and let it get a type instead
|
||||
if (constantValue !== undefined) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
return resolver.createLiteralConstValue(getParseTreeNode(node, canHaveLiteralInitializer)!, symbolTracker);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
function ensureType(node: VariableDeclaration | ParameterDeclaration | BindingElement | PropertyDeclaration | PropertySignature | ExportAssignment | SignatureDeclaration, ignorePrivate?: boolean): TypeNode | undefined {
|
||||
if (!ignorePrivate && hasEffectiveModifier(node, ModifierFlags.Private)) {
|
||||
|
||||
21
tests/cases/compiler/enumNamespaceConstantsDeclaration.d.ts
vendored
Normal file
21
tests/cases/compiler/enumNamespaceConstantsDeclaration.d.ts
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
declare enum Foo {
|
||||
bar = 0
|
||||
}
|
||||
declare namespace Foo {
|
||||
const baz = bar;
|
||||
}
|
||||
declare enum MyEnum {
|
||||
First = 1,
|
||||
Second = 2
|
||||
}
|
||||
declare namespace MyEnum {
|
||||
const value1 = First;
|
||||
const value2 = Second;
|
||||
}
|
||||
declare enum StringEnum {
|
||||
Option1 = "option1",
|
||||
Option2 = "option2"
|
||||
}
|
||||
declare namespace StringEnum {
|
||||
const selected: any;
|
||||
}
|
||||
26
tests/cases/compiler/enumNamespaceConstantsDeclaration.ts
Normal file
26
tests/cases/compiler/enumNamespaceConstantsDeclaration.ts
Normal file
@ -0,0 +1,26 @@
|
||||
// Test for constant declarations inside namespace merged with enum
|
||||
enum Foo {
|
||||
bar
|
||||
}
|
||||
namespace Foo {
|
||||
export const baz = Foo.bar;
|
||||
}
|
||||
|
||||
// Multiple enum members
|
||||
enum MyEnum {
|
||||
First = 1,
|
||||
Second = 2
|
||||
}
|
||||
namespace MyEnum {
|
||||
export const value1 = MyEnum.First;
|
||||
export const value2 = MyEnum.Second;
|
||||
}
|
||||
|
||||
// String enum
|
||||
enum StringEnum {
|
||||
Option1 = "option1",
|
||||
Option2 = "option2"
|
||||
}
|
||||
namespace StringEnum {
|
||||
export const selected = StringEnum.Option1;
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user