mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-06 02:33:53 -06:00
Improve type check, add baselines
This commit is contained in:
parent
24f3794952
commit
dba5c2bf87
@ -865,7 +865,8 @@ namespace ts {
|
||||
else {
|
||||
return node.kind === SyntaxKind.BinaryExpression && (
|
||||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.AmpersandAmpersandToken ||
|
||||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken);
|
||||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.BarBarToken ||
|
||||
(<BinaryExpression>node).operatorToken.kind === SyntaxKind.QuestionQuestionToken);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1230,7 +1231,9 @@ namespace ts {
|
||||
|
||||
function bindBinaryExpressionFlow(node: BinaryExpression) {
|
||||
const operator = node.operatorToken.kind;
|
||||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken) {
|
||||
if (operator === SyntaxKind.AmpersandAmpersandToken ||
|
||||
operator === SyntaxKind.BarBarToken ||
|
||||
operator === SyntaxKind.QuestionQuestionToken) {
|
||||
if (isTopLevelLogicalExpression(node)) {
|
||||
const postExpressionLabel = createBranchLabel();
|
||||
bindLogicalExpression(node, postExpressionLabel, postExpressionLabel);
|
||||
@ -2546,6 +2549,10 @@ namespace ts {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
if (subtreeFlags & TransformFlags.ContainsSpread
|
||||
|| isSuperOrSuperProperty(expression, expressionKind)) {
|
||||
// If the this node contains a SpreadExpression, or is a super call, then it is an ES6
|
||||
@ -2577,6 +2584,9 @@ namespace ts {
|
||||
if (node.typeArguments) {
|
||||
transformFlags |= TransformFlags.AssertTypeScript;
|
||||
}
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
if (subtreeFlags & TransformFlags.ContainsSpread) {
|
||||
// If the this node contains a SpreadElementExpression then it is an ES6
|
||||
// node.
|
||||
@ -2987,6 +2997,9 @@ namespace ts {
|
||||
let transformFlags = subtreeFlags;
|
||||
const expression = node.expression;
|
||||
const expressionKind = expression.kind;
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
|
||||
// If a PropertyAccessExpression starts with a super keyword, then it is
|
||||
// ES6 syntax, and requires a lexical `this` binding.
|
||||
@ -3111,6 +3124,7 @@ namespace ts {
|
||||
|
||||
switch (kind) {
|
||||
case SyntaxKind.BarGreaterThanToken:
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
break;
|
||||
|
||||
@ -3315,6 +3329,12 @@ namespace ts {
|
||||
|
||||
break;
|
||||
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
transformFlags |= TransformFlags.AssertESNext;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.DoStatement:
|
||||
case SyntaxKind.WhileStatement:
|
||||
case SyntaxKind.ForStatement:
|
||||
|
||||
@ -163,7 +163,6 @@ namespace ts {
|
||||
const unknownSignature = createSignature(undefined, undefined, undefined, emptyArray, unknownType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
const resolvingSignature = createSignature(undefined, undefined, undefined, emptyArray, anyType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
const silentNeverSignature = createSignature(undefined, undefined, undefined, emptyArray, silentNeverType, /*typePredicate*/ undefined, 0, /*hasRestParameter*/ false, /*hasLiteralTypes*/ false);
|
||||
const resolvingPartialSignatures: Signature[] = [];
|
||||
|
||||
const enumNumberIndexInfo = createIndexInfo(stringType, /*isReadonly*/ true);
|
||||
const operatorExpressionTypes = createMap<Type>();
|
||||
@ -2618,7 +2617,7 @@ namespace ts {
|
||||
|
||||
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||
const parameterNode = <ParameterDeclaration>p.valueDeclaration;
|
||||
if ((isTransient(p) && p.transientSymbolIsRest) || isRestParameter(parameterNode)) {
|
||||
if (isTransient(p) && typeof p.transientSymbolIsRest === "boolean" ? p.transientSymbolIsRest : isRestParameter(parameterNode)) {
|
||||
writePunctuation(writer, SyntaxKind.DotDotDotToken);
|
||||
}
|
||||
if (parameterNode && isBindingPattern(parameterNode.name)) {
|
||||
@ -8170,6 +8169,20 @@ namespace ts {
|
||||
return strictNullChecks ? getTypeWithFacts(type, TypeFacts.NEUndefinedOrNull) : type;
|
||||
}
|
||||
|
||||
function propagateNullType(type: Type, propagatingType: Type) {
|
||||
return propagatingType === neverType ? type : getUnionType([type, propagatingType]);
|
||||
}
|
||||
|
||||
function propagateNullReturnType(signature: Signature, propagatingType: Type) {
|
||||
if (propagatingType === neverType || isTypeAny(signature.resolvedReturnType)) {
|
||||
return signature;
|
||||
}
|
||||
|
||||
signature = cloneSignature(signature);
|
||||
signature.resolvedReturnType = getUnionType([signature.resolvedReturnType, propagatingType]);
|
||||
return signature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return true if type was inferred from an object literal or written as an object type literal
|
||||
* with no call or construct signatures.
|
||||
@ -11122,6 +11135,14 @@ namespace ts {
|
||||
// with this type. It is neither affected by it, nor does it propagate it to its operand.
|
||||
// So the fact that contextualMapper is passed is not important, because the operand of a spread
|
||||
// element is not contextually typed.
|
||||
if (node.expression.kind === SyntaxKind.OmittedExpression && (
|
||||
node.parent.kind === SyntaxKind.CallExpression ||
|
||||
node.parent.kind === SyntaxKind.NewExpression)) {
|
||||
// positional spread in an argument list indicates partial application.
|
||||
// we indicate `unknownType` here as the type is not known and should not
|
||||
// introduce type errors.
|
||||
return unknownType;
|
||||
}
|
||||
const arrayOrIterableType = checkExpressionCached(node.expression, contextualMapper);
|
||||
return checkIteratedTypeOrElementType(arrayOrIterableType, node.expression, /*allowStringInput*/ false);
|
||||
}
|
||||
@ -12070,7 +12091,11 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkPropertyAccessExpressionOrQualifiedName(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, right: Identifier) {
|
||||
const type = checkNonNullExpression(left);
|
||||
const propagateNull = node.flags & NodeFlags.PropagateNull;
|
||||
const objectType = propagateNull ? checkExpression(left) : checkNonNullExpression(left);
|
||||
const type = propagateNull ? getNonNullableType(objectType) : objectType;
|
||||
const propagatingType = propagateNull ? getTypeWithFacts(objectType, TypeFacts.EQUndefinedOrNull) : neverType;
|
||||
|
||||
if (isTypeAny(type) || type === silentNeverType) {
|
||||
return type;
|
||||
}
|
||||
@ -12112,10 +12137,10 @@ namespace ts {
|
||||
if (node.kind !== SyntaxKind.PropertyAccessExpression || assignmentKind === AssignmentKind.Definite ||
|
||||
!(prop.flags & (SymbolFlags.Variable | SymbolFlags.Property | SymbolFlags.Accessor)) &&
|
||||
!(prop.flags & SymbolFlags.Method && propType.flags & TypeFlags.Union)) {
|
||||
return propType;
|
||||
return propagateNullType(propType, propagatingType);
|
||||
}
|
||||
const flowType = getFlowTypeOfReference(node, propType, /*assumeInitialized*/ true, /*flowContainer*/ undefined);
|
||||
return assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType;
|
||||
return propagateNullType(assignmentKind ? getBaseTypeOfLiteralType(flowType) : flowType, propagatingType);
|
||||
}
|
||||
|
||||
function isValidPropertyAccess(node: PropertyAccessExpression | QualifiedName, propertyName: string): boolean {
|
||||
@ -12184,7 +12209,10 @@ namespace ts {
|
||||
}
|
||||
|
||||
function checkIndexedAccess(node: ElementAccessExpression): Type {
|
||||
const objectType = checkNonNullExpression(node.expression);
|
||||
const propagateNull = node.flags & NodeFlags.PropagateNull;
|
||||
const objectType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression);
|
||||
const type = propagateNull ? getNonNullableType(objectType) : objectType;
|
||||
const propagatingType = propagateNull ? getTypeWithFacts(objectType, TypeFacts.EQUndefinedOrNull) : neverType;
|
||||
|
||||
const indexExpression = node.argumentExpression;
|
||||
if (!indexExpression) {
|
||||
@ -12204,27 +12232,24 @@ namespace ts {
|
||||
|
||||
const indexType = isForInVariableForNumericPropertyNames(indexExpression) ? numberType : checkExpression(indexExpression);
|
||||
|
||||
if (objectType === unknownType || objectType === silentNeverType) {
|
||||
return objectType;
|
||||
if (type === unknownType || type === silentNeverType) {
|
||||
return type;
|
||||
}
|
||||
|
||||
if (isConstEnumObjectType(objectType) && indexExpression.kind !== SyntaxKind.StringLiteral) {
|
||||
if (isConstEnumObjectType(type) && indexExpression.kind !== SyntaxKind.StringLiteral) {
|
||||
error(indexExpression, Diagnostics.A_const_enum_member_can_only_be_accessed_using_a_string_literal);
|
||||
return unknownType;
|
||||
}
|
||||
|
||||
return getIndexedAccessType(objectType, indexType, node);
|
||||
return propagateNullType(getIndexedAccessType(type, indexType, node), propagatingType);
|
||||
}
|
||||
|
||||
function checkBindExpression(node: BindExpression | BindToExpression): Type {
|
||||
if (node.kind === SyntaxKind.BindToExpression) {
|
||||
checkNonNullExpression(node.targetExpression);
|
||||
const signature = getResolvedSignature(node);
|
||||
if (signature === unknownSignature) {
|
||||
return unknownType;
|
||||
}
|
||||
const signatures = getResolvedPartialSignatures(node);
|
||||
if (signatures.length === 0 || singleOrUndefined(signatures) === unknownSignature) {
|
||||
return unknownType
|
||||
}
|
||||
return createTypeFromSignatures(map(signatures, getSignatureWithoutThis));
|
||||
return getReturnTypeOfSignature(signature);
|
||||
}
|
||||
|
||||
function checkThatExpressionIsProperSymbolReference(expression: Expression, expressionType: Type, reportError: boolean): boolean {
|
||||
@ -12269,7 +12294,7 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
|
||||
function resolveUntypedCall(node: CallLikeExpression, partialSignaturesOutArray: Signature[]): Signature {
|
||||
function resolveUntypedCall(node: CallLikeExpression): Signature {
|
||||
if (node.kind === SyntaxKind.TaggedTemplateExpression) {
|
||||
checkExpression((<TaggedTemplateExpression>node).template);
|
||||
}
|
||||
@ -12278,17 +12303,11 @@ namespace ts {
|
||||
checkExpression(argument);
|
||||
});
|
||||
}
|
||||
if (partialSignaturesOutArray) {
|
||||
partialSignaturesOutArray.push(anySignature);
|
||||
}
|
||||
return anySignature;
|
||||
}
|
||||
|
||||
function resolveErrorCall(node: CallLikeExpression, partialSignaturesOutArray: Signature[]): Signature {
|
||||
resolveUntypedCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
if (partialSignaturesOutArray) {
|
||||
partialSignaturesOutArray.push(unknownSignature);
|
||||
}
|
||||
function resolveErrorCall(node: CallLikeExpression): Signature {
|
||||
resolveUntypedCall(node);
|
||||
return unknownSignature;
|
||||
}
|
||||
|
||||
@ -12655,20 +12674,57 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
else if (node.kind === SyntaxKind.BinaryExpression) {
|
||||
let expression = (<PipelineExpression>node).left;
|
||||
const expression = (<PipelineExpression>node).left;
|
||||
const pipelineArguments: Expression[] = [];
|
||||
if (expression.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
// comma expressions are right-deep
|
||||
args = [];
|
||||
expression = (<ParenthesizedExpression>expression).expression;
|
||||
while (expression.kind === SyntaxKind.BinaryExpression &&
|
||||
(<BinaryExpression>expression).operatorToken.kind === SyntaxKind.CommaToken) {
|
||||
args.push((<BinaryExpression>expression).left);
|
||||
expression = (<BinaryExpression>expression).right;
|
||||
}
|
||||
args.push(expression);
|
||||
collectPipelineArguments((<ParenthesizedExpression>expression).expression, pipelineArguments);
|
||||
}
|
||||
else {
|
||||
args = [expression];
|
||||
pipelineArguments.push(expression);
|
||||
}
|
||||
|
||||
if (isPartialApplication(node.right)) {
|
||||
const argumentList = node.right.arguments;
|
||||
const positionalOffsetMap = new Array<number>(argumentList.length);
|
||||
let numFreePositions = 0;
|
||||
let maxFixedPosition = -1;
|
||||
for (let i = 0; i < argumentList.length; i++) {
|
||||
const argument = argumentList[i];
|
||||
if (isPositionalElement(argument)) {
|
||||
if (argument.literal) {
|
||||
const fixedPosition = +argument.literal.text | 0;
|
||||
if (maxFixedPosition < fixedPosition) {
|
||||
maxFixedPosition = fixedPosition;
|
||||
}
|
||||
positionalOffsetMap[i] = fixedPosition;
|
||||
}
|
||||
else {
|
||||
positionalOffsetMap[i] = numFreePositions;
|
||||
numFreePositions++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
args = [];
|
||||
|
||||
const maxNonRestPosition = maxFixedPosition >= numFreePositions ? maxFixedPosition + 1 : numFreePositions;
|
||||
for (let i = 0; i < argumentList.length; i++) {
|
||||
const argument = argumentList[i];
|
||||
if (isPositionalElement(argument)) {
|
||||
args.push(pipelineArguments[positionalOffsetMap[i]] || argument);
|
||||
}
|
||||
else if (isPositionalSpreadElement(argument)) {
|
||||
for (let j = maxNonRestPosition; j < pipelineArguments.length; j++) {
|
||||
args.push(pipelineArguments[j]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
args.push(argument);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
args = pipelineArguments;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@ -12678,6 +12734,15 @@ namespace ts {
|
||||
return args;
|
||||
}
|
||||
|
||||
function collectPipelineArguments(node: Expression, argumentList: Expression[]) {
|
||||
if (isCommaExpression(node)) {
|
||||
collectPipelineArguments(node.left, argumentList);
|
||||
collectPipelineArguments(node.right, argumentList);
|
||||
}
|
||||
else {
|
||||
argumentList.push(node);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the effective argument count for a node that works like a function invocation.
|
||||
@ -12939,7 +13004,6 @@ namespace ts {
|
||||
(argIndex === 0 && node.kind === SyntaxKind.TaggedTemplateExpression)) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
return args[argIndex];
|
||||
}
|
||||
|
||||
@ -12960,14 +13024,28 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCall(node: CallLikeExpression, signatures: Signature[], partialSignaturesOutArray: Signature[], candidatesOutArray: Signature[], headMessage?: DiagnosticMessage): Signature {
|
||||
let typeArguments: TypeNode[];
|
||||
function getEffectiveTypeArguments(node: CallLikeExpression): NodeArray<TypeNode> {
|
||||
if (node.kind === SyntaxKind.CallExpression || node.kind === SyntaxKind.NewExpression) {
|
||||
typeArguments = node.typeArguments;
|
||||
const typeArguments = node.typeArguments;
|
||||
// We already perform checking on the type arguments on the class declaration itself.
|
||||
if ((<CallExpression>node).expression.kind !== SyntaxKind.SuperKeyword) {
|
||||
forEach(typeArguments, checkSourceElement);
|
||||
}
|
||||
return typeArguments;
|
||||
}
|
||||
if (node.kind === SyntaxKind.BinaryExpression && isPartialApplication(node.right)) {
|
||||
return getEffectiveTypeArguments(node.right);
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], propagatingType?: Type, headMessage?: DiagnosticMessage): Signature {
|
||||
const typeArguments: TypeNode[] = getEffectiveTypeArguments(node);
|
||||
|
||||
let partialSignatures: Signature[];
|
||||
if (node.kind === SyntaxKind.BindExpression ||
|
||||
node.kind === SyntaxKind.BindToExpression ||
|
||||
isPartialApplication(node)) {
|
||||
partialSignatures = [];
|
||||
}
|
||||
|
||||
const candidates = candidatesOutArray || [];
|
||||
@ -12975,7 +13053,7 @@ namespace ts {
|
||||
reorderCandidates(signatures, candidates);
|
||||
if (!candidates.length) {
|
||||
reportError(Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
const args = getEffectiveCallArguments(node);
|
||||
@ -13001,7 +13079,7 @@ namespace ts {
|
||||
// We do not need to call `getEffectiveArgumentCount` here as it only
|
||||
// applies when calculating the number of arguments for a decorator.
|
||||
for (let i = node.kind === SyntaxKind.TaggedTemplateExpression ? 1 : 0; i < args.length; i++) {
|
||||
if (isContextSensitive(args[i])) {
|
||||
if (isContextSensitive(getEffectiveArgument(node, args, i))) {
|
||||
if (!excludeArgument) {
|
||||
excludeArgument = new Array(args.length);
|
||||
}
|
||||
@ -13051,7 +13129,7 @@ namespace ts {
|
||||
// Whether the call is an error is determined by assignability of the arguments. The subtype pass
|
||||
// is just important for choosing the best signature. So in the case where there is only one
|
||||
// signature, the subtype pass is useless. So skipping it is an optimization.
|
||||
if (candidates.length > 1 && !partialSignaturesOutArray) {
|
||||
if (candidates.length > 1 && !partialSignatures) {
|
||||
result = chooseOverload(candidates, subtypeRelation);
|
||||
}
|
||||
if (!result) {
|
||||
@ -13061,8 +13139,24 @@ namespace ts {
|
||||
resultOfFailedInference = undefined;
|
||||
result = chooseOverload(candidates, assignableRelation);
|
||||
}
|
||||
if (result || some(partialSignaturesOutArray)) {
|
||||
return result;
|
||||
if (some(partialSignatures)) {
|
||||
const returnType = node.kind === SyntaxKind.BindExpression || node.kind === SyntaxKind.BindToExpression
|
||||
? createTypeFromSignatures(map(partialSignatures, getSignatureWithoutThis))
|
||||
: getPartialApplicationOfSignatures(args, partialSignatures);
|
||||
result = createSignature(
|
||||
/*isConstruct*/ false,
|
||||
/*typeParameters*/ undefined,
|
||||
/*typeParameter*/ undefined,
|
||||
/*parameters*/ emptyArray,
|
||||
returnType,
|
||||
/*typePredicate*/ undefined,
|
||||
/*minArgumentCount*/ 0,
|
||||
/*hasRestParameter*/ false,
|
||||
/*hasLiteralTypes*/ false
|
||||
);
|
||||
}
|
||||
if (result) {
|
||||
return propagateNullReturnType(result, propagatingType || neverType);
|
||||
}
|
||||
|
||||
// No signatures were applicable. Now report errors based on the last applicable signature with
|
||||
@ -13117,7 +13211,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
|
||||
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
|
||||
let errorInfo: DiagnosticMessageChain;
|
||||
@ -13164,11 +13258,11 @@ namespace ts {
|
||||
}
|
||||
const index = excludeArgument ? indexOf(excludeArgument, true) : -1;
|
||||
if (index < 0) {
|
||||
if (partialSignaturesOutArray) {
|
||||
if (partialSignatures) {
|
||||
const partialCandidate = originalCandidate.typeParameters
|
||||
? getPartialSignatureInstantiation(originalCandidate, typeArgumentTypes)
|
||||
: originalCandidate;
|
||||
partialSignaturesOutArray.push(partialCandidate);
|
||||
partialSignatures.push(partialCandidate);
|
||||
continue nextCandidate;
|
||||
}
|
||||
return candidate;
|
||||
@ -13202,7 +13296,7 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function resolveCallExpression(node: CallExpression, partialSignaturesOutArray: Signature[], candidatesOutArray: Signature[]): Signature {
|
||||
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
const superType = checkSuperExpression(node.expression);
|
||||
if (superType !== unknownType) {
|
||||
@ -13211,21 +13305,23 @@ namespace ts {
|
||||
const baseTypeNode = getClassExtendsHeritageClauseElement(getContainingClass(node));
|
||||
if (baseTypeNode) {
|
||||
const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments);
|
||||
return resolveCall(node, baseConstructors, partialSignaturesOutArray, candidatesOutArray);
|
||||
return resolveCall(node, baseConstructors, candidatesOutArray);
|
||||
}
|
||||
}
|
||||
return resolveUntypedCall(node, partialSignaturesOutArray);
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
const funcType = checkNonNullExpression(node.expression);
|
||||
if (funcType === silentNeverType) {
|
||||
const propagateNull = node.flags & NodeFlags.PropagateNull;
|
||||
const funcType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression);
|
||||
const type = propagateNull ? getNonNullableType(funcType) : funcType;
|
||||
if (type === silentNeverType) {
|
||||
return silentNeverSignature;
|
||||
}
|
||||
const apparentType = getApparentType(funcType);
|
||||
|
||||
const apparentType = getApparentType(type);
|
||||
if (apparentType === unknownType) {
|
||||
// Another error has already been reported
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
// Technically, this signatures list may be incomplete. We are taking the apparent type,
|
||||
@ -13238,27 +13334,29 @@ namespace ts {
|
||||
// TS 1.0 Spec: 4.12
|
||||
// In an untyped function call no TypeArgs are permitted, Args can be any argument list, no contextual
|
||||
// types are provided for the argument expressions, and the result is always of type Any.
|
||||
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
if (isUntypedFunctionCall(type, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
// The unknownType indicates that an error already occurred (and was reported). No
|
||||
// need to report another error in this case.
|
||||
if (funcType !== unknownType && node.typeArguments) {
|
||||
if (type !== unknownType && node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
return resolveUntypedCall(node, partialSignaturesOutArray);
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
// If FuncExpr's apparent type(section 3.8.1) is a function type, the call is a typed function call.
|
||||
// TypeScript employs overload resolution in typed function calls in order to support functions
|
||||
// with multiple call signatures.
|
||||
if (!callSignatures.length) {
|
||||
if (constructSignatures.length) {
|
||||
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
|
||||
error(node, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(type));
|
||||
}
|
||||
else {
|
||||
error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
}
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
return resolveCall(node, callSignatures, partialSignaturesOutArray, candidatesOutArray);
|
||||
|
||||
const propagatingType = propagateNull ? getTypeWithFacts(funcType, TypeFacts.EQUndefinedOrNull) : neverType;
|
||||
return resolveCall(node, callSignatures, candidatesOutArray, propagatingType);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -13292,8 +13390,10 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
let expressionType = checkNonNullExpression(node.expression);
|
||||
if (expressionType === silentNeverType) {
|
||||
const propagateNull = node.flags & NodeFlags.PropagateNull;
|
||||
const funcType = propagateNull ? checkExpression(node.expression) : checkNonNullExpression(node.expression);
|
||||
const type = propagateNull ? getNonNullableType(funcType) : funcType;
|
||||
if (type === silentNeverType) {
|
||||
return silentNeverSignature;
|
||||
}
|
||||
|
||||
@ -13302,51 +13402,53 @@ namespace ts {
|
||||
// function call, but using the construct signatures as the initial set of candidate
|
||||
// signatures for overload resolution. The result type of the function call becomes
|
||||
// the result type of the operation.
|
||||
expressionType = getApparentType(expressionType);
|
||||
if (expressionType === unknownType) {
|
||||
const apparentType = getApparentType(type);
|
||||
if (apparentType === unknownType) {
|
||||
// Another error has already been reported
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
// If the expression is a class of abstract type, then it cannot be instantiated.
|
||||
// Note, only class declarations can be declared abstract.
|
||||
// In the case of a merged class-module or class-interface declaration,
|
||||
// only the class declaration node will have the Abstract flag set.
|
||||
const valueDecl = expressionType.symbol && getClassLikeDeclarationOfSymbol(expressionType.symbol);
|
||||
const valueDecl = apparentType.symbol && getClassLikeDeclarationOfSymbol(apparentType.symbol);
|
||||
if (valueDecl && getModifierFlags(valueDecl) & ModifierFlags.Abstract) {
|
||||
error(node, Diagnostics.Cannot_create_an_instance_of_the_abstract_class_0, declarationNameToString(valueDecl.name));
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
// TS 1.0 spec: 4.11
|
||||
// If expressionType is of type Any, Args can be any argument
|
||||
// list and the result of the operation is of type Any.
|
||||
if (isTypeAny(expressionType)) {
|
||||
if (isTypeAny(apparentType)) {
|
||||
if (node.typeArguments) {
|
||||
error(node, Diagnostics.Untyped_function_calls_may_not_accept_type_arguments);
|
||||
}
|
||||
return resolveUntypedCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
// Technically, this signatures list may be incomplete. We are taking the apparent type,
|
||||
// but we are not including construct signatures that may have been added to the Object or
|
||||
// Function interface, since they have none by default. This is a bit of a leap of faith
|
||||
// that the user will not add any.
|
||||
const constructSignatures = getSignaturesOfType(expressionType, SignatureKind.Construct);
|
||||
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
|
||||
if (constructSignatures.length) {
|
||||
if (!isConstructorAccessible(node, constructSignatures[0])) {
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
return resolveCall(node, constructSignatures, /*partialSignaturesOutArray*/ undefined, candidatesOutArray);
|
||||
|
||||
const propagatingType = propagateNull ? getTypeWithFacts(funcType, TypeFacts.EQUndefinedOrNull) : neverType;
|
||||
return resolveCall(node, constructSignatures, candidatesOutArray, propagatingType);
|
||||
}
|
||||
|
||||
// If expressionType's apparent type is an object type with no construct signatures but
|
||||
// one or more call signatures, the expression is processed as a function call. A compile-time
|
||||
// error occurs if the result of the function call is not Void. The type of the result of the
|
||||
// operation is Any. It is an error to have a Void this type.
|
||||
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
|
||||
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
if (callSignatures.length) {
|
||||
const signature = resolveCall(node, callSignatures, /*partialSignaturesOutArray*/ undefined, candidatesOutArray);
|
||||
const signature = resolveCall(node, callSignatures, candidatesOutArray);
|
||||
if (getReturnTypeOfSignature(signature) !== voidType) {
|
||||
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
|
||||
}
|
||||
@ -13357,7 +13459,7 @@ namespace ts {
|
||||
}
|
||||
|
||||
error(node, Diagnostics.Cannot_use_new_with_an_expression_whose_type_lacks_a_call_or_construct_signature);
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
function isConstructorAccessible(node: NewExpression, signature: Signature) {
|
||||
@ -13408,22 +13510,22 @@ namespace ts {
|
||||
|
||||
if (apparentType === unknownType) {
|
||||
// Another error has already been reported
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
|
||||
|
||||
if (isUntypedFunctionCall(tagType, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
if (!callSignatures.length) {
|
||||
error(node, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
return resolveCall(node, callSignatures, /*partialSignaturesOutArray*/ undefined, candidatesOutArray);
|
||||
return resolveCall(node, callSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -13455,13 +13557,13 @@ namespace ts {
|
||||
const funcType = checkExpression(node.expression);
|
||||
const apparentType = getApparentType(funcType);
|
||||
if (apparentType === unknownType) {
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
|
||||
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
const headMessage = getDiagnosticHeadMessageForDecoratorResolution(node);
|
||||
@ -13470,62 +13572,69 @@ namespace ts {
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, Diagnostics.Cannot_invoke_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
errorInfo = chainDiagnosticMessages(errorInfo, headMessage);
|
||||
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
return resolveCall(node, callSignatures, /*partialSignaturesOutArray*/ undefined, candidatesOutArray, headMessage);
|
||||
return resolveCall(node, callSignatures, candidatesOutArray, /*propagatingType*/ undefined, headMessage);
|
||||
}
|
||||
|
||||
function resolvePipelineExpression(node: PipelineExpression, candidatesOutArray: Signature[]): Signature {
|
||||
const funcType = checkExpression(node.right);
|
||||
const apparentType = getApparentType(funcType);
|
||||
const type = isPartialApplication(node.right)
|
||||
? checkNonNullExpression(node.right.expression)
|
||||
: checkNonNullExpression(node.right);
|
||||
|
||||
const apparentType = getApparentType(type);
|
||||
if (apparentType === unknownType) {
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
|
||||
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
if (isUntypedFunctionCall(type, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
if (!callSignatures.length) {
|
||||
return resolveErrorCall(node, /*partialSignaturesOutArray*/ undefined);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
return resolveCall(node, callSignatures, /*partialSignaturesOutArray*/ undefined, candidatesOutArray);
|
||||
return resolveCall(node, callSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
function resolveBindExpression(node: BindExpression | BindToExpression, partialSignaturesOutArray: Signature[], candidatesOutArray?: Signature[]): Signature {
|
||||
const funcType = checkExpression(node.expression);
|
||||
const apparentType = getApparentType(funcType);
|
||||
function resolveBindExpression(node: BindExpression | BindToExpression, candidatesOutArray?: Signature[]): Signature {
|
||||
const type = checkNonNullExpression(node.expression);
|
||||
if (type === silentNeverType) {
|
||||
return silentNeverSignature;
|
||||
}
|
||||
|
||||
const apparentType = getApparentType(type);
|
||||
if (apparentType === unknownType) {
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
const callSignatures = getSignaturesOfType(apparentType, SignatureKind.Call);
|
||||
const constructSignatures = getSignaturesOfType(apparentType, SignatureKind.Construct);
|
||||
if (isUntypedFunctionCall(funcType, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node, partialSignaturesOutArray);
|
||||
if (isUntypedFunctionCall(type, apparentType, callSignatures.length, constructSignatures.length)) {
|
||||
return resolveUntypedCall(node);
|
||||
}
|
||||
|
||||
if (!callSignatures.length) {
|
||||
if (constructSignatures.length) {
|
||||
error(node.expression, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(funcType));
|
||||
error(node.expression, Diagnostics.Value_of_type_0_is_not_callable_Did_you_mean_to_include_new, typeToString(type));
|
||||
}
|
||||
else {
|
||||
error(node.expression, Diagnostics.Cannot_bind_an_expression_whose_type_lacks_a_call_signature_Type_0_has_no_compatible_call_signatures, typeToString(apparentType));
|
||||
}
|
||||
return resolveErrorCall(node, partialSignaturesOutArray);
|
||||
return resolveErrorCall(node);
|
||||
}
|
||||
|
||||
return resolveCall(node, callSignatures, partialSignaturesOutArray, candidatesOutArray);
|
||||
return resolveCall(node, callSignatures, candidatesOutArray);
|
||||
}
|
||||
|
||||
function resolveSignature(node: CallLikeExpression, partialSignaturesOutArray: Signature[], candidatesOutArray?: Signature[]): Signature {
|
||||
function resolveSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.CallExpression:
|
||||
return resolveCallExpression(node, partialSignaturesOutArray, candidatesOutArray);
|
||||
return resolveCallExpression(node, candidatesOutArray);
|
||||
case SyntaxKind.NewExpression:
|
||||
return resolveNewExpression(node, candidatesOutArray);
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
@ -13536,7 +13645,7 @@ namespace ts {
|
||||
return resolvePipelineExpression(node, candidatesOutArray);
|
||||
case SyntaxKind.BindExpression:
|
||||
case SyntaxKind.BindToExpression:
|
||||
return resolveBindExpression(node, partialSignaturesOutArray, candidatesOutArray);
|
||||
return resolveBindExpression(node, candidatesOutArray);
|
||||
}
|
||||
Debug.fail("Branch in 'resolveSignature' should be unreachable.");
|
||||
}
|
||||
@ -13554,7 +13663,7 @@ namespace ts {
|
||||
return cached;
|
||||
}
|
||||
links.resolvedSignature = resolvingSignature;
|
||||
const result = resolveSignature(node, /*partialSignaturesOutArray*/ undefined, candidatesOutArray);
|
||||
const result = resolveSignature(node, candidatesOutArray);
|
||||
// If signature resolution originated in control flow type analysis (for example to compute the
|
||||
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
|
||||
// types from the control flow analysis.
|
||||
@ -13562,26 +13671,6 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function getResolvedPartialSignatures(node: CallLikeExpression): Signature[] {
|
||||
const links = getNodeLinks(node);
|
||||
// If getResolvedSignature has already been called, we will have cached the resolvedSignature.
|
||||
// However, it is possible that either candidatesOutArray was not passed in the first time,
|
||||
// or that a different candidatesOutArray was passed in. Therefore, we need to redo the work
|
||||
// to correctly fill the candidatesOutArray.
|
||||
const cached = links.resolvedPartialSignatures;
|
||||
if (cached && cached !== resolvingPartialSignatures) {
|
||||
return cached;
|
||||
}
|
||||
links.resolvedPartialSignatures = resolvingPartialSignatures;
|
||||
const partialSignatures: Signature[] = [];
|
||||
resolveSignature(node, partialSignatures);
|
||||
// If signature resolution originated in control flow type analysis (for example to compute the
|
||||
// assigned type in a flow assignment) we don't cache the result as it may be based on temporary
|
||||
// types from the control flow analysis.
|
||||
links.resolvedPartialSignatures = flowLoopStart === flowLoopCount ? partialSignatures : cached;
|
||||
return partialSignatures;
|
||||
}
|
||||
|
||||
function getResolvedOrAnySignature(node: CallLikeExpression) {
|
||||
// If we're already in the process of resolving the given signature, don't resolve again as
|
||||
// that could cause infinite recursion. Instead, return anySignature.
|
||||
@ -13605,9 +13694,7 @@ namespace ts {
|
||||
// Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true
|
||||
checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
|
||||
|
||||
const partialApplication = node.kind === SyntaxKind.CallExpression && forEach(node.arguments, isPositionalOrPositionalSpreadElement);
|
||||
const signatures = partialApplication && getResolvedPartialSignatures(node);
|
||||
const signature = !partialApplication && getResolvedSignature(node);
|
||||
const signature = getResolvedSignature(node);
|
||||
|
||||
if (node.expression.kind === SyntaxKind.SuperKeyword) {
|
||||
return voidType;
|
||||
@ -13645,9 +13732,7 @@ namespace ts {
|
||||
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
|
||||
}
|
||||
|
||||
return partialApplication ?
|
||||
getPartialApplicationOfSignatures(node.arguments, signatures) :
|
||||
getReturnTypeOfSignature(signature);
|
||||
return getReturnTypeOfSignature(signature);
|
||||
}
|
||||
|
||||
function getPartialApplicationOfSignatures(argumentList: Expression[], signatures: Signature[]) {
|
||||
@ -13655,13 +13740,7 @@ namespace ts {
|
||||
for (const signature of signatures) {
|
||||
partialSignatures.push(getPartialApplicationOfSignature(argumentList, signature));
|
||||
}
|
||||
|
||||
const partialType = createObjectType(ObjectFlags.Anonymous);
|
||||
(<ResolvedType>partialType).members = emptySymbols;
|
||||
(<ResolvedType>partialType).properties = emptyArray;
|
||||
(<ResolvedType>partialType).callSignatures = partialSignatures;
|
||||
(<ResolvedType>partialType).constructSignatures = emptyArray;
|
||||
return partialType;
|
||||
return createTypeFromSignatures(partialSignatures);
|
||||
}
|
||||
|
||||
function getPartialApplicationOfSignature(argumentList: Expression[], signature: Signature) {
|
||||
@ -13670,12 +13749,11 @@ namespace ts {
|
||||
uniqueParameterNames[parameter.name] = true;
|
||||
}
|
||||
|
||||
let positionalParameters: TransientSymbol[];
|
||||
const positionalParameters: TransientSymbol[] = [];
|
||||
let positionalRestParameter: TransientSymbol;
|
||||
let position = 0;
|
||||
for (let i = 0; i < argumentList.length; i++) {
|
||||
const argument = argumentList[i];
|
||||
// const inRestParameter = signature.hasRestParameter && i >= signature.parameters.length;
|
||||
const parameter = i < signature.parameters.length ? signature.parameters[i] : lastOrUndefined(signature.parameters);
|
||||
if (isPositionalElement(argument)) {
|
||||
let ordinalPosition: number;
|
||||
@ -13686,9 +13764,7 @@ namespace ts {
|
||||
ordinalPosition = position;
|
||||
position++;
|
||||
}
|
||||
if (!positionalParameters) {
|
||||
positionalParameters = [];
|
||||
}
|
||||
|
||||
const type = getTypeAtPosition(signature, i);
|
||||
const previousParameter = positionalParameters[ordinalPosition];
|
||||
if (previousParameter) {
|
||||
@ -13697,17 +13773,14 @@ namespace ts {
|
||||
}
|
||||
previousParameter.type = getIntersectionType([previousParameter.type, type]);
|
||||
}
|
||||
else if (parameter) {
|
||||
const sym = createTransientSymbol(parameter, type);
|
||||
if (sym)
|
||||
positionalParameters[ordinalPosition] = createTransientSymbol(parameter, type);
|
||||
}
|
||||
else {
|
||||
// TODO(rbuckton): implicit any error?
|
||||
const name = getUniqueName(uniqueParameterNames, `arg${ordinalPosition}`);
|
||||
const newParameter = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
|
||||
newParameter.type = type;
|
||||
positionalParameters[ordinalPosition] = newParameter;
|
||||
const name = i < signature.parameters.length - (signature.hasRestParameter ? 1 : 0) ?
|
||||
parameter.name :
|
||||
getUniqueName(uniqueParameterNames, parameter ? parameter.name : `arg${ordinalPosition}`);
|
||||
positionalParameters[ordinalPosition] = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
|
||||
positionalParameters[ordinalPosition].target = parameter;
|
||||
positionalParameters[ordinalPosition].type = type;
|
||||
positionalParameters[ordinalPosition].transientSymbolIsRest = false;
|
||||
}
|
||||
}
|
||||
else if (isPositionalSpreadElement(argument)) {
|
||||
@ -13718,28 +13791,26 @@ namespace ts {
|
||||
}
|
||||
positionalRestParameter.type = getIntersectionType([positionalRestParameter.type, type]);
|
||||
}
|
||||
else if (parameter) {
|
||||
positionalRestParameter = createTransientSymbol(parameter, type);
|
||||
positionalRestParameter.transientSymbolIsRest = true;
|
||||
}
|
||||
else {
|
||||
// TODO(rbuckton): implicit any error?
|
||||
const name = getUniqueName(uniqueParameterNames, `args`);
|
||||
const name = parameter ? parameter.name : getUniqueName(uniqueParameterNames, `args`);
|
||||
positionalRestParameter = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
|
||||
positionalRestParameter.target = parameter;
|
||||
positionalRestParameter.type = type;
|
||||
positionalRestParameter.transientSymbolIsRest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
positionalParameters = append(positionalParameters, positionalRestParameter) || [];
|
||||
if (positionalRestParameter) {
|
||||
positionalParameters.push(positionalRestParameter);
|
||||
}
|
||||
|
||||
for (let i = 0; i < positionalParameters.length; i++) {
|
||||
if (!positionalParameters[i]) {
|
||||
const name = getUniqueName(uniqueParameterNames, `arg${i}`);
|
||||
// TODO(rbuckton): implicit any error
|
||||
positionalParameters[i] = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
|
||||
positionalParameters[i].type = anyType;
|
||||
// TODO(rbuckton): implicit any error
|
||||
}
|
||||
}
|
||||
|
||||
@ -13759,7 +13830,7 @@ namespace ts {
|
||||
let uniqueName = name;
|
||||
let index = 0;
|
||||
while (uniqueNames[uniqueName]) {
|
||||
uniqueName = `${name}_${index}`;
|
||||
uniqueName = `${name}${index}`;
|
||||
index++;
|
||||
}
|
||||
uniqueNames[uniqueName] = true;
|
||||
@ -15000,6 +15071,10 @@ namespace ts {
|
||||
return getTypeFacts(leftType) & TypeFacts.Truthy ?
|
||||
includeFalsyTypes(rightType, getFalsyFlags(strictNullChecks ? leftType : getBaseTypeOfLiteralType(rightType))) :
|
||||
leftType;
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
return getTypeFacts(leftType) & TypeFacts.EQUndefinedOrNull ?
|
||||
getBestChoiceType(getNonNullableType(leftType), rightType) :
|
||||
leftType;
|
||||
case SyntaxKind.BarBarToken:
|
||||
return getTypeFacts(leftType) & TypeFacts.Falsy ?
|
||||
getBestChoiceType(removeDefinitelyFalsyTypes(leftType), rightType) :
|
||||
|
||||
@ -1037,12 +1037,13 @@ namespace ts {
|
||||
}
|
||||
|
||||
function emitPropertyAccessExpression(node: PropertyAccessExpression) {
|
||||
const propagatesNull = node.flags & NodeFlags.PropagateNull;
|
||||
let indentBeforeDot = false;
|
||||
let indentAfterDot = false;
|
||||
if (!(getEmitFlags(node) & EmitFlags.NoIndentation)) {
|
||||
const dotRangeStart = node.expression.end;
|
||||
const dotRangeEnd = skipTrivia(currentText, node.expression.end) + 1;
|
||||
const dotToken = <Node>{ kind: SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd };
|
||||
const dotRangeEnd = skipTrivia(currentText, node.expression.end) + (propagatesNull ? 2 : 1);
|
||||
const dotToken = <Node>{ kind: propagatesNull ? SyntaxKind.QuestionDotToken : SyntaxKind.DotToken, pos: dotRangeStart, end: dotRangeEnd };
|
||||
indentBeforeDot = needsIndentation(node, node.expression, dotToken);
|
||||
indentAfterDot = needsIndentation(node, dotToken, node.name);
|
||||
}
|
||||
@ -1050,8 +1051,8 @@ namespace ts {
|
||||
emitExpression(node.expression);
|
||||
increaseIndentIf(indentBeforeDot);
|
||||
|
||||
const shouldEmitDotDot = !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
write(shouldEmitDotDot ? ".." : ".");
|
||||
const shouldEmitDotDot = !propagatesNull && !indentBeforeDot && needsDotDotForPropertyAccess(node.expression);
|
||||
write(shouldEmitDotDot ? ".." : propagatesNull ? "?." : ".");
|
||||
|
||||
increaseIndentIf(indentAfterDot);
|
||||
emit(node.name);
|
||||
@ -1078,25 +1079,28 @@ namespace ts {
|
||||
|
||||
function emitElementAccessExpression(node: ElementAccessExpression) {
|
||||
emitExpression(node.expression);
|
||||
write("[");
|
||||
write(node.flags & NodeFlags.PropagateNull ? "?.[" : "[");
|
||||
emitExpression(node.argumentExpression);
|
||||
write("]");
|
||||
}
|
||||
|
||||
function emitBindToExpression(node: BindToExpression) {
|
||||
emitExpression(node.targetExpression);
|
||||
write("::");
|
||||
write(node.flags & NodeFlags.PropagateNull ? "?::" : "::");
|
||||
emitExpression(node.expression);
|
||||
}
|
||||
|
||||
function emitBindExpression(node: BindExpression) {
|
||||
write("::");
|
||||
write(node.flags & NodeFlags.PropagateNull ? "?::" : "::");
|
||||
emitExpression(node.expression);
|
||||
}
|
||||
|
||||
function emitCallExpression(node: CallExpression) {
|
||||
emitExpression(node.expression);
|
||||
emitTypeArguments(node, node.typeArguments);
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
write("?.");
|
||||
}
|
||||
emitExpressionList(node, node.arguments, ListFormat.CallExpressionArguments);
|
||||
}
|
||||
|
||||
@ -1104,6 +1108,9 @@ namespace ts {
|
||||
write("new ");
|
||||
emitExpression(node.expression);
|
||||
emitTypeArguments(node, node.typeArguments);
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
write("?.");
|
||||
}
|
||||
emitExpressionList(node, node.arguments, ListFormat.NewExpressionArguments);
|
||||
}
|
||||
|
||||
@ -1119,7 +1126,6 @@ namespace ts {
|
||||
emit(node.type);
|
||||
write(">");
|
||||
}
|
||||
|
||||
emitExpression(node.expression);
|
||||
}
|
||||
|
||||
|
||||
@ -437,8 +437,8 @@ namespace ts {
|
||||
return node;
|
||||
}
|
||||
|
||||
export function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange) {
|
||||
const node = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, location);
|
||||
export function createElementAccess(expression: Expression, index: number | Expression, location?: TextRange, flags?: NodeFlags) {
|
||||
const node = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, location, flags);
|
||||
node.expression = parenthesizeForAccess(expression);
|
||||
node.argumentExpression = typeof index === "number" ? createLiteral(index) : index;
|
||||
return node;
|
||||
@ -446,7 +446,7 @@ namespace ts {
|
||||
|
||||
export function updateElementAccess(node: ElementAccessExpression, expression: Expression, argumentExpression: Expression) {
|
||||
if (node.expression !== expression || node.argumentExpression !== argumentExpression) {
|
||||
return updateNode(createElementAccess(expression, argumentExpression, node), node);
|
||||
return updateNode(createElementAccess(expression, argumentExpression, /*location*/ node, node.flags), node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@ -653,16 +653,16 @@ namespace ts {
|
||||
if (whenFalse) {
|
||||
// second overload
|
||||
node.questionToken = <QuestionToken>questionTokenOrWhenTrue;
|
||||
node.whenTrue = whenTrueOrWhenFalse;
|
||||
node.whenTrue = parenthesizeForConditionalResult(whenTrueOrWhenFalse);
|
||||
node.colonToken = <ColonToken>colonTokenOrLocation;
|
||||
node.whenFalse = whenFalse;
|
||||
node.whenFalse = parenthesizeForConditionalResult(whenFalse);
|
||||
}
|
||||
else {
|
||||
// first overload
|
||||
node.questionToken = createToken(SyntaxKind.QuestionToken);
|
||||
node.whenTrue = <Expression>questionTokenOrWhenTrue;
|
||||
node.whenTrue = parenthesizeForConditionalResult(<Expression>questionTokenOrWhenTrue);
|
||||
node.colonToken = createToken(SyntaxKind.ColonToken);
|
||||
node.whenFalse = whenTrueOrWhenFalse;
|
||||
node.whenFalse = parenthesizeForConditionalResult(whenTrueOrWhenFalse);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
@ -1561,10 +1561,18 @@ namespace ts {
|
||||
return createBinary(left, SyntaxKind.EqualsEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createEquality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.EqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createStrictInequality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.ExclamationEqualsEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createInequality(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.ExclamationEqualsToken, right);
|
||||
}
|
||||
|
||||
export function createAdd(left: Expression, right: Expression) {
|
||||
return createBinary(left, SyntaxKind.PlusToken, right);
|
||||
}
|
||||
@ -2392,6 +2400,16 @@ namespace ts {
|
||||
return condition;
|
||||
}
|
||||
|
||||
export function parenthesizeForConditionalResult(expression: Expression) {
|
||||
const conditionalPrecedence = getOperatorPrecedence(SyntaxKind.ConditionalExpression, SyntaxKind.ColonToken);
|
||||
const emittedExpression = skipPartiallyEmittedExpressions(expression);
|
||||
const expressionPrecedence = getExpressionPrecedence(emittedExpression);
|
||||
if (compareValues(expressionPrecedence, conditionalPrecedence) === Comparison.LessThan) {
|
||||
return createParen(expression);
|
||||
}
|
||||
return expression;
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps an expression in parentheses if it is needed in order to use the expression
|
||||
* as the expression of a NewExpression node.
|
||||
|
||||
@ -209,6 +209,8 @@ namespace ts {
|
||||
visitNode(cbNode, (<ConditionalExpression>node).whenTrue) ||
|
||||
visitNode(cbNode, (<ConditionalExpression>node).colonToken) ||
|
||||
visitNode(cbNode, (<ConditionalExpression>node).whenFalse);
|
||||
case SyntaxKind.PositionalElement:
|
||||
return visitNode(cbNode, (<PositionalElement>node).literal);
|
||||
case SyntaxKind.SpreadElement:
|
||||
return visitNode(cbNode, (<SpreadElement>node).expression);
|
||||
case SyntaxKind.Block:
|
||||
@ -3373,6 +3375,7 @@ namespace ts {
|
||||
switch (token()) {
|
||||
case SyntaxKind.BarGreaterThanToken:
|
||||
return 1;
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
case SyntaxKind.BarBarToken:
|
||||
return 2;
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
@ -3745,7 +3748,11 @@ namespace ts {
|
||||
|
||||
function parseSuperExpression(): MemberExpression {
|
||||
const expression = parseTokenNode<PrimaryExpression>();
|
||||
if (token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.DotToken || token() === SyntaxKind.OpenBracketToken) {
|
||||
if (token() === SyntaxKind.OpenParenToken ||
|
||||
token() === SyntaxKind.DotToken ||
|
||||
token() === SyntaxKind.OpenBracketToken ||
|
||||
token() === SyntaxKind.QuestionDotToken ||
|
||||
token() === SyntaxKind.QuestionDotOpenBracketToken) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
@ -3996,9 +4003,12 @@ namespace ts {
|
||||
|
||||
function parseMemberExpressionRest(expression: LeftHandSideExpression): MemberExpression {
|
||||
while (true) {
|
||||
const dotToken = parseOptionalToken(SyntaxKind.DotToken);
|
||||
if (dotToken) {
|
||||
if (token() === SyntaxKind.DotToken || token() === SyntaxKind.QuestionDotToken) {
|
||||
const propertyAccess = <PropertyAccessExpression>createNode(SyntaxKind.PropertyAccessExpression, expression.pos);
|
||||
if (token() === SyntaxKind.QuestionDotToken) {
|
||||
propertyAccess.flags |= NodeFlags.PropagateNull;
|
||||
}
|
||||
nextToken();
|
||||
propertyAccess.expression = expression;
|
||||
propertyAccess.name = parseRightSideOfDot(/*allowIdentifierNames*/ true);
|
||||
expression = finishNode(propertyAccess);
|
||||
@ -4014,8 +4024,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
// when in the [Decorator] context, we do not parse ElementAccess as it could be part of a ComputedPropertyName
|
||||
if (!inDecoratorContext() && parseOptional(SyntaxKind.OpenBracketToken)) {
|
||||
if (!inDecoratorContext() && (token() === SyntaxKind.OpenBracketToken || token() === SyntaxKind.QuestionDotOpenBracketToken)) {
|
||||
const indexedAccess = <ElementAccessExpression>createNode(SyntaxKind.ElementAccessExpression, expression.pos);
|
||||
if (token() === SyntaxKind.QuestionDotOpenBracketToken) {
|
||||
indexedAccess.flags |= NodeFlags.PropagateNull;
|
||||
}
|
||||
nextToken();
|
||||
indexedAccess.expression = expression;
|
||||
|
||||
// It's not uncommon for a user to write: "new Type[]".
|
||||
@ -4043,8 +4057,9 @@ namespace ts {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (parseOptional(SyntaxKind.ColonColonToken)) {
|
||||
if (token() === SyntaxKind.ColonColonToken) {
|
||||
const bindExpression = <BindToExpression>createNode(SyntaxKind.BindToExpression, expression.pos);
|
||||
nextToken();
|
||||
bindExpression.targetExpression = expression;
|
||||
bindExpression.expression = parseMemberExpressionOrHigher();
|
||||
expression = finishNode(bindExpression);
|
||||
@ -4058,37 +4073,35 @@ namespace ts {
|
||||
function parseCallExpressionRest(expression: LeftHandSideExpression): LeftHandSideExpression {
|
||||
while (true) {
|
||||
expression = parseMemberExpressionRest(expression);
|
||||
let typeArguments: NodeArray<TypeNode>;
|
||||
if (token() === SyntaxKind.LessThanToken) {
|
||||
// See if this is the start of a generic invocation. If so, consume it and
|
||||
// keep checking for postfix expressions. Otherwise, it's just a '<' that's
|
||||
// part of an arithmetic expression. Break out so we consume it higher in the
|
||||
// stack.
|
||||
const typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
if (!typeArguments) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
|
||||
callExpr.expression = expression;
|
||||
callExpr.typeArguments = typeArguments;
|
||||
callExpr.arguments = parseArgumentList();
|
||||
expression = finishNode(callExpr);
|
||||
continue;
|
||||
}
|
||||
else if (token() === SyntaxKind.OpenParenToken) {
|
||||
const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
|
||||
callExpr.expression = expression;
|
||||
callExpr.arguments = parseArgumentList();
|
||||
expression = finishNode(callExpr);
|
||||
continue;
|
||||
else if (token() !== SyntaxKind.OpenParenToken && token() !== SyntaxKind.QuestionDotOpenParenToken) {
|
||||
return expression;
|
||||
}
|
||||
|
||||
return expression;
|
||||
const callExpr = <CallExpression>createNode(SyntaxKind.CallExpression, expression.pos);
|
||||
if (token() === SyntaxKind.QuestionDotOpenParenToken) {
|
||||
callExpr.flags |= NodeFlags.PropagateNull;
|
||||
}
|
||||
callExpr.expression = expression;
|
||||
callExpr.typeArguments = typeArguments;
|
||||
callExpr.arguments = parseArgumentList();
|
||||
expression = finishNode(callExpr);
|
||||
}
|
||||
}
|
||||
|
||||
function parseArgumentList() {
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
if (!parseOptional(SyntaxKind.QuestionDotOpenParenToken)) {
|
||||
parseExpected(SyntaxKind.OpenParenToken);
|
||||
}
|
||||
const result = parseDelimitedList(ParsingContext.ArgumentExpressions, parseArgumentExpression);
|
||||
parseExpected(SyntaxKind.CloseParenToken);
|
||||
return result;
|
||||
@ -4115,6 +4128,7 @@ namespace ts {
|
||||
function canFollowTypeArgumentsInExpression(): boolean {
|
||||
switch (token()) {
|
||||
case SyntaxKind.OpenParenToken: // foo<x>(
|
||||
case SyntaxKind.QuestionDotOpenParenToken: // foo<x>?.(
|
||||
// this case are the only case where this token can legally follow a type argument
|
||||
// list. So we definitely want to treat this as a type arg list.
|
||||
|
||||
@ -4437,7 +4451,10 @@ namespace ts {
|
||||
parseExpected(SyntaxKind.NewKeyword);
|
||||
node.expression = parseMemberExpressionOrHigher();
|
||||
node.typeArguments = tryParse(parseTypeArgumentsInExpression);
|
||||
if (node.typeArguments || token() === SyntaxKind.OpenParenToken) {
|
||||
if (node.typeArguments || token() === SyntaxKind.OpenParenToken || token() === SyntaxKind.QuestionDotOpenParenToken) {
|
||||
if (token() === SyntaxKind.QuestionDotOpenParenToken) {
|
||||
node.flags |= NodeFlags.PropagateNull;
|
||||
}
|
||||
node.arguments = parseArgumentList();
|
||||
}
|
||||
|
||||
|
||||
@ -170,6 +170,10 @@ namespace ts {
|
||||
"&&": SyntaxKind.AmpersandAmpersandToken,
|
||||
"||": SyntaxKind.BarBarToken,
|
||||
"?": SyntaxKind.QuestionToken,
|
||||
"??": SyntaxKind.QuestionQuestionToken,
|
||||
"?.": SyntaxKind.QuestionDotToken,
|
||||
"?.[": SyntaxKind.QuestionDotOpenBracketToken,
|
||||
"?.(": SyntaxKind.QuestionDotOpenParenToken,
|
||||
":": SyntaxKind.ColonToken,
|
||||
"::": SyntaxKind.ColonColonToken,
|
||||
"=": SyntaxKind.EqualsToken,
|
||||
@ -1550,6 +1554,20 @@ namespace ts {
|
||||
pos++;
|
||||
return token = SyntaxKind.GreaterThanToken;
|
||||
case CharacterCodes.question:
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.question) {
|
||||
return pos += 2, token = SyntaxKind.QuestionQuestionToken;
|
||||
}
|
||||
if (text.charCodeAt(pos + 1) === CharacterCodes.dot) {
|
||||
if (text.charCodeAt(pos + 2) === CharacterCodes.openParen) {
|
||||
return pos += 3, token = SyntaxKind.QuestionDotOpenParenToken;
|
||||
}
|
||||
if (text.charCodeAt(pos + 2) === CharacterCodes.openBracket) {
|
||||
return pos += 3, token = SyntaxKind.QuestionDotOpenBracketToken;
|
||||
}
|
||||
if (!isDigit(text.charCodeAt(pos + 2))) {
|
||||
return pos += 2, token = SyntaxKind.QuestionDotToken;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
return token = SyntaxKind.QuestionToken;
|
||||
case CharacterCodes.openBracket:
|
||||
|
||||
@ -69,12 +69,18 @@ namespace ts {
|
||||
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
|
||||
case SyntaxKind.CallExpression:
|
||||
return visitCallExpression(node as CallExpression);
|
||||
case SyntaxKind.NewExpression:
|
||||
return visitNewExpression(node as NewExpression);
|
||||
case SyntaxKind.OperatorExpression:
|
||||
return visitOperatorExpression(node as OperatorExpression);
|
||||
case SyntaxKind.BindExpression:
|
||||
return visitBindExpression(node as BindExpression);
|
||||
case SyntaxKind.BindToExpression:
|
||||
return visitBindToExpression(node as BindToExpression);
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
return visitPropertyAccess(node as PropertyAccessExpression);
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return visitElementAccess(node as ElementAccessExpression);
|
||||
default:
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
@ -159,28 +165,25 @@ namespace ts {
|
||||
visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression)
|
||||
);
|
||||
case SyntaxKind.BarGreaterThanToken:
|
||||
return transformPipelineExpression(node);
|
||||
return transformPipelineExpression(<PipelineExpression>node);
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
return transformCoalesceExpression(<CoalesceExpression>node);
|
||||
}
|
||||
return visitEachChild(node, visitor, context);
|
||||
}
|
||||
|
||||
function transformPipelineExpression(node: BinaryExpression) {
|
||||
function transformPipelineExpression(node: PipelineExpression) {
|
||||
const argumentList: Expression[] = [];
|
||||
let expression = node.left;
|
||||
if (expression.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
// comma expressions are right-deep
|
||||
expression = (<ParenthesizedExpression>expression).expression;
|
||||
while (expression.kind === SyntaxKind.BinaryExpression &&
|
||||
(<BinaryExpression>expression).operatorToken.kind === SyntaxKind.CommaToken) {
|
||||
argumentList.push(visitNode((<BinaryExpression>expression).left, visitor, isExpression));
|
||||
expression = (<BinaryExpression>expression).right;
|
||||
}
|
||||
if (node.left.kind === SyntaxKind.ParenthesizedExpression) {
|
||||
collectPipelineArguments((<ParenthesizedExpression>node.left).expression, argumentList);
|
||||
}
|
||||
else {
|
||||
argumentList.push(visitNode(node.left, visitor, isExpression));
|
||||
}
|
||||
argumentList.push(visitNode(expression, visitor, isExpression));
|
||||
const func = visitNode(node.right, visitor, isExpression);
|
||||
if (func.kind === SyntaxKind.ArrowFunction ||
|
||||
func.kind === SyntaxKind.FunctionExpression) {
|
||||
return createCall(func, /*typeArguments*/ undefined, argumentList);
|
||||
return createCall(func, /*typeArguments*/ undefined, argumentList, node);
|
||||
}
|
||||
else {
|
||||
const parameterList: ParameterDeclaration[] = [];
|
||||
@ -204,7 +207,38 @@ namespace ts {
|
||||
)
|
||||
),
|
||||
/*typeArguments*/ undefined,
|
||||
argumentList
|
||||
argumentList,
|
||||
node
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function collectPipelineArguments(node: Expression, argumentList: Expression[]) {
|
||||
if (isCommaExpression(node)) {
|
||||
collectPipelineArguments(node.left, argumentList);
|
||||
collectPipelineArguments(node.right, argumentList);
|
||||
}
|
||||
else {
|
||||
argumentList.push(visitNode(node, visitor, isExpression));
|
||||
}
|
||||
}
|
||||
|
||||
function transformCoalesceExpression(node: CoalesceExpression): Expression {
|
||||
const left = visitNode(node.left, visitor, isExpression);
|
||||
const right = visitNode(node.right, visitor, isExpression);
|
||||
if (isIdentifier(left)) {
|
||||
return createConditional(
|
||||
createInequality(left, createNull()),
|
||||
left,
|
||||
right
|
||||
);
|
||||
}
|
||||
else {
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
return createConditional(
|
||||
createInequality(createAssignment(temp, left), createNull()),
|
||||
temp,
|
||||
right
|
||||
);
|
||||
}
|
||||
}
|
||||
@ -442,65 +476,181 @@ namespace ts {
|
||||
return body;
|
||||
}
|
||||
|
||||
function propagateNull<T extends Node>(finishExpression: (node: T, nullableExpression: Expression) => Expression, node: T, nullableExpression: Expression): Expression;
|
||||
function propagateNull<T extends Node, U>(finishExpression: (node: T, nullableExpression: Expression, data: U) => Expression, node: T, nullableExpression: Expression, data: U): Expression;
|
||||
function propagateNull<T extends Node, U>(finishExpression: (node: T, nullableExpression: Expression, data: U) => Expression, node: T, nullableExpression: Expression, data?: U): Expression {
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
if (isIdentifier(nullableExpression)) {
|
||||
return createConditional(
|
||||
createEquality(nullableExpression, createNull()),
|
||||
nullableExpression,
|
||||
finishExpression(node, nullableExpression, data),
|
||||
node
|
||||
);
|
||||
}
|
||||
else {
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
return createConditional(
|
||||
createEquality(
|
||||
createAssignment(temp, nullableExpression),
|
||||
createNull()
|
||||
),
|
||||
temp,
|
||||
finishExpression(node, temp, data),
|
||||
node
|
||||
);
|
||||
}
|
||||
}
|
||||
return finishExpression(node, nullableExpression, data);
|
||||
}
|
||||
|
||||
function visitCallExpression(node: CallExpression): Expression {
|
||||
let expression = visitNode(node.expression, visitor, isExpression) as Expression;
|
||||
if (!forEach(node.arguments, isPositionalOrPositionalSpreadElement)) {
|
||||
return updateCall(
|
||||
node,
|
||||
expression,
|
||||
/*typeArguments*/ undefined,
|
||||
visitNodes(node.arguments, visitor, isExpression));
|
||||
return propagateNull(finishCallExpression, node, visitNode(node.expression, visitor, isExpression));
|
||||
}
|
||||
|
||||
function finishCallExpression(node: CallExpression, expression: Expression) {
|
||||
if (forEach(node.arguments, isPositionalOrPositionalSpreadElement)) {
|
||||
return transformPartialCallExpression(node, expression);
|
||||
}
|
||||
else {
|
||||
const expressionTemp = createTempVariable(hoistVariableDeclaration);
|
||||
const argumentList: Expression[] = [];
|
||||
const pendingExpressions: Expression[] = [createAssignment(expressionTemp, expression)];
|
||||
const positionalParameters: ParameterDeclaration[] = [];
|
||||
let positionalRestParameter: ParameterDeclaration;
|
||||
let position = 0;
|
||||
for (let i = 0; i < node.arguments.length; i++) {
|
||||
let argument = node.arguments[i];
|
||||
if (isPositionalElement(argument)) {
|
||||
if (argument.literal) {
|
||||
position = +argument.literal.text;
|
||||
}
|
||||
const parameter = positionalParameters[position] || (positionalParameters[position] = createParameter());
|
||||
argument = <Identifier>parameter.name;
|
||||
position++;
|
||||
}
|
||||
else if (isPositionalSpreadElement(argument)) {
|
||||
const parameter = positionalRestParameter || (positionalRestParameter = createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken)));
|
||||
argument = createSpreadElement(<Identifier>parameter.name);
|
||||
}
|
||||
else {
|
||||
argument = visitNode(argument, visitor, isExpression);
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
pendingExpressions.push(createAssignment(temp, isSpreadElement(argument) ? argument.expression : argument));
|
||||
argument = isSpreadElement(argument) ? createSpreadElement(temp) : temp;
|
||||
}
|
||||
argumentList.push(argument);
|
||||
}
|
||||
if (positionalRestParameter) {
|
||||
positionalParameters.push(positionalRestParameter);
|
||||
}
|
||||
for (let i = 0; i < positionalParameters.length; i++) {
|
||||
if (!positionalParameters[i]) {
|
||||
positionalParameters[i] = createParameter();
|
||||
}
|
||||
}
|
||||
pendingExpressions.push(
|
||||
createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
positionalParameters,
|
||||
/*type*/ undefined,
|
||||
/*equalsGreaterThanToken*/ createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
updateCall(node, expressionTemp, /*typeArguments*/ undefined, argumentList),
|
||||
/*location*/ node
|
||||
)
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
return setOriginalNode(
|
||||
createCall(
|
||||
expression,
|
||||
/*typeArguments*/ undefined,
|
||||
visitNodes(node.arguments, visitor, isExpression),
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
return inlineExpressions(pendingExpressions);
|
||||
}
|
||||
return updateCall(
|
||||
node,
|
||||
expression,
|
||||
/*typeArguments*/ undefined,
|
||||
visitNodes(node.arguments, visitor, isExpression),
|
||||
)
|
||||
}
|
||||
|
||||
function transformPartialCallExpression(node: CallExpression, expression: Expression) {
|
||||
const expressionTemp = createTempVariable(hoistVariableDeclaration);
|
||||
const argumentList: Expression[] = [];
|
||||
const pendingExpressions: Expression[] = [createAssignment(expressionTemp, expression)];
|
||||
const positionalParameters: ParameterDeclaration[] = [];
|
||||
let positionalRestParameter: ParameterDeclaration;
|
||||
let position = 0;
|
||||
for (let i = 0; i < node.arguments.length; i++) {
|
||||
let argument = node.arguments[i];
|
||||
if (isPositionalElement(argument)) {
|
||||
if (argument.literal) {
|
||||
position = +argument.literal.text;
|
||||
}
|
||||
const parameter = positionalParameters[position] || (positionalParameters[position] = createParameter());
|
||||
argument = <Identifier>parameter.name;
|
||||
position++;
|
||||
}
|
||||
else if (isPositionalSpreadElement(argument)) {
|
||||
const parameter = positionalRestParameter || (positionalRestParameter = createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken)));
|
||||
argument = createSpreadElement(<Identifier>parameter.name);
|
||||
}
|
||||
else {
|
||||
argument = visitNode(argument, visitor, isExpression);
|
||||
const temp = createTempVariable(hoistVariableDeclaration);
|
||||
pendingExpressions.push(createAssignment(temp, isSpreadElement(argument) ? argument.expression : argument));
|
||||
argument = isSpreadElement(argument) ? createSpreadElement(temp) : temp;
|
||||
}
|
||||
argumentList.push(argument);
|
||||
}
|
||||
if (positionalRestParameter) {
|
||||
positionalParameters.push(positionalRestParameter);
|
||||
}
|
||||
for (let i = 0; i < positionalParameters.length; i++) {
|
||||
if (!positionalParameters[i]) {
|
||||
positionalParameters[i] = createParameter();
|
||||
}
|
||||
}
|
||||
pendingExpressions.push(
|
||||
createArrowFunction(
|
||||
/*modifiers*/ undefined,
|
||||
/*typeParameters*/ undefined,
|
||||
positionalParameters,
|
||||
/*type*/ undefined,
|
||||
/*equalsGreaterThanToken*/ createToken(SyntaxKind.EqualsGreaterThanToken),
|
||||
setOriginalNode(
|
||||
createCall(expressionTemp, /*typeArguments*/ undefined, argumentList, node),
|
||||
node
|
||||
),
|
||||
/*location*/ node
|
||||
)
|
||||
);
|
||||
return inlineExpressions(pendingExpressions);
|
||||
}
|
||||
|
||||
function visitNewExpression(node: NewExpression): Expression {
|
||||
return propagateNull(finishNewExpression, node, visitNode(node.expression, visitor, isExpression));
|
||||
}
|
||||
|
||||
function finishNewExpression(node: NewExpression, expression: Expression) {
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
return setOriginalNode(
|
||||
createNew(
|
||||
expression,
|
||||
/*typeArguments*/ undefined,
|
||||
visitNodes(node.arguments, visitor, isExpression),
|
||||
/*location*/ node
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
return updateNew(
|
||||
node,
|
||||
expression,
|
||||
/*typeArguments*/ undefined,
|
||||
visitNodes(node.arguments, visitor, isExpression),
|
||||
);
|
||||
}
|
||||
|
||||
function visitPropertyAccess(node: PropertyAccessExpression): Expression {
|
||||
return propagateNull(finishPropertyAccess, node, visitNode(node.expression, visitor, isExpression));
|
||||
}
|
||||
|
||||
function finishPropertyAccess(node: PropertyAccessExpression, expression: Expression) {
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
return setOriginalNode(
|
||||
createPropertyAccess(
|
||||
expression,
|
||||
node.name,
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
return updatePropertyAccess(
|
||||
node,
|
||||
expression,
|
||||
node.name
|
||||
);
|
||||
}
|
||||
|
||||
function visitElementAccess(node: ElementAccessExpression): Expression {
|
||||
return propagateNull(finishElementAccess, node, visitNode(node.expression, visitor, isExpression));
|
||||
}
|
||||
|
||||
function finishElementAccess(node: ElementAccessExpression, expression: Expression) {
|
||||
if (node.flags & NodeFlags.PropagateNull) {
|
||||
return setOriginalNode(
|
||||
createElementAccess(
|
||||
expression,
|
||||
visitNode(node.argumentExpression, visitor, isExpression),
|
||||
node
|
||||
),
|
||||
node
|
||||
);
|
||||
}
|
||||
return updateElementAccess(
|
||||
node,
|
||||
expression,
|
||||
visitNode(node.argumentExpression, visitor, isExpression),
|
||||
);
|
||||
}
|
||||
|
||||
function visitOperatorExpression(node: OperatorExpression) {
|
||||
@ -551,37 +701,27 @@ namespace ts {
|
||||
if (operand.kind === SyntaxKind.PropertyAccessExpression
|
||||
|| operand.kind === SyntaxKind.ElementAccessExpression) {
|
||||
const { target, thisArg } = createCallBinding(operand, hoistVariableDeclaration);
|
||||
return createFunctionBind(
|
||||
target,
|
||||
thisArg,
|
||||
[],
|
||||
node
|
||||
)
|
||||
return createFunctionBind(target, thisArg, [], node);
|
||||
}
|
||||
else {
|
||||
return createFunctionBind(
|
||||
operand,
|
||||
createNull(),
|
||||
[],
|
||||
node
|
||||
);
|
||||
return createFunctionBind(operand, createNull(), [], node);
|
||||
}
|
||||
}
|
||||
|
||||
function visitBindToExpression(node: BindToExpression) {
|
||||
const targetExpression = visitNode(node.targetExpression, visitor, isExpression);
|
||||
const expression = visitNode(node.expression, visitor, isLeftHandSideExpression);
|
||||
if (isIdentifier(targetExpression)) {
|
||||
return createFunctionBind(expression, targetExpression, [], node);
|
||||
}
|
||||
const thisArg = createTempVariable(context.hoistVariableDeclaration);
|
||||
return createComma(
|
||||
createAssignment(
|
||||
thisArg,
|
||||
visitNode(node.targetExpression, visitor, isExpression),
|
||||
targetExpression,
|
||||
node.targetExpression
|
||||
),
|
||||
createFunctionBind(
|
||||
visitNode(node.expression, visitor, isLeftHandSideExpression),
|
||||
thisArg,
|
||||
[],
|
||||
node
|
||||
)
|
||||
createFunctionBind(expression, thisArg, [], node)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@ -53,7 +53,7 @@ namespace ts {
|
||||
TemplateMiddle,
|
||||
TemplateTail,
|
||||
// Punctuation
|
||||
OpenBraceToken,
|
||||
OpenBraceToken, // FirstPunctuation
|
||||
CloseBraceToken,
|
||||
OpenParenToken,
|
||||
CloseParenToken,
|
||||
@ -62,10 +62,21 @@ namespace ts {
|
||||
DotToken,
|
||||
DotDotDotToken,
|
||||
SemicolonToken,
|
||||
BarGreaterThanToken,
|
||||
CommaToken,
|
||||
EqualsGreaterThanToken,
|
||||
LessThanToken,
|
||||
QuestionDotToken,
|
||||
QuestionDotOpenBracketToken,
|
||||
QuestionDotOpenParenToken,
|
||||
QuestionToken,
|
||||
ColonToken,
|
||||
AtToken,
|
||||
PlusPlusToken, // FirstPrefixUnaryOperator, FirstPostfixUnaryOperator
|
||||
MinusMinusToken, // LastPostfixUnaryOperator
|
||||
ExclamationToken,
|
||||
TildeToken, // LastPrefixUnaryOperator
|
||||
TildePlusToken,
|
||||
TildeMinusToken,
|
||||
LessThanToken, // FirstBinaryOperator
|
||||
LessThanSlashToken,
|
||||
GreaterThanToken,
|
||||
LessThanEqualsToken,
|
||||
@ -80,27 +91,20 @@ namespace ts {
|
||||
AsteriskAsteriskToken,
|
||||
SlashToken,
|
||||
PercentToken,
|
||||
PlusPlusToken,
|
||||
MinusMinusToken,
|
||||
LessThanLessThanToken,
|
||||
GreaterThanGreaterThanToken,
|
||||
GreaterThanGreaterThanGreaterThanToken,
|
||||
AmpersandToken,
|
||||
BarToken,
|
||||
CaretToken,
|
||||
ExclamationToken,
|
||||
TildeToken,
|
||||
TildePlusToken,
|
||||
TildeMinusToken,
|
||||
AmpersandAmpersandToken,
|
||||
BarBarToken,
|
||||
QuestionToken,
|
||||
ColonToken,
|
||||
QuestionQuestionToken,
|
||||
ColonColonToken,
|
||||
AtToken,
|
||||
BarGreaterThanToken,
|
||||
// Assignments
|
||||
EqualsToken,
|
||||
PlusEqualsToken,
|
||||
EqualsToken, // FirstAssignment
|
||||
PlusEqualsToken, // FirstCompoundAssignment
|
||||
MinusEqualsToken,
|
||||
AsteriskEqualsToken,
|
||||
AsteriskAsteriskEqualsToken,
|
||||
@ -111,7 +115,7 @@ namespace ts {
|
||||
GreaterThanGreaterThanGreaterThanEqualsToken,
|
||||
AmpersandEqualsToken,
|
||||
BarEqualsToken,
|
||||
CaretEqualsToken,
|
||||
CaretEqualsToken, // LastAssignment, LastCompoundAssignment, LastBinaryOperator, LastPunctuation
|
||||
// Identifiers
|
||||
Identifier,
|
||||
// Reserved words
|
||||
@ -382,10 +386,6 @@ namespace ts {
|
||||
// Enum value count
|
||||
Count,
|
||||
// Markers
|
||||
FirstAssignment = EqualsToken,
|
||||
LastAssignment = CaretEqualsToken,
|
||||
FirstCompoundAssignment = PlusEqualsToken,
|
||||
LastCompoundAssignment = CaretEqualsToken,
|
||||
FirstReservedWord = BreakKeyword,
|
||||
LastReservedWord = WithKeyword,
|
||||
FirstKeyword = BreakKeyword,
|
||||
@ -394,6 +394,16 @@ namespace ts {
|
||||
LastFutureReservedWord = YieldKeyword,
|
||||
FirstTypeNode = TypePredicate,
|
||||
LastTypeNode = LiteralType,
|
||||
FirstAssignment = EqualsToken,
|
||||
LastAssignment = CaretEqualsToken,
|
||||
FirstCompoundAssignment = PlusEqualsToken,
|
||||
LastCompoundAssignment = CaretEqualsToken,
|
||||
FirstPrefixUnaryOperator = PlusPlusToken,
|
||||
LastPrefixUnaryOperator = TildeToken,
|
||||
FirstPostfixUnaryOperator = PlusPlusToken,
|
||||
LastPostfixUnaryOperator = MinusMinusToken,
|
||||
FirstBinaryOperator = LessThanToken,
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstPunctuation = OpenBraceToken,
|
||||
LastPunctuation = CaretEqualsToken,
|
||||
FirstToken = Unknown,
|
||||
@ -404,8 +414,6 @@ namespace ts {
|
||||
LastLiteralToken = NoSubstitutionTemplateLiteral,
|
||||
FirstTemplateToken = NoSubstitutionTemplateLiteral,
|
||||
LastTemplateToken = TemplateTail,
|
||||
FirstBinaryOperator = LessThanToken,
|
||||
LastBinaryOperator = CaretEqualsToken,
|
||||
FirstNode = QualifiedName,
|
||||
FirstJSDocNode = JSDocTypeExpression,
|
||||
LastJSDocNode = JSDocLiteralType,
|
||||
@ -420,25 +428,26 @@ namespace ts {
|
||||
NestedNamespace = 1 << 2, // Namespace declaration
|
||||
Synthesized = 1 << 3, // Node was synthesized during transformation
|
||||
Namespace = 1 << 4, // Namespace declaration
|
||||
ExportContext = 1 << 5, // Export context (initialized by binding)
|
||||
ContainsThis = 1 << 6, // Interface contains references to "this"
|
||||
HasImplicitReturn = 1 << 7, // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
HasExplicitReturn = 1 << 8, // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
GlobalAugmentation = 1 << 9, // Set if module declaration is an augmentation for the global scope
|
||||
HasClassExtends = 1 << 10, // If the file has a non-ambient class with an extends clause in ES5 or lower (initialized by binding)
|
||||
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)
|
||||
HasSpreadAttribute = 1 << 14, // If the file as JSX spread attributes (initialized by binding)
|
||||
HasRestAttribute = 1 << 15, // If the file has object destructure elements
|
||||
DisallowInContext = 1 << 16, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 17, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 18, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 19, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 20, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 21, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 22, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 23, // If we've computed data from children and cached it in this node
|
||||
PropagateNull = 1 << 5, // Expression
|
||||
ExportContext = 1 << 6, // Export context (initialized by binding)
|
||||
ContainsThis = 1 << 7, // Interface contains references to "this"
|
||||
HasImplicitReturn = 1 << 8, // If function implicitly returns on one of codepaths (initialized by binding)
|
||||
HasExplicitReturn = 1 << 9, // If function has explicit reachable return on one of codepaths (initialized by binding)
|
||||
GlobalAugmentation = 1 << 10, // Set if module declaration is an augmentation for the global scope
|
||||
HasClassExtends = 1 << 11, // If the file has a non-ambient class with an extends clause in ES5 or lower (initialized by binding)
|
||||
HasDecorators = 1 << 12, // If the file has decorators (initialized by binding)
|
||||
HasParamDecorators = 1 << 13, // If the file has parameter decorators (initialized by binding)
|
||||
HasAsyncFunctions = 1 << 14, // If the file has async functions (initialized by binding)
|
||||
HasSpreadAttribute = 1 << 15, // If the file as JSX spread attributes (initialized by binding)
|
||||
HasRestAttribute = 1 << 16, // If the file has object destructure elements
|
||||
DisallowInContext = 1 << 17, // If node was parsed in a context where 'in-expressions' are not allowed
|
||||
YieldContext = 1 << 18, // If node was parsed in the 'yield' context created when parsing a generator
|
||||
DecoratorContext = 1 << 19, // If node was parsed as part of a decorator
|
||||
AwaitContext = 1 << 20, // If node was parsed in the 'await' context created when parsing an async function
|
||||
ThisNodeHasError = 1 << 21, // If the parser encountered an error when parsing the code that created this node
|
||||
JavaScriptFile = 1 << 22, // If node was parsed in a JavaScript
|
||||
ThisNodeOrAnySubNodesHasError = 1 << 23, // If this node or any of its children had an error
|
||||
HasAggregatedChildData = 1 << 24, // If we've computed data from children and cached it in this node
|
||||
|
||||
BlockScoped = Let | Const,
|
||||
|
||||
@ -1140,6 +1149,7 @@ namespace ts {
|
||||
export type LogicalOperator
|
||||
= SyntaxKind.AmpersandAmpersandToken
|
||||
| SyntaxKind.BarBarToken
|
||||
| SyntaxKind.QuestionQuestionToken
|
||||
;
|
||||
|
||||
// see: https://tc39.github.io/ecma262/#prod-LogicalANDExpression
|
||||
@ -1181,6 +1191,7 @@ namespace ts {
|
||||
export type BinaryOperator
|
||||
= AssignmentOperatorOrHigher
|
||||
| SyntaxKind.BarGreaterThanToken
|
||||
| SyntaxKind.QuestionQuestionToken
|
||||
| SyntaxKind.CommaToken
|
||||
;
|
||||
|
||||
@ -1194,12 +1205,22 @@ namespace ts {
|
||||
right: Expression;
|
||||
}
|
||||
|
||||
export type CommaToken = Token<SyntaxKind.CommaToken>;
|
||||
export type BarGreaterThanToken = Token<SyntaxKind.BarGreaterThanToken>;
|
||||
export type QuestionQuestionToken = Token<SyntaxKind.QuestionQuestionToken>;
|
||||
|
||||
export interface CommaExpression extends BinaryExpression {
|
||||
operatorToken: CommaToken;
|
||||
}
|
||||
|
||||
export interface PipelineExpression extends BinaryExpression {
|
||||
operatorToken: BarGreaterThanToken;
|
||||
}
|
||||
|
||||
export interface CoalesceExpression extends BinaryExpression {
|
||||
operatorToken: QuestionQuestionToken;
|
||||
}
|
||||
|
||||
export type AssignmentOperatorToken = Token<AssignmentOperator>;
|
||||
|
||||
export interface AssignmentExpression<TOperator extends AssignmentOperatorToken> extends BinaryExpression {
|
||||
@ -2777,7 +2798,6 @@ namespace ts {
|
||||
flags?: NodeCheckFlags; // Set of flags specific to Node
|
||||
resolvedType?: Type; // Cached type of type node
|
||||
resolvedSignature?: Signature; // Cached signature of signature node or call expression
|
||||
resolvedPartialSignatures?: Signature[];
|
||||
resolvedSymbol?: Symbol; // Cached name resolution result
|
||||
resolvedIndexInfo?: IndexInfo; // Cached indexing info resolution result
|
||||
maybeTypePredicate?: boolean; // Cached check whether call expression might reference a type predicate
|
||||
|
||||
@ -2135,36 +2135,40 @@ namespace ts {
|
||||
case SyntaxKind.ParenthesizedExpression:
|
||||
case SyntaxKind.OmittedExpression:
|
||||
case SyntaxKind.RawExpression:
|
||||
return 19;
|
||||
case SyntaxKind.BindExpression:
|
||||
return 20;
|
||||
|
||||
case SyntaxKind.TaggedTemplateExpression:
|
||||
case SyntaxKind.PropertyAccessExpression:
|
||||
case SyntaxKind.ElementAccessExpression:
|
||||
return 18;
|
||||
case SyntaxKind.BindToExpression:
|
||||
return 19;
|
||||
|
||||
case SyntaxKind.NewExpression:
|
||||
return hasArguments ? 18 : 17;
|
||||
return hasArguments ? 19 : 18;
|
||||
|
||||
case SyntaxKind.CallExpression:
|
||||
return 17;
|
||||
return 18;
|
||||
|
||||
case SyntaxKind.PostfixUnaryExpression:
|
||||
return 16;
|
||||
return 17;
|
||||
|
||||
case SyntaxKind.PrefixUnaryExpression:
|
||||
case SyntaxKind.TypeOfExpression:
|
||||
case SyntaxKind.VoidExpression:
|
||||
case SyntaxKind.DeleteExpression:
|
||||
case SyntaxKind.AwaitExpression:
|
||||
return 15;
|
||||
return 16;
|
||||
|
||||
case SyntaxKind.BinaryExpression:
|
||||
switch (operatorKind) {
|
||||
case SyntaxKind.ExclamationToken:
|
||||
case SyntaxKind.TildeToken:
|
||||
return 15;
|
||||
return 16;
|
||||
|
||||
case SyntaxKind.AsteriskAsteriskToken:
|
||||
return 15;
|
||||
|
||||
case SyntaxKind.AsteriskToken:
|
||||
case SyntaxKind.SlashToken:
|
||||
case SyntaxKind.PercentToken:
|
||||
@ -2206,6 +2210,7 @@ namespace ts {
|
||||
return 6;
|
||||
|
||||
case SyntaxKind.BarBarToken:
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
return 5;
|
||||
|
||||
case SyntaxKind.EqualsToken:
|
||||
@ -2231,11 +2236,12 @@ namespace ts {
|
||||
}
|
||||
|
||||
case SyntaxKind.ConditionalExpression:
|
||||
return 4;
|
||||
return operatorKind === SyntaxKind.QuestionToken ? 4 : 3;
|
||||
|
||||
case SyntaxKind.YieldExpression:
|
||||
return 2;
|
||||
|
||||
case SyntaxKind.PositionalElement:
|
||||
case SyntaxKind.SpreadElement:
|
||||
return 1;
|
||||
|
||||
@ -3903,6 +3909,7 @@ namespace ts {
|
||||
case SyntaxKind.AmpersandAmpersandToken:
|
||||
case SyntaxKind.BarBarToken:
|
||||
case SyntaxKind.BarGreaterThanToken:
|
||||
case SyntaxKind.QuestionQuestionToken:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -3912,6 +3919,11 @@ namespace ts {
|
||||
return node.kind === SyntaxKind.BinaryExpression;
|
||||
}
|
||||
|
||||
export function isCommaExpression(node: Node): node is CommaExpression {
|
||||
return isBinaryExpression(node)
|
||||
&& node.operatorToken.kind === SyntaxKind.CommaToken
|
||||
}
|
||||
|
||||
export function isConditionalExpression(node: Node): node is ConditionalExpression {
|
||||
return node.kind === SyntaxKind.ConditionalExpression;
|
||||
}
|
||||
@ -3943,6 +3955,11 @@ namespace ts {
|
||||
return isPositionalElement(node) || isPositionalSpreadElement(node);
|
||||
}
|
||||
|
||||
export function isPartialApplication(node: Node): node is CallExpression {
|
||||
return node.kind === SyntaxKind.CallExpression
|
||||
&& forEach((<CallExpression>node).arguments, isPositionalOrPositionalSpreadElement);
|
||||
}
|
||||
|
||||
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
|
||||
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
|
||||
}
|
||||
|
||||
72
tests/baselines/reference/parser.bindTo.esnext.1.symbols
Normal file
72
tests/baselines/reference/parser.bindTo.esnext.1.symbols
Normal file
@ -0,0 +1,72 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.bindTo.esnext.1.ts ===
|
||||
// single argument
|
||||
declare function f1(this: number): string;
|
||||
>f1 : Symbol(f1, Decl(parser.bindTo.esnext.1.ts, 0, 0))
|
||||
>this : Symbol(this, Decl(parser.bindTo.esnext.1.ts, 1, 20))
|
||||
|
||||
1 :: f1;
|
||||
1 :: f1();
|
||||
// multiple steps
|
||||
declare function f2(this: string): boolean;
|
||||
>f2 : Symbol(f2, Decl(parser.bindTo.esnext.1.ts, 3, 10))
|
||||
>this : Symbol(this, Decl(parser.bindTo.esnext.1.ts, 5, 20))
|
||||
|
||||
1 :: f1() :: f2();
|
||||
// use cases
|
||||
declare function map<T, U>(this: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
>map : Symbol(map, Decl(parser.bindTo.esnext.1.ts, 6, 18))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 8, 21))
|
||||
>U : Symbol(U, Decl(parser.bindTo.esnext.1.ts, 8, 23))
|
||||
>this : Symbol(this, Decl(parser.bindTo.esnext.1.ts, 8, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 8, 21))
|
||||
>cb : Symbol(cb, Decl(parser.bindTo.esnext.1.ts, 8, 45))
|
||||
>value : Symbol(value, Decl(parser.bindTo.esnext.1.ts, 8, 51))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 8, 21))
|
||||
>U : Symbol(U, Decl(parser.bindTo.esnext.1.ts, 8, 23))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>U : Symbol(U, Decl(parser.bindTo.esnext.1.ts, 8, 23))
|
||||
|
||||
declare function filter<T>(this: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
>filter : Symbol(filter, Decl(parser.bindTo.esnext.1.ts, 8, 80))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 9, 24))
|
||||
>this : Symbol(this, Decl(parser.bindTo.esnext.1.ts, 9, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 9, 24))
|
||||
>cb : Symbol(cb, Decl(parser.bindTo.esnext.1.ts, 9, 45))
|
||||
>value : Symbol(value, Decl(parser.bindTo.esnext.1.ts, 9, 51))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 9, 24))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 9, 24))
|
||||
|
||||
declare function reduce<T>(this: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
>reduce : Symbol(reduce, Decl(parser.bindTo.esnext.1.ts, 9, 86))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>this : Symbol(this, Decl(parser.bindTo.esnext.1.ts, 10, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>cb : Symbol(cb, Decl(parser.bindTo.esnext.1.ts, 10, 45))
|
||||
>memo : Symbol(memo, Decl(parser.bindTo.esnext.1.ts, 10, 51))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>value : Symbol(value, Decl(parser.bindTo.esnext.1.ts, 10, 59))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>initial : Symbol(initial, Decl(parser.bindTo.esnext.1.ts, 10, 75))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
>T : Symbol(T, Decl(parser.bindTo.esnext.1.ts, 10, 24))
|
||||
|
||||
[1, 2, 3]
|
||||
:: map(x => x * 2)
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 12, 11))
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 12, 11))
|
||||
|
||||
:: filter(x => x > 2)
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 13, 14))
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 13, 14))
|
||||
|
||||
:: reduce((x, y) => x + y, 0);
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 14, 15))
|
||||
>y : Symbol(y, Decl(parser.bindTo.esnext.1.ts, 14, 17))
|
||||
>x : Symbol(x, Decl(parser.bindTo.esnext.1.ts, 14, 15))
|
||||
>y : Symbol(y, Decl(parser.bindTo.esnext.1.ts, 14, 17))
|
||||
|
||||
102
tests/baselines/reference/parser.bindTo.esnext.1.types
Normal file
102
tests/baselines/reference/parser.bindTo.esnext.1.types
Normal file
@ -0,0 +1,102 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.bindTo.esnext.1.ts ===
|
||||
// single argument
|
||||
declare function f1(this: number): string;
|
||||
>f1 : (this: number) => string
|
||||
>this : number
|
||||
|
||||
1 :: f1;
|
||||
>f1 : any
|
||||
|
||||
1 :: f1();
|
||||
>1 :: f1() : string
|
||||
>f1 : any
|
||||
|
||||
// multiple steps
|
||||
declare function f2(this: string): boolean;
|
||||
>f2 : (this: string) => boolean
|
||||
>this : string
|
||||
|
||||
1 :: f1() :: f2();
|
||||
>1 :: f1() :: f2() : boolean
|
||||
>1 :: f1() : string
|
||||
>f1 : any
|
||||
>f2 : any
|
||||
|
||||
// use cases
|
||||
declare function map<T, U>(this: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
>map : <T, U>(this: Iterable<T>, cb: (value: T) => U) => Iterable<U>
|
||||
>T : T
|
||||
>U : U
|
||||
>this : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (value: T) => U
|
||||
>value : T
|
||||
>T : T
|
||||
>U : U
|
||||
>Iterable : Iterable<T>
|
||||
>U : U
|
||||
|
||||
declare function filter<T>(this: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
>filter : <T>(this: Iterable<T>, cb: (value: T) => boolean) => Iterable<T>
|
||||
>T : T
|
||||
>this : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (value: T) => boolean
|
||||
>value : T
|
||||
>T : T
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
|
||||
declare function reduce<T>(this: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
>reduce : <T>(this: Iterable<T>, cb: (memo: T, value: T) => T, initial: T) => T
|
||||
>T : T
|
||||
>this : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (memo: T, value: T) => T
|
||||
>memo : T
|
||||
>T : T
|
||||
>value : T
|
||||
>T : T
|
||||
>T : T
|
||||
>initial : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
[1, 2, 3]
|
||||
>[1, 2, 3] :: map(x => x * 2) :: filter(x => x > 2) :: reduce((x, y) => x + y, 0) : number
|
||||
>[1, 2, 3] :: map(x => x * 2) :: filter(x => x > 2) : Iterable<number>
|
||||
>[1, 2, 3] :: map(x => x * 2) : Iterable<number>
|
||||
>[1, 2, 3] : number[]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
:: map(x => x * 2)
|
||||
>map : any
|
||||
>x => x * 2 : (x: number) => number
|
||||
>x : number
|
||||
>x * 2 : number
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
:: filter(x => x > 2)
|
||||
>filter : any
|
||||
>x => x > 2 : (x: number) => boolean
|
||||
>x : number
|
||||
>x > 2 : boolean
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
:: reduce((x, y) => x + y, 0);
|
||||
>reduce : any
|
||||
>(x, y) => x + y : (x: number, y: number) => number
|
||||
>x : number
|
||||
>y : number
|
||||
>x + y : number
|
||||
>x : number
|
||||
>y : number
|
||||
>0 : 0
|
||||
|
||||
@ -0,0 +1,114 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.partialApplication.esnext.1.ts ===
|
||||
declare function f(a: number, b: number, ...c: number[]): void;
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
>a : Symbol(a, Decl(parser.partialApplication.esnext.1.ts, 0, 19))
|
||||
>b : Symbol(b, Decl(parser.partialApplication.esnext.1.ts, 0, 29))
|
||||
>c : Symbol(c, Decl(parser.partialApplication.esnext.1.ts, 0, 40))
|
||||
|
||||
declare const o: { m(a: number, b: number, ...c: number[]): void; };
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>a : Symbol(a, Decl(parser.partialApplication.esnext.1.ts, 1, 21))
|
||||
>b : Symbol(b, Decl(parser.partialApplication.esnext.1.ts, 1, 31))
|
||||
>c : Symbol(c, Decl(parser.partialApplication.esnext.1.ts, 1, 42))
|
||||
|
||||
// positional elements
|
||||
f(?, 0);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(0, ?);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(?, ?);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
o.m(?, 0);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(0, ?);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(?, ?);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
// ordinal positional elements
|
||||
f(?0, 0);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(0, ?0);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(?0, ?1);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(?1, ?0);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
o.m(?0, 0);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(0, ?0);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(?0, ?1);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(?1, ?0);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
// positional spread element
|
||||
f(0, 1, ...);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(0, 1, ..., 2);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
o.m(0, 1, ...);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(0, 1, ..., 2);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
// mixed
|
||||
f(?, 0, ...);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(0, ?, ...);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
f(0, 1, ..., ?0);
|
||||
>f : Symbol(f, Decl(parser.partialApplication.esnext.1.ts, 0, 0))
|
||||
|
||||
o.m(?, 0, ...);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(0, ?, ...);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
o.m(0, 1, ..., ?0);
|
||||
>o.m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
>o : Symbol(o, Decl(parser.partialApplication.esnext.1.ts, 1, 13))
|
||||
>m : Symbol(m, Decl(parser.partialApplication.esnext.1.ts, 1, 18))
|
||||
|
||||
@ -0,0 +1,184 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.partialApplication.esnext.1.ts ===
|
||||
declare function f(a: number, b: number, ...c: number[]): void;
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>a : number
|
||||
>b : number
|
||||
>c : number[]
|
||||
|
||||
declare const o: { m(a: number, b: number, ...c: number[]): void; };
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>a : number
|
||||
>b : number
|
||||
>c : number[]
|
||||
|
||||
// positional elements
|
||||
f(?, 0);
|
||||
>f(?, 0) : (a: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
f(0, ?);
|
||||
>f(0, ?) : (b: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
f(?, ?);
|
||||
>f(?, ?) : (a: number, b: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
o.m(?, 0);
|
||||
>o.m(?, 0) : (a: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
o.m(0, ?);
|
||||
>o.m(0, ?) : (b: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
o.m(?, ?);
|
||||
>o.m(?, ?) : (a: number, b: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
// ordinal positional elements
|
||||
f(?0, 0);
|
||||
>f(?0, 0) : (a: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
f(0, ?0);
|
||||
>f(0, ?0) : (b: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
f(?0, ?1);
|
||||
>f(?0, ?1) : (a: number, b: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
f(?1, ?0);
|
||||
>f(?1, ?0) : (b: number, a: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
o.m(?0, 0);
|
||||
>o.m(?0, 0) : (a: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
o.m(0, ?0);
|
||||
>o.m(0, ?0) : (b: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
|
||||
o.m(?0, ?1);
|
||||
>o.m(?0, ?1) : (a: number, b: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
o.m(?1, ?0);
|
||||
>o.m(?1, ?0) : (b: number, a: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
|
||||
// positional spread element
|
||||
f(0, 1, ...);
|
||||
>f(0, 1, ...) : (...c: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
f(0, 1, ..., 2);
|
||||
>f(0, 1, ..., 2) : (...c: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
>2 : 2
|
||||
|
||||
o.m(0, 1, ...);
|
||||
>o.m(0, 1, ...) : (...c: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
o.m(0, 1, ..., 2);
|
||||
>o.m(0, 1, ..., 2) : (...c: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
>2 : 2
|
||||
|
||||
// mixed
|
||||
f(?, 0, ...);
|
||||
>f(?, 0, ...) : (a: number, ...c: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
f(0, ?, ...);
|
||||
>f(0, ?, ...) : (b: number, ...c: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
f(0, 1, ..., ?0);
|
||||
>f(0, 1, ..., ?0) : (c0: number, ...c: number) => void
|
||||
>f : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
o.m(?, 0, ...);
|
||||
>o.m(?, 0, ...) : (a: number, ...c: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
o.m(0, ?, ...);
|
||||
>o.m(0, ?, ...) : (b: number, ...c: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
o.m(0, 1, ..., ?0);
|
||||
>o.m(0, 1, ..., ?0) : (c0: number, ...c: number) => void
|
||||
>o.m : (a: number, b: number, ...c: number[]) => void
|
||||
>o : { m(a: number, b: number, ...c: number[]): void; }
|
||||
>m : (a: number, b: number, ...c: number[]) => void
|
||||
>0 : 0
|
||||
>1 : 1
|
||||
>... : any
|
||||
> : undefined
|
||||
|
||||
121
tests/baselines/reference/parser.pipeline.esnext.1.symbols
Normal file
121
tests/baselines/reference/parser.pipeline.esnext.1.symbols
Normal file
@ -0,0 +1,121 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.pipeline.esnext.1.ts ===
|
||||
// single argument
|
||||
declare function f1(x: number): string;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 1, 20))
|
||||
|
||||
1 |> f1;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
|
||||
1 |> f1(?);
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
|
||||
(1) |> f1;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
|
||||
(1) |> f1(?);
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
|
||||
// multiple argument
|
||||
declare function f2(x: number, y: number): string;
|
||||
>f2 : Symbol(f2, Decl(parser.pipeline.esnext.1.ts, 5, 13))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 7, 20))
|
||||
>y : Symbol(y, Decl(parser.pipeline.esnext.1.ts, 7, 30))
|
||||
|
||||
(1, 2) |> f2;
|
||||
>f2 : Symbol(f2, Decl(parser.pipeline.esnext.1.ts, 5, 13))
|
||||
|
||||
(1, 2) |> f2(?, ?);
|
||||
>f2 : Symbol(f2, Decl(parser.pipeline.esnext.1.ts, 5, 13))
|
||||
|
||||
// multiple steps
|
||||
declare function f3(x: string): boolean;
|
||||
>f3 : Symbol(f3, Decl(parser.pipeline.esnext.1.ts, 9, 19))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 11, 20))
|
||||
|
||||
declare function f4(x: string, y: number): boolean;
|
||||
>f4 : Symbol(f4, Decl(parser.pipeline.esnext.1.ts, 11, 40))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 12, 20))
|
||||
>y : Symbol(y, Decl(parser.pipeline.esnext.1.ts, 12, 30))
|
||||
|
||||
1 |> f1 |> f3;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>f3 : Symbol(f3, Decl(parser.pipeline.esnext.1.ts, 9, 19))
|
||||
|
||||
1 |> f1(?) |> f3;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>f3 : Symbol(f3, Decl(parser.pipeline.esnext.1.ts, 9, 19))
|
||||
|
||||
1 |> f1 |> f3(?);
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>f3 : Symbol(f3, Decl(parser.pipeline.esnext.1.ts, 9, 19))
|
||||
|
||||
1 |> f1(?) |> f3(?);
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>f3 : Symbol(f3, Decl(parser.pipeline.esnext.1.ts, 9, 19))
|
||||
|
||||
(1 |> f1(?), 2) |> f4;
|
||||
>f1 : Symbol(f1, Decl(parser.pipeline.esnext.1.ts, 0, 0))
|
||||
>f4 : Symbol(f4, Decl(parser.pipeline.esnext.1.ts, 11, 40))
|
||||
|
||||
// use case
|
||||
declare function map<T, U>(source: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
>map : Symbol(map, Decl(parser.pipeline.esnext.1.ts, 17, 22))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 19, 21))
|
||||
>U : Symbol(U, Decl(parser.pipeline.esnext.1.ts, 19, 23))
|
||||
>source : Symbol(source, Decl(parser.pipeline.esnext.1.ts, 19, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 19, 21))
|
||||
>cb : Symbol(cb, Decl(parser.pipeline.esnext.1.ts, 19, 47))
|
||||
>value : Symbol(value, Decl(parser.pipeline.esnext.1.ts, 19, 53))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 19, 21))
|
||||
>U : Symbol(U, Decl(parser.pipeline.esnext.1.ts, 19, 23))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>U : Symbol(U, Decl(parser.pipeline.esnext.1.ts, 19, 23))
|
||||
|
||||
declare function filter<T>(source: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
>filter : Symbol(filter, Decl(parser.pipeline.esnext.1.ts, 19, 82))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 20, 24))
|
||||
>source : Symbol(source, Decl(parser.pipeline.esnext.1.ts, 20, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 20, 24))
|
||||
>cb : Symbol(cb, Decl(parser.pipeline.esnext.1.ts, 20, 47))
|
||||
>value : Symbol(value, Decl(parser.pipeline.esnext.1.ts, 20, 53))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 20, 24))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 20, 24))
|
||||
|
||||
declare function reduce<T>(source: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
>reduce : Symbol(reduce, Decl(parser.pipeline.esnext.1.ts, 20, 88))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>source : Symbol(source, Decl(parser.pipeline.esnext.1.ts, 21, 27))
|
||||
>Iterable : Symbol(Iterable, Decl(lib.es2015.iterable.d.ts, --, --))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>cb : Symbol(cb, Decl(parser.pipeline.esnext.1.ts, 21, 47))
|
||||
>memo : Symbol(memo, Decl(parser.pipeline.esnext.1.ts, 21, 53))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>value : Symbol(value, Decl(parser.pipeline.esnext.1.ts, 21, 61))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>initial : Symbol(initial, Decl(parser.pipeline.esnext.1.ts, 21, 77))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
>T : Symbol(T, Decl(parser.pipeline.esnext.1.ts, 21, 24))
|
||||
|
||||
[1, 2, 3]
|
||||
|> map(?, x => x * 2)
|
||||
>map : Symbol(map, Decl(parser.pipeline.esnext.1.ts, 17, 22))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 23, 13))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 23, 13))
|
||||
|
||||
|> filter(?, x => x > 2)
|
||||
>filter : Symbol(filter, Decl(parser.pipeline.esnext.1.ts, 19, 82))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 24, 16))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 24, 16))
|
||||
|
||||
|> reduce(?, (x, y) => x + y, 0);
|
||||
>reduce : Symbol(reduce, Decl(parser.pipeline.esnext.1.ts, 20, 88))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 25, 18))
|
||||
>y : Symbol(y, Decl(parser.pipeline.esnext.1.ts, 25, 20))
|
||||
>x : Symbol(x, Decl(parser.pipeline.esnext.1.ts, 25, 18))
|
||||
>y : Symbol(y, Decl(parser.pipeline.esnext.1.ts, 25, 20))
|
||||
|
||||
187
tests/baselines/reference/parser.pipeline.esnext.1.types
Normal file
187
tests/baselines/reference/parser.pipeline.esnext.1.types
Normal file
@ -0,0 +1,187 @@
|
||||
=== tests/cases/conformance/parser/esnext/parser.pipeline.esnext.1.ts ===
|
||||
// single argument
|
||||
declare function f1(x: number): string;
|
||||
>f1 : (x: number) => string
|
||||
>x : number
|
||||
|
||||
1 |> f1;
|
||||
>1 |> f1 : string
|
||||
>1 : 1
|
||||
>f1 : (x: number) => string
|
||||
|
||||
1 |> f1(?);
|
||||
>1 |> f1(?) : string
|
||||
>1 : 1
|
||||
>f1(?) : (x: number) => string
|
||||
>f1 : (x: number) => string
|
||||
|
||||
(1) |> f1;
|
||||
>(1) |> f1 : string
|
||||
>(1) : 1
|
||||
>1 : 1
|
||||
>f1 : (x: number) => string
|
||||
|
||||
(1) |> f1(?);
|
||||
>(1) |> f1(?) : string
|
||||
>(1) : 1
|
||||
>1 : 1
|
||||
>f1(?) : (x: number) => string
|
||||
>f1 : (x: number) => string
|
||||
|
||||
// multiple argument
|
||||
declare function f2(x: number, y: number): string;
|
||||
>f2 : (x: number, y: number) => string
|
||||
>x : number
|
||||
>y : number
|
||||
|
||||
(1, 2) |> f2;
|
||||
>(1, 2) |> f2 : string
|
||||
>(1, 2) : 2
|
||||
>1, 2 : 2
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>f2 : (x: number, y: number) => string
|
||||
|
||||
(1, 2) |> f2(?, ?);
|
||||
>(1, 2) |> f2(?, ?) : string
|
||||
>(1, 2) : 2
|
||||
>1, 2 : 2
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>f2(?, ?) : (x: number, y: number) => string
|
||||
>f2 : (x: number, y: number) => string
|
||||
|
||||
// multiple steps
|
||||
declare function f3(x: string): boolean;
|
||||
>f3 : (x: string) => boolean
|
||||
>x : string
|
||||
|
||||
declare function f4(x: string, y: number): boolean;
|
||||
>f4 : (x: string, y: number) => boolean
|
||||
>x : string
|
||||
>y : number
|
||||
|
||||
1 |> f1 |> f3;
|
||||
>1 |> f1 |> f3 : boolean
|
||||
>1 |> f1 : string
|
||||
>1 : 1
|
||||
>f1 : (x: number) => string
|
||||
>f3 : (x: string) => boolean
|
||||
|
||||
1 |> f1(?) |> f3;
|
||||
>1 |> f1(?) |> f3 : boolean
|
||||
>1 |> f1(?) : string
|
||||
>1 : 1
|
||||
>f1(?) : (x: number) => string
|
||||
>f1 : (x: number) => string
|
||||
>f3 : (x: string) => boolean
|
||||
|
||||
1 |> f1 |> f3(?);
|
||||
>1 |> f1 |> f3(?) : boolean
|
||||
>1 |> f1 : string
|
||||
>1 : 1
|
||||
>f1 : (x: number) => string
|
||||
>f3(?) : (x: string) => boolean
|
||||
>f3 : (x: string) => boolean
|
||||
|
||||
1 |> f1(?) |> f3(?);
|
||||
>1 |> f1(?) |> f3(?) : boolean
|
||||
>1 |> f1(?) : string
|
||||
>1 : 1
|
||||
>f1(?) : (x: number) => string
|
||||
>f1 : (x: number) => string
|
||||
>f3(?) : (x: string) => boolean
|
||||
>f3 : (x: string) => boolean
|
||||
|
||||
(1 |> f1(?), 2) |> f4;
|
||||
>(1 |> f1(?), 2) |> f4 : boolean
|
||||
>(1 |> f1(?), 2) : 2
|
||||
>1 |> f1(?), 2 : 2
|
||||
>1 |> f1(?) : string
|
||||
>1 : 1
|
||||
>f1(?) : (x: number) => string
|
||||
>f1 : (x: number) => string
|
||||
>2 : 2
|
||||
>f4 : (x: string, y: number) => boolean
|
||||
|
||||
// use case
|
||||
declare function map<T, U>(source: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
>map : <T, U>(source: Iterable<T>, cb: (value: T) => U) => Iterable<U>
|
||||
>T : T
|
||||
>U : U
|
||||
>source : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (value: T) => U
|
||||
>value : T
|
||||
>T : T
|
||||
>U : U
|
||||
>Iterable : Iterable<T>
|
||||
>U : U
|
||||
|
||||
declare function filter<T>(source: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
>filter : <T>(source: Iterable<T>, cb: (value: T) => boolean) => Iterable<T>
|
||||
>T : T
|
||||
>source : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (value: T) => boolean
|
||||
>value : T
|
||||
>T : T
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
|
||||
declare function reduce<T>(source: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
>reduce : <T>(source: Iterable<T>, cb: (memo: T, value: T) => T, initial: T) => T
|
||||
>T : T
|
||||
>source : Iterable<T>
|
||||
>Iterable : Iterable<T>
|
||||
>T : T
|
||||
>cb : (memo: T, value: T) => T
|
||||
>memo : T
|
||||
>T : T
|
||||
>value : T
|
||||
>T : T
|
||||
>T : T
|
||||
>initial : T
|
||||
>T : T
|
||||
>T : T
|
||||
|
||||
[1, 2, 3]
|
||||
>[1, 2, 3] |> map(?, x => x * 2) |> filter(?, x => x > 2) |> reduce(?, (x, y) => x + y, 0) : number
|
||||
>[1, 2, 3] |> map(?, x => x * 2) |> filter(?, x => x > 2) : Iterable<number>
|
||||
>[1, 2, 3] |> map(?, x => x * 2) : Iterable<number>
|
||||
>[1, 2, 3] : number[]
|
||||
>1 : 1
|
||||
>2 : 2
|
||||
>3 : 3
|
||||
|
||||
|> map(?, x => x * 2)
|
||||
>map(?, x => x * 2) : <T>(source: Iterable<T>) => Iterable<number>
|
||||
>map : <T, U>(source: Iterable<T>, cb: (value: T) => U) => Iterable<U>
|
||||
>x => x * 2 : (x: number) => number
|
||||
>x : number
|
||||
>x * 2 : number
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
|> filter(?, x => x > 2)
|
||||
>filter(?, x => x > 2) : <T>(source: Iterable<T>) => Iterable<T>
|
||||
>filter : <T>(source: Iterable<T>, cb: (value: T) => boolean) => Iterable<T>
|
||||
>x => x > 2 : (x: number) => boolean
|
||||
>x : number
|
||||
>x > 2 : boolean
|
||||
>x : number
|
||||
>2 : 2
|
||||
|
||||
|> reduce(?, (x, y) => x + y, 0);
|
||||
>reduce(?, (x, y) => x + y, 0) : (source: Iterable<number>) => number
|
||||
>reduce : <T>(source: Iterable<T>, cb: (memo: T, value: T) => T, initial: T) => T
|
||||
>(x, y) => x + y : (x: number, y: number) => number
|
||||
>x : number
|
||||
>y : number
|
||||
>x + y : number
|
||||
>x : number
|
||||
>y : number
|
||||
>0 : 0
|
||||
|
||||
@ -0,0 +1,18 @@
|
||||
// @target: esnext
|
||||
// @noEmit: true
|
||||
// @lib: es2015
|
||||
// single argument
|
||||
declare function f1(this: number): string;
|
||||
1 :: f1;
|
||||
1 :: f1();
|
||||
// multiple steps
|
||||
declare function f2(this: string): boolean;
|
||||
1 :: f1() :: f2();
|
||||
// use cases
|
||||
declare function map<T, U>(this: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
declare function filter<T>(this: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
declare function reduce<T>(this: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
[1, 2, 3]
|
||||
:: map(x => x * 2)
|
||||
:: filter(x => x > 2)
|
||||
:: reduce((x, y) => x + y, 0);
|
||||
@ -0,0 +1,32 @@
|
||||
// @target: esnext
|
||||
// @noEmit: true
|
||||
declare function f(a: number, b: number, ...c: number[]): void;
|
||||
declare const o: { m(a: number, b: number, ...c: number[]): void; };
|
||||
// positional elements
|
||||
f(?, 0);
|
||||
f(0, ?);
|
||||
f(?, ?);
|
||||
o.m(?, 0);
|
||||
o.m(0, ?);
|
||||
o.m(?, ?);
|
||||
// ordinal positional elements
|
||||
f(?0, 0);
|
||||
f(0, ?0);
|
||||
f(?0, ?1);
|
||||
f(?1, ?0);
|
||||
o.m(?0, 0);
|
||||
o.m(0, ?0);
|
||||
o.m(?0, ?1);
|
||||
o.m(?1, ?0);
|
||||
// positional spread element
|
||||
f(0, 1, ...);
|
||||
f(0, 1, ..., 2);
|
||||
o.m(0, 1, ...);
|
||||
o.m(0, 1, ..., 2);
|
||||
// mixed
|
||||
f(?, 0, ...);
|
||||
f(0, ?, ...);
|
||||
f(0, 1, ..., ?0);
|
||||
o.m(?, 0, ...);
|
||||
o.m(0, ?, ...);
|
||||
o.m(0, 1, ..., ?0);
|
||||
@ -0,0 +1,29 @@
|
||||
// @target: esnext
|
||||
// @noEmit: true
|
||||
// @lib: es2015
|
||||
// single argument
|
||||
declare function f1(x: number): string;
|
||||
1 |> f1;
|
||||
1 |> f1(?);
|
||||
(1) |> f1;
|
||||
(1) |> f1(?);
|
||||
// multiple argument
|
||||
declare function f2(x: number, y: number): string;
|
||||
(1, 2) |> f2;
|
||||
(1, 2) |> f2(?, ?);
|
||||
// multiple steps
|
||||
declare function f3(x: string): boolean;
|
||||
declare function f4(x: string, y: number): boolean;
|
||||
1 |> f1 |> f3;
|
||||
1 |> f1(?) |> f3;
|
||||
1 |> f1 |> f3(?);
|
||||
1 |> f1(?) |> f3(?);
|
||||
(1 |> f1(?), 2) |> f4;
|
||||
// use case
|
||||
declare function map<T, U>(source: Iterable<T>, cb: (value: T) => U): Iterable<U>;
|
||||
declare function filter<T>(source: Iterable<T>, cb: (value: T) => boolean): Iterable<T>;
|
||||
declare function reduce<T>(source: Iterable<T>, cb: (memo: T, value: T) => T, initial: T): T;
|
||||
[1, 2, 3]
|
||||
|> map(?, x => x * 2)
|
||||
|> filter(?, x => x > 2)
|
||||
|> reduce(?, (x, y) => x + y, 0);
|
||||
Loading…
x
Reference in New Issue
Block a user