merge with origin/master

This commit is contained in:
vladima
2015-12-17 21:30:47 -08:00
58 changed files with 2635 additions and 772 deletions

View File

@@ -3507,7 +3507,7 @@ namespace ts {
function findMatchingSignature(signatureList: Signature[], signature: Signature, partialMatch: boolean, ignoreReturnTypes: boolean): Signature {
for (const s of signatureList) {
if (compareSignatures(s, signature, partialMatch, ignoreReturnTypes, compareTypes)) {
if (compareSignaturesIdentical(s, signature, partialMatch, ignoreReturnTypes, compareTypesIdentical)) {
return s;
}
}
@@ -3768,11 +3768,14 @@ namespace ts {
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
const types = containingType.types;
let props: Symbol[];
// Flags we want to propagate to the result if they exist in all source symbols
let commonFlags = (containingType.flags & TypeFlags.Intersection) ? SymbolFlags.Optional : SymbolFlags.None;
for (const current of types) {
const type = getApparentType(current);
if (type !== unknownType) {
const prop = getPropertyOfType(type, name);
if (prop && !(getDeclarationFlagsFromSymbol(prop) & (NodeFlags.Private | NodeFlags.Protected))) {
commonFlags &= prop.flags;
if (!props) {
props = [prop];
}
@@ -3800,7 +3803,12 @@ namespace ts {
}
propTypes.push(getTypeOfSymbol(prop));
}
const result = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | SymbolFlags.SyntheticProperty, name);
const result = <TransientSymbol>createSymbol(
SymbolFlags.Property |
SymbolFlags.Transient |
SymbolFlags.SyntheticProperty |
commonFlags,
name);
result.containingType = containingType;
result.declarations = declarations;
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
@@ -4959,7 +4967,7 @@ namespace ts {
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined);
}
function compareTypes(source: Type, target: Type): Ternary {
function compareTypesIdentical(source: Type, target: Type): Ternary {
return checkTypeRelatedTo(source, target, identityRelation, /*errorNode*/ undefined) ? Ternary.True : Ternary.False;
}
@@ -4979,10 +4987,96 @@ namespace ts {
return checkTypeRelatedTo(source, target, assignableRelation, errorNode, headMessage, containingMessageChain);
}
function isSignatureAssignableTo(source: Signature, target: Signature): boolean {
const sourceType = getOrCreateTypeFromSignature(source);
const targetType = getOrCreateTypeFromSignature(target);
return checkTypeRelatedTo(sourceType, targetType, assignableRelation, /*errorNode*/ undefined);
/**
* See signatureRelatedTo, compareSignaturesIdentical
*/
function isSignatureAssignableTo(source: Signature, target: Signature, ignoreReturnTypes: boolean): boolean {
// TODO (drosen): De-duplicate code between related functions.
if (source === target) {
return true;
}
if (!target.hasRestParameter && source.minArgumentCount > target.parameters.length) {
return false;
}
// Spec 1.0 Section 3.8.3 & 3.8.4:
// M and N (the signatures) are instantiated using type Any as the type argument for all type parameters declared by M and N
source = getErasedSignature(source);
target = getErasedSignature(target);
const sourceMax = getNumNonRestParameters(source);
const targetMax = getNumNonRestParameters(target);
const checkCount = getNumParametersToCheckForSignatureRelatability(source, sourceMax, target, targetMax);
for (let i = 0; i < checkCount; i++) {
const s = i < sourceMax ? getTypeOfSymbol(source.parameters[i]) : getRestTypeOfSignature(source);
const t = i < targetMax ? getTypeOfSymbol(target.parameters[i]) : getRestTypeOfSignature(target);
const related = isTypeAssignableTo(t, s) || isTypeAssignableTo(s, t);
if (!related) {
return false;
}
}
if (!ignoreReturnTypes) {
const targetReturnType = getReturnTypeOfSignature(target);
if (targetReturnType === voidType) {
return true;
}
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)) {
return false;
}
}
return isTypeAssignableTo(sourceReturnType, targetReturnType);
}
return true;
}
function isImplementationCompatibleWithOverload(implementation: Signature, overload: Signature): boolean {
const erasedSource = getErasedSignature(implementation);
const erasedTarget = getErasedSignature(overload);
// First see if the return types are compatible in either direction.
const sourceReturnType = getReturnTypeOfSignature(erasedSource);
const targetReturnType = getReturnTypeOfSignature(erasedTarget);
if (targetReturnType === voidType
|| checkTypeRelatedTo(targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined)
|| checkTypeRelatedTo(sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined)) {
return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true);
}
return false;
}
function getNumNonRestParameters(signature: Signature) {
const numParams = signature.parameters.length;
return signature.hasRestParameter ?
numParams - 1 :
numParams;
}
function getNumParametersToCheckForSignatureRelatability(source: Signature, sourceNonRestParamCount: number, target: Signature, targetNonRestParamCount: number) {
if (source.hasRestParameter === target.hasRestParameter) {
if (source.hasRestParameter) {
// If both have rest parameters, get the max and add 1 to
// compensate for the rest parameter.
return Math.max(sourceNonRestParamCount, targetNonRestParamCount) + 1;
}
else {
return Math.min(sourceNonRestParamCount, targetNonRestParamCount);
}
}
else {
// Return the count for whichever signature doesn't have rest parameters.
return source.hasRestParameter ?
targetNonRestParamCount :
sourceNonRestParamCount;
}
}
/**
@@ -5574,7 +5668,7 @@ namespace ts {
shouldElaborateErrors = false;
}
}
// don't elaborate the primitive apparent types (like Number)
// don't elaborate the primitive apparent types (like Number)
// because the actual primitives will have already been reported.
if (shouldElaborateErrors && !isPrimitiveApparentType(source)) {
reportError(Diagnostics.Type_0_provides_no_match_for_the_signature_1,
@@ -5621,7 +5715,11 @@ namespace ts {
}
}
/**
* See signatureAssignableTo, signatureAssignableTo
*/
function signatureRelatedTo(source: Signature, target: Signature, reportErrors: boolean): Ternary {
// TODO (drosen): De-duplicate code between related functions.
if (source === target) {
return Ternary.True;
}
@@ -5673,10 +5771,12 @@ namespace ts {
}
const targetReturnType = getReturnTypeOfSignature(target);
if (targetReturnType === voidType) return result;
if (targetReturnType === voidType) {
return result;
}
const sourceReturnType = getReturnTypeOfSignature(source);
// The follow block preserves old behavior forbidding boolean returning functions from being assignable to type guard returning functions
// 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 (reportErrors) {
@@ -5697,7 +5797,7 @@ namespace ts {
}
let result = Ternary.True;
for (let i = 0, len = sourceSignatures.length; i < len; ++i) {
const related = compareSignatures(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
const related = compareSignaturesIdentical(sourceSignatures[i], targetSignatures[i], /*partialMatch*/ false, /*ignoreReturnTypes*/ false, isRelatedTo);
if (!related) {
return Ternary.False;
}
@@ -5830,7 +5930,7 @@ namespace ts {
}
function isPropertyIdenticalTo(sourceProp: Symbol, targetProp: Symbol): boolean {
return compareProperties(sourceProp, targetProp, compareTypes) !== Ternary.False;
return compareProperties(sourceProp, targetProp, compareTypesIdentical) !== Ternary.False;
}
function compareProperties(sourceProp: Symbol, targetProp: Symbol, compareTypes: (source: Type, target: Type) => Ternary): Ternary {
@@ -5877,7 +5977,11 @@ namespace ts {
return false;
}
function compareSignatures(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
/**
* See signatureRelatedTo, compareSignaturesIdentical
*/
function compareSignaturesIdentical(source: Signature, target: Signature, partialMatch: boolean, ignoreReturnTypes: boolean, compareTypes: (s: Type, t: Type) => Ternary): Ternary {
// TODO (drosen): De-duplicate code between related functions.
if (source === target) {
return Ternary.True;
}
@@ -7605,7 +7709,7 @@ namespace ts {
// This signature will contribute to contextual union signature
signatureList = [signature];
}
else if (!compareSignatures(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypes)) {
else if (!compareSignaturesIdentical(signatureList[0], signature, /*partialMatch*/ false, /*ignoreReturnTypes*/ true, compareTypesIdentical)) {
// Signatures aren't identical, do not use
return undefined;
}
@@ -8280,9 +8384,9 @@ namespace ts {
// Props is of type 'any' or unknown
return links.resolvedJsxType = attributesType;
}
else if (!(attributesType.flags & TypeFlags.ObjectType)) {
// Props is not an object type
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_must_be_an_object_type, typeToString(attributesType));
else if (attributesType.flags & TypeFlags.Union) {
// Props cannot be a union type
error(node.tagName, Diagnostics.JSX_element_attributes_type_0_may_not_be_a_union_type, typeToString(attributesType));
return links.resolvedJsxType = anyType;
}
else {
@@ -11626,7 +11730,7 @@ namespace ts {
}
for (const otherSignature of signaturesToCheck) {
if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature)) {
if (!otherSignature.hasStringLiterals && isSignatureAssignableTo(signature, otherSignature, /*ignoreReturnTypes*/ false)) {
return;
}
}
@@ -11873,7 +11977,7 @@ namespace ts {
//
// The implementation is completely unrelated to the specialized signature, yet we do not check this.
for (const signature of signatures) {
if (!signature.hasStringLiterals && !isSignatureAssignableTo(bodySignature, signature)) {
if (!signature.hasStringLiterals && !isImplementationCompatibleWithOverload(bodySignature, signature)) {
error(signature.declaration, Diagnostics.Overload_signature_is_not_compatible_with_function_implementation);
break;
}

View File

@@ -1691,7 +1691,7 @@
"category": "Error",
"code": 2528
},
"JSX element attributes type '{0}' must be an object type.": {
"JSX element attributes type '{0}' may not be a union type.": {
"category": "Error",
"code": 2600
},