Merge branch 'master' of https://github.com/microsoft/TypeScript into bug/38295

This commit is contained in:
Alexander T
2020-05-20 20:13:50 +03:00
135 changed files with 4676 additions and 1036 deletions
+8 -2
View File
@@ -985,7 +985,7 @@ namespace ts {
return initFlowNode({ flags: FlowFlags.SwitchClause, antecedent, switchStatement, clauseStart, clauseEnd });
}
function createFlowMutation(flags: FlowFlags, antecedent: FlowNode, node: Node): FlowNode {
function createFlowMutation(flags: FlowFlags, antecedent: FlowNode, node: Expression | VariableDeclaration | ArrayBindingElement): FlowNode {
setFlowNodeReferenced(antecedent);
const result = initFlowNode({ flags, antecedent, node });
if (currentExceptionTarget) {
@@ -1341,7 +1341,7 @@ namespace ts {
// is potentially an assertion and is therefore included in the control flow.
if (node.expression.kind === SyntaxKind.CallExpression) {
const call = <CallExpression>node.expression;
if (isDottedName(call.expression)) {
if (isDottedName(call.expression) && call.expression.kind !== SyntaxKind.SuperKeyword) {
currentFlow = createFlowCall(currentFlow, call);
}
}
@@ -1747,6 +1747,9 @@ namespace ts {
}
else {
bindEachChild(node);
if (node.expression.kind === SyntaxKind.SuperKeyword) {
currentFlow = createFlowCall(currentFlow, node);
}
}
}
if (node.expression.kind === SyntaxKind.PropertyAccessExpression) {
@@ -2464,6 +2467,9 @@ namespace ts {
node.flowNode = currentFlow;
}
return checkStrictModeIdentifier(<Identifier>node);
case SyntaxKind.SuperKeyword:
node.flowNode = currentFlow;
break;
case SyntaxKind.PrivateIdentifier:
return checkPrivateIdentifier(node as PrivateIdentifier);
case SyntaxKind.PropertyAccessExpression:
+266 -106
View File
@@ -911,6 +911,7 @@ namespace ts {
const sharedFlowNodes: FlowNode[] = [];
const sharedFlowTypes: FlowType[] = [];
const flowNodeReachable: (boolean | undefined)[] = [];
const flowNodePostSuper: (boolean | undefined)[] = [];
const potentialThisCollisions: Node[] = [];
const potentialNewTargetCollisions: Node[] = [];
const potentialWeakMapCollisions: Node[] = [];
@@ -4563,17 +4564,32 @@ namespace ts {
const tupleConstituentNodes = mapToTypeNodes(typeArguments.slice(0, arity), context);
const hasRestElement = (<TupleType>type.target).hasRestElement;
if (tupleConstituentNodes) {
for (let i = (<TupleType>type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) {
tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
createOptionalTypeNode(tupleConstituentNodes[i]);
if ((type.target as TupleType).labeledElementDeclarations) {
for (let i = 0; i < tupleConstituentNodes.length; i++) {
const isOptionalOrRest = i >= (<TupleType>type.target).minLength;
const isRest = isOptionalOrRest && hasRestElement && i === arity - 1;
const isOptional = isOptionalOrRest && !isRest;
tupleConstituentNodes[i] = createNamedTupleMember(
isRest ? createToken(SyntaxKind.DotDotDotToken) : undefined,
createIdentifier(unescapeLeadingUnderscores(getTupleElementLabel((type.target as TupleType).labeledElementDeclarations![i]))),
isOptional ? createToken(SyntaxKind.QuestionToken) : undefined,
isRest ? createArrayTypeNode(tupleConstituentNodes[i]) : tupleConstituentNodes[i]
);
}
}
const tupleTypeNode = createTupleTypeNode(tupleConstituentNodes);
else {
for (let i = (<TupleType>type.target).minLength; i < Math.min(arity, tupleConstituentNodes.length); i++) {
tupleConstituentNodes[i] = hasRestElement && i === arity - 1 ?
createRestTypeNode(createArrayTypeNode(tupleConstituentNodes[i])) :
createOptionalTypeNode(tupleConstituentNodes[i]);
}
}
const tupleTypeNode = setEmitFlags(createTupleTypeNode(tupleConstituentNodes), EmitFlags.SingleLine);
return (<TupleType>type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
}
}
if (context.encounteredError || (context.flags & NodeBuilderFlags.AllowEmptyTuple)) {
const tupleTypeNode = createTupleTypeNode([]);
const tupleTypeNode = setEmitFlags(createTupleTypeNode([]), EmitFlags.SingleLine);
return (<TupleType>type.target).readonly ? createTypeOperatorNode(SyntaxKind.ReadonlyKeyword, tupleTypeNode) : tupleTypeNode;
}
context.encounteredError = true;
@@ -4907,7 +4923,7 @@ namespace ts {
typeParameters = signature.typeParameters && signature.typeParameters.map(parameter => typeParameterToDeclaration(parameter, context));
}
const parameters = getExpandedParameters(signature).map(parameter => symbolToParameterDeclaration(parameter, context, kind === SyntaxKind.Constructor, privateSymbolVisitor, bundledImports));
const parameters = getExpandedParameters(signature, /*skipUnionExpanding*/ true)[0].map(parameter => symbolToParameterDeclaration(parameter, context, kind === SyntaxKind.Constructor, privateSymbolVisitor, bundledImports));
if (signature.thisParameter) {
const thisParameter = symbolToParameterDeclaration(signature.thisParameter, context);
parameters.unshift(thisParameter);
@@ -5555,6 +5571,7 @@ namespace ts {
cancellationToken.throwIfCancellationRequested();
}
let hadError = false;
const file = getSourceFileOfNode(existing);
const transformed = visitNode(existing, visitExistingNodeTreeSymbols);
if (hadError) {
return undefined;
@@ -5683,6 +5700,10 @@ namespace ts {
}
}
if (file && isTupleTypeNode(node) && (getLineAndCharacterOfPosition(file, node.pos).line === getLineAndCharacterOfPosition(file, node.end).line)) {
setEmitFlags(node, EmitFlags.SingleLine);
}
return visitEachChild(node, visitExistingNodeTreeSymbols, nullTransformationContext);
function getEffectiveDotDotDotForParameter(p: ParameterDeclaration) {
@@ -5949,6 +5970,7 @@ namespace ts {
}
}
// Synthesize declarations for a symbol - might be an Interface, a Class, a Namespace, a Type, a Variable (const, let, or var), an Alias
// or a merge of some number of those.
// An interesting challenge is ensuring that when classes merge with namespaces and interfaces, is keeping
@@ -6317,7 +6339,10 @@ namespace ts {
const baseTypes = getBaseTypes(classType);
const implementsTypes = getImplementsTypes(classType);
const staticType = getTypeOfSymbol(symbol);
const staticBaseType = getBaseConstructorTypeOfClass(staticType as InterfaceType);
const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
const staticBaseType = isClass
? getBaseConstructorTypeOfClass(staticType as InterfaceType)
: anyType;
const heritageClauses = [
...!length(baseTypes) ? [] : [createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
...!length(implementsTypes) ? [] : [createHeritageClause(SyntaxKind.ImplementsKeyword, map(implementsTypes, b => serializeBaseType(b, staticBaseType, localName)))]
@@ -6353,7 +6378,17 @@ namespace ts {
const staticMembers = flatMap(
filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)),
p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType));
const constructors = serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
// When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether
// the value is ever initialized with a class or function-like value. For cases where `X` could never be
// created via `new`, we will inject a `private constructor()` declaration to indicate it is not createable.
const isNonConstructableClassLikeInJsFile =
!isClass &&
!!symbol.valueDeclaration &&
isInJSFile(symbol.valueDeclaration) &&
!some(getSignaturesOfType(staticType, SignatureKind.Construct));
const constructors = isNonConstructableClassLikeInJsFile ?
[createConstructor(/*decorators*/ undefined, createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] :
serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
for (const c of constructors) {
// A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration
// `signatureToSignatureDeclarationHelper` appends them regardless, so for now we delete them here
@@ -6929,7 +6964,7 @@ namespace ts {
function getTypeAliasForTypeLiteral(type: Type): Symbol | undefined {
if (type.symbol && type.symbol.flags & SymbolFlags.TypeLiteral) {
const node = findAncestor(type.symbol.declarations[0].parent, n => n.kind !== SyntaxKind.ParenthesizedType)!;
const node = walkUpParenthesizedTypes(type.symbol.declarations[0].parent);
if (node.kind === SyntaxKind.TypeAliasDeclaration) {
return getSymbolOfNode(node);
}
@@ -7117,6 +7152,7 @@ namespace ts {
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.ParenthesizedType:
case SyntaxKind.NamedTupleMember:
return isDeclarationVisible(node.parent);
// Default binding, import specifier and namespace import is visible
@@ -9520,27 +9556,36 @@ namespace ts {
return result;
}
function getExpandedParameters(sig: Signature): readonly Symbol[] {
function getExpandedParameters(sig: Signature, skipUnionExpanding?: boolean): readonly (readonly Symbol[])[] {
if (signatureHasRestParameter(sig)) {
const restIndex = sig.parameters.length - 1;
const restParameter = sig.parameters[restIndex];
const restType = getTypeOfSymbol(restParameter);
const restType = getTypeOfSymbol(sig.parameters[restIndex]);
if (isTupleType(restType)) {
const elementTypes = getTypeArguments(restType);
const minLength = restType.target.minLength;
const tupleRestIndex = restType.target.hasRestElement ? elementTypes.length - 1 : -1;
const restParams = map(elementTypes, (t, i) => {
const name = getParameterNameAtPosition(sig, restIndex + i);
const checkFlags = i === tupleRestIndex ? CheckFlags.RestParameter :
i >= minLength ? CheckFlags.OptionalParameter : 0;
const symbol = createSymbol(SymbolFlags.FunctionScopedVariable, name, checkFlags);
symbol.type = i === tupleRestIndex ? createArrayType(t) : t;
return symbol;
});
return concatenate(sig.parameters.slice(0, restIndex), restParams);
return [expandSignatureParametersWithTupleMembers(restType, restIndex)];
}
else if (!skipUnionExpanding && restType.flags & TypeFlags.Union && every((restType as UnionType).types, isTupleType)) {
return map((restType as UnionType).types, t => expandSignatureParametersWithTupleMembers(t as TupleTypeReference, restIndex));
}
}
return sig.parameters;
return [sig.parameters];
function expandSignatureParametersWithTupleMembers(restType: TupleTypeReference, restIndex: number) {
const elementTypes = getTypeArguments(restType);
const minLength = restType.target.minLength;
const tupleRestIndex = restType.target.hasRestElement ? elementTypes.length - 1 : -1;
const associatedNames = restType.target.labeledElementDeclarations;
const restParams = map(elementTypes, (t, i) => {
// Lookup the label from the individual tuple passed in before falling back to the signature `rest` parameter name
const tupleLabelName = !!associatedNames && getTupleElementLabel(associatedNames[i]);
const name = tupleLabelName || getParameterNameAtPosition(sig, restIndex + i);
const checkFlags = i === tupleRestIndex ? CheckFlags.RestParameter :
i >= minLength ? CheckFlags.OptionalParameter : 0;
const symbol = createSymbol(SymbolFlags.FunctionScopedVariable, name, checkFlags);
symbol.type = i === tupleRestIndex ? createArrayType(t) : t;
return symbol;
});
return concatenate(sig.parameters.slice(0, restIndex), restParams);
}
}
function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
@@ -11583,7 +11628,7 @@ namespace ts {
const typeArguments = !node ? emptyArray :
node.kind === SyntaxKind.TypeReference ? concatenate(type.target.outerTypeParameters, getEffectiveTypeArguments(node, type.target.localTypeParameters!)) :
node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] :
map(node.elementTypes, getTypeFromTypeNode);
map(node.elements, getTypeFromTypeNode);
if (popTypeResolution()) {
type.resolvedTypeArguments = type.mapper ? instantiateTypes(typeArguments, type.mapper) : typeArguments;
}
@@ -11789,11 +11834,11 @@ namespace ts {
}
function isUnaryTupleTypeNode(node: TypeNode) {
return node.kind === SyntaxKind.TupleType && (<TupleTypeNode>node).elementTypes.length === 1;
return node.kind === SyntaxKind.TupleType && (<TupleTypeNode>node).elements.length === 1;
}
function getImpliedConstraint(type: Type, checkNode: TypeNode, extendsNode: TypeNode): Type | undefined {
return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (<TupleTypeNode>checkNode).elementTypes[0], (<TupleTypeNode>extendsNode).elementTypes[0]) :
return isUnaryTupleTypeNode(checkNode) && isUnaryTupleTypeNode(extendsNode) ? getImpliedConstraint(type, (<TupleTypeNode>checkNode).elements[0], (<TupleTypeNode>extendsNode).elements[0]) :
getActualTypeVariable(getTypeFromTypeNode(checkNode)) === type ? getTypeFromTypeNode(extendsNode) :
undefined;
}
@@ -12089,15 +12134,24 @@ namespace ts {
return createTypeFromGenericGlobalType(readonly ? globalReadonlyArrayType : globalArrayType, [elementType]);
}
function isTupleRestElement(node: TypeNode) {
return node.kind === SyntaxKind.RestType || (node.kind === SyntaxKind.NamedTupleMember && !!(node as NamedTupleMember).dotDotDotToken);
}
function isTupleOptionalElement(node: TypeNode) {
return node.kind === SyntaxKind.OptionalType || (node.kind === SyntaxKind.NamedTupleMember && !!(node as NamedTupleMember).questionToken);
}
function getArrayOrTupleTargetType(node: ArrayTypeNode | TupleTypeNode): GenericType {
const readonly = isReadonlyTypeOperator(node.parent);
if (node.kind === SyntaxKind.ArrayType || node.elementTypes.length === 1 && node.elementTypes[0].kind === SyntaxKind.RestType) {
if (node.kind === SyntaxKind.ArrayType || node.elements.length === 1 && isTupleRestElement(node.elements[0])) {
return readonly ? globalReadonlyArrayType : globalArrayType;
}
const lastElement = lastOrUndefined(node.elementTypes);
const restElement = lastElement && lastElement.kind === SyntaxKind.RestType ? lastElement : undefined;
const minLength = findLastIndex(node.elementTypes, n => n.kind !== SyntaxKind.OptionalType && n !== restElement) + 1;
return getTupleTypeOfArity(node.elementTypes.length, minLength, !!restElement, readonly, /*associatedNames*/ undefined);
const lastElement = lastOrUndefined(node.elements);
const restElement = lastElement && isTupleRestElement(lastElement) ? lastElement : undefined;
const minLength = findLastIndex(node.elements, n => !isTupleOptionalElement(n) && n !== restElement) + 1;
const missingName = some(node.elements, e => e.kind !== SyntaxKind.NamedTupleMember);
return getTupleTypeOfArity(node.elements.length, minLength, !!restElement, readonly, /*associatedNames*/ missingName ? undefined : node.elements as readonly NamedTupleMember[]);
}
// Return true if the given type reference node is directly aliased or if it needs to be deferred
@@ -12105,7 +12159,7 @@ namespace ts {
function isDeferredTypeReferenceNode(node: TypeReferenceNode | ArrayTypeNode | TupleTypeNode, hasDefaultTypeArguments?: boolean) {
return !!getAliasSymbolForTypeNode(node) || isResolvedByTypeAlias(node) && (
node.kind === SyntaxKind.ArrayType ? mayResolveTypeAlias(node.elementType) :
node.kind === SyntaxKind.TupleType ? some(node.elementTypes, mayResolveTypeAlias) :
node.kind === SyntaxKind.TupleType ? some(node.elements, mayResolveTypeAlias) :
hasDefaultTypeArguments || some(node.typeArguments, mayResolveTypeAlias));
}
@@ -12116,6 +12170,7 @@ namespace ts {
const parent = node.parent;
switch (parent.kind) {
case SyntaxKind.ParenthesizedType:
case SyntaxKind.NamedTupleMember:
case SyntaxKind.TypeReference:
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
@@ -12143,11 +12198,12 @@ namespace ts {
return (<TypeOperatorNode>node).operator !== SyntaxKind.UniqueKeyword && mayResolveTypeAlias((<TypeOperatorNode>node).type);
case SyntaxKind.ParenthesizedType:
case SyntaxKind.OptionalType:
case SyntaxKind.NamedTupleMember:
case SyntaxKind.JSDocOptionalType:
case SyntaxKind.JSDocNullableType:
case SyntaxKind.JSDocNonNullableType:
case SyntaxKind.JSDocTypeExpression:
return mayResolveTypeAlias((<ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode>node).type);
return mayResolveTypeAlias((<ParenthesizedTypeNode | OptionalTypeNode | JSDocTypeReferencingNode | NamedTupleMember>node).type);
case SyntaxKind.RestType:
return (<RestTypeNode>node).type.kind !== SyntaxKind.ArrayType || mayResolveTypeAlias((<ArrayTypeNode>(<RestTypeNode>node).type).elementType);
case SyntaxKind.UnionType:
@@ -12170,11 +12226,11 @@ namespace ts {
links.resolvedType = emptyObjectType;
}
else if (isDeferredTypeReferenceNode(node)) {
links.resolvedType = node.kind === SyntaxKind.TupleType && node.elementTypes.length === 0 ? target :
links.resolvedType = node.kind === SyntaxKind.TupleType && node.elements.length === 0 ? target :
createDeferredTypeReference(target, node, /*mapper*/ undefined);
}
else {
const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : map(node.elementTypes, getTypeFromTypeNode);
const elementTypes = node.kind === SyntaxKind.ArrayType ? [getTypeFromTypeNode(node.elementType)] : map(node.elements, getTypeFromTypeNode);
links.resolvedType = createTypeReference(target, elementTypes);
}
}
@@ -12192,7 +12248,7 @@ namespace ts {
//
// Note that the generic type created by this function has no symbol associated with it. The same
// is true for each of the synthesized type parameters.
function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames: __String[] | undefined): TupleType {
function createTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations: readonly (NamedTupleMember | ParameterDeclaration)[] | undefined): TupleType {
let typeParameters: TypeParameter[] | undefined;
const properties: Symbol[] = [];
const maxLength = hasRestElement ? arity - 1 : arity;
@@ -12203,6 +12259,7 @@ namespace ts {
if (i < maxLength) {
const property = createSymbol(SymbolFlags.Property | (i >= minLength ? SymbolFlags.Optional : 0),
"" + i as __String, readonly ? CheckFlags.Readonly : 0);
property.tupleLabelDeclaration = namedMemberDeclarations?.[i];
property.type = typeParameter;
properties.push(property);
}
@@ -12232,25 +12289,25 @@ namespace ts {
type.minLength = minLength;
type.hasRestElement = hasRestElement;
type.readonly = readonly;
type.associatedNames = associatedNames;
type.labeledElementDeclarations = namedMemberDeclarations;
return type;
}
function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, associatedNames?: __String[]): GenericType {
const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (associatedNames && associatedNames.length ? "," + associatedNames.join(",") : "");
function getTupleTypeOfArity(arity: number, minLength: number, hasRestElement: boolean, readonly: boolean, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]): GenericType {
const key = arity + (hasRestElement ? "+" : ",") + minLength + (readonly ? "R" : "") + (namedMemberDeclarations && namedMemberDeclarations.length ? "," + map(namedMemberDeclarations, getNodeId).join(",") : "");
let type = tupleTypes.get(key);
if (!type) {
tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, associatedNames));
tupleTypes.set(key, type = createTupleTypeOfArity(arity, minLength, hasRestElement, readonly, namedMemberDeclarations));
}
return type;
}
function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, associatedNames?: __String[]) {
function createTupleType(elementTypes: readonly Type[], minLength = elementTypes.length, hasRestElement = false, readonly = false, namedMemberDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[]) {
const arity = elementTypes.length;
if (arity === 1 && hasRestElement) {
return createArrayType(elementTypes[0], readonly);
}
const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, associatedNames);
const tupleType = getTupleTypeOfArity(arity, minLength, arity > 0 && hasRestElement, readonly, namedMemberDeclarations);
return elementTypes.length ? createTypeReference(tupleType, elementTypes) : tupleType;
}
@@ -12265,7 +12322,7 @@ namespace ts {
Math.max(0, tuple.minLength - index),
tuple.hasRestElement,
tuple.readonly,
tuple.associatedNames && tuple.associatedNames.slice(index),
tuple.labeledElementDeclarations && tuple.labeledElementDeclarations.slice(index),
);
}
@@ -13844,6 +13901,21 @@ namespace ts {
return links.resolvedType;
}
function getTypeFromNamedTupleTypeNode(node: NamedTupleMember): Type {
const links = getNodeLinks(node);
if (!links.resolvedType) {
let type = getTypeFromTypeNode(node.type);
if (node.dotDotDotToken) {
type = getElementTypeOfArrayType(type) || errorType;
}
if (node.questionToken && strictNullChecks) {
type = getOptionalType(type);
}
links.resolvedType = type;
}
return links.resolvedType;
}
function getTypeFromTypeNode(node: TypeNode): Type {
return getConditionalFlowTypeOfType(getTypeFromTypeNodeWorker(node), node);
}
@@ -13902,10 +13974,12 @@ namespace ts {
return getTypeFromJSDocNullableTypeNode(<JSDocNullableType>node);
case SyntaxKind.JSDocOptionalType:
return addOptionality(getTypeFromTypeNode((node as JSDocOptionalType).type));
case SyntaxKind.NamedTupleMember:
return getTypeFromNamedTupleTypeNode(node as NamedTupleMember);
case SyntaxKind.ParenthesizedType:
case SyntaxKind.JSDocNonNullableType:
case SyntaxKind.JSDocTypeExpression:
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression>node).type);
return getTypeFromTypeNode((<ParenthesizedTypeNode | JSDocTypeReferencingNode | JSDocTypeExpression | NamedTupleMember>node).type);
case SyntaxKind.RestType:
return getElementTypeOfArrayType(getTypeFromTypeNode((<RestTypeNode>node).type)) || errorType;
case SyntaxKind.JSDocVariadicType:
@@ -14264,7 +14338,7 @@ namespace ts {
minLength;
const newReadonly = getModifiedReadonlyState(tupleType.target.readonly, modifiers);
return contains(elementTypes, errorType) ? errorType :
createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.associatedNames);
createTupleType(elementTypes, newMinLength, tupleType.target.hasRestElement, newReadonly, tupleType.target.labeledElementDeclarations);
}
function instantiateMappedTypeTemplate(type: MappedType, key: Type, isOptional: boolean, mapper: TypeMapper) {
@@ -18521,7 +18595,7 @@ namespace ts {
const elementTypes = map(getTypeArguments(source), t => inferReverseMappedType(t, target, constraint));
const minLength = getMappedTypeModifiers(target) & MappedTypeModifiers.IncludeOptional ?
getTypeReferenceArity(source) - (source.target.hasRestElement ? 1 : 0) : source.target.minLength;
return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.associatedNames);
return createTupleType(elementTypes, minLength, source.target.hasRestElement, source.target.readonly, source.target.labeledElementDeclarations);
}
// For all other object types we infer a new object type where the reverse mapping has been
// applied to the type of each property.
@@ -20134,7 +20208,7 @@ namespace ts {
noCacheCheck = false;
}
if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation)) {
flow = (<FlowAssignment | FlowCondition | FlowArrayMutation | PreFinallyFlow>flow).antecedent;
flow = (<FlowAssignment | FlowCondition | FlowArrayMutation>flow).antecedent;
}
else if (flags & FlowFlags.Call) {
const signature = getEffectsSignature((<FlowCall>flow).node);
@@ -20184,6 +20258,51 @@ namespace ts {
}
}
// Return true if the given flow node is preceded by a 'super(...)' call in every possible code path
// leading to the node.
function isPostSuperFlowNode(flow: FlowNode, noCacheCheck: boolean): boolean {
while (true) {
const flags = flow.flags;
if (flags & FlowFlags.Shared) {
if (!noCacheCheck) {
const id = getFlowNodeId(flow);
const postSuper = flowNodePostSuper[id];
return postSuper !== undefined ? postSuper : (flowNodePostSuper[id] = isPostSuperFlowNode(flow, /*noCacheCheck*/ true));
}
noCacheCheck = false;
}
if (flags & (FlowFlags.Assignment | FlowFlags.Condition | FlowFlags.ArrayMutation | FlowFlags.SwitchClause)) {
flow = (<FlowAssignment | FlowCondition | FlowArrayMutation | FlowSwitchClause>flow).antecedent;
}
else if (flags & FlowFlags.Call) {
if ((<FlowCall>flow).node.expression.kind === SyntaxKind.SuperKeyword) {
return true;
}
flow = (<FlowCall>flow).antecedent;
}
else if (flags & FlowFlags.BranchLabel) {
// A branching point is post-super if every branch is post-super.
return every((<FlowLabel>flow).antecedents, f => isPostSuperFlowNode(f, /*noCacheCheck*/ false));
}
else if (flags & FlowFlags.LoopLabel) {
// A loop is post-super if the control flow path that leads to the top is post-super.
flow = (<FlowLabel>flow).antecedents![0];
}
else if (flags & FlowFlags.ReduceLabel) {
const target = (<FlowReduceLabel>flow).target;
const saveAntecedents = target.antecedents;
target.antecedents = (<FlowReduceLabel>flow).antecedents;
const result = isPostSuperFlowNode((<FlowReduceLabel>flow).antecedent, /*noCacheCheck*/ false);
target.antecedents = saveAntecedents;
return result;
}
else {
// Unreachable nodes are considered post-super to silence errors
return !!(flags & FlowFlags.Unreachable);
}
}
}
function getFlowTypeOfReference(reference: Node, declaredType: Type, initialType = declaredType, flowContainer?: Node, couldBeUninitialized?: boolean) {
let key: string | undefined;
let keySet = false;
@@ -21583,31 +21702,10 @@ namespace ts {
}
}
function findFirstSuperCall(n: Node): SuperCall | undefined {
if (isSuperCall(n)) {
return n;
}
else if (isFunctionLike(n)) {
return undefined;
}
return forEachChild(n, findFirstSuperCall);
}
/**
* Return a cached result if super-statement is already found.
* Otherwise, find a super statement in a given constructor function and cache the result in the node-links of the constructor
*
* @param constructor constructor-function to look for super statement
*/
function getSuperCallInConstructor(constructor: ConstructorDeclaration): SuperCall | undefined {
const links = getNodeLinks(constructor);
// Only trying to find super-call if we haven't yet tried to find one. Once we try, we will record the result
if (links.hasSuperCall === undefined) {
links.superCall = findFirstSuperCall(constructor.body!);
links.hasSuperCall = links.superCall ? true : false;
}
return links.superCall!;
function findFirstSuperCall(node: Node): SuperCall | undefined {
return isSuperCall(node) ? node :
isFunctionLike(node) ? undefined :
forEachChild(node, findFirstSuperCall);
}
/**
@@ -21630,17 +21728,7 @@ namespace ts {
// If a containing class does not have extends clause or the class extends null
// skip checking whether super statement is called before "this" accessing.
if (baseTypeNode && !classDeclarationExtendsNull(containingClassDecl)) {
const superCall = getSuperCallInConstructor(<ConstructorDeclaration>container);
// We should give an error in the following cases:
// - No super-call
// - "this" is accessing before super-call.
// i.e super(this)
// this.x; super();
// We want to make sure that super-call is done before accessing "this" so that
// "this" is not accessed as a parameter of the super-call.
if (!superCall || superCall.end > node.pos) {
// In ES6, super inside constructor of class-declaration has to precede "this" accessing
if (node.flowNode && !isPostSuperFlowNode(node.flowNode, /*noCacheCheck*/ false)) {
error(node, diagnosticMessage);
}
}
@@ -21865,7 +21953,8 @@ namespace ts {
function checkSuperExpression(node: Node): Type {
const isCallExpression = node.parent.kind === SyntaxKind.CallExpression && (<CallExpression>node.parent).expression === node;
let container = getSuperContainer(node, /*stopOnFunctions*/ true);
const immediateContainer = getSuperContainer(node, /*stopOnFunctions*/ true);
let container = immediateContainer;
let needToCaptureLexicalThis = false;
// adjust the container reference in case if super is used inside arrow functions with arbitrarily deep nesting
@@ -21901,7 +21990,7 @@ namespace ts {
return errorType;
}
if (!isCallExpression && container.kind === SyntaxKind.Constructor) {
if (!isCallExpression && immediateContainer.kind === SyntaxKind.Constructor) {
checkThisBeforeSuper(node, container, Diagnostics.super_must_be_called_before_accessing_a_property_of_super_in_the_constructor_of_a_derived_class);
}
@@ -22439,6 +22528,10 @@ namespace ts {
}
}
function isCircularMappedProperty(symbol: Symbol) {
return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(<MappedSymbol>symbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0);
}
function getTypeOfPropertyOfContextualType(type: Type, name: __String) {
return mapType(type, t => {
if (isGenericMappedType(t)) {
@@ -22452,7 +22545,7 @@ namespace ts {
else if (t.flags & TypeFlags.StructuredType) {
const prop = getPropertyOfType(t, name);
if (prop) {
return getTypeOfSymbol(prop);
return isCircularMappedProperty(prop) ? undefined : getTypeOfSymbol(prop);
}
if (isTupleType(t)) {
const restType = getRestTypeOfTupleType(t);
@@ -25101,7 +25194,7 @@ namespace ts {
function getArrayifiedType(type: Type) {
return type.flags & TypeFlags.Union ? mapType(type, getArrayifiedType) :
type.flags & (TypeFlags.Any | TypeFlags.Instantiable) || isMutableArrayOrTuple(type) ? type :
isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.associatedNames) :
isTupleType(type) ? createTupleType(getTypeArguments(type), type.target.minLength, type.target.hasRestElement, /*readonly*/ false, type.target.labeledElementDeclarations) :
createArrayType(getIndexedAccessType(type, numberType));
}
@@ -25117,6 +25210,7 @@ namespace ts {
}
}
const types = [];
const names: (ParameterDeclaration | NamedTupleMember)[] = [];
let spreadIndex = -1;
for (let i = index; i < argCount; i++) {
const contextualType = getIndexedAccessType(restType, getLiteralType(i - index));
@@ -25124,12 +25218,15 @@ namespace ts {
if (spreadIndex < 0 && isSpreadArgument(args[i])) {
spreadIndex = i - index;
}
if (args[i].kind === SyntaxKind.SyntheticExpression && (args[i] as SyntheticExpression).tupleNameSource) {
names.push((args[i] as SyntheticExpression).tupleNameSource!);
}
const hasPrimitiveContextualType = maybeTypeOfKind(contextualType, TypeFlags.Primitive | TypeFlags.Index);
types.push(hasPrimitiveContextualType ? getRegularTypeOfLiteralType(argType) : getWidenedLiteralType(argType));
}
return spreadIndex < 0 ?
createTupleType(types) :
createTupleType(append(types.slice(0, spreadIndex), getUnionType(types.slice(spreadIndex))), spreadIndex, /*hasRestElement*/ true);
createTupleType(types, /*minLength*/ undefined, /*hasRestElement*/ undefined, /*readonly*/ undefined, length(names) === length(types) ? names : undefined) :
createTupleType(append(types.slice(0, spreadIndex), getUnionType(types.slice(spreadIndex))), spreadIndex, /*hasRestElement*/ true, /*readonly*/ undefined);
}
function checkTypeArguments(signature: Signature, typeArgumentNodes: readonly TypeNode[], reportErrors: boolean, headMessage?: DiagnosticMessage): Type[] | undefined {
@@ -25380,11 +25477,12 @@ namespace ts {
}
}
function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean) {
function createSyntheticExpression(parent: Node, type: Type, isSpread?: boolean, tupleNameSource?: ParameterDeclaration | NamedTupleMember) {
const result = <SyntheticExpression>createNode(SyntaxKind.SyntheticExpression, parent.pos, parent.end);
result.parent = parent;
result.type = type;
result.isSpread = isSpread || false;
result.tupleNameSource = tupleNameSource;
return result;
}
@@ -25419,7 +25517,7 @@ namespace ts {
if (isTupleType(type)) {
const typeArguments = getTypeArguments(<TypeReference>type);
const restIndex = type.target.hasRestElement ? typeArguments.length - 1 : -1;
const syntheticArgs = map(typeArguments, (t, i) => createSyntheticExpression(spreadArgument, t, /*isSpread*/ i === restIndex));
const syntheticArgs = map(typeArguments, (t, i) => createSyntheticExpression(spreadArgument, t, /*isSpread*/ i === restIndex, type.target.labeledElementDeclarations?.[i]));
return concatenate(args.slice(0, length - 1), syntheticArgs);
}
}
@@ -26961,6 +27059,11 @@ namespace ts {
return type;
}
function getTupleElementLabel(d: ParameterDeclaration | NamedTupleMember) {
Debug.assert(isIdentifier(d.name)); // Parameter declarations could be binding patterns, but we only allow identifier names
return d.name.escapedText;
}
function getParameterNameAtPosition(signature: Signature, pos: number) {
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
if (pos < paramCount) {
@@ -26969,13 +27072,33 @@ namespace ts {
const restParameter = signature.parameters[paramCount] || unknownSymbol;
const restType = getTypeOfSymbol(restParameter);
if (isTupleType(restType)) {
const associatedNames = (<TupleType>(<TypeReference>restType).target).associatedNames;
const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations;
const index = pos - paramCount;
return associatedNames && associatedNames[index] || restParameter.escapedName + "_" + index as __String;
return associatedNames && getTupleElementLabel(associatedNames[index]) || restParameter.escapedName + "_" + index as __String;
}
return restParameter.escapedName;
}
function isValidDeclarationForTupleLabel(d: Declaration): d is NamedTupleMember | (ParameterDeclaration & { name: Identifier }) {
return d.kind === SyntaxKind.NamedTupleMember || (isParameter(d) && d.name && isIdentifier(d.name));
}
function getNameableDeclarationAtPosition(signature: Signature, pos: number) {
const paramCount = signature.parameters.length - (signatureHasRestParameter(signature) ? 1 : 0);
if (pos < paramCount) {
const decl = signature.parameters[pos].valueDeclaration;
return decl && isValidDeclarationForTupleLabel(decl) ? decl : undefined;
}
const restParameter = signature.parameters[paramCount] || unknownSymbol;
const restType = getTypeOfSymbol(restParameter);
if (isTupleType(restType)) {
const associatedNames = (<TupleType>(<TypeReference>restType).target).labeledElementDeclarations;
const index = pos - paramCount;
return associatedNames && associatedNames[index];
}
return restParameter.valueDeclaration && isValidDeclarationForTupleLabel(restParameter.valueDeclaration) ? restParameter.valueDeclaration : undefined;
}
function getTypeAtPosition(signature: Signature, pos: number): Type {
return tryGetTypeAtPosition(signature, pos) || anyType;
}
@@ -27006,14 +27129,26 @@ namespace ts {
return restType;
}
const types = [];
const names = [];
let names: (NamedTupleMember | ParameterDeclaration)[] | undefined = [];
for (let i = pos; i < nonRestCount; i++) {
types.push(getTypeAtPosition(source, i));
names.push(getParameterNameAtPosition(source, i));
const name = getNameableDeclarationAtPosition(source, i);
if (name && names) {
names.push(name);
}
else {
names = undefined;
}
}
if (restType) {
types.push(getIndexedAccessType(restType, numberType));
names.push(getParameterNameAtPosition(source, nonRestCount));
const name = getNameableDeclarationAtPosition(source, nonRestCount);
if (name && names) {
names.push(name);
}
else {
names = undefined;
}
}
const minArgumentCount = getMinArgumentCount(source);
const minLength = minArgumentCount < pos ? 0 : minArgumentCount - pos;
@@ -29898,7 +30033,7 @@ namespace ts {
if (getClassExtendsHeritageElement(containingClassDecl)) {
captureLexicalThis(node.parent, containingClassDecl);
const classExtendsNull = classDeclarationExtendsNull(containingClassDecl);
const superCall = getSuperCallInConstructor(node);
const superCall = findFirstSuperCall(node.body!);
if (superCall) {
if (classExtendsNull) {
error(superCall, Diagnostics.A_constructor_cannot_contain_a_super_call_when_its_class_extends_null);
@@ -30089,11 +30224,19 @@ namespace ts {
}
function checkTupleType(node: TupleTypeNode) {
const elementTypes = node.elementTypes;
const elementTypes = node.elements;
let seenOptionalElement = false;
let seenNamedElement = false;
for (let i = 0; i < elementTypes.length; i++) {
const e = elementTypes[i];
if (e.kind === SyntaxKind.RestType) {
if (e.kind === SyntaxKind.NamedTupleMember) {
seenNamedElement = true;
}
else if (seenNamedElement) {
grammarErrorOnNode(e, Diagnostics.Tuple_members_must_all_have_names_or_all_not_have_names);
break;
}
if (isTupleRestElement(e)) {
if (i !== elementTypes.length - 1) {
grammarErrorOnNode(e, Diagnostics.A_rest_element_must_be_last_in_a_tuple_type);
break;
@@ -30102,7 +30245,7 @@ namespace ts {
error(e, Diagnostics.A_rest_element_type_must_be_an_array_type);
}
}
else if (e.kind === SyntaxKind.OptionalType) {
else if (isTupleOptionalElement(e)) {
seenOptionalElement = true;
}
else if (seenOptionalElement) {
@@ -30110,7 +30253,7 @@ namespace ts {
break;
}
}
forEach(node.elementTypes, checkSourceElement);
forEach(node.elements, checkSourceElement);
}
function checkUnionOrIntersectionType(node: UnionOrIntersectionTypeNode) {
@@ -30196,6 +30339,20 @@ namespace ts {
getTypeFromTypeNode(node);
}
function checkNamedTupleMember(node: NamedTupleMember) {
if (node.dotDotDotToken && node.questionToken) {
grammarErrorOnNode(node, Diagnostics.A_tuple_member_cannot_be_both_optional_and_rest);
}
if (node.type.kind === SyntaxKind.OptionalType) {
grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_optional_with_a_question_mark_after_the_name_and_before_the_colon_rather_than_after_the_type);
}
if (node.type.kind === SyntaxKind.RestType) {
grammarErrorOnNode(node.type, Diagnostics.A_labeled_tuple_element_is_declared_as_rest_with_a_before_the_name_rather_than_before_the_type);
}
checkSourceElement(node.type);
getTypeFromTypeNode(node);
}
function isPrivateWithinAmbient(node: Node): boolean {
return (hasEffectiveModifier(node, ModifierFlags.Private) || isPrivateIdentifierPropertyDeclaration(node)) && !!(node.flags & NodeFlags.Ambient);
}
@@ -30975,6 +31132,7 @@ namespace ts {
return getEntityNameForDecoratorMetadataFromTypeList([(<ConditionalTypeNode>node).trueType, (<ConditionalTypeNode>node).falseType]);
case SyntaxKind.ParenthesizedType:
case SyntaxKind.NamedTupleMember:
return getEntityNameForDecoratorMetadata((<ParenthesizedTypeNode>node).type);
case SyntaxKind.TypeReference:
@@ -30986,8 +31144,8 @@ namespace ts {
function getEntityNameForDecoratorMetadataFromTypeList(types: readonly TypeNode[]): EntityName | undefined {
let commonEntityName: EntityName | undefined;
for (let typeNode of types) {
while (typeNode.kind === SyntaxKind.ParenthesizedType) {
typeNode = (typeNode as ParenthesizedTypeNode).type; // Skip parens if need be
while (typeNode.kind === SyntaxKind.ParenthesizedType || typeNode.kind === SyntaxKind.NamedTupleMember) {
typeNode = (typeNode as ParenthesizedTypeNode | NamedTupleMember).type; // Skip parens if need be
}
if (typeNode.kind === SyntaxKind.NeverKeyword) {
continue; // Always elide `never` from the union/intersection if possible
@@ -34740,6 +34898,8 @@ namespace ts {
return checkInferType(<InferTypeNode>node);
case SyntaxKind.ImportType:
return checkImportType(<ImportTypeNode>node);
case SyntaxKind.NamedTupleMember:
return checkNamedTupleMember(<NamedTupleMember>node);
case SyntaxKind.JSDocAugmentsTag:
return checkJSDocAugmentsTag(node as JSDocAugmentsTag);
case SyntaxKind.JSDocImplementsTag:
+1
View File
@@ -53,6 +53,7 @@ namespace ts {
["es2020.promise", "lib.es2020.promise.d.ts"],
["es2020.string", "lib.es2020.string.d.ts"],
["es2020.symbol.wellknown", "lib.es2020.symbol.wellknown.d.ts"],
["es2020.intl", "lib.es2020.intl.d.ts"],
["esnext.array", "lib.es2019.array.d.ts"],
["esnext.symbol", "lib.es2019.symbol.d.ts"],
["esnext.asynciterable", "lib.es2018.asynciterable.d.ts"],
+1 -1
View File
@@ -150,7 +150,7 @@ namespace ts {
* returns a falsey value, then returns false.
* If no such value is found, the callback is applied to each element of array and `true` is returned.
*/
export function every<T>(array: readonly T[], callback: (element: T, index: number) => boolean): boolean {
export function every<T>(array: readonly T[] | undefined, callback: (element: T, index: number) => boolean): boolean {
if (array) {
for (let i = 0; i < array.length; i++) {
if (!callback(array[i], i)) {
+24
View File
@@ -3517,6 +3517,22 @@
"category": "Error",
"code": 5083
},
"Tuple members must all have names or all not have names.": {
"category": "Error",
"code": 5084
},
"A tuple member cannot be both optional and rest.": {
"category": "Error",
"code": 5085
},
"A labeled tuple element is declared as optional with a question mark after the name and before the colon, rather than after the type.": {
"category": "Error",
"code": 5086
},
"A labeled tuple element is declared as rest with a `...` before the name, rather than before the type.": {
"category": "Error",
"code": 5087
},
"Generates a sourcemap for each corresponding '.d.ts' file.": {
"category": "Message",
@@ -5677,6 +5693,14 @@
"category": "Message",
"code": 95116
},
"Move labeled tuple element modifiers to labels": {
"category": "Message",
"code": 95117
},
"Convert overload list to single signature": {
"category": "Message",
"code": 95118
},
"No value exists in scope for the shorthand property '{0}'. Either declare one or provide an initializer.": {
"category": "Error",
+16 -4
View File
@@ -1370,6 +1370,8 @@ namespace ts {
case SyntaxKind.RestType:
case SyntaxKind.JSDocVariadicType:
return emitRestOrJSDocVariadicType(node as RestTypeNode | JSDocVariadicType);
case SyntaxKind.NamedTupleMember:
return emitNamedTupleMember(node as NamedTupleMember);
// Binding patterns
case SyntaxKind.ObjectBindingPattern:
@@ -2099,9 +2101,19 @@ namespace ts {
}
function emitTupleType(node: TupleTypeNode) {
writePunctuation("[");
emitList(node, node.elementTypes, ListFormat.TupleTypeElements);
writePunctuation("]");
emitTokenWithComment(SyntaxKind.OpenBracketToken, node.pos, writePunctuation, node);
const flags = getEmitFlags(node) & EmitFlags.SingleLine ? ListFormat.SingleLineTupleTypeElements : ListFormat.MultiLineTupleTypeElements;
emitList(node, node.elements, flags | ListFormat.NoSpaceIfEmpty);
emitTokenWithComment(SyntaxKind.CloseBracketToken, node.elements.end, writePunctuation, node);
}
function emitNamedTupleMember(node: NamedTupleMember) {
emit(node.dotDotDotToken);
emit(node.name);
emit(node.questionToken);
emitTokenWithComment(SyntaxKind.ColonToken, node.name.end, writePunctuation, node);
writeSpace();
emit(node.type);
}
function emitOptionalType(node: OptionalTypeNode) {
@@ -4968,7 +4980,7 @@ namespace ts {
}
function emitLeadingSynthesizedComment(comment: SynthesizedComment) {
if (comment.kind === SyntaxKind.SingleLineCommentTrivia) {
if (comment.hasLeadingNewline || comment.kind === SyntaxKind.SingleLineCommentTrivia) {
writer.writeLine();
}
writeSynthesizedComment(comment);
+38 -5
View File
@@ -810,15 +810,15 @@ namespace ts {
: node;
}
export function createTupleTypeNode(elementTypes: readonly TypeNode[]) {
export function createTupleTypeNode(elements: readonly (TypeNode | NamedTupleMember)[]) {
const node = createSynthesizedNode(SyntaxKind.TupleType) as TupleTypeNode;
node.elementTypes = createNodeArray(elementTypes);
node.elements = createNodeArray(elements);
return node;
}
export function updateTupleTypeNode(node: TupleTypeNode, elementTypes: readonly TypeNode[]) {
return node.elementTypes !== elementTypes
? updateNode(createTupleTypeNode(elementTypes), node)
export function updateTupleTypeNode(node: TupleTypeNode, elements: readonly (TypeNode | NamedTupleMember)[]) {
return node.elements !== elements
? updateNode(createTupleTypeNode(elements), node)
: node;
}
@@ -934,6 +934,24 @@ namespace ts {
: node;
}
export function createNamedTupleMember(dotDotDotToken: Token<SyntaxKind.DotDotDotToken> | undefined, name: Identifier, questionToken: Token<SyntaxKind.QuestionToken> | undefined, type: TypeNode) {
const node = <NamedTupleMember>createSynthesizedNode(SyntaxKind.NamedTupleMember);
node.dotDotDotToken = dotDotDotToken;
node.name = name;
node.questionToken = questionToken;
node.type = type;
return node;
}
export function updateNamedTupleMember(node: NamedTupleMember, dotDotDotToken: Token<SyntaxKind.DotDotDotToken> | undefined, name: Identifier, questionToken: Token<SyntaxKind.QuestionToken> | undefined, type: TypeNode) {
return node.dotDotDotToken !== dotDotDotToken
|| node.name !== name
|| node.questionToken !== questionToken
|| node.type !== type
? updateNode(createNamedTupleMember(dotDotDotToken, name, questionToken, type), node)
: node;
}
export function createThisTypeNode() {
return <ThisTypeNode>createSynthesizedNode(SyntaxKind.ThisType);
}
@@ -2616,6 +2634,21 @@ namespace ts {
return node;
}
/* @internal */
export function createJSDocVariadicType(type: TypeNode): JSDocVariadicType {
const node = createSynthesizedNode(SyntaxKind.JSDocVariadicType) as JSDocVariadicType;
node.type = type;
return node;
}
/* @internal */
export function updateJSDocVariadicType(node: JSDocVariadicType, type: TypeNode): JSDocVariadicType {
return node.type !== type
? updateNode(createJSDocVariadicType(type), node)
: node;
}
// JSX
export function createJsxElement(openingElement: JsxOpeningElement, children: readonly JsxChild[], closingElement: JsxClosingElement) {
+31 -2
View File
@@ -179,7 +179,7 @@ namespace ts {
case SyntaxKind.ArrayType:
return visitNode(cbNode, (<ArrayTypeNode>node).elementType);
case SyntaxKind.TupleType:
return visitNodes(cbNode, cbNodes, (<TupleTypeNode>node).elementTypes);
return visitNodes(cbNode, cbNodes, (<TupleTypeNode>node).elements);
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
return visitNodes(cbNode, cbNodes, (<UnionOrIntersectionTypeNode>node).types);
@@ -207,6 +207,11 @@ namespace ts {
visitNode(cbNode, (<MappedTypeNode>node).type);
case SyntaxKind.LiteralType:
return visitNode(cbNode, (<LiteralTypeNode>node).literal);
case SyntaxKind.NamedTupleMember:
return visitNode(cbNode, (<NamedTupleMember>node).dotDotDotToken) ||
visitNode(cbNode, (<NamedTupleMember>node).name) ||
visitNode(cbNode, (<NamedTupleMember>node).questionToken) ||
visitNode(cbNode, (<NamedTupleMember>node).type);
case SyntaxKind.ObjectBindingPattern:
case SyntaxKind.ArrayBindingPattern:
return visitNodes(cbNode, cbNodes, (<BindingPattern>node).elements);
@@ -3056,9 +3061,33 @@ namespace ts {
return type;
}
function isNextTokenColonOrQuestionColon() {
return nextToken() === SyntaxKind.ColonToken || (token() === SyntaxKind.QuestionToken && nextToken() === SyntaxKind.ColonToken);
}
function isTupleElementName() {
if (token() === SyntaxKind.DotDotDotToken) {
return tokenIsIdentifierOrKeyword(nextToken()) && isNextTokenColonOrQuestionColon();
}
return tokenIsIdentifierOrKeyword(token()) && isNextTokenColonOrQuestionColon();
}
function parseTupleElementNameOrTupleElementType() {
if (lookAhead(isTupleElementName)) {
const node = <NamedTupleMember>createNode(SyntaxKind.NamedTupleMember);
node.dotDotDotToken = parseOptionalToken(SyntaxKind.DotDotDotToken);
node.name = parseIdentifierName();
node.questionToken = parseOptionalToken(SyntaxKind.QuestionToken);
parseExpected(SyntaxKind.ColonToken);
node.type = parseTupleElementType();
return addJSDocComment(finishNode(node));
}
return parseTupleElementType();
}
function parseTupleType(): TupleTypeNode {
const node = <TupleTypeNode>createNode(SyntaxKind.TupleType);
node.elementTypes = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
node.elements = parseBracketedList(ParsingContext.TupleElementTypes, parseTupleElementNameOrTupleElementType, SyntaxKind.OpenBracketToken, SyntaxKind.CloseBracketToken);
return finishNode(node);
}
@@ -1018,6 +1018,10 @@ namespace ts {
}
}
if (isTupleTypeNode(input) && (getLineAndCharacterOfPosition(currentSourceFile, input.pos).line === getLineAndCharacterOfPosition(currentSourceFile, input.end).line)) {
setEmitFlags(input, EmitFlags.SingleLine);
}
return cleanup(visitEachChild(input, visitDeclarationSubtree, context));
function cleanup<T extends Node>(returnValue: T | undefined): T | undefined {
+1 -1
View File
@@ -2583,7 +2583,7 @@ namespace ts {
&& i < numInitialPropertiesWithoutYield) {
numInitialPropertiesWithoutYield = i;
}
if (property.name!.kind === SyntaxKind.ComputedPropertyName) {
if (Debug.checkDefined(property.name).kind === SyntaxKind.ComputedPropertyName) {
numInitialProperties = i;
break;
}
+15 -10
View File
@@ -8,7 +8,7 @@ namespace ts {
export function processTaggedTemplateExpression(
context: TransformationContext,
node: TaggedTemplateExpression,
visitor: ((node: Node) => VisitResult<Node>) | undefined,
visitor: Visitor,
currentSourceFile: SourceFile,
recordTaggedTemplateString: (temp: Identifier) => void,
level: ProcessLevel) {
@@ -24,7 +24,9 @@ namespace ts {
const rawStrings: Expression[] = [];
const template = node.template;
if (level === ProcessLevel.LiftRestriction && !hasInvalidEscape(template)) return node;
if (level === ProcessLevel.LiftRestriction && !hasInvalidEscape(template)) {
return visitEachChild(node, visitor, context);
}
if (isNoSubstitutionTemplateLiteral(template)) {
cookedStrings.push(createTemplateCooked(template));
@@ -71,18 +73,21 @@ namespace ts {
*
* @param node The ES6 template literal.
*/
function getRawLiteral(node: LiteralLikeNode, currentSourceFile: SourceFile) {
function getRawLiteral(node: TemplateLiteralLikeNode, currentSourceFile: SourceFile) {
// Find original source text, since we need to emit the raw strings of the tagged template.
// The raw strings contain the (escaped) strings of what the user wrote.
// Examples: `\n` is converted to "\\n", a template string with a newline to "\n".
let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
let text = node.rawText;
if (text === undefined) {
text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node);
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
// text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"),
// thus we need to remove those characters.
// First template piece starts with "`", others with "}"
// Last template piece ends with "`", others with "${"
const isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail;
text = text.substring(1, text.length - (isLast ? 1 : 2));
}
// Newline normalization:
// ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's
+21 -22
View File
@@ -328,6 +328,7 @@ namespace ts {
IndexedAccessType,
MappedType,
LiteralType,
NamedTupleMember,
ImportType,
// Binding patterns
ObjectBindingPattern,
@@ -700,6 +701,7 @@ namespace ts {
| ConstructorTypeNode
| JSDocFunctionType
| ExportDeclaration
| NamedTupleMember
| EndOfFileToken;
export type HasType =
@@ -1274,7 +1276,15 @@ namespace ts {
export interface TupleTypeNode extends TypeNode {
kind: SyntaxKind.TupleType;
elementTypes: NodeArray<TypeNode>;
elements: NodeArray<TypeNode | NamedTupleMember>;
}
export interface NamedTupleMember extends TypeNode, JSDocContainer, Declaration {
kind: SyntaxKind.NamedTupleMember;
dotDotDotToken?: Token<SyntaxKind.DotDotDotToken>;
name: Identifier;
questionToken?: Token<SyntaxKind.QuestionToken>;
type: TypeNode;
}
export interface OptionalTypeNode extends TypeNode {
@@ -1478,6 +1488,7 @@ namespace ts {
kind: SyntaxKind.SyntheticExpression;
isSpread: boolean;
type: Type;
tupleNameSource?: ParameterDeclaration | NamedTupleMember;
}
// see: https://tc39.github.io/ecma262/#prod-ExponentiationExpression
@@ -2590,6 +2601,7 @@ namespace ts {
text: string;
pos: -1;
end: -1;
hasLeadingNewline?: boolean;
}
// represents a top level: { type } expression in a JSDoc comment.
@@ -2791,34 +2803,21 @@ namespace ts {
}
export type FlowNode =
| AfterFinallyFlow
| PreFinallyFlow
| FlowStart
| FlowLabel
| FlowAssignment
| FlowCall
| FlowCondition
| FlowSwitchClause
| FlowArrayMutation;
| FlowArrayMutation
| FlowCall
| FlowReduceLabel;
export interface FlowNodeBase {
flags: FlowFlags;
id?: number; // Node id used by flow type cache in checker
}
export interface FlowLock {
locked?: boolean;
}
export interface AfterFinallyFlow extends FlowNodeBase, FlowLock {
antecedent: FlowNode;
}
export interface PreFinallyFlow extends FlowNodeBase {
antecedent: FlowNode;
lock: FlowLock;
}
// FlowStart represents the start of a control flow. For a function expression or arrow
// function, the node property references the function (which in turn has a flowNode
// property for the containing control flow).
@@ -3508,7 +3507,7 @@ namespace ts {
*/
getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
/* @internal */ getResolvedSignatureForSignatureHelp(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined;
/* @internal */ getExpandedParameters(sig: Signature): readonly Symbol[];
/* @internal */ getExpandedParameters(sig: Signature): readonly (readonly Symbol[])[];
/* @internal */ hasEffectiveRestParameter(sig: Signature): boolean;
getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined;
isImplementationOfOverload(node: SignatureDeclaration): boolean | undefined;
@@ -4161,6 +4160,7 @@ namespace ts {
cjsExportMerged?: Symbol; // Version of the symbol with all non export= exports merged with the export= target
typeOnlyDeclaration?: TypeOnlyCompatibleAliasDeclaration | false; // First resolved alias declaration that makes the symbol only usable in type constructs
isConstructorDeclaredProperty?: boolean; // Property declared through 'this.x = ...' assignment in constructor
tupleLabelDeclaration?: NamedTupleMember | ParameterDeclaration; // Declaration associated with the tuple's label
}
/* @internal */
@@ -4316,8 +4316,6 @@ namespace ts {
resolvedJsxElementAttributesType?: Type; // resolved element attributes type of a JSX openinglike element
resolvedJsxElementAllAttributesType?: Type; // resolved all element attributes type of a JSX openinglike element
resolvedJSDocType?: Type; // Resolved type of a JSDoc type reference
hasSuperCall?: boolean; // recorded result when we try to find super-call. We only try to find one if this flag is undefined, indicating that we haven't made an attempt.
superCall?: SuperCall; // Cached first super-call found in the constructor. Used in checking whether super is called before this-accessing
switchTypes?: Type[]; // Cached array of switch case expression types
jsxNamespace?: Symbol | false; // Resolved jsx namespace symbol for this node
contextFreeType?: Type; // Cached context-free type used by the first pass of inference; used when a function's return is partially contextually sensitive
@@ -4633,7 +4631,7 @@ namespace ts {
minLength: number;
hasRestElement: boolean;
readonly: boolean;
associatedNames?: __String[];
labeledElementDeclarations?: readonly (NamedTupleMember | ParameterDeclaration)[];
}
export interface TupleTypeReference extends TypeReference {
@@ -6574,7 +6572,8 @@ namespace ts {
SingleLineTypeLiteralMembers = SingleLine | SpaceBetweenBraces | SpaceBetweenSiblings,
MultiLineTypeLiteralMembers = MultiLine | Indented | OptionalIfEmpty,
TupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine,
SingleLineTupleTypeElements = CommaDelimited | SpaceBetweenSiblings | SingleLine,
MultiLineTupleTypeElements = CommaDelimited | Indented | SpaceBetweenSiblings | MultiLine,
UnionTypeConstituents = BarDelimited | SpaceBetweenSiblings | SingleLine,
IntersectionTypeConstituents = AmpersandDelimited | SpaceBetweenSiblings | SingleLine,
ObjectBindingPatternElements = SingleLine | AllowTrailingComma | SpaceBetweenBraces | CommaDelimited | SpaceBetweenSiblings | NoSpaceIfEmpty,
+9 -1
View File
@@ -480,7 +480,7 @@ namespace ts {
case SyntaxKind.TupleType:
return updateTupleTypeNode((<TupleTypeNode>node),
nodesVisitor((<TupleTypeNode>node).elementTypes, visitor, isTypeNode));
nodesVisitor((<TupleTypeNode>node).elements, visitor, isTypeNode));
case SyntaxKind.OptionalType:
return updateOptionalTypeNode((<OptionalTypeNode>node),
@@ -517,6 +517,14 @@ namespace ts {
(<ImportTypeNode>node).isTypeOf
);
case SyntaxKind.NamedTupleMember:
return updateNamedTupleMember(<NamedTupleMember>node,
visitNode((<NamedTupleMember>node).dotDotDotToken, visitor, isToken),
visitNode((<NamedTupleMember>node).name, visitor, isIdentifier),
visitNode((<NamedTupleMember>node).questionToken, visitor, isToken),
visitNode((<NamedTupleMember>node).type, visitor, isTypeNode),
);
case SyntaxKind.ParenthesizedType:
return updateParenthesizedType(<ParenthesizedTypeNode>node,
visitNode((<ParenthesizedTypeNode>node).type, visitor, isTypeNode));