@@ -109,6 +109,7 @@ import {
109
109
createDiagnosticForNodeFromMessageChain,
110
110
createDiagnosticMessageChainFromDiagnostic,
111
111
createEmptyExports,
112
+ createEvaluator,
112
113
createFileDiagnostic,
113
114
createGetCanonicalFileName,
114
115
createGetSymbolWalker,
@@ -1477,6 +1478,10 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1477
1478
var checkBinaryExpression = createCheckBinaryExpression();
1478
1479
var emitResolver = createResolver();
1479
1480
var nodeBuilder = createNodeBuilder();
1481
+ var evaluate = createEvaluator({
1482
+ evaluateElementAccessExpression,
1483
+ evaluateEntityNameExpression,
1484
+ });
1480
1485
1481
1486
var globals = createSymbolTable();
1482
1487
var undefinedSymbol = createSymbol(SymbolFlags.Property, "undefined" as __String);
@@ -39331,7 +39336,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
39331
39336
if (isConstContext(node) || isTemplateLiteralContext(node) || someType(getContextualType(node, /*contextFlags*/ undefined) || unknownType, isTemplateLiteralContextualType)) {
39332
39337
return getTemplateLiteralType(texts, types);
39333
39338
}
39334
- const evaluated = node.parent.kind !== SyntaxKind.TaggedTemplateExpression && evaluateTemplateExpression (node);
39339
+ const evaluated = node.parent.kind !== SyntaxKind.TaggedTemplateExpression && evaluate (node);
39335
39340
return evaluated ? getFreshTypeOfLiteralType(getStringLiteralType(evaluated)) : stringType;
39336
39341
}
39337
39342
@@ -45828,108 +45833,40 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45828
45833
return false;
45829
45834
}
45830
45835
45831
- function evaluate(expr: Expression, location?: Declaration): string | number | undefined {
45832
- switch (expr.kind) {
45833
- case SyntaxKind.PrefixUnaryExpression:
45834
- const value = evaluate((expr as PrefixUnaryExpression).operand, location);
45835
- if (typeof value === "number") {
45836
- switch ((expr as PrefixUnaryExpression).operator) {
45837
- case SyntaxKind.PlusToken:
45838
- return value;
45839
- case SyntaxKind.MinusToken:
45840
- return -value;
45841
- case SyntaxKind.TildeToken:
45842
- return ~value;
45843
- }
45844
- }
45845
- break;
45846
- case SyntaxKind.BinaryExpression:
45847
- const left = evaluate((expr as BinaryExpression).left, location);
45848
- const right = evaluate((expr as BinaryExpression).right, location);
45849
- if (typeof left === "number" && typeof right === "number") {
45850
- switch ((expr as BinaryExpression).operatorToken.kind) {
45851
- case SyntaxKind.BarToken:
45852
- return left | right;
45853
- case SyntaxKind.AmpersandToken:
45854
- return left & right;
45855
- case SyntaxKind.GreaterThanGreaterThanToken:
45856
- return left >> right;
45857
- case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
45858
- return left >>> right;
45859
- case SyntaxKind.LessThanLessThanToken:
45860
- return left << right;
45861
- case SyntaxKind.CaretToken:
45862
- return left ^ right;
45863
- case SyntaxKind.AsteriskToken:
45864
- return left * right;
45865
- case SyntaxKind.SlashToken:
45866
- return left / right;
45867
- case SyntaxKind.PlusToken:
45868
- return left + right;
45869
- case SyntaxKind.MinusToken:
45870
- return left - right;
45871
- case SyntaxKind.PercentToken:
45872
- return left % right;
45873
- case SyntaxKind.AsteriskAsteriskToken:
45874
- return left ** right;
45875
- }
45876
- }
45877
- else if (
45878
- (typeof left === "string" || typeof left === "number") &&
45879
- (typeof right === "string" || typeof right === "number") &&
45880
- (expr as BinaryExpression).operatorToken.kind === SyntaxKind.PlusToken
45881
- ) {
45882
- return "" + left + right;
45883
- }
45884
- break;
45885
- case SyntaxKind.StringLiteral:
45886
- case SyntaxKind.NoSubstitutionTemplateLiteral:
45887
- return (expr as StringLiteralLike).text;
45888
- case SyntaxKind.TemplateExpression:
45889
- return evaluateTemplateExpression(expr as TemplateExpression, location);
45890
- case SyntaxKind.NumericLiteral:
45891
- checkGrammarNumericLiteral(expr as NumericLiteral);
45892
- return +(expr as NumericLiteral).text;
45893
- case SyntaxKind.ParenthesizedExpression:
45894
- return evaluate((expr as ParenthesizedExpression).expression, location);
45895
- case SyntaxKind.Identifier: {
45896
- const identifier = expr as Identifier;
45897
- if (isInfinityOrNaNString(identifier.escapedText) && (resolveEntityName(identifier, SymbolFlags.Value, /*ignoreErrors*/ true) === getGlobalSymbol(identifier.escapedText, SymbolFlags.Value, /*diagnostic*/ undefined))) {
45898
- return +(identifier.escapedText);
45899
- }
45900
- // falls through
45836
+ function evaluateEntityNameExpression(expr: EntityNameExpression, location?: Declaration) {
45837
+ const symbol = resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true);
45838
+ if (!symbol) return undefined;
45839
+
45840
+ if (expr.kind === SyntaxKind.Identifier) {
45841
+ const identifier = expr;
45842
+ if (isInfinityOrNaNString(identifier.escapedText) && (symbol === getGlobalSymbol(identifier.escapedText, SymbolFlags.Value, /*diagnostic*/ undefined))) {
45843
+ return +(identifier.escapedText);
45901
45844
}
45902
- case SyntaxKind.PropertyAccessExpression:
45903
- if (isEntityNameExpression(expr)) {
45904
- const symbol = resolveEntityName(expr, SymbolFlags.Value, /*ignoreErrors*/ true);
45905
- if (symbol) {
45906
- if (symbol.flags & SymbolFlags.EnumMember) {
45907
- return location ? evaluateEnumMember(expr, symbol, location) : getEnumMemberValue(symbol.valueDeclaration as EnumMember);
45908
- }
45909
- if (isConstantVariable(symbol)) {
45910
- const declaration = symbol.valueDeclaration;
45911
- if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && (!location || declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location))) {
45912
- return evaluate(declaration.initializer, declaration);
45913
- }
45914
- }
45915
- }
45916
- }
45917
- break;
45918
- case SyntaxKind.ElementAccessExpression:
45919
- const root = (expr as ElementAccessExpression).expression;
45920
- if (isEntityNameExpression(root) && isStringLiteralLike((expr as ElementAccessExpression).argumentExpression)) {
45921
- const rootSymbol = resolveEntityName(root, SymbolFlags.Value, /*ignoreErrors*/ true);
45922
- if (rootSymbol && rootSymbol.flags & SymbolFlags.Enum) {
45923
- const name = escapeLeadingUnderscores(((expr as ElementAccessExpression).argumentExpression as StringLiteralLike).text);
45924
- const member = rootSymbol.exports!.get(name);
45925
- if (member) {
45926
- return location ? evaluateEnumMember(expr, member, location) : getEnumMemberValue(member.valueDeclaration as EnumMember);
45927
- }
45928
- }
45845
+ }
45846
+
45847
+ if (symbol.flags & SymbolFlags.EnumMember) {
45848
+ return location ? evaluateEnumMember(expr, symbol, location) : getEnumMemberValue(symbol.valueDeclaration as EnumMember);
45849
+ }
45850
+ if (isConstantVariable(symbol)) {
45851
+ const declaration = symbol.valueDeclaration;
45852
+ if (declaration && isVariableDeclaration(declaration) && !declaration.type && declaration.initializer && (!location || declaration !== location && isBlockScopedNameDeclaredBeforeUse(declaration, location))) {
45853
+ return evaluate(declaration.initializer, declaration);
45854
+ }
45855
+ }
45856
+ }
45857
+
45858
+ function evaluateElementAccessExpression(expr: ElementAccessExpression, location?: Declaration) {
45859
+ const root = expr.expression;
45860
+ if (isEntityNameExpression(root) && isStringLiteralLike(expr.argumentExpression)) {
45861
+ const rootSymbol = resolveEntityName(root, SymbolFlags.Value, /*ignoreErrors*/ true);
45862
+ if (rootSymbol && rootSymbol.flags & SymbolFlags.Enum) {
45863
+ const name = escapeLeadingUnderscores(expr.argumentExpression.text);
45864
+ const member = rootSymbol.exports!.get(name);
45865
+ if (member) {
45866
+ return location ? evaluateEnumMember(expr, member, location) : getEnumMemberValue(member.valueDeclaration as EnumMember);
45929
45867
}
45930
- break;
45868
+ }
45931
45869
}
45932
- return undefined;
45933
45870
}
45934
45871
45935
45872
function evaluateEnumMember(expr: Expression, symbol: Symbol, location: Declaration) {
@@ -45945,19 +45882,6 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
45945
45882
return getEnumMemberValue(declaration as EnumMember);
45946
45883
}
45947
45884
45948
- function evaluateTemplateExpression(expr: TemplateExpression, location?: Declaration) {
45949
- let result = expr.head.text;
45950
- for (const span of expr.templateSpans) {
45951
- const value = evaluate(span.expression, location);
45952
- if (value === undefined) {
45953
- return undefined;
45954
- }
45955
- result += value;
45956
- result += span.literal.text;
45957
- }
45958
- return result;
45959
- }
45960
-
45961
45885
function checkEnumDeclaration(node: EnumDeclaration) {
45962
45886
addLazyDiagnostic(() => checkEnumDeclarationWorker(node));
45963
45887
}
0 commit comments