Initial parse, check, emit for partial application, pipeline, and operator expressions

This commit is contained in:
Ron Buckton
2016-11-17 18:16:25 -08:00
parent 52ec508e27
commit 7cd77536ac
12 changed files with 753 additions and 77 deletions
+15
View File
@@ -3110,6 +3110,10 @@ namespace ts {
let excludeFlags = TransformFlags.NodeExcludes;
switch (kind) {
case SyntaxKind.BarGreaterThanToken:
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.AsyncKeyword:
case SyntaxKind.AwaitExpression:
// async/await is ES2017 syntax
@@ -3221,12 +3225,23 @@ namespace ts {
case SyntaxKind.SpreadElement:
transformFlags |= TransformFlags.AssertES2015 | TransformFlags.ContainsSpread;
if ((<SpreadElement>node).expression.kind === SyntaxKind.OmittedExpression) {
transformFlags |= TransformFlags.AssertESNext;
}
break;
case SyntaxKind.SpreadAssignment:
transformFlags |= TransformFlags.AssertESNext | TransformFlags.ContainsObjectSpread;
break;
case SyntaxKind.PositionalElement:
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.OperatorExpression:
transformFlags |= TransformFlags.AssertESNext;
break;
case SyntaxKind.SuperKeyword:
// This node is ES6 syntax.
transformFlags |= TransformFlags.AssertES2015;
+352 -30
View File
@@ -163,6 +163,7 @@ 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);
@@ -240,6 +241,7 @@ namespace ts {
const visitedFlowTypes: FlowType[] = [];
const potentialThisCollisions: Node[] = [];
const awaitedTypeStack: number[] = [];
const operatorExpressionTypes = createMap<Type>();
const diagnostics = createDiagnosticCollection();
@@ -2616,16 +2618,16 @@ namespace ts {
function buildParameterDisplay(p: Symbol, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
const parameterNode = <ParameterDeclaration>p.valueDeclaration;
if (isRestParameter(parameterNode)) {
if ((isTransient(p) && p.transientSymbolIsRest) || isRestParameter(parameterNode)) {
writePunctuation(writer, SyntaxKind.DotDotDotToken);
}
if (isBindingPattern(parameterNode.name)) {
if (parameterNode && isBindingPattern(parameterNode.name)) {
buildBindingPatternDisplay(<BindingPattern>parameterNode.name, writer, enclosingDeclaration, flags, symbolStack);
}
else {
appendSymbolNameOnly(p, writer);
}
if (isOptionalParameter(parameterNode)) {
if (parameterNode && isOptionalParameter(parameterNode)) {
writePunctuation(writer, SyntaxKind.QuestionToken);
}
writePunctuation(writer, SyntaxKind.ColonToken);
@@ -4277,10 +4279,15 @@ namespace ts {
resolveObjectTypeMembers(type, source, typeParameters, typeArguments);
}
function createSignature(isConstruct: boolean, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature;
function createSignature(declaration: SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature;
function createSignature(declaration: boolean | SignatureDeclaration, typeParameters: TypeParameter[], thisParameter: Symbol | undefined, parameters: Symbol[],
resolvedReturnType: Type, typePredicate: TypePredicate, minArgumentCount: number, hasRestParameter: boolean, hasLiteralTypes: boolean): Signature {
const sig = new Signature(checker);
sig.declaration = declaration;
sig.declaration = typeof declaration === "boolean" ? undefined : declaration;
sig.isConstruct = typeof declaration === "boolean" ? declaration : declaration && (declaration.kind === SyntaxKind.Constructor || declaration.kind === SyntaxKind.ConstructSignature);
sig.typeParameters = typeParameters;
sig.parameters = parameters;
sig.thisParameter = thisParameter;
@@ -5174,12 +5181,11 @@ namespace ts {
// object type literal or interface (using the new keyword). Each way of declaring a constructor
// will result in a different declaration kind.
if (!signature.isolatedSignatureType) {
const isConstructor = signature.declaration.kind === SyntaxKind.Constructor || signature.declaration.kind === SyntaxKind.ConstructSignature;
const type = <ResolvedType>createObjectType(ObjectFlags.Anonymous);
type.members = emptySymbols;
type.properties = emptyArray;
type.callSignatures = !isConstructor ? [signature] : emptyArray;
type.constructSignatures = isConstructor ? [signature] : emptyArray;
type.callSignatures = !signature.isConstruct ? [signature] : emptyArray;
type.constructSignatures = signature.isConstruct ? [signature] : emptyArray;
signature.isolatedSignatureType = type;
}
@@ -8119,6 +8125,10 @@ namespace ts {
getSignaturesOfType(type, SignatureKind.Construct).length === 0;
}
function isTransient(symbol: Symbol): symbol is TransientSymbol {
return (symbol.flags & SymbolFlags.Transient) !== 0;
}
function createTransientSymbol(source: Symbol, type: Type) {
const symbol = <TransientSymbol>createSymbol(source.flags | SymbolFlags.Transient, source.name);
symbol.declarations = source.declarations;
@@ -12307,6 +12317,11 @@ namespace ts {
typeArguments = undefined;
argCount = getEffectiveArgumentCount(node, /*args*/ undefined, signature);
}
else if (node.kind === SyntaxKind.BinaryExpression) {
typeArguments = undefined;
argCount = getEffectiveArgumentCount(node, args, signature);
spreadArgIndex = getSpreadArgumentIndex(args);
}
else {
const callExpression = <CallExpression | NewExpression>node;
if (!callExpression.arguments) {
@@ -12558,6 +12573,23 @@ namespace ts {
// `getEffectiveArgumentCount` and `getEffectiveArgumentType` below.
return undefined;
}
else if (node.kind === SyntaxKind.BinaryExpression) {
let expression = (<PipelineExpression>node).left;
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);
}
else {
args = [expression];
}
}
else {
args = (<CallExpression>node).arguments || emptyArray;
}
@@ -12837,13 +12869,17 @@ namespace ts {
}
}
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], headMessage?: DiagnosticMessage): Signature {
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], partialApplication: false, headMessage?: DiagnosticMessage): Signature;
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], partialApplication: true, headMessage?: DiagnosticMessage): Signature[];
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], partialApplication: boolean, headMessage?: DiagnosticMessage): Signature | Signature[];
function resolveCall(node: CallLikeExpression, signatures: Signature[], candidatesOutArray: Signature[], partialApplication: boolean, headMessage?: DiagnosticMessage): Signature | Signature[] {
const isTaggedTemplate = node.kind === SyntaxKind.TaggedTemplateExpression;
const isDecorator = node.kind === SyntaxKind.Decorator;
const isPipeline = node.kind === SyntaxKind.BinaryExpression;
let typeArguments: TypeNode[];
if (!isTaggedTemplate && !isDecorator) {
if (!isTaggedTemplate && !isDecorator && !isPipeline) {
typeArguments = (<CallExpression>node).typeArguments;
// We already perform checking on the type arguments on the class declaration itself.
@@ -12857,7 +12893,7 @@ namespace ts {
reorderCandidates(signatures, candidates);
if (!candidates.length) {
reportError(Diagnostics.Supplied_parameters_do_not_match_any_signature_of_call_target);
return resolveErrorCall(node);
return partialApplication ? [resolveErrorCall(node)] : resolveErrorCall(node);
}
const args = getEffectiveCallArguments(node);
@@ -12914,7 +12950,7 @@ namespace ts {
let candidateForArgumentError: Signature;
let candidateForTypeArgumentError: Signature;
let resultOfFailedInference: InferenceContext;
let result: Signature;
let result: Signature | Signature[];
// If we are in signature help, a trailing comma indicates that we intend to provide another argument,
// so we will only accept overloads with arity at least 1 higher than the current number of provided arguments.
@@ -12934,7 +12970,7 @@ namespace ts {
if (candidates.length > 1) {
result = chooseOverload(candidates, subtypeRelation, signatureHelpTrailingComma);
}
if (!result) {
if (!result || partialApplication) {
// Reinitialize these pointers for round two
candidateForArgumentError = undefined;
candidateForTypeArgumentError = undefined;
@@ -12993,12 +13029,12 @@ namespace ts {
if (candidate.typeParameters && typeArguments) {
candidate = getSignatureInstantiation(candidate, map(typeArguments, getTypeFromTypeNode));
}
return candidate;
return partialApplication ? [candidate] : candidate;
}
}
}
return resolveErrorCall(node);
return partialApplication ? [resolveErrorCall(node)] : resolveErrorCall(node);
function reportError(message: DiagnosticMessage, arg0?: string, arg1?: string, arg2?: string): void {
let errorInfo: DiagnosticMessageChain;
@@ -13010,8 +13046,9 @@ namespace ts {
diagnostics.add(createDiagnosticForNodeFromMessageChain(node, errorInfo));
}
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false) {
for (const originalCandidate of candidates) {
function chooseOverload(candidates: Signature[], relation: Map<RelationComparisonResult>, signatureHelpTrailingComma = false): Signature | Signature[] {
let partialCandidates: Signature[];
outer: for (const originalCandidate of candidates) {
if (!hasCorrectArity(node, args, originalCandidate, signatureHelpTrailingComma)) {
continue;
}
@@ -13045,6 +13082,10 @@ namespace ts {
}
const index = excludeArgument ? indexOf(excludeArgument, true) : -1;
if (index < 0) {
if (partialApplication) {
partialCandidates = append(partialCandidates, originalCandidate);
continue outer;
}
return candidate;
}
excludeArgument[index] = false;
@@ -13073,12 +13114,14 @@ namespace ts {
}
}
return undefined;
return partialCandidates;
}
}
function resolveCallExpression(node: CallExpression, candidatesOutArray: Signature[]): Signature {
function resolveCallExpression(node: CallExpression, partialApplication: false, candidatesOutArray: Signature[]): Signature;
function resolveCallExpression(node: CallExpression, partialApplication: true, candidatesOutArray: Signature[]): Signature[];
function resolveCallExpression(node: CallExpression, partialApplication: boolean, candidatesOutArray: Signature[]): Signature | Signature[];
function resolveCallExpression(node: CallExpression, partialApplication: boolean, candidatesOutArray: Signature[]): Signature | Signature[] {
if (node.expression.kind === SyntaxKind.SuperKeyword) {
const superType = checkSuperExpression(node.expression);
if (superType !== unknownType) {
@@ -13087,7 +13130,7 @@ namespace ts {
const baseTypeNode = getClassExtendsHeritageClauseElement(getContainingClass(node));
if (baseTypeNode) {
const baseConstructors = getInstantiatedConstructorsForTypeArguments(superType, baseTypeNode.typeArguments);
return resolveCall(node, baseConstructors, candidatesOutArray);
return resolveCall(node, baseConstructors, candidatesOutArray, partialApplication);
}
}
return resolveUntypedCall(node);
@@ -13134,7 +13177,7 @@ namespace ts {
}
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray);
return resolveCall(node, callSignatures, candidatesOutArray, partialApplication);
}
/**
@@ -13213,7 +13256,7 @@ namespace ts {
if (!isConstructorAccessible(node, constructSignatures[0])) {
return resolveErrorCall(node);
}
return resolveCall(node, constructSignatures, candidatesOutArray);
return resolveCall(node, constructSignatures, candidatesOutArray, /*allowPartialApplication*/ false);
}
// If expressionType's apparent type is an object type with no construct signatures but
@@ -13222,7 +13265,7 @@ namespace ts {
// operation is Any. It is an error to have a Void this type.
const callSignatures = getSignaturesOfType(expressionType, SignatureKind.Call);
if (callSignatures.length) {
const signature = resolveCall(node, callSignatures, candidatesOutArray);
const signature = resolveCall(node, callSignatures, candidatesOutArray, /*allowPartialApplication*/ false);
if (getReturnTypeOfSignature(signature) !== voidType) {
error(node, Diagnostics.Only_a_void_function_can_be_called_with_the_new_keyword);
}
@@ -13299,7 +13342,7 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray);
return resolveCall(node, callSignatures, candidatesOutArray, /*partialApplication*/ false);
}
/**
@@ -13349,19 +13392,44 @@ namespace ts {
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, headMessage);
return resolveCall(node, callSignatures, candidatesOutArray, /*allowPartialApplication*/ false, headMessage);
}
function resolveSignature(node: CallLikeExpression, candidatesOutArray?: Signature[]): Signature {
function resolvePipelineExpression(node: PipelineExpression, candidatesOutArray: Signature[]): Signature {
const funcType = checkExpression(node.right);
const apparentType = getApparentType(funcType);
if (apparentType === unknownType) {
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);
}
if (!callSignatures.length) {
return resolveErrorCall(node);
}
return resolveCall(node, callSignatures, candidatesOutArray, /*partialApplication*/ false);
}
function resolveSignature(node: CallLikeExpression, partialApplication: false, candidatesOutArray?: Signature[]): Signature;
function resolveSignature(node: CallLikeExpression, partialApplication: true, candidatesOutArray?: Signature[]): Signature[];
function resolveSignature(node: CallLikeExpression, partialApplication: boolean, candidatesOutArray?: Signature[]): Signature | Signature[];
function resolveSignature(node: CallLikeExpression, partialApplication: boolean, candidatesOutArray?: Signature[]): Signature | Signature[] {
switch (node.kind) {
case SyntaxKind.CallExpression:
return resolveCallExpression(<CallExpression>node, candidatesOutArray);
return resolveCallExpression(<CallExpression>node, partialApplication, candidatesOutArray);
case SyntaxKind.NewExpression:
return resolveNewExpression(<NewExpression>node, candidatesOutArray);
case SyntaxKind.TaggedTemplateExpression:
return resolveTaggedTemplateExpression(<TaggedTemplateExpression>node, candidatesOutArray);
case SyntaxKind.Decorator:
return resolveDecorator(<Decorator>node, candidatesOutArray);
case SyntaxKind.BinaryExpression:
return resolvePipelineExpression(<PipelineExpression>node, candidatesOutArray);
}
Debug.fail("Branch in 'resolveSignature' should be unreachable.");
}
@@ -13379,7 +13447,7 @@ namespace ts {
return cached;
}
links.resolvedSignature = resolvingSignature;
const result = resolveSignature(node, candidatesOutArray);
const result = resolveSignature(node, /*allowPartialApplication*/ false, 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.
@@ -13387,6 +13455,25 @@ namespace ts {
return result;
}
function getResolvedPartialSignatures(node: CallLikeExpression, candidatesOutArray?: Signature[]): 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 && !candidatesOutArray) {
return cached;
}
links.resolvedPartialSignatures = resolvingPartialSignatures;
const result = resolveSignature(node, /*partialApplication*/ true, 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.
links.resolvedPartialSignatures = flowLoopStart === flowLoopCount ? result : cached;
return result;
}
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.
@@ -13410,7 +13497,9 @@ namespace ts {
// Grammar checking; stop grammar-checking if checkGrammarTypeArguments return true
checkGrammarTypeArguments(node, node.typeArguments) || checkGrammarArguments(node, node.arguments);
const signature = getResolvedSignature(node);
const partialApplication = node.kind === SyntaxKind.CallExpression && forEach(node.arguments, isPositionalOrPositionalSpreadElement);
const signatures = partialApplication && getResolvedPartialSignatures(node);
const signature = !partialApplication && getResolvedSignature(node);
if (node.expression.kind === SyntaxKind.SuperKeyword) {
return voidType;
@@ -13448,7 +13537,123 @@ namespace ts {
return resolveExternalModuleTypeByLiteral(<StringLiteral>node.arguments[0]);
}
return getReturnTypeOfSignature(signature);
return partialApplication ?
getPartialApplicationOfSignatures(node.arguments, signatures) :
getReturnTypeOfSignature(signature);
}
function getPartialApplicationOfSignatures(argumentList: Expression[], signatures: Signature[]) {
const partialSignatures: Signature[] = [];
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;
}
function getPartialApplicationOfSignature(argumentList: Expression[], signature: Signature) {
const uniqueParameterNames = createMap<boolean>();
for (const parameter of signature.parameters) {
uniqueParameterNames[parameter.name] = true;
}
let 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;
if (argument.literal) {
ordinalPosition = +argument.literal.text;
}
else {
ordinalPosition = position;
position++;
}
if (!positionalParameters) {
positionalParameters = [];
}
const type = getTypeAtPosition(signature, i);
const previousParameter = positionalParameters[ordinalPosition];
if (previousParameter) {
if (previousParameter.name === previousParameter.target.name) {
previousParameter.name = getUniqueName(uniqueParameterNames, `arg${ordinalPosition}`);
}
previousParameter.type = getIntersectionType([previousParameter.type, type]);
}
else if (parameter) {
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;
}
}
else if (isPositionalSpreadElement(argument)) {
const type = getRestTypeOfSignature(signature);
if (positionalRestParameter) {
if (positionalRestParameter.name === positionalRestParameter.target.name) {
positionalRestParameter.name = getUniqueName(uniqueParameterNames, `args`);
}
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`);
positionalRestParameter = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
positionalRestParameter.type = type;
positionalRestParameter.transientSymbolIsRest = true;
}
}
}
positionalParameters = append(positionalParameters, positionalRestParameter) || [];
for (let i = 0; i < positionalParameters.length; i++) {
if (!positionalParameters[i]) {
const name = getUniqueName(uniqueParameterNames, `arg${i}`);
positionalParameters[i] = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, name);
positionalParameters[i].type = anyType;
// TODO(rbuckton): implicit any error
}
}
return createSignature(
/*declaration*/ undefined,
signature.typeParameters,
signature.thisParameter,
positionalParameters,
getReturnTypeOfSignature(signature),
signature.typePredicate,
position,
positionalRestParameter !== undefined,
signature.hasLiteralTypes);
}
function getUniqueName(uniqueNames: Map<boolean>, name: string) {
let uniqueName = name;
let index = 0;
while (uniqueNames[uniqueName]) {
uniqueName = `${name}_${index}`;
index++;
}
uniqueNames[uniqueName] = true;
return uniqueName;
}
function isCommonJsRequire(node: Node) {
@@ -13959,6 +14164,112 @@ namespace ts {
}
}
function checkOperatorExpression(node: OperatorExpression) {
return operatorExpressionTypes[node.operator] || (operatorExpressionTypes[node.operator] = createOperatorExpressionType(node.operator));
}
function createBinaryOperatorType(typeParameters: TypeParameter[], leftType: Type, rightType: Type, returnType: Type) {
return getOrCreateTypeFromSignature(createBinaryOperatorSignature(typeParameters, leftType, rightType, returnType));
}
function createBinaryOperatorSignature(typeParameters: TypeParameter[], leftType: Type, rightType: Type, returnType: Type) {
const left = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, "a");
left.type = leftType;
const right = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, "b");
right.type = rightType;
return createSignature(
/*isConstruct*/ false,
typeParameters,
/*thisParameter*/ undefined,
[left, right],
returnType,
/*typePredicate*/ undefined,
2,
/*hasRestParameter*/ false,
/*hasLiteralTypes*/ false
);
}
function createUnaryOperatorType(operandType: Type, returnType: Type) {
return getOrCreateTypeFromSignature(createUnaryOperatorSignature(operandType, returnType));
}
function createUnaryOperatorSignature(operandType: Type, returnType: Type) {
const operand = <TransientSymbol>createSymbol(SymbolFlags.Transient | SymbolFlags.Variable, "a");
operand.type = operandType;
return createSignature(
/*isConstruct*/ false,
/*typeParameters*/ undefined,
/*thisParameter*/ undefined,
[operand],
returnType,
/*typePredicate*/ undefined,
1,
/*hasRestParameter*/ false,
/*hasLiteralTypes*/ false
);
}
function createOperatorExpressionType(operator: SyntaxKind) {
switch (operator) {
case SyntaxKind.PlusToken:
const signatures = [
createBinaryOperatorSignature(undefined, stringType, stringType, stringType),
createBinaryOperatorSignature(undefined, stringType, numberType, stringType),
createBinaryOperatorSignature(undefined, numberType, stringType, stringType),
createBinaryOperatorSignature(undefined, numberType, numberType, numberType),
]
const plusType = createObjectType(ObjectFlags.Anonymous);
(<ResolvedType>plusType).members = emptySymbols;
(<ResolvedType>plusType).properties = emptyArray;
(<ResolvedType>plusType).callSignatures = signatures;
(<ResolvedType>plusType).constructSignatures = emptyArray;
return plusType;
case SyntaxKind.AsteriskToken:
case SyntaxKind.AsteriskAsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.BarToken:
case SyntaxKind.CaretToken:
case SyntaxKind.AmpersandToken:
return createBinaryOperatorType(undefined, numberType, numberType, numberType);
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanEqualsToken:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
// TODO: type parameters
return createBinaryOperatorType(undefined, anyType, anyType, booleanType);
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
// TODO: type parameters
return createBinaryOperatorType(undefined, anyType, anyType, anyType);
case SyntaxKind.TildeToken:
case SyntaxKind.TildePlusToken:
case SyntaxKind.TildeMinusToken:
return createUnaryOperatorType(anyType, numberType);
case SyntaxKind.ExclamationToken:
return createUnaryOperatorType(anyType, booleanType);
case SyntaxKind.VoidKeyword:
return createUnaryOperatorType(anyType, voidType);
case SyntaxKind.TypeOfKeyword:
return createUnaryOperatorType(anyType, stringType);
}
}
function checkArithmeticOperandType(operand: Node, type: Type, diagnostic: DiagnosticMessage): boolean {
if (!isTypeAnyOrAllConstituentTypesHaveKind(type, TypeFlags.NumberLike)) {
error(operand, diagnostic);
@@ -14413,6 +14724,9 @@ namespace ts {
}
function checkBinaryExpression(node: BinaryExpression, contextualMapper?: TypeMapper) {
if (node.operatorToken.kind === SyntaxKind.BarGreaterThanToken) {
return checkPipelineExpression(<PipelineExpression>node);
}
return checkBinaryLikeExpression(node.left, node.operatorToken, node.right, contextualMapper, node);
}
@@ -14421,6 +14735,7 @@ namespace ts {
if (operator === SyntaxKind.EqualsToken && (left.kind === SyntaxKind.ObjectLiteralExpression || left.kind === SyntaxKind.ArrayLiteralExpression)) {
return checkDestructuringAssignment(left, checkExpression(right, contextualMapper), contextualMapper);
}
let leftType = checkExpression(left, contextualMapper);
let rightType = checkExpression(right, contextualMapper);
switch (operator) {
@@ -14625,6 +14940,11 @@ namespace ts {
}
}
function checkPipelineExpression(node: PipelineExpression) {
const signature = getResolvedSignature(node);
return getReturnTypeOfSignature(signature);
}
function isYieldExpressionInClass(node: YieldExpression): boolean {
let current: Node = node;
let parent = node.parent;
@@ -14890,6 +15210,8 @@ namespace ts {
return checkTaggedTemplateExpression(<TaggedTemplateExpression>node);
case SyntaxKind.ParenthesizedExpression:
return checkExpression((<ParenthesizedExpression>node).expression, contextualMapper);
case SyntaxKind.OperatorExpression:
return checkOperatorExpression(<OperatorExpression>node);
case SyntaxKind.ClassExpression:
return checkClassExpression(<ClassExpression>node);
case SyntaxKind.FunctionExpression:
+17 -2
View File
@@ -651,7 +651,11 @@ namespace ts {
case SyntaxKind.YieldExpression:
return emitYieldExpression(<YieldExpression>node);
case SyntaxKind.SpreadElement:
return emitSpreadExpression(<SpreadElement>node);
return emitSpreadElement(<SpreadElement>node);
case SyntaxKind.PositionalElement:
return emitPositionalElement(<PositionalElement>node);
case SyntaxKind.OperatorExpression:
return emitOperatorExpression(<OperatorExpression>node);
case SyntaxKind.ClassExpression:
return emitClassExpression(<ClassExpression>node);
case SyntaxKind.OmittedExpression:
@@ -1222,11 +1226,22 @@ namespace ts {
emitExpressionWithPrefix(" ", node.expression);
}
function emitSpreadExpression(node: SpreadElement) {
function emitSpreadElement(node: SpreadElement) {
write("...");
emitExpression(node.expression);
}
function emitPositionalElement(node: PositionalElement) {
write("?");
emitExpression(node.literal);
}
function emitOperatorExpression(node: OperatorExpression) {
write("(");
writeTokenText(node.operator);
write(")");
}
function emitClassExpression(node: ClassExpression) {
emitClassDeclarationOrExpression(node);
}
+11 -12
View File
@@ -225,13 +225,12 @@ namespace ts {
}
// Signature elements
export function createParameter(decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression, location?: TextRange, flags?: NodeFlags) {
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter, location, flags);
export function createParameter(decorators?: Decorator[], modifiers?: Modifier[], dotDotDotToken?: DotDotDotToken, name?: string | Identifier | BindingPattern, questionToken?: QuestionToken, type?: TypeNode, initializer?: Expression, location?: TextRange) {
const node = <ParameterDeclaration>createNode(SyntaxKind.Parameter, location);
node.decorators = decorators ? createNodeArray(decorators) : undefined;
node.modifiers = modifiers ? createNodeArray(modifiers) : undefined;
node.dotDotDotToken = dotDotDotToken;
node.name = typeof name === "string" ? createIdentifier(name) : name;
node.name = typeof name === "string" ? createIdentifier(name) : name || createTempVariable(/*recordTempVariable*/ undefined);
node.questionToken = questionToken;
node.type = type;
node.initializer = initializer ? parenthesizeExpressionForList(initializer) : undefined;
@@ -240,7 +239,7 @@ namespace ts {
export function updateParameter(node: ParameterDeclaration, decorators: Decorator[], modifiers: Modifier[], dotDotDotToken: DotDotDotToken, name: BindingName, type: TypeNode, initializer: Expression) {
if (node.decorators !== decorators || node.modifiers !== modifiers || node.dotDotDotToken !== dotDotDotToken || node.name !== name || node.type !== type || node.initializer !== initializer) {
return updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node, /*flags*/ node.flags), node);
return updateNode(createParameter(decorators, modifiers, dotDotDotToken, name, node.questionToken, type, initializer, /*location*/ node), node);
}
return node;
@@ -703,7 +702,7 @@ namespace ts {
return node;
}
export function createSpread(expression: Expression, location?: TextRange) {
export function createSpreadElement(expression: Expression, location?: TextRange) {
const node = <SpreadElement>createNode(SyntaxKind.SpreadElement, location);
node.expression = parenthesizeExpressionForList(expression);
return node;
@@ -711,7 +710,7 @@ namespace ts {
export function updateSpread(node: SpreadElement, expression: Expression) {
if (node.expression !== expression) {
return updateNode(createSpread(expression, node), node);
return updateNode(createSpreadElement(expression, node), node);
}
return node;
}
@@ -1787,7 +1786,7 @@ namespace ts {
}
}
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean): CallBinding {
export function createCallBinding(expression: Expression, recordTempVariable: (temp: Identifier) => void, languageVersion?: ScriptTarget, cacheIdentifiers?: boolean, useThisAsDefaultThisArg?: boolean): CallBinding {
const callee = skipOuterExpressions(expression, OuterExpressionKinds.All);
let thisArg: Expression;
let target: LeftHandSideExpression;
@@ -1846,7 +1845,7 @@ namespace ts {
default: {
// for `a()` target is `a` and thisArg is `void 0`
thisArg = createVoidZero();
thisArg = useThisAsDefaultThisArg ? createThis() : createVoidZero();
target = parenthesizeForAccess(expression);
break;
}
@@ -3032,7 +3031,7 @@ namespace ts {
return bindingElement.right;
}
if (isSpreadExpression(bindingElement)) {
if (isSpreadElement(bindingElement)) {
// Recovery consistent with existing emit.
return getInitializerOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.expression);
}
@@ -3100,7 +3099,7 @@ namespace ts {
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.left);
}
if (isSpreadExpression(bindingElement)) {
if (isSpreadElement(bindingElement)) {
// `a` in `[...a] = ...`
return getTargetOfBindingOrAssignmentElement(<BindingOrAssignmentElement>bindingElement.expression);
}
@@ -3202,7 +3201,7 @@ namespace ts {
if (isBindingElement(element)) {
if (element.dotDotDotToken) {
Debug.assertNode(element.name, isIdentifier);
return setOriginalNode(createSpread(<Identifier>element.name, element), element);
return setOriginalNode(createSpreadElement(<Identifier>element.name, element), element);
}
const expression = convertToAssignmentElementTarget(<ObjectBindingPattern | ArrayBindingPattern | Identifier>element.name);
return element.initializer ? setOriginalNode(createAssignment(expression, element.initializer, element), element) : expression;
+107 -19
View File
@@ -1319,7 +1319,7 @@ namespace ts {
return isIdentifier();
case ParsingContext.ArgumentExpressions:
case ParsingContext.ArrayLiteralMembers:
return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || isStartOfExpression();
return token() === SyntaxKind.CommaToken || token() === SyntaxKind.DotDotDotToken || token() === SyntaxKind.QuestionToken || isStartOfExpression();
case ParsingContext.Parameters:
return isStartOfParameter();
case ParsingContext.TypeArguments:
@@ -3361,21 +3361,23 @@ namespace ts {
function getBinaryOperatorPrecedence(): number {
switch (token()) {
case SyntaxKind.BarBarToken:
case SyntaxKind.BarGreaterThanToken:
return 1;
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
return 2;
case SyntaxKind.BarToken:
case SyntaxKind.AmpersandAmpersandToken:
return 3;
case SyntaxKind.CaretToken:
case SyntaxKind.BarToken:
return 4;
case SyntaxKind.AmpersandToken:
case SyntaxKind.CaretToken:
return 5;
case SyntaxKind.AmpersandToken:
return 6;
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
return 6;
return 7;
case SyntaxKind.LessThanToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.LessThanEqualsToken:
@@ -3383,20 +3385,20 @@ namespace ts {
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.AsKeyword:
return 7;
return 8;
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
return 8;
return 9;
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
return 9;
return 10;
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
return 10;
case SyntaxKind.AsteriskAsteriskToken:
return 11;
case SyntaxKind.AsteriskAsteriskToken:
return 12;
}
// -1 is lower than all other precedences. Returning it will cause binary expression
@@ -4171,7 +4173,12 @@ namespace ts {
return parseIdentifier(Diagnostics.Expression_expected);
}
function parseParenthesizedExpression(): ParenthesizedExpression {
function parseParenthesizedExpression(): PrimaryExpression {
const operatorExpression = tryParse(parsePossibleOperatorExpression);
if (operatorExpression) {
return operatorExpression;
}
const node = <ParenthesizedExpression>createNode(SyntaxKind.ParenthesizedExpression);
parseExpected(SyntaxKind.OpenParenToken);
node.expression = allowInAnd(parseExpression);
@@ -4179,21 +4186,102 @@ namespace ts {
return finishNode(node);
}
function parseSpreadElement(): Expression {
function parsePossibleOperatorExpression() {
const fullStart = scanner.getStartPos();
parseExpected(SyntaxKind.OpenParenToken);
let operator = token();
switch (operator) {
case SyntaxKind.AsteriskAsteriskToken:
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.BarToken:
case SyntaxKind.CaretToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.ExclamationToken:
case SyntaxKind.VoidKeyword:
case SyntaxKind.TypeOfKeyword:
nextToken();
if (token() === SyntaxKind.CloseParenToken) {
nextToken();
const node = <OperatorExpression>createNode(SyntaxKind.OperatorExpression, fullStart);
node.operator = operator;
return finishNode(node);
}
return undefined;
case SyntaxKind.TildeToken:
nextToken();
if (token() === SyntaxKind.PlusToken) {
nextToken();
operator = SyntaxKind.TildePlusToken;
}
else if (token() === SyntaxKind.MinusToken) {
nextToken();
operator = SyntaxKind.TildeMinusToken;
}
if (token() === SyntaxKind.CloseParenToken) {
nextToken();
const node = <OperatorExpression>createNode(SyntaxKind.OperatorExpression, fullStart);
node.operator = operator;
return finishNode(node);
}
return undefined;
default:
return undefined;
}
}
function parseSpreadElement(isArgument: boolean): Expression {
const node = <SpreadElement>createNode(SyntaxKind.SpreadElement);
parseExpected(SyntaxKind.DotDotDotToken);
node.expression = parseAssignmentExpressionOrHigher();
node.expression = !isArgument || isStartOfExpression() ?
parseAssignmentExpressionOrHigher() :
<Expression>createNode(SyntaxKind.OmittedExpression);
return finishNode(node);
}
function parseArgumentOrArrayLiteralElement(): Expression {
return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement() :
function parsePositionalElement(): Expression {
const node = <PositionalElement>createNode(SyntaxKind.PositionalElement);
parseExpected(SyntaxKind.QuestionToken);
node.literal = token() === SyntaxKind.NumericLiteral ? <NumericLiteral>parseLiteralNode() : undefined;
return finishNode(node);
}
function parseArgument() {
return parseArgumentOrArrayLiteralElement(/*isArgument*/ true);
}
function parseArrayLiteralElement() {
return parseArgumentOrArrayLiteralElement(/*isArgument*/ false);
}
function parseArgumentOrArrayLiteralElement(isArgument: boolean): Expression {
return token() === SyntaxKind.DotDotDotToken ? parseSpreadElement(isArgument) :
token() === SyntaxKind.CommaToken ? <Expression>createNode(SyntaxKind.OmittedExpression) :
isArgument && token() === SyntaxKind.QuestionToken ? parsePositionalElement() :
parseAssignmentExpressionOrHigher();
}
function parseArgumentExpression(): Expression {
return doOutsideOfContext(disallowInAndDecoratorContext, parseArgumentOrArrayLiteralElement);
return doOutsideOfContext(disallowInAndDecoratorContext, parseArgument);
}
function parseArrayLiteralExpression(): ArrayLiteralExpression {
@@ -4202,7 +4290,7 @@ namespace ts {
if (scanner.hasPrecedingLineBreak()) {
node.multiLine = true;
}
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArgumentOrArrayLiteralElement);
node.elements = parseDelimitedList(ParsingContext.ArrayLiteralMembers, parseArrayLiteralElement);
parseExpected(SyntaxKind.CloseBracketToken);
return finishNode(node);
}
+6
View File
@@ -135,6 +135,7 @@ namespace ts {
"]": SyntaxKind.CloseBracketToken,
".": SyntaxKind.DotToken,
"...": SyntaxKind.DotDotDotToken,
"|>": SyntaxKind.BarGreaterThanToken,
";": SyntaxKind.SemicolonToken,
",": SyntaxKind.CommaToken,
"<": SyntaxKind.LessThanToken,
@@ -163,6 +164,8 @@ namespace ts {
"^": SyntaxKind.CaretToken,
"!": SyntaxKind.ExclamationToken,
"~": SyntaxKind.TildeToken,
"~+": SyntaxKind.TildePlusToken,
"~-": SyntaxKind.TildeMinusToken,
"&&": SyntaxKind.AmpersandAmpersandToken,
"||": SyntaxKind.BarBarToken,
"?": SyntaxKind.QuestionToken,
@@ -1551,6 +1554,9 @@ namespace ts {
if (text.charCodeAt(pos + 1) === CharacterCodes.equals) {
return pos += 2, token = SyntaxKind.BarEqualsToken;
}
if (text.charCodeAt(pos + 1) === CharacterCodes.greaterThan) {
return pos += 2, token = SyntaxKind.BarGreaterThanToken;
}
pos++;
return token = SyntaxKind.BarToken;
case CharacterCodes.closeBrace:
+2 -2
View File
@@ -2911,7 +2911,7 @@ namespace ts {
if (segments.length === 1) {
const firstElement = elements[0];
return needsUniqueCopy && isSpreadExpression(firstElement) && firstElement.expression.kind !== SyntaxKind.ArrayLiteralExpression
return needsUniqueCopy && isSpreadElement(firstElement) && firstElement.expression.kind !== SyntaxKind.ArrayLiteralExpression
? createArraySlice(segments[0])
: segments[0];
}
@@ -2921,7 +2921,7 @@ namespace ts {
}
function partitionSpread(node: Expression) {
return isSpreadExpression(node)
return isSpreadElement(node)
? visitSpanOfSpreads
: visitSpanOfNonSpreads;
}
+159 -6
View File
@@ -5,6 +5,7 @@
namespace ts {
export function transformESNext(context: TransformationContext) {
const {
startLexicalEnvironment,
resumeLexicalEnvironment,
endLexicalEnvironment
} = context;
@@ -66,6 +67,10 @@ namespace ts {
return visitExpressionStatement(node as ExpressionStatement);
case SyntaxKind.ParenthesizedExpression:
return visitParenthesizedExpression(node as ParenthesizedExpression, noDestructuringValue);
case SyntaxKind.CallExpression:
return visitCallExpression(node as CallExpression);
case SyntaxKind.OperatorExpression:
return visitOperatorExpression(node as OperatorExpression);
default:
return visitEachChild(node, visitor, context);
}
@@ -142,16 +147,64 @@ namespace ts {
!noDestructuringValue
);
}
else if (node.operatorToken.kind === SyntaxKind.CommaToken) {
return updateBinary(
node,
visitNode(node.left, visitorNoDestructuringValue, isExpression),
visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression)
);
switch (node.operatorToken.kind) {
case SyntaxKind.CommaToken:
return updateBinary(
node,
visitNode(node.left, visitorNoDestructuringValue, isExpression),
visitNode(node.right, noDestructuringValue ? visitorNoDestructuringValue : visitor, isExpression)
);
case SyntaxKind.BarGreaterThanToken:
return transformPipelineExpression(node);
}
return visitEachChild(node, visitor, context);
}
function transformPipelineExpression(node: BinaryExpression) {
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;
}
}
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);
}
else {
const parameterList: ParameterDeclaration[] = [];
const innerArgumentList: Expression[] = [];
for (let i = 0; i < argumentList.length; i++) {
const parameter = createParameter();
parameterList.push(parameter);
innerArgumentList.push(<Identifier>parameter.name);
}
return createCall(
createArrowFunction(
/*modifiers*/ undefined,
/*typeParameters*/ undefined,
parameterList,
/*type*/ undefined,
createToken(SyntaxKind.EqualsGreaterThanToken),
createCall(
func,
/*typeArguments*/ undefined,
innerArgumentList
)
),
/*typeArguments*/ undefined,
argumentList
);
}
}
/**
* Visits a VariableDeclaration node with a binding pattern.
*
@@ -384,6 +437,106 @@ namespace ts {
}
return body;
}
function visitCallExpression(node: CallExpression): Expression {
const expression = visitNode(node.expression, visitor, isExpression);
let position = 0;
let positionalParameters: ParameterDeclaration[];
let positionalRestParameter: ParameterDeclaration;
let argumentList: Expression[];
for (let i = 0; i < node.arguments.length; i++) {
const argument = node.arguments[i];
let updated: Expression;
if (isPositionalElement(argument)) {
if (!positionalParameters) {
positionalParameters = [];
}
if (argument.literal) {
position = +argument.literal.text;
}
const parameter = positionalParameters[position] || (positionalParameters[position] = createParameter());
updated = <Identifier>parameter.name;
position++;
}
else if (isPositionalSpreadElement(argument)) {
const parameter = positionalRestParameter || (positionalRestParameter = createParameter(/*decorators*/ undefined, /*modifiers*/ undefined, createToken(SyntaxKind.DotDotDotToken)));
updated = createSpreadElement(<Identifier>parameter.name);
}
else {
updated = visitNode(argument, visitor, isExpression);
}
if (argumentList || updated !== argument) {
if (!argumentList) {
argumentList = node.arguments.slice(0, i);
}
argumentList.push(updated);
}
}
if (positionalParameters || positionalRestParameter) {
startLexicalEnvironment();
if (positionalRestParameter) {
positionalParameters = append(positionalParameters, positionalRestParameter);
}
for (let i = 0; i < positionalParameters.length; i++) {
if (!positionalParameters[i]) {
positionalParameters[i] = createParameter();
}
}
return createArrowFunction(
/*modifiers*/ undefined,
/*typeParameters*/ undefined,
positionalParameters,
/*type*/ undefined,
/*equalsGreaterThanToken*/ createToken(SyntaxKind.EqualsGreaterThanToken),
updateCall(node, expression, /*typeArguments*/ undefined, argumentList),
/*location*/ node
);
}
return updateCall(node, expression, /*typeArguments*/ undefined, argumentList);
}
function visitOperatorExpression(node: OperatorExpression) {
let parameters: ParameterDeclaration[];
let expression: Expression;
if (isBinaryOperator(node.operator)) {
parameters = [createParameter(), createParameter()];
expression = createBinary(
<Identifier>parameters[0].name,
node.operator,
<Identifier>parameters[1].name
);
}
else {
parameters = [createParameter()];
switch (node.operator) {
case SyntaxKind.TildePlusToken:
expression = createPrefix(SyntaxKind.PlusToken, <Identifier>parameters[0].name, node);
break;
case SyntaxKind.TildeMinusToken:
expression = createPrefix(SyntaxKind.MinusToken, <Identifier>parameters[0].name, node);
break;
case SyntaxKind.TildeToken:
case SyntaxKind.ExclamationToken:
expression = createPrefix(node.operator, <Identifier>parameters[0].name, node);
break;
case SyntaxKind.VoidKeyword:
expression = createVoid(<Identifier>parameters[0].name, node);
break;
case SyntaxKind.TypeOfKeyword:
expression = createTypeOf(<Identifier>parameters[0].name, node);
break;
}
}
return createArrowFunction(
/*modifiers*/ undefined,
/*typeParameters*/ undefined,
parameters,
/*type*/ undefined,
createToken(SyntaxKind.EqualsGreaterThanToken),
expression,
node
);
}
}
const assignHelper: EmitHelper = {
+1 -1
View File
@@ -1497,7 +1497,7 @@ namespace ts {
if (isAssignmentExpression(node)) {
return hasExportedReferenceInDestructuringTarget(node.left);
}
else if (isSpreadExpression(node)) {
else if (isSpreadElement(node)) {
return hasExportedReferenceInDestructuringTarget(node.expression);
}
else if (isObjectLiteralExpression(node)) {
+1 -1
View File
@@ -892,7 +892,7 @@ namespace ts {
createCall(
createSuper(),
/*typeArguments*/ undefined,
[createSpread(createIdentifier("arguments"))]
[createSpreadElement(createIdentifier("arguments"))]
)
)
);
+34 -3
View File
@@ -62,7 +62,9 @@ namespace ts {
DotToken,
DotDotDotToken,
SemicolonToken,
BarGreaterThanToken,
CommaToken,
EqualsGreaterThanToken,
LessThanToken,
LessThanSlashToken,
GreaterThanToken,
@@ -72,7 +74,6 @@ namespace ts {
ExclamationEqualsToken,
EqualsEqualsEqualsToken,
ExclamationEqualsEqualsToken,
EqualsGreaterThanToken,
PlusToken,
MinusToken,
AsteriskToken,
@@ -89,6 +90,8 @@ namespace ts {
CaretToken,
ExclamationToken,
TildeToken,
TildePlusToken,
TildeMinusToken,
AmpersandAmpersandToken,
BarBarToken,
QuestionToken,
@@ -248,11 +251,13 @@ namespace ts {
TemplateExpression,
YieldExpression,
SpreadElement,
PositionalElement,
ClassExpression,
OmittedExpression,
ExpressionWithTypeArguments,
AsExpression,
NonNullExpression,
OperatorExpression,
// Misc
TemplateSpan,
@@ -1172,6 +1177,7 @@ namespace ts {
// see: https://tc39.github.io/ecma262/#prod-Expression
export type BinaryOperator
= AssignmentOperatorOrHigher
| SyntaxKind.BarGreaterThanToken
| SyntaxKind.CommaToken
;
@@ -1185,6 +1191,12 @@ namespace ts {
right: Expression;
}
export type BarGreaterThanToken = Token<SyntaxKind.BarGreaterThanToken>;
export interface PipelineExpression extends BinaryExpression {
operatorToken: BarGreaterThanToken;
}
export type AssignmentOperatorToken = Token<AssignmentOperator>;
export interface AssignmentExpression<TOperator extends AssignmentOperatorToken> extends BinaryExpression {
@@ -1332,6 +1344,11 @@ namespace ts {
expression: Expression;
}
export interface OperatorExpression extends PrimaryExpression {
kind: SyntaxKind.OperatorExpression;
operator: SyntaxKind;
}
export interface ArrayLiteralExpression extends PrimaryExpression {
kind: SyntaxKind.ArrayLiteralExpression;
elements: NodeArray<Expression>;
@@ -1344,6 +1361,10 @@ namespace ts {
expression: Expression;
}
export interface PositionalSpreadElement extends SpreadElement {
expression: OmittedExpression;
}
/**
* This interface is a base interface for ObjectLiteralExpression and JSXAttributes to extend from. JSXAttributes is similar to
* ObjectLiteralExpression in that it contains array of properties; however, JSXAttributes' properties can only be
@@ -1427,7 +1448,12 @@ namespace ts {
template: TemplateLiteral;
}
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator;
export type CallLikeExpression = CallExpression | NewExpression | TaggedTemplateExpression | Decorator | PipelineExpression;
export interface PositionalElement extends Expression {
kind: SyntaxKind.PositionalElement;
literal?: NumericLiteral;
}
export interface AsExpression extends Expression {
kind: SyntaxKind.AsExpression;
@@ -2688,7 +2714,9 @@ namespace ts {
}
/* @internal */
export interface TransientSymbol extends Symbol, SymbolLinks { }
export interface TransientSymbol extends Symbol, SymbolLinks {
transientSymbolIsRest?: boolean;
}
export type SymbolTable = Map<Symbol>;
@@ -2735,6 +2763,7 @@ 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
@@ -3021,6 +3050,8 @@ namespace ts {
typePredicate?: TypePredicate;
/* @internal */
instantiations?: Map<Signature>; // Generic signature instantiation cache
/* @internal */
isConstruct?: boolean;
}
export const enum IndexKind {
+48 -1
View File
@@ -3876,6 +3876,38 @@ namespace ts {
return node.kind === SyntaxKind.ElementAccessExpression;
}
export function isBinaryOperator(operator: SyntaxKind): operator is BinaryOperator {
switch (operator) {
case SyntaxKind.AsteriskAsteriskToken:
case SyntaxKind.AsteriskToken:
case SyntaxKind.SlashToken:
case SyntaxKind.PercentToken:
case SyntaxKind.PlusToken:
case SyntaxKind.MinusToken:
case SyntaxKind.LessThanLessThanToken:
case SyntaxKind.GreaterThanGreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanGreaterThanToken:
case SyntaxKind.LessThanToken:
case SyntaxKind.LessThanEqualsToken:
case SyntaxKind.GreaterThanToken:
case SyntaxKind.GreaterThanGreaterThanEqualsToken:
case SyntaxKind.InstanceOfKeyword:
case SyntaxKind.InKeyword:
case SyntaxKind.EqualsEqualsToken:
case SyntaxKind.EqualsEqualsEqualsToken:
case SyntaxKind.ExclamationEqualsToken:
case SyntaxKind.ExclamationEqualsEqualsToken:
case SyntaxKind.AmpersandToken:
case SyntaxKind.BarToken:
case SyntaxKind.CaretToken:
case SyntaxKind.AmpersandAmpersandToken:
case SyntaxKind.BarBarToken:
case SyntaxKind.BarGreaterThanToken:
return true;
}
return false;
}
export function isBinaryExpression(node: Node): node is BinaryExpression {
return node.kind === SyntaxKind.BinaryExpression;
}
@@ -3894,10 +3926,23 @@ namespace ts {
|| kind === SyntaxKind.NoSubstitutionTemplateLiteral;
}
export function isSpreadExpression(node: Node): node is SpreadElement {
export function isSpreadElement(node: Node): node is SpreadElement {
return node.kind === SyntaxKind.SpreadElement;
}
export function isPositionalSpreadElement(node: Node): node is PositionalSpreadElement {
return node.kind === SyntaxKind.SpreadElement
&& (<SpreadElement>node).expression.kind === SyntaxKind.OmittedExpression;
}
export function isPositionalElement(node: Node): node is PositionalElement {
return node.kind === SyntaxKind.PositionalElement;
}
export function isPositionalOrPositionalSpreadElement(node: Node): node is PositionalElement | PositionalSpreadElement {
return isPositionalElement(node) || isPositionalSpreadElement(node);
}
export function isExpressionWithTypeArguments(node: Node): node is ExpressionWithTypeArguments {
return node.kind === SyntaxKind.ExpressionWithTypeArguments;
}
@@ -3912,6 +3957,7 @@ namespace ts {
|| kind === SyntaxKind.TaggedTemplateExpression
|| kind === SyntaxKind.ArrayLiteralExpression
|| kind === SyntaxKind.ParenthesizedExpression
|| kind === SyntaxKind.OperatorExpression
|| kind === SyntaxKind.ObjectLiteralExpression
|| kind === SyntaxKind.ClassExpression
|| kind === SyntaxKind.FunctionExpression
@@ -3955,6 +4001,7 @@ namespace ts {
|| kind === SyntaxKind.ArrowFunction
|| kind === SyntaxKind.BinaryExpression
|| kind === SyntaxKind.SpreadElement
|| kind === SyntaxKind.PositionalElement
|| kind === SyntaxKind.AsExpression
|| kind === SyntaxKind.OmittedExpression
|| kind === SyntaxKind.RawExpression