mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 11:54:44 -06:00
added folding for references to enum members in enum member initializers, added tests
This commit is contained in:
parent
97460f5123
commit
ce336bcec7
@ -7473,18 +7473,31 @@ module ts {
|
||||
case SyntaxKind.PropertyAccess:
|
||||
if (!program.getCompilerOptions().propagateEnumConstants) return undefined;
|
||||
|
||||
var refSymbol =
|
||||
e.kind === SyntaxKind.Identifier
|
||||
? resolveName(member, (<Identifier>e).text, SymbolFlags.EnumMember, /*nameNotFoundMessage*/ undefined, /*nameArg*/ undefined)
|
||||
: resolveEntityName(member, e, SymbolFlags.EnumMember, /*suppressErrors*/ true);
|
||||
var enumSymbol: Symbol;
|
||||
var propertyName: string;
|
||||
|
||||
if (!refSymbol) return undefined;
|
||||
var refDecl = <EnumMember>refSymbol.valueDeclaration;
|
||||
// self references are not permitted
|
||||
// non-qualified names are permitted only to members defined in the same enum
|
||||
if (member === refDecl || (e.kind === SyntaxKind.Identifier && refDecl.parent !== member.parent)) return undefined;
|
||||
// enumMemberValue might be undefined if corresponding enum value was not yet computed and it is ok to return undefined in this case
|
||||
return <number>getNodeLinks(refDecl).enumMemberValue;
|
||||
if (e.kind === SyntaxKind.Identifier) {
|
||||
// unqualified names can refer to member that reside in different declaration of the enum so just doing name resolution won't work.
|
||||
// instead pick symbol that correspond of enum declaration and later try to fetch member from the symbol
|
||||
enumSymbol = getSymbolOfNode(member.parent);
|
||||
propertyName = (<Identifier>e).text;
|
||||
}
|
||||
else {
|
||||
// left part in PropertyAccess should be resolved to the symbol of enum that declared 'member'
|
||||
enumSymbol = resolveEntityName(member, (<PropertyAccess>e).left, SymbolFlags.Enum, /*suppressErrors*/ true);
|
||||
|
||||
if (enumSymbol !== getSymbolOfNode(member.parent)) return undefined;
|
||||
propertyName = (<Identifier>(<PropertyAccess>e).right).text;
|
||||
}
|
||||
|
||||
var propertySymbol = enumSymbol.exports[propertyName];
|
||||
if (!propertyName || !(propertySymbol.flags & SymbolFlags.EnumMember)) return undefined;
|
||||
var propertyDecl = <EnumMember>propertySymbol.valueDeclaration;
|
||||
// self references are illegal
|
||||
if (member === propertyDecl) return undefined;
|
||||
// enumMemberValue might be undefined if corresponding enum value was not yet computed
|
||||
// and it is ok to return undefined in this case (use before defition)
|
||||
return <number>getNodeLinks(propertyDecl).enumMemberValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -749,6 +749,9 @@ module Harness {
|
||||
case 'usecasesensitivefilenames':
|
||||
useCaseSensitiveFileNames = setting.value === 'true';
|
||||
break;
|
||||
case 'propagateenumconstants':
|
||||
options.propagateEnumConstants = setting.value === 'true';
|
||||
break;
|
||||
|
||||
case 'mapsourcefiles':
|
||||
case 'maproot':
|
||||
@ -757,7 +760,6 @@ module Harness {
|
||||
case 'codepage':
|
||||
case 'createFileLog':
|
||||
case 'filename':
|
||||
case 'propagateenumconstants':
|
||||
case 'removecomments':
|
||||
case 'watch':
|
||||
case 'allowautomaticsemicoloninsertion':
|
||||
@ -772,7 +774,6 @@ module Harness {
|
||||
case 'errortruncation':
|
||||
options.noErrorTruncation = setting.value === 'false';
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new Error('Unsupported compiler setting ' + setting.flag);
|
||||
}
|
||||
@ -1147,7 +1148,7 @@ module Harness {
|
||||
var optionRegex = /^[\/]{2}\s*@(\w+)\s*:\s*(\S*)/gm; // multiple matches on multiple lines
|
||||
|
||||
// List of allowed metadata names
|
||||
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames"];
|
||||
var fileMetadataNames = ["filename", "comments", "declaration", "module", "nolib", "sourcemap", "target", "out", "outdir", "noimplicitany", "noresolve", "newline", "newlines", "emitbom", "errortruncation", "usecasesensitivefilenames", "propagateenumconstants"];
|
||||
|
||||
function extractCompilerSettings(content: string): CompilerSetting[] {
|
||||
|
||||
|
||||
153
tests/baselines/reference/constantsInEnumMembers.js
Normal file
153
tests/baselines/reference/constantsInEnumMembers.js
Normal file
@ -0,0 +1,153 @@
|
||||
//// [constantsInEnumMembers.ts]
|
||||
|
||||
enum Enum1 {
|
||||
A0 = 100,
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
// correct cases
|
||||
A,
|
||||
B,
|
||||
C = 10,
|
||||
D = A + B,
|
||||
E = A + 1,
|
||||
F = 1 + A,
|
||||
G = 1 + 1,
|
||||
H = A - B,
|
||||
I = A - 1,
|
||||
J = 1 - A,
|
||||
K = 1 - 1,
|
||||
L = ~D,
|
||||
M = E << B,
|
||||
N = E << 1,
|
||||
O = E >> B,
|
||||
P = E >> 1,
|
||||
Q = -D,
|
||||
R = C & 5,
|
||||
S = 5 & C,
|
||||
T = C | D,
|
||||
U = C | 1,
|
||||
V = 10 | D,
|
||||
W = Enum1.V,
|
||||
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
W1 = A0,
|
||||
W2 = Enum1.A0,
|
||||
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
X = Y,
|
||||
// forward reference to the element of the same enum
|
||||
Y = Enum1.Z,
|
||||
Z = 100,
|
||||
}
|
||||
|
||||
|
||||
function foo(x: Enum1) {
|
||||
switch (x) {
|
||||
case Enum1.A:
|
||||
case Enum1.B:
|
||||
case Enum1.C:
|
||||
case Enum1.D:
|
||||
case Enum1.E:
|
||||
case Enum1.F:
|
||||
case Enum1.G:
|
||||
case Enum1.H:
|
||||
case Enum1.I:
|
||||
case Enum1.J:
|
||||
case Enum1.K:
|
||||
case Enum1.L:
|
||||
case Enum1.M:
|
||||
case Enum1.N:
|
||||
case Enum1.O:
|
||||
case Enum1.P:
|
||||
case Enum1.Q:
|
||||
case Enum1.R:
|
||||
case Enum1.S:
|
||||
case Enum1.T:
|
||||
case Enum1.U:
|
||||
case Enum1.V:
|
||||
case Enum1.W:
|
||||
case Enum1.W1:
|
||||
case Enum1.W2:
|
||||
case Enum1.X:
|
||||
case Enum1.Y:
|
||||
case Enum1.Z:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//// [constantsInEnumMembers.js]
|
||||
var Enum1;
|
||||
(function (Enum1) {
|
||||
Enum1[Enum1["A0"] = 100] = "A0";
|
||||
})(Enum1 || (Enum1 = {}));
|
||||
var Enum1;
|
||||
(function (Enum1) {
|
||||
// correct cases
|
||||
Enum1[Enum1["A"] = 0] = "A";
|
||||
Enum1[Enum1["B"] = 1] = "B";
|
||||
Enum1[Enum1["C"] = 10] = "C";
|
||||
Enum1[Enum1["D"] = A + B] = "D";
|
||||
Enum1[Enum1["E"] = A + 1] = "E";
|
||||
Enum1[Enum1["F"] = 1 + A] = "F";
|
||||
Enum1[Enum1["G"] = 1 + 1] = "G";
|
||||
Enum1[Enum1["H"] = A - B] = "H";
|
||||
Enum1[Enum1["I"] = A - 1] = "I";
|
||||
Enum1[Enum1["J"] = 1 - A] = "J";
|
||||
Enum1[Enum1["K"] = 1 - 1] = "K";
|
||||
Enum1[Enum1["L"] = ~D] = "L";
|
||||
Enum1[Enum1["M"] = E << B] = "M";
|
||||
Enum1[Enum1["N"] = E << 1] = "N";
|
||||
Enum1[Enum1["O"] = E >> B] = "O";
|
||||
Enum1[Enum1["P"] = E >> 1] = "P";
|
||||
Enum1[Enum1["Q"] = -D] = "Q";
|
||||
Enum1[Enum1["R"] = C & 5] = "R";
|
||||
Enum1[Enum1["S"] = 5 & C] = "S";
|
||||
Enum1[Enum1["T"] = C | D] = "T";
|
||||
Enum1[Enum1["U"] = C | 1] = "U";
|
||||
Enum1[Enum1["V"] = 10 | D] = "V";
|
||||
Enum1[Enum1["W"] = Enum1.V] = "W";
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
Enum1[Enum1["W1"] = A0] = "W1";
|
||||
Enum1[Enum1["W2"] = Enum1.A0] = "W2";
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
Enum1[Enum1["X"] = Enum1.Y] = "X";
|
||||
// forward reference to the element of the same enum
|
||||
Enum1[Enum1["Y"] = 100 /* Z */] = "Y";
|
||||
Enum1[Enum1["Z"] = 100] = "Z";
|
||||
})(Enum1 || (Enum1 = {}));
|
||||
function foo(x) {
|
||||
switch (x) {
|
||||
case 0 /* A */:
|
||||
case 1 /* B */:
|
||||
case 10 /* C */:
|
||||
case 1 /* D */:
|
||||
case 1 /* E */:
|
||||
case 1 /* F */:
|
||||
case 2 /* G */:
|
||||
case -1 /* H */:
|
||||
case -1 /* I */:
|
||||
case 1 /* J */:
|
||||
case 0 /* K */:
|
||||
case -2 /* L */:
|
||||
case 2 /* M */:
|
||||
case 2 /* N */:
|
||||
case 0 /* O */:
|
||||
case 0 /* P */:
|
||||
case -1 /* Q */:
|
||||
case 0 /* R */:
|
||||
case 0 /* S */:
|
||||
case 11 /* T */:
|
||||
case 11 /* U */:
|
||||
case 11 /* V */:
|
||||
case 11 /* W */:
|
||||
case 100 /* W1 */:
|
||||
case 100 /* W2 */:
|
||||
case Enum1.X:
|
||||
case Enum1.Y:
|
||||
case 100 /* Z */:
|
||||
break;
|
||||
}
|
||||
}
|
||||
306
tests/baselines/reference/constantsInEnumMembers.types
Normal file
306
tests/baselines/reference/constantsInEnumMembers.types
Normal file
@ -0,0 +1,306 @@
|
||||
=== tests/cases/compiler/constantsInEnumMembers.ts ===
|
||||
|
||||
enum Enum1 {
|
||||
>Enum1 : Enum1
|
||||
|
||||
A0 = 100,
|
||||
>A0 : Enum1
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
>Enum1 : Enum1
|
||||
|
||||
// correct cases
|
||||
A,
|
||||
>A : Enum1
|
||||
|
||||
B,
|
||||
>B : Enum1
|
||||
|
||||
C = 10,
|
||||
>C : Enum1
|
||||
|
||||
D = A + B,
|
||||
>D : Enum1
|
||||
>A + B : number
|
||||
>A : Enum1
|
||||
>B : Enum1
|
||||
|
||||
E = A + 1,
|
||||
>E : Enum1
|
||||
>A + 1 : number
|
||||
>A : Enum1
|
||||
|
||||
F = 1 + A,
|
||||
>F : Enum1
|
||||
>1 + A : number
|
||||
>A : Enum1
|
||||
|
||||
G = 1 + 1,
|
||||
>G : Enum1
|
||||
>1 + 1 : number
|
||||
|
||||
H = A - B,
|
||||
>H : Enum1
|
||||
>A - B : number
|
||||
>A : Enum1
|
||||
>B : Enum1
|
||||
|
||||
I = A - 1,
|
||||
>I : Enum1
|
||||
>A - 1 : number
|
||||
>A : Enum1
|
||||
|
||||
J = 1 - A,
|
||||
>J : Enum1
|
||||
>1 - A : number
|
||||
>A : Enum1
|
||||
|
||||
K = 1 - 1,
|
||||
>K : Enum1
|
||||
>1 - 1 : number
|
||||
|
||||
L = ~D,
|
||||
>L : Enum1
|
||||
>~D : number
|
||||
>D : Enum1
|
||||
|
||||
M = E << B,
|
||||
>M : Enum1
|
||||
>E << B : number
|
||||
>E : Enum1
|
||||
>B : Enum1
|
||||
|
||||
N = E << 1,
|
||||
>N : Enum1
|
||||
>E << 1 : number
|
||||
>E : Enum1
|
||||
|
||||
O = E >> B,
|
||||
>O : Enum1
|
||||
>E >> B : number
|
||||
>E : Enum1
|
||||
>B : Enum1
|
||||
|
||||
P = E >> 1,
|
||||
>P : Enum1
|
||||
>E >> 1 : number
|
||||
>E : Enum1
|
||||
|
||||
Q = -D,
|
||||
>Q : Enum1
|
||||
>-D : number
|
||||
>D : Enum1
|
||||
|
||||
R = C & 5,
|
||||
>R : Enum1
|
||||
>C & 5 : number
|
||||
>C : Enum1
|
||||
|
||||
S = 5 & C,
|
||||
>S : Enum1
|
||||
>5 & C : number
|
||||
>C : Enum1
|
||||
|
||||
T = C | D,
|
||||
>T : Enum1
|
||||
>C | D : number
|
||||
>C : Enum1
|
||||
>D : Enum1
|
||||
|
||||
U = C | 1,
|
||||
>U : Enum1
|
||||
>C | 1 : number
|
||||
>C : Enum1
|
||||
|
||||
V = 10 | D,
|
||||
>V : Enum1
|
||||
>10 | D : number
|
||||
>D : Enum1
|
||||
|
||||
W = Enum1.V,
|
||||
>W : Enum1
|
||||
>Enum1.V : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>V : Enum1
|
||||
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
W1 = A0,
|
||||
>W1 : Enum1
|
||||
>A0 : Enum1
|
||||
|
||||
W2 = Enum1.A0,
|
||||
>W2 : Enum1
|
||||
>Enum1.A0 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>A0 : Enum1
|
||||
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
X = Y,
|
||||
>X : Enum1
|
||||
>Y : Enum1
|
||||
|
||||
// forward reference to the element of the same enum
|
||||
Y = Enum1.Z,
|
||||
>Y : Enum1
|
||||
>Enum1.Z : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Z : Enum1
|
||||
|
||||
Z = 100,
|
||||
>Z : Enum1
|
||||
}
|
||||
|
||||
|
||||
function foo(x: Enum1) {
|
||||
>foo : (x: Enum1) => void
|
||||
>x : Enum1
|
||||
>Enum1 : Enum1
|
||||
|
||||
switch (x) {
|
||||
>x : Enum1
|
||||
|
||||
case Enum1.A:
|
||||
>Enum1.A : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>A : Enum1
|
||||
|
||||
case Enum1.B:
|
||||
>Enum1.B : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>B : Enum1
|
||||
|
||||
case Enum1.C:
|
||||
>Enum1.C : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>C : Enum1
|
||||
|
||||
case Enum1.D:
|
||||
>Enum1.D : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>D : Enum1
|
||||
|
||||
case Enum1.E:
|
||||
>Enum1.E : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>E : Enum1
|
||||
|
||||
case Enum1.F:
|
||||
>Enum1.F : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>F : Enum1
|
||||
|
||||
case Enum1.G:
|
||||
>Enum1.G : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>G : Enum1
|
||||
|
||||
case Enum1.H:
|
||||
>Enum1.H : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>H : Enum1
|
||||
|
||||
case Enum1.I:
|
||||
>Enum1.I : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>I : Enum1
|
||||
|
||||
case Enum1.J:
|
||||
>Enum1.J : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>J : Enum1
|
||||
|
||||
case Enum1.K:
|
||||
>Enum1.K : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>K : Enum1
|
||||
|
||||
case Enum1.L:
|
||||
>Enum1.L : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>L : Enum1
|
||||
|
||||
case Enum1.M:
|
||||
>Enum1.M : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>M : Enum1
|
||||
|
||||
case Enum1.N:
|
||||
>Enum1.N : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>N : Enum1
|
||||
|
||||
case Enum1.O:
|
||||
>Enum1.O : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>O : Enum1
|
||||
|
||||
case Enum1.P:
|
||||
>Enum1.P : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>P : Enum1
|
||||
|
||||
case Enum1.Q:
|
||||
>Enum1.Q : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Q : Enum1
|
||||
|
||||
case Enum1.R:
|
||||
>Enum1.R : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>R : Enum1
|
||||
|
||||
case Enum1.S:
|
||||
>Enum1.S : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>S : Enum1
|
||||
|
||||
case Enum1.T:
|
||||
>Enum1.T : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>T : Enum1
|
||||
|
||||
case Enum1.U:
|
||||
>Enum1.U : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>U : Enum1
|
||||
|
||||
case Enum1.V:
|
||||
>Enum1.V : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>V : Enum1
|
||||
|
||||
case Enum1.W:
|
||||
>Enum1.W : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W : Enum1
|
||||
|
||||
case Enum1.W1:
|
||||
>Enum1.W1 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W1 : Enum1
|
||||
|
||||
case Enum1.W2:
|
||||
>Enum1.W2 : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>W2 : Enum1
|
||||
|
||||
case Enum1.X:
|
||||
>Enum1.X : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>X : Enum1
|
||||
|
||||
case Enum1.Y:
|
||||
>Enum1.Y : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Y : Enum1
|
||||
|
||||
case Enum1.Z:
|
||||
>Enum1.Z : Enum1
|
||||
>Enum1 : typeof Enum1
|
||||
>Z : Enum1
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
78
tests/cases/compiler/constantsInEnumMembers.ts
Normal file
78
tests/cases/compiler/constantsInEnumMembers.ts
Normal file
@ -0,0 +1,78 @@
|
||||
// @propagateEnumConstants: true
|
||||
|
||||
enum Enum1 {
|
||||
A0 = 100,
|
||||
}
|
||||
|
||||
enum Enum1 {
|
||||
// correct cases
|
||||
A,
|
||||
B,
|
||||
C = 10,
|
||||
D = A + B,
|
||||
E = A + 1,
|
||||
F = 1 + A,
|
||||
G = 1 + 1,
|
||||
H = A - B,
|
||||
I = A - 1,
|
||||
J = 1 - A,
|
||||
K = 1 - 1,
|
||||
L = ~D,
|
||||
M = E << B,
|
||||
N = E << 1,
|
||||
O = E >> B,
|
||||
P = E >> 1,
|
||||
Q = -D,
|
||||
R = C & 5,
|
||||
S = 5 & C,
|
||||
T = C | D,
|
||||
U = C | 1,
|
||||
V = 10 | D,
|
||||
W = Enum1.V,
|
||||
|
||||
// correct cases: reference to the enum member from different enum declaration
|
||||
W1 = A0,
|
||||
W2 = Enum1.A0,
|
||||
|
||||
// illegal case
|
||||
// forward reference to the element of the same enum
|
||||
X = Y,
|
||||
// forward reference to the element of the same enum
|
||||
Y = Enum1.Z,
|
||||
Z = 100,
|
||||
}
|
||||
|
||||
|
||||
function foo(x: Enum1) {
|
||||
switch (x) {
|
||||
case Enum1.A:
|
||||
case Enum1.B:
|
||||
case Enum1.C:
|
||||
case Enum1.D:
|
||||
case Enum1.E:
|
||||
case Enum1.F:
|
||||
case Enum1.G:
|
||||
case Enum1.H:
|
||||
case Enum1.I:
|
||||
case Enum1.J:
|
||||
case Enum1.K:
|
||||
case Enum1.L:
|
||||
case Enum1.M:
|
||||
case Enum1.N:
|
||||
case Enum1.O:
|
||||
case Enum1.P:
|
||||
case Enum1.Q:
|
||||
case Enum1.R:
|
||||
case Enum1.S:
|
||||
case Enum1.T:
|
||||
case Enum1.U:
|
||||
case Enum1.V:
|
||||
case Enum1.W:
|
||||
case Enum1.W1:
|
||||
case Enum1.W2:
|
||||
case Enum1.X:
|
||||
case Enum1.Y:
|
||||
case Enum1.Z:
|
||||
break;
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user