mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Add greater typesafety in the expression portion of the syntax system.
Note: this change reveals that there is definitely some wonkyness going on with nodes like FunctionLikeDeclaration.
This commit is contained in:
+43
-32
@@ -4514,8 +4514,8 @@ module ts {
|
||||
}
|
||||
break;
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
if ((<UnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
|
||||
return narrowType(type, (<UnaryExpression>expr).operand, !assumeTrue);
|
||||
if ((<PrefixUnaryExpression>expr).operator === SyntaxKind.ExclamationToken) {
|
||||
return narrowType(type,(<PrefixUnaryExpression>expr).operand, !assumeTrue);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -4722,8 +4722,9 @@ module ts {
|
||||
function getContextuallyTypedParameterType(parameter: ParameterDeclaration): Type {
|
||||
var func = <FunctionLikeDeclaration>parameter.parent;
|
||||
if (func.kind === SyntaxKind.FunctionExpression || func.kind === SyntaxKind.ArrowFunction) {
|
||||
if (isContextSensitiveExpression(func)) {
|
||||
var contextualSignature = getContextualSignature(func);
|
||||
var funcExpr = <Expression>parameter.parent;
|
||||
if (isContextSensitiveExpression(funcExpr)) {
|
||||
var contextualSignature = getContextualSignature(funcExpr);
|
||||
if (contextualSignature) {
|
||||
|
||||
var funcHasRestParameters = hasRestParameters(func);
|
||||
@@ -4771,7 +4772,7 @@ module ts {
|
||||
}
|
||||
// Otherwise, if the containing function is contextually typed by a function type with exactly one call signature
|
||||
// and that call signature is non-generic, return statements are contextually typed by the return type of the signature
|
||||
var signature = getContextualSignature(func);
|
||||
var signature = getContextualSignature(<Expression><Node>func);
|
||||
if (signature) {
|
||||
return getReturnTypeOfSignature(signature);
|
||||
}
|
||||
@@ -5053,7 +5054,9 @@ module ts {
|
||||
}
|
||||
else {
|
||||
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
|
||||
type = checkExpression(memberDecl.name, contextualMapper);
|
||||
type = memberDecl.name.kind === SyntaxKind.ComputedPropertyName
|
||||
? unknownType
|
||||
: checkExpression(<Expression><Node>memberDecl.name, contextualMapper);
|
||||
}
|
||||
var prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
|
||||
prop.declarations = member.declarations;
|
||||
@@ -5115,7 +5118,7 @@ module ts {
|
||||
return s.valueDeclaration ? s.valueDeclaration.flags : s.flags & SymbolFlags.Prototype ? NodeFlags.Public | NodeFlags.Static : 0;
|
||||
}
|
||||
|
||||
function checkClassPropertyAccess(node: PropertyAccessExpression, type: Type, prop: Symbol) {
|
||||
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, type: Type, prop: Symbol) {
|
||||
var flags = getDeclarationFlagsFromSymbol(prop);
|
||||
// Public properties are always accessible
|
||||
if (!(flags & (NodeFlags.Private | NodeFlags.Protected))) {
|
||||
@@ -5154,7 +5157,15 @@ module ts {
|
||||
}
|
||||
|
||||
function checkPropertyAccess(node: PropertyAccessExpression) {
|
||||
var type = checkExpression(node.left);
|
||||
return checkPropertyAccessCore(node, node.left, node.right);
|
||||
}
|
||||
|
||||
function checkQualifiedName(node: QualifiedName) {
|
||||
return checkPropertyAccessCore(node, node.left, node.right);
|
||||
}
|
||||
|
||||
function checkPropertyAccessCore(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
|
||||
var type = checkExpression(left);
|
||||
if (type === unknownType) return type;
|
||||
if (type !== anyType) {
|
||||
var apparentType = getApparentType(getWidenedType(type));
|
||||
@@ -5162,10 +5173,10 @@ module ts {
|
||||
// handle cases when type is Type parameter with invalid constraint
|
||||
return unknownType;
|
||||
}
|
||||
var prop = getPropertyOfType(apparentType, node.right.text);
|
||||
var prop = getPropertyOfType(apparentType, right.text);
|
||||
if (!prop) {
|
||||
if (node.right.text) {
|
||||
error(node.right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(node.right), typeToString(type));
|
||||
if (right.text) {
|
||||
error(right, Diagnostics.Property_0_does_not_exist_on_type_1, declarationNameToString(right), typeToString(type));
|
||||
}
|
||||
return unknownType;
|
||||
}
|
||||
@@ -5178,8 +5189,8 @@ module ts {
|
||||
// - In a static member function or static member accessor
|
||||
// where this references the constructor function object of a derived class,
|
||||
// a super property access is permitted and must specify a public static member function of the base class.
|
||||
if (node.left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.Method) {
|
||||
error(node.right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
|
||||
if (left.kind === SyntaxKind.SuperKeyword && getDeclarationKindFromSymbol(prop) !== SyntaxKind.Method) {
|
||||
error(right, Diagnostics.Only_public_and_protected_methods_of_the_base_class_are_accessible_via_the_super_keyword);
|
||||
}
|
||||
else {
|
||||
checkClassPropertyAccess(node, type, prop);
|
||||
@@ -5477,7 +5488,7 @@ module ts {
|
||||
// String literals get string literal types unless we're reporting errors
|
||||
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
|
||||
? getStringLiteralType(<LiteralExpression>arg)
|
||||
: checkExpressionWithContextualType(arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
|
||||
: checkExpressionWithContextualType(<LiteralExpression>arg, paramType, excludeArgument && excludeArgument[i] ? identityMapper : undefined);
|
||||
}
|
||||
|
||||
// Use argument expression as error location when reporting errors
|
||||
@@ -5968,9 +5979,9 @@ module ts {
|
||||
}
|
||||
|
||||
function getReturnTypeFromBody(func: FunctionLikeDeclaration, contextualMapper?: TypeMapper): Type {
|
||||
var contextualSignature = getContextualSignature(func);
|
||||
var contextualSignature = getContextualSignature(<Expression><Node>func);
|
||||
if (func.body.kind !== SyntaxKind.FunctionBlock) {
|
||||
var unwidenedType = checkAndMarkExpression(func.body, contextualMapper);
|
||||
var unwidenedType = checkAndMarkExpression(<Expression>func.body, contextualMapper);
|
||||
var widenedType = getWidenedType(unwidenedType);
|
||||
|
||||
if (fullTypeCheck && compilerOptions.noImplicitAny && !contextualSignature && widenedType !== unwidenedType && getInnermostTypeOfNestedArrayTypes(widenedType) === anyType) {
|
||||
@@ -6126,7 +6137,7 @@ module ts {
|
||||
checkSourceElement(node.body);
|
||||
}
|
||||
else {
|
||||
var exprType = checkExpression(node.body);
|
||||
var exprType = checkExpression(<Expression>node.body);
|
||||
if (node.type) {
|
||||
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
|
||||
}
|
||||
@@ -6229,7 +6240,7 @@ module ts {
|
||||
return undefinedType;
|
||||
}
|
||||
|
||||
function checkPrefixExpression(node: UnaryExpression): Type {
|
||||
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
|
||||
var operandType = checkExpression(node.operand);
|
||||
switch (node.operator) {
|
||||
case SyntaxKind.PlusToken:
|
||||
@@ -6252,7 +6263,7 @@ module ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
function checkPostfixExpression(node: UnaryExpression): Type {
|
||||
function checkPostfixUnaryExpression(node: PostfixUnaryExpression): Type {
|
||||
var operandType = checkExpression(node.operand);
|
||||
var ok = checkArithmeticOperandType(node.operand, operandType, Diagnostics.An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type);
|
||||
if (ok) {
|
||||
@@ -6503,12 +6514,12 @@ module ts {
|
||||
// object, it serves as an indicator that all contained function and arrow expressions should be considered to
|
||||
// have the wildcard function type; this form of type check is used during overload resolution to exclude
|
||||
// contextually typed function and arrow expressions in the initial phase.
|
||||
function checkExpression(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||
function checkExpression(node: Expression | QualifiedName, contextualMapper?: TypeMapper): Type {
|
||||
var type = checkExpressionNode(node, contextualMapper);
|
||||
if (contextualMapper && contextualMapper !== identityMapper) {
|
||||
if (contextualMapper && contextualMapper !== identityMapper && node.kind !== SyntaxKind.QualifiedName) {
|
||||
var signature = getSingleCallSignature(type);
|
||||
if (signature && signature.typeParameters) {
|
||||
var contextualType = getContextualType(node);
|
||||
var contextualType = getContextualType(<Expression>node);
|
||||
if (contextualType) {
|
||||
var contextualSignature = getSingleCallSignature(contextualType);
|
||||
if (contextualSignature && !contextualSignature.typeParameters) {
|
||||
@@ -6526,7 +6537,7 @@ module ts {
|
||||
var ok =
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).left === node) ||
|
||||
(node.parent.kind === SyntaxKind.ElementAccessExpression && (<ElementAccessExpression>node.parent).expression === node) ||
|
||||
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<EntityName>node));
|
||||
((node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName) && isInRightSideOfImportOrExportAssignment(<Identifier>node));
|
||||
|
||||
if (!ok) {
|
||||
error(node, Diagnostics.const_enums_can_only_be_used_in_property_or_index_access_expressions_or_the_right_hand_side_of_an_import_declaration_or_export_assignment);
|
||||
@@ -6535,7 +6546,7 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function checkExpressionNode(node: Expression, contextualMapper: TypeMapper): Type {
|
||||
function checkExpressionNode(node: Expression | QualifiedName, contextualMapper: TypeMapper): Type {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
return checkIdentifier(<Identifier>node);
|
||||
@@ -6558,7 +6569,7 @@ module ts {
|
||||
case SyntaxKind.RegularExpressionLiteral:
|
||||
return globalRegExpType;
|
||||
case SyntaxKind.QualifiedName:
|
||||
return checkPropertyAccess(<QualifiedName>node);
|
||||
return checkQualifiedName(<QualifiedName>node);
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return checkArrayLiteral(<ArrayLiteralExpression>node, contextualMapper);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
@@ -6586,9 +6597,9 @@ module ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
return checkVoidExpression(<VoidExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return checkPrefixExpression(<UnaryExpression>node);
|
||||
return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return checkPostfixExpression(<UnaryExpression>node);
|
||||
return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return checkBinaryExpression(<BinaryExpression>node, contextualMapper);
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
@@ -8097,11 +8108,11 @@ module ts {
|
||||
function evalConstant(e: Node): number {
|
||||
switch (e.kind) {
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
var value = evalConstant((<UnaryExpression>e).operand);
|
||||
var value = evalConstant((<PrefixUnaryExpression>e).operand);
|
||||
if (value === undefined) {
|
||||
return undefined;
|
||||
}
|
||||
switch ((<UnaryExpression>e).operator) {
|
||||
switch ((<PrefixUnaryExpression>e).operator) {
|
||||
case SyntaxKind.PlusToken: return value;
|
||||
case SyntaxKind.MinusToken: return -value;
|
||||
case SyntaxKind.TildeToken: return enumIsConst ? ~value : undefined;
|
||||
@@ -8839,7 +8850,7 @@ module ts {
|
||||
else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
var symbol = getNodeLinks(entityName).resolvedSymbol;
|
||||
if (!symbol) {
|
||||
checkPropertyAccess(<QualifiedName>entityName);
|
||||
checkQualifiedName(<QualifiedName>entityName);
|
||||
}
|
||||
return getNodeLinks(entityName).resolvedSymbol;
|
||||
}
|
||||
@@ -8885,7 +8896,7 @@ module ts {
|
||||
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
var type = checkExpression(node);
|
||||
var type = checkExpression(<Expression>node);
|
||||
return type.symbol;
|
||||
|
||||
case SyntaxKind.ConstructorKeyword:
|
||||
@@ -8976,7 +8987,7 @@ module ts {
|
||||
|
||||
function getTypeOfExpression(expr: Expression): Type {
|
||||
if (isRightSideOfQualifiedNameOrPropertyAccess(expr)) {
|
||||
expr = expr.parent;
|
||||
expr = <Expression>expr.parent;
|
||||
}
|
||||
return checkExpression(expr);
|
||||
}
|
||||
|
||||
+21
-10
@@ -2268,6 +2268,12 @@ module ts {
|
||||
emit(node.right);
|
||||
}
|
||||
|
||||
function emitQualifiedName(node: QualifiedName) {
|
||||
emit(node.left);
|
||||
write(".");
|
||||
emit(node.right);
|
||||
}
|
||||
|
||||
function emitIndexedAccess(node: ElementAccessExpression) {
|
||||
if (tryEmitConstantValue(node)) {
|
||||
return;
|
||||
@@ -2374,10 +2380,8 @@ module ts {
|
||||
emit(node.expression);
|
||||
}
|
||||
|
||||
function emitUnaryExpression(node: UnaryExpression) {
|
||||
if (node.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
write(tokenToString(node.operator));
|
||||
}
|
||||
function emitPrefixUnaryExpression(node: PrefixUnaryExpression) {
|
||||
write(tokenToString(node.operator));
|
||||
// In some cases, we need to emit a space between the operator and the operand. One obvious case
|
||||
// is when the operator is an identifier, like delete or typeof. We also need to do this for plus
|
||||
// and minus expressions in certain cases. Specifically, consider the following two cases (parens
|
||||
@@ -2394,7 +2398,7 @@ module ts {
|
||||
write(" ");
|
||||
}
|
||||
else if (node.kind === SyntaxKind.PrefixUnaryExpression && node.operand.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
var operand = <UnaryExpression>node.operand;
|
||||
var operand = <PrefixUnaryExpression>node.operand;
|
||||
if (node.operator === SyntaxKind.PlusToken && (operand.operator === SyntaxKind.PlusToken || operand.operator === SyntaxKind.PlusPlusToken)) {
|
||||
write(" ");
|
||||
}
|
||||
@@ -2403,11 +2407,17 @@ module ts {
|
||||
}
|
||||
}
|
||||
emit(node.operand);
|
||||
if (node.kind === SyntaxKind.PostfixUnaryExpression) {
|
||||
write(tokenToString(node.operator));
|
||||
}
|
||||
}
|
||||
|
||||
function emitPostfixUnaryExpression(node: PostfixUnaryExpression) {
|
||||
if (node.operator >= SyntaxKind.Identifier) {
|
||||
write(" ");
|
||||
}
|
||||
emit(node.operand);
|
||||
write(tokenToString(node.operator));
|
||||
}
|
||||
|
||||
|
||||
function emitBinaryExpression(node: BinaryExpression) {
|
||||
emit(node.left);
|
||||
if (node.operator !== SyntaxKind.CommaToken) write(" ");
|
||||
@@ -3494,7 +3504,7 @@ module ts {
|
||||
case SyntaxKind.TemplateSpan:
|
||||
return emitTemplateSpan(<TemplateSpan>node);
|
||||
case SyntaxKind.QualifiedName:
|
||||
return emitPropertyAccess(<QualifiedName>node);
|
||||
return emitQualifiedName(<QualifiedName>node);
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
return emitArrayLiteral(<ArrayLiteralExpression>node);
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
@@ -3530,8 +3540,9 @@ module ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
return emitVoidExpression(<VoidExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return emitPrefixUnaryExpression(<PrefixUnaryExpression>node);
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return emitUnaryExpression(<UnaryExpression>node);
|
||||
return emitPostfixUnaryExpression(<PostfixUnaryExpression>node);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return emitBinaryExpression(<BinaryExpression>node);
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
|
||||
+74
-60
@@ -285,8 +285,9 @@ module ts {
|
||||
case SyntaxKind.VoidExpression:
|
||||
return child((<VoidExpression>node).expression);
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
return child((<PrefixUnaryExpression>node).operand);
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return child((<UnaryExpression>node).operand);
|
||||
return child((<PostfixUnaryExpression>node).operand);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return child((<BinaryExpression>node).left) ||
|
||||
child((<BinaryExpression>node).right);
|
||||
@@ -1557,8 +1558,8 @@ module ts {
|
||||
return entity;
|
||||
}
|
||||
|
||||
function parseAnyTokenNode(): Node {
|
||||
var node = createNode(token);
|
||||
function parseAnyTokenNode(): PrimaryExpression {
|
||||
var node = <PrimaryExpression>createNode(token);
|
||||
nextToken();
|
||||
return finishNode(node);
|
||||
}
|
||||
@@ -1572,7 +1573,7 @@ module ts {
|
||||
return createMissingNode();
|
||||
}
|
||||
|
||||
function parseTemplateExpression() {
|
||||
function parseTemplateExpression(): TemplateExpression {
|
||||
var template = <TemplateExpression>createNode(SyntaxKind.TemplateExpression);
|
||||
|
||||
template.head = parseLiteralNode();
|
||||
@@ -2396,7 +2397,7 @@ module ts {
|
||||
}
|
||||
else {
|
||||
// If not, we're probably better off bailing out and returning a bogus function expression.
|
||||
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, createMissingNode());
|
||||
return makeFunctionExpression(SyntaxKind.ArrowFunction, pos, /*asteriskToken:*/ undefined, /*name:*/ undefined, sig, <Expression>createMissingNode());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2510,7 +2511,7 @@ module ts {
|
||||
}
|
||||
|
||||
function parseArrowExpressionTail(pos: number, sig: ParsedSignature): FunctionExpression {
|
||||
var body: Node;
|
||||
var body: Block | Expression;
|
||||
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
body = parseFunctionBlock(/*allowYield:*/ false, /* ignoreMissingOpenBrace */ false);
|
||||
@@ -2635,8 +2636,37 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseUnaryExpressionOrHigher(): Expression {
|
||||
var pos = getNodePos();
|
||||
function parsePrefixUnaryExpression() {
|
||||
var node = <PrefixUnaryExpression>createNode(SyntaxKind.PrefixUnaryExpression);
|
||||
var operator = token;
|
||||
nextToken();
|
||||
node.operator = operator;
|
||||
node.operand = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseDeleteExpression() {
|
||||
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseTypeOfExpression() {
|
||||
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseVoidExpression() {
|
||||
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseUnaryExpressionOrHigher(): UnaryExpression {
|
||||
switch (token) {
|
||||
case SyntaxKind.PlusToken:
|
||||
case SyntaxKind.MinusToken:
|
||||
@@ -2644,24 +2674,13 @@ module ts {
|
||||
case SyntaxKind.ExclamationToken:
|
||||
case SyntaxKind.PlusPlusToken:
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
var operator = token;
|
||||
nextToken();
|
||||
return makeUnaryExpression(SyntaxKind.PrefixUnaryExpression, pos, operator, parseUnaryExpressionOrHigher());
|
||||
return parsePrefixUnaryExpression();
|
||||
case SyntaxKind.DeleteKeyword:
|
||||
var node = <DeleteExpression>createNode(SyntaxKind.DeleteExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
return parseDeleteExpression();
|
||||
case SyntaxKind.TypeOfKeyword:
|
||||
var node = <TypeOfExpression>createNode(SyntaxKind.TypeOfExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
return parseTypeOfExpression();
|
||||
case SyntaxKind.VoidKeyword:
|
||||
var node = <VoidExpression>createNode(SyntaxKind.VoidExpression);
|
||||
nextToken();
|
||||
node.expression = parseUnaryExpressionOrHigher();
|
||||
return finishNode(node);
|
||||
return parseVoidExpression();
|
||||
case SyntaxKind.LessThanToken:
|
||||
return parseTypeAssertion();
|
||||
default:
|
||||
@@ -2669,20 +2688,22 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function parsePostfixExpressionOrHigher(): Expression {
|
||||
function parsePostfixExpressionOrHigher(): PostfixExpression {
|
||||
var expression = parseLeftHandSideExpressionOrHigher();
|
||||
|
||||
Debug.assert(isLeftHandSideExpression(expression));
|
||||
if ((token === SyntaxKind.PlusPlusToken || token === SyntaxKind.MinusMinusToken) && !scanner.hasPrecedingLineBreak()) {
|
||||
var operator = token;
|
||||
var node = <PostfixUnaryExpression>createNode(SyntaxKind.PostfixUnaryExpression, expression.pos);
|
||||
node.operand = expression;
|
||||
node.operator = token;
|
||||
nextToken();
|
||||
return makeUnaryExpression(SyntaxKind.PostfixUnaryExpression, expression.pos, operator, expression);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
return expression;
|
||||
}
|
||||
|
||||
function parseLeftHandSideExpressionOrHigher(): Expression {
|
||||
function parseLeftHandSideExpressionOrHigher(): LeftHandSideExpression {
|
||||
// Original Ecma:
|
||||
// LeftHandSideExpression: See 11.2
|
||||
// NewExpression
|
||||
@@ -2713,7 +2734,7 @@ module ts {
|
||||
// the last two CallExpression productions. Or we have a MemberExpression which either
|
||||
// completes the LeftHandSideExpression, or starts the beginning of the first four
|
||||
// CallExpression productions.
|
||||
var expression: Expression;
|
||||
var expression: MemberExpression;
|
||||
if (token === SyntaxKind.SuperKeyword) {
|
||||
expression = parseSuperExpression();
|
||||
}
|
||||
@@ -2726,7 +2747,7 @@ module ts {
|
||||
return parseCallExpressionRest(expression);
|
||||
}
|
||||
|
||||
function parseMemberExpressionOrHigher(): Expression {
|
||||
function parseMemberExpressionOrHigher(): MemberExpression {
|
||||
// Note: to make our lives simpler, we decompose the the NewExpression productions and
|
||||
// place ObjectCreationExpression and FunctionExpression into PrimaryExpression.
|
||||
// like so:
|
||||
@@ -2778,7 +2799,7 @@ module ts {
|
||||
return parseMemberExpressionRest(expression);
|
||||
}
|
||||
|
||||
function parseSuperExpression(): Expression {
|
||||
function parseSuperExpression(): MemberExpression {
|
||||
var expression = parseAnyTokenNode();
|
||||
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) {
|
||||
return expression;
|
||||
@@ -2802,14 +2823,7 @@ module ts {
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function makeUnaryExpression(kind: SyntaxKind, pos: number, operator: SyntaxKind, operand: Expression): UnaryExpression {
|
||||
var node = <UnaryExpression>createNode(kind, pos);
|
||||
node.operator = operator;
|
||||
node.operand = operand;
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function parseMemberExpressionRest(expression: Expression): Expression {
|
||||
function parseMemberExpressionRest(expression: LeftHandSideExpression): MemberExpression {
|
||||
while (true) {
|
||||
var dotOrBracketStart = scanner.getTokenPos();
|
||||
if (parseOptional(SyntaxKind.DotToken)) {
|
||||
@@ -2867,7 +2881,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
else {
|
||||
indexedAccess.argumentExpression = createMissingNode();
|
||||
indexedAccess.argumentExpression = <Expression>createMissingNode();
|
||||
}
|
||||
|
||||
indexedAccess.closeBracketToken = parseTokenNode(SyntaxKind.CloseBracketToken);
|
||||
@@ -2885,11 +2899,11 @@ module ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
return expression;
|
||||
return <MemberExpression>expression;
|
||||
}
|
||||
}
|
||||
|
||||
function parseCallExpressionRest(expression: Expression): Expression {
|
||||
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
|
||||
while (true) {
|
||||
expression = parseMemberExpressionRest(expression);
|
||||
|
||||
@@ -2950,7 +2964,7 @@ module ts {
|
||||
return parseType();
|
||||
}
|
||||
|
||||
function parsePrimaryExpression(): Expression {
|
||||
function parsePrimaryExpression(): PrimaryExpression {
|
||||
switch (token) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
@@ -2963,11 +2977,11 @@ module ts {
|
||||
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
||||
return parseLiteralNode();
|
||||
case SyntaxKind.OpenParenToken:
|
||||
return parseParenExpression();
|
||||
return parseParenthesizedExpression();
|
||||
case SyntaxKind.OpenBracketToken:
|
||||
return parseArrayLiteral();
|
||||
return parseArrayLiteralExpression();
|
||||
case SyntaxKind.OpenBraceToken:
|
||||
return parseObjectLiteral();
|
||||
return parseObjectLiteralExpression();
|
||||
case SyntaxKind.FunctionKeyword:
|
||||
return parseFunctionExpression();
|
||||
case SyntaxKind.NewKeyword:
|
||||
@@ -2987,10 +3001,10 @@ module ts {
|
||||
}
|
||||
}
|
||||
error(Diagnostics.Expression_expected);
|
||||
return <Expression>createMissingNode();
|
||||
return <PrimaryExpression>createMissingNode();
|
||||
}
|
||||
|
||||
function parseParenExpression(): ParenthesizedExpression {
|
||||
function parseParenthesizedExpression(): ParenthesizedExpression {
|
||||
var node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression);
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
node.expression = allowInAnd(parseExpression);
|
||||
@@ -3000,7 +3014,7 @@ module ts {
|
||||
|
||||
function parseAssignmentExpressionOrOmittedExpression(): Expression {
|
||||
return token === SyntaxKind.CommaToken
|
||||
? createNode(SyntaxKind.OmittedExpression)
|
||||
? <Expression>createNode(SyntaxKind.OmittedExpression)
|
||||
: parseAssignmentExpressionOrHigher();
|
||||
}
|
||||
|
||||
@@ -3012,7 +3026,7 @@ module ts {
|
||||
return allowInAnd(parseAssignmentExpressionOrOmittedExpression);
|
||||
}
|
||||
|
||||
function parseArrayLiteral(): ArrayLiteralExpression {
|
||||
function parseArrayLiteralExpression(): ArrayLiteralExpression {
|
||||
var node = <ArrayLiteralExpression>createNode(SyntaxKind.ArrayLiteralExpression);
|
||||
parseExpected(SyntaxKind.OpenBracketToken);
|
||||
if (scanner.hasPrecedingLineBreak()) node.flags |= NodeFlags.MultiLine;
|
||||
@@ -3077,7 +3091,7 @@ module ts {
|
||||
return parsePropertyAssignment();
|
||||
}
|
||||
|
||||
function parseObjectLiteral(): ObjectLiteralExpression {
|
||||
function parseObjectLiteralExpression(): ObjectLiteralExpression {
|
||||
var node = <ObjectLiteralExpression>createNode(SyntaxKind.ObjectLiteralExpression);
|
||||
parseExpected(SyntaxKind.OpenBraceToken);
|
||||
if (scanner.hasPrecedingLineBreak()) {
|
||||
@@ -3109,7 +3123,7 @@ module ts {
|
||||
return isIdentifier() ? parseIdentifier() : undefined;
|
||||
}
|
||||
|
||||
function makeFunctionExpression(kind: SyntaxKind, pos: number, asteriskToken: Node, name: Identifier, sig: ParsedSignature, body: Node): FunctionExpression {
|
||||
function makeFunctionExpression(kind: SyntaxKind, pos: number, asteriskToken: Node, name: Identifier, sig: ParsedSignature, body: Block | Expression): FunctionExpression {
|
||||
var node = <FunctionExpression>createNode(kind, pos);
|
||||
node.asteriskToken = asteriskToken;
|
||||
node.name = name;
|
||||
@@ -4236,17 +4250,17 @@ module ts {
|
||||
case SyntaxKind.FunctionDeclaration: return checkFunctionDeclaration(<FunctionLikeDeclaration>node);
|
||||
case SyntaxKind.FunctionExpression: return checkFunctionExpression(<FunctionExpression>node);
|
||||
case SyntaxKind.GetAccessor: return checkGetAccessor(<MethodDeclaration>node);
|
||||
case SyntaxKind.ElementAccessExpression: return checkIndexedAccess(<ElementAccessExpression>node);
|
||||
case SyntaxKind.ElementAccessExpression: return checkElementAccessExpression(<ElementAccessExpression>node);
|
||||
case SyntaxKind.IndexSignature: return checkIndexSignature(<SignatureDeclaration>node);
|
||||
case SyntaxKind.InterfaceDeclaration: return checkInterfaceDeclaration(<InterfaceDeclaration>node);
|
||||
case SyntaxKind.LabeledStatement: return checkLabeledStatement(<LabeledStatement>node);
|
||||
case SyntaxKind.Method: return checkMethod(<MethodDeclaration>node);
|
||||
case SyntaxKind.ModuleDeclaration: return checkModuleDeclaration(<ModuleDeclaration>node);
|
||||
case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteral(<ObjectLiteralExpression>node);
|
||||
case SyntaxKind.ObjectLiteralExpression: return checkObjectLiteralExpression(<ObjectLiteralExpression>node);
|
||||
case SyntaxKind.NumericLiteral: return checkNumericLiteral(<LiteralExpression>node);
|
||||
case SyntaxKind.Parameter: return checkParameter(<ParameterDeclaration>node);
|
||||
case SyntaxKind.PostfixUnaryExpression: return checkPostfixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression: return checkPrefixOperator(<UnaryExpression>node);
|
||||
case SyntaxKind.PostfixUnaryExpression: return checkPostfixUnaryExpression(<PostfixUnaryExpression>node);
|
||||
case SyntaxKind.PrefixUnaryExpression: return checkPrefixUnaryExpression(<PrefixUnaryExpression>node);
|
||||
case SyntaxKind.Property: return checkProperty(<PropertyDeclaration>node);
|
||||
case SyntaxKind.PropertyAssignment: return checkPropertyAssignment(<PropertyDeclaration>node);
|
||||
case SyntaxKind.ReturnStatement: return checkReturnStatement(<ReturnStatement>node);
|
||||
@@ -4567,7 +4581,7 @@ module ts {
|
||||
}
|
||||
|
||||
if (expression.kind === SyntaxKind.PrefixUnaryExpression) {
|
||||
var unaryExpression = <UnaryExpression>expression;
|
||||
var unaryExpression = <PrefixUnaryExpression>expression;
|
||||
if (unaryExpression.operator === SyntaxKind.PlusToken || unaryExpression.operator === SyntaxKind.MinusToken) {
|
||||
expression = unaryExpression.operand;
|
||||
}
|
||||
@@ -4632,7 +4646,7 @@ module ts {
|
||||
checkAccessor(node);
|
||||
}
|
||||
|
||||
function checkIndexedAccess(node: ElementAccessExpression) {
|
||||
function checkElementAccessExpression(node: ElementAccessExpression) {
|
||||
if (node.argumentExpression.kind === SyntaxKind.Missing) {
|
||||
if (node.parent.kind === SyntaxKind.NewExpression &&
|
||||
(<NewExpression>node.parent).expression === node) {
|
||||
@@ -4763,7 +4777,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkObjectLiteral(node: ObjectLiteralExpression): boolean {
|
||||
function checkObjectLiteralExpression(node: ObjectLiteralExpression): boolean {
|
||||
var seen: Map<SymbolFlags> = {};
|
||||
var Property = 1;
|
||||
var GetAccessor = 2;
|
||||
@@ -5029,7 +5043,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkPostfixOperator(node: UnaryExpression) {
|
||||
function checkPostfixUnaryExpression(node: PostfixUnaryExpression) {
|
||||
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
|
||||
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
|
||||
// operated upon by a Prefix Increment(11.4.4) or a Prefix Decrement(11.4.5) operator.
|
||||
@@ -5038,7 +5052,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function checkPrefixOperator(node: UnaryExpression) {
|
||||
function checkPrefixUnaryExpression(node: PrefixUnaryExpression) {
|
||||
if (node.parserContextFlags & ParserContextFlags.StrictMode) {
|
||||
// The identifier eval or arguments may not appear as the LeftHandSideExpression of an
|
||||
// Assignment operator(11.13) or of a PostfixExpression(11.3) or as the UnaryExpression
|
||||
|
||||
+45
-19
@@ -315,7 +315,7 @@ module ts {
|
||||
flags: number;
|
||||
}
|
||||
|
||||
export interface Identifier extends Node {
|
||||
export interface Identifier extends PrimaryExpression {
|
||||
text: string; // Text of identifier (with escapes converted to characters)
|
||||
}
|
||||
|
||||
@@ -436,23 +436,49 @@ module ts {
|
||||
}
|
||||
|
||||
export interface Expression extends Node {
|
||||
_expressionBrand: any;
|
||||
contextualType?: Type; // Used to temporarily assign a contextual type during overload resolution
|
||||
}
|
||||
|
||||
export interface UnaryExpression extends Expression {
|
||||
_unaryExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface PrefixUnaryExpression extends UnaryExpression {
|
||||
operator: SyntaxKind;
|
||||
operand: Expression;
|
||||
}
|
||||
|
||||
export interface DeleteExpression extends Expression {
|
||||
export interface PostfixUnaryExpression extends PostfixExpression {
|
||||
operand: LeftHandSideExpression;
|
||||
operator: SyntaxKind;
|
||||
}
|
||||
|
||||
export interface PostfixExpression extends UnaryExpression {
|
||||
_postfixExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface LeftHandSideExpression extends PostfixExpression {
|
||||
_leftHandSideExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface MemberExpression extends LeftHandSideExpression {
|
||||
_memberExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface PrimaryExpression extends MemberExpression {
|
||||
_primaryExpressionBrand: any;
|
||||
}
|
||||
|
||||
export interface DeleteExpression extends UnaryExpression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface TypeOfExpression extends Expression {
|
||||
export interface TypeOfExpression extends UnaryExpression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface VoidExpression extends Expression {
|
||||
export interface VoidExpression extends UnaryExpression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
@@ -473,7 +499,7 @@ module ts {
|
||||
whenFalse: Expression;
|
||||
}
|
||||
|
||||
export interface FunctionExpression extends Expression, FunctionLikeDeclaration {
|
||||
export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration {
|
||||
name?: Identifier;
|
||||
body: Block | Expression; // Required, whereas the member inherited from FunctionDeclaration is optional
|
||||
}
|
||||
@@ -481,11 +507,11 @@ module ts {
|
||||
// The text property of a LiteralExpression stores the interpreted value of the literal in text form. For a StringLiteral,
|
||||
// or any literal of a template, this means quotes have been removed and escapes have been converted to actual characters.
|
||||
// For a NumericLiteral, the stored value is the toString() representation of the number. For example 1, 1.00, and 1e0 are all stored as just "1".
|
||||
export interface LiteralExpression extends Expression {
|
||||
export interface LiteralExpression extends PrimaryExpression {
|
||||
text: string;
|
||||
}
|
||||
|
||||
export interface TemplateExpression extends Expression {
|
||||
export interface TemplateExpression extends PrimaryExpression {
|
||||
head: LiteralExpression;
|
||||
templateSpans: NodeArray<TemplateSpan>;
|
||||
}
|
||||
@@ -497,46 +523,46 @@ module ts {
|
||||
literal: LiteralExpression;
|
||||
}
|
||||
|
||||
export interface ParenthesizedExpression extends Expression {
|
||||
export interface ParenthesizedExpression extends PrimaryExpression {
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
export interface ArrayLiteralExpression extends Expression {
|
||||
export interface ArrayLiteralExpression extends PrimaryExpression {
|
||||
elements: NodeArray<Expression>;
|
||||
}
|
||||
|
||||
export interface ObjectLiteralExpression extends Expression {
|
||||
export interface ObjectLiteralExpression extends PrimaryExpression {
|
||||
properties: NodeArray<Node>;
|
||||
}
|
||||
|
||||
export interface PropertyAccessExpression extends Expression {
|
||||
left: Expression;
|
||||
export interface PropertyAccessExpression extends MemberExpression {
|
||||
left: LeftHandSideExpression;
|
||||
right: Identifier;
|
||||
}
|
||||
|
||||
export interface ElementAccessExpression extends Expression {
|
||||
expression: Expression;
|
||||
export interface ElementAccessExpression extends MemberExpression {
|
||||
expression: LeftHandSideExpression;
|
||||
openBracketToken: Node;
|
||||
argumentExpression: Expression;
|
||||
closeBracketToken: Node;
|
||||
}
|
||||
|
||||
export interface CallExpression extends Expression {
|
||||
export interface CallExpression extends LeftHandSideExpression {
|
||||
expression: Expression;
|
||||
typeArguments?: NodeArray<TypeNode>;
|
||||
arguments: NodeArray<Expression>;
|
||||
}
|
||||
|
||||
export interface NewExpression extends CallExpression { }
|
||||
export interface NewExpression extends CallExpression, PrimaryExpression { }
|
||||
|
||||
export interface TaggedTemplateExpression extends Expression {
|
||||
tag: Expression;
|
||||
export interface TaggedTemplateExpression extends MemberExpression {
|
||||
tag: LeftHandSideExpression;
|
||||
template: LiteralExpression | TemplateExpression;
|
||||
}
|
||||
|
||||
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression;
|
||||
|
||||
export interface TypeAssertion extends Expression {
|
||||
export interface TypeAssertion extends UnaryExpression {
|
||||
type: TypeNode;
|
||||
expression: Expression;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user