Merge remote-tracking branch 'origin/master' into disallowDefaultExportDeclMerging

This commit is contained in:
Daniel Rosenwasser
2015-07-22 12:01:15 -07:00
448 changed files with 6751 additions and 6217 deletions
+14 -8
View File
@@ -518,15 +518,21 @@ namespace ts {
}
else {
declareSymbolAndAddToSymbolTable(node, SymbolFlags.ValueModule, SymbolFlags.ValueModuleExcludes);
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
if (node.symbol.constEnumOnlyModule === undefined) {
// non-merged case - use the current state
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
if (node.symbol.flags & (SymbolFlags.Function | SymbolFlags.Class | SymbolFlags.RegularEnum)) {
// if module was already merged with some function, class or non-const enum
// treat is a non-const-enum-only
node.symbol.constEnumOnlyModule = false;
}
else {
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
let currentModuleIsConstEnumOnly = state === ModuleInstanceState.ConstEnumOnly;
if (node.symbol.constEnumOnlyModule === undefined) {
// non-merged case - use the current state
node.symbol.constEnumOnlyModule = currentModuleIsConstEnumOnly;
}
else {
// merged case: module is const enum only if all its pieces are non-instantiated or const enum
node.symbol.constEnumOnlyModule = node.symbol.constEnumOnlyModule && currentModuleIsConstEnumOnly;
}
}
}
}
@@ -1056,4 +1062,4 @@ namespace ts {
: declareSymbolAndAddToSymbolTable(node, symbolFlags, symbolExcludes);
}
}
}
}
+396 -192
View File
@@ -59,7 +59,10 @@ namespace ts {
isArgumentsSymbol: symbol => symbol === argumentsSymbol,
getDiagnostics,
getGlobalDiagnostics,
getTypeOfSymbolAtLocation,
// The language service will always care about the narrowed type of a symbol, because that is
// the type the language says the symbol should have.
getTypeOfSymbolAtLocation: getNarrowedTypeOfSymbol,
getDeclaredTypeOfSymbol,
getPropertiesOfType,
getPropertyOfType,
@@ -69,7 +72,7 @@ namespace ts {
getSymbolsInScope,
getSymbolAtLocation,
getShorthandAssignmentValueSymbol,
getTypeAtLocation,
getTypeAtLocation: getTypeOfNode,
typeToString,
getSymbolDisplayBuilder,
symbolToString,
@@ -159,8 +162,9 @@ namespace ts {
let emitAwaiter = false;
let emitGenerator = false;
let resolutionTargets: Object[] = [];
let resolutionTargets: TypeSystemEntity[] = [];
let resolutionResults: boolean[] = [];
let resolutionPropertyNames: TypeSystemPropertyName[] = [];
let mergedSymbols: Symbol[] = [];
let symbolLinks: SymbolLinks[] = [];
@@ -201,6 +205,15 @@ namespace ts {
let assignableRelation: Map<RelationComparisonResult> = {};
let identityRelation: Map<RelationComparisonResult> = {};
type TypeSystemEntity = Symbol | Type | Signature;
const enum TypeSystemPropertyName {
Type,
ResolvedBaseConstructorType,
DeclaredType,
ResolvedReturnType
}
initializeTypeChecker();
return checker;
@@ -1980,15 +1993,12 @@ namespace ts {
}
return _displayBuilder || (_displayBuilder = {
symbolToString: symbolToString,
typeToString: typeToString,
buildSymbolDisplay: buildSymbolDisplay,
buildTypeDisplay: buildTypeDisplay,
buildTypeParameterDisplay: buildTypeParameterDisplay,
buildParameterDisplay: buildParameterDisplay,
buildDisplayForParametersAndDelimiters: buildDisplayForParametersAndDelimiters,
buildDisplayForTypeParametersAndDelimiters: buildDisplayForTypeParametersAndDelimiters,
buildDisplayForTypeArgumentsAndDelimiters: buildDisplayForTypeArgumentsAndDelimiters,
buildTypeParameterDisplayFromSymbol: buildTypeParameterDisplayFromSymbol,
buildSignatureDisplay: buildSignatureDisplay,
buildReturnTypeDisplay: buildReturnTypeDisplay
@@ -2177,35 +2187,69 @@ namespace ts {
}
}
// Push an entry on the type resolution stack. If an entry with the given target is not already on the stack,
// a new entry with that target and an associated result value of true is pushed on the stack, and the value
// true is returned. Otherwise, a circularity has occurred and the result values of the existing entry and
// all entries pushed after it are changed to false, and the value false is returned. The target object provides
// a unique identity for a particular type resolution result: Symbol instances are used to track resolution of
// SymbolLinks.type, SymbolLinks instances are used to track resolution of SymbolLinks.declaredType, and
// Signature instances are used to track resolution of Signature.resolvedReturnType.
function pushTypeResolution(target: Object): boolean {
let i = 0;
let count = resolutionTargets.length;
while (i < count && resolutionTargets[i] !== target) {
i++;
}
if (i < count) {
do {
resolutionResults[i++] = false;
/**
* Push an entry on the type resolution stack. If an entry with the given target and the given property name
* is already on the stack, and no entries in between already have a type, then a circularity has occurred.
* In this case, the result values of the existing entry and all entries pushed after it are changed to false,
* and the value false is returned. Otherwise, the new entry is just pushed onto the stack, and true is returned.
* In order to see if the same query has already been done before, the target object and the propertyName both
* must match the one passed in.
*
* @param target The symbol, type, or signature whose type is being queried
* @param propertyName The property name that should be used to query the target for its type
*/
function pushTypeResolution(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): boolean {
let resolutionCycleStartIndex = findResolutionCycleStartIndex(target, propertyName);
if (resolutionCycleStartIndex >= 0) {
// A cycle was found
let { length } = resolutionTargets;
for (let i = resolutionCycleStartIndex; i < length; i++) {
resolutionResults[i] = false;
}
while (i < count);
return false;
}
resolutionTargets.push(target);
resolutionResults.push(true);
resolutionPropertyNames.push(propertyName);
return true;
}
function findResolutionCycleStartIndex(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): number {
for (let i = resolutionTargets.length - 1; i >= 0; i--) {
if (hasType(resolutionTargets[i], resolutionPropertyNames[i])) {
return -1;
}
if (resolutionTargets[i] === target && resolutionPropertyNames[i] === propertyName) {
return i;
}
}
return -1;
}
function hasType(target: TypeSystemEntity, propertyName: TypeSystemPropertyName): Type {
if (propertyName === TypeSystemPropertyName.Type) {
return getSymbolLinks(<Symbol>target).type;
}
if (propertyName === TypeSystemPropertyName.DeclaredType) {
return getSymbolLinks(<Symbol>target).declaredType;
}
if (propertyName === TypeSystemPropertyName.ResolvedBaseConstructorType) {
Debug.assert(!!((<Type>target).flags & TypeFlags.Class));
return (<InterfaceType>target).resolvedBaseConstructorType;
}
if (propertyName === TypeSystemPropertyName.ResolvedReturnType) {
return (<Signature>target).resolvedReturnType;
}
Debug.fail("Unhandled TypeSystemPropertyName " + propertyName);
}
// Pop an entry from the type resolution stack and return its associated result value. The result value will
// be true if no circularities were detected, or false if a circularity was found.
function popTypeResolution(): boolean {
resolutionTargets.pop();
resolutionPropertyNames.pop();
return resolutionResults.pop();
}
@@ -2274,10 +2318,6 @@ namespace ts {
// fact an iterable or array (depending on target language).
let elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false);
if (!declaration.dotDotDotToken) {
if (isTypeAny(elementType)) {
return elementType;
}
// Use specific property type when parent is a tuple or numeric index type when parent is an array
let propName = "" + indexOf(pattern.elements, declaration);
type = isTupleLikeType(parentType)
@@ -2307,6 +2347,7 @@ namespace ts {
if (declaration.parent.parent.kind === SyntaxKind.ForInStatement) {
return anyType;
}
if (declaration.parent.parent.kind === SyntaxKind.ForOfStatement) {
// checkRightHandSideOfForOf will return undefined if the for-of expression type was
// missing properties/signatures required to get its iteratedType (like
@@ -2314,13 +2355,16 @@ namespace ts {
// or it may have led to an error inside getElementTypeOfIterable.
return checkRightHandSideOfForOf((<ForOfStatement>declaration.parent.parent).expression) || anyType;
}
if (isBindingPattern(declaration.parent)) {
return getTypeForBindingElement(<BindingElement>declaration);
}
// Use type from type annotation if one is present
if (declaration.type) {
return getTypeFromTypeNode(declaration.type);
}
if (declaration.kind === SyntaxKind.Parameter) {
let func = <FunctionLikeDeclaration>declaration.parent;
// For a parameter of a set accessor, use the type of the get accessor if one is present
@@ -2336,14 +2380,22 @@ namespace ts {
return type;
}
}
// Use the type of the initializer expression if one is present
if (declaration.initializer) {
return checkExpressionCached(declaration.initializer);
}
// If it is a short-hand property assignment, use the type of the identifier
if (declaration.kind === SyntaxKind.ShorthandPropertyAssignment) {
return checkIdentifier(<Identifier>declaration.name);
}
// If the declaration specifies a binding pattern, use the type implied by the binding pattern
if (isBindingPattern(declaration.name)) {
return getTypeFromBindingPattern(<BindingPattern>declaration.name);
}
// No type specified and nothing can be inferred
return undefined;
}
@@ -2429,13 +2481,10 @@ namespace ts {
// tools see the actual type.
return declaration.kind !== SyntaxKind.PropertyAssignment ? getWidenedType(type) : type;
}
// If no type was specified and nothing could be inferred, and if the declaration specifies a binding pattern, use
// the type implied by the binding pattern
if (isBindingPattern(declaration.name)) {
return getTypeFromBindingPattern(<BindingPattern>declaration.name);
}
// Rest parameters default to type any[], other parameters default to type any
type = declaration.dotDotDotToken ? anyArrayType : anyType;
// Report implicit any errors unless this is a private property within an ambient declaration
if (reportErrors && compilerOptions.noImplicitAny) {
let root = getRootDeclaration(declaration);
@@ -2463,7 +2512,7 @@ namespace ts {
return links.type = checkExpression((<ExportAssignment>declaration).expression);
}
// Handle variable, parameter or property
if (!pushTypeResolution(symbol)) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return unknownType;
}
let type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
@@ -2504,7 +2553,7 @@ namespace ts {
function getTypeOfAccessors(symbol: Symbol): Type {
let links = getSymbolLinks(symbol);
if (!links.type) {
if (!pushTypeResolution(symbol)) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.Type)) {
return unknownType;
}
let getter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.GetAccessor);
@@ -2720,7 +2769,7 @@ namespace ts {
if (!baseTypeNode) {
return type.resolvedBaseConstructorType = undefinedType;
}
if (!pushTypeResolution(type)) {
if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) {
return unknownType;
}
let baseConstructorType = checkExpression(baseTypeNode.expression);
@@ -2847,7 +2896,7 @@ namespace ts {
if (!links.declaredType) {
// Note that we use the links object as the target here because the symbol object is used as the unique
// identity for resolution of the 'type' property in SymbolLinks.
if (!pushTypeResolution(links)) {
if (!pushTypeResolution(symbol, TypeSystemPropertyName.DeclaredType)) {
return unknownType;
}
let declaration = <TypeAliasDeclaration>getDeclarationOfKind(symbol, SyntaxKind.TypeAliasDeclaration);
@@ -3063,44 +3112,57 @@ namespace ts {
setObjectTypeMembers(type, members, arrayType.callSignatures, arrayType.constructSignatures, arrayType.stringIndexType, arrayType.numberIndexType);
}
function signatureListsIdentical(s: Signature[], t: Signature[]): boolean {
if (s.length !== t.length) {
return false;
}
for (let i = 0; i < s.length; i++) {
if (!compareSignatures(s[i], t[i], /*compareReturnTypes*/ false, compareTypes)) {
return false;
function findMatchingSignature(signature: Signature, signatureList: Signature[]): Signature {
for (let s of signatureList) {
// Only signatures with no type parameters may differ in return types
if (compareSignatures(signature, s, /*compareReturnTypes*/ !!signature.typeParameters, compareTypes)) {
return s;
}
}
return true;
}
// If the lists of call or construct signatures in the given types are all identical except for return types,
// and if none of the signatures are generic, return a list of signatures that has substitutes a union of the
// return types of the corresponding signatures in each resulting signature.
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
let signatureLists = map(types, t => getSignaturesOfType(t, kind));
let signatures = signatureLists[0];
for (let signature of signatures) {
if (signature.typeParameters) {
return emptyArray;
}
}
function findMatchingSignatures(signature: Signature, signatureLists: Signature[][]): Signature[] {
let result: Signature[] = undefined;
for (let i = 1; i < signatureLists.length; i++) {
if (!signatureListsIdentical(signatures, signatureLists[i])) {
return emptyArray;
let match = findMatchingSignature(signature, signatureLists[i]);
if (!match) {
return undefined;
}
if (!result) {
result = [signature];
}
if (match !== signature) {
result.push(match);
}
}
let result = map(signatures, cloneSignature);
for (var i = 0; i < result.length; i++) {
let s = result[i];
// Clear resolved return type we possibly got from cloneSignature
s.resolvedReturnType = undefined;
s.unionSignatures = map(signatureLists, signatures => signatures[i]);
}
return result;
}
// The signatures of a union type are those signatures that are present and identical in each of the
// constituent types, except that non-generic signatures may differ in return types. When signatures
// differ in return types, the resulting return type is the union of the constituent return types.
function getUnionSignatures(types: Type[], kind: SignatureKind): Signature[] {
let signatureLists = map(types, t => getSignaturesOfType(t, kind));
let result: Signature[] = undefined;
for (let source of signatureLists[0]) {
let unionSignatures = findMatchingSignatures(source, signatureLists);
if (unionSignatures) {
let signature: Signature = undefined;
if (unionSignatures.length === 1 || source.typeParameters) {
signature = source;
}
else {
signature = cloneSignature(source);
// Clear resolved return type we possibly got from cloneSignature
signature.resolvedReturnType = undefined;
signature.unionSignatures = unionSignatures;
}
(result || (result = [])).push(signature);
}
}
return result || emptyArray;
}
function getUnionIndexType(types: Type[], kind: IndexKind): Type {
let indexTypes: Type[] = [];
for (let type of types) {
@@ -3258,9 +3320,6 @@ namespace ts {
* type itself. Note that the apparent type of a union type is the union type itself.
*/
function getApparentType(type: Type): Type {
if (type.flags & TypeFlags.Union) {
type = getReducedTypeOfUnionType(<UnionType>type);
}
if (type.flags & TypeFlags.TypeParameter) {
do {
type = getConstraintOfTypeParameter(<TypeParameter>type);
@@ -3365,6 +3424,29 @@ namespace ts {
return undefined;
}
// Check if a property with the given name is known anywhere in the given type. In an object
// type, a property is considered known if the object type is empty, if it has any index
// signatures, or if the property is actually declared in the type. In a union or intersection
// type, a property is considered known if it is known in any constituent type.
function isKnownProperty(type: Type, name: string): boolean {
if (type.flags & TypeFlags.ObjectType && type !== globalObjectType) {
var resolved = resolveStructuredTypeMembers(type);
return !!(resolved.properties.length === 0 ||
resolved.stringIndexType ||
resolved.numberIndexType ||
getPropertyOfType(type, name));
}
if (type.flags & TypeFlags.UnionOrIntersection) {
for (let t of (<UnionOrIntersectionType>type).types) {
if (isKnownProperty(t, name)) {
return true;
}
}
return false;
}
return true;
}
function getSignaturesOfStructuredType(type: Type, kind: SignatureKind): Signature[] {
if (type.flags & TypeFlags.StructuredType) {
let resolved = resolveStructuredTypeMembers(<ObjectType>type);
@@ -3534,7 +3616,7 @@ namespace ts {
function getReturnTypeOfSignature(signature: Signature): Type {
if (!signature.resolvedReturnType) {
if (!pushTypeResolution(signature)) {
if (!pushTypeResolution(signature, TypeSystemPropertyName.ResolvedReturnType)) {
return unknownType;
}
let type: Type;
@@ -3974,26 +4056,79 @@ namespace ts {
}
}
function isSubtypeOfAny(candidate: Type, types: Type[]): boolean {
function isObjectLiteralTypeDuplicateOf(source: ObjectType, target: ObjectType): boolean {
let sourceProperties = getPropertiesOfObjectType(source);
let targetProperties = getPropertiesOfObjectType(target);
if (sourceProperties.length !== targetProperties.length) {
return false;
}
for (let sourceProp of sourceProperties) {
let targetProp = getPropertyOfObjectType(target, sourceProp.name);
if (!targetProp ||
getDeclarationFlagsFromSymbol(targetProp) & (NodeFlags.Private | NodeFlags.Protected) ||
!isTypeDuplicateOf(getTypeOfSymbol(sourceProp), getTypeOfSymbol(targetProp))) {
return false;
}
}
return true;
}
function isTupleTypeDuplicateOf(source: TupleType, target: TupleType): boolean {
let sourceTypes = source.elementTypes;
let targetTypes = target.elementTypes;
if (sourceTypes.length !== targetTypes.length) {
return false;
}
for (var i = 0; i < sourceTypes.length; i++) {
if (!isTypeDuplicateOf(sourceTypes[i], targetTypes[i])) {
return false;
}
}
return true;
}
// Returns true if the source type is a duplicate of the target type. A source type is a duplicate of
// a target type if the the two are identical, with the exception that the source type may have null or
// undefined in places where the target type doesn't. This is by design an asymmetric relationship.
function isTypeDuplicateOf(source: Type, target: Type): boolean {
if (source === target) {
return true;
}
if (source.flags & TypeFlags.Undefined || source.flags & TypeFlags.Null && !(target.flags & TypeFlags.Undefined)) {
return true;
}
if (source.flags & TypeFlags.ObjectLiteral && target.flags & TypeFlags.ObjectType) {
return isObjectLiteralTypeDuplicateOf(<ObjectType>source, <ObjectType>target);
}
if (isArrayType(source) && isArrayType(target)) {
return isTypeDuplicateOf((<TypeReference>source).typeArguments[0], (<TypeReference>target).typeArguments[0]);
}
if (isTupleType(source) && isTupleType(target)) {
return isTupleTypeDuplicateOf(<TupleType>source, <TupleType>target);
}
return isTypeIdenticalTo(source, target);
}
function isTypeDuplicateOfSomeType(candidate: Type, types: Type[]): boolean {
for (let type of types) {
if (candidate !== type && isTypeSubtypeOf(candidate, type)) {
if (candidate !== type && isTypeDuplicateOf(candidate, type)) {
return true;
}
}
return false;
}
function removeSubtypes(types: Type[]) {
function removeDuplicateTypes(types: Type[]) {
let i = types.length;
while (i > 0) {
i--;
if (isSubtypeOfAny(types[i], types)) {
if (isTypeDuplicateOfSomeType(types[i], types)) {
types.splice(i, 1);
}
}
}
function containsTypeAny(types: Type[]) {
function containsTypeAny(types: Type[]): boolean {
for (let type of types) {
if (isTypeAny(type)) {
return true;
@@ -4012,30 +4147,26 @@ namespace ts {
}
}
function compareTypeIds(type1: Type, type2: Type): number {
return type1.id - type2.id;
}
// The noSubtypeReduction flag is there because it isn't possible to always do subtype reduction. The flag
// is true when creating a union type from a type node and when instantiating a union type. In both of those
// cases subtype reduction has to be deferred to properly support recursive union types. For example, a
// type alias of the form "type Item = string | (() => Item)" cannot be reduced during its declaration.
function getUnionType(types: Type[], noSubtypeReduction?: boolean): Type {
// We always deduplicate the constituent type set based on object identity, but we'll also deduplicate
// based on the structure of the types unless the noDeduplication flag is true, which is the case when
// creating a union type from a type node and when instantiating a union type. In both of those cases,
// structural deduplication has to be deferred to properly support recursive union types. For example,
// a type of the form "type Item = string | (() => Item)" cannot be deduplicated during its declaration.
function getUnionType(types: Type[], noDeduplication?: boolean): Type {
if (types.length === 0) {
return emptyObjectType;
}
let typeSet: Type[] = [];
addTypesToSet(typeSet, types, TypeFlags.Union);
typeSet.sort(compareTypeIds);
if (noSubtypeReduction) {
if (containsTypeAny(typeSet)) {
return anyType;
}
if (containsTypeAny(typeSet)) {
return anyType;
}
if (noDeduplication) {
removeAllButLast(typeSet, undefinedType);
removeAllButLast(typeSet, nullType);
}
else {
removeSubtypes(typeSet);
removeDuplicateTypes(typeSet);
}
if (typeSet.length === 1) {
return typeSet[0];
@@ -4045,38 +4176,19 @@ namespace ts {
if (!type) {
type = unionTypes[id] = <UnionType>createObjectType(TypeFlags.Union | getWideningFlagsOfTypes(typeSet));
type.types = typeSet;
type.reducedType = noSubtypeReduction ? undefined : type;
}
return type;
}
// Subtype reduction is basically an optimization we do to avoid excessively large union types, which take longer
// to process and look strange in quick info and error messages. Semantically there is no difference between the
// reduced type and the type itself. So, when we detect a circularity we simply say that the reduced type is the
// type itself.
function getReducedTypeOfUnionType(type: UnionType): Type {
if (!type.reducedType) {
type.reducedType = circularType;
let reducedType = getUnionType(type.types, /*noSubtypeReduction*/ false);
if (type.reducedType === circularType) {
type.reducedType = reducedType;
}
}
else if (type.reducedType === circularType) {
type.reducedType = type;
}
return type.reducedType;
}
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, getTypeFromTypeNode), /*noDeduplication*/ true);
}
return links.resolvedType;
}
// We do not perform supertype reduction on intersection types. Intersection types are created only by the &
// We do not perform structural deduplication on intersection types. Intersection types are created only by the &
// type operator and we can't reduce those because we want to support recursive intersection types. For example,
// a type alias of the form "type List<T> = T & { next: List<T> }" cannot be reduced during its declaration.
// Also, unlike union types, the order of the constituent types is preserved in order that overload resolution
@@ -4179,7 +4291,7 @@ namespace ts {
// Callers should first ensure this by calling isTypeNode
case SyntaxKind.Identifier:
case SyntaxKind.QualifiedName:
let symbol = getSymbolInfo(node);
let symbol = getSymbolAtLocation(node);
return symbol && getDeclaredTypeOfSymbol(symbol);
default:
return unknownType;
@@ -4244,15 +4356,18 @@ namespace ts {
}
function createInferenceMapper(context: InferenceContext): TypeMapper {
return t => {
let mapper: TypeMapper = t => {
for (let i = 0; i < context.typeParameters.length; i++) {
if (t === context.typeParameters[i]) {
context.inferences[i].isFixed = true;
return getInferredType(context, i);
}
}
return t;
return t;
};
mapper.context = context;
return mapper;
}
function identityMapper(type: Type): Type {
@@ -4354,7 +4469,7 @@ namespace ts {
return createTupleType(instantiateList((<TupleType>type).elementTypes, mapper, instantiateType));
}
if (type.flags & TypeFlags.Union) {
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noSubtypeReduction*/ true);
return getUnionType(instantiateList((<UnionType>type).types, mapper, instantiateType), /*noDeduplication*/ true);
}
if (type.flags & TypeFlags.Intersection) {
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType));
@@ -4499,6 +4614,16 @@ namespace ts {
errorInfo = chainDiagnosticMessages(errorInfo, message, arg0, arg1, arg2);
}
function reportRelationError(message: DiagnosticMessage, source: Type, target: Type) {
let sourceType = typeToString(source);
let targetType = typeToString(target);
if (sourceType === targetType) {
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
}
reportError(message || Diagnostics.Type_0_is_not_assignable_to_type_1, sourceType, targetType);
}
// Compare two types and return
// Ternary.True if they are related with no assumptions,
// Ternary.Maybe if they are related with assumptions of other relationships, or
@@ -4518,7 +4643,23 @@ namespace ts {
if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
}
}
if (relation !== identityRelation && source.flags & TypeFlags.FreshObjectLiteral) {
if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
if (reportErrors) {
reportRelationError(headMessage, source, target);
}
return Ternary.False;
}
// Above we check for excess properties with respect to the entire target type. When union
// and intersection types are further deconstructed on the target side, we don't want to
// make the check again (as it might fail for a partial target type). Therefore we obtain
// the regular source type and proceed with that.
source = getRegularTypeOfObjectLiteral(source);
}
let saveErrorInfo = errorInfo;
if (source.flags & TypeFlags.Reference && target.flags & TypeFlags.Reference && (<TypeReference>source).target === (<TypeReference>target).target) {
// We have type references to same target type, see if relationship holds for all type arguments
if (result = typesRelatedTo((<TypeReference>source).typeArguments, (<TypeReference>target).typeArguments, reportErrors)) {
@@ -4595,18 +4736,22 @@ namespace ts {
}
if (reportErrors) {
headMessage = headMessage || Diagnostics.Type_0_is_not_assignable_to_type_1;
let sourceType = typeToString(source);
let targetType = typeToString(target);
if (sourceType === targetType) {
sourceType = typeToString(source, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
targetType = typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType);
}
reportError(headMessage, sourceType, targetType);
reportRelationError(headMessage, source, target);
}
return Ternary.False;
}
function hasExcessProperties(source: FreshObjectLiteralType, target: Type, reportErrors: boolean): boolean {
for (let prop of getPropertiesOfObjectType(source)) {
if (!isKnownProperty(target, prop.name)) {
if (reportErrors) {
reportError(Diagnostics.Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1, symbolToString(prop), typeToString(target));
}
return true;
}
}
}
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType): Ternary {
let result = Ternary.True;
let sourceTypes = source.types;
@@ -5303,6 +5448,24 @@ namespace ts {
return !!(type.flags & TypeFlags.Tuple);
}
function getRegularTypeOfObjectLiteral(type: Type): Type {
if (type.flags & TypeFlags.FreshObjectLiteral) {
let regularType = (<FreshObjectLiteralType>type).regularType;
if (!regularType) {
regularType = <ResolvedType>createType((<ResolvedType>type).flags & ~TypeFlags.FreshObjectLiteral);
regularType.symbol = (<ResolvedType>type).symbol;
regularType.members = (<ResolvedType>type).members;
regularType.properties = (<ResolvedType>type).properties;
regularType.callSignatures = (<ResolvedType>type).callSignatures;
regularType.constructSignatures = (<ResolvedType>type).constructSignatures;
regularType.stringIndexType = (<ResolvedType>type).stringIndexType;
regularType.numberIndexType = (<ResolvedType>type).numberIndexType;
}
return regularType;
}
return type;
}
function getWidenedTypeOfObjectLiteral(type: Type): Type {
let properties = getPropertiesOfObjectType(type);
let members: SymbolTable = {};
@@ -5463,7 +5626,9 @@ namespace ts {
function createInferenceContext(typeParameters: TypeParameter[], inferUnionTypes: boolean): InferenceContext {
let inferences: TypeInferences[] = [];
for (let unused of typeParameters) {
inferences.push({ primary: undefined, secondary: undefined, isFixed: false });
inferences.push({
primary: undefined, secondary: undefined, isFixed: false
});
}
return {
typeParameters,
@@ -5831,47 +5996,6 @@ namespace ts {
}
}
function resolveLocation(node: Node) {
// Resolve location from top down towards node if it is a context sensitive expression
// That helps in making sure not assigning types as any when resolved out of order
let containerNodes: Node[] = [];
for (let parent = node.parent; parent; parent = parent.parent) {
if ((isExpression(parent) || isObjectLiteralMethod(node)) &&
isContextSensitive(<Expression>parent)) {
containerNodes.unshift(parent);
}
}
ts.forEach(containerNodes, node => { getTypeOfNode(node); });
}
function getSymbolAtLocation(node: Node): Symbol {
resolveLocation(node);
return getSymbolInfo(node);
}
function getTypeAtLocation(node: Node): Type {
resolveLocation(node);
return getTypeOfNode(node);
}
function getTypeOfSymbolAtLocation(symbol: Symbol, node: Node): Type {
resolveLocation(node);
// Get the narrowed type of symbol at given location instead of just getting
// the type of the symbol.
// eg.
// function foo(a: string | number) {
// if (typeof a === "string") {
// a/**/
// }
// }
// getTypeOfSymbol for a would return type of parameter symbol string | number
// Unless we provide location /**/, checker wouldn't know how to narrow the type
// By using getNarrowedTypeOfSymbol would return string since it would be able to narrow
// it by typeguard in the if true condition
return getNarrowedTypeOfSymbol(symbol, node);
}
// Get the narrowed type of a given symbol at a given location
function getNarrowedTypeOfSymbol(symbol: Symbol, node: Node) {
let type = getTypeOfSymbol(symbol);
@@ -6764,10 +6888,23 @@ namespace ts {
return result;
}
// Presence of a contextual type mapper indicates inferential typing, except the identityMapper object is
// used as a special marker for other purposes.
/**
* Detect if the mapper implies an inference context. Specifically, there are 4 possible values
* for a mapper. Let's go through each one of them:
*
* 1. undefined - this means we are not doing inferential typing, but we may do contextual typing,
* which could cause us to assign a parameter a type
* 2. identityMapper - means we want to avoid assigning a parameter a type, whether or not we are in
* inferential typing (context is undefined for the identityMapper)
* 3. a mapper created by createInferenceMapper - we are doing inferential typing, we want to assign
* types to parameters and fix type parameters (context is defined)
* 4. an instantiation mapper created by createTypeMapper or createTypeEraser - this should never be
* passed as the contextual mapper when checking an expression (context is undefined for these)
*
* isInferentialContext is detecting if we are in case 3
*/
function isInferentialContext(mapper: TypeMapper) {
return mapper && mapper !== identityMapper;
return mapper && mapper.context;
}
// A node is an assignment target if it is on the left hand side of an '=' token, if it is parented by a property
@@ -6955,7 +7092,7 @@ namespace ts {
let stringIndexType = getIndexType(IndexKind.String);
let numberIndexType = getIndexType(IndexKind.Number);
let result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexType, numberIndexType);
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
result.flags |= TypeFlags.ObjectLiteral | TypeFlags.FreshObjectLiteral | TypeFlags.ContainsObjectLiteral | (typeFlags & TypeFlags.ContainsUndefinedOrNull);
return result;
function getIndexType(kind: IndexKind) {
@@ -8487,6 +8624,9 @@ namespace ts {
if (!produceDiagnostics) {
for (let candidate of candidates) {
if (hasCorrectArity(node, args, candidate)) {
if (candidate.typeParameters && typeArguments) {
candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode));
}
return candidate;
}
}
@@ -8835,7 +8975,7 @@ namespace ts {
}
function checkAssertion(node: AssertionExpression) {
let exprType = checkExpression(node.expression);
let exprType = getRegularTypeOfObjectLiteral(checkExpression(node.expression));
let targetType = getTypeFromTypeNode(node.type);
if (produceDiagnostics && targetType !== unknownType) {
let widenedType = getWidenedType(exprType);
@@ -8856,13 +8996,52 @@ namespace ts {
let len = signature.parameters.length - (signature.hasRestParameter ? 1 : 0);
for (let i = 0; i < len; i++) {
let parameter = signature.parameters[i];
let links = getSymbolLinks(parameter);
links.type = instantiateType(getTypeAtPosition(context, i), mapper);
let contextualParameterType = getTypeAtPosition(context, i);
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
}
if (signature.hasRestParameter && context.hasRestParameter && signature.parameters.length >= context.parameters.length) {
let parameter = lastOrUndefined(signature.parameters);
let links = getSymbolLinks(parameter);
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
let contextualParameterType = getTypeOfSymbol(lastOrUndefined(context.parameters));
assignTypeToParameterAndFixTypeParameters(parameter, contextualParameterType, mapper);
}
}
function assignTypeToParameterAndFixTypeParameters(parameter: Symbol, contextualType: Type, mapper: TypeMapper) {
let links = getSymbolLinks(parameter);
if (!links.type) {
links.type = instantiateType(contextualType, mapper);
}
else if (isInferentialContext(mapper)) {
// Even if the parameter already has a type, it might be because it was given a type while
// processing the function as an argument to a prior signature during overload resolution.
// If this was the case, it may have caused some type parameters to be fixed. So here,
// we need to ensure that type parameters at the same positions get fixed again. This is
// done by calling instantiateType to attach the mapper to the contextualType, and then
// calling inferTypes to force a walk of contextualType so that all the correct fixing
// happens. The choice to pass in links.type may seem kind of arbitrary, but it serves
// to make sure that all the correct positions in contextualType are reached by the walk.
// Here is an example:
//
// interface Base {
// baseProp;
// }
// interface Derived extends Base {
// toBase(): Base;
// }
//
// var derived: Derived;
//
// declare function foo<T>(x: T, func: (p: T) => T): T;
// declare function foo<T>(x: T, func: (p: T) => T): T;
//
// var result = foo(derived, d => d.toBase());
//
// We are typing d while checking the second overload. But we've already given d
// a type (Derived) from the first overload. However, we still want to fix the
// T in the second overload so that we do not infer Base as a candidate for T
// (inferring Base would make type argument inference inconsistent between the two
// overloads).
inferTypes(mapper.context, links.type, instantiateType(contextualType, mapper));
}
}
@@ -9082,27 +9261,36 @@ namespace ts {
let links = getNodeLinks(node);
let type = getTypeOfSymbol(node.symbol);
// Check if function expression is contextually typed and assign parameter types if so
if (!(links.flags & NodeCheckFlags.ContextChecked)) {
let contextSensitive = isContextSensitive(node);
let mightFixTypeParameters = contextSensitive && isInferentialContext(contextualMapper);
// Check if function expression is contextually typed and assign parameter types if so.
// See the comment in assignTypeToParameterAndFixTypeParameters to understand why we need to
// check mightFixTypeParameters.
if (mightFixTypeParameters || !(links.flags & NodeCheckFlags.ContextChecked)) {
let contextualSignature = getContextualSignature(node);
// If a type check is started at a function expression that is an argument of a function call, obtaining the
// contextual type may recursively get back to here during overload resolution of the call. If so, we will have
// already assigned contextual types.
if (!(links.flags & NodeCheckFlags.ContextChecked)) {
let contextChecked = !!(links.flags & NodeCheckFlags.ContextChecked);
if (mightFixTypeParameters || !contextChecked) {
links.flags |= NodeCheckFlags.ContextChecked;
if (contextualSignature) {
let signature = getSignaturesOfType(type, SignatureKind.Call)[0];
if (isContextSensitive(node)) {
if (contextSensitive) {
assignContextualParameterTypes(signature, contextualSignature, contextualMapper || identityMapper);
}
if (!node.type && !signature.resolvedReturnType) {
if (mightFixTypeParameters || !node.type && !signature.resolvedReturnType) {
let returnType = getReturnTypeFromBody(node, contextualMapper);
if (!signature.resolvedReturnType) {
signature.resolvedReturnType = returnType;
}
}
}
checkSignatureDeclaration(node);
if (!contextChecked) {
checkSignatureDeclaration(node);
}
}
}
@@ -9612,7 +9800,7 @@ namespace ts {
return getUnionType([leftType, rightType]);
case SyntaxKind.EqualsToken:
checkAssignmentOperator(rightType);
return rightType;
return getRegularTypeOfObjectLiteral(rightType);
case SyntaxKind.CommaToken:
return rightType;
}
@@ -9792,7 +9980,7 @@ namespace ts {
}
function instantiateTypeWithSingleGenericCallSignature(node: Expression | MethodDeclaration, type: Type, contextualMapper?: TypeMapper) {
if (contextualMapper && contextualMapper !== identityMapper) {
if (isInferentialContext(contextualMapper)) {
let signature = getSingleCallSignature(type);
if (signature && signature.typeParameters) {
let contextualType = getContextualType(<Expression>node);
@@ -10037,7 +10225,7 @@ namespace ts {
}
else {
checkTypeAssignableTo(typePredicate.type,
getTypeAtLocation(node.parameters[typePredicate.parameterIndex]),
getTypeOfNode(node.parameters[typePredicate.parameterIndex]),
typePredicateNode.type);
}
}
@@ -13669,7 +13857,7 @@ namespace ts {
return undefined;
}
function getSymbolInfo(node: Node) {
function getSymbolAtLocation(node: Node) {
if (isInsideWithStatementBody(node)) {
// We cannot answer semantic questions within a with block, do not proceed any further
return undefined;
@@ -13680,10 +13868,22 @@ namespace ts {
return getSymbolOfNode(node.parent);
}
if (node.kind === SyntaxKind.Identifier && isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
return node.parent.kind === SyntaxKind.ExportAssignment
? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
if (node.kind === SyntaxKind.Identifier) {
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
return node.parent.kind === SyntaxKind.ExportAssignment
? getSymbolOfEntityNameOrPropertyAccessExpression(<Identifier>node)
: getSymbolOfPartOfRightHandSideOfImportEquals(<Identifier>node);
}
else if (node.parent.kind === SyntaxKind.BindingElement &&
node.parent.parent.kind === SyntaxKind.ObjectBindingPattern &&
node === (<BindingElement>node.parent).propertyName) {
let typeOfPattern = getTypeOfNode(node.parent.parent);
let propertyDeclaration = typeOfPattern && getPropertyOfType(typeOfPattern, (<Identifier>node).text);
if (propertyDeclaration) {
return propertyDeclaration;
}
}
}
switch (node.kind) {
@@ -13760,24 +13960,24 @@ namespace ts {
}
if (isTypeDeclaration(node)) {
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
// In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
let symbol = getSymbolOfNode(node);
return getDeclaredTypeOfSymbol(symbol);
}
if (isTypeDeclarationName(node)) {
let symbol = getSymbolInfo(node);
let symbol = getSymbolAtLocation(node);
return symbol && getDeclaredTypeOfSymbol(symbol);
}
if (isDeclaration(node)) {
// In this case, we call getSymbolOfNode instead of getSymbolInfo because it is a declaration
// In this case, we call getSymbolOfNode instead of getSymbolAtLocation because it is a declaration
let symbol = getSymbolOfNode(node);
return getTypeOfSymbol(symbol);
}
if (isDeclarationName(node)) {
let symbol = getSymbolInfo(node);
let symbol = getSymbolAtLocation(node);
return symbol && getTypeOfSymbol(symbol);
}
@@ -13786,7 +13986,7 @@ namespace ts {
}
if (isInRightSideOfImportOrExportAssignment(<Identifier>node)) {
let symbol = getSymbolInfo(node);
let symbol = getSymbolAtLocation(node);
let declaredType = symbol && getDeclaredTypeOfSymbol(symbol);
return declaredType !== unknownType ? declaredType : getTypeOfSymbol(symbol);
}
@@ -13955,7 +14155,11 @@ namespace ts {
return true;
}
// const enums and modules that contain only const enums are not considered values from the emit perespective
return target !== unknownSymbol && target && target.flags & SymbolFlags.Value && !isConstEnumOrConstEnumOnlyModule(target);
// unless 'preserveConstEnums' option is set to true
return target !== unknownSymbol &&
target &&
target.flags & SymbolFlags.Value &&
(compilerOptions.preserveConstEnums || !isConstEnumOrConstEnumOnlyModule(target));
}
function isConstEnumOrConstEnumOnlyModule(s: Symbol): boolean {
@@ -254,6 +254,7 @@ namespace ts {
Only_a_void_function_can_be_called_with_the_new_keyword: { code: 2350, category: DiagnosticCategory.Error, key: "Only a void function can be called with the 'new' keyword." },
Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature: { code: 2351, category: DiagnosticCategory.Error, key: "Cannot use 'new' with an expression whose type lacks a call or construct signature." },
Neither_type_0_nor_type_1_is_assignable_to_the_other: { code: 2352, category: DiagnosticCategory.Error, key: "Neither type '{0}' nor type '{1}' is assignable to the other." },
Object_literal_may_only_specify_known_properties_and_0_does_not_exist_in_type_1: { code: 2353, category: DiagnosticCategory.Error, key: "Object literal may only specify known properties, and '{0}' does not exist in type '{1}'." },
No_best_common_type_exists_among_return_expressions: { code: 2354, category: DiagnosticCategory.Error, key: "No best common type exists among return expressions." },
A_function_whose_declared_type_is_neither_void_nor_any_must_return_a_value_or_consist_of_a_single_throw_statement: { code: 2355, category: DiagnosticCategory.Error, key: "A function whose declared type is neither 'void' nor 'any' must return a value or consist of a single 'throw' statement." },
An_arithmetic_operand_must_be_of_type_any_number_or_an_enum_type: { code: 2356, category: DiagnosticCategory.Error, key: "An arithmetic operand must be of type 'any', 'number' or an enum type." },
+4
View File
@@ -1005,6 +1005,10 @@
"category": "Error",
"code": 2352
},
"Object literal may only specify known properties, and '{0}' does not exist in type '{1}'.": {
"category": "Error",
"code": 2353
},
"No best common type exists among return expressions.": {
"category": "Error",
"code": 2354
+100 -18
View File
@@ -1425,6 +1425,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
case SyntaxKind.IfStatement:
case SyntaxKind.JsxSelfClosingElement:
case SyntaxKind.JsxOpeningElement:
case SyntaxKind.JsxExpression:
case SyntaxKind.NewExpression:
case SyntaxKind.ParenthesizedExpression:
case SyntaxKind.PostfixUnaryExpression:
@@ -3012,6 +3013,26 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
return result;
}
function emitEs6ExportDefaultCompat(node: Node) {
if (node.parent.kind === SyntaxKind.SourceFile) {
Debug.assert(!!(node.flags & NodeFlags.Default) || node.kind === SyntaxKind.ExportAssignment);
// only allow export default at a source file level
if (compilerOptions.module === ModuleKind.CommonJS || compilerOptions.module === ModuleKind.AMD || compilerOptions.module === ModuleKind.UMD) {
if (!currentSourceFile.symbol.exports["___esModule"]) {
if (languageVersion === ScriptTarget.ES5) {
// default value of configurable, enumerable, writable are `false`.
write("Object.defineProperty(exports, \"__esModule\", { value: true });");
writeLine();
}
else if (languageVersion === ScriptTarget.ES3) {
write("exports.__esModule = true;");
writeLine();
}
}
}
}
}
function emitExportMemberAssignment(node: FunctionLikeDeclaration | ClassDeclaration) {
if (node.flags & NodeFlags.Export) {
writeLine();
@@ -3034,9 +3055,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
else {
if (node.flags & NodeFlags.Default) {
emitEs6ExportDefaultCompat(node);
if (languageVersion === ScriptTarget.ES3) {
write("exports[\"default\"]");
} else {
}
else {
write("exports.default");
}
}
@@ -3249,7 +3272,11 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
function emitAssignmentExpression(root: BinaryExpression) {
let target = root.left;
let value = root.right;
if (isAssignmentExpressionStatement) {
if (isEmptyObjectLiteralOrArrayLiteral(target)) {
emit(value);
}
else if (isAssignmentExpressionStatement) {
emitDestructuringAssignment(target, value);
}
else {
@@ -4215,10 +4242,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
}
let startIndex = 0;
write(" {");
scopeEmitStart(node, "constructor");
increaseIndent();
if (ctor) {
// Emit all the directive prologues (like "use strict"). These have to come before
// any other preamble code we write (like parameter initializers).
startIndex = emitDirectivePrologues(ctor.body.statements, /*startWithNewLine*/ true);
emitDetachedComments(ctor.body.statements);
}
emitCaptureThisForNodeIfNecessary(node);
@@ -4253,7 +4285,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (superCall) {
statements = statements.slice(1);
}
emitLines(statements);
emitLinesStartingAt(statements, startIndex);
}
emitTempDeclarations(/*newLine*/ true);
writeLine();
@@ -5398,17 +5430,43 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
(!isExternalModule(currentSourceFile) && resolver.isTopLevelValueImportEqualsWithEntityName(node))) {
emitLeadingComments(node);
emitStart(node);
if (isES6ExportedDeclaration(node)) {
write("export ");
write("var ");
// variable declaration for import-equals declaration can be hoisted in system modules
// in this case 'var' should be omitted and emit should contain only initialization
let variableDeclarationIsHoisted = shouldHoistVariable(node, /*checkIfSourceFileLevelDecl*/ true);
// is it top level export import v = a.b.c in system module?
// if yes - it needs to be rewritten as exporter('v', v = a.b.c)
let isExported = isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ true);
if (!variableDeclarationIsHoisted) {
Debug.assert(!isExported);
if (isES6ExportedDeclaration(node)) {
write("export ");
write("var ");
}
else if (!(node.flags & NodeFlags.Export)) {
write("var ");
}
}
else if (!(node.flags & NodeFlags.Export)) {
write("var ");
if (isExported) {
write(`${exportFunctionForFile}("`);
emitNodeWithoutSourceMap(node.name);
write(`", `);
}
emitModuleMemberName(node);
write(" = ");
emit(node.moduleReference);
write(";");
if (isExported) {
write(")");
}
write(";");
emitEnd(node);
emitExportImportAssignments(node);
emitTrailingComments(node);
@@ -5529,6 +5587,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(")");
}
else {
emitEs6ExportDefaultCompat(node);
emitContainingModuleName(node);
if (languageVersion === ScriptTarget.ES3) {
write("[\"default\"] = ");
@@ -5747,6 +5806,8 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
write(`function ${exportStarFunction}(m) {`);
increaseIndent();
writeLine();
write(`var exports = {};`);
writeLine();
write(`for(var n in m) {`);
increaseIndent();
writeLine();
@@ -5754,10 +5815,12 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if (localNames) {
write(`&& !${localNames}.hasOwnProperty(n)`);
}
write(`) ${exportFunctionForFile}(n, m[n]);`);
write(`) exports[n] = m[n];`);
decreaseIndent();
writeLine();
write("}");
writeLine();
write(`${exportFunctionForFile}(exports);`)
decreaseIndent();
writeLine();
write("}");
@@ -5929,6 +5992,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
}
return;
}
if (isInternalModuleImportEqualsDeclaration(node)) {
if (!hoistedVars) {
hoistedVars = [];
}
hoistedVars.push(node.name);
return;
}
if (isBindingPattern(node)) {
forEach((<BindingPattern>node).elements, visit);
@@ -6090,16 +6162,23 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
if ((<ExportDeclaration>importNode).exportClause) {
// export {a, b as c} from 'foo'
// emit as:
// exports('a', _foo["a"])
// exports('c', _foo["b"])
// var reexports = {}
// reexports['a'] = _foo["a"];
// reexports['c'] = _foo["b"];
// exports_(reexports);
let reexportsVariableName = makeUniqueName("reexports");
writeLine();
write(`var ${reexportsVariableName} = {};`)
writeLine();
for (let e of (<ExportDeclaration>importNode).exportClause.elements) {
writeLine();
write(`${exportFunctionForFile}("`);
write(`${reexportsVariableName}["`);
emitNodeWithoutSourceMap(e.name);
write(`", ${parameterName}["`);
write(`"] = ${parameterName}["`);
emitNodeWithoutSourceMap(e.propertyName || e.name);
write(`"]);`);
write(`"];`);
writeLine();
}
write(`${exportFunctionForFile}(${reexportsVariableName});`);
}
else {
writeLine();
@@ -6126,14 +6205,17 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
writeLine();
for (let i = startIndex; i < node.statements.length; ++i) {
let statement = node.statements[i];
// - imports/exports are not emitted for system modules
// - external module related imports/exports are not emitted for system modules
// - function declarations are not emitted because they were already hoisted
switch (statement.kind) {
case SyntaxKind.ExportDeclaration:
case SyntaxKind.ImportDeclaration:
case SyntaxKind.ImportEqualsDeclaration:
case SyntaxKind.FunctionDeclaration:
continue;
case SyntaxKind.ImportEqualsDeclaration:
if (!isInternalModuleImportEqualsDeclaration(statement)) {
continue;
}
}
writeLine();
emit(statement);
+1 -1
View File
@@ -3295,7 +3295,7 @@ namespace ts {
function parseSuperExpression(): MemberExpression {
let expression = parseTokenNode<PrimaryExpression>();
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken) {
if (token === SyntaxKind.OpenParenToken || token === SyntaxKind.DotToken || token === SyntaxKind.OpenBracketToken) {
return expression;
}
+17 -3
View File
@@ -1762,10 +1762,12 @@ namespace ts {
FromSignature = 0x00040000, // Created for signature assignment check
ObjectLiteral = 0x00080000, // Originates in an object literal
/* @internal */
ContainsUndefinedOrNull = 0x00100000, // Type is or contains Undefined or Null type
FreshObjectLiteral = 0x00100000, // Fresh object literal type
/* @internal */
ContainsObjectLiteral = 0x00200000, // Type is or contains object literal type
ESSymbol = 0x00400000, // Type of symbol primitive introduced in ES6
ContainsUndefinedOrNull = 0x00200000, // Type is or contains Undefined or Null type
/* @internal */
ContainsObjectLiteral = 0x00400000, // Type is or contains object literal type
ESSymbol = 0x00800000, // Type of symbol primitive introduced in ES6
/* @internal */
Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null,
@@ -1858,6 +1860,14 @@ namespace ts {
numberIndexType?: Type; // Numeric index type
}
/* @internal */
// Object literals are initially marked fresh. Freshness disappears following an assignment,
// before a type assertion, or when when an object literal's type is widened. The regular
// version of a fresh type is identical except for the TypeFlags.FreshObjectLiteral flag.
export interface FreshObjectLiteralType extends ResolvedType {
regularType: ResolvedType; // Regular version of fresh type
}
// Just a place to cache element types of iterables and iterators
/* @internal */
export interface IterableOrIteratorType extends ObjectType, UnionType {
@@ -1912,6 +1922,9 @@ namespace ts {
/* @internal */
export interface TypeMapper {
(t: TypeParameter): Type;
context?: InferenceContext; // The inference context this mapper was created from.
// Only inference mappers have this set (in createInferenceMapper).
// The identity mapper and regular instantiation mappers do not need it.
}
/* @internal */
@@ -2208,6 +2221,7 @@ namespace ts {
export interface CompilerHost {
getSourceFile(fileName: string, languageVersion: ScriptTarget, onError?: (message: string) => void): SourceFile;
getCancellationToken?(): CancellationToken;
getDefaultLibFileName(options: CompilerOptions): string;
writeFile: WriteFileCallback;
getCurrentDirectory(): string;
+13 -2
View File
@@ -568,7 +568,7 @@ namespace ts {
}
}
export function isVariableLike(node: Node): boolean {
export function isVariableLike(node: Node): node is VariableLikeDeclaration {
if (node) {
switch (node.kind) {
case SyntaxKind.BindingElement:
@@ -965,7 +965,7 @@ namespace ts {
return (<ExternalModuleReference>(<ImportEqualsDeclaration>node).moduleReference).expression;
}
export function isInternalModuleImportEqualsDeclaration(node: Node) {
export function isInternalModuleImportEqualsDeclaration(node: Node): node is ImportEqualsDeclaration {
return node.kind === SyntaxKind.ImportEqualsDeclaration && (<ImportEqualsDeclaration>node).moduleReference.kind !== SyntaxKind.ExternalModuleReference;
}
@@ -1981,6 +1981,17 @@ namespace ts {
(node.parent.kind === SyntaxKind.PropertyAccessExpression && (<PropertyAccessExpression>node.parent).name === node);
}
export function isEmptyObjectLiteralOrArrayLiteral(expression: Node): boolean {
let kind = expression.kind;
if (kind === SyntaxKind.ObjectLiteralExpression) {
return (<ObjectLiteralExpression>expression).properties.length === 0;
}
if (kind === SyntaxKind.ArrayLiteralExpression) {
return (<ArrayLiteralExpression>expression).elements.length === 0;
}
return false;
}
export function getLocalSymbolForExportDefault(symbol: Symbol) {
return symbol && symbol.valueDeclaration && (symbol.valueDeclaration.flags & NodeFlags.Default) ? symbol.valueDeclaration.localSymbol : undefined;
}
+6 -7
View File
@@ -26,9 +26,8 @@ module FourSlash {
export interface FourSlashFile {
// The contents of the file (with markers, etc stripped out)
content: string;
fileName: string;
version: number;
// File-specific options (name/value pairs)
fileOptions: { [index: string]: string; };
}
@@ -671,20 +670,20 @@ module FourSlash {
let completions = this.getCompletionListAtCaret();
if ((!completions || completions.entries.length === 0) && negative) {
this.raiseError("Completion list is empty at Caret");
} else if ((completions && completions.entries.length !== 0) && !negative) {
this.raiseError("Completion list is empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition);
}
else if (completions && completions.entries.length !== 0 && !negative) {
let errorMsg = "\n" + "Completion List contains: [" + completions.entries[0].name;
for (let i = 1; i < completions.entries.length; i++) {
errorMsg += ", " + completions.entries[i].name;
}
errorMsg += "]\n";
Harness.IO.log(errorMsg);
this.raiseError("Completion list is not empty at Caret");
this.raiseError("Completion list is not empty at caret at position " + this.activeFile.fileName + " " + this.currentCaretPosition + errorMsg);
}
}
public verifyCompletionListAllowsNewIdentifier(negative: boolean) {
let completions = this.getCompletionListAtCaret();
+1
View File
@@ -12,6 +12,7 @@ interface FindFileResult {
}
interface IOLog {
timestamp: string;
arguments: string[];
executingPath: string;
currentDirectory: string;
+2 -4
View File
@@ -1,6 +1,6 @@
/// <reference path="harness.ts" />
class RunnerBase {
abstract class RunnerBase {
constructor() { }
// contains the tests to run
@@ -18,9 +18,7 @@ class RunnerBase {
/** Setup the runner's tests so that they are ready to be executed by the harness
* The first test should be a describe/it block that sets up the harness's compiler instance appropriately
*/
public initializeTests(): void {
throw new Error('method not implemented');
}
public abstract initializeTests(): void;
/** Replaces instances of full paths with fileNames only */
static removeFullPaths(path: string) {
+1 -1
View File
@@ -123,7 +123,7 @@ module RWC {
content = ts.sys.readFile(unitName);
}
catch (e) {
// Leave content undefined.
content = ts.sys.readFile(fileName);
}
return { unitName, content };
}
+3 -3
View File
@@ -971,14 +971,14 @@ interface JSON {
* @param replacer A function that transforms the results.
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
stringify(value: any, replacer: (key: string, value: any) => any, space: any): string;
stringify(value: any, replacer: (key: string, value: any) => any, space: string | number): string;
/**
* Converts a JavaScript value to a JavaScript Object Notation (JSON) string.
* @param value A JavaScript value, usually an object or array, to be converted.
* @param replacer Array that transforms the results.
* @param space Adds indentation, white space, and line break characters to the return-value JSON text to make it easier to read.
*/
stringify(value: any, replacer: any[], space: any): string;
stringify(value: any, replacer: any[], space: string | number): string;
}
/**
* An intrinsic object that provides functions to convert JavaScript values to and from the JavaScript Object Notation (JSON) format.
@@ -1181,4 +1181,4 @@ interface PromiseLike<T> {
*/
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => TResult | PromiseLike<TResult>): PromiseLike<TResult>;
then<TResult>(onfulfilled?: (value: T) => TResult | PromiseLike<TResult>, onrejected?: (reason: any) => void): PromiseLike<TResult>;
}
}
+1 -1
View File
@@ -377,7 +377,7 @@ interface String {
* @param searchString search string
* @param position If position is undefined, 0 is assumed, so as to search all of the String.
*/
contains(searchString: string, position?: number): boolean;
includes(searchString: string, position?: number): boolean;
/**
* Returns true if the sequence of elements of searchString converted to a String is the
+1 -3
View File
@@ -202,9 +202,7 @@ namespace ts.server {
return {
isMemberCompletion: false,
isNewIdentifierLocation: false,
entries: response.body,
fileName: fileName,
position: position
entries: response.body
};
}
+17 -17
View File
@@ -842,53 +842,53 @@ namespace ts.server {
private handlers : Map<(request: protocol.Request) => {response?: any, responseRequired?: boolean}> = {
[CommandNames.Exit]: () => {
this.exit();
return {};
return { responseRequired: false};
},
[CommandNames.Definition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file)};
return {response: this.getDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.TypeDefinition]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file)};
return {response: this.getTypeDefinition(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.References]: (request: protocol.Request) => {
var defArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file)};
return {response: this.getReferences(defArgs.line, defArgs.offset, defArgs.file), responseRequired: true};
},
[CommandNames.Rename]: (request: protocol.Request) => {
var renameArgs = <protocol.RenameRequestArgs>request.arguments;
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings)}
return {response: this.getRenameLocations(renameArgs.line, renameArgs.offset, renameArgs.file, renameArgs.findInComments, renameArgs.findInStrings), responseRequired: true}
},
[CommandNames.Open]: (request: protocol.Request) => {
var openArgs = <protocol.OpenRequestArgs>request.arguments;
this.openClientFile(openArgs.file);
return {}
return {responseRequired: false}
},
[CommandNames.Quickinfo]: (request: protocol.Request) => {
var quickinfoArgs = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file)};
return {response: this.getQuickInfo(quickinfoArgs.line, quickinfoArgs.offset, quickinfoArgs.file), responseRequired: true};
},
[CommandNames.Format]: (request: protocol.Request) => {
var formatArgs = <protocol.FormatRequestArgs>request.arguments;
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file)};
return {response: this.getFormattingEditsForRange(formatArgs.line, formatArgs.offset, formatArgs.endLine, formatArgs.endOffset, formatArgs.file), responseRequired: true};
},
[CommandNames.Formatonkey]: (request: protocol.Request) => {
var formatOnKeyArgs = <protocol.FormatOnKeyRequestArgs>request.arguments;
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file)};
return {response: this.getFormattingEditsAfterKeystroke(formatOnKeyArgs.line, formatOnKeyArgs.offset, formatOnKeyArgs.key, formatOnKeyArgs.file), responseRequired: true};
},
[CommandNames.Completions]: (request: protocol.Request) => {
var completionsArgs = <protocol.CompletionsRequestArgs>request.arguments;
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file)}
return {response: this.getCompletions(completionsArgs.line, completionsArgs.offset, completionsArgs.prefix, completionsArgs.file), responseRequired: true}
},
[CommandNames.CompletionDetails]: (request: protocol.Request) => {
var completionDetailsArgs = <protocol.CompletionDetailsRequestArgs>request.arguments;
return {response: this.getCompletionEntryDetails(completionDetailsArgs.line,completionDetailsArgs.offset,
completionDetailsArgs.entryNames,completionDetailsArgs.file)}
completionDetailsArgs.entryNames,completionDetailsArgs.file), responseRequired: true}
},
[CommandNames.SignatureHelp]: (request: protocol.Request) => {
var signatureHelpArgs = <protocol.SignatureHelpRequestArgs>request.arguments;
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file)}
return {response: this.getSignatureHelpItems(signatureHelpArgs.line, signatureHelpArgs.offset, signatureHelpArgs.file), responseRequired: true}
},
[CommandNames.Geterr]: (request: protocol.Request) => {
var geterrArgs = <protocol.GeterrRequestArgs>request.arguments;
@@ -923,23 +923,23 @@ namespace ts.server {
},
[CommandNames.Navto]: (request: protocol.Request) => {
var navtoArgs = <protocol.NavtoRequestArgs>request.arguments;
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount)};
return {response: this.getNavigateToItems(navtoArgs.searchValue, navtoArgs.file, navtoArgs.maxResultCount), responseRequired: true};
},
[CommandNames.Brace]: (request: protocol.Request) => {
var braceArguments = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file)};
return {response: this.getBraceMatching(braceArguments.line, braceArguments.offset, braceArguments.file), responseRequired: true};
},
[CommandNames.NavBar]: (request: protocol.Request) => {
var navBarArgs = <protocol.FileRequestArgs>request.arguments;
return {response: this.getNavigationBarItems(navBarArgs.file)};
return {response: this.getNavigationBarItems(navBarArgs.file), responseRequired: true};
},
[CommandNames.Occurrences]: (request: protocol.Request) => {
var { line, offset, file: fileName } = <protocol.FileLocationRequestArgs>request.arguments;
return {response: this.getOccurrences(line, offset, fileName)};
return {response: this.getOccurrences(line, offset, fileName), responseRequired: true};
},
[CommandNames.ProjectInfo]: (request: protocol.Request) => {
var { file, needFileNameList } = <protocol.ProjectInfoRequestArgs>request.arguments;
return {response: this.getProjectInfo(file, needFileNameList)};
return {response: this.getProjectInfo(file, needFileNameList), responseRequired: true};
},
};
addProtocolHandler(command: string, handler: (request: protocol.Request) => {response?: any, responseRequired: boolean}) {
+17 -3
View File
@@ -1105,6 +1105,7 @@ namespace ts {
}
export interface HighlightSpan {
fileName?: string;
textSpan: TextSpan;
kind: string;
}
@@ -1411,7 +1412,9 @@ namespace ts {
* @param fileName The name of the file to be released
* @param compilationSettings The compilation settings used to acquire the file
*/
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void
releaseDocument(fileName: string, compilationSettings: CompilerOptions): void;
reportStats(): string;
}
// TODO: move these to enums
@@ -3234,8 +3237,19 @@ namespace ts {
// We are *only* completing on properties from the type being destructured.
isNewIdentifierLocation = false;
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
existingMembers = (<BindingPattern>objectLikeContainer).elements;
let rootDeclaration = getRootDeclaration(objectLikeContainer.parent);
if (isVariableLike(rootDeclaration)) {
// We don't want to complete using the type acquired by the shape
// of the binding pattern; we are only interested in types acquired
// through type declaration or inference.
if (rootDeclaration.initializer || rootDeclaration.type) {
typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
existingMembers = (<BindingPattern>objectLikeContainer).elements;
}
}
else {
Debug.fail("Root declaration is not variable-like.")
}
}
else {
Debug.fail("Expected object literal or binding pattern, got " + objectLikeContainer.kind);
+21 -6
View File
@@ -64,8 +64,13 @@ namespace ts {
/** Public interface of the the of a config service shim instance.*/
export interface CoreServicesShimHost extends Logger {
/** Returns a JSON-encoded value of the type: string[] */
readDirectory(rootDir: string, extension: string): string;
/**
* Returns a JSON-encoded value of the type: string[]
*
* @param exclude A JSON encoded string[] containing the paths to exclude
* when enumerating the directory.
*/
readDirectory(rootDir: string, extension: string, exclude?: string): string;
}
///
@@ -386,8 +391,18 @@ namespace ts {
constructor(private shimHost: CoreServicesShimHost) {
}
public readDirectory(rootDir: string, extension: string): string[] {
var encoded = this.shimHost.readDirectory(rootDir, extension);
public readDirectory(rootDir: string, extension: string, exclude: string[]): string[] {
// Wrap the API changes for 1.5 release. This try/catch
// should be removed once TypeScript 1.5 has shipped.
// Also consider removing the optional designation for
// the exclude param at this time.
var encoded: string;
try {
encoded = this.shimHost.readDirectory(rootDir, extension, JSON.stringify(exclude));
}
catch (e) {
encoded = this.shimHost.readDirectory(rootDir, extension);
}
return JSON.parse(encoded);
}
}
@@ -439,11 +454,11 @@ namespace ts {
}
}
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; } []{
export function realizeDiagnostics(diagnostics: Diagnostic[], newLine: string): { message: string; start: number; length: number; category: string; code: number; } []{
return diagnostics.map(d => realizeDiagnostic(d, newLine));
}
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; } {
function realizeDiagnostic(diagnostic: Diagnostic, newLine: string): { message: string; start: number; length: number; category: string; code: number; } {
return {
message: flattenDiagnosticMessageText(diagnostic.messageText, newLine),
start: diagnostic.start,