mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Parse, bind and check spread types and elements
This commit is contained in:
+10
-2
@@ -1825,8 +1825,9 @@ namespace ts {
|
||||
case SyntaxKind.EnumMember:
|
||||
return bindPropertyOrMethodOrAccessor(<Declaration>node, SymbolFlags.EnumMember, SymbolFlags.EnumMemberExcludes);
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
case SyntaxKind.JsxSpreadAttribute:
|
||||
emitFlags |= NodeFlags.HasJsxSpreadAttributes;
|
||||
emitFlags |= NodeFlags.HasSpreadAttribute;
|
||||
return;
|
||||
|
||||
case SyntaxKind.CallSignature:
|
||||
@@ -2956,8 +2957,9 @@ namespace ts {
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.SpreadElement:
|
||||
case SyntaxKind.SpreadElementExpression:
|
||||
// This node is ES6 syntax, but is handled by a containing node.
|
||||
// This node is ES6 or ES future syntax, but is handled by a containing node.
|
||||
transformFlags |= TransformFlags.ContainsSpreadElementExpression;
|
||||
break;
|
||||
|
||||
@@ -2996,6 +2998,12 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.ContainsLexicalThis;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsSpreadElementExpression) {
|
||||
// If an ObjectLiteralExpression contains a spread element, then it
|
||||
// is an ES experimental node.
|
||||
transformFlags |= TransformFlags.AssertExperimental;
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ArrayLiteralExpression:
|
||||
|
||||
+332
-75
@@ -112,6 +112,7 @@ namespace ts {
|
||||
const tupleTypes: GenericType[] = [];
|
||||
const unionTypes = createMap<UnionType>();
|
||||
const intersectionTypes = createMap<IntersectionType>();
|
||||
const spreadTypes = createMap<SpreadType>();
|
||||
const stringLiteralTypes = createMap<LiteralType>();
|
||||
const numericLiteralTypes = createMap<LiteralType>();
|
||||
|
||||
@@ -2185,7 +2186,10 @@ namespace ts {
|
||||
writeSymbolTypeReference(type.aliasSymbol, typeArguments, 0, typeArguments ? typeArguments.length : 0, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
writeUnionOrIntersectionType(<UnionOrIntersectionType>type, nextFlags);
|
||||
writeUnionOrIntersectionType(<TypeOperatorType>type, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Spread) {
|
||||
writeSpreadType(<SpreadType>type, nextFlags);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Anonymous) {
|
||||
writeAnonymousType(<ObjectType>type, nextFlags);
|
||||
@@ -2279,7 +2283,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeUnionOrIntersectionType(type: UnionOrIntersectionType, flags: TypeFormatFlags) {
|
||||
function writeUnionOrIntersectionType(type: TypeOperatorType, flags: TypeFormatFlags) {
|
||||
if (flags & TypeFormatFlags.InElementType) {
|
||||
writePunctuation(writer, SyntaxKind.OpenParenToken);
|
||||
}
|
||||
@@ -2294,6 +2298,36 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function writeSpreadType(type: SpreadType, flags: TypeFormatFlags) {
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
let printFollowingPunctuation = false;
|
||||
for (const t of type.types) {
|
||||
if (printFollowingPunctuation) {
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
writer.writeLine();
|
||||
}
|
||||
if (t.isDeclaredProperty) {
|
||||
const saveInObjectTypeLiteral = inObjectTypeLiteral;
|
||||
inObjectTypeLiteral = true;
|
||||
writeObjectLiteralType(resolveStructuredTypeMembers(t));
|
||||
printFollowingPunctuation = false;
|
||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||
}
|
||||
else {
|
||||
writePunctuation(writer, SyntaxKind.DotDotDotToken);
|
||||
writeType(t, TypeFormatFlags.None);
|
||||
printFollowingPunctuation = true;
|
||||
}
|
||||
}
|
||||
writer.decreaseIndent();
|
||||
if (printFollowingPunctuation) {
|
||||
writeSpace(writer);
|
||||
}
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
}
|
||||
|
||||
function writeAnonymousType(type: ObjectType, flags: TypeFormatFlags) {
|
||||
const symbol = type.symbol;
|
||||
if (symbol) {
|
||||
@@ -2436,6 +2470,13 @@ namespace ts {
|
||||
writePunctuation(writer, SyntaxKind.OpenBraceToken);
|
||||
writer.writeLine();
|
||||
writer.increaseIndent();
|
||||
writeObjectLiteralType(resolved);
|
||||
writer.decreaseIndent();
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||
}
|
||||
|
||||
function writeObjectLiteralType(resolved: ResolvedType) {
|
||||
for (const signature of resolved.callSignatures) {
|
||||
buildSignatureDisplay(signature, writer, enclosingDeclaration, globalFlagsToPass, /*kind*/ undefined, symbolStack);
|
||||
writePunctuation(writer, SyntaxKind.SemicolonToken);
|
||||
@@ -2468,11 +2509,8 @@ namespace ts {
|
||||
writer.writeLine();
|
||||
}
|
||||
}
|
||||
writer.decreaseIndent();
|
||||
writePunctuation(writer, SyntaxKind.CloseBraceToken);
|
||||
inObjectTypeLiteral = saveInObjectTypeLiteral;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function buildTypeParameterDisplayFromSymbol(symbol: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags) {
|
||||
const targetSymbol = getTargetSymbol(symbol);
|
||||
@@ -2981,7 +3019,11 @@ namespace ts {
|
||||
// present (aka the tuple element property). This call also checks that the parentType is in
|
||||
// fact an iterable or array (depending on target language).
|
||||
const elementType = checkIteratedTypeOrElementType(parentType, pattern, /*allowStringInput*/ false);
|
||||
if (!declaration.dotDotDotToken) {
|
||||
if (declaration.dotDotDotToken) {
|
||||
// Rest element has an array type with the same element type as the parent type
|
||||
type = createArrayType(elementType);
|
||||
}
|
||||
else {
|
||||
// Use specific property type when parent is a tuple or numeric index type when parent is an array
|
||||
const propName = "" + indexOf(pattern.elements, declaration);
|
||||
type = isTupleLikeType(parentType)
|
||||
@@ -2997,10 +3039,6 @@ namespace ts {
|
||||
return unknownType;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// Rest element has an array type with the same element type as the parent type
|
||||
type = createArrayType(elementType);
|
||||
}
|
||||
}
|
||||
// In strict null checking mode, if a default value of a non-undefined type is specified, remove
|
||||
// undefined from the final type.
|
||||
@@ -4266,6 +4304,22 @@ namespace ts {
|
||||
setObjectTypeMembers(type, emptySymbols, callSignatures, constructSignatures, stringIndexInfo, numberIndexInfo);
|
||||
}
|
||||
|
||||
function resolveSpreadTypeMembers(type: SpreadType) {
|
||||
// The members and properties collections are empty for spread types. To get all properties of an
|
||||
// spread type use getPropertiesOfType (only the language service uses this).
|
||||
let stringIndexInfo: IndexInfo = undefined;
|
||||
let numberIndexInfo: IndexInfo = undefined;
|
||||
for (let i = type.types.length - 1; i > -1; i--) {
|
||||
const t = type.types[i];
|
||||
stringIndexInfo = intersectIndexInfos(stringIndexInfo, getIndexInfoOfType(t, IndexKind.String));
|
||||
numberIndexInfo = intersectIndexInfos(numberIndexInfo, getIndexInfoOfType(t, IndexKind.Number));
|
||||
if (!t.symbol || !(t.symbol.flags & SymbolFlags.Optional)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
setObjectTypeMembers(type, emptySymbols, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
}
|
||||
|
||||
function resolveAnonymousTypeMembers(type: AnonymousType) {
|
||||
const symbol = type.symbol;
|
||||
if (type.target) {
|
||||
@@ -4332,6 +4386,9 @@ namespace ts {
|
||||
else if (type.flags & TypeFlags.Intersection) {
|
||||
resolveIntersectionTypeMembers(<IntersectionType>type);
|
||||
}
|
||||
else if (type.flags & TypeFlags.Spread) {
|
||||
resolveSpreadTypeMembers(<SpreadType>type);
|
||||
}
|
||||
}
|
||||
return <ResolvedType>type;
|
||||
}
|
||||
@@ -4341,6 +4398,9 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.ObjectType) {
|
||||
return resolveStructuredTypeMembers(<ObjectType>type).properties;
|
||||
}
|
||||
if (type.flags & TypeFlags.Spread) {
|
||||
return getPropertiesOfType(type);
|
||||
}
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
@@ -4356,10 +4416,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
|
||||
function getPropertiesOfUnionOrIntersectionOrSpreadType(type: TypeOperatorType): Symbol[] {
|
||||
const getProperty = type.flags & TypeFlags.Spread ? getPropertyOfSpreadType : getPropertyOfUnionOrIntersectionType;
|
||||
for (const current of type.types) {
|
||||
for (const prop of getPropertiesOfType(current)) {
|
||||
getPropertyOfUnionOrIntersectionType(type, prop.name);
|
||||
getProperty(type, prop.name);
|
||||
}
|
||||
// The properties of a union type are those that are present in all constituent types, so
|
||||
// we only need to check the properties of the first type
|
||||
@@ -4372,7 +4433,8 @@ namespace ts {
|
||||
|
||||
function getPropertiesOfType(type: Type): Symbol[] {
|
||||
type = getApparentType(type);
|
||||
return type.flags & TypeFlags.UnionOrIntersection ? getPropertiesOfUnionOrIntersectionType(<UnionType>type) : getPropertiesOfObjectType(type);
|
||||
return type.flags & (TypeFlags.UnionOrIntersection | TypeFlags.Spread) ? getPropertiesOfUnionOrIntersectionOrSpreadType(<UnionType>type) :
|
||||
getPropertiesOfObjectType(type);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -4398,7 +4460,7 @@ namespace ts {
|
||||
function getApparentType(type: Type): Type {
|
||||
if (type.flags & TypeFlags.TypeParameter) {
|
||||
type = getApparentTypeOfTypeParameter(<TypeParameter>type);
|
||||
}
|
||||
}
|
||||
if (type.flags & TypeFlags.StringLike) {
|
||||
type = globalStringType;
|
||||
}
|
||||
@@ -4414,34 +4476,43 @@ namespace ts {
|
||||
return type;
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionProperty(containingType: UnionOrIntersectionType, name: string): Symbol {
|
||||
function createUnionOrIntersectionProperty(containingType: TypeOperatorType, 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;
|
||||
let isReadonly = false;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
return createUnionOrIntersectionOrSpreadPropertySymbol(containingType, name, () => {
|
||||
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;
|
||||
let isReadonly = false;
|
||||
for (const current of types) {
|
||||
const type = getApparentType(current);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop && !(getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected))) {
|
||||
commonFlags &= prop.flags;
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
else if (!contains(props, prop)) {
|
||||
props.push(prop);
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
}
|
||||
else if (!contains(props, prop)) {
|
||||
props.push(prop);
|
||||
else if (containingType.flags & TypeFlags.Union) {
|
||||
// A union type requires the property to be present in all constituent types
|
||||
return [undefined, false, 0];
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
}
|
||||
else if (containingType.flags & TypeFlags.Union) {
|
||||
// A union type requires the property to be present in all constituent types
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
return [props, isReadonly, commonFlags];
|
||||
});
|
||||
}
|
||||
|
||||
function createUnionOrIntersectionOrSpreadPropertySymbol(containingType: TypeOperatorType,
|
||||
name: string,
|
||||
symbolCreator: () => [Symbol[], boolean, SymbolFlags]) {
|
||||
const [props, isReadonly, flags] = symbolCreator();
|
||||
if (!props) {
|
||||
return undefined;
|
||||
}
|
||||
@@ -4469,17 +4540,17 @@ namespace ts {
|
||||
SymbolFlags.Property |
|
||||
SymbolFlags.Transient |
|
||||
SymbolFlags.SyntheticProperty |
|
||||
commonFlags,
|
||||
flags,
|
||||
name);
|
||||
result.containingType = containingType;
|
||||
result.hasCommonType = hasCommonType;
|
||||
result.declarations = declarations;
|
||||
result.isReadonly = isReadonly;
|
||||
result.type = containingType.flags & TypeFlags.Union ? getUnionType(propTypes) : getIntersectionType(propTypes);
|
||||
result.type = containingType.flags & TypeFlags.Intersection ? getIntersectionType(propTypes) : getUnionType(propTypes);
|
||||
return result;
|
||||
}
|
||||
|
||||
function getPropertyOfUnionOrIntersectionType(type: UnionOrIntersectionType, name: string): Symbol {
|
||||
function getPropertyOfUnionOrIntersectionType(type: TypeOperatorType, name: string): Symbol {
|
||||
const properties = type.resolvedProperties || (type.resolvedProperties = createMap<Symbol>());
|
||||
let property = properties[name];
|
||||
if (!property) {
|
||||
@@ -4491,6 +4562,61 @@ namespace ts {
|
||||
return property;
|
||||
}
|
||||
|
||||
function createSpreadProperty(containingType: SpreadType, name: string): Symbol {
|
||||
const types = containingType.types;
|
||||
return createUnionOrIntersectionOrSpreadPropertySymbol(containingType, name, () => {
|
||||
let props: Symbol[];
|
||||
// Result is readonly if any source is readonly
|
||||
let isReadonly = false;
|
||||
// Result is optional if all sources are optional
|
||||
let commonFlags = SymbolFlags.Optional;
|
||||
for (let i = types.length - 1; i > -1; i--) {
|
||||
const type = getApparentType(types[i]);
|
||||
if (type !== unknownType) {
|
||||
const prop = getPropertyOfType(type, name);
|
||||
if (prop) {
|
||||
if (prop.flags & SymbolFlags.Method && !types[i].isDeclaredProperty ||
|
||||
prop.flags & SymbolFlags.SetAccessor && !(prop.flags & SymbolFlags.GetAccessor)) {
|
||||
// skip non-object-literal methods and set-only properties and keep looking
|
||||
continue;
|
||||
}
|
||||
if (!props) {
|
||||
props = [prop];
|
||||
}
|
||||
else if (!contains(props, prop)) {
|
||||
props.unshift(prop);
|
||||
}
|
||||
if (isReadonlySymbol(prop)) {
|
||||
isReadonly = true;
|
||||
}
|
||||
if (getDeclarationModifierFlagsFromSymbol(prop) & (ModifierFlags.Private | ModifierFlags.Protected)) {
|
||||
// return immediately because even if prop is optional, it would make the unioned spread property private
|
||||
return [undefined, false, 0];
|
||||
}
|
||||
if (!(prop.flags & SymbolFlags.Optional)) {
|
||||
// Reset extraFlags to None since we found a non-optional property
|
||||
commonFlags = SymbolFlags.None;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return [props, isReadonly, commonFlags];
|
||||
});
|
||||
}
|
||||
|
||||
function getPropertyOfSpreadType(type: TypeOperatorType, name: string): Symbol {
|
||||
const properties = type.resolvedProperties || (type.resolvedProperties = createMap<Symbol>());
|
||||
let property = properties[name];
|
||||
if (!property) {
|
||||
property = createSpreadProperty(type as SpreadType, name);
|
||||
if (property) {
|
||||
properties[name] = property;
|
||||
}
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the symbol for the property with the given name in the given type. Creates synthetic union properties when
|
||||
* necessary, maps primitive types and type parameters are to their apparent types, and augments with properties from
|
||||
@@ -4516,7 +4642,10 @@ namespace ts {
|
||||
return getPropertyOfObjectType(globalObjectType, name);
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getPropertyOfUnionOrIntersectionType(<UnionOrIntersectionType>type, name);
|
||||
return getPropertyOfUnionOrIntersectionType(<TypeOperatorType>type, name);
|
||||
}
|
||||
if (type.flags & TypeFlags.Spread) {
|
||||
return getPropertyOfSpreadType(<SpreadType>type, name);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
@@ -5538,8 +5667,44 @@ namespace ts {
|
||||
function getTypeFromTypeLiteralOrFunctionOrConstructorTypeNode(node: Node, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
|
||||
const links = getNodeLinks(node);
|
||||
if (!links.resolvedType) {
|
||||
// Deferred resolution of members is handled by resolveObjectTypeMembers
|
||||
const type = createObjectType(TypeFlags.Anonymous, node.symbol);
|
||||
const isSpread = (node.kind === SyntaxKind.TypeLiteral &&
|
||||
find((node as TypeLiteralNode).members, elt => elt.kind === SyntaxKind.SpreadTypeElement));
|
||||
let type: ObjectType;
|
||||
if (isSpread) {
|
||||
let members: Map<Symbol>;
|
||||
const spreads: SpreadElementType[] = [];
|
||||
for (const member of (node as TypeLiteralNode).members) {
|
||||
if (member.kind === SyntaxKind.SpreadTypeElement) {
|
||||
if (members) {
|
||||
const t = createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined) as SpreadElementType;
|
||||
t.isDeclaredProperty = true;
|
||||
spreads.push(t);
|
||||
members = undefined;
|
||||
}
|
||||
spreads.push(getTypeFromTypeNode((member as SpreadTypeElement).type) as SpreadElementType);
|
||||
}
|
||||
else if (member.kind !== SyntaxKind.CallSignature && member.kind !== SyntaxKind.ConstructSignature) {
|
||||
// note that spread types don't include call and construct signatures
|
||||
const flags = SymbolFlags.Property | SymbolFlags.Transient | (member.questionToken ? SymbolFlags.Optional : 0);
|
||||
const text = getTextOfPropertyName(member.name);
|
||||
const symbol = <TransientSymbol>createSymbol(flags, text);
|
||||
symbol.type = getTypeFromTypeNodeNoAlias((member as IndexSignatureDeclaration | PropertySignature | MethodSignature).type);
|
||||
if (!members) {
|
||||
members = createMap<Symbol>();
|
||||
}
|
||||
members[symbol.name] = symbol;
|
||||
}
|
||||
}
|
||||
if (members) {
|
||||
const t = createAnonymousType(undefined, members, emptyArray, emptyArray, undefined, undefined) as SpreadElementType;
|
||||
t.isDeclaredProperty = true;
|
||||
spreads.push(t);
|
||||
}
|
||||
return getSpreadType(spreads, node.symbol);
|
||||
}
|
||||
else {
|
||||
type = createObjectType(TypeFlags.Anonymous, node.symbol);
|
||||
}
|
||||
type.aliasSymbol = aliasSymbol;
|
||||
type.aliasTypeArguments = aliasTypeArguments;
|
||||
links.resolvedType = type;
|
||||
@@ -5547,6 +5712,18 @@ namespace ts {
|
||||
return links.resolvedType;
|
||||
}
|
||||
|
||||
function getSpreadType(types: SpreadElementType[], symbol: Symbol, aliasSymbol?: Symbol, aliasTypeArguments?: Type[]): Type {
|
||||
const id = getTypeListId(types);
|
||||
if (id in spreadTypes) {
|
||||
return spreadTypes[id];
|
||||
}
|
||||
const spread = spreadTypes[id] = createObjectType(TypeFlags.Spread, symbol) as SpreadType;
|
||||
spread.types = filter(types, t => !(t.flags & (TypeFlags.Null | TypeFlags.Undefined)));
|
||||
spread.aliasSymbol = aliasSymbol;
|
||||
spread.aliasTypeArguments = aliasTypeArguments;
|
||||
return spread;
|
||||
}
|
||||
|
||||
function createLiteralType(flags: TypeFlags, text: string) {
|
||||
const type = <LiteralType>createType(flags);
|
||||
type.text = text;
|
||||
@@ -5937,6 +6114,9 @@ namespace ts {
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
return getIntersectionType(instantiateList((<IntersectionType>type).types, mapper, instantiateType), type.aliasSymbol, mapper.targetTypes);
|
||||
}
|
||||
if (type.flags & TypeFlags.Spread) {
|
||||
return getSpreadType(instantiateList((type as SpreadType).types, mapper, instantiateType) as SpreadElementType[], type.symbol, type.aliasSymbol, mapper.targetTypes);
|
||||
}
|
||||
}
|
||||
return type;
|
||||
}
|
||||
@@ -6460,6 +6640,26 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.Spread && target.flags & TypeFlags.Spread) {
|
||||
const sourceParameters = filter((source as SpreadType).types, t => !!(t.flags & TypeFlags.TypeParameter));
|
||||
const targetParameters = filter((target as SpreadType).types, t => !!(t.flags & TypeFlags.TypeParameter));
|
||||
if (sourceParameters.length !== targetParameters.length) {
|
||||
reportRelationError(headMessage, source, target);
|
||||
return Ternary.False;
|
||||
}
|
||||
for (let i = 0; i < sourceParameters.length; i++) {
|
||||
if (sourceParameters[i].symbol !== targetParameters[i].symbol) {
|
||||
reportRelationError(headMessage, source, target);
|
||||
return Ternary.False;
|
||||
}
|
||||
}
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo;
|
||||
if (result = objectTypeRelatedTo(source, source, target, reportStructuralErrors)) {
|
||||
errorInfo = saveErrorInfo;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (source.flags & TypeFlags.TypeParameter) {
|
||||
let constraint = getConstraintOfTypeParameter(<TypeParameter>source);
|
||||
|
||||
@@ -6490,7 +6690,7 @@ namespace ts {
|
||||
// In a check of the form X = A & B, we will have previously checked if A relates to X or B relates
|
||||
// to X. Failing both of those we want to check if the aggregation of A and B's members structurally
|
||||
// relates to X. Thus, we include intersection types on the source side here.
|
||||
if (apparentSource.flags & (TypeFlags.ObjectType | TypeFlags.Intersection) && target.flags & TypeFlags.ObjectType) {
|
||||
if (apparentSource.flags & (TypeFlags.ObjectType | TypeFlags.Intersection | TypeFlags.Spread) && target.flags & TypeFlags.ObjectType) {
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !(source.flags & TypeFlags.Primitive);
|
||||
if (result = objectTypeRelatedTo(apparentSource, source, target, reportStructuralErrors)) {
|
||||
@@ -6525,8 +6725,8 @@ namespace ts {
|
||||
}
|
||||
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union ||
|
||||
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
|
||||
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target, /*reportErrors*/ false)) {
|
||||
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source, /*reportErrors*/ false)) {
|
||||
if (result = eachTypeRelatedToSomeType(<TypeOperatorType>source, <TypeOperatorType>target, /*reportErrors*/ false)) {
|
||||
if (result &= eachTypeRelatedToSomeType(<TypeOperatorType>target, <TypeOperatorType>source, /*reportErrors*/ false)) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -6549,7 +6749,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
for (const t of (<UnionOrIntersectionType>type).types) {
|
||||
for (const t of (<TypeOperatorType>type).types) {
|
||||
if (isKnownProperty(t, name)) {
|
||||
return true;
|
||||
}
|
||||
@@ -6586,7 +6786,7 @@ namespace ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
function eachTypeRelatedToSomeType(source: UnionOrIntersectionType, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
function eachTypeRelatedToSomeType(source: TypeOperatorType, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
@@ -6599,7 +6799,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToSomeType(source: Type, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
const targetTypes = target.types;
|
||||
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
|
||||
return Ternary.True;
|
||||
@@ -6614,7 +6814,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function typeRelatedToEachType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
|
||||
function typeRelatedToEachType(source: Type, target: TypeOperatorType, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const targetTypes = target.types;
|
||||
for (const targetType of targetTypes) {
|
||||
@@ -6627,7 +6827,7 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function someTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||
function someTypeRelatedToType(source: TypeOperatorType, target: Type, reportErrors: boolean): Ternary {
|
||||
const sourceTypes = source.types;
|
||||
if (source.flags & TypeFlags.Union && containsType(sourceTypes, target)) {
|
||||
return Ternary.True;
|
||||
@@ -6642,7 +6842,7 @@ namespace ts {
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean): Ternary {
|
||||
function eachTypeRelatedToType(source: TypeOperatorType, target: Type, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
@@ -7578,10 +7778,10 @@ namespace ts {
|
||||
return !!(type.flags & TypeFlags.TypeParameter ||
|
||||
type.flags & TypeFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
|
||||
type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
|
||||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
|
||||
type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<TypeOperatorType>type));
|
||||
}
|
||||
|
||||
function couldUnionOrIntersectionContainTypeParameters(type: UnionOrIntersectionType): boolean {
|
||||
function couldUnionOrIntersectionContainTypeParameters(type: TypeOperatorType): boolean {
|
||||
if (type.couldContainTypeParameters === undefined) {
|
||||
type.couldContainTypeParameters = forEach(type.types, couldContainTypeParameters);
|
||||
}
|
||||
@@ -7589,7 +7789,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
function isTypeParameterAtTopLevel(type: Type, typeParameter: TypeParameter): boolean {
|
||||
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<UnionOrIntersectionType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
|
||||
return type === typeParameter || type.flags & TypeFlags.UnionOrIntersection && forEach((<TypeOperatorType>type).types, t => isTypeParameterAtTopLevel(t, typeParameter));
|
||||
}
|
||||
|
||||
function inferTypes(context: InferenceContext, originalSource: Type, originalTarget: Type) {
|
||||
@@ -7619,7 +7819,7 @@ namespace ts {
|
||||
// Source and target are both unions or both intersections. If source and target
|
||||
// are the same type, just relate each constituent type to itself.
|
||||
if (source === target) {
|
||||
for (const t of (<UnionOrIntersectionType>source).types) {
|
||||
for (const t of (<TypeOperatorType>source).types) {
|
||||
inferFromTypes(t, t);
|
||||
}
|
||||
return;
|
||||
@@ -7631,14 +7831,14 @@ namespace ts {
|
||||
// and string literals because the number and string types are not represented as unions
|
||||
// of all their possible values.
|
||||
let matchingTypes: Type[];
|
||||
for (const t of (<UnionOrIntersectionType>source).types) {
|
||||
if (typeIdenticalToSomeType(t, (<UnionOrIntersectionType>target).types)) {
|
||||
for (const t of (<TypeOperatorType>source).types) {
|
||||
if (typeIdenticalToSomeType(t, (<TypeOperatorType>target).types)) {
|
||||
(matchingTypes || (matchingTypes = [])).push(t);
|
||||
inferFromTypes(t, t);
|
||||
}
|
||||
else if (t.flags & (TypeFlags.NumberLiteral | TypeFlags.StringLiteral)) {
|
||||
const b = getBaseTypeOfLiteralType(t);
|
||||
if (typeIdenticalToSomeType(b, (<UnionOrIntersectionType>target).types)) {
|
||||
if (typeIdenticalToSomeType(b, (<TypeOperatorType>target).types)) {
|
||||
(matchingTypes || (matchingTypes = [])).push(t, b);
|
||||
}
|
||||
}
|
||||
@@ -7647,8 +7847,8 @@ namespace ts {
|
||||
// removing the identically matched constituents. For example, when inferring from
|
||||
// 'string | string[]' to 'string | T' we reduce the types to 'string[]' and 'T'.
|
||||
if (matchingTypes) {
|
||||
source = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>source, matchingTypes);
|
||||
target = removeTypesFromUnionOrIntersection(<UnionOrIntersectionType>target, matchingTypes);
|
||||
source = removeTypesFromUnionOrIntersection(<TypeOperatorType>source, matchingTypes);
|
||||
target = removeTypesFromUnionOrIntersection(<TypeOperatorType>target, matchingTypes);
|
||||
}
|
||||
}
|
||||
if (target.flags & TypeFlags.TypeParameter) {
|
||||
@@ -7695,7 +7895,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
else if (target.flags & TypeFlags.UnionOrIntersection) {
|
||||
const targetTypes = (<UnionOrIntersectionType>target).types;
|
||||
const targetTypes = (<TypeOperatorType>target).types;
|
||||
let typeParameterCount = 0;
|
||||
let typeParameter: TypeParameter;
|
||||
// First infer to each type in union or intersection that isn't a type parameter
|
||||
@@ -7719,7 +7919,7 @@ namespace ts {
|
||||
}
|
||||
else if (source.flags & TypeFlags.UnionOrIntersection) {
|
||||
// Source is a union or intersection type, infer from each constituent type
|
||||
const sourceTypes = (<UnionOrIntersectionType>source).types;
|
||||
const sourceTypes = (<TypeOperatorType>source).types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
inferFromTypes(sourceType, target);
|
||||
}
|
||||
@@ -7824,7 +8024,7 @@ namespace ts {
|
||||
* Return a new union or intersection type computed by removing a given set of types
|
||||
* from a given union or intersection type.
|
||||
*/
|
||||
function removeTypesFromUnionOrIntersection(type: UnionOrIntersectionType, typesToRemove: Type[]) {
|
||||
function removeTypesFromUnionOrIntersection(type: TypeOperatorType, typesToRemove: Type[]) {
|
||||
const reducedTypes: Type[] = [];
|
||||
for (const t of type.types) {
|
||||
if (!typeIdenticalToSomeType(t, typesToRemove)) {
|
||||
@@ -8148,7 +8348,7 @@ namespace ts {
|
||||
return getTypeFacts(constraint || emptyObjectType);
|
||||
}
|
||||
if (flags & TypeFlags.UnionOrIntersection) {
|
||||
return getTypeFactsOfTypes((<UnionOrIntersectionType>type).types);
|
||||
return getTypeFactsOfTypes((<TypeOperatorType>type).types);
|
||||
}
|
||||
return TypeFacts.All;
|
||||
}
|
||||
@@ -10184,8 +10384,9 @@ namespace ts {
|
||||
// Grammar checking
|
||||
checkGrammarObjectLiteralExpression(node, inDestructuringPattern);
|
||||
|
||||
const propertiesTable = createMap<Symbol>();
|
||||
const propertiesArray: Symbol[] = [];
|
||||
let propertiesTable = createMap<Symbol>();
|
||||
let propertiesArray: Symbol[] = [];
|
||||
const spreads: SpreadElementType[] = [];
|
||||
const contextualType = getApparentTypeOfContextualType(node);
|
||||
const contextualTypeHasPattern = contextualType && contextualType.pattern &&
|
||||
(contextualType.pattern.kind === SyntaxKind.ObjectBindingPattern || contextualType.pattern.kind === SyntaxKind.ObjectLiteralExpression);
|
||||
@@ -10210,6 +10411,14 @@ namespace ts {
|
||||
Debug.assert(memberDecl.kind === SyntaxKind.ShorthandPropertyAssignment);
|
||||
type = checkExpressionForMutableLocation((<ShorthandPropertyAssignment>memberDecl).name, contextualMapper);
|
||||
}
|
||||
|
||||
if (hasProperty(propertiesTable, member.name)) {
|
||||
const existingPropType = getTypeOfSymbol(propertiesTable[member.name]);
|
||||
if (!isTypeIdenticalTo(existingPropType, type)) {
|
||||
error(memberDecl.name, Diagnostics.Cannot_change_type_of_property_0_from_1_to_2, member.name, typeToString(existingPropType), typeToString(type));
|
||||
}
|
||||
}
|
||||
|
||||
typeFlags |= type.flags;
|
||||
const prop = <TransientSymbol>createSymbol(SymbolFlags.Property | SymbolFlags.Transient | member.flags, member.name);
|
||||
if (inDestructuringPattern) {
|
||||
@@ -10247,6 +10456,19 @@ namespace ts {
|
||||
prop.target = member;
|
||||
member = prop;
|
||||
}
|
||||
else if (memberDecl.kind === SyntaxKind.SpreadElement) {
|
||||
if (propertiesArray.length > 0) {
|
||||
const t = createObjectLiteralType(node, hasComputedStringProperty, hasComputedNumberProperty, propertiesArray, propertiesTable, typeFlags, patternWithComputedProperties, inDestructuringPattern) as SpreadElementType;
|
||||
t.isDeclaredProperty = true;
|
||||
spreads.push(t);
|
||||
propertiesArray = [];
|
||||
propertiesTable = createMap<Symbol>();
|
||||
hasComputedStringProperty = false;
|
||||
hasComputedNumberProperty = false;
|
||||
}
|
||||
spreads.push(checkExpression((memberDecl as SpreadElement).target) as SpreadElementType);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
// TypeScript 1.0 spec (April 2014)
|
||||
// A get accessor declaration is processed in the same manner as
|
||||
@@ -10286,6 +10508,22 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
if (spreads.length > 0) {
|
||||
if (propertiesArray.length > 0) {
|
||||
const t = createObjectLiteralType(node, hasComputedStringProperty, hasComputedNumberProperty, propertiesArray, propertiesTable, typeFlags, patternWithComputedProperties, inDestructuringPattern) as SpreadElementType;
|
||||
t.isDeclaredProperty = true;
|
||||
spreads.push(t);
|
||||
}
|
||||
const propagatedFlags = getPropagatingFlagsOfTypes(spreads, /*excludeKinds*/ TypeFlags.Nullable);
|
||||
const spread = getSpreadType(spreads, node.symbol);
|
||||
spread.flags |= propagatedFlags;
|
||||
return spread;
|
||||
}
|
||||
|
||||
return createObjectLiteralType(node, hasComputedStringProperty, hasComputedNumberProperty, propertiesArray, propertiesTable, typeFlags, patternWithComputedProperties, inDestructuringPattern);
|
||||
}
|
||||
|
||||
function createObjectLiteralType(node: ObjectLiteralExpression, hasComputedStringProperty: boolean, hasComputedNumberProperty: boolean, propertiesArray: Symbol[], propertiesTable: Map<Symbol>, typeFlags: TypeFlags, patternWithComputedProperties: boolean, inDestructuringPattern: boolean) {
|
||||
const stringIndexInfo = hasComputedStringProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.String) : undefined;
|
||||
const numberIndexInfo = hasComputedNumberProperty ? getObjectLiteralIndexInfo(node, propertiesArray, IndexKind.Number) : undefined;
|
||||
const result = createAnonymousType(node.symbol, propertiesTable, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo);
|
||||
@@ -10534,7 +10772,7 @@ namespace ts {
|
||||
elemType = checkExpression(node.tagName);
|
||||
}
|
||||
if (elemType.flags & TypeFlags.Union) {
|
||||
const types = (<UnionOrIntersectionType>elemType).types;
|
||||
const types = (<TypeOperatorType>elemType).types;
|
||||
return getUnionType(types.map(type => {
|
||||
return getResolvedJsxType(node, type, elemClassType);
|
||||
}), /*subtypeReduction*/ true);
|
||||
@@ -13096,7 +13334,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.UnionOrIntersection) {
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
for (const t of types) {
|
||||
if (maybeTypeOfKind(t, kind)) {
|
||||
return true;
|
||||
@@ -13114,7 +13352,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Union) {
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
for (const t of types) {
|
||||
if (!isTypeOfKind(t, kind)) {
|
||||
return false;
|
||||
@@ -13123,7 +13361,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (type.flags & TypeFlags.Intersection) {
|
||||
const types = (<UnionOrIntersectionType>type).types;
|
||||
const types = (<TypeOperatorType>type).types;
|
||||
for (const t of types) {
|
||||
if (isTypeOfKind(t, kind)) {
|
||||
return true;
|
||||
@@ -19194,7 +19432,7 @@ namespace ts {
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasClassExtends && languageVersion < ScriptTarget.ES6) {
|
||||
verifyHelperSymbol(exports, "__extends", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasJsxSpreadAttributes && compilerOptions.jsx !== JsxEmit.Preserve) {
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasSpreadAttribute && compilerOptions.jsx !== JsxEmit.Preserve) {
|
||||
verifyHelperSymbol(exports, "__assign", SymbolFlags.Value);
|
||||
}
|
||||
if (requestedExternalEmitHelpers & NodeFlags.HasDecorators) {
|
||||
@@ -19758,6 +19996,11 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
let result: TypeElement;
|
||||
if (result = find(node.members, e => e.kind === SyntaxKind.SpreadTypeElement)) {
|
||||
return grammarErrorOnNode(result, Diagnostics.Interface_declaration_cannot_contain_a_spread_property);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -19805,9 +20048,23 @@ namespace ts {
|
||||
const GetOrSetAccessor = GetAccessor | SetAccessor;
|
||||
|
||||
for (const prop of node.properties) {
|
||||
if (prop.kind === SyntaxKind.SpreadElement) {
|
||||
const target = (prop as SpreadElement).target;
|
||||
switch (target.kind) {
|
||||
case SyntaxKind.Identifier:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ObjectLiteralExpression:
|
||||
case SyntaxKind.NullKeyword:
|
||||
break;
|
||||
default:
|
||||
grammarErrorOnNode(target, Diagnostics.Spread_properties_must_be_identifiers_property_accesses_or_object_literals);
|
||||
}
|
||||
|
||||
continue;
|
||||
}
|
||||
const name = prop.name;
|
||||
if (prop.kind === SyntaxKind.OmittedExpression ||
|
||||
name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
name && name.kind === SyntaxKind.ComputedPropertyName) {
|
||||
// If the name is not a ComputedPropertyName, the grammar checking will skip it
|
||||
checkGrammarComputedPropertyName(<ComputedPropertyName>name);
|
||||
}
|
||||
@@ -20127,7 +20384,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
if (node.initializer) {
|
||||
// Error on equals token which immediate precedes the initializer
|
||||
// Error on equals token which immediately precedes the initializer
|
||||
return grammarErrorAtPos(getSourceFileOfNode(node), node.initializer.pos - 1, 1, Diagnostics.A_rest_element_cannot_have_an_initializer);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1963,6 +1963,18 @@
|
||||
"category": "Error",
|
||||
"code": 2696
|
||||
},
|
||||
"Spread properties must be identifiers, property accesses, or object literals.": {
|
||||
"category": "Error",
|
||||
"code": 2697
|
||||
},
|
||||
"Cannot change type of property '{0}' from '{1}' to '{2}'.": {
|
||||
"category": "Error",
|
||||
"code": 2698
|
||||
},
|
||||
"Interface declaration cannot contain a spread property.": {
|
||||
"category": "Error",
|
||||
"code": 2699
|
||||
},
|
||||
|
||||
"Import declaration '{0}' is using private name '{1}'.": {
|
||||
"category": "Error",
|
||||
|
||||
+28
-1
@@ -74,6 +74,11 @@ namespace ts {
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).questionToken) ||
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).equalsToken) ||
|
||||
visitNode(cbNode, (<ShorthandPropertyAssignment>node).objectAssignmentInitializer);
|
||||
case SyntaxKind.SpreadElement:
|
||||
return visitNode(cbNode, (<SpreadElement>node).dotDotDotToken) ||
|
||||
visitNode(cbNode, (<SpreadElement>node).target);
|
||||
case SyntaxKind.SpreadTypeElement:
|
||||
return visitNode(cbNode, (node as SpreadTypeElement).type);
|
||||
case SyntaxKind.Parameter:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.PropertySignature:
|
||||
@@ -1262,7 +1267,7 @@ namespace ts {
|
||||
// which would be a candidate for improved error reporting.
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
case ParsingContext.ObjectLiteralMembers:
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || isLiteralPropertyName();
|
||||
return token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.AsteriskToken || token() === SyntaxKind.DotDotDotToken || isLiteralPropertyName();
|
||||
case ParsingContext.ObjectBindingElements:
|
||||
return token() === SyntaxKind.OpenBracketToken || isLiteralPropertyName();
|
||||
case ParsingContext.HeritageClauseElement:
|
||||
@@ -2328,6 +2333,10 @@ namespace ts {
|
||||
if (token() === SyntaxKind.OpenBracketToken) {
|
||||
return true;
|
||||
}
|
||||
// spread elements are type members
|
||||
if (token() === SyntaxKind.DotDotDotToken) {
|
||||
return true;
|
||||
}
|
||||
// Try to get the first property-like token following all modifiers
|
||||
if (isLiteralPropertyName()) {
|
||||
idToken = token();
|
||||
@@ -2353,6 +2362,9 @@ namespace ts {
|
||||
if (token() === SyntaxKind.NewKeyword && lookAhead(isStartOfConstructSignature)) {
|
||||
return parseSignatureMember(SyntaxKind.ConstructSignature);
|
||||
}
|
||||
if (token() === SyntaxKind.DotDotDotToken) {
|
||||
return parseSpreadTypeElement();
|
||||
}
|
||||
const fullStart = getNodePos();
|
||||
const modifiers = parseModifiers();
|
||||
if (isIndexSignature()) {
|
||||
@@ -2361,6 +2373,14 @@ namespace ts {
|
||||
return parsePropertyOrMethodSignature(fullStart, modifiers);
|
||||
}
|
||||
|
||||
function parseSpreadTypeElement() {
|
||||
const element = createNode(SyntaxKind.SpreadTypeElement, scanner.getStartPos()) as SpreadTypeElement;
|
||||
parseTokenNode<Node>(); // parse `...`
|
||||
element.type = parseType();
|
||||
parseTypeMemberSemicolon();
|
||||
return finishNode(element);
|
||||
}
|
||||
|
||||
function isStartOfConstructSignature() {
|
||||
nextToken();
|
||||
return token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.LessThanToken;
|
||||
@@ -4123,6 +4143,13 @@ namespace ts {
|
||||
|
||||
function parseObjectLiteralElement(): ObjectLiteralElement {
|
||||
const fullStart = scanner.getStartPos();
|
||||
const dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
|
||||
if (dotDotDotToken) {
|
||||
const spreadElement = <SpreadElement>createNode(SyntaxKind.SpreadElement, fullStart);
|
||||
spreadElement.dotDotDotToken = dotDotDotToken;
|
||||
spreadElement.target = parseAssignmentExpressionOrHigher();
|
||||
return addJSDocComment(finishNode(spreadElement));
|
||||
}
|
||||
const decorators = parseDecorators();
|
||||
const modifiers = parseModifiers();
|
||||
|
||||
|
||||
+60
-32
@@ -316,6 +316,9 @@ namespace ts {
|
||||
// Property assignments
|
||||
PropertyAssignment,
|
||||
ShorthandPropertyAssignment,
|
||||
SpreadElement, // maybe name it SpreadProperty?
|
||||
SpreadTypeElement, // maybe name it SpreadTypeNode?
|
||||
|
||||
|
||||
// Enum
|
||||
EnumMember,
|
||||
@@ -412,7 +415,7 @@ namespace ts {
|
||||
HasDecorators = 1 << 11, // If the file has decorators (initialized by binding)
|
||||
HasParamDecorators = 1 << 12, // If the file has parameter decorators (initialized by binding)
|
||||
HasAsyncFunctions = 1 << 13, // If the file has async functions (initialized by binding)
|
||||
HasJsxSpreadAttributes = 1 << 14, // If the file as JSX spread attributes (initialized by binding)
|
||||
HasSpreadAttribute = 1 << 14, // If the file as JSX spread attributes (initialized by binding)
|
||||
DisallowInContext = 1 << 15, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 16, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 17, // If node was parsed as part of a decorator
|
||||
@@ -425,7 +428,7 @@ namespace ts {
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
ReachabilityCheckFlags = HasImplicitReturn | HasExplicitReturn,
|
||||
EmitHelperFlags = HasClassExtends | HasDecorators | HasParamDecorators | HasAsyncFunctions | HasJsxSpreadAttributes,
|
||||
EmitHelperFlags = HasClassExtends | HasDecorators | HasParamDecorators | HasAsyncFunctions | HasSpreadAttribute,
|
||||
ReachabilityAndEmitFlags = ReachabilityCheckFlags | EmitHelperFlags,
|
||||
|
||||
// Parsing context flags
|
||||
@@ -450,7 +453,6 @@ namespace ts {
|
||||
Async = 1 << 8, // Property/Method/Function
|
||||
Default = 1 << 9, // Function/Class (export default declaration)
|
||||
Const = 1 << 11, // Variable declaration
|
||||
|
||||
HasComputedFlags = 1 << 29, // Modifier flags have been computed
|
||||
|
||||
AccessibilityModifier = Public | Private | Protected,
|
||||
@@ -635,6 +637,11 @@ namespace ts {
|
||||
initializer?: Expression; // Optional initializer
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.SpreadTypeElement)
|
||||
export interface SpreadTypeElement extends TypeElement {
|
||||
type: TypeNode;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.PropertyDeclaration)
|
||||
export interface PropertyDeclaration extends ClassElement {
|
||||
questionToken?: Node; // Present for use with reporting a grammar error
|
||||
@@ -666,6 +673,12 @@ namespace ts {
|
||||
objectAssignmentInitializer?: Expression;
|
||||
}
|
||||
|
||||
// @kind(SyntaxKind.SpreadElementExpression)
|
||||
export interface SpreadElement extends ObjectLiteralElement {
|
||||
dotDotDotToken: Node;
|
||||
target: Expression;
|
||||
}
|
||||
|
||||
// SyntaxKind.VariableDeclaration
|
||||
// SyntaxKind.Parameter
|
||||
// SyntaxKind.BindingElement
|
||||
@@ -2275,7 +2288,7 @@ namespace ts {
|
||||
instantiations?: Map<Type>; // Instantiations of generic type alias (undefined if non-generic)
|
||||
mapper?: TypeMapper; // Type mapper for instantiation alias
|
||||
referenced?: boolean; // True if alias symbol has been referenced as a value
|
||||
containingType?: UnionOrIntersectionType; // Containing union or intersection type for synthetic property
|
||||
containingType?: TypeOperatorType; // Containing union or intersection type for synthetic property
|
||||
hasCommonType?: boolean; // True if constituents of synthetic property all have same type
|
||||
isDiscriminantProperty?: boolean; // True if discriminant synthetic property
|
||||
resolvedExports?: SymbolTable; // Resolved exports of module
|
||||
@@ -2381,6 +2394,8 @@ namespace ts {
|
||||
ContainsAnyFunctionType = 1 << 27, // Type is or contains object literal type
|
||||
ThisType = 1 << 28, // This type
|
||||
ObjectLiteralPatternWithComputedProperties = 1 << 29, // Object literal type implied by binding pattern has computed properties
|
||||
Spread = 1 << 30, // Spread types
|
||||
// TODO: Move some types out to make room for Spread.
|
||||
|
||||
/* @internal */
|
||||
Nullable = Undefined | Null,
|
||||
@@ -2398,12 +2413,12 @@ namespace ts {
|
||||
EnumLike = Enum | EnumLiteral,
|
||||
ObjectType = Class | Interface | Reference | Tuple | Anonymous,
|
||||
UnionOrIntersection = Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection,
|
||||
StructuredType = ObjectType | Union | Intersection | Spread,
|
||||
StructuredOrTypeParameter = StructuredType | TypeParameter,
|
||||
|
||||
// 'Narrowable' types are types where narrowing actually narrows.
|
||||
// This *should* be every type other than null, undefined, void, and never
|
||||
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | BooleanLike | ESSymbol,
|
||||
Narrowable = Any | StructuredType | TypeParameter | StringLike | NumberLike | BooleanLike | ESSymbol | Spread,
|
||||
NotUnionOrUnit = Any | String | Number | ESSymbol | ObjectType,
|
||||
/* @internal */
|
||||
RequiresWidening = ContainsWideningType | ContainsObjectLiteral,
|
||||
@@ -2486,7 +2501,7 @@ namespace ts {
|
||||
instantiations: Map<TypeReference>; // Generic instantiation cache
|
||||
}
|
||||
|
||||
export interface UnionOrIntersectionType extends Type {
|
||||
export interface TypeOperatorType extends Type {
|
||||
types: Type[]; // Constituent types
|
||||
/* @internal */
|
||||
resolvedProperties: SymbolTable; // Cache of resolved properties
|
||||
@@ -2494,9 +2509,19 @@ namespace ts {
|
||||
couldContainTypeParameters: boolean;
|
||||
}
|
||||
|
||||
export interface UnionType extends UnionOrIntersectionType { }
|
||||
export interface UnionType extends TypeOperatorType { }
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType { }
|
||||
export interface IntersectionType extends TypeOperatorType { }
|
||||
|
||||
/* @internal */
|
||||
export interface SpreadType extends TypeOperatorType {
|
||||
types: SpreadElementType[]; // Constituent types
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
export interface SpreadElementType extends ResolvedType {
|
||||
isDeclaredProperty: boolean | undefined;
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
// An instantiated anonymous type has a target and a mapper
|
||||
@@ -2506,8 +2531,8 @@ namespace ts {
|
||||
}
|
||||
|
||||
/* @internal */
|
||||
// Resolved object, union, or intersection type
|
||||
export interface ResolvedType extends ObjectType, UnionOrIntersectionType {
|
||||
// Resolved object, spread, union, or intersection type
|
||||
export interface ResolvedType extends ObjectType, TypeOperatorType {
|
||||
members: SymbolTable; // Properties by name
|
||||
properties: Symbol[]; // Properties
|
||||
callSignatures: Signature[]; // Call signatures of type
|
||||
@@ -3096,29 +3121,31 @@ namespace ts {
|
||||
ContainsTypeScript = 1 << 1,
|
||||
Jsx = 1 << 2,
|
||||
ContainsJsx = 1 << 3,
|
||||
ES7 = 1 << 4,
|
||||
ContainsES7 = 1 << 5,
|
||||
ES6 = 1 << 6,
|
||||
ContainsES6 = 1 << 7,
|
||||
DestructuringAssignment = 1 << 8,
|
||||
Generator = 1 << 9,
|
||||
ContainsGenerator = 1 << 10,
|
||||
Experimental = 1 << 4,
|
||||
ContainsExperimental = 1 << 5,
|
||||
ES7 = 1 << 6,
|
||||
ContainsES7 = 1 << 7,
|
||||
ES6 = 1 << 8,
|
||||
ContainsES6 = 1 << 9,
|
||||
DestructuringAssignment = 1 << 10,
|
||||
Generator = 1 << 11,
|
||||
ContainsGenerator = 1 << 12,
|
||||
|
||||
// Markers
|
||||
// - Flags used to indicate that a subtree contains a specific transformation.
|
||||
ContainsDecorators = 1 << 11,
|
||||
ContainsPropertyInitializer = 1 << 12,
|
||||
ContainsLexicalThis = 1 << 13,
|
||||
ContainsCapturedLexicalThis = 1 << 14,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 15,
|
||||
ContainsDefaultValueAssignments = 1 << 16,
|
||||
ContainsParameterPropertyAssignments = 1 << 17,
|
||||
ContainsSpreadElementExpression = 1 << 18,
|
||||
ContainsComputedPropertyName = 1 << 19,
|
||||
ContainsBlockScopedBinding = 1 << 20,
|
||||
ContainsBindingPattern = 1 << 21,
|
||||
ContainsYield = 1 << 22,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 23,
|
||||
ContainsDecorators = 1 << 13,
|
||||
ContainsPropertyInitializer = 1 << 14,
|
||||
ContainsLexicalThis = 1 << 15,
|
||||
ContainsCapturedLexicalThis = 1 << 16,
|
||||
ContainsLexicalThisInComputedPropertyName = 1 << 17,
|
||||
ContainsDefaultValueAssignments = 1 << 18,
|
||||
ContainsParameterPropertyAssignments = 1 << 19,
|
||||
ContainsSpreadElementExpression = 1 << 20,
|
||||
ContainsComputedPropertyName = 1 << 21,
|
||||
ContainsBlockScopedBinding = 1 << 22,
|
||||
ContainsBindingPattern = 1 << 23,
|
||||
ContainsYield = 1 << 24,
|
||||
ContainsHoistedDeclarationOrCompletion = 1 << 25,
|
||||
|
||||
HasComputedFlags = 1 << 29, // Transform flags have been computed.
|
||||
|
||||
@@ -3126,6 +3153,7 @@ namespace ts {
|
||||
// - Bitmasks that are used to assert facts about the syntax of a node and its subtree.
|
||||
AssertTypeScript = TypeScript | ContainsTypeScript,
|
||||
AssertJsx = Jsx | ContainsJsx,
|
||||
AssertExperimental = Experimental | ContainsExperimental,
|
||||
AssertES7 = ES7 | ContainsES7,
|
||||
AssertES6 = ES6 | ContainsES6,
|
||||
AssertGenerator = Generator | ContainsGenerator,
|
||||
@@ -3133,7 +3161,7 @@ namespace ts {
|
||||
// Scope Exclusions
|
||||
// - Bitmasks that exclude flags from propagating out of a specific context
|
||||
// into the subtree flags of their container.
|
||||
NodeExcludes = TypeScript | Jsx | ES7 | ES6 | DestructuringAssignment | Generator | HasComputedFlags,
|
||||
NodeExcludes = TypeScript | Jsx | Experimental | ES7 | ES6 | DestructuringAssignment | Generator | HasComputedFlags,
|
||||
ArrowFunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
FunctionExcludes = NodeExcludes | ContainsDecorators | ContainsDefaultValueAssignments | ContainsCapturedLexicalThis | ContainsLexicalThis | ContainsParameterPropertyAssignments | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
ConstructorExcludes = NodeExcludes | ContainsDefaultValueAssignments | ContainsLexicalThis | ContainsCapturedLexicalThis | ContainsBlockScopedBinding | ContainsYield | ContainsHoistedDeclarationOrCompletion,
|
||||
|
||||
@@ -3740,6 +3740,7 @@ namespace ts {
|
||||
const kind = node.kind;
|
||||
return kind === SyntaxKind.PropertyAssignment
|
||||
|| kind === SyntaxKind.ShorthandPropertyAssignment
|
||||
|| kind === SyntaxKind.SpreadElement
|
||||
|| kind === SyntaxKind.MethodDeclaration
|
||||
|| kind === SyntaxKind.GetAccessor
|
||||
|| kind === SyntaxKind.SetAccessor
|
||||
|
||||
@@ -1463,7 +1463,7 @@ namespace Harness {
|
||||
}
|
||||
|
||||
if (typesError && symbolsError) {
|
||||
throw new Error(typesError.message + ts.sys.newLine + symbolsError.message);
|
||||
throw new Error(typesError.message + Harness.IO.newLine() + symbolsError.message);
|
||||
}
|
||||
|
||||
if (typesError) {
|
||||
|
||||
@@ -458,7 +458,7 @@ namespace ts.FindAllReferences {
|
||||
return [localParentType.symbol];
|
||||
}
|
||||
else if (localParentType.flags & TypeFlags.UnionOrIntersection) {
|
||||
return getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>localParentType);
|
||||
return getSymbolsForClassAndInterfaceComponents(<TypeOperatorType>localParentType);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -630,13 +630,13 @@ namespace ts.FindAllReferences {
|
||||
}
|
||||
}
|
||||
|
||||
function getSymbolsForClassAndInterfaceComponents(type: UnionOrIntersectionType, result: Symbol[] = []): Symbol[] {
|
||||
function getSymbolsForClassAndInterfaceComponents(type: TypeOperatorType, result: Symbol[] = []): Symbol[] {
|
||||
for (const componentType of type.types) {
|
||||
if (componentType.symbol && componentType.symbol.getFlags() & (SymbolFlags.Class | SymbolFlags.Interface)) {
|
||||
result.push(componentType.symbol);
|
||||
}
|
||||
if (componentType.getFlags() & TypeFlags.UnionOrIntersection) {
|
||||
getSymbolsForClassAndInterfaceComponents(<UnionOrIntersectionType>componentType, result);
|
||||
getSymbolsForClassAndInterfaceComponents(<TypeOperatorType>componentType, result);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
|
||||
Reference in New Issue
Block a user