mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
enum cleanup: apply constant folding to all enum initializers, inline accesses only for const enums
This commit is contained in:
+32
-20
@@ -9560,7 +9560,7 @@ module ts {
|
||||
}
|
||||
var initializer = member.initializer;
|
||||
if (initializer) {
|
||||
autoValue = getConstantValueForEnumMemberInitializer(initializer, enumIsConst);
|
||||
autoValue = getConstantValueForEnumMemberInitializer(initializer);
|
||||
if (autoValue === undefined) {
|
||||
if (enumIsConst) {
|
||||
error(initializer, Diagnostics.In_const_enum_declarations_member_initializer_must_be_constant_expression);
|
||||
@@ -9570,7 +9570,7 @@ module ts {
|
||||
// If it is a constant value (not undefined), it is syntactically constrained to be a number.
|
||||
// Also, we do not need to check this for ambients because there is already
|
||||
// a syntax error if it is not a constant.
|
||||
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined);
|
||||
checkTypeAssignableTo(checkExpression(initializer), enumType, initializer, /*headMessage*/ undefined);
|
||||
}
|
||||
}
|
||||
else if (enumIsConst) {
|
||||
@@ -9595,7 +9595,7 @@ module ts {
|
||||
nodeLinks.flags |= NodeCheckFlags.EnumValuesComputed;
|
||||
}
|
||||
|
||||
function getConstantValueForEnumMemberInitializer(initializer: Expression, enumIsConst: boolean): number {
|
||||
function getConstantValueForEnumMemberInitializer(initializer: Expression): number {
|
||||
return evalConstant(initializer);
|
||||
|
||||
function evalConstant(e: Node): number {
|
||||
@@ -9608,14 +9608,10 @@ module ts {
|
||||
switch ((<PrefixUnaryExpression>e).operator) {
|
||||
case SyntaxKind.PlusToken: return value;
|
||||
case SyntaxKind.MinusToken: return -value;
|
||||
case SyntaxKind.TildeToken: return enumIsConst ? ~value : undefined;
|
||||
case SyntaxKind.TildeToken: return ~value;
|
||||
}
|
||||
return undefined;
|
||||
case SyntaxKind.BinaryExpression:
|
||||
if (!enumIsConst) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var left = evalConstant((<BinaryExpression>e).left);
|
||||
if (left === undefined) {
|
||||
return undefined;
|
||||
@@ -9641,14 +9637,10 @@ module ts {
|
||||
case SyntaxKind.NumericLiteral:
|
||||
return +(<LiteralExpression>e).text;
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
return enumIsConst ? evalConstant((<ParenthesizedExpression>e).expression) : undefined;
|
||||
return evalConstant((<ParenthesizedExpression>e).expression);
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
if (!enumIsConst) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var member = initializer.parent;
|
||||
var currentType = getTypeOfSymbol(getSymbolOfNode(member.parent));
|
||||
var enumType: Type;
|
||||
@@ -9661,19 +9653,37 @@ module ts {
|
||||
propertyName = (<Identifier>e).text;
|
||||
}
|
||||
else {
|
||||
var expression: Expression;
|
||||
if (e.kind === SyntaxKind.ElementAccessExpression) {
|
||||
if ((<ElementAccessExpression>e).argumentExpression === undefined ||
|
||||
(<ElementAccessExpression>e).argumentExpression.kind !== SyntaxKind.StringLiteral) {
|
||||
return undefined;
|
||||
}
|
||||
var enumType = getTypeOfNode((<ElementAccessExpression>e).expression);
|
||||
expression = (<ElementAccessExpression>e).expression;
|
||||
propertyName = (<LiteralExpression>(<ElementAccessExpression>e).argumentExpression).text;
|
||||
}
|
||||
else {
|
||||
var enumType = getTypeOfNode((<PropertyAccessExpression>e).expression);
|
||||
expression = (<PropertyAccessExpression>e).expression;
|
||||
propertyName = (<PropertyAccessExpression>e).name.text;
|
||||
}
|
||||
if (enumType !== currentType) {
|
||||
|
||||
// expression part in ElementAccess\PropertyAccess should be either identifier or dottedName
|
||||
var current = expression;
|
||||
while (current) {
|
||||
if (current.kind === SyntaxKind.Identifier) {
|
||||
break;
|
||||
}
|
||||
else if (current.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
current = (<ElementAccessExpression>current).expression;
|
||||
}
|
||||
else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
var enumType = checkExpression(expression);
|
||||
// allow references to constant members of other enums
|
||||
if (!(enumType.symbol && (enumType.symbol.flags & SymbolFlags.Enum))) {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
@@ -9681,10 +9691,12 @@ module ts {
|
||||
if (propertyName === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var property = getPropertyOfObjectType(enumType, propertyName);
|
||||
if (!property || !(property.flags & SymbolFlags.EnumMember)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
var propertyDecl = property.valueDeclaration;
|
||||
// self references are illegal
|
||||
if (member === propertyDecl) {
|
||||
@@ -9695,6 +9707,7 @@ module ts {
|
||||
if (!isDefinedBefore(propertyDecl, member)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return <number>getNodeLinks(propertyDecl).enumMemberValue;
|
||||
}
|
||||
}
|
||||
@@ -10866,10 +10879,9 @@ module ts {
|
||||
|
||||
var symbol = getNodeLinks(node).resolvedSymbol;
|
||||
if (symbol && (symbol.flags & SymbolFlags.EnumMember)) {
|
||||
var declaration = symbol.valueDeclaration;
|
||||
var constantValue: number;
|
||||
if (declaration.kind === SyntaxKind.EnumMember) {
|
||||
return getEnumMemberValue(<EnumMember>declaration);
|
||||
// inline property\index accesses only for const enums
|
||||
if (isConstEnumDeclaration(symbol.valueDeclaration.parent)) {
|
||||
return getEnumMemberValue(<EnumMember>symbol.valueDeclaration);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -4612,15 +4612,12 @@ module ts {
|
||||
}
|
||||
|
||||
function writeEnumMemberDeclarationValue(member: EnumMember) {
|
||||
if (!member.initializer || isConst(member.parent)) {
|
||||
var value = resolver.getConstantValue(member);
|
||||
if (value !== undefined) {
|
||||
write(value.toString());
|
||||
return;
|
||||
}
|
||||
var value = resolver.getConstantValue(member);
|
||||
if (value !== undefined) {
|
||||
write(value.toString());
|
||||
return;
|
||||
}
|
||||
|
||||
if (member.initializer) {
|
||||
else if (member.initializer) {
|
||||
emit(member.initializer);
|
||||
}
|
||||
else {
|
||||
|
||||
Reference in New Issue
Block a user