Skip to content

Commit 303bf25

Browse files
committed
Fix conformance tests, add additional test cases to enumLiteralBaiscs.ts for individual members as types
1 parent d002e9e commit 303bf25

10 files changed

+480
-74
lines changed

src/compiler/factory/nodeFactory.ts

+3-4
Original file line numberDiff line numberDiff line change
@@ -4546,15 +4546,14 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
45464546
// @api
45474547
function createEnumLiteralExpression(
45484548
modifiers: readonly ModifierLike[] | undefined,
4549-
name: string | Identifier,
4549+
name: __String,
45504550
members: readonly EnumMember[],
45514551
) {
45524552
const node = createBaseDeclaration<EnumLiteralExpression>(SyntaxKind.EnumLiteralExpression);
45534553
node.modifiers = asNodeArray(modifiers);
4554-
node.name = asName(name);
4554+
node.name = name;
45554555
node.members = createNodeArray(members);
45564556
node.transformFlags |= propagateChildrenFlags(node.modifiers) |
4557-
propagateChildFlags(node.name) |
45584557
propagateChildrenFlags(node.members) |
45594558
TransformFlags.ContainsTypeScript;
45604559
node.transformFlags &= ~TransformFlags.ContainsPossibleTopLevelAwait; // Enum declarations cannot contain `await`
@@ -4567,7 +4566,7 @@ export function createNodeFactory(flags: NodeFactoryFlags, baseFactory: BaseNode
45674566
function updateEnumLiteralExpression(
45684567
node: EnumLiteralExpression,
45694568
modifiers: readonly ModifierLike[] | undefined,
4570-
name: Identifier,
4569+
name: __String,
45714570
members: readonly EnumMember[],
45724571
) {
45734572
return node.modifiers !== modifiers

src/compiler/parser.ts

+7-4
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ import {
110110
getLeadingCommentRanges,
111111
getSpellingSuggestion,
112112
getTextOfNodeFromSourceText,
113+
getTokenPosOfNode,
113114
HasJSDoc,
114115
hasJSDocNodes,
115116
HasModifiers,
@@ -923,8 +924,9 @@ const forEachChildTable: ForEachChildTable = {
923924
visitNode(cbNode, node.initializer);
924925
},
925926
[SyntaxKind.EnumLiteralExpression]: function forEachChildInEnumLiteralExpression<T>(node: EnumLiteralExpression, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
927+
// For EnumLiteralExpression, the name is not visited or emitted. It is a reference to the binding name of a Declaration for which
928+
// the EnumLiteralExpression is an initializer, and is used to permit diagnostic code for EnumDeclarations to be used.
926929
return visitNodes(cbNode, cbNodes, node.modifiers) ||
927-
visitNode(cbNode, node.name) ||
928930
visitNodes(cbNode, cbNodes, node.members);
929931
},
930932
[SyntaxKind.ModuleDeclaration]: function forEachChildInModuleDeclaration<T>(node: ModuleDeclaration, cbNode: (node: Node) => T | undefined, cbNodes?: (nodes: NodeArray<Node>) => T | undefined): T | undefined {
@@ -7645,7 +7647,7 @@ namespace Parser {
76457647
}
76467648
const type = parseTypeAnnotation();
76477649
if (allowEnumType && type && isEnumTypeReference(type) && name.kind === SyntaxKind.Identifier) {
7648-
const initializer = parseInitializerAsEnumLiteralExpression(name, pos);
7650+
const initializer = parseInitializerAsEnumLiteralExpression(name);
76497651
const node = factoryCreateVariableDeclaration(name, exclamationToken, type, initializer);
76507652
return withJSDoc(finishNode(node, pos), hasJSDoc);
76517653
}
@@ -8293,16 +8295,17 @@ namespace Parser {
82938295
return withJSDoc(finishNode(node, pos), hasJSDoc);
82948296
}
82958297

8296-
function parseInitializerAsEnumLiteralExpression(name: Identifier, pos: number) {
8298+
function parseInitializerAsEnumLiteralExpression(name: Identifier) {
82978299
// A VariableDeclaration with a declared type `enum` expects the initializer to be in a format like an ObjectLiteralExpression,
82988300
// with only constant keys and property assignments, which are treated as EnumMembers.
8301+
const pos = getNodePos();
82998302
parseExpected(SyntaxKind.EqualsToken);
83008303
parseExpected(SyntaxKind.OpenBraceToken);
83018304
const members = parseDelimitedList(ParsingContext.ObjectLiteralMembers, parseObjectLiteralEnumMember);
83028305
parseExpected(SyntaxKind.CloseBraceToken);
83038306

83048307
// Should the variable have the jsdoc, or the enum literal, or both?
8305-
return finishNode(factory.createEnumLiteralExpression(/*modifiers*/ undefined, name, members), pos);
8308+
return finishNode(factory.createEnumLiteralExpression(/*modifiers*/ undefined, name.escapedText, members), pos);
83068309
}
83078310

83088311
function parseModuleBlock(): ModuleBlock {

src/compiler/types.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -3616,7 +3616,7 @@ export interface EnumLiteralExpression extends PrimaryExpression, Declaration, J
36163616
readonly kind: SyntaxKind.EnumLiteralExpression;
36173617
readonly parent: VariableDeclaration;
36183618
readonly modifiers?: NodeArray<ModifierLike>;
3619-
readonly name: Identifier; // For compatibility with EnumDeclaration -- however this must be equal to the BindingName in the VariableDeclaration.
3619+
readonly name: __String; // For compatibility with EnumDeclaration -- however this must be equal to the BindingName in the VariableDeclaration.
36203620
readonly members: NodeArray<EnumMember>;
36213621
}
36223622

@@ -9025,8 +9025,8 @@ export interface NodeFactory {
90259025
updateTypeAliasDeclaration(node: TypeAliasDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, typeParameters: readonly TypeParameterDeclaration[] | undefined, type: TypeNode): TypeAliasDeclaration;
90269026
createEnumDeclaration(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumDeclaration;
90279027
updateEnumDeclaration(node: EnumDeclaration, modifiers: readonly ModifierLike[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumDeclaration;
9028-
createEnumLiteralExpression(modifiers: readonly ModifierLike[] | undefined, name: string | Identifier, members: readonly EnumMember[]): EnumLiteralExpression;
9029-
updateEnumLiteralExpression(node: EnumLiteralExpression, modifiers: readonly ModifierLike[] | undefined, name: Identifier, members: readonly EnumMember[]): EnumLiteralExpression;
9028+
createEnumLiteralExpression(modifiers: readonly ModifierLike[] | undefined, name: __String, members: readonly EnumMember[]): EnumLiteralExpression;
9029+
updateEnumLiteralExpression(node: EnumLiteralExpression, modifiers: readonly ModifierLike[] | undefined, name: __String, members: readonly EnumMember[]): EnumLiteralExpression;
90309030
createModuleDeclaration(modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined, flags?: NodeFlags): ModuleDeclaration;
90319031
updateModuleDeclaration(node: ModuleDeclaration, modifiers: readonly ModifierLike[] | undefined, name: ModuleName, body: ModuleBody | undefined): ModuleDeclaration;
90329032
createModuleBlock(statements: readonly Statement[]): ModuleBlock;

tests/baselines/reference/enumLiteralBasics.errors.txt

+42-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
enumLiteralBasics.ts(6,5): error TS1061: Enum member must have initializer.
22
enumLiteralBasics.ts(7,5): error TS1061: Enum member must have initializer.
3-
enumLiteralBasics.ts(21,7): error TS2322: Type '"exists"' is not assignable to type 'E1'.
4-
enumLiteralBasics.ts(23,7): error TS2322: Type '"string"' is not assignable to type 'E1'.
5-
enumLiteralBasics.ts(33,33): error TS2345: Argument of type '"exists"' is not assignable to parameter of type 'E1'.
6-
enumLiteralBasics.ts(38,32): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'E1'.
3+
enumLiteralBasics.ts(22,1): error TS2322: Type 'E1.Flag' is not assignable to type 'E1.Int'.
4+
enumLiteralBasics.ts(27,7): error TS2322: Type '"exists"' is not assignable to type 'E1'.
5+
enumLiteralBasics.ts(29,7): error TS2322: Type '"string"' is not assignable to type 'E1'.
6+
enumLiteralBasics.ts(39,33): error TS2345: Argument of type '"exists"' is not assignable to parameter of type 'E1'.
7+
enumLiteralBasics.ts(44,32): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'E1'.
8+
enumLiteralBasics.ts(52,38): error TS2345: Argument of type '"exists"' is not assignable to parameter of type 'E1.Int'.
9+
enumLiteralBasics.ts(54,38): error TS2345: Argument of type '4' is not assignable to parameter of type 'E1.Int'.
10+
enumLiteralBasics.ts(56,38): error TS2345: Argument of type 'E1.String' is not assignable to parameter of type 'E1.Int'.
11+
enumLiteralBasics.ts(57,7): error TS2322: Type 'E1.Int' is not assignable to type 'E1.Flag'.
12+
enumLiteralBasics.ts(57,38): error TS2345: Argument of type '"string"' is not assignable to parameter of type 'E1.Int'.
713

814

9-
==== enumLiteralBasics.ts (6 errors) ====
15+
==== enumLiteralBasics.ts (12 errors) ====
1016
// Enum without initializers have first member = 0 and successive members = N + 1
1117

1218
// Enum literal syntax does not implement auto-incrementing behaviour.
@@ -28,6 +34,14 @@ enumLiteralBasics.ts(38,32): error TS2345: Argument of type '"string"' is not as
2834
const exist: E1 = E1.ExistingShorthand; // ok
2935
const ival: E1 = E1.Int; // ok
3036
const sval: E1 = E1.String; // ok
37+
let p_int: E1.Int = E1.Int; // ok
38+
const p_nonexist: E1.NonexistingShorthand = E1.NonexistingShorthand; // ok
39+
const p_exist: E1.ExistingShorthand = E1.ExistingShorthand; // ok
40+
const p_string: E1.String = E1.String; // ok
41+
p_int = E1.Flag; // Type 'E1.Flag' is not assignable to type 'E1.Int'.
42+
~~~~~
43+
!!! error TS2322: Type 'E1.Flag' is not assignable to type 'E1.Int'.
44+
p_int = E1.Int | E1.Flag;
3145

3246
// Assigning values which are not part of the enum despite being present in the enum
3347
const nonexist_bad: E1 = undefined; // error
@@ -57,4 +71,26 @@ enumLiteralBasics.ts(38,32): error TS2345: Argument of type '"string"' is not as
5771
const sval_bad2: E1 = functest("string"); // error
5872
~~~~~~~~
5973
!!! error TS2345: Argument of type '"string"' is not assignable to parameter of type 'E1'.
60-
74+
75+
function functest2(value: E1.Int) {
76+
console.log(value);
77+
return value;
78+
}
79+
80+
const nonexist_bad3: E1.Int = functest2(undefined);
81+
const exist_bad3: E1.Int = functest2("exists"); // error
82+
~~~~~~~~
83+
!!! error TS2345: Argument of type '"exists"' is not assignable to parameter of type 'E1.Int'.
84+
const ival_good5: E1.Int = functest2(1); // ok
85+
const ival_good6: E1.Int = functest2(4); // ok
86+
~
87+
!!! error TS2345: Argument of type '4' is not assignable to parameter of type 'E1.Int'.
88+
const ival_good7: E1.Int = functest2(E1.Int | E1.Flag); // ok
89+
const sval_good3: E1.Int = functest2(E1.String);
90+
~~~~~~~~~
91+
!!! error TS2345: Argument of type 'E1.String' is not assignable to parameter of type 'E1.Int'.
92+
const sval_bad3: E1.Flag = functest2("string"); // error
93+
~~~~~~~~~
94+
!!! error TS2322: Type 'E1.Int' is not assignable to type 'E1.Flag'.
95+
~~~~~~~~
96+
!!! error TS2345: Argument of type '"string"' is not assignable to parameter of type 'E1.Int'.

tests/baselines/reference/enumLiteralBasics.js

+36-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ const nonexist: E1 = E1.NonexistingShorthand; // ok
1818
const exist: E1 = E1.ExistingShorthand; // ok
1919
const ival: E1 = E1.Int; // ok
2020
const sval: E1 = E1.String; // ok
21+
let p_int: E1.Int = E1.Int; // ok
22+
const p_nonexist: E1.NonexistingShorthand = E1.NonexistingShorthand; // ok
23+
const p_exist: E1.ExistingShorthand = E1.ExistingShorthand; // ok
24+
const p_string: E1.String = E1.String; // ok
25+
p_int = E1.Flag; // Type 'E1.Flag' is not assignable to type 'E1.Int'.
26+
p_int = E1.Int | E1.Flag;
2127

2228
// Assigning values which are not part of the enum despite being present in the enum
2329
const nonexist_bad: E1 = undefined; // error
@@ -39,7 +45,19 @@ const ival_good3: E1 = functest(4); // ok
3945
const ival_good4: E1 = functest(E1.Int | E1.Flag); // ok
4046
const sval_good2: E1 = functest(E1.String);
4147
const sval_bad2: E1 = functest("string"); // error
42-
48+
49+
function functest2(value: E1.Int) {
50+
console.log(value);
51+
return value;
52+
}
53+
54+
const nonexist_bad3: E1.Int = functest2(undefined);
55+
const exist_bad3: E1.Int = functest2("exists"); // error
56+
const ival_good5: E1.Int = functest2(1); // ok
57+
const ival_good6: E1.Int = functest2(4); // ok
58+
const ival_good7: E1.Int = functest2(E1.Int | E1.Flag); // ok
59+
const sval_good3: E1.Int = functest2(E1.String);
60+
const sval_bad3: E1.Flag = functest2("string"); // error
4361

4462
//// [enumLiteralBasics.js]
4563
// Enum without initializers have first member = 0 and successive members = N + 1
@@ -57,6 +75,12 @@ var nonexist = E1.NonexistingShorthand; // ok
5775
var exist = E1.ExistingShorthand; // ok
5876
var ival = E1.Int; // ok
5977
var sval = E1.String; // ok
78+
var p_int = E1.Int; // ok
79+
var p_nonexist = E1.NonexistingShorthand; // ok
80+
var p_exist = E1.ExistingShorthand; // ok
81+
var p_string = E1.String; // ok
82+
p_int = E1.Flag; // Type 'E1.Flag' is not assignable to type 'E1.Int'.
83+
p_int = E1.Int | E1.Flag;
6084
// Assigning values which are not part of the enum despite being present in the enum
6185
var nonexist_bad = undefined; // error
6286
var exist_bad = "exists"; // error
@@ -74,3 +98,14 @@ var ival_good3 = functest(4); // ok
7498
var ival_good4 = functest(E1.Int | E1.Flag); // ok
7599
var sval_good2 = functest(E1.String);
76100
var sval_bad2 = functest("string"); // error
101+
function functest2(value) {
102+
console.log(value);
103+
return value;
104+
}
105+
var nonexist_bad3 = functest2(undefined);
106+
var exist_bad3 = functest2("exists"); // error
107+
var ival_good5 = functest2(1); // ok
108+
var ival_good6 = functest2(4); // ok
109+
var ival_good7 = functest2(E1.Int | E1.Flag); // ok
110+
var sval_good3 = functest2(E1.String);
111+
var sval_bad3 = functest2("string"); // error

0 commit comments

Comments
 (0)