Merge branch 'master' into constructorAccessibility

Conflicts:
	src/compiler/checker.ts
This commit is contained in:
AbubakerB
2016-02-16 22:49:23 +00:00
105 changed files with 1945 additions and 1017 deletions

View File

@@ -131,8 +131,8 @@ namespace ts {
const noConstraintType = createAnonymousType(undefined, emptySymbols, emptyArray, emptyArray, undefined, undefined);
const anySignature = createSignature(undefined, undefined, emptyArray, anyType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const anySignature = createSignature(undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const unknownSignature = createSignature(undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false);
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
@@ -1711,6 +1711,15 @@ namespace ts {
return result;
}
function typePredicateToString(typePredicate: TypePredicate, enclosingDeclaration?: Declaration, flags?: TypeFormatFlags): string {
const writer = getSingleLineStringWriter();
getSymbolDisplayBuilder().buildTypePredicateDisplay(typePredicate, writer, enclosingDeclaration, flags);
const result = writer.string();
releaseStringWriter(writer);
return result;
}
function visibilityToString(flags: NodeFlags) {
if (flags === NodeFlags.Private) {
return "private";
@@ -1854,16 +1863,10 @@ namespace ts {
function writeType(type: Type, flags: TypeFormatFlags) {
// Write undefined/null type as any
if (type.flags & TypeFlags.Intrinsic) {
if (type.flags & TypeFlags.PredicateType) {
buildTypePredicateDisplay(writer, (type as PredicateType).predicate);
buildTypeDisplay((type as PredicateType).predicate.type, writer, enclosingDeclaration, flags, symbolStack);
}
else {
// Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
? "any"
: (<IntrinsicType>type).intrinsicName);
}
// Special handling for unknown / resolving types, they should show up as any and not unknown or __resolving
writer.writeKeyword(!(globalFlags & TypeFormatFlags.WriteOwnNameForAnyLike) && isTypeAny(type)
? "any"
: (<IntrinsicType>type).intrinsicName);
}
else if (type.flags & TypeFlags.ThisType) {
if (inObjectTypeLiteral) {
@@ -2223,7 +2226,7 @@ namespace ts {
writePunctuation(writer, SyntaxKind.CloseParenToken);
}
function buildTypePredicateDisplay(writer: SymbolWriter, predicate: TypePredicate) {
function buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]): void {
if (isIdentifierTypePredicate(predicate)) {
writer.writeParameter(predicate.parameterName);
}
@@ -2233,6 +2236,7 @@ namespace ts {
writeSpace(writer);
writeKeyword(writer, SyntaxKind.IsKeyword);
writeSpace(writer);
buildTypeDisplay(predicate.type, writer, enclosingDeclaration, flags, symbolStack);
}
function buildReturnTypeDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
@@ -2245,8 +2249,13 @@ namespace ts {
}
writeSpace(writer);
const returnType = getReturnTypeOfSignature(signature);
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
if (signature.typePredicate) {
buildTypePredicateDisplay(signature.typePredicate, writer, enclosingDeclaration, flags, symbolStack);
}
else {
const returnType = getReturnTypeOfSignature(signature);
buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack);
}
}
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind, symbolStack?: Symbol[]) {
@@ -2265,6 +2274,7 @@ namespace ts {
}
buildDisplayForParametersAndDelimiters(signature.parameters, writer, enclosingDeclaration, flags, symbolStack);
buildReturnTypeDisplay(signature, writer, enclosingDeclaration, flags, symbolStack);
}
@@ -2272,6 +2282,7 @@ namespace ts {
buildSymbolDisplay,
buildTypeDisplay,
buildTypeParameterDisplay,
buildTypePredicateDisplay,
buildParameterDisplay,
buildDisplayForParametersAndDelimiters,
buildDisplayForTypeParametersAndDelimiters,
@@ -2810,9 +2821,6 @@ namespace ts {
if (declaration.kind === SyntaxKind.PropertyAssignment) {
return type;
}
if (type.flags & TypeFlags.PredicateType && (declaration.kind === SyntaxKind.PropertyDeclaration || declaration.kind === SyntaxKind.PropertySignature)) {
return type;
}
return getWidenedType(type);
}
@@ -3543,12 +3551,13 @@ namespace ts {
}
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], parameters: Symbol[],
resolvedReturnType: Type, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasStringLiterals: boolean): Signature {
const sig = new Signature(checker);
sig.declaration = declaration;
sig.typeParameters = typeParameters;
sig.parameters = parameters;
sig.resolvedReturnType = resolvedReturnType;
sig.typePredicate = typePredicate;
sig.minArgumentCount = minArgumentCount;
sig.hasRestParameter = hasRestParameter;
sig.hasStringLiterals = hasStringLiterals;
@@ -3557,14 +3566,14 @@ namespace ts {
function cloneSignature(sig: Signature): Signature {
return createSignature(sig.declaration, sig.typeParameters, sig.parameters, sig.resolvedReturnType,
sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
sig.typePredicate, sig.minArgumentCount, sig.hasRestParameter, sig.hasStringLiterals);
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
const baseConstructorType = getBaseConstructorTypeOfClass(classType);
const baseSignatures = getSignaturesOfType(baseConstructorType, SignatureKind.Construct);
if (baseSignatures.length === 0) {
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
return [createSignature(undefined, classType.localTypeParameters, emptyArray, classType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasStringLiterals*/ false)];
}
const baseTypeNode = getBaseTypeNodeOfClass(classType);
const typeArguments = map(baseTypeNode.typeArguments, getTypeFromTypeNode);
@@ -4096,6 +4105,7 @@ namespace ts {
let minArgumentCount = -1;
const isJSConstructSignature = isJSDocConstructSignature(declaration);
let returnType: Type = undefined;
let typePredicate: TypePredicate = undefined;
// If this is a JSDoc construct signature, then skip the first parameter in the
// parameter list. The first parameter represents the return type of the construct
@@ -4139,6 +4149,9 @@ namespace ts {
}
else if (declaration.type) {
returnType = getTypeFromTypeNode(declaration.type);
if (declaration.type.kind === SyntaxKind.TypePredicate) {
typePredicate = createTypePredicateFromTypePredicateNode(declaration.type as TypePredicateNode);
}
}
else {
if (declaration.flags & NodeFlags.JavaScriptFile) {
@@ -4160,7 +4173,7 @@ namespace ts {
}
}
links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
links.resolvedSignature = createSignature(declaration, typeParameters, parameters, returnType, typePredicate, minArgumentCount, hasRestParameter(declaration), hasStringLiterals);
}
return links.resolvedSignature;
}
@@ -4872,25 +4885,6 @@ namespace ts {
return links.resolvedType;
}
function getPredicateType(node: TypePredicateNode): Type {
return createPredicateType(getSymbolOfNode(node), createTypePredicateFromTypePredicateNode(node));
}
function createPredicateType(symbol: Symbol, predicate: ThisTypePredicate | IdentifierTypePredicate) {
const type = createType(TypeFlags.Boolean | TypeFlags.PredicateType) as PredicateType;
type.symbol = symbol;
type.predicate = predicate;
return type;
}
function getTypeFromPredicateTypeNode(node: TypePredicateNode): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
links.resolvedType = getPredicateType(node);
}
return links.resolvedType;
}
function getTypeFromTypeNode(node: TypeNode): Type {
switch (node.kind) {
case SyntaxKind.AnyKeyword:
@@ -4915,7 +4909,7 @@ namespace ts {
case SyntaxKind.JSDocTypeReference:
return getTypeFromTypeReference(<TypeReferenceNode>node);
case SyntaxKind.TypePredicate:
return getTypeFromPredicateTypeNode(<TypePredicateNode>node);
return booleanType;
case SyntaxKind.ExpressionWithTypeArguments:
return getTypeFromTypeReference(<ExpressionWithTypeArguments>node);
case SyntaxKind.TypeQuery:
@@ -5067,6 +5061,7 @@ namespace ts {
function instantiateSignature(signature: Signature, mapper: TypeMapper, eraseTypeParameters?: boolean): Signature {
let freshTypeParameters: TypeParameter[];
let freshTypePredicate: TypePredicate;
if (signature.typeParameters && !eraseTypeParameters) {
// First create a fresh set of type parameters, then include a mapping from the old to the
// new type parameters in the mapper function. Finally store this mapper in the new type
@@ -5077,9 +5072,13 @@ namespace ts {
tp.mapper = mapper;
}
}
if (signature.typePredicate) {
freshTypePredicate = cloneTypePredicate(signature.typePredicate, mapper);
}
const result = createSignature(signature.declaration, freshTypeParameters,
instantiateList(signature.parameters, mapper, instantiateSymbol),
instantiateType(signature.resolvedReturnType, mapper),
freshTypePredicate,
signature.minArgumentCount, signature.hasRestParameter, signature.hasStringLiterals);
result.target = signature;
result.mapper = mapper;
@@ -5149,10 +5148,6 @@ namespace ts {
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
}
if (type.flags & TypeFlags.PredicateType) {
const predicate = (type as PredicateType).predicate;
return createPredicateType(type.symbol, cloneTypePredicate(predicate, mapper));
}
}
return type;
}
@@ -5298,21 +5293,58 @@ namespace ts {
const sourceReturnType = getReturnTypeOfSignature(source);
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
if (targetReturnType.flags & TypeFlags.PredicateType && (targetReturnType as PredicateType).predicate.kind === TypePredicateKind.Identifier) {
if (!(sourceReturnType.flags & TypeFlags.PredicateType)) {
if (target.typePredicate) {
if (source.typePredicate) {
result &= compareTypePredicateRelatedTo(source.typePredicate, target.typePredicate, reportErrors, errorReporter, compareTypes);
}
else if (isIdentifierTypePredicate(target.typePredicate)) {
if (reportErrors) {
errorReporter(Diagnostics.Signature_0_must_have_a_type_predicate, signatureToString(source));
}
return Ternary.False;
}
}
else {
result &= compareTypes(sourceReturnType, targetReturnType, reportErrors);
}
result &= compareTypes(sourceReturnType, targetReturnType, reportErrors);
}
return result;
}
function compareTypePredicateRelatedTo(source: TypePredicate,
target: TypePredicate,
reportErrors: boolean,
errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void,
compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
if (source.kind !== target.kind) {
if (reportErrors) {
errorReporter(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard);
errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
}
return Ternary.False;
}
if (source.kind === TypePredicateKind.Identifier) {
const sourceIdentifierPredicate = source as IdentifierTypePredicate;
const targetIdentifierPredicate = target as IdentifierTypePredicate;
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
if (reportErrors) {
errorReporter(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
}
return Ternary.False;
}
}
const related = compareTypes(source.type, target.type, reportErrors);
if (related === Ternary.False && reportErrors) {
errorReporter(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typePredicateToString(source), typePredicateToString(target));
}
return related;
}
function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean {
const erasedSource = getErasedSignature(implementation);
const erasedTarget = getErasedSignature(overload);
@@ -5439,33 +5471,6 @@ namespace ts {
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
}
if (source.flags & TypeFlags.Boolean && target.flags & TypeFlags.Boolean) {
if (source.flags & TypeFlags.PredicateType && target.flags & TypeFlags.PredicateType) {
const sourcePredicate = source as PredicateType;
const targetPredicate = target as PredicateType;
if (sourcePredicate.predicate.kind !== targetPredicate.predicate.kind) {
if (reportErrors) {
reportError(Diagnostics.A_this_based_type_guard_is_not_compatible_with_a_parameter_based_type_guard);
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
}
return Ternary.False;
}
if (sourcePredicate.predicate.kind === TypePredicateKind.Identifier) {
const sourceIdentifierPredicate = sourcePredicate.predicate as IdentifierTypePredicate;
const targetIdentifierPredicate = targetPredicate.predicate as IdentifierTypePredicate;
if (sourceIdentifierPredicate.parameterIndex !== targetIdentifierPredicate.parameterIndex) {
if (reportErrors) {
reportError(Diagnostics.Parameter_0_is_not_in_the_same_position_as_parameter_1, sourceIdentifierPredicate.parameterName, targetIdentifierPredicate.parameterName);
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
}
return Ternary.False;
}
}
const related = isRelatedTo(sourcePredicate.predicate.type, targetPredicate.predicate.type, reportErrors, headMessage);
if (related === Ternary.False && reportErrors) {
reportError(Diagnostics.Type_predicate_0_is_not_assignable_to_1, typeToString(source), typeToString(target));
}
return related;
}
return Ternary.True;
}
@@ -6355,9 +6360,6 @@ namespace ts {
if (type.flags & (TypeFlags.Undefined | TypeFlags.Null)) {
return anyType;
}
if (type.flags & TypeFlags.PredicateType) {
return booleanType;
}
if (type.flags & TypeFlags.ObjectLiteral) {
return getWidenedTypeOfObjectLiteral(type);
}
@@ -6585,11 +6587,6 @@ namespace ts {
inferFromTypes(sourceTypes[i], targetTypes[i]);
}
}
else if (source.flags & TypeFlags.PredicateType && target.flags & TypeFlags.PredicateType) {
if ((source as PredicateType).predicate.kind === (target as PredicateType).predicate.kind) {
inferFromTypes((source as PredicateType).predicate.type, (target as PredicateType).predicate.type);
}
}
else if (source.flags & TypeFlags.Tuple && target.flags & TypeFlags.Tuple && (<TupleType>source).elementTypes.length === (<TupleType>target).elementTypes.length) {
// If source and target are tuples of the same size, infer from element types
const sourceTypes = (<TupleType>source).elementTypes;
@@ -6685,7 +6682,13 @@ namespace ts {
function inferFromSignature(source: Signature, target: Signature) {
forEachMatchingParameterType(source, target, inferFromTypes);
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
if (source.typePredicate && target.typePredicate && source.typePredicate.kind === target.typePredicate.kind) {
inferFromTypes(source.typePredicate.type, target.typePredicate.type);
}
else {
inferFromTypes(getReturnTypeOfSignature(source), getReturnTypeOfSignature(target));
}
}
function inferFromIndexTypes(source: Type, target: Type, sourceKind: IndexKind, targetKind: IndexKind) {
@@ -7111,46 +7114,33 @@ namespace ts {
return originalType;
}
function narrowTypeByTypePredicate(type: Type, expr: CallExpression, assumeTrue: boolean): Type {
function narrowTypeByTypePredicate(type: Type, callExpression: CallExpression, assumeTrue: boolean): Type {
if (type.flags & TypeFlags.Any) {
return type;
}
const signature = getResolvedSignature(expr);
const predicateType = getReturnTypeOfSignature(signature);
const signature = getResolvedSignature(callExpression);
if (!predicateType || !(predicateType.flags & TypeFlags.PredicateType)) {
const predicate = signature.typePredicate;
if (!predicate) {
return type;
}
const predicate = (predicateType as PredicateType).predicate;
if (isIdentifierTypePredicate(predicate)) {
const callExpression = expr as CallExpression;
if (callExpression.arguments[predicate.parameterIndex] &&
getSymbolAtTypePredicatePosition(callExpression.arguments[predicate.parameterIndex]) === symbol) {
return getNarrowedType(type, predicate.type, assumeTrue);
}
}
else {
const expression = skipParenthesizedNodes(expr.expression);
return narrowTypeByThisTypePredicate(type, predicate, expression, assumeTrue);
const invokedExpression = skipParenthesizedNodes(callExpression.expression);
return narrowTypeByThisTypePredicate(type, predicate, invokedExpression, assumeTrue);
}
return type;
}
function narrowTypeByTypePredicateMember(type: Type, expr: ElementAccessExpression | PropertyAccessExpression, assumeTrue: boolean): Type {
if (type.flags & TypeFlags.Any) {
return type;
}
const memberType = getTypeOfExpression(expr);
if (!(memberType.flags & TypeFlags.PredicateType)) {
return type;
}
return narrowTypeByThisTypePredicate(type, (memberType as PredicateType).predicate as ThisTypePredicate, expr, assumeTrue);
}
function narrowTypeByThisTypePredicate(type: Type, predicate: ThisTypePredicate, expression: Expression, assumeTrue: boolean): Type {
if (expression.kind === SyntaxKind.ElementAccessExpression || expression.kind === SyntaxKind.PropertyAccessExpression) {
const accessExpression = expression as ElementAccessExpression | PropertyAccessExpression;
function narrowTypeByThisTypePredicate(type: Type, predicate: ThisTypePredicate, invokedExpression: Expression, assumeTrue: boolean): Type {
if (invokedExpression.kind === SyntaxKind.ElementAccessExpression || invokedExpression.kind === SyntaxKind.PropertyAccessExpression) {
const accessExpression = invokedExpression as ElementAccessExpression | PropertyAccessExpression;
const possibleIdentifier = skipParenthesizedNodes(accessExpression.expression);
if (possibleIdentifier.kind === SyntaxKind.Identifier && getSymbolAtTypePredicatePosition(possibleIdentifier) === symbol) {
return getNarrowedType(type, predicate.type, assumeTrue);
@@ -7164,8 +7154,7 @@ namespace ts {
switch (expr.kind) {
case SyntaxKind.Identifier:
case SyntaxKind.PropertyAccessExpression:
case SyntaxKind.QualifiedName:
return getSymbolOfEntityNameOrPropertyAccessExpression(expr as Node as (EntityName | PropertyAccessExpression));
return getSymbolOfEntityNameOrPropertyAccessExpression(expr as (Identifier | PropertyAccessExpression));
}
}
@@ -7197,9 +7186,6 @@ namespace ts {
return narrowType(type, (<PrefixUnaryExpression>expr).operand, !assumeTrue);
}
break;
case SyntaxKind.ElementAccessExpression:
case SyntaxKind.PropertyAccessExpression:
return narrowTypeByTypePredicateMember(type, expr as (ElementAccessExpression | PropertyAccessExpression), assumeTrue);
}
return type;
}
@@ -7372,6 +7358,46 @@ namespace ts {
}
}
function findFirstSuperCall(n: Node): Node {
if (isSuperCallExpression(n)) {
return n;
}
else if (isFunctionLike(n)) {
return undefined;
}
return forEachChild(n, findFirstSuperCall);
}
/**
* Return a cached result if super-statement is already found.
* Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor
*
* @param constructor constructor-function to look for super statement
*/
function getSuperCallInConstructor(constructor: ConstructorDeclaration): ExpressionStatement {
const links = getNodeLinks(constructor);
// Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result
if (links.hasSuperCall === undefined) {
links.superCall = <ExpressionStatement>findFirstSuperCall(constructor.body);
links.hasSuperCall = links.superCall ? true : false;
}
return links.superCall;
}
/**
* Check if the given class-declaration extends null then return true.
* Otherwise, return false
* @param classDecl a class declaration to check if it extends null
*/
function classDeclarationExtendsNull(classDecl: ClassDeclaration): boolean {
const classSymbol = getSymbolOfNode(classDecl);
const classInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(classSymbol);
const baseConstructorType = getBaseConstructorTypeOfClass(classInstanceType);
return baseConstructorType === nullType;
}
function checkThisExpression(node: Node): Type {
// Stop at the first arrow function so that we can
// tell whether 'this' needs to be captured.
@@ -7379,10 +7405,25 @@ namespace ts {
let needToCaptureLexicalThis = false;
if (container.kind === SyntaxKind.Constructor) {
const baseTypeNode = getClassExtendsHeritageClauseElement(<ClassLikeDeclaration>container.parent);
if (baseTypeNode && !(getNodeCheckFlags(container) & NodeCheckFlags.HasSeenSuperCall)) {
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
const containingClassDecl = <ClassDeclaration>container.parent;
const baseTypeNode = getClassExtendsHeritageClauseElement(containingClassDecl);
// If a containing class does not have extends clause or the class extends null
// skip checking whether super statement is called before "this" accessing.
if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
// We should give an error in the following cases:
// - No super-call
// - "this" is accessing before super-call.
// i.e super(this)
// this.x; super();
// We want to make sure that super-call is done before accessing "this" so that
// "this" is not accessed as a parameter of the super-call.
if (!superCall || superCall.end > node.pos) {
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
error(node, Diagnostics.super_must_be_called_before_accessing_this_in_the_constructor_of_a_derived_class);
}
}
}
@@ -10329,14 +10370,11 @@ namespace ts {
checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
const signature = getResolvedSignature(node);
if (node.expression.kind === SyntaxKind.SuperKeyword) {
const containingFunction = getContainingFunction(node.expression);
if (containingFunction && containingFunction.kind === SyntaxKind.Constructor) {
getNodeLinks(containingFunction).flags |= NodeCheckFlags.HasSeenSuperCall;
}
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return voidType;
}
if (node.kind === SyntaxKind.NewExpression) {
const declaration = signature.declaration;
@@ -10621,12 +10659,13 @@ namespace ts {
return aggregatedTypes;
}
/*
*TypeScript Specification 1.0 (6.3) - July 2014
* An explicitly typed function whose return type isn't the Void type,
* the Any type, or a union type containing the Void or Any type as a constituent
* must have at least one return statement somewhere in its body.
* An exception to this rule is if the function implementation consists of a single 'throw' statement.
/**
* TypeScript Specification 1.0 (6.3) - July 2014
* An explicitly typed function whose return type isn't the Void type,
* the Any type, or a union type containing the Void or Any type as a constituent
* must have at least one return statement somewhere in its body.
* An exception to this rule is if the function implementation consists of a single 'throw' statement.
*
* @param returnType - return type of the function, can be undefined if return type is not explicitly specified
*/
function checkAllCodePathsInNonVoidFunctionReturnOrThrow(func: FunctionLikeDeclaration, returnType: Type): void {
@@ -11651,21 +11690,24 @@ namespace ts {
return -1;
}
function checkTypePredicate(node: TypePredicateNode) {
function checkTypePredicate(node: TypePredicateNode): void {
const parent = getTypePredicateParent(node);
if (!parent) {
// The parent must not be valid.
error(node, Diagnostics.A_type_predicate_is_only_allowed_in_return_type_position_for_functions_and_methods);
return;
}
const returnType = getReturnTypeOfSignature(getSignatureFromDeclaration(parent));
if (!returnType || !(returnType.flags & TypeFlags.PredicateType)) {
const typePredicate = getSignatureFromDeclaration(parent).typePredicate;
if (!typePredicate) {
return;
}
const { parameterName } = node;
if (parameterName.kind === SyntaxKind.ThisType) {
if (isThisTypePredicate(typePredicate)) {
getTypeFromThisTypeNode(parameterName as ThisTypeNode);
}
else {
const typePredicate = <IdentifierTypePredicate>(<PredicateType>returnType).predicate;
if (typePredicate.parameterIndex >= 0) {
if (parent.parameters[typePredicate.parameterIndex].dotDotDotToken) {
error(parameterName,
@@ -11680,12 +11722,8 @@ namespace ts {
else if (parameterName) {
let hasReportedError = false;
for (const { name } of parent.parameters) {
if ((name.kind === SyntaxKind.ObjectBindingPattern ||
name.kind === SyntaxKind.ArrayBindingPattern) &&
checkIfTypePredicateVariableIsDeclaredInBindingPattern(
<BindingPattern>name,
parameterName,
typePredicate.parameterName)) {
if (isBindingPattern(name) &&
checkIfTypePredicateVariableIsDeclaredInBindingPattern(name, parameterName, typePredicate.parameterName)) {
hasReportedError = true;
break;
}
@@ -11753,8 +11791,9 @@ namespace ts {
forEach(node.parameters, checkParameter);
checkSourceElement(node.type);
if (node.type) {
checkSourceElement(node.type);
}
if (produceDiagnostics) {
checkCollisionWithArgumentsInGeneratedCode(node);
@@ -11921,13 +11960,11 @@ namespace ts {
// constructors of derived classes must contain at least one super call somewhere in their function body.
const containingClassDecl = <ClassDeclaration>node.parent;
if (getClassExtendsHeritageClauseElement(containingClassDecl)) {
const containingClassSymbol = getSymbolOfNode(containingClassDecl);
const containingClassInstanceType = <InterfaceType>getDeclaredTypeOfSymbol(containingClassSymbol);
const baseConstructorType = getBaseConstructorTypeOfClass(containingClassInstanceType);
if (containsSuperCall(node.body)) {
if (baseConstructorType === nullType) {
error(node, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
const classExtendsNull = classDeclarationExtendsNull(containingClassDecl);
const superCall = getSuperCallInConstructor(node);
if (superCall) {
if (classExtendsNull) {
error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
}
// The first statement in the body of a constructor (excluding prologue directives) must be a super call
@@ -11944,6 +11981,7 @@ namespace ts {
if (superCallShouldBeFirst) {
const statements = (<Block>node.body).statements;
let superCallStatement: ExpressionStatement;
for (const statement of statements) {
if (statement.kind === SyntaxKind.ExpressionStatement && isSuperCallExpression((<ExpressionStatement>statement).expression)) {
superCallStatement = <ExpressionStatement>statement;
@@ -11958,7 +11996,7 @@ namespace ts {
}
}
}
else if (baseConstructorType !== nullType) {
else if (!classExtendsNull) {
error(node, Diagnostics.Constructors_for_derived_classes_must_contain_a_super_call);
}
}
@@ -12817,7 +12855,7 @@ namespace ts {
}
if (!compilerOptions.experimentalDecorators) {
error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalDecorators_to_remove_this_warning);
error(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning);
}
if (compilerOptions.emitDecoratorMetadata) {
@@ -13711,7 +13749,7 @@ namespace ts {
error(node.expression, Diagnostics.Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class);
}
}
else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func) || returnType.flags & TypeFlags.PredicateType) {
else if (func.type || isGetAccessorWithAnnotatedSetAccessor(func)) {
if (isAsyncFunctionLike(func)) {
const promisedType = getPromisedType(returnType);
const awaitedType = checkAwaitedType(exprType, node.expression, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);

View File

@@ -687,7 +687,7 @@
"category": "Error",
"code": 1218
},
"Experimental support for decorators is a feature that is subject to change in a future release. Specify '--experimentalDecorators' to remove this warning.": {
"Experimental support for decorators is a feature that is subject to change in a future release. Set the 'experimentalDecorators' option to remove this warning.": {
"category": "Error",
"code": 1219
},
@@ -723,6 +723,10 @@
"category": "Error",
"code": 1227
},
"A type predicate is only allowed in return type position for functions and methods.": {
"category": "Error",
"code": 1228
},
"A type predicate cannot reference a rest parameter.": {
"category": "Error",
"code": 1229
@@ -2745,11 +2749,6 @@
"category": "Error",
"code": 8016
},
"'decorators' can only be used in a .ts file.": {
"category": "Error",
"code": 8017
},
"Only identifiers/qualified-names with optional type arguments are currently supported in a class 'extends' clauses.": {
"category": "Error",
"code": 9002

View File

@@ -1937,7 +1937,7 @@ namespace ts {
return finishNode(node);
}
function parseTypePredicate(lhs: Identifier | ThisTypeNode): TypePredicateNode {
function parseThisTypePredicate(lhs: ThisTypeNode): TypePredicateNode {
nextToken();
const node = createNode(SyntaxKind.TypePredicate, lhs.pos) as TypePredicateNode;
node.parameterName = lhs;
@@ -2362,7 +2362,7 @@ namespace ts {
case SyntaxKind.ThisKeyword: {
const thisKeyword = parseThisTypeNode();
if (token === SyntaxKind.IsKeyword && !scanner.hasPrecedingLineBreak()) {
return parseTypePredicate(thisKeyword);
return parseThisTypePredicate(thisKeyword);
}
else {
return thisKeyword;

View File

@@ -533,18 +533,25 @@ namespace ts {
}
let referencedSourceFile: string;
while (true) {
const searchName = normalizePath(combinePaths(containingDirectory, moduleName));
referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
if (referencedSourceFile) {
break;
if (moduleHasNonRelativeName(moduleName)) {
while (true) {
const searchName = normalizePath(combinePaths(containingDirectory, moduleName));
referencedSourceFile = loadModuleFromFile(searchName, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
if (referencedSourceFile) {
break;
}
const parentPath = getDirectoryPath(containingDirectory);
if (parentPath === containingDirectory) {
break;
}
containingDirectory = parentPath;
}
const parentPath = getDirectoryPath(containingDirectory);
if (parentPath === containingDirectory) {
break;
}
containingDirectory = parentPath;
}
else {
const candidate = normalizePath(combinePaths(containingDirectory, moduleName));
referencedSourceFile = loadModuleFromFile(candidate, supportedExtensions, failedLookupLocations, /*onlyRecordFailures*/ false, state);
}
return referencedSourceFile
? { resolvedModule: { resolvedFileName: referencedSourceFile }, failedLookupLocations }
@@ -1169,7 +1176,9 @@ namespace ts {
diagnostics.push(createDiagnosticForNode(typeAssertionExpression.type, Diagnostics.type_assertion_expressions_can_only_be_used_in_a_ts_file));
return true;
case SyntaxKind.Decorator:
diagnostics.push(createDiagnosticForNode(node, Diagnostics.decorators_can_only_be_used_in_a_ts_file));
if (!options.experimentalDecorators) {
diagnostics.push(createDiagnosticForNode(node, Diagnostics.Experimental_support_for_decorators_is_a_feature_that_is_subject_to_change_in_a_future_release_Set_the_experimentalDecorators_option_to_remove_this_warning));
}
return true;
}

View File

@@ -1,6 +1,5 @@
{
"compilerOptions": {
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
@@ -8,9 +7,9 @@
"sourceMap": true
},
"files": [
"types.ts",
"core.ts",
"sys.ts",
"types.ts",
"diagnosticInformationMap.generated.ts",
"scanner.ts",
"parser.ts",

View File

@@ -426,7 +426,6 @@ namespace ts {
IntrinsicElement = IntrinsicNamedElement | IntrinsicIndexedElement,
}
/* @internal */
export const enum RelationComparisonResult {
Succeeded = 1, // Should be truthy
@@ -1749,6 +1748,7 @@ namespace ts {
buildSignatureDisplay(signatures: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, kind?: SignatureKind): void;
buildParameterDisplay(parameter: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplay(tp: TypeParameter, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypePredicateDisplay(predicate: TypePredicate, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildDisplayForParametersAndDelimiters(parameters: Symbol[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
buildDisplayForTypeParametersAndDelimiters(typeParameters: TypeParameter[], writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags): void;
@@ -1814,22 +1814,24 @@ namespace ts {
Identifier
}
export interface TypePredicate {
export interface TypePredicateBase {
kind: TypePredicateKind;
type: Type;
}
// @kind (TypePredicateKind.This)
export interface ThisTypePredicate extends TypePredicate {
export interface ThisTypePredicate extends TypePredicateBase {
_thisTypePredicateBrand: any;
}
// @kind (TypePredicateKind.Identifier)
export interface IdentifierTypePredicate extends TypePredicate {
export interface IdentifierTypePredicate extends TypePredicateBase {
parameterName: string;
parameterIndex: number;
}
export type TypePredicate = IdentifierTypePredicate | ThisTypePredicate;
/* @internal */
export type AnyImportSyntax = ImportDeclaration | ImportEqualsDeclaration;
@@ -2037,10 +2039,9 @@ namespace ts {
LoopWithCapturedBlockScopedBinding = 0x00010000, // Loop that contains block scoped variable captured in closure
CapturedBlockScopedBinding = 0x00020000, // Block-scoped binding that is captured in some function
BlockScopedBindingInLoop = 0x00040000, // Block-scoped binding with declaration nested inside iteration statement
HasSeenSuperCall = 0x00080000, // Set during the binding when encounter 'super'
ClassWithBodyScopedClassBinding = 0x00100000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00200000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00400000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
ClassWithBodyScopedClassBinding = 0x00080000, // Decorated class that contains a binding to itself inside of the class body.
BodyScopedClassBinding = 0x00100000, // Binding to a decorated class inside of the class's body.
NeedsLoopOutParameter = 0x00200000, // Block scoped binding whose value should be explicitly copied outside of the converted loop
}
/* @internal */
@@ -2060,6 +2061,8 @@ namespace ts {
importOnRightSide?: Symbol; // for import declarations - import that appear on the right side
jsxFlags?: JsxFlags; // flags for knowing what kind of element/attributes we're dealing with
resolvedJsxType?: Type; // resolved element attributes type of a JSX openinglike element
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
superCall?: ExpressionStatement; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
}
export const enum TypeFlags {
@@ -2095,7 +2098,6 @@ namespace ts {
ESSymbol = 0x01000000, // Type of symbol primitive introduced in ES6
ThisType = 0x02000000, // This type
ObjectLiteralPatternWithComputedProperties = 0x04000000, // Object literal type implied by binding pattern has computed properties
PredicateType = 0x08000000, // Predicate types are also Boolean types, but should not be considered Intrinsics - there's no way to capture this with flags
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
@@ -2107,7 +2109,7 @@ namespace ts {
UnionOrIntersection = Union | Intersection,
StructuredType = ObjectType | Union | Intersection,
/* @internal */
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral | PredicateType,
RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral,
/* @internal */
PropagatingFlags = ContainsUndefinedOrNull | ContainsObjectLiteral | ContainsAnyFunctionType
}
@@ -2128,11 +2130,6 @@ namespace ts {
intrinsicName: string; // Name of intrinsic type
}
// Predicate types (TypeFlags.Predicate)
export interface PredicateType extends Type {
predicate: ThisTypePredicate | IdentifierTypePredicate;
}
// String literal types (TypeFlags.StringLiteral)
export interface StringLiteralType extends Type {
text: string; // Text of string literal
@@ -2267,6 +2264,8 @@ namespace ts {
erasedSignatureCache?: Signature; // Erased version of signature (deferred)
/* @internal */
isolatedSignatureType?: ObjectType; // A manufactured type that just contains the signature for purposes of signature comparison
/* @internal */
typePredicate?: TypePredicate;
}
export const enum IndexKind {

View File

@@ -748,6 +748,10 @@ namespace ts {
return predicate && predicate.kind === TypePredicateKind.Identifier;
}
export function isThisTypePredicate(predicate: TypePredicate): predicate is ThisTypePredicate {
return predicate && predicate.kind === TypePredicateKind.This;
}
export function getContainingFunction(node: Node): FunctionLikeDeclaration {
while (true) {
node = node.parent;