mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Introduce a new HeritageClauseElment type.
This type represents the expression+type arguments you can get in a class or interface heritage clause section. For class-implements clauses, or interface-extends clauses, these expressions can only be identifiers or dotted names. For class extends clauses, these could be any expressions in the future. However, for now, we only support identifiers and dotted names.
This commit is contained in:
+145
-83
@@ -582,7 +582,7 @@ module ts {
|
||||
if (moduleSymbol.flags & SymbolFlags.Variable) {
|
||||
let typeAnnotation = (<VariableDeclaration>moduleSymbol.valueDeclaration).type;
|
||||
if (typeAnnotation) {
|
||||
return getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name);
|
||||
return getPropertyOfType(getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(typeAnnotation), name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -631,7 +631,7 @@ module ts {
|
||||
if (symbol.flags & SymbolFlags.Variable) {
|
||||
var typeAnnotation = (<VariableDeclaration>symbol.valueDeclaration).type;
|
||||
if (typeAnnotation) {
|
||||
return resolveSymbol(getPropertyOfType(getTypeFromTypeNode(typeAnnotation), name));
|
||||
return resolveSymbol(getPropertyOfType(getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(typeAnnotation), name));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -773,7 +773,7 @@ module ts {
|
||||
}
|
||||
|
||||
// Resolves a qualified name and any involved aliases
|
||||
function resolveEntityName(name: EntityName, meaning: SymbolFlags): Symbol {
|
||||
function resolveEntityName(name: EntityName | Expression, meaning: SymbolFlags): Symbol {
|
||||
if (getFullWidth(name) === 0) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -785,18 +785,23 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else if (name.kind === SyntaxKind.QualifiedName) {
|
||||
let namespace = resolveEntityName((<QualifiedName>name).left, SymbolFlags.Namespace);
|
||||
if (!namespace || namespace === unknownSymbol || getFullWidth((<QualifiedName>name).right) === 0) {
|
||||
else if (name.kind === SyntaxKind.QualifiedName || name.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
let left = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).left : (<PropertyAccessExpression>name).expression;
|
||||
let right = name.kind === SyntaxKind.QualifiedName ? (<QualifiedName>name).right : (<PropertyAccessExpression>name).name;
|
||||
|
||||
let namespace = resolveEntityName(left, SymbolFlags.Namespace);
|
||||
if (!namespace || namespace === unknownSymbol || getFullWidth(right) === 0) {
|
||||
return undefined;
|
||||
}
|
||||
let right = (<QualifiedName>name).right;
|
||||
symbol = getSymbol(getExportsOfSymbol(namespace), right.text, meaning);
|
||||
if (!symbol) {
|
||||
error(right, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString(right));
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
Debug.fail("Unknown entity name kind.");
|
||||
}
|
||||
Debug.assert((symbol.flags & SymbolFlags.Instantiated) === 0, "Should never get an instantiated symbol here.");
|
||||
return symbol.flags & meaning ? symbol : resolveAlias(symbol);
|
||||
}
|
||||
@@ -1255,14 +1260,15 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult {
|
||||
function isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult {
|
||||
|
||||
// get symbol of the first identifier of the entityName
|
||||
let meaning: SymbolFlags;
|
||||
if (entityName.parent.kind === SyntaxKind.TypeQuery) {
|
||||
// Typeof value
|
||||
meaning = SymbolFlags.Value | SymbolFlags.ExportValue;
|
||||
}
|
||||
else if (entityName.kind === SyntaxKind.QualifiedName ||
|
||||
else if (entityName.kind === SyntaxKind.QualifiedName || entityName.kind === SyntaxKind.PropertyAccessExpression ||
|
||||
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration) {
|
||||
// Left identifier from type reference or TypeAlias
|
||||
// Entity name of the import declaration
|
||||
@@ -2088,7 +2094,7 @@ module ts {
|
||||
}
|
||||
// Use type from type annotation if one is present
|
||||
if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
return getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(declaration.type);
|
||||
}
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
let func = <FunctionLikeDeclaration>declaration.parent;
|
||||
@@ -2225,7 +2231,7 @@ module ts {
|
||||
return links.type = checkExpression(exportAssignment.expression);
|
||||
}
|
||||
else if (exportAssignment.type) {
|
||||
return links.type = getTypeFromTypeNode(exportAssignment.type);
|
||||
return links.type = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(exportAssignment.type);
|
||||
}
|
||||
else {
|
||||
return links.type = anyType;
|
||||
@@ -2257,11 +2263,11 @@ module ts {
|
||||
function getAnnotatedAccessorType(accessor: AccessorDeclaration): Type {
|
||||
if (accessor) {
|
||||
if (accessor.kind === SyntaxKind.GetAccessor) {
|
||||
return accessor.type && getTypeFromTypeNode(accessor.type);
|
||||
return accessor.type && getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(accessor.type);
|
||||
}
|
||||
else {
|
||||
let setterTypeAnnotation = getSetAccessorTypeAnnotationNode(accessor);
|
||||
return setterTypeAnnotation && getTypeFromTypeNode(setterTypeAnnotation);
|
||||
return setterTypeAnnotation && getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(setterTypeAnnotation);
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
@@ -2429,7 +2435,7 @@ module ts {
|
||||
let declaration = <ClassDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
|
||||
let baseTypeNode = getClassBaseTypeNode(declaration);
|
||||
if (baseTypeNode) {
|
||||
let baseType = getTypeFromTypeReferenceNode(baseTypeNode);
|
||||
let baseType = getTypeFromTypeReferenceOrHeritageClauseElement(baseTypeNode);
|
||||
if (baseType !== unknownType) {
|
||||
if (getTargetType(baseType).flags & TypeFlags.Class) {
|
||||
if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
|
||||
@@ -2470,7 +2476,8 @@ module ts {
|
||||
forEach(symbol.declarations, declaration => {
|
||||
if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
|
||||
forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), node => {
|
||||
let baseType = getTypeFromTypeReferenceNode(node);
|
||||
let baseType = getTypeFromTypeReferenceOrHeritageClauseElement(node);
|
||||
|
||||
if (baseType !== unknownType) {
|
||||
if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
|
||||
@@ -2501,7 +2508,7 @@ module ts {
|
||||
if (!links.declaredType) {
|
||||
links.declaredType = resolvingType;
|
||||
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
|
||||
let type = getTypeFromTypeNode(declaration.type);
|
||||
let type = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(declaration.type);
|
||||
if (links.declaredType === resolvingType) {
|
||||
links.declaredType = type;
|
||||
}
|
||||
@@ -3043,7 +3050,7 @@ module ts {
|
||||
returnType = classType;
|
||||
}
|
||||
else if (declaration.type) {
|
||||
returnType = getTypeFromTypeNode(declaration.type);
|
||||
returnType = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(declaration.type);
|
||||
}
|
||||
else {
|
||||
// TypeScript 1.0 spec (April 2014):
|
||||
@@ -3201,7 +3208,7 @@ module ts {
|
||||
function getIndexTypeOfSymbol(symbol: Symbol, kind: IndexKind): Type {
|
||||
let declaration = getIndexDeclarationOfSymbol(symbol, kind);
|
||||
return declaration
|
||||
? declaration.type ? getTypeFromTypeNode(declaration.type) : anyType
|
||||
? declaration.type ? getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(declaration.type) : anyType
|
||||
: undefined;
|
||||
}
|
||||
|
||||
@@ -3212,7 +3219,7 @@ module ts {
|
||||
type.constraint = targetConstraint ? instantiateType(targetConstraint, type.mapper) : noConstraintType;
|
||||
}
|
||||
else {
|
||||
type.constraint = getTypeFromTypeNode((<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint);
|
||||
type.constraint = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement((<TypeParameterDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.TypeParameter)).constraint);
|
||||
}
|
||||
}
|
||||
return type.constraint === noConstraintType ? undefined : type.constraint;
|
||||
@@ -3260,7 +3267,7 @@ module ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode: TypeReferenceNode, typeParameterSymbol: Symbol): boolean {
|
||||
function isTypeParameterReferenceIllegalInConstraint(typeReferenceNode: TypeReferenceNode | HeritageClauseElement, typeParameterSymbol: Symbol): boolean {
|
||||
let links = getNodeLinks(typeReferenceNode);
|
||||
if (links.isIllegalTypeReferenceInConstraint !== undefined) {
|
||||
return links.isIllegalTypeReferenceInConstraint;
|
||||
@@ -3309,39 +3316,47 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeFromTypeReferenceNode(node: TypeReferenceNode): Type {
|
||||
function getTypeFromTypeReferenceOrHeritageClauseElement(node: TypeReferenceNode | HeritageClauseElement): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
let symbol = resolveEntityName(node.typeName, SymbolFlags.Type);
|
||||
let type: Type;
|
||||
if (symbol) {
|
||||
if ((symbol.flags & SymbolFlags.TypeParameter) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.4.1
|
||||
// Type parameters declared in a particular type parameter list
|
||||
// may not be referenced in constraints in that type parameter list
|
||||
// Implementation: such type references are resolved to 'unknown' type that usually denotes error
|
||||
type = unknownType;
|
||||
}
|
||||
else {
|
||||
type = getDeclaredTypeOfSymbol(symbol);
|
||||
if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) {
|
||||
let typeParameters = (<InterfaceType>type).typeParameters;
|
||||
if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
|
||||
type = createTypeReference(<GenericType>type, map(node.typeArguments, getTypeFromTypeNode));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
|
||||
type = undefined;
|
||||
}
|
||||
|
||||
if (node.kind !== SyntaxKind.HeritageClauseElement || isSupportedHeritageClauseElement(<HeritageClauseElement>node)) {
|
||||
let typeNameOrExpression = node.kind === SyntaxKind.TypeReference
|
||||
? (<TypeReferenceNode>node).typeName
|
||||
: (<HeritageClauseElement>node).expression;
|
||||
|
||||
let symbol = resolveEntityName(typeNameOrExpression, SymbolFlags.Type);
|
||||
if (symbol) {
|
||||
if ((symbol.flags & SymbolFlags.TypeParameter) && isTypeParameterReferenceIllegalInConstraint(node, symbol)) {
|
||||
// TypeScript 1.0 spec (April 2014): 3.4.1
|
||||
// Type parameters declared in a particular type parameter list
|
||||
// may not be referenced in constraints in that type parameter list
|
||||
// Implementation: such type references are resolved to 'unknown' type that usually denotes error
|
||||
type = unknownType;
|
||||
}
|
||||
else {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
|
||||
type = undefined;
|
||||
type = getDeclaredTypeOfSymbol(symbol);
|
||||
if (type.flags & (TypeFlags.Class | TypeFlags.Interface) && type.flags & TypeFlags.Reference) {
|
||||
let typeParameters = (<InterfaceType>type).typeParameters;
|
||||
if (node.typeArguments && node.typeArguments.length === typeParameters.length) {
|
||||
type = createTypeReference(<GenericType>type, map(node.typeArguments, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Generic_type_0_requires_1_type_argument_s, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType), typeParameters.length);
|
||||
type = undefined;
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Type_0_is_not_generic, typeToString(type));
|
||||
type = undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
links.resolvedType = type || unknownType;
|
||||
}
|
||||
return links.resolvedType;
|
||||
@@ -3419,7 +3434,7 @@ module ts {
|
||||
function getTypeFromArrayTypeNode(node: ArrayTypeNode): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = createArrayType(getTypeFromTypeNode(node.elementType));
|
||||
links.resolvedType = createArrayType(getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node.elementType));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -3437,7 +3452,7 @@ module ts {
|
||||
function getTypeFromTupleTypeNode(node: TupleTypeNode): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNode));
|
||||
links.resolvedType = createTupleType(map(node.elementTypes, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement));
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -3533,7 +3548,7 @@ module ts {
|
||||
function getTypeFromUnionTypeNode(node: UnionTypeNode): Type {
|
||||
let links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNode), /*noSubtypeReduction*/ true);
|
||||
links.resolvedType = getUnionType(map(node.types, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement), /*noSubtypeReduction*/ true);
|
||||
}
|
||||
return links.resolvedType;
|
||||
}
|
||||
@@ -3565,7 +3580,7 @@ module ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getTypeFromTypeNode(node: TypeNode | LiteralExpression): Type {
|
||||
function getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node: TypeNode | LiteralExpression | HeritageClauseElement): Type {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
return anyType;
|
||||
@@ -3582,7 +3597,9 @@ module ts {
|
||||
case SyntaxKind.StringLiteral:
|
||||
return getTypeFromStringLiteral(<LiteralExpression>node);
|
||||
case SyntaxKind.TypeReference:
|
||||
return getTypeFromTypeReferenceNode(<TypeReferenceNode>node);
|
||||
return getTypeFromTypeReferenceOrHeritageClauseElement(<TypeReferenceNode>node);
|
||||
case SyntaxKind.HeritageClauseElement:
|
||||
return getTypeFromTypeReferenceOrHeritageClauseElement(<HeritageClauseElement>node);
|
||||
case SyntaxKind.TypeQuery:
|
||||
return getTypeFromTypeQueryNode(<TypeQueryNode>node);
|
||||
case SyntaxKind.ArrayType:
|
||||
@@ -3592,7 +3609,7 @@ module ts {
|
||||
case SyntaxKind.UnionType:
|
||||
return getTypeFromUnionTypeNode(<UnionTypeNode>node);
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return getTypeFromTypeNode((<ParenthesizedTypeNode>node).type);
|
||||
return getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement((<ParenthesizedTypeNode>node).type);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
@@ -5593,7 +5610,7 @@ module ts {
|
||||
let declaration = <VariableLikeDeclaration>node.parent;
|
||||
if (node === declaration.initializer) {
|
||||
if (declaration.type) {
|
||||
return getTypeFromTypeNode(declaration.type);
|
||||
return getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(declaration.type);
|
||||
}
|
||||
if (declaration.kind === SyntaxKind.Parameter) {
|
||||
let type = getContextuallyTypedParameterType(<ParameterDeclaration>declaration);
|
||||
@@ -5796,7 +5813,7 @@ module ts {
|
||||
case SyntaxKind.NewExpression:
|
||||
return getContextualTypeForArgument(<CallExpression>parent, node);
|
||||
case SyntaxKind.TypeAssertionExpression:
|
||||
return getTypeFromTypeNode((<TypeAssertion>parent).type);
|
||||
return getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement((<TypeAssertion>parent).type);
|
||||
case SyntaxKind.BinaryExpression:
|
||||
return getContextualTypeForBinaryOperand(node);
|
||||
case SyntaxKind.PropertyAssignment:
|
||||
@@ -6597,7 +6614,7 @@ module ts {
|
||||
let typeArgumentsAreAssignable = true;
|
||||
for (let i = 0; i < typeParameters.length; i++) {
|
||||
let typeArgNode = typeArguments[i];
|
||||
let typeArgument = getTypeFromTypeNode(typeArgNode);
|
||||
let typeArgument = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(typeArgNode);
|
||||
// Do not push on this array! It has a preallocated length
|
||||
typeArgumentResultTypes[i] = typeArgument;
|
||||
if (typeArgumentsAreAssignable /* so far */) {
|
||||
@@ -7079,7 +7096,7 @@ module ts {
|
||||
|
||||
function checkTypeAssertion(node: TypeAssertion): Type {
|
||||
let exprType = checkExpression(node.expression);
|
||||
let targetType = getTypeFromTypeNode(node.type);
|
||||
let targetType = getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node.type);
|
||||
if (produceDiagnostics && targetType !== unknownType) {
|
||||
let widenedType = getWidenedType(exprType);
|
||||
if (!(isTypeAssignableTo(targetType, widenedType))) {
|
||||
@@ -7258,7 +7275,7 @@ module ts {
|
||||
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
|
||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||
if (node.type) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node.type));
|
||||
}
|
||||
|
||||
if (node.body) {
|
||||
@@ -7268,7 +7285,7 @@ module ts {
|
||||
else {
|
||||
let exprType = checkExpression(<Expression>node.body);
|
||||
if (node.type) {
|
||||
checkTypeAssignableTo(exprType, getTypeFromTypeNode(node.type), node.body, /*headMessage*/ undefined);
|
||||
checkTypeAssignableTo(exprType, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node.type), node.body, /*headMessage*/ undefined);
|
||||
}
|
||||
checkFunctionExpressionBodies(node.body);
|
||||
}
|
||||
@@ -8272,11 +8289,11 @@ module ts {
|
||||
checkDecorators(node);
|
||||
}
|
||||
|
||||
function checkTypeReference(node: TypeReferenceNode) {
|
||||
function checkTypeReferenceOrHeritageClauseElement(node: TypeReferenceNode | HeritageClauseElement) {
|
||||
// Grammar checking
|
||||
checkGrammarTypeArguments(node, node.typeArguments);
|
||||
|
||||
let type = getTypeFromTypeReferenceNode(node);
|
||||
let type = getTypeFromTypeReferenceOrHeritageClauseElement(node);
|
||||
if (type !== unknownType && node.typeArguments) {
|
||||
// Do type argument local checks only if referenced type is successfully resolved
|
||||
let len = node.typeArguments.length;
|
||||
@@ -8767,7 +8784,7 @@ module ts {
|
||||
|
||||
checkSourceElement(node.body);
|
||||
if (node.type && !isAccessor(node.kind)) {
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNode(node.type));
|
||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node.type));
|
||||
}
|
||||
|
||||
// Report an implicit any error if there is no body, no explicit return type, and node is not a private method
|
||||
@@ -9731,8 +9748,12 @@ module ts {
|
||||
let staticType = <ObjectType>getTypeOfSymbol(symbol);
|
||||
let baseTypeNode = getClassBaseTypeNode(node);
|
||||
if (baseTypeNode) {
|
||||
if (!isSupportedHeritageClauseElement(baseTypeNode)) {
|
||||
error(baseTypeNode.expression, Diagnostics.Only_type_references_are_currently_supported_in_a_class_extends_clauses);
|
||||
}
|
||||
|
||||
emitExtends = emitExtends || !isInAmbientContext(node);
|
||||
checkTypeReference(baseTypeNode);
|
||||
checkTypeReferenceOrHeritageClauseElement(baseTypeNode);
|
||||
}
|
||||
if (type.baseTypes.length) {
|
||||
if (produceDiagnostics) {
|
||||
@@ -9741,7 +9762,8 @@ module ts {
|
||||
let staticBaseType = getTypeOfSymbol(baseType.symbol);
|
||||
checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node,
|
||||
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
|
||||
if (baseType.symbol !== resolveEntityName(baseTypeNode.typeName, SymbolFlags.Value)) {
|
||||
|
||||
if (baseType.symbol !== resolveEntityName(baseTypeNode.expression, SymbolFlags.Value)) {
|
||||
error(baseTypeNode, Diagnostics.Type_name_0_in_extends_clause_does_not_reference_constructor_function_for_0, typeToString(baseType));
|
||||
}
|
||||
|
||||
@@ -9749,15 +9771,19 @@ module ts {
|
||||
}
|
||||
|
||||
// Check that base type can be evaluated as expression
|
||||
checkExpressionOrQualifiedName(baseTypeNode.typeName);
|
||||
checkExpressionOrQualifiedName(baseTypeNode.expression);
|
||||
}
|
||||
|
||||
let implementedTypeNodes = getClassImplementedTypeNodes(node);
|
||||
if (implementedTypeNodes) {
|
||||
forEach(implementedTypeNodes, typeRefNode => {
|
||||
checkTypeReference(typeRefNode);
|
||||
if (!isSupportedHeritageClauseElement(typeRefNode)) {
|
||||
error(typeRefNode.expression, Diagnostics.A_class_can_only_implement_type_references);
|
||||
}
|
||||
|
||||
checkTypeReferenceOrHeritageClauseElement(typeRefNode);
|
||||
if (produceDiagnostics) {
|
||||
let t = getTypeFromTypeReferenceNode(typeRefNode);
|
||||
let t = getTypeFromTypeReferenceOrHeritageClauseElement(typeRefNode);
|
||||
if (t !== unknownType) {
|
||||
let declaredType = (t.flags & TypeFlags.Reference) ? (<TypeReference>t).target : t;
|
||||
if (declaredType.flags & (TypeFlags.Class | TypeFlags.Interface)) {
|
||||
@@ -9879,7 +9905,7 @@ module ts {
|
||||
if (!tp1.constraint || !tp2.constraint) {
|
||||
return false;
|
||||
}
|
||||
if (!isTypeIdenticalTo(getTypeFromTypeNode(tp1.constraint), getTypeFromTypeNode(tp2.constraint))) {
|
||||
if (!isTypeIdenticalTo(getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(tp1.constraint), getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(tp2.constraint))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -9950,7 +9976,13 @@ module ts {
|
||||
}
|
||||
}
|
||||
}
|
||||
forEach(getInterfaceBaseTypeNodes(node), checkTypeReference);
|
||||
forEach(getInterfaceBaseTypeNodes(node), heritageElement => {
|
||||
if (!isSupportedHeritageClauseElement(heritageElement)) {
|
||||
error(heritageElement.expression, Diagnostics.An_interface_can_only_extend_a_type_reference);
|
||||
}
|
||||
|
||||
checkTypeReferenceOrHeritageClauseElement(heritageElement);
|
||||
});
|
||||
forEach(node.members, checkSourceElement);
|
||||
|
||||
if (produceDiagnostics) {
|
||||
@@ -10248,10 +10280,19 @@ module ts {
|
||||
checkSourceElement(node.body);
|
||||
}
|
||||
|
||||
function getFirstIdentifier(node: EntityName): Identifier {
|
||||
while (node.kind === SyntaxKind.QualifiedName) {
|
||||
node = (<QualifiedName>node).left;
|
||||
function getFirstIdentifier(node: EntityName | Expression): Identifier {
|
||||
while (true) {
|
||||
if (node.kind === SyntaxKind.QualifiedName) {
|
||||
node = (<QualifiedName>node).left;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
node = (<PropertyAccessExpression>node).expression;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
Debug.assert(node.kind === SyntaxKind.Identifier);
|
||||
return <Identifier>node;
|
||||
}
|
||||
|
||||
@@ -10478,7 +10519,7 @@ module ts {
|
||||
case SyntaxKind.SetAccessor:
|
||||
return checkAccessorDeclaration(<AccessorDeclaration>node);
|
||||
case SyntaxKind.TypeReference:
|
||||
return checkTypeReference(<TypeReferenceNode>node);
|
||||
return checkTypeReferenceOrHeritageClauseElement(<TypeReferenceNode>node);
|
||||
case SyntaxKind.TypeQuery:
|
||||
return checkTypeQuery(<TypeQueryNode>node);
|
||||
case SyntaxKind.TypeLiteral:
|
||||
@@ -10854,11 +10895,23 @@ module ts {
|
||||
// True if the given identifier is part of a type reference
|
||||
function isTypeReferenceIdentifier(entityName: EntityName): boolean {
|
||||
let node: Node = entityName;
|
||||
while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) node = node.parent;
|
||||
while (node.parent && node.parent.kind === SyntaxKind.QualifiedName) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node.parent && node.parent.kind === SyntaxKind.TypeReference;
|
||||
}
|
||||
|
||||
function isTypeNode(node: Node): boolean {
|
||||
function isHeritageClauseElementIdentifier(entityName: Node): boolean {
|
||||
let node = entityName;
|
||||
while (node.parent && node.parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node.parent && node.parent.kind === SyntaxKind.HeritageClauseElement;
|
||||
}
|
||||
|
||||
function isTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node: Node): boolean {
|
||||
if (SyntaxKind.FirstTypeNode <= node.kind && node.kind <= SyntaxKind.LastTypeNode) {
|
||||
return true;
|
||||
}
|
||||
@@ -10875,6 +10928,8 @@ module ts {
|
||||
case SyntaxKind.StringLiteral:
|
||||
// Specialized signatures can have string literals as their parameters' type names
|
||||
return node.parent.kind === SyntaxKind.Parameter;
|
||||
case SyntaxKind.HeritageClauseElement:
|
||||
return true;
|
||||
|
||||
// Identifiers and qualified names may be type nodes, depending on their context. Climb
|
||||
// above them to find the lowest container
|
||||
@@ -10883,10 +10938,15 @@ module ts {
|
||||
if (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) {
|
||||
node = node.parent;
|
||||
}
|
||||
else if (node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node) {
|
||||
node = node.parent;
|
||||
}
|
||||
// fall through
|
||||
case SyntaxKind.QualifiedName:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
// At this point, node is either a qualified name or an identifier
|
||||
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName, "'node' was expected to be a qualified name or identifier in 'isTypeNode'.");
|
||||
Debug.assert(node.kind === SyntaxKind.Identifier || node.kind === SyntaxKind.QualifiedName || node.kind === SyntaxKind.PropertyAccessExpression,
|
||||
"'node' was expected to be a qualified name, identifier or property access in 'isTypeNode'.");
|
||||
|
||||
let parent = node.parent;
|
||||
if (parent.kind === SyntaxKind.TypeQuery) {
|
||||
@@ -10902,6 +10962,8 @@ module ts {
|
||||
return true;
|
||||
}
|
||||
switch (parent.kind) {
|
||||
case SyntaxKind.HeritageClauseElement:
|
||||
return true;
|
||||
case SyntaxKind.TypeParameter:
|
||||
return node === (<TypeParameterDeclaration>parent).constraint;
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
@@ -10956,11 +11018,6 @@ module ts {
|
||||
return getLeftSideOfImportEqualsOrExportAssignment(node) !== undefined;
|
||||
}
|
||||
|
||||
function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
return (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) ||
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
}
|
||||
|
||||
function getSymbolOfEntityNameOrPropertyAccessExpression(entityName: EntityName | PropertyAccessExpression): Symbol {
|
||||
if (isDeclarationName(entityName)) {
|
||||
return getSymbolOfNode(entityName.parent);
|
||||
@@ -10982,7 +11039,12 @@ module ts {
|
||||
entityName = <QualifiedName | PropertyAccessExpression>entityName.parent;
|
||||
}
|
||||
|
||||
if (isExpression(entityName)) {
|
||||
if (isHeritageClauseElementIdentifier(<EntityName>entityName)) {
|
||||
let meaning = entityName.parent.kind === SyntaxKind.HeritageClauseElement ? SymbolFlags.Type : SymbolFlags.Namespace;
|
||||
meaning |= SymbolFlags.Alias;
|
||||
return resolveEntityName(<EntityName>entityName, meaning);
|
||||
}
|
||||
else if (isExpression(entityName)) {
|
||||
if (getFullWidth(entityName) === 0) {
|
||||
// Missing entity name.
|
||||
return undefined;
|
||||
@@ -11098,12 +11160,12 @@ module ts {
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
if (isExpression(node)) {
|
||||
return getTypeOfExpression(<Expression>node);
|
||||
if (isTypeNodeOrStringLiteralTypeOrHeritageClauseElement(node)) {
|
||||
return getTypeFromTypeNodeOrStringLiteralTypeOrHeritageClauseElement(<TypeNode>node);
|
||||
}
|
||||
|
||||
if (isTypeNode(node)) {
|
||||
return getTypeFromTypeNode(<TypeNode>node);
|
||||
if (isExpression(node)) {
|
||||
return getTypeOfExpression(<Expression>node);
|
||||
}
|
||||
|
||||
if (isTypeDeclaration(node)) {
|
||||
|
||||
@@ -314,12 +314,12 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type: TypeNode | EntityName, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
|
||||
function emitTypeWithNewGetSymbolAccessibilityDiagnostic(type: TypeNode | EntityName | HeritageClauseElement, getSymbolAccessibilityDiagnostic: GetSymbolAccessibilityDiagnostic) {
|
||||
writer.getSymbolAccessibilityDiagnostic = getSymbolAccessibilityDiagnostic;
|
||||
emitType(type);
|
||||
}
|
||||
|
||||
function emitType(type: TypeNode | StringLiteralExpression | Identifier | QualifiedName) {
|
||||
function emitType(type: TypeNode | StringLiteralExpression | Identifier | QualifiedName | HeritageClauseElement) {
|
||||
switch (type.kind) {
|
||||
case SyntaxKind.AnyKeyword:
|
||||
case SyntaxKind.StringKeyword:
|
||||
@@ -329,6 +329,8 @@ module ts {
|
||||
case SyntaxKind.VoidKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return writeTextOfNode(currentSourceFile, type);
|
||||
case SyntaxKind.HeritageClauseElement:
|
||||
return emitHeritageClauseElement(<HeritageClauseElement>type);
|
||||
case SyntaxKind.TypeReference:
|
||||
return emitTypeReference(<TypeReferenceNode>type);
|
||||
case SyntaxKind.TypeQuery:
|
||||
@@ -350,11 +352,9 @@ module ts {
|
||||
return emitEntityName(<Identifier>type);
|
||||
case SyntaxKind.QualifiedName:
|
||||
return emitEntityName(<QualifiedName>type);
|
||||
default:
|
||||
Debug.fail("Unknown type annotation: " + type.kind);
|
||||
}
|
||||
|
||||
function emitEntityName(entityName: EntityName) {
|
||||
function emitEntityName(entityName: EntityName | PropertyAccessExpression) {
|
||||
let visibilityResult = resolver.isEntityNameVisible(entityName,
|
||||
// Aliases can be written asynchronously so use correct enclosing declaration
|
||||
entityName.parent.kind === SyntaxKind.ImportEqualsDeclaration ? entityName.parent : enclosingDeclaration);
|
||||
@@ -362,15 +362,28 @@ module ts {
|
||||
handleSymbolAccessibilityError(visibilityResult);
|
||||
writeEntityName(entityName);
|
||||
|
||||
function writeEntityName(entityName: EntityName) {
|
||||
function writeEntityName(entityName: EntityName | Expression) {
|
||||
if (entityName.kind === SyntaxKind.Identifier) {
|
||||
writeTextOfNode(currentSourceFile, entityName);
|
||||
}
|
||||
else {
|
||||
let qualifiedName = <QualifiedName>entityName;
|
||||
writeEntityName(qualifiedName.left);
|
||||
let left = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).left : (<PropertyAccessExpression>entityName).expression;
|
||||
let right = entityName.kind === SyntaxKind.QualifiedName ? (<QualifiedName>entityName).right : (<PropertyAccessExpression>entityName).name;
|
||||
writeEntityName(left);
|
||||
write(".");
|
||||
writeTextOfNode(currentSourceFile, qualifiedName.right);
|
||||
writeTextOfNode(currentSourceFile, right);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function emitHeritageClauseElement(node: HeritageClauseElement) {
|
||||
if (isSupportedHeritageClauseElement(node)) {
|
||||
Debug.assert(node.expression.kind === SyntaxKind.Identifier || node.expression.kind === SyntaxKind.PropertyAccessExpression);
|
||||
emitEntityName(<Identifier | PropertyAccessExpression>node.expression);
|
||||
if (node.typeArguments) {
|
||||
write("<");
|
||||
emitCommaList(node.typeArguments, emitType);
|
||||
write(">");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -827,14 +840,16 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitHeritageClause(typeReferences: TypeReferenceNode[], isImplementsList: boolean) {
|
||||
function emitHeritageClause(typeReferences: HeritageClauseElement[], isImplementsList: boolean) {
|
||||
if (typeReferences) {
|
||||
write(isImplementsList ? " implements " : " extends ");
|
||||
emitCommaList(typeReferences, emitTypeOfTypeReference);
|
||||
}
|
||||
|
||||
function emitTypeOfTypeReference(node: TypeReferenceNode) {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
|
||||
function emitTypeOfTypeReference(node: HeritageClauseElement) {
|
||||
if (isSupportedHeritageClauseElement(node)) {
|
||||
emitTypeWithNewGetSymbolAccessibilityDiagnostic(node, getHeritageClauseVisibilityError);
|
||||
}
|
||||
|
||||
function getHeritageClauseVisibilityError(symbolAccesibilityResult: SymbolAccessiblityResult): SymbolAccessibilityDiagnostic {
|
||||
let diagnosticMessage: DiagnosticMessage;
|
||||
|
||||
@@ -351,6 +351,8 @@ module ts {
|
||||
The_arguments_object_cannot_be_referenced_in_an_arrow_function_Consider_using_a_standard_function_expression: { code: 2496, category: DiagnosticCategory.Error, key: "The 'arguments' object cannot be referenced in an arrow function. Consider using a standard function expression." },
|
||||
External_module_0_resolves_to_a_non_module_entity_and_cannot_be_imported_using_this_construct: { code: 2497, category: DiagnosticCategory.Error, key: "External module '{0}' resolves to a non-module entity and cannot be imported using this construct." },
|
||||
External_module_0_uses_export_and_cannot_be_used_with_export_Asterisk: { code: 2498, category: DiagnosticCategory.Error, key: "External module '{0}' uses 'export =' and cannot be used with 'export *'." },
|
||||
An_interface_can_only_extend_a_type_reference: { code: 2499, category: DiagnosticCategory.Error, key: "An interface can only extend a type reference." },
|
||||
A_class_can_only_implement_type_references: { code: 2500, category: DiagnosticCategory.Error, key: "A class can only implement type references." },
|
||||
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },
|
||||
Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." },
|
||||
@@ -498,5 +500,6 @@ module ts {
|
||||
You_cannot_rename_elements_that_are_defined_in_the_standard_TypeScript_library: { code: 8001, category: DiagnosticCategory.Error, key: "You cannot rename elements that are defined in the standard TypeScript library." },
|
||||
yield_expressions_are_not_currently_supported: { code: 9000, category: DiagnosticCategory.Error, key: "'yield' expressions are not currently supported." },
|
||||
Generators_are_not_currently_supported: { code: 9001, category: DiagnosticCategory.Error, key: "Generators are not currently supported." },
|
||||
Only_type_references_are_currently_supported_in_a_class_extends_clauses: { code: 9002, category: DiagnosticCategory.Error, key: "Only type references are currently supported in a class 'extends' clauses." },
|
||||
};
|
||||
}
|
||||
@@ -1396,6 +1396,14 @@
|
||||
"category": "Error",
|
||||
"code": 2498
|
||||
},
|
||||
"An interface can only extend a type reference.": {
|
||||
"category": "Error",
|
||||
"code": 2499
|
||||
},
|
||||
"A class can only implement type references.": {
|
||||
"category": "Error",
|
||||
"code": 2500
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
@@ -1985,5 +1993,9 @@
|
||||
"Generators are not currently supported.": {
|
||||
"category": "Error",
|
||||
"code": 9001
|
||||
},
|
||||
"Only type references are currently supported in a class 'extends' clauses.": {
|
||||
"category": "Error",
|
||||
"code": 9002
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3314,7 +3314,7 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitConstructor(node: ClassDeclaration, baseTypeNode: TypeReferenceNode) {
|
||||
function emitConstructor(node: ClassDeclaration, baseTypeElement: HeritageClauseElement) {
|
||||
let saveTempFlags = tempFlags;
|
||||
let saveTempVariables = tempVariables;
|
||||
let saveTempParameters = tempParameters;
|
||||
@@ -3368,7 +3368,7 @@ module ts {
|
||||
// Let constructor be the result of parsing the String "constructor(... args){ super (...args);}" using the syntactic grammar with the goal symbol MethodDefinition.
|
||||
// Else,
|
||||
// Let constructor be the result of parsing the String "constructor( ){ }" using the syntactic grammar with the goal symbol MethodDefinition
|
||||
if (baseTypeNode) {
|
||||
if (baseTypeElement) {
|
||||
write("(...args)");
|
||||
}
|
||||
else {
|
||||
@@ -3387,7 +3387,7 @@ module ts {
|
||||
if (ctor) {
|
||||
emitDefaultValueAssignments(ctor);
|
||||
emitRestParameter(ctor);
|
||||
if (baseTypeNode) {
|
||||
if (baseTypeElement) {
|
||||
var superCall = findInitialSuperCall(ctor);
|
||||
if (superCall) {
|
||||
writeLine();
|
||||
@@ -3397,16 +3397,16 @@ module ts {
|
||||
emitParameterPropertyAssignments(ctor);
|
||||
}
|
||||
else {
|
||||
if (baseTypeNode) {
|
||||
if (baseTypeElement) {
|
||||
writeLine();
|
||||
emitStart(baseTypeNode);
|
||||
emitStart(baseTypeElement);
|
||||
if (languageVersion < ScriptTarget.ES6) {
|
||||
write("_super.apply(this, arguments);");
|
||||
}
|
||||
else {
|
||||
write("super(...args);");
|
||||
}
|
||||
emitEnd(baseTypeNode);
|
||||
emitEnd(baseTypeElement);
|
||||
}
|
||||
}
|
||||
emitMemberAssignments(node, /*staticFlag*/0);
|
||||
@@ -3525,7 +3525,7 @@ module ts {
|
||||
var baseTypeNode = getClassBaseTypeNode(node);
|
||||
if (baseTypeNode) {
|
||||
write(" extends ");
|
||||
emit(baseTypeNode.typeName);
|
||||
emit(baseTypeNode.expression);
|
||||
}
|
||||
|
||||
write(" {");
|
||||
@@ -3639,7 +3639,7 @@ module ts {
|
||||
emitStart(node);
|
||||
write(")(");
|
||||
if (baseTypeNode) {
|
||||
emit(baseTypeNode.typeName);
|
||||
emit(baseTypeNode.expression);
|
||||
}
|
||||
write(");");
|
||||
emitEnd(node);
|
||||
|
||||
+84
-20
@@ -308,6 +308,9 @@ module ts {
|
||||
return visitNode(cbNode, (<ComputedPropertyName>node).expression);
|
||||
case SyntaxKind.HeritageClause:
|
||||
return visitNodes(cbNodes, (<HeritageClause>node).types);
|
||||
case SyntaxKind.HeritageClauseElement:
|
||||
return visitNode(cbNode, (<HeritageClauseElement>node).expression) ||
|
||||
visitNodes(cbNodes, (<HeritageClauseElement>node).typeArguments);
|
||||
case SyntaxKind.ExternalModuleReference:
|
||||
return visitNode(cbNode, (<ExternalModuleReference>node).expression);
|
||||
case SyntaxKind.MissingDeclaration:
|
||||
@@ -324,7 +327,7 @@ module ts {
|
||||
TypeMembers, // Members in interface or type literal
|
||||
ClassMembers, // Members in class declaration
|
||||
EnumMembers, // Members in enum declaration
|
||||
TypeReferences, // Type references in extends or implements clause
|
||||
HeritageClauseElement, // Elements in a heritage clause
|
||||
VariableDeclarations, // Variable declarations in variable statement
|
||||
ObjectBindingElements, // Binding elements in object binding list
|
||||
ArrayBindingElements, // Binding elements in array binding list
|
||||
@@ -356,7 +359,7 @@ module ts {
|
||||
case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected;
|
||||
case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected;
|
||||
case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected;
|
||||
case ParsingContext.TypeReferences: return Diagnostics.Type_reference_expected;
|
||||
case ParsingContext.HeritageClauseElement: return Diagnostics.Expression_expected;
|
||||
case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected;
|
||||
case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected;
|
||||
case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected;
|
||||
@@ -1614,10 +1617,22 @@ module ts {
|
||||
return token === SyntaxKind.OpenBracketToken || token === SyntaxKind.AsteriskToken || isLiteralPropertyName();
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return isLiteralPropertyName();
|
||||
case ParsingContext.TypeReferences:
|
||||
// We want to make sure that the "extends" in "extends foo" or the "implements" in
|
||||
// "implements foo" is not considered a type name.
|
||||
return isIdentifier() && !isNotHeritageClauseTypeName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
// If we see { } then only consume it as an expression if it is followed by , or {
|
||||
// That way we won't consume the body of a class in its heritage clause.
|
||||
if (token === SyntaxKind.OpenBraceToken) {
|
||||
return lookAhead(isValidHeritageClauseObjectLiteral);
|
||||
}
|
||||
|
||||
if (!inErrorRecovery) {
|
||||
return isStartOfLeftHandSideExpression() && !isHeritageClauseExtendsOrImplementsKeyword();
|
||||
}
|
||||
else {
|
||||
// If we're in error recovery we tighten up what we're willing to match.
|
||||
// That way we don't treat something like "this" as a valid heritage clause
|
||||
// element during recovery.
|
||||
return isIdentifier() && !isHeritageClauseExtendsOrImplementsKeyword();
|
||||
}
|
||||
case ParsingContext.VariableDeclarations:
|
||||
return isIdentifierOrPattern();
|
||||
case ParsingContext.ArrayBindingElements:
|
||||
@@ -1641,21 +1656,44 @@ module ts {
|
||||
Debug.fail("Non-exhaustive case in 'isListElement'.");
|
||||
}
|
||||
|
||||
function isValidHeritageClauseObjectLiteral() {
|
||||
Debug.assert(token === SyntaxKind.OpenBraceToken);
|
||||
if (nextToken() === SyntaxKind.CloseBraceToken) {
|
||||
// if we see "extends {}" then only treat the {} as what we're extending (and not
|
||||
// the class body) if we have:
|
||||
//
|
||||
// extends {} {
|
||||
// extends {},
|
||||
// extends {} extends
|
||||
// extends {} implements
|
||||
|
||||
let next = nextToken();
|
||||
return next === SyntaxKind.CommaToken || next === SyntaxKind.OpenBraceToken || next === SyntaxKind.ExtendsKeyword || next === SyntaxKind.ImplementsKeyword;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
function nextTokenIsIdentifier() {
|
||||
nextToken();
|
||||
return isIdentifier();
|
||||
}
|
||||
|
||||
function isNotHeritageClauseTypeName(): boolean {
|
||||
function isHeritageClauseExtendsOrImplementsKeyword(): boolean {
|
||||
if (token === SyntaxKind.ImplementsKeyword ||
|
||||
token === SyntaxKind.ExtendsKeyword) {
|
||||
|
||||
return lookAhead(nextTokenIsIdentifier);
|
||||
return lookAhead(nextTokenIsStartOfExpression);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function nextTokenIsStartOfExpression() {
|
||||
nextToken();
|
||||
return isStartOfExpression();
|
||||
}
|
||||
|
||||
// True if positioned at a list terminator
|
||||
function isListTerminator(kind: ParsingContext): boolean {
|
||||
if (token === SyntaxKind.EndOfFileToken) {
|
||||
@@ -1676,7 +1714,7 @@ module ts {
|
||||
return token === SyntaxKind.CloseBraceToken;
|
||||
case ParsingContext.SwitchClauseStatements:
|
||||
return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword;
|
||||
case ParsingContext.TypeReferences:
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
return token === SyntaxKind.OpenBraceToken || token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword;
|
||||
case ParsingContext.VariableDeclarations:
|
||||
return isVariableDeclaratorListTerminator();
|
||||
@@ -1891,12 +1929,6 @@ module ts {
|
||||
// This would probably be safe to reuse. There is no speculative parsing with
|
||||
// heritage clauses.
|
||||
|
||||
case ParsingContext.TypeReferences:
|
||||
// This would probably be safe to reuse. There is no speculative parsing with
|
||||
// type names in a heritage clause. There can be generic names in the type
|
||||
// name list. But because it is a type context, we never use speculative
|
||||
// parsing on the type argument list.
|
||||
|
||||
case ParsingContext.TypeParameters:
|
||||
// This would probably be safe to reuse. There is no speculative parsing with
|
||||
// type parameters. Note that that's because type *parameters* only occur in
|
||||
@@ -1923,6 +1955,12 @@ module ts {
|
||||
// cases. i.e. a property assignment may end with an expression, and thus might
|
||||
// have lookahead far beyond it's old node.
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
|
||||
// This is probably not safe to reuse. There can be speculative parsing with
|
||||
// type names in a heritage clause. There can be generic names in the type
|
||||
// name list, and there can be left hand side expressions (which can have type
|
||||
// arguments.)
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -2846,8 +2884,7 @@ module ts {
|
||||
}
|
||||
|
||||
// EXPRESSIONS
|
||||
|
||||
function isStartOfExpression(): boolean {
|
||||
function isStartOfLeftHandSideExpression(): boolean {
|
||||
switch (token) {
|
||||
case SyntaxKind.ThisKeyword:
|
||||
case SyntaxKind.SuperKeyword:
|
||||
@@ -2865,6 +2902,19 @@ module ts {
|
||||
case SyntaxKind.NewKeyword:
|
||||
case SyntaxKind.SlashToken:
|
||||
case SyntaxKind.SlashEqualsToken:
|
||||
case SyntaxKind.Identifier:
|
||||
return true;
|
||||
default:
|
||||
return isIdentifier();
|
||||
}
|
||||
}
|
||||
|
||||
function isStartOfExpression(): boolean {
|
||||
if (isStartOfLeftHandSideExpression()) {
|
||||
return true;
|
||||
}
|
||||
|
||||
switch (token) {
|
||||
case SyntaxKind.PlusToken:
|
||||
case SyntaxKind.MinusToken:
|
||||
case SyntaxKind.TildeToken:
|
||||
@@ -2875,7 +2925,6 @@ module ts {
|
||||
case SyntaxKind.PlusPlusToken:
|
||||
case SyntaxKind.MinusMinusToken:
|
||||
case SyntaxKind.LessThanToken:
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.YieldKeyword:
|
||||
// Yield always starts an expression. Either it is an identifier (in which case
|
||||
// it is definitely an expression). Or it's a keyword (either because we're in
|
||||
@@ -3667,7 +3716,6 @@ module ts {
|
||||
case SyntaxKind.CloseBracketToken: // foo<x>]
|
||||
case SyntaxKind.ColonToken: // foo<x>:
|
||||
case SyntaxKind.SemicolonToken: // foo<x>;
|
||||
case SyntaxKind.CommaToken: // foo<x>,
|
||||
case SyntaxKind.QuestionToken: // foo<x>?
|
||||
case SyntaxKind.EqualsEqualsToken: // foo<x> ==
|
||||
case SyntaxKind.EqualsEqualsEqualsToken: // foo<x> ===
|
||||
@@ -3685,6 +3733,12 @@ module ts {
|
||||
// treat it as such.
|
||||
return true;
|
||||
|
||||
case SyntaxKind.CommaToken: // foo<x>,
|
||||
case SyntaxKind.OpenBraceToken: // foo<x> {
|
||||
// We don't want to treat these as type arguments. Otherwise we'll parse this
|
||||
// as an invocation expression. Instead, we want to parse out the expression
|
||||
// in isolation from the type arguments.
|
||||
|
||||
default:
|
||||
// Anything else treat as an expression.
|
||||
return false;
|
||||
@@ -4714,13 +4768,23 @@ module ts {
|
||||
let node = <HeritageClause>createNode(SyntaxKind.HeritageClause);
|
||||
node.token = token;
|
||||
nextToken();
|
||||
node.types = parseDelimitedList(ParsingContext.TypeReferences, parseTypeReference);
|
||||
node.types = parseDelimitedList(ParsingContext.HeritageClauseElement, parseHeritageClauseElement);
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseHeritageClauseElement(): HeritageClauseElement {
|
||||
let node = <HeritageClauseElement>createNode(SyntaxKind.HeritageClauseElement);
|
||||
node.expression = parseLeftHandSideExpressionOrHigher();
|
||||
if (token === SyntaxKind.LessThanToken) {
|
||||
node.typeArguments = parseBracketedList(ParsingContext.TypeArguments, parseType, SyntaxKind.LessThanToken, SyntaxKind.GreaterThanToken);
|
||||
}
|
||||
|
||||
return finishNode(node);
|
||||
}
|
||||
|
||||
function isHeritageClause(): boolean {
|
||||
return token === SyntaxKind.ExtendsKeyword || token === SyntaxKind.ImplementsKeyword;
|
||||
}
|
||||
|
||||
@@ -206,6 +206,7 @@ module ts {
|
||||
OmittedExpression,
|
||||
// Misc
|
||||
TemplateSpan,
|
||||
HeritageClauseElement,
|
||||
// Element
|
||||
Block,
|
||||
VariableStatement,
|
||||
@@ -728,6 +729,11 @@ module ts {
|
||||
arguments: NodeArray<Expression>;
|
||||
}
|
||||
|
||||
export interface HeritageClauseElement extends Node {
|
||||
expression: LeftHandSideExpression;
|
||||
typeArguments?: NodeArray<TypeNode>;
|
||||
}
|
||||
|
||||
export interface NewExpression extends CallExpression, PrimaryExpression { }
|
||||
|
||||
export interface TaggedTemplateExpression extends MemberExpression {
|
||||
@@ -869,7 +875,7 @@ module ts {
|
||||
|
||||
export interface HeritageClause extends Node {
|
||||
token: SyntaxKind;
|
||||
types?: NodeArray<TypeReferenceNode>;
|
||||
types?: NodeArray<HeritageClauseElement>;
|
||||
}
|
||||
|
||||
export interface TypeAliasDeclaration extends Declaration, ModuleElement {
|
||||
@@ -1231,7 +1237,7 @@ module ts {
|
||||
writeReturnTypeOfSignatureDeclaration(signatureDeclaration: SignatureDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
writeTypeOfExpression(expr: Expression, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter): void;
|
||||
isSymbolAccessible(symbol: Symbol, enclosingDeclaration: Node, meaning: SymbolFlags): SymbolAccessiblityResult;
|
||||
isEntityNameVisible(entityName: EntityName, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
isEntityNameVisible(entityName: EntityName | Expression, enclosingDeclaration: Node): SymbolVisibilityResult;
|
||||
// Returns the constant value this property access resolves to, or 'undefined' for a non-constant
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
resolvesToSomeValue(location: Node, name: string): boolean;
|
||||
|
||||
@@ -1768,4 +1768,26 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
// Returns true if this heritage clause element's expression contains something unsupported
|
||||
// (i.e. not a name or dotted name).
|
||||
export function isSupportedHeritageClauseElement(node: HeritageClauseElement): boolean {
|
||||
return isSupportedHeritageClauseElementExpression(node.expression);
|
||||
}
|
||||
|
||||
function isSupportedHeritageClauseElementExpression(node: Expression): boolean {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
return true;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
return isSupportedHeritageClauseElementExpression((<PropertyAccessExpression>node).expression);
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
export function isRightSideOfQualifiedNameOrPropertyAccess(node: Node) {
|
||||
return (node.parent.kind === SyntaxKind.QualifiedName && (<QualifiedName>node.parent).right === node) ||
|
||||
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,7 +38,6 @@ class TypeWriterWalker {
|
||||
case ts.SyntaxKind.SuperKeyword:
|
||||
case ts.SyntaxKind.ArrayLiteralExpression:
|
||||
case ts.SyntaxKind.ObjectLiteralExpression:
|
||||
case ts.SyntaxKind.PropertyAccessExpression:
|
||||
case ts.SyntaxKind.ElementAccessExpression:
|
||||
case ts.SyntaxKind.CallExpression:
|
||||
case ts.SyntaxKind.NewExpression:
|
||||
@@ -56,6 +55,14 @@ class TypeWriterWalker {
|
||||
this.log(node, this.getTypeOfNode(node));
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.PropertyAccessExpression:
|
||||
for (var current = node; current.kind === ts.SyntaxKind.PropertyAccessExpression; current = current.parent) {
|
||||
}
|
||||
if (current.kind !== ts.SyntaxKind.HeritageClauseElement) {
|
||||
this.log(node, this.getTypeOfNode(node));
|
||||
}
|
||||
break;
|
||||
|
||||
// Should not change expression status (maybe expressions)
|
||||
// TODO: Again, ideally should log number and string literals too,
|
||||
// but to be consistent with the old typeWriter, just log identifiers
|
||||
|
||||
@@ -2932,7 +2932,7 @@ module ts {
|
||||
|
||||
function getCompletionsAtPosition(fileName: string, position: number): CompletionInfo {
|
||||
synchronizeHostData();
|
||||
|
||||
|
||||
let completionData = getCompletionData(fileName, position);
|
||||
if (!completionData) {
|
||||
return undefined;
|
||||
@@ -4887,7 +4887,7 @@ module ts {
|
||||
}
|
||||
return;
|
||||
|
||||
function getPropertySymbolFromTypeReference(typeReference: TypeReferenceNode) {
|
||||
function getPropertySymbolFromTypeReference(typeReference: HeritageClauseElement) {
|
||||
if (typeReference) {
|
||||
let type = typeInfoResolver.getTypeAtLocation(typeReference);
|
||||
if (type) {
|
||||
@@ -5144,19 +5144,44 @@ module ts {
|
||||
}
|
||||
|
||||
function isTypeReference(node: Node): boolean {
|
||||
if (isRightSideOfQualifiedName(node)) {
|
||||
if (isRightSideOfQualifiedNameOrPropertyAccess(node) ) {
|
||||
node = node.parent;
|
||||
}
|
||||
|
||||
return node.parent.kind === SyntaxKind.TypeReference;
|
||||
return node.parent.kind === SyntaxKind.TypeReference || node.parent.kind === SyntaxKind.HeritageClauseElement;
|
||||
}
|
||||
|
||||
function isNamespaceReference(node: Node): boolean {
|
||||
return isQualifiedNameNamespaceReference(node) || isPropertyAccessNamespaceReference(node);
|
||||
}
|
||||
|
||||
function isPropertyAccessNamespaceReference(node: Node): boolean {
|
||||
let root = node;
|
||||
let isLastClause = true;
|
||||
if (root.parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
while (root.parent && root.parent.kind === SyntaxKind.PropertyAccessExpression) {
|
||||
root = root.parent;
|
||||
}
|
||||
|
||||
isLastClause = (<PropertyAccessExpression>root).name === node;
|
||||
}
|
||||
|
||||
if (!isLastClause && root.parent.kind === SyntaxKind.HeritageClauseElement && root.parent.parent.kind === SyntaxKind.HeritageClause) {
|
||||
let decl = root.parent.parent.parent;
|
||||
return (decl.kind === SyntaxKind.ClassDeclaration && (<HeritageClause>root.parent.parent).token === SyntaxKind.ImplementsKeyword) ||
|
||||
(decl.kind === SyntaxKind.InterfaceDeclaration && (<HeritageClause>root.parent.parent).token === SyntaxKind.ExtendsKeyword);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function isQualifiedNameNamespaceReference(node: Node): boolean {
|
||||
let root = node;
|
||||
let isLastClause = true;
|
||||
if (root.parent.kind === SyntaxKind.QualifiedName) {
|
||||
while (root.parent && root.parent.kind === SyntaxKind.QualifiedName)
|
||||
while (root.parent && root.parent.kind === SyntaxKind.QualifiedName) {
|
||||
root = root.parent;
|
||||
}
|
||||
|
||||
isLastClause = (<QualifiedName>root).right === node;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user