diff --git a/tsc/internal/parser/jsdoc.go b/tsc/internal/parser/jsdoc.go index 6d239d2f228fc..650cb66892d22 100644 --- a/tsc/internal/parser/jsdoc.go +++ b/tsc/internal/parser/jsdoc.go @@ -54,7 +54,7 @@ const ( ) func (p *Parser) withJSDoc(node *ast.Node, info jsdocScannerInfo) []*ast.Node { - if info&jsdocScannerInfoHasJSDoc == 0 { + if info&jsdocScannerInfoHasJSDoc == 0 || p.parsingFlags&ParsingFlagsTentative != 0 { return nil } diff --git a/tsc/internal/parser/parser.go b/tsc/internal/parser/parser.go index c670d64ad21c2..ea6c0de4cba27 100644 --- a/tsc/internal/parser/parser.go +++ b/tsc/internal/parser/parser.go @@ -62,6 +62,20 @@ const ( jsdocScannerInfoHasSeeOrLink ) +type functionSignature struct { + modifiers *ast.ModifierList + typeParameters *ast.NodeList + parameters *ast.NodeList + returnType *ast.Node +} + +type tentativeExpression struct { + expressions collections.Set[int] + heads []int + contextFlags ast.NodeFlags + result core.Tristate +} + type Parser struct { scanner *scanner.Scanner factory ast.NodeFactory @@ -85,6 +99,9 @@ type Parser struct { identifierCount int notParenthesizedArrow collections.Set[int] + tentativeExpression *tentativeExpression + tentativeNodes map[int][]tentativeNode + parsingFlags ParsingFlags nodeSliceArena core.Arena[*ast.Node] stringSliceArena core.Arena[string] jsdocInfos []JSDocInfo @@ -327,6 +344,9 @@ func (p *Parser) parseErrorAtCurrentToken(message *diagnostics.Message, args ... } func (p *Parser) parseErrorAtRange(loc core.TextRange, message *diagnostics.Message, args ...any) *ast.Diagnostic { + if p.parsingFlags&ParsingFlagsTentative != 0 { + panic(tentativeParseFailure{}) + } // Don't report another error if it would just be at the same location as the last error var result *ast.Diagnostic if len(p.diagnostics) == 0 || p.diagnostics[len(p.diagnostics)-1].Pos() != loc.Pos() { @@ -338,46 +358,67 @@ func (p *Parser) parseErrorAtRange(loc core.TextRange, message *diagnostics.Mess } type ParserState struct { + tentativeExpression *tentativeExpression + tentativeNodes map[int][]tentativeNode + identifierCount int scannerState scanner.ScannerState contextFlags ast.NodeFlags diagnosticsLen int jsDiagnosticsLen int + jsdocDiagnosticsLen int jsdocInfosLen int reparsedClonesLen int + reparseList []*ast.Node statementHasAwaitIdentifier bool hasParseError bool } func (p *Parser) mark() ParserState { return ParserState{ + tentativeExpression: p.tentativeExpression, + tentativeNodes: p.tentativeNodes, + identifierCount: p.identifierCount, scannerState: p.scanner.Mark(), contextFlags: p.contextFlags, diagnosticsLen: len(p.diagnostics), jsDiagnosticsLen: len(p.jsDiagnostics), + jsdocDiagnosticsLen: len(p.jsdocDiagnostics), jsdocInfosLen: len(p.jsdocInfos), reparsedClonesLen: len(p.reparsedClones), + reparseList: p.reparseList, statementHasAwaitIdentifier: p.statementHasAwaitIdentifier, hasParseError: p.hasParseError, } } func (p *Parser) rewind(state ParserState) { + p.tentativeExpression = state.tentativeExpression + p.tentativeNodes = state.tentativeNodes + p.identifierCount = state.identifierCount p.scanner.Rewind(state.scannerState) p.token = p.scanner.Token() p.contextFlags = state.contextFlags p.diagnostics = p.diagnostics[0:state.diagnosticsLen] p.jsDiagnostics = p.jsDiagnostics[0:state.jsDiagnosticsLen] + p.jsdocDiagnostics = p.jsdocDiagnostics[0:state.jsdocDiagnosticsLen] p.jsdocInfos = p.jsdocInfos[0:state.jsdocInfosLen] p.reparsedClones = p.reparsedClones[0:state.reparsedClonesLen] + p.reparseList = state.reparseList p.statementHasAwaitIdentifier = state.statementHasAwaitIdentifier p.hasParseError = state.hasParseError } func (p *Parser) lookAhead(callback func(p *Parser) bool) bool { - state := p.mark() - result := callback(p) - p.rewind(state) - return result + if p.parsingFlags == ParsingFlagsNone { + state := p.mark() + result := callback(p) + p.rewind(state) + return result + } + tentative := p.beginTentativeParse() + defer tentative.close() + p.parsingFlags = ParsingFlagsNone + return callback(p) } func (p *Parser) nextToken() ast.Kind { @@ -2826,13 +2867,10 @@ func (p *Parser) parseNonArrayType() *ast.Node { switch p.token { case ast.KindAnyKeyword, ast.KindUnknownKeyword, ast.KindStringKeyword, ast.KindNumberKeyword, ast.KindBigIntKeyword, ast.KindSymbolKeyword, ast.KindBooleanKeyword, ast.KindUndefinedKeyword, ast.KindNeverKeyword, ast.KindObjectKeyword: - state := p.mark() - keywordTypeNode := p.parseKeywordTypeNode() - // If these are followed by a dot then parse these out as a dotted type reference instead - if p.token != ast.KindDotToken { + keywordTypeNode := p.tryParseKeywordTypeNode() + if keywordTypeNode != nil { return keywordTypeNode } - p.rewind(state) return p.parseTypeReference() case ast.KindAsteriskEqualsToken: // If there is '*=', treat it as * followed by postfix = @@ -2892,6 +2930,17 @@ func (p *Parser) parseNonArrayType() *ast.Node { } } +func (p *Parser) tryParseKeywordTypeNode() *ast.Node { + tentative := p.beginTentativeParse() + defer tentative.close() + node := p.parseKeywordTypeNode() + if p.token == ast.KindDotToken { + return nil + } + tentative.commit() + return node +} + func (p *Parser) parseKeywordTypeNode() *ast.Node { pos := p.nodePos() result := p.factory.NewKeywordTypeNode(p.token) @@ -4014,20 +4063,28 @@ func (p *Parser) tryParseModifier(hasSeenStaticModifier bool, permitConstAsModif } func (p *Parser) parseContextualModifier(t ast.Kind) bool { - state := p.mark() - if p.token == t && p.nextTokenCanFollowModifier() { + if p.token != t { + return false + } + tentative := p.beginTentativeParse() + defer tentative.close() + if p.nextTokenCanFollowModifier() { + tentative.commit() return true } - p.rewind(state) return false } func (p *Parser) parseAnyContextualModifier() bool { - state := p.mark() - if ast.IsModifierKind(p.token) && p.nextTokenCanFollowModifier() { + if !ast.IsModifierKind(p.token) { + return false + } + tentative := p.beginTentativeParse() + defer tentative.close() + if p.nextTokenCanFollowModifier() { + tentative.commit() return true } - p.rewind(state) return false } @@ -4148,11 +4205,24 @@ func (p *Parser) parseExpressionAllowIn() *ast.Expression { return p.doInContext(ast.NodeFlagsDisallowInContext, false, (*Parser).parseExpression) } -func (p *Parser) parseAssignmentExpressionOrHigher() *ast.Expression { - return p.parseAssignmentExpressionOrHigherWorker(true /*allowReturnTypeInArrowFunction*/) +func (p *Parser) parseAssignmentExpressionOrHigher() (expression *ast.Expression) { + if p.parsingFlags&ParsingFlagsTentative != 0 { + pos := p.nodePos() + node := p.getTentativeNode(pos) + if node == nil { + defer p.recordTentativeNode(pos, p.contextFlags, &expression) + } else { + return node + } + } + scope := p.beginTentativeScope() + scope.suspendExpression() + expression = p.parseAssignmentExpressionOrHigherWorker(ExpressionParseFlagsNone) + scope.restore() + return expression } -func (p *Parser) parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowFunction bool) *ast.Expression { +func (p *Parser) parseAssignmentExpressionOrHigherWorker(flags ExpressionParseFlags) *ast.Expression { // AssignmentExpression[in,yield]: // 1) ConditionalExpression[?in,?yield] // 2) LeftHandSideExpression = AssignmentExpression[?in,?yield] @@ -4165,7 +4235,7 @@ func (p *Parser) parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowF // (i.e. they're both BinaryExpressions with an assignment operator in it). // First, do the simple check if we have a YieldExpression (production '6'). if p.isYieldExpression() { - return p.parseYieldExpression() + return p.parseYieldExpression(flags) } // Then, check if we have an arrow function (production '4' and '5') that starts with a parenthesized // parameter list or is an async arrow function. @@ -4178,18 +4248,14 @@ func (p *Parser) parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowF // If we do successfully parse arrow-function, we must *not* recurse for productions 1, 2 or 3. An ArrowFunction is // not a LeftHandSideExpression, nor does it start a ConditionalExpression. So we are done // with AssignmentExpression if we see one. - arrowExpression := p.tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) + arrowExpression := p.tryParseParenthesizedArrowFunctionExpression(flags) if arrowExpression != nil { return arrowExpression } - arrowExpression = p.tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction) + arrowExpression = p.tryParseAsyncSimpleArrowFunctionExpression(flags) if arrowExpression != nil { return arrowExpression } - // arrowExpression2 := p.tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction) - // if arrowExpression2 != nil { - // return arrowExpression2 - // } // Now try to see if we're in production '1', '2' or '3'. A conditional expression can // start with a LogicalOrExpression, while the assignment productions can only start with // LeftHandSideExpressions. @@ -4206,7 +4272,7 @@ func (p *Parser) parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowF // parameter ('x => ...') above. We handle it here by checking if the parsed expression was a single // identifier and the current token is an arrow. if expr.Kind == ast.KindIdentifier && p.token == ast.KindEqualsGreaterThanToken { - return p.parseSimpleArrowFunctionExpression(pos, expr, allowReturnTypeInArrowFunction, jsdoc, nil /*asyncModifier*/) + return p.parseSimpleArrowFunctionExpression(pos, expr, flags, jsdoc, nil /*asyncModifier*/) } // Now see if we might be in cases '2' or '3'. // If the expression was a LHS expression, and we have an assignment operator, then @@ -4215,10 +4281,12 @@ func (p *Parser) parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowF // Note: we call reScanGreaterToken so that we get an appropriately merged token // for cases like `> > =` becoming `>>=` if ast.IsLeftHandSideExpression(expr) && ast.IsAssignmentOperator(p.reScanGreaterThanToken()) { - return p.makeBinaryExpression(expr, p.parseTokenNode(), p.parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowFunction), pos) + operatorToken := p.parseTokenNode() + right := p.parseAssignmentExpressionOrHigherWorker(flags) + return p.makeBinaryExpression(expr, operatorToken, right, pos) } // It wasn't an assignment or a lambda. This is a conditional expression: - return p.parseConditionalExpressionRest(expr, pos, allowReturnTypeInArrowFunction) + return p.parseConditionalExpressionRest(expr, pos, flags) } func (p *Parser) isYieldExpression() bool { @@ -4248,7 +4316,7 @@ func (p *Parser) isYieldExpression() bool { return false } -func (p *Parser) parseYieldExpression() *ast.Node { +func (p *Parser) parseYieldExpression(flags ExpressionParseFlags) *ast.Node { pos := p.nodePos() // YieldExpression[In] : // yield @@ -4257,7 +4325,9 @@ func (p *Parser) parseYieldExpression() *ast.Node { p.nextToken() var result *ast.Node if !p.hasPrecedingLineBreak() && (p.token == ast.KindAsteriskToken || p.isStartOfExpression()) { - result = p.factory.NewYieldExpression(p.parseOptionalToken(ast.KindAsteriskToken), p.parseAssignmentExpressionOrHigher()) + asteriskToken := p.parseOptionalToken(ast.KindAsteriskToken) + expression := p.parseAssignmentExpressionOrHigherWorker(flags) + result = p.factory.NewYieldExpression(asteriskToken, expression) } else { // if the next token is not on the same line as yield. or we don't have an '*' or // the start of an expression, then this is just a simple "yield" expression. @@ -4268,10 +4338,9 @@ func (p *Parser) parseYieldExpression() *ast.Node { func (p *Parser) isParenthesizedArrowFunctionExpression() core.Tristate { if p.token == ast.KindOpenParenToken || p.token == ast.KindLessThanToken || p.token == ast.KindAsyncKeyword { - state := p.mark() - result := p.nextIsParenthesizedArrowFunctionExpression() - p.rewind(state) - return result + tentative := p.beginTentativeParse() + defer tentative.close() + return p.nextIsParenthesizedArrowFunctionExpression() } if p.token == ast.KindEqualsGreaterThanToken { // ERROR RECOVERY TWEAK: @@ -4284,7 +4353,8 @@ func (p *Parser) isParenthesizedArrowFunctionExpression() core.Tristate { } func (p *Parser) nextIsParenthesizedArrowFunctionExpression() core.Tristate { - if p.token == ast.KindAsyncKeyword { + isAsync := p.token == ast.KindAsyncKeyword + if isAsync { p.nextToken() if p.hasPrecedingLineBreak() { return core.TSFalse @@ -4298,16 +4368,27 @@ func (p *Parser) nextIsParenthesizedArrowFunctionExpression() core.Tristate { if first == ast.KindOpenParenToken { if second == ast.KindCloseParenToken { // Simple cases: "() =>", "(): ", and "() {". - // This is an arrow function with no parameters. // The last one is not actually an arrow function, // but this is probably what the user intended. - third := p.nextToken() - switch third { - case ast.KindEqualsGreaterThanToken, ast.KindColonToken, ast.KindOpenBraceToken: + switch p.nextToken() { + case ast.KindColonToken: + if isAsync { + return core.TSUnknown + } + return core.TSTrue + case ast.KindEqualsGreaterThanToken, ast.KindOpenBraceToken: return core.TSTrue } return core.TSFalse } + // Simple case: "(...". After "async", this could also be a spread argument. + if second == ast.KindDotDotDotToken { + if isAsync { + second = p.nextToken() + } else { + return core.TSTrue + } + } // If encounter "([" or "({", this could be the start of a binding pattern. // Examples: // ([ x ]) => { } @@ -4317,11 +4398,6 @@ func (p *Parser) nextIsParenthesizedArrowFunctionExpression() core.Tristate { if second == ast.KindOpenBracketToken || second == ast.KindOpenBraceToken { return core.TSUnknown } - // Simple case: "(..." - // This is an arrow function with a rest parameter. - if second == ast.KindDotDotDotToken { - return core.TSTrue - } // Check for "(xxx yyy", where xxx is a modifier and yyy is an identifier. This // isn't actually allowed, but we want to treat it as a lambda so we can provide // a good error message. @@ -4391,30 +4467,142 @@ func (p *Parser) nextIsParenthesizedArrowFunctionExpression() core.Tristate { } } -func (p *Parser) tryParseParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction bool) *ast.Node { - tristate := p.isParenthesizedArrowFunctionExpression() - if tristate == core.TSFalse { - // It's definitely not a parenthesized arrow function expression. +func (p *Parser) tryParseParenthesizedArrowFunctionExpression(flags ExpressionParseFlags) *ast.Node { + result := p.isParenthesizedArrowFunctionExpression() + if result == core.TSFalse { return nil } - // If we definitely have an arrow function, then we can just parse one, not requiring a - // following => or { token. Otherwise, we *might* have an arrow function. Try to parse - // it out, but don't allow any ambiguity, and return 'undefined' if this could be an - // expression instead. - if tristate == core.TSTrue { - return p.parseParenthesizedArrowFunctionExpression(true /*allowAmbiguity*/, true /*allowReturnTypeInArrowFunction*/) - } - state := p.mark() - result := p.parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction) - if result == nil { - p.rewind(state) + if result == core.TSTrue { + flags |= ExpressionParseFlagsAllowArrowFunctionRecovery } - return result + return p.parseParenthesizedArrowFunctionExpression(flags) } -func (p *Parser) parseParenthesizedArrowFunctionExpression(allowAmbiguity bool, allowReturnTypeInArrowFunction bool) *ast.Node { +func (p *Parser) parseParenthesizedArrowFunctionExpression(flags ExpressionParseFlags) *ast.Node { pos := p.nodePos() jsdoc := p.jsdocScannerInfo() + + var tentative tentativeParse + if flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 { + tentative = p.beginTentativeParse() + defer tentative.close() + } + + result, signature := p.tryParseArrowFunctionHead(flags) + if result == core.TSFalse { + return nil + } + + isAsync := modifierListHasAsync(signature.modifiers) + requiresColon := result == core.TSUnknown + bodyFlags := flags & (ExpressionParseFlagsDisallowArrowReturnType | ExpressionParseFlagsAllowAmbiguousAsyncArrow) + if requiresColon && !isAsync { + bodyFlags |= ExpressionParseFlagsAllowAmbiguousAsyncArrow + } + + expression := p.tentativeExpression + switch result { + case core.TSTrue: + tentative.commit() + case core.TSUnknown: + if p.token == ast.KindEqualsGreaterThanToken && (expression == nil || expression.result != core.TSFalse) { + if expression == nil { + tentative.commit() + panic(tentativeParseFailure{}) + } + if expression.expressions.Has(pos) { + return nil + } + if expression.result == core.TSUnknown && p.isArrowFunctionHeadAmbiguous(tentative.state, signature.returnType) { + debug.Assert(len(expression.heads) == 0 || expression.heads[len(expression.heads)-1] < pos) + expression.heads = append(expression.heads, pos) + } + tentative.commit() + } + } + lastToken := p.token + equalsGreaterThanToken := p.parseExpectedToken(ast.KindEqualsGreaterThanToken) + + var body *ast.Node + if lastToken == ast.KindEqualsGreaterThanToken || lastToken == ast.KindOpenBraceToken { + body = p.parseArrowFunctionExpressionBody(isAsync, bodyFlags) + } else { + body = p.parseIdentifier() + } + if requiresColon && p.token != ast.KindColonToken { + if lastToken == ast.KindOpenBraceToken || expression == nil || expression.result == core.TSFalse { + return nil + } + if expression.result == core.TSUnknown { + panic(tentativeParseFailure{}) + } + } + node := p.finishNode(p.factory.NewArrowFunction(signature.modifiers, signature.typeParameters, signature.parameters, signature.returnType, nil /*fullSignature*/, equalsGreaterThanToken, body), pos) + p.withJSDoc(node, jsdoc) + p.checkJSSyntax(node) + tentative.commit() + return node +} + +func (p *Parser) isArrowFunctionHeadAmbiguous(state ParserState, returnType *ast.Node) bool { + tentative := p.beginTentativeParse() + defer tentative.close() + + contextFlags := p.tentativeExpression.contextFlags + arrowPos := p.scanner.TokenStart() + p.rewind(state) + tentative.silence() + tentative.suspendExpression() + + p.parseBinaryExpressionOrHigher(ast.OperatorPrecedenceLowest) + if p.token != ast.KindColonToken || p.scanner.TokenEnd() != returnType.Pos() { + return false + } + + p.contextFlags = contextFlags + p.nextToken() + for { + if p.isIdentifier() { + p.nextToken() + } else { + result, _ := p.parseArrowFunctionHead(ExpressionParseFlagsNone) + if result == core.TSFalse { + return false + } + } + if p.token != ast.KindEqualsGreaterThanToken || p.hasPrecedingLineBreak() { + return false + } + pos := p.scanner.TokenStart() + if pos >= arrowPos { + return pos == arrowPos + } + p.nextToken() + } +} + +func (p *Parser) tryParseArrowFunctionHead(flags ExpressionParseFlags) (core.Tristate, functionSignature) { + pos := p.nodePos() + result, signature := p.parseArrowFunctionHead(flags) + if result == core.TSFalse { + p.notParenthesizedArrow.Add(pos) + } + return result, signature +} + +func (p *Parser) parseArrowFunctionHead(flags ExpressionParseFlags) (result core.Tristate, signature functionSignature) { + result = core.TSFalse + pos := p.nodePos() + if flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 && p.notParenthesizedArrow.Has(pos) { + return core.TSFalse, functionSignature{} + } + + var tentative tentativeParse + if flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 && p.parsingFlags&ParsingFlagsTentative != 0 { + tentative = p.beginTentativeParse() + defer tentative.close() + } + modifiers := p.parseModifiersForArrowFunction() isAsync := modifierListHasAsync(modifiers) signatureFlags := core.IfElse(isAsync, ParseFlagsAwait, ParseFlagsNone) @@ -4426,30 +4614,30 @@ func (p *Parser) parseParenthesizedArrowFunctionExpression(allowAmbiguity bool, // And think that "(b =>" was actually a parenthesized arrow function with a missing // close paren. typeParameters := p.parseTypeParameters() + parameterToken := ast.KindUnknown var parameters *ast.NodeList if !p.parseExpected(ast.KindOpenParenToken) { - if !allowAmbiguity { - return nil + if flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 { + return core.TSFalse, functionSignature{} } parameters = p.createMissingList() } else { - if !allowAmbiguity { - maybeParameters := p.parseParametersWorker(signatureFlags, allowAmbiguity) - if maybeParameters == nil { - return nil - } - parameters = maybeParameters - } else { - parameters = p.parseParametersWorker(signatureFlags, allowAmbiguity) + parameterToken = p.token + parameters = p.parseParametersWorker(signatureFlags, flags&ExpressionParseFlagsAllowArrowFunctionRecovery != 0) + if parameters == nil { + return core.TSFalse, functionSignature{} } - if !p.parseExpected(ast.KindCloseParenToken) && !allowAmbiguity { - return nil + if !p.parseExpected(ast.KindCloseParenToken) && flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 { + return core.TSFalse, functionSignature{} } } - hasReturnColon := p.token == ast.KindColonToken + requiresColon := flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 && p.token == ast.KindColonToken && flags&ExpressionParseFlagsDisallowArrowReturnType != 0 + if canParseAmbiguousAsyncArrow(isAsync, typeParameters, parameterToken, flags) { + requiresColon = false + } returnType := p.parseReturnType(ast.KindColonToken /*isType*/, false) - if returnType != nil && !allowAmbiguity && typeHasArrowFunctionBlockingParseError(returnType) { - return nil + if returnType != nil && flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 && typeHasArrowFunctionBlockingParseError(returnType) { + return core.TSFalse, functionSignature{} } // Parsing a signature isn't enough. // Parenthesized arrow signatures often look like other valid expressions. @@ -4461,53 +4649,20 @@ func (p *Parser) parseParenthesizedArrowFunctionExpression(allowAmbiguity bool, // - "a ? (b): (function() {})" as well, but inside of a parenthesized type with an arbitrary amount of nesting. // // So we need just a bit of lookahead to ensure that it can only be a signature. - unwrappedType := returnType - for unwrappedType != nil && unwrappedType.Kind == ast.KindParenthesizedType { - unwrappedType = unwrappedType.Type() // Skip parens if need be - } - if !allowAmbiguity && p.token != ast.KindEqualsGreaterThanToken && p.token != ast.KindOpenBraceToken { - // Returning undefined here will cause our caller to rewind to where we started from. - return nil - } - // If we have an arrow, then try to parse the body. Even if not, try to parse if we - // have an opening brace, just in case we're in an error state. - lastToken := p.token - equalsGreaterThanToken := p.parseExpectedToken(ast.KindEqualsGreaterThanToken) - var body *ast.Node - if lastToken == ast.KindEqualsGreaterThanToken || lastToken == ast.KindOpenBraceToken { - body = p.parseArrowFunctionExpressionBody(isAsync, allowReturnTypeInArrowFunction) - } else { - body = p.parseIdentifier() + if flags&ExpressionParseFlagsAllowArrowFunctionRecovery == 0 && p.token != ast.KindEqualsGreaterThanToken && p.token != ast.KindOpenBraceToken { + return core.TSFalse, functionSignature{} } - // Given: - // x ? y => ({ y }) : z => ({ z }) - // We try to parse the body of the first arrow function by looking at: - // ({ y }) : z => ({ z }) - // This is a valid arrow function with "z" as the return type. - // - // But, if we're in the true side of a conditional expression, this colon - // terminates the expression, so we cannot allow a return type if we aren't - // certain whether or not the preceding text was parsed as a parameter list. - // - // For example, - // a() ? (b: number, c?: string): void => d() : e - // is determined by isParenthesizedArrowFunctionExpression to unambiguously - // be an arrow expression, so we allow a return type. - if !allowReturnTypeInArrowFunction && hasReturnColon { - // However, if the arrow function we were able to parse is followed by another colon - // as in: - // a ? (x): string => x : null - // Then allow the arrow function, and treat the second colon as terminating - // the conditional expression. It's okay to do this because this code would - // be a syntax error in JavaScript (as the second colon shouldn't be there). - if p.token != ast.KindColonToken { - return nil - } + result = core.TSTrue + if requiresColon { + result = core.TSUnknown } - result := p.finishNode(p.factory.NewArrowFunction(modifiers, typeParameters, parameters, returnType, nil /*fullSignature*/, equalsGreaterThanToken, body), pos) - p.withJSDoc(result, jsdoc) - p.checkJSSyntax(result) - return result + tentative.commit() + return result, functionSignature{modifiers, typeParameters, parameters, returnType} +} + +func canParseAmbiguousAsyncArrow(isAsync bool, typeParameters *ast.NodeList, parameterToken ast.Kind, flags ExpressionParseFlags) bool { + return isAsync && typeParameters == nil && flags&ExpressionParseFlagsAllowAmbiguousAsyncArrow != 0 && + (parameterToken == ast.KindCloseParenToken || parameterToken == ast.KindDotDotDotToken) } func (p *Parser) parseModifiersForArrowFunction() *ast.ModifierList { @@ -4533,7 +4688,7 @@ func typeHasArrowFunctionBlockingParseError(node *ast.TypeNode) bool { return false } -func (p *Parser) parseArrowFunctionExpressionBody(isAsync bool, allowReturnTypeInArrowFunction bool) *ast.Node { +func (p *Parser) parseArrowFunctionExpressionBody(isAsync bool, flags ExpressionParseFlags) *ast.Node { if p.token == ast.KindOpenBraceToken { return p.parseFunctionBlock(core.IfElse(isAsync, ParseFlagsAwait, ParseFlagsNone), nil /*diagnosticMessage*/) } @@ -4557,7 +4712,7 @@ func (p *Parser) parseArrowFunctionExpressionBody(isAsync bool, allowReturnTypeI saveContextFlags := p.contextFlags p.setContextFlags(ast.NodeFlagsAwaitContext, isAsync) p.setContextFlags(ast.NodeFlagsYieldContext, false) - node := p.parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowFunction) + node := p.parseAssignmentExpressionOrHigherWorker(flags) p.contextFlags = saveContextFlags return node } @@ -4567,26 +4722,14 @@ func (p *Parser) isStartOfExpressionStatement() bool { return p.token != ast.KindOpenBraceToken && p.token != ast.KindFunctionKeyword && p.token != ast.KindClassKeyword && p.token != ast.KindAtToken && p.isStartOfExpression() } -func (p *Parser) parsePossibleParenthesizedArrowFunctionExpression(allowReturnTypeInArrowFunction bool) *ast.Node { - tokenPos := p.scanner.TokenStart() - if p.notParenthesizedArrow.Has(tokenPos) { - return nil - } - result := p.parseParenthesizedArrowFunctionExpression(false /*allowAmbiguity*/, allowReturnTypeInArrowFunction) - if result == nil { - p.notParenthesizedArrow.Add(tokenPos) - } - return result -} - -func (p *Parser) tryParseAsyncSimpleArrowFunctionExpression(allowReturnTypeInArrowFunction bool) *ast.Node { +func (p *Parser) tryParseAsyncSimpleArrowFunctionExpression(flags ExpressionParseFlags) *ast.Node { // We do a check here so that we won't be doing unnecessarily call to "lookAhead" if p.token == ast.KindAsyncKeyword && p.lookAhead((*Parser).nextIsUnParenthesizedAsyncArrowFunction) { pos := p.nodePos() jsdoc := p.jsdocScannerInfo() asyncModifier := p.parseModifiersForArrowFunction() expr := p.parseBinaryExpressionOrHigher(ast.OperatorPrecedenceLowest) - return p.parseSimpleArrowFunctionExpression(pos, expr, allowReturnTypeInArrowFunction, jsdoc, asyncModifier) + return p.parseSimpleArrowFunctionExpression(pos, expr, flags, jsdoc, asyncModifier) } return nil } @@ -4612,33 +4755,108 @@ func (p *Parser) nextIsUnParenthesizedAsyncArrowFunction() bool { return false } -func (p *Parser) parseSimpleArrowFunctionExpression(pos int, identifier *ast.Node, allowReturnTypeInArrowFunction bool, jsdoc jsdocScannerInfo, asyncModifier *ast.ModifierList) *ast.Node { +func (p *Parser) parseSimpleArrowFunctionExpression(pos int, identifier *ast.Node, flags ExpressionParseFlags, jsdoc jsdocScannerInfo, asyncModifier *ast.ModifierList) *ast.Node { debug.Assert(p.token == ast.KindEqualsGreaterThanToken, "parseSimpleArrowFunctionExpression should only have been called if we had a =>") parameter := p.finishNode(p.factory.NewParameterDeclaration(nil /*modifiers*/, nil /*dotDotDotToken*/, identifier, nil /*questionToken*/, nil /*typeNode*/, nil /*initializer*/), identifier.Pos()) parameters := p.newNodeList(parameter.Loc, []*ast.Node{parameter}) equalsGreaterThanToken := p.parseExpectedToken(ast.KindEqualsGreaterThanToken) - body := p.parseArrowFunctionExpressionBody(asyncModifier != nil /*isAsync*/, allowReturnTypeInArrowFunction) + body := p.parseArrowFunctionExpressionBody(asyncModifier != nil /*isAsync*/, flags) result := p.finishNode(p.factory.NewArrowFunction(asyncModifier, nil /*typeParameters*/, parameters, nil /*returnType*/, nil /*fullSignature*/, equalsGreaterThanToken, body), pos) p.withJSDoc(result, jsdoc) return result } -func (p *Parser) parseConditionalExpressionRest(leftOperand *ast.Expression, pos int, allowReturnTypeInArrowFunction bool) *ast.Expression { - // Note: we are passed in an expression which was produced from parseBinaryExpressionOrHigher. +func (p *Parser) parseConditionalExpressionRest(leftOperand *ast.Expression, pos int, flags ExpressionParseFlags) *ast.Expression { questionToken := p.parseOptionalToken(ast.KindQuestionToken) if questionToken == nil { return leftOperand } - // Note: we explicitly 'allowIn' in the whenTrue part of the condition expression, and - // we do not that for the 'whenFalse' part. - saveContextFlags := p.contextFlags + if p.tentativeExpression != nil || flags&ExpressionParseFlagsDisallowArrowReturnType != 0 { + return p.parseConditionalBranches(leftOperand, questionToken, pos, flags) + } + node := p.tryParseConditionalBranches(leftOperand, questionToken, pos, flags) + if node != nil { + return node + } + + node = p.tryParseConditionalExpression(leftOperand, questionToken, pos, flags|ExpressionParseFlagsAllowAmbiguousAsyncArrow) + if node != nil { + return node + } + node = p.tryParseConditionalExpression(leftOperand, questionToken, pos, flags) + if node != nil { + return node + } + expression := tentativeExpression{result: core.TSFalse} + scope := p.beginTentativeScope() + defer scope.restore() + p.tentativeExpression = &expression + return p.parseConditionalBranches(leftOperand, questionToken, pos, flags) +} + +func (p *Parser) tryParseConditionalExpression(leftOperand, questionToken *ast.Node, pos int, flags ExpressionParseFlags) *ast.Node { + tentative := p.beginTentativeParse() + defer tentative.revert() + var expression tentativeExpression + for { + tentative.rewind() + p.tentativeExpression = &expression + expression.heads = expression.heads[:0] + tentative.silence() + node := p.tryParseConditionalBranches(leftOperand, questionToken, pos, flags) + if node != nil { + if tentative.parsingFlags&ParsingFlagsTentative != 0 { + tentative.commit() + return node + } + expression.result = core.TSTrue + tentative.rewind() + p.tentativeExpression = &expression + p.tentativeNodes = tentative.nodes + node = p.parseConditionalBranches(leftOperand, questionToken, pos, flags) + tentative.commit() + return node + } + if len(expression.heads) == 0 { + return nil + } + expression.expressions.Add(expression.heads[len(expression.heads)-1]) + } +} + +func (p *Parser) tryParseConditionalBranches(leftOperand, questionToken *ast.Node, pos int, flags ExpressionParseFlags) (node *ast.Node) { + tentative := p.beginTentativeParse() + defer tentative.close() + node = p.parseConditionalBranches(leftOperand, questionToken, pos, flags) + tentative.commit() + return node +} + +func (p *Parser) parseConditionalBranches(leftOperand, questionToken *ast.Node, pos int, flags ExpressionParseFlags) *ast.Node { + expression := p.tentativeExpression + outerContextFlags := p.contextFlags + var contextFlags ast.NodeFlags + if expression != nil { + contextFlags = expression.contextFlags + expression.contextFlags = outerContextFlags + } p.setContextFlags(ast.NodeFlagsDisallowInContext, false) - trueExpression := p.parseAssignmentExpressionOrHigherWorker(false /*allowReturnTypeInArrowFunction*/) - p.contextFlags = saveContextFlags + expressionFlags := ExpressionParseFlagsDisallowArrowReturnType | flags&ExpressionParseFlagsAllowAmbiguousAsyncArrow + if expression != nil && expression.result == core.TSFalse { + expressionFlags |= ExpressionParseFlagsAllowAmbiguousAsyncArrow + } + trueExpression := p.parseAssignmentExpressionOrHigherWorker(expressionFlags) + if p.token != ast.KindColonToken && p.parsingFlags&ParsingFlagsTentative != 0 { + panic(tentativeParseFailure{}) + } + if expression != nil { + expression.contextFlags = contextFlags + } + p.contextFlags = outerContextFlags colonToken := p.parseExpectedToken(ast.KindColonToken) var falseExpression *ast.Expression if ast.NodeIsPresent(colonToken) { - falseExpression = p.parseAssignmentExpressionOrHigherWorker(allowReturnTypeInArrowFunction) + falseExpression = p.parseAssignmentExpressionOrHigherWorker(flags) } else { falseExpression = p.createMissingIdentifier() } @@ -5337,7 +5555,8 @@ func (p *Parser) tryParseTypeArgumentsInExpression() *ast.NodeList { if p.contextFlags&ast.NodeFlagsJavaScriptFile != 0 || (p.token != ast.KindLessThanToken && p.token != ast.KindLessThanLessThanToken) { return nil } - state := p.mark() + tentative := p.beginTentativeParse() + defer tentative.close() if p.reScanLessThanToken() == ast.KindLessThanToken { p.nextToken() typeArguments := p.parseDelimitedList(PCTypeArguments, (*Parser).parseType) @@ -5349,11 +5568,11 @@ func (p *Parser) tryParseTypeArgumentsInExpression() *ast.NodeList { // `f(42)`, we favor the type argument interpretation even though JavaScript would view // it as a relational expression. if p.canFollowTypeArgumentsInExpression() { + tentative.commit() return typeArguments } } } - p.rewind(state) return nil } @@ -6800,9 +7019,10 @@ func (p *Parser) checkJSDecoratorSyntax(node *ast.Node) { } func (p *Parser) checkJSSyntax(node *ast.Node) *ast.Node { - if node.Flags&ast.NodeFlagsJavaScriptFile == 0 || node.Flags&(ast.NodeFlagsJSDoc|ast.NodeFlagsReparsed) != 0 { + if p.parsingFlags&ParsingFlagsTentative != 0 || node.Flags&ast.NodeFlagsJavaScriptFile == 0 || node.Flags&(ast.NodeFlagsJSDoc|ast.NodeFlagsReparsed) != 0 { return node } + switch node.Kind { case ast.KindParameter, ast.KindPropertyDeclaration, ast.KindMethodDeclaration: if token := node.QuestionToken(); token != nil && token.Flags&ast.NodeFlagsReparsed == 0 && ast.IsQuestionToken(token) { diff --git a/tsc/internal/parser/parser_test.go b/tsc/internal/parser/parser_test.go index ffa96713eb444..b6c21367d509d 100644 --- a/tsc/internal/parser/parser_test.go +++ b/tsc/internal/parser/parser_test.go @@ -5,6 +5,7 @@ import ( "iter" "os" "path/filepath" + "strconv" "strings" "testing" @@ -45,6 +46,48 @@ func BenchmarkParse(b *testing.B) { } } +func BenchmarkConditionalAsyncExpressions(b *testing.B) { + for _, test := range []struct{ name, prefix, suffix, closing string }{ + {"call", "a ? async() : x => ", "0;", ""}, + {"arrow", "a ? async(): T => async() : x => ", "0;", ""}, + {"priority", "a ? d = (d): T => a ? 0 : async(...c) : T => ", "0;", ""}, + {"invalidCall", "a ? async() : x => ", "0 +;", ""}, + {"invalidArrow", "a ? async(): T => async() : x => ", "0 +;", ""}, + {"parenthesizedCall", "a ? async() : x => (", "0", ")"}, + {"invalidParenthesizedCall", "a ? async() : x => (", "0 +", ")"}, + {"array", "a ? async() : x => [", "0", "]"}, + {"invalidArray", "a ? async() : x => [", "0 +", "]"}, + {"callArgument", "a ? async() : x => b(", "0", ")"}, + {"invalidCallArgument", "a ? async() : x => b(", "0 +", ")"}, + } { + b.Run(test.name, func(b *testing.B) { + for _, count := range []int{10, 20, 40, 80} { + b.Run(strconv.Itoa(count), func(b *testing.B) { + source := "const r = " + strings.Repeat(test.prefix, count) + test.suffix + strings.Repeat(test.closing, count) + opts := ast.SourceFileParseOptions{FileName: "/a.ts", PathKey: "/a.ts"} + b.ReportAllocs() + for b.Loop() { + parser.ParseSourceFile(opts, source, core.ScriptKindTS) + } + }) + } + }) + } +} + +func BenchmarkConditionalExpressions(b *testing.B) { + for _, count := range []int{1, 100} { + b.Run(strconv.Itoa(count), func(b *testing.B) { + source := strings.Repeat("{ const r = a ? b : c; }\n", count) + opts := ast.SourceFileParseOptions{FileName: "/a.ts", PathKey: "/a.ts"} + b.ReportAllocs() + for b.Loop() { + parser.ParseSourceFile(opts, source, core.ScriptKindTS) + } + }) + } +} + type parsableFile struct { path string name string @@ -188,6 +231,187 @@ class MissingImplements implements B. {} assert.Equal(t, missingImplementsDecl.HeritageClauses.Nodes[0].AsHeritageClause().Types.Nodes[0].Kind, ast.KindExpressionWithTypeArguments) } +func parseConditionalInGenerator(t *testing.T, expression string, kind core.ScriptKind) *ast.ConditionalExpression { + t.Helper() + fileName := tspath.RootedFilePathFromNormalized(core.IfElse(kind == core.ScriptKindJS, "/a.js", "/a.ts")) + file := parser.ParseSourceFile(ast.SourceFileParseOptions{ + FileName: fileName, + PathKey: tspath.CaseSensitive.PathKey(tspath.RootedPath(fileName)), + }, "function* g() { const a = "+expression+"; }", kind) + assert.Equal(t, len(file.Diagnostics()), 0) + assert.Equal(t, len(file.JSDiagnostics()), 0) + statement := file.Statements.Nodes[0].Body().AsBlock().Statements.Nodes[0] + declaration := statement.AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0] + conditional := declaration.Initializer().AsConditionalExpression() + assert.Equal(t, conditional.WhenTrue.Flags&ast.NodeFlagsYieldContext, ast.NodeFlagsYieldContext) + return conditional +} + +func checkConditionalAsyncNesting(t *testing.T, prefix string, closing string) { + t.Helper() + const depth = 8 + source := "const r = " + strings.Repeat(prefix, depth) + "0" + strings.Repeat(closing, depth) + ";" + file := parsetestutil.ParseTypeScript(source, false) + parsetestutil.CheckDiagnostics(t, file) + maxNodeCount := len(source) * len(source) + assert.Assert(t, file.NodeCount <= maxNodeCount, "created %d nodes for %d bytes", file.NodeCount, len(source)) +} + +func TestConditionalAsyncNestedArray(t *testing.T) { + t.Parallel() + checkConditionalAsyncNesting(t, "a ? async() : x => [", "]") +} + +func TestConditionalAsyncNestedCallArgument(t *testing.T) { + t.Parallel() + checkConditionalAsyncNesting(t, "a ? async() : x => b(", ")") +} + +func TestConditionalAsyncCall(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? async(...c) : 0", core.ScriptKindTS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindCallExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindNumericLiteral) +} + +func TestConditionalAsyncCallWithArrow(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? async(...c) : d => d", core.ScriptKindTS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindCallExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindArrowFunction) +} + +func TestConditionalAsyncCallYield(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? yield async(...c) : 0", core.ScriptKindTS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindYieldExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindNumericLiteral) + assert.Equal(t, conditional.WhenTrue.Expression().Kind, ast.KindCallExpression) +} + +func TestConditionalAsyncCallYieldWithArrow(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? yield async(...c) : d => d", core.ScriptKindTS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindYieldExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindArrowFunction) + assert.Equal(t, conditional.WhenTrue.Expression().Kind, ast.KindCallExpression) +} + +func TestConditionalAsyncCallJS(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? async(...c) : 0", core.ScriptKindJS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindCallExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindNumericLiteral) +} + +func TestConditionalAsyncCallWithArrowJS(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? async(...c) : d => d", core.ScriptKindJS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindCallExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindArrowFunction) +} + +func TestConditionalAsyncCallYieldJS(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? yield async(...c) : 0", core.ScriptKindJS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindYieldExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindNumericLiteral) + assert.Equal(t, conditional.WhenTrue.Expression().Kind, ast.KindCallExpression) +} + +func TestConditionalAsyncCallYieldWithArrowJS(t *testing.T) { + t.Parallel() + conditional := parseConditionalInGenerator(t, "b ? yield async(...c) : d => d", core.ScriptKindJS) + assert.Equal(t, conditional.WhenTrue.Kind, ast.KindYieldExpression) + assert.Equal(t, conditional.WhenFalse.Kind, ast.KindArrowFunction) + assert.Equal(t, conditional.WhenTrue.Expression().Kind, ast.KindCallExpression) +} + +func TestConditionalAsyncCallJSDoc(t *testing.T) { + t.Parallel() + file := parser.ParseSourceFile(ast.SourceFileParseOptions{ + FileName: "/a.js", + PathKey: "/a.js", + }, "const a = b ? async(...c) : d => /** @param {number */ e => e;", core.ScriptKindJS) + assert.Equal(t, len(file.Diagnostics()), 0) + assert.Equal(t, len(file.JSDiagnostics()), 0) + assert.Equal(t, len(file.JSDocDiagnostics()), 1) + assert.Equal(t, len(file.Statements.Nodes), 1) + statement := file.Statements.Nodes[0] + declaration := statement.AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0] + arrow := declaration.Initializer().AsConditionalExpression().WhenFalse.Body() + assert.Equal(t, len(arrow.JSDoc(file)), 1) +} + +func TestConditionalAsyncCallJSDocTypedef(t *testing.T) { + t.Parallel() + file := parser.ParseSourceFile(ast.SourceFileParseOptions{ + FileName: "/a.js", + PathKey: "/a.js", + }, "const a = b ? async(...c) : d => /** @typedef {number} T */ e => e;", core.ScriptKindJS) + assert.Equal(t, len(file.Diagnostics()), 0) + assert.Equal(t, len(file.JSDiagnostics()), 0) + assert.Equal(t, len(file.JSDocDiagnostics()), 0) + assert.Equal(t, len(file.Statements.Nodes), 2) + statement := file.Statements.Nodes[1] + declaration := statement.AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0] + arrow := declaration.Initializer().AsConditionalExpression().WhenFalse.Body() + assert.Equal(t, len(arrow.JSDoc(file)), 1) +} + +func TestConditionalAsyncCallCommentDirectives(t *testing.T) { + t.Parallel() + file := parsetestutil.ParseTypeScript(`const r = a ? async() : x => + // @ts-expect-error + a ? async() : x => + // @ts-ignore + 0; + const s = a ? async(x = ( + // @ts-expect-error + b + ), + // @ts-ignore + c + ): T => b : c;`, false) + parsetestutil.CheckDiagnostics(t, file) + assert.Equal(t, len(file.CommentDirectives), 4) + assert.Equal(t, file.CommentDirectives[0].Kind, ast.CommentDirectiveKindExpectError) + assert.Equal(t, file.CommentDirectives[1].Kind, ast.CommentDirectiveKindIgnore) + assert.Equal(t, file.CommentDirectives[2].Kind, ast.CommentDirectiveKindExpectError) + assert.Equal(t, file.CommentDirectives[3].Kind, ast.CommentDirectiveKindIgnore) + assert.Equal(t, len(file.Statements.Nodes), 2) +} + +func TestConditionalAsyncArrowBodyContext(t *testing.T) { + t.Parallel() + file := parser.ParseSourceFile(ast.SourceFileParseOptions{ + FileName: "/a.ts", + PathKey: "/a.ts", + }, "const a = b ? async (): Promise => async() : d => d;", core.ScriptKindTS) + assert.Equal(t, len(file.Diagnostics()), 0) + declaration := file.Statements.Nodes[0].AsVariableStatement().DeclarationList.AsVariableDeclarationList().Declarations.Nodes[0] + arrow := declaration.Initializer().AsConditionalExpression().WhenTrue + assert.Equal(t, arrow.Kind, ast.KindArrowFunction) + body := arrow.Body() + assert.Equal(t, body.Kind, ast.KindCallExpression) + assert.Equal(t, body.Flags&ast.NodeFlagsAwaitContext, ast.NodeFlagsAwaitContext) + assert.Equal(t, body.Flags&ast.NodeFlagsYieldContext, ast.NodeFlagsNone) +} + +func TestConditionalAsyncArrowYieldContext(t *testing.T) { + t.Parallel() + expression := parseConditionalInGenerator(t, "a ? async (): T => a ? async (): T => async() : async() : yield b", core.ScriptKindTS) + assert.Equal(t, expression.WhenTrue.Kind, ast.KindArrowFunction) + assert.Equal(t, expression.WhenFalse.Kind, ast.KindYieldExpression) + assert.Assert(t, expression.WhenFalse.Flags&ast.NodeFlagsYieldContext != 0) + assert.Equal(t, expression.WhenFalse.Flags&ast.NodeFlagsAwaitContext, ast.NodeFlagsNone) + body := expression.WhenTrue.Body().AsConditionalExpression() + assert.Equal(t, body.WhenTrue.Kind, ast.KindArrowFunction) + assert.Equal(t, body.WhenFalse.Kind, ast.KindCallExpression) + assert.Assert(t, body.WhenFalse.Flags&ast.NodeFlagsAwaitContext != 0) + assert.Equal(t, body.WhenFalse.Flags&ast.NodeFlagsYieldContext, ast.NodeFlagsNone) +} + func TestParseStaticSourcePhaseImport(t *testing.T) { t.Parallel() tests := []struct { diff --git a/tsc/internal/parser/tentative.go b/tsc/internal/parser/tentative.go new file mode 100644 index 0000000000000..6adfb7a916389 --- /dev/null +++ b/tsc/internal/parser/tentative.go @@ -0,0 +1,125 @@ +package parser + +import "github.com/microsoft/TypeScript/tsc/internal/ast" + +type tentativeParseFailure struct{} + +type tentativeNode struct { + contextFlags ast.NodeFlags + node *ast.Node +} + +type tentativeScope struct { + parser *Parser + expression *tentativeExpression +} + +type tentativeParse struct { + tentativeScope + state ParserState + nodes map[int][]tentativeNode + parsingFlags ParsingFlags + parsingContexts ParsingContexts +} + +func (p *Parser) beginTentativeScope() tentativeScope { + return tentativeScope{parser: p, expression: p.tentativeExpression} +} + +func (tc *tentativeScope) suspendExpression() { + tc.parser.tentativeExpression = nil +} + +func (tc *tentativeScope) restore() { + tc.parser.tentativeExpression = tc.expression +} + +func (p *Parser) beginTentativeParse() tentativeParse { + return tentativeParse{ + tentativeScope: p.beginTentativeScope(), + state: p.mark(), + parsingFlags: p.parsingFlags, + parsingContexts: p.parsingContexts, + } +} + +func (tp *tentativeParse) silence() { + parser := tp.parser + if tp.nodes == nil { + tp.nodes = parser.tentativeNodes + if tp.nodes == nil { + tp.nodes = make(map[int][]tentativeNode) + } + } + parser.tentativeNodes = tp.nodes + parser.parsingFlags |= ParsingFlagsTentative + parser.hasParseError = false +} + +func (tp *tentativeParse) rewind() { + parser := tp.parser + parser.rewind(tp.state) + parser.parsingFlags = tp.parsingFlags + parser.parsingContexts = tp.parsingContexts +} + +func (tp *tentativeParse) commit() { + parser := tp.parser + if parser == nil { + return + } + tp.restore() + parser.tentativeNodes = tp.state.tentativeNodes + tp.parser = nil +} + +func (tp *tentativeParse) revert() { + if tp.parser == nil { + return + } + tp.rewind() + tp.parser = nil +} + +func (tp *tentativeParse) close() { + failure := recover() + if failure == nil { + tp.revert() + return + } + if tp.parser == nil { + panic(failure) + } + tp.revert() + if _, ok := failure.(tentativeParseFailure); ok { + return + } + panic(failure) +} + +func (p *Parser) getTentativeNode(pos int) *ast.Node { + for _, entry := range p.tentativeNodes[pos] { + if entry.contextFlags == p.contextFlags { + if entry.node == nil { + panic(tentativeParseFailure{}) + } + p.scanner.ResetTokenState(entry.node.End()) + p.nextToken() + return entry.node + } + } + return nil +} + +func (p *Parser) recordTentativeNode(pos int, contextFlags ast.NodeFlags, node **ast.Node) { + failure := recover() + if failure != nil { + if _, ok := failure.(tentativeParseFailure); !ok { + panic(failure) + } + } + p.tentativeNodes[pos] = append(p.tentativeNodes[pos], tentativeNode{contextFlags: contextFlags, node: *node}) + if failure != nil { + panic(failure) + } +} diff --git a/tsc/internal/parser/tentative_test.go b/tsc/internal/parser/tentative_test.go new file mode 100644 index 0000000000000..a653c3a4bc68d --- /dev/null +++ b/tsc/internal/parser/tentative_test.go @@ -0,0 +1,334 @@ +package parser + +import ( + "reflect" + "testing" + + "github.com/microsoft/TypeScript/tsc/internal/ast" + "github.com/microsoft/TypeScript/tsc/internal/core" + "github.com/microsoft/TypeScript/tsc/internal/diagnostics" + "gotest.tools/v3/assert" +) + +func newTestParser(source string) *Parser { + p := newParser() + p.initializeState(ast.SourceFileParseOptions{FileName: "/a.ts", PathKey: "/a.ts"}, source, core.ScriptKindTS) + p.nextToken() + return p +} + +func TestTentativeScopeRestore(t *testing.T) { + t.Parallel() + p := newTestParser("a + b") + var expression tentativeExpression + p.tentativeExpression = &expression + failure := new(int) + var recovered any + func() { + defer func() { recovered = recover() }() + scope := p.beginTentativeScope() + defer scope.restore() + scope.suspendExpression() + assert.Assert(t, p.tentativeExpression == nil) + p.nextToken() + panic(failure) + }() + assert.Equal(t, recovered, any(failure)) + assert.Equal(t, p.tentativeExpression, &expression) + assert.Equal(t, p.token, ast.KindPlusToken) +} + +func TestTentativeParseCommitAndRevert(t *testing.T) { + t.Parallel() + p := newTestParser("a + b") + outer := p.beginTentativeParse() + p.nextToken() + inner := p.beginTentativeParse() + p.nextToken() + inner.commit() + inner.close() + assert.Equal(t, p.scanner.TokenText(), "b") + outer.revert() + assert.Equal(t, p.scanner.TokenText(), "a") + + outer = p.beginTentativeParse() + p.nextToken() + inner = p.beginTentativeParse() + p.nextToken() + inner.revert() + outer.commit() + outer.close() + assert.Equal(t, p.token, ast.KindPlusToken) +} + +func TestTentativeParseExpression(t *testing.T) { + t.Parallel() + p := newTestParser("a + b") + var expression tentativeExpression + p.tentativeExpression = &expression + tentative := p.beginTentativeParse() + tentative.suspendExpression() + assert.Assert(t, p.tentativeExpression == nil) + p.nextToken() + tentative.commit() + assert.Equal(t, p.tentativeExpression, &expression) + assert.Equal(t, p.token, ast.KindPlusToken) + + state := p.mark() + tentative = p.beginTentativeParse() + tentative.suspendExpression() + inner := p.beginTentativeParse() + p.tentativeExpression = &tentativeExpression{} + p.nextToken() + inner.commit() + assert.Assert(t, p.tentativeExpression == nil) + tentative.revert() + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) +} + +func TestTentativeParseFailure(t *testing.T) { + t.Parallel() + p := newTestParser("a + // @ts-expect-error\nb") + p.tentativeExpression = &tentativeExpression{} + state := p.mark() + result := func() (result *ast.Node) { + tentative := p.beginTentativeParse() + defer tentative.close() + tentative.silence() + tentative.suspendExpression() + p.parsingContexts |= 1 << PCParameters + p.contextFlags |= ast.NodeFlagsAwaitContext + p.nextToken() + p.nextToken() + p.parseErrorAtCurrentToken(diagnostics.Expression_expected) + return p.factory.NewEmptyStatement() + }() + assert.Assert(t, result == nil) + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) + assert.Equal(t, p.parsingContexts, ParsingContexts(0)) + assert.Equal(t, p.parsingFlags, ParsingFlagsNone) + p.nextToken() + p.nextToken() + assert.Equal(t, len(p.scanner.CommentDirectives()), 1) +} + +func TestTentativeParseUnexpectedFailure(t *testing.T) { + t.Parallel() + p := newTestParser("a + b") + failure := new(int) + var recovered any + func() { + defer func() { recovered = recover() }() + tentative := p.beginTentativeParse() + defer tentative.close() + p.nextToken() + panic(failure) + }() + assert.Equal(t, recovered, any(failure)) + assert.Equal(t, p.scanner.TokenText(), "a") +} + +func TestTentativeConditionalFailure(t *testing.T) { + t.Parallel() + p := newTestParser("a ? b") + leftOperand := p.parseIdentifier() + questionToken := p.parseExpectedToken(ast.KindQuestionToken) + p.tentativeExpression = &tentativeExpression{} + p.parsingFlags = ParsingFlagsTentative + state := p.mark() + node := p.tryParseConditionalBranches(leftOperand, questionToken, leftOperand.Pos(), ExpressionParseFlagsNone) + assert.Assert(t, node == nil) + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) + assert.Equal(t, p.parsingFlags, ParsingFlagsTentative) +} + +func TestTentativeTypeArgumentsRollback(t *testing.T) { + t.Parallel() + p := newTestParser("<(a + 1)") + tentative := p.beginTentativeParse() + defer tentative.revert() + tentative.silence() + state := p.mark() + parsingContexts := p.parsingContexts + typeArguments := p.tryParseTypeArgumentsInExpression() + assert.Assert(t, typeArguments == nil) + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) + assert.Equal(t, p.parsingContexts, parsingContexts) + assert.Equal(t, p.parsingFlags, ParsingFlagsTentative) +} + +func TestTentativeTypeArgumentsCommit(t *testing.T) { + t.Parallel() + p := newTestParser("(a)") + tentative := p.beginTentativeParse() + defer tentative.revert() + tentative.silence() + typeArguments := p.tryParseTypeArgumentsInExpression() + assert.Assert(t, typeArguments != nil) + assert.Equal(t, len(typeArguments.Nodes), 1) + assert.Equal(t, typeArguments.Nodes[0].Kind, ast.KindTypeReference) + assert.Equal(t, p.token, ast.KindOpenParenToken) + assert.Equal(t, p.parsingContexts, ParsingContexts(0)) + assert.Equal(t, p.parsingFlags, ParsingFlagsTentative) +} + +func TestTentativeLookAheadRecovery(t *testing.T) { + t.Parallel() + p := newTestParser(`r\u0065adonly: number`) + tentative := p.beginTentativeParse() + defer tentative.revert() + tentative.silence() + state := p.mark() + assert.Assert(t, p.lookAhead((*Parser).scanTypeMemberStart)) + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) + assert.Equal(t, p.parsingFlags, ParsingFlagsTentative) +} + +func TestTentativeParseCommittedFailure(t *testing.T) { + t.Parallel() + p := newTestParser("a + b") + state := p.mark() + outer := p.beginTentativeParse() + func() { + defer outer.close() + outer.silence() + func() { + inner := p.beginTentativeParse() + defer inner.close() + p.nextToken() + inner.commit() + p.parseErrorAtCurrentToken(diagnostics.Expression_expected) + }() + t.Fatal("a committed inner transaction swallowed the failure") + }() + assert.Assert(t, reflect.DeepEqual(p.mark(), state)) + assert.Equal(t, p.parsingFlags, ParsingFlagsNone) +} + +func TestArrowFunctionHeadSyntaxFailure(t *testing.T) { + t.Parallel() + p := newTestParser("(a = b; c)") + pos := p.nodePos() + tentative := p.beginTentativeParse() + defer tentative.revert() + tentative.silence() + status, _ := p.tryParseArrowFunctionHead(ExpressionParseFlagsNone) + assert.Equal(t, status, core.TSFalse) + assert.Assert(t, p.notParenthesizedArrow.Has(pos)) + assert.Equal(t, p.nodePos(), pos) + expression := p.tryParseParenthesizedArrowFunctionExpression(ExpressionParseFlagsNone) + assert.Assert(t, expression == nil) + assert.Assert(t, p.notParenthesizedArrow.Has(pos)) + assert.Equal(t, p.nodePos(), pos) +} + +func TestTentativeParseNode(t *testing.T) { + t.Parallel() + p := newTestParser("b(await(a)), c") + tentative := p.beginTentativeParse() + tentative.silence() + state := p.mark() + first := p.parseAssignmentExpressionOrHigher() + assert.Equal(t, first.AsCallExpression().Arguments.Nodes[0].Kind, ast.KindCallExpression) + assert.Equal(t, p.token, ast.KindCommaToken) + p.rewind(state) + second := p.parseAssignmentExpressionOrHigher() + assert.Equal(t, first, second) + assert.Equal(t, p.token, ast.KindCommaToken) + p.rewind(state) + p.contextFlags |= ast.NodeFlagsAwaitContext + third := p.parseAssignmentExpressionOrHigher() + assert.Assert(t, third != first) + assert.Equal(t, third.Flags&ast.NodeFlagsAwaitContext, ast.NodeFlagsAwaitContext) + assert.Equal(t, third.AsCallExpression().Arguments.Nodes[0].Kind, ast.KindAwaitExpression) + tentative.revert() + assert.Assert(t, p.tentativeNodes == nil) + assert.Equal(t, p.scanner.TokenText(), "b") +} + +func TestTentativeParseNodeFailure(t *testing.T) { + t.Parallel() + p := newTestParser("(a +)") + tentative := p.beginTentativeParse() + tentative.silence() + pos := p.nodePos() + func() { + attempt := p.beginTentativeParse() + defer attempt.close() + p.parseAssignmentExpressionOrHigher() + t.Fatal("invalid expression accepted") + }() + assert.Equal(t, len(p.tentativeNodes[pos]), 1) + assert.Assert(t, p.tentativeNodes[pos][0].node == nil) + func() { + attempt := p.beginTentativeParse() + defer attempt.close() + p.parseAssignmentExpressionOrHigher() + t.Fatal("failed recognition reused as a valid expression") + }() + assert.Equal(t, len(p.tentativeNodes[pos]), 1) + assert.Equal(t, p.nodePos(), pos) + tentative.revert() + assert.Assert(t, p.tentativeNodes == nil) +} + +func TestArrowFunctionHeadAmbiguity(t *testing.T) { + t.Parallel() + p := newTestParser("async(): T => a ?") + p.tentativeExpression = &tentativeExpression{} + state := p.mark() + status, signature := p.parseArrowFunctionHead(ExpressionParseFlagsDisallowArrowReturnType) + assert.Equal(t, status, core.TSUnknown) + assert.Equal(t, len(signature.parameters.Nodes), 0) + assert.Equal(t, signature.returnType.Kind, ast.KindTypeReference) + assert.Equal(t, p.token, ast.KindEqualsGreaterThanToken) + assert.Equal(t, len(p.diagnostics), 0) + headState := p.mark() + assert.Assert(t, p.isArrowFunctionHeadAmbiguous(state, signature.returnType)) + assert.Assert(t, reflect.DeepEqual(p.mark(), headState)) +} + +func TestArrowFunctionHeadRollback(t *testing.T) { + t.Parallel() + p := newTestParser("async(a = b.c)") + pos := p.nodePos() + tentative := p.beginTentativeParse() + status, _ := p.parseArrowFunctionHead(ExpressionParseFlagsNone) + assert.Equal(t, status, core.TSFalse) + assert.Equal(t, p.notParenthesizedArrow.Len(), 0) + tentative.revert() + expression := p.tryParseParenthesizedArrowFunctionExpression(ExpressionParseFlagsNone) + assert.Assert(t, expression == nil) + assert.Assert(t, p.notParenthesizedArrow.Has(pos)) + assert.Equal(t, p.nodePos(), pos) + expression = p.parseAssignmentExpressionOrHigher() + assert.Equal(t, expression.Kind, ast.KindCallExpression) + assert.Equal(t, p.token, ast.KindEndOfFile) + assert.Equal(t, len(p.diagnostics), 0) +} + +func TestArrowFunctionBodyFailureDoesNotCacheHead(t *testing.T) { + t.Parallel() + p := newTestParser("async(): T => a") + p.tentativeExpression = &tentativeExpression{result: core.TSFalse} + p.parsingFlags |= ParsingFlagsTentative + expression := p.tryParseParenthesizedArrowFunctionExpression(ExpressionParseFlagsDisallowArrowReturnType) + assert.Assert(t, expression == nil) + assert.Equal(t, p.notParenthesizedArrow.Len(), 0) + p.parsingFlags = ParsingFlagsNone + expression = p.tryParseParenthesizedArrowFunctionExpression(ExpressionParseFlagsNone) + assert.Equal(t, expression.Kind, ast.KindArrowFunction) + assert.Equal(t, p.token, ast.KindEndOfFile) +} + +func TestArrowFunctionBodySyntaxFailureDoesNotCacheHead(t *testing.T) { + t.Parallel() + p := newTestParser("async(): T => a +;") + p.tentativeExpression = &tentativeExpression{result: core.TSFalse} + p.parsingFlags |= ParsingFlagsTentative + pos := p.nodePos() + expression := p.tryParseParenthesizedArrowFunctionExpression(ExpressionParseFlagsDisallowArrowReturnType) + assert.Assert(t, expression == nil) + assert.Equal(t, p.notParenthesizedArrow.Len(), 0) + assert.Equal(t, p.nodePos(), pos) +} diff --git a/tsc/internal/parser/types.go b/tsc/internal/parser/types.go index 671189445f1eb..17f5a5895d361 100644 --- a/tsc/internal/parser/types.go +++ b/tsc/internal/parser/types.go @@ -12,3 +12,19 @@ const ( ParseFlagsIgnoreMissingOpenBrace ParseFlags = 1 << 4 ParseFlagsJSDoc ParseFlags = 1 << 5 ) + +type ExpressionParseFlags uint32 + +const ( + ExpressionParseFlagsNone ExpressionParseFlags = 0 + ExpressionParseFlagsDisallowArrowReturnType ExpressionParseFlags = 1 << 0 + ExpressionParseFlagsAllowAmbiguousAsyncArrow ExpressionParseFlags = 1 << 1 + ExpressionParseFlagsAllowArrowFunctionRecovery ExpressionParseFlags = 1 << 2 +) + +type ParsingFlags uint8 + +const ( + ParsingFlagsNone ParsingFlags = 0 + ParsingFlagsTentative ParsingFlags = 1 << 0 +) diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.errors.txt b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.errors.txt new file mode 100644 index 0000000000000..b8dd4659c2b18 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.errors.txt @@ -0,0 +1,163 @@ +b.ts(1,60): error TS1005: ':' expected. +b.ts(2,27): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +b.ts(2,43): error TS1005: '=>' expected. +b.ts(3,22): error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. +b.ts(3,29): error TS1005: '=>' expected. +b.ts(5,43): error TS1005: ':' expected. +b.ts(5,44): error TS1005: ':' expected. +c.ts(35,34): error TS1260: Keywords cannot contain escape characters. + + +==== a.ts (0 errors) ==== + // Repro from #20096 + + let foo = (async bar => bar); + + const a = true; + const b = 1; + const c = [b]; + + function async(...c: number[]): number { + return b; + } + + const f1 = a ? async() : 0; + const f2 = a ? async() : x => x; + const f3 = a ? a ? async() : 0 : b; + const f4 = a ? x => async() : x => x; + const f5 = a ? async (): Promise => b : () => b; + const f6 = a ? async (): Promise => { return b; } : () => b; + const f7 = a ? async (): Promise => a ? async() : 0 : () => b; + const f8 = a ? (): number => b : () => b; + + const f9 = a ? async(...c) : 0; + const f10 = a ? async(...c) : x => x; + const f11 = a ? async (...c: number[]): Promise => c.length : () => 0; + const f12 = a ? async() : x => async (...c): Promise => c.length; + + type T = Promise; + const f13 = a ? async() : x => async (): Promise => b; + const f14 = a ? async() : T => async (): T => 0; + const f15 = a ? (b) : x => async (): T => 0; + const f16 = a ? async(...c) : T => async (): T => 0; + const f17 = a ? async() : T => (b): number => b; + const f18 = a ? async() : T => async (): T => 0; + const f19 = a ? async(...c) : T => (b): number => b; + const f20 = a ? async(...c) : T => async (): T => 0; + const f21 = a ? (x): number => (b): T => 0; + const f22 = a ? async (): Promise => (b): T => 0; + const f23 = a ? async () => async() : x => x; + const f24 = a ? async (...c) => async() : x => x; + const f25 = a ? () => async() : x => x; + const f26 = a ? async (c: number): Promise => async() : x => x; + const f27 = a ? async (): Promise => async() : x => x; + const f28 = a ? async (): Promise => async(...c) : x => x; + const f29 = a ? async (...c): Promise => async() : x => x; + const f30 = a ? async (): Promise => async() : x => x; + const f31 = a ? async (): (Promise) => async() : x => x; + const f32 = a ? async (...c: number[]): T => async() : x => x; + + const f33 = a ? async() : 0 + {} + const f34 = a ? async() : {} + {} + + function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; + } + + const d = { a: c }; + const e = () => c; + const f35 = async(...d.a); + const f36 = async(...e()); + const f37 = async(...[b]); + + type U = number; + const f38 = a ? (c): U => (b) : x => x; + const f39 = a ? async() : function() {}; + const f40 = a ? async() : "b" + {} + const f41 = a ? async(...c) : 0 + {} + const f42 = a ? (c) : 0 + {} + + const f43 = a ? async() : T => async (...c): T => c.length; + + const f44 = a ? async (): T => (b) : d => d; + const f45 = a ? async (): T => async() : d => d; + const f46 = a ? async (): T => async() : b; + const f47 = a ? a ? async() : d => d : b; + const f48 = a ? a ? async(b) : d => d : b; + const f49 = a ? a ? async(...c) : d => d : b; + const f50 = a ? a ? async() : T => b : async (): T => b; + const f51 = a ? async (): T => async() : (d): number => d; + const f52 = a ? a ? async (): T => async() : d => d : b; + const f53 = a ? async (): T => a ? async() : b : d => d; + const f54 = a ? a ? async() : d => d : a ? async() : d => d; + const f55 = a ? a ? a ? async() : d => d : b : b; + + const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); + const f57 = a ? d => d = async () => async() : (d => d = 0); + +==== b.ts (7 errors) ==== + const f58 = a ? async(...c: number[]): Promise => 0; + ~ +!!! error TS1005: ':' expected. + const f59 = a ? async (): Promise {} : d => d; + ~~~~~~~~~~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + ~ +!!! error TS1005: '=>' expected. + const f60 = a ? (c): number {} : d => d; + ~~~~~~ +!!! error TS2355: A function whose declared type is neither 'undefined', 'void', nor 'any' must return a value. + ~ +!!! error TS1005: '=>' expected. + + const f61 = a ? async() : T => async(a ? b); + ~ +!!! error TS1005: ':' expected. + ~ +!!! error TS1005: ':' expected. + +==== c.ts (1 errors) ==== + export {}; + declare const a: any, b: any, c: any[]; + declare function async(...a: any[]): any; + type T = Promise; + let d: any; + const f62 = a ? d = (d): T => a ? 0 : async(...c) : T => b; + const f63 = a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b; + const f64 = a ? async (): T => (d): T => async() : b; + const f65 = (a ? async (): T => (d): T => async() : b); + const f66 = a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b; + const f67 = a ? async (c = a ? async() : d => d): T => async() : b; + const f68 = a ? a ? (d): T => a ? async() : b : d => d : b; + const f69 = a ? async() : (d => d); + const f70 = a ? async() : d => (a ? async() : d => d); + + type x = T; + declare const x: any; + const f71 = a ? a ? async (): T => (x): T => async() : x => x; + const f72 = a ? a ? async (): Promise => (x): T => async() : x => x; + const f73 = a ? async (x): T => async (): T => b; + const f74 = a ? async (x): T => async() : x => x; + + declare function h(a: A): A; + declare namespace number { type T = number; } + const f75 = a ? async(x = b < (d + 1)): T => x : 0; + const f76 = a ? async(x = b << (d + 1)): T => x : 0; + const f77 = a ? async(x = new b < (d + 1)): T => x : 0; + const f78 = a ? async(x = h(b)): T => x : 0; + const f79 = a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0; + const f80 = a ? async(): Promise<([a: number])> => [b] : 0; + const f81 = a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0; + const f82 = a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0; + const f83 = a ? async(): Promise => b : 0; + const f84 = a ? a ? as\u0079nc() : d => d : b; + const f85 = a ? async(): Promise => 0 : 0; + ~~~~~~~~~~~ +!!! error TS1260: Keywords cannot contain escape characters. + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.js b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.js index a7b6057753bcf..b0cca4276d68e 100644 --- a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.js +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.js @@ -1,12 +1,144 @@ //// [tests/cases/compiler/parenthesizedAsyncArrowFunction.ts] //// -//// [parenthesizedAsyncArrowFunction.ts] +//// [a.ts] // Repro from #20096 let foo = (async bar => bar); + +const a = true; +const b = 1; +const c = [b]; + +function async(...c: number[]): number { + return b; +} + +const f1 = a ? async() : 0; +const f2 = a ? async() : x => x; +const f3 = a ? a ? async() : 0 : b; +const f4 = a ? x => async() : x => x; +const f5 = a ? async (): Promise => b : () => b; +const f6 = a ? async (): Promise => { return b; } : () => b; +const f7 = a ? async (): Promise => a ? async() : 0 : () => b; +const f8 = a ? (): number => b : () => b; + +const f9 = a ? async(...c) : 0; +const f10 = a ? async(...c) : x => x; +const f11 = a ? async (...c: number[]): Promise => c.length : () => 0; +const f12 = a ? async() : x => async (...c): Promise => c.length; + +type T = Promise; +const f13 = a ? async() : x => async (): Promise => b; +const f14 = a ? async() : T => async (): T => 0; +const f15 = a ? (b) : x => async (): T => 0; +const f16 = a ? async(...c) : T => async (): T => 0; +const f17 = a ? async() : T => (b): number => b; +const f18 = a ? async() : T => async (): T => 0; +const f19 = a ? async(...c) : T => (b): number => b; +const f20 = a ? async(...c) : T => async (): T => 0; +const f21 = a ? (x): number => (b): T => 0; +const f22 = a ? async (): Promise => (b): T => 0; +const f23 = a ? async () => async() : x => x; +const f24 = a ? async (...c) => async() : x => x; +const f25 = a ? () => async() : x => x; +const f26 = a ? async (c: number): Promise => async() : x => x; +const f27 = a ? async (): Promise => async() : x => x; +const f28 = a ? async (): Promise => async(...c) : x => x; +const f29 = a ? async (...c): Promise => async() : x => x; +const f30 = a ? async (): Promise => async() : x => x; +const f31 = a ? async (): (Promise) => async() : x => x; +const f32 = a ? async (...c: number[]): T => async() : x => x; + +const f33 = a ? async() : 0 +{} +const f34 = a ? async() : {} +{} + +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} + +const d = { a: c }; +const e = () => c; +const f35 = async(...d.a); +const f36 = async(...e()); +const f37 = async(...[b]); + +type U = number; +const f38 = a ? (c): U => (b) : x => x; +const f39 = a ? async() : function() {}; +const f40 = a ? async() : "b" +{} +const f41 = a ? async(...c) : 0 +{} +const f42 = a ? (c) : 0 +{} + +const f43 = a ? async() : T => async (...c): T => c.length; + +const f44 = a ? async (): T => (b) : d => d; +const f45 = a ? async (): T => async() : d => d; +const f46 = a ? async (): T => async() : b; +const f47 = a ? a ? async() : d => d : b; +const f48 = a ? a ? async(b) : d => d : b; +const f49 = a ? a ? async(...c) : d => d : b; +const f50 = a ? a ? async() : T => b : async (): T => b; +const f51 = a ? async (): T => async() : (d): number => d; +const f52 = a ? a ? async (): T => async() : d => d : b; +const f53 = a ? async (): T => a ? async() : b : d => d; +const f54 = a ? a ? async() : d => d : a ? async() : d => d; +const f55 = a ? a ? a ? async() : d => d : b : b; + +const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f57 = a ? d => d = async () => async() : (d => d = 0); +//// [b.ts] +const f58 = a ? async(...c: number[]): Promise => 0; +const f59 = a ? async (): Promise {} : d => d; +const f60 = a ? (c): number {} : d => d; + +const f61 = a ? async() : T => async(a ? b); -//// [parenthesizedAsyncArrowFunction.js] +//// [c.ts] +export {}; +declare const a: any, b: any, c: any[]; +declare function async(...a: any[]): any; +type T = Promise; +let d: any; +const f62 = a ? d = (d): T => a ? 0 : async(...c) : T => b; +const f63 = a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b; +const f64 = a ? async (): T => (d): T => async() : b; +const f65 = (a ? async (): T => (d): T => async() : b); +const f66 = a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b; +const f67 = a ? async (c = a ? async() : d => d): T => async() : b; +const f68 = a ? a ? (d): T => a ? async() : b : d => d : b; +const f69 = a ? async() : (d => d); +const f70 = a ? async() : d => (a ? async() : d => d); + +type x = T; +declare const x: any; +const f71 = a ? a ? async (): T => (x): T => async() : x => x; +const f72 = a ? a ? async (): Promise => (x): T => async() : x => x; +const f73 = a ? async (x): T => async (): T => b; +const f74 = a ? async (x): T => async() : x => x; + +declare function h(a: A): A; +declare namespace number { type T = number; } +const f75 = a ? async(x = b < (d + 1)): T => x : 0; +const f76 = a ? async(x = b << (d + 1)): T => x : 0; +const f77 = a ? async(x = new b < (d + 1)): T => x : 0; +const f78 = a ? async(x = h(b)): T => x : 0; +const f79 = a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0; +const f80 = a ? async(): Promise<([a: number])> => [b] : 0; +const f81 = a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0; +const f82 = a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0; +const f83 = a ? async(): Promise => b : 0; +const f84 = a ? a ? as\u0079nc() : d => d : b; +const f85 = a ? async(): Promise => 0 : 0; + + +//// [a.js] "use strict"; // Repro from #20096 var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { @@ -19,3 +151,128 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge }); }; let foo = ((bar) => __awaiter(void 0, void 0, void 0, function* () { return bar; })); +const a = true; +const b = 1; +const c = [b]; +function async(...c) { + return b; +} +const f1 = a ? async() : 0; +const f2 = a ? async() : x => x; +const f3 = a ? a ? async() : 0 : b; +const f4 = a ? x => async() : x => x; +const f5 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return b; }) : () => b; +const f6 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return b; }) : () => b; +const f7 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return a ? async() : 0; }) : () => b; +const f8 = a ? () => b : () => b; +const f9 = a ? async(...c) : 0; +const f10 = a ? async(...c) : x => x; +const f11 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return c.length; }) : () => 0; +const f12 = a ? async() : x => (...c) => __awaiter(void 0, void 0, void 0, function* () { return c.length; }); +const f13 = a ? async() : x => () => __awaiter(void 0, void 0, void 0, function* () { return b; }); +const f14 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : T => 0; +const f15 = a ? (b) : x => () => __awaiter(void 0, void 0, void 0, function* () { return 0; }); +const f16 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : T => 0; +const f17 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return (b); }) : number => b; +const f18 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : T => 0; +const f19 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return (b); }) : number => b; +const f20 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : T => 0; +const f21 = a ? (x) => (b) : T => 0; +const f22 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return (b); }) : T => 0; +const f23 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f24 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f25 = a ? () => async() : x => x; +const f26 = a ? (c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f27 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f28 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(...c); }) : x => x; +const f29 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f30 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f31 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f32 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f33 = a ? async() : 0; +{ } +const f34 = a ? async() : {}; +{ } +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} +const d = { a: c }; +const e = () => c; +const f35 = async(...d.a); +const f36 = async(...e()); +const f37 = async(...[b]); +const f38 = a ? (c) => (b) : x => x; +const f39 = a ? async() : function () { }; +const f40 = a ? async() : "b"; +{ } +const f41 = a ? async(...c) : 0; +{ } +const f42 = a ? (c) : 0; +{ } +const f43 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(...c); }) : T => c.length; +const f44 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return (b); }) : d => d; +const f45 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : d => d; +const f46 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : b; +const f47 = a ? a ? async() : d => d : b; +const f48 = a ? a ? async(b) : d => d : b; +const f49 = a ? a ? async(...c) : d => d : b; +const f50 = a ? a ? () => __awaiter(void 0, void 0, void 0, function* () { return b; }) : async() : T => b; +const f51 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : (d) => d; +const f52 = a ? a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : d => d : b; +const f53 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return a ? async() : b; }) : d => d; +const f54 = a ? a ? async() : d => d : a ? async() : d => d; +const f55 = a ? a ? a ? async() : d => d : b : b; +const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f57 = a ? d => d = () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : (d => d = 0); +//// [b.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const f58 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return 0; }) : ; +const f59 = a ? () => __awaiter(void 0, void 0, void 0, function* () { }) : d => d; +const f60 = a ? (c) => { } : d => d; +const f61 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(a ? b : ); }) : ; +//// [c.js] +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +let d; +const f62 = a ? d = (d) : T => a ? 0 : (...c) => __awaiter(void 0, void 0, void 0, function* () { return b; }); +const f63 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return () => __awaiter(void 0, void 0, void 0, function* () { return (d) => b; }); }) : a ? d => (d) : T => (...c) => __awaiter(void 0, void 0, void 0, function* () { return b; }); +const f64 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return (d) => async(); }) : b; +const f65 = (a ? () => __awaiter(void 0, void 0, void 0, function* () { return (d) => async(); }) : b); +const f66 = a ? d = (d) : T => a ? 0 : (...c) => __awaiter(void 0, void 0, void 0, function* () { return a ? d = (d) : T => a ? 0 : (...c) => __awaiter(void 0, void 0, void 0, function* () { return b; }); }); +const f67 = a ? (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (c = a ? async() : d => d) { return async(); }) : b; +const f68 = a ? a ? (d) => a ? async() : b : d => d : b; +const f69 = a ? async() : (d => d); +const f70 = a ? async() : d => (a ? async() : d => d); +const f71 = a ? a ? () => __awaiter(void 0, void 0, void 0, function* () { return (x); }) : T => async() : x => x; +const f72 = a ? a ? () => __awaiter(void 0, void 0, void 0, function* () { return (x); }) : T => async() : x => x; +const f73 = a ? async(x) : T => () => __awaiter(void 0, void 0, void 0, function* () { return b; }); +const f74 = a ? async(x) : T => () => __awaiter(void 0, void 0, void 0, function* () { return x; }); +const f75 = a ? (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (x = b < (d + 1)) { return x; }) : 0; +const f76 = a ? (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (x = b << (d + 1)) { return x; }) : 0; +const f77 = a ? (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (x = new b < (d + 1)) { return x; }) : 0; +const f78 = a ? (...args_1) => __awaiter(void 0, [...args_1], void 0, function* (x = h(b)) { return x; }) : 0; +const f79 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return ({ a: [] }); }) : 0; +const f80 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return [b]; }) : 0; +const f81 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return ({ readonly: 0 }); }) : 0; +const f82 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return ({ get: 0 }); }) : 0; +const f83 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return b; }) : 0; +const f84 = a ? a ? as\u0079nc() : d => d : b; +const f85 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return 0; }) : 0; +export {}; diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.symbols b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.symbols index 53286f39e8465..3eeb79b9aef66 100644 --- a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.symbols +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.symbols @@ -1,10 +1,820 @@ //// [tests/cases/compiler/parenthesizedAsyncArrowFunction.ts] //// -=== parenthesizedAsyncArrowFunction.ts === +=== a.ts === // Repro from #20096 let foo = (async bar => bar); ->foo : Symbol(foo, Decl(parenthesizedAsyncArrowFunction.ts, 2, 3)) ->bar : Symbol(bar, Decl(parenthesizedAsyncArrowFunction.ts, 2, 16)) ->bar : Symbol(bar, Decl(parenthesizedAsyncArrowFunction.ts, 2, 16)) +>foo : Symbol(foo, Decl(a.ts, 2, 3)) +>bar : Symbol(bar, Decl(a.ts, 2, 16)) +>bar : Symbol(bar, Decl(a.ts, 2, 16)) + +const a = true; +>a : Symbol(a, Decl(a.ts, 4, 5)) + +const b = 1; +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const c = [b]; +>c : Symbol(c, Decl(a.ts, 6, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +function async(...c: number[]): number { +>async : Symbol(async, Decl(a.ts, 6, 14)) +>V : Symbol(V, Decl(a.ts, 8, 15)) +>c : Symbol(c, Decl(a.ts, 8, 18)) + + return b; +>b : Symbol(b, Decl(a.ts, 5, 5)) +} + +const f1 = a ? async() : 0; +>f1 : Symbol(f1, Decl(a.ts, 12, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) + +const f2 = a ? async() : x => x; +>f2 : Symbol(f2, Decl(a.ts, 13, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 13, 24)) +>x : Symbol(x, Decl(a.ts, 13, 24)) + +const f3 = a ? a ? async() : 0 : b; +>f3 : Symbol(f3, Decl(a.ts, 14, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f4 = a ? x => async() : x => x; +>f4 : Symbol(f4, Decl(a.ts, 15, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>x : Symbol(x, Decl(a.ts, 15, 14)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 15, 29)) +>x : Symbol(x, Decl(a.ts, 15, 29)) + +const f5 = a ? async (): Promise => b : () => b; +>f5 : Symbol(f5, Decl(a.ts, 16, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f6 = a ? async (): Promise => { return b; } : () => b; +>f6 : Symbol(f6, Decl(a.ts, 17, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f7 = a ? async (): Promise => a ? async() : 0 : () => b; +>f7 : Symbol(f7, Decl(a.ts, 18, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f8 = a ? (): number => b : () => b; +>f8 : Symbol(f8, Decl(a.ts, 19, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f9 = a ? async(...c) : 0; +>f9 : Symbol(f9, Decl(a.ts, 21, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + +const f10 = a ? async(...c) : x => x; +>f10 : Symbol(f10, Decl(a.ts, 22, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>x : Symbol(x, Decl(a.ts, 22, 29)) +>x : Symbol(x, Decl(a.ts, 22, 29)) + +const f11 = a ? async (...c: number[]): Promise => c.length : () => 0; +>f11 : Symbol(f11, Decl(a.ts, 23, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 23, 23)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>c.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>c : Symbol(c, Decl(a.ts, 23, 23)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + +const f12 = a ? async() : x => async (...c): Promise => c.length; +>f12 : Symbol(f12, Decl(a.ts, 24, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 24, 25)) +>c : Symbol(c, Decl(a.ts, 24, 38)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>c.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>c : Symbol(c, Decl(a.ts, 24, 38)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + +type T = Promise; +>T : Symbol(T, Decl(a.ts, 24, 73)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const f13 = a ? async() : x => async (): Promise => b; +>f13 : Symbol(f13, Decl(a.ts, 27, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 27, 25)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f14 = a ? async() : T => async (): T => 0; +>f14 : Symbol(f14, Decl(a.ts, 28, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>T : Symbol(T, Decl(a.ts, 28, 40)) + +const f15 = a ? (b) : x => async (): T => 0; +>f15 : Symbol(f15, Decl(a.ts, 29, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>x : Symbol(x, Decl(a.ts, 29, 21)) +>T : Symbol(T, Decl(a.ts, 24, 73)) + +const f16 = a ? async(...c) : T => async (): T => 0; +>f16 : Symbol(f16, Decl(a.ts, 30, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 30, 22)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>T : Symbol(T, Decl(a.ts, 30, 44)) + +const f17 = a ? async() : T => (b): number => b; +>f17 : Symbol(f17, Decl(a.ts, 31, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>number : Symbol(number, Decl(a.ts, 31, 35)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f18 = a ? async() : T => async (): T => 0; +>f18 : Symbol(f18, Decl(a.ts, 32, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>U : Symbol(U, Decl(a.ts, 62, 26)) +>T : Symbol(T, Decl(a.ts, 32, 43)) + +const f19 = a ? async(...c) : T => (b): number => b; +>f19 : Symbol(f19, Decl(a.ts, 33, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 33, 22)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>number : Symbol(number, Decl(a.ts, 33, 39)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f20 = a ? async(...c) : T => async (): T => 0; +>f20 : Symbol(f20, Decl(a.ts, 34, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 34, 22)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>U : Symbol(U, Decl(a.ts, 62, 26)) +>T : Symbol(T, Decl(a.ts, 34, 47)) + +const f21 = a ? (x): number => (b): T => 0; +>f21 : Symbol(f21, Decl(a.ts, 35, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>x : Symbol(x, Decl(a.ts, 35, 17)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>T : Symbol(T, Decl(a.ts, 35, 35)) + +const f22 = a ? async (): Promise => (b): T => 0; +>f22 : Symbol(f22, Decl(a.ts, 36, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>U : Symbol(U, Decl(a.ts, 36, 23)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>T : Symbol(T, Decl(a.ts, 36, 52)) + +const f23 = a ? async () => async() : x => x; +>f23 : Symbol(f23, Decl(a.ts, 37, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 37, 37)) +>x : Symbol(x, Decl(a.ts, 37, 37)) + +const f24 = a ? async (...c) => async() : x => x; +>f24 : Symbol(f24, Decl(a.ts, 38, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 38, 23)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 38, 41)) +>x : Symbol(x, Decl(a.ts, 38, 41)) + +const f25 = a ? () => async() : x => x; +>f25 : Symbol(f25, Decl(a.ts, 39, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 39, 31)) +>x : Symbol(x, Decl(a.ts, 39, 31)) + +const f26 = a ? async (c: number): Promise => async() : x => x; +>f26 : Symbol(f26, Decl(a.ts, 40, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 40, 23)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 40, 63)) +>x : Symbol(x, Decl(a.ts, 40, 63)) + +const f27 = a ? async (): Promise => async() : x => x; +>f27 : Symbol(f27, Decl(a.ts, 41, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 41, 54)) +>x : Symbol(x, Decl(a.ts, 41, 54)) + +const f28 = a ? async (): Promise => async(...c) : x => x; +>f28 : Symbol(f28, Decl(a.ts, 42, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>x : Symbol(x, Decl(a.ts, 42, 58)) +>x : Symbol(x, Decl(a.ts, 42, 58)) + +const f29 = a ? async (...c): Promise => async() : x => x; +>f29 : Symbol(f29, Decl(a.ts, 43, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 43, 23)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 43, 58)) +>x : Symbol(x, Decl(a.ts, 43, 58)) + +const f30 = a ? async (): Promise => async() : x => x; +>f30 : Symbol(f30, Decl(a.ts, 44, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>U : Symbol(U, Decl(a.ts, 44, 23)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 44, 57)) +>x : Symbol(x, Decl(a.ts, 44, 57)) + +const f31 = a ? async (): (Promise) => async() : x => x; +>f31 : Symbol(f31, Decl(a.ts, 45, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 45, 56)) +>x : Symbol(x, Decl(a.ts, 45, 56)) + +const f32 = a ? async (...c: number[]): T => async() : x => x; +>f32 : Symbol(f32, Decl(a.ts, 46, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 46, 23)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>x : Symbol(x, Decl(a.ts, 46, 54)) +>x : Symbol(x, Decl(a.ts, 46, 54)) + +const f33 = a ? async() : 0 +>f33 : Symbol(f33, Decl(a.ts, 48, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) + +{} +const f34 = a ? async() : {} +>f34 : Symbol(f34, Decl(a.ts, 50, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) + +{} + +function* g() { +>g : Symbol(g, Decl(a.ts, 51, 2)) + + const f1 = a ? yield async(...c) : 0; +>f1 : Symbol(f1, Decl(a.ts, 54, 9)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + + const f2 = a ? yield async(...c) : x => x; +>f2 : Symbol(f2, Decl(a.ts, 55, 9)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>x : Symbol(x, Decl(a.ts, 55, 38)) +>x : Symbol(x, Decl(a.ts, 55, 38)) +} + +const d = { a: c }; +>d : Symbol(d, Decl(a.ts, 58, 5)) +>a : Symbol(a, Decl(a.ts, 58, 11)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + +const e = () => c; +>e : Symbol(e, Decl(a.ts, 59, 5)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + +const f35 = async(...d.a); +>f35 : Symbol(f35, Decl(a.ts, 60, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d.a : Symbol(a, Decl(a.ts, 58, 11)) +>d : Symbol(d, Decl(a.ts, 58, 5)) +>a : Symbol(a, Decl(a.ts, 58, 11)) + +const f36 = async(...e()); +>f36 : Symbol(f36, Decl(a.ts, 61, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>e : Symbol(e, Decl(a.ts, 59, 5)) + +const f37 = async(...[b]); +>f37 : Symbol(f37, Decl(a.ts, 62, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +type U = number; +>U : Symbol(U, Decl(a.ts, 62, 26)) + +const f38 = a ? (c): U => (b) : x => x; +>f38 : Symbol(f38, Decl(a.ts, 65, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 65, 17)) +>U : Symbol(U, Decl(a.ts, 62, 26)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>x : Symbol(x, Decl(a.ts, 65, 31)) +>x : Symbol(x, Decl(a.ts, 65, 31)) + +const f39 = a ? async() : function() {}; +>f39 : Symbol(f39, Decl(a.ts, 66, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) + +const f40 = a ? async() : "b" +>f40 : Symbol(f40, Decl(a.ts, 67, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) + +{} +const f41 = a ? async(...c) : 0 +>f41 : Symbol(f41, Decl(a.ts, 69, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + +{} +const f42 = a ? (c) : 0 +>f42 : Symbol(f42, Decl(a.ts, 71, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(a.ts, 6, 5)) + +{} + +const f43 = a ? async() : T => async (...c): T => c.length; +>f43 : Symbol(f43, Decl(a.ts, 74, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>T : Symbol(T, Decl(a.ts, 74, 44)) +>c.length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>length : Symbol(Array.length, Decl(lib.es5.d.ts, --, --)) + +const f44 = a ? async (): T => (b) : d => d; +>f44 : Symbol(f44, Decl(a.ts, 76, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>d : Symbol(d, Decl(a.ts, 76, 36)) +>d : Symbol(d, Decl(a.ts, 76, 36)) + +const f45 = a ? async (): T => async() : d => d; +>f45 : Symbol(f45, Decl(a.ts, 77, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 77, 40)) +>d : Symbol(d, Decl(a.ts, 77, 40)) + +const f46 = a ? async (): T => async() : b; +>f46 : Symbol(f46, Decl(a.ts, 78, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f47 = a ? a ? async() : d => d : b; +>f47 : Symbol(f47, Decl(a.ts, 79, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 79, 29)) +>d : Symbol(d, Decl(a.ts, 79, 29)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f48 = a ? a ? async(b) : d => d : b; +>f48 : Symbol(f48, Decl(a.ts, 80, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>d : Symbol(d, Decl(a.ts, 80, 30)) +>d : Symbol(d, Decl(a.ts, 80, 30)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f49 = a ? a ? async(...c) : d => d : b; +>f49 : Symbol(f49, Decl(a.ts, 81, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>c : Symbol(c, Decl(a.ts, 6, 5)) +>d : Symbol(d, Decl(a.ts, 81, 33)) +>d : Symbol(d, Decl(a.ts, 81, 33)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f50 = a ? a ? async() : T => b : async (): T => b; +>f50 : Symbol(f50, Decl(a.ts, 82, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>T : Symbol(T, Decl(a.ts, 82, 48)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f51 = a ? async (): T => async() : (d): number => d; +>f51 : Symbol(f51, Decl(a.ts, 83, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 83, 42)) +>d : Symbol(d, Decl(a.ts, 83, 42)) + +const f52 = a ? a ? async (): T => async() : d => d : b; +>f52 : Symbol(f52, Decl(a.ts, 84, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 84, 44)) +>d : Symbol(d, Decl(a.ts, 84, 44)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f53 = a ? async (): T => a ? async() : b : d => d; +>f53 : Symbol(f53, Decl(a.ts, 85, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>d : Symbol(d, Decl(a.ts, 85, 48)) +>d : Symbol(d, Decl(a.ts, 85, 48)) + +const f54 = a ? a ? async() : d => d : a ? async() : d => d; +>f54 : Symbol(f54, Decl(a.ts, 86, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 86, 29)) +>d : Symbol(d, Decl(a.ts, 86, 29)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 86, 52)) +>d : Symbol(d, Decl(a.ts, 86, 52)) + +const f55 = a ? a ? a ? async() : d => d : b : b; +>f55 : Symbol(f55, Decl(a.ts, 87, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 87, 33)) +>d : Symbol(d, Decl(a.ts, 87, 33)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +>f56 : Symbol(f56, Decl(a.ts, 89, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>d : Symbol(d, Decl(a.ts, 89, 15)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>b : Symbol(b, Decl(a.ts, 5, 5)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 89, 57)) +>d : Symbol(d, Decl(a.ts, 89, 57)) +>a : Symbol(a, Decl(a.ts, 4, 5)) + +const f57 = a ? d => d = async () => async() : (d => d = 0); +>f57 : Symbol(f57, Decl(a.ts, 90, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>d : Symbol(d, Decl(a.ts, 90, 15)) +>d : Symbol(d, Decl(a.ts, 90, 15)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>d : Symbol(d, Decl(a.ts, 90, 48)) +>d : Symbol(d, Decl(a.ts, 90, 48)) + +=== b.ts === +const f58 = a ? async(...c: number[]): Promise => 0; +>f58 : Symbol(f58, Decl(b.ts, 0, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(b.ts, 0, 22)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +const f59 = a ? async (): Promise {} : d => d; +>f59 : Symbol(f59, Decl(b.ts, 1, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>d : Symbol(d, Decl(b.ts, 1, 46)) +>d : Symbol(d, Decl(b.ts, 1, 46)) + +const f60 = a ? (c): number {} : d => d; +>f60 : Symbol(f60, Decl(b.ts, 2, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>c : Symbol(c, Decl(b.ts, 2, 17)) +>d : Symbol(d, Decl(b.ts, 2, 32)) +>d : Symbol(d, Decl(b.ts, 2, 32)) + +const f61 = a ? async() : T => async(a ? b); +>f61 : Symbol(f61, Decl(b.ts, 4, 5)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>T : Symbol(T, Decl(a.ts, 24, 73)) +>async : Symbol(async, Decl(a.ts, 6, 14)) +>a : Symbol(a, Decl(a.ts, 4, 5)) +>b : Symbol(b, Decl(a.ts, 5, 5)) + +=== c.ts === +export {}; +declare const a: any, b: any, c: any[]; +>a : Symbol(a, Decl(c.ts, 1, 13)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>c : Symbol(c, Decl(c.ts, 1, 29)) + +declare function async(...a: any[]): any; +>async : Symbol(async, Decl(c.ts, 1, 39)) +>a : Symbol(a, Decl(c.ts, 2, 23)) + +type T = Promise; +>T : Symbol(T, Decl(c.ts, 2, 41)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) + +let d: any; +>d : Symbol(d, Decl(c.ts, 4, 3)) + +const f62 = a ? d = (d): T => a ? 0 : async(...c) : T => b; +>f62 : Symbol(f62, Decl(c.ts, 5, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 5, 24)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>c : Symbol(c, Decl(c.ts, 5, 44)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f63 = a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b; +>f63 : Symbol(f63, Decl(c.ts, 6, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>d : Symbol(d, Decl(c.ts, 6, 47)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>d : Symbol(d, Decl(c.ts, 6, 63)) +>d : Symbol(d, Decl(c.ts, 6, 63)) +>T : Symbol(T, Decl(c.ts, 6, 73)) +>c : Symbol(c, Decl(c.ts, 6, 85)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f64 = a ? async (): T => (d): T => async() : b; +>f64 : Symbol(f64, Decl(c.ts, 7, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>d : Symbol(d, Decl(c.ts, 7, 32)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f65 = (a ? async (): T => (d): T => async() : b); +>f65 : Symbol(f65, Decl(c.ts, 8, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>d : Symbol(d, Decl(c.ts, 8, 33)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f66 = a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b; +>f66 : Symbol(f66, Decl(c.ts, 9, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 9, 24)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>c : Symbol(c, Decl(c.ts, 9, 44)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 9, 69)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>c : Symbol(c, Decl(c.ts, 9, 89)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f67 = a ? async (c = a ? async() : d => d): T => async() : b; +>f67 : Symbol(f67, Decl(c.ts, 10, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>c : Symbol(c, Decl(c.ts, 10, 23)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>d : Symbol(d, Decl(c.ts, 10, 40)) +>d : Symbol(d, Decl(c.ts, 10, 40)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f68 = a ? a ? (d): T => a ? async() : b : d => d : b; +>f68 : Symbol(f68, Decl(c.ts, 11, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>d : Symbol(d, Decl(c.ts, 11, 21)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>d : Symbol(d, Decl(c.ts, 11, 47)) +>d : Symbol(d, Decl(c.ts, 11, 47)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f69 = a ? async() : (d => d); +>f69 : Symbol(f69, Decl(c.ts, 12, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>d : Symbol(d, Decl(c.ts, 12, 27)) +>d : Symbol(d, Decl(c.ts, 12, 27)) + +const f70 = a ? async() : d => (a ? async() : d => d); +>f70 : Symbol(f70, Decl(c.ts, 13, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>d : Symbol(d, Decl(c.ts, 13, 25)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>d : Symbol(d, Decl(c.ts, 13, 45)) +>d : Symbol(d, Decl(c.ts, 13, 45)) + +type x = T; +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>T : Symbol(T, Decl(c.ts, 2, 41)) + +declare const x: any; +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) + +const f71 = a ? a ? async (): T => (x): T => async() : x => x; +>f71 : Symbol(f71, Decl(c.ts, 17, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>T : Symbol(T, Decl(c.ts, 17, 39)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>x : Symbol(x, Decl(c.ts, 17, 54)) +>x : Symbol(x, Decl(c.ts, 17, 54)) + +const f72 = a ? a ? async (): Promise => (x): T => async() : x => x; +>f72 : Symbol(f72, Decl(c.ts, 18, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>T : Symbol(T, Decl(c.ts, 18, 50)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>x : Symbol(x, Decl(c.ts, 18, 65)) +>x : Symbol(x, Decl(c.ts, 18, 65)) + +const f73 = a ? async (x): T => async (): T => b; +>f73 : Symbol(f73, Decl(c.ts, 19, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>T : Symbol(T, Decl(c.ts, 19, 26)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f74 = a ? async (x): T => async() : x => x; +>f74 : Symbol(f74, Decl(c.ts, 20, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>async : Symbol(async, Decl(c.ts, 1, 39)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>T : Symbol(T, Decl(c.ts, 20, 26)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) +>x : Symbol(x, Decl(c.ts, 13, 54), Decl(c.ts, 16, 13)) + +declare function h(a: A): A; +>h : Symbol(h, Decl(c.ts, 20, 49)) +>A : Symbol(A, Decl(c.ts, 22, 19)) +>a : Symbol(a, Decl(c.ts, 22, 22)) +>A : Symbol(A, Decl(c.ts, 22, 19)) +>A : Symbol(A, Decl(c.ts, 22, 19)) + +declare namespace number { type T = number; } +>number : Symbol(number, Decl(c.ts, 22, 31)) +>T : Symbol(T, Decl(c.ts, 23, 26)) + +const f75 = a ? async(x = b < (d + 1)): T => x : 0; +>f75 : Symbol(f75, Decl(c.ts, 24, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>x : Symbol(x, Decl(c.ts, 24, 22)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>x : Symbol(x, Decl(c.ts, 24, 22)) + +const f76 = a ? async(x = b << (d + 1)): T => x : 0; +>f76 : Symbol(f76, Decl(c.ts, 25, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>x : Symbol(x, Decl(c.ts, 25, 22)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>x : Symbol(x, Decl(c.ts, 25, 22)) + +const f77 = a ? async(x = new b < (d + 1)): T => x : 0; +>f77 : Symbol(f77, Decl(c.ts, 26, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>x : Symbol(x, Decl(c.ts, 26, 22)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>d : Symbol(d, Decl(c.ts, 4, 3)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>x : Symbol(x, Decl(c.ts, 26, 22)) + +const f78 = a ? async(x = h(b)): T => x : 0; +>f78 : Symbol(f78, Decl(c.ts, 27, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>x : Symbol(x, Decl(c.ts, 27, 22)) +>h : Symbol(h, Decl(c.ts, 20, 49)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>b : Symbol(b, Decl(c.ts, 1, 21)) +>T : Symbol(T, Decl(c.ts, 2, 41)) +>x : Symbol(x, Decl(c.ts, 27, 22)) + +const f79 = a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0; +>f79 : Symbol(f79, Decl(c.ts, 28, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>a : Symbol(a, Decl(c.ts, 28, 35)) +>a : Symbol(a, Decl(c.ts, 28, 57)) + +const f80 = a ? async(): Promise<([a: number])> => [b] : 0; +>f80 : Symbol(f80, Decl(c.ts, 29, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f81 = a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0; +>f81 : Symbol(f81, Decl(c.ts, 30, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>r\u0065adonly : Symbol(r\u0065adonly, Decl(c.ts, 30, 34)) +>readonly : Symbol(readonly, Decl(c.ts, 30, 65)) + +const f82 = a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0; +>f82 : Symbol(f82, Decl(c.ts, 31, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>g\u0065t : Symbol(g\u0065t, Decl(c.ts, 31, 34)) +>get : Symbol(get, Decl(c.ts, 31, 60)) + +const f83 = a ? async(): Promise => b : 0; +>f83 : Symbol(f83, Decl(c.ts, 32, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) +>n\u0075mber : Symbol(number, Decl(c.ts, 22, 31)) +>T : Symbol(number.T, Decl(c.ts, 23, 26)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f84 = a ? a ? as\u0079nc() : d => d : b; +>f84 : Symbol(f84, Decl(c.ts, 33, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>as\u0079nc : Symbol(async, Decl(c.ts, 1, 39)) +>d : Symbol(d, Decl(c.ts, 33, 34)) +>d : Symbol(d, Decl(c.ts, 33, 34)) +>b : Symbol(b, Decl(c.ts, 1, 21)) + +const f85 = a ? async(): Promise => 0 : 0; +>f85 : Symbol(f85, Decl(c.ts, 34, 5)) +>a : Symbol(a, Decl(c.ts, 1, 13)) +>Promise : Symbol(Promise, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.iterable.d.ts, --, --), Decl(lib.es2015.promise.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --)) diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.types b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.types index 9f5aa33f8d645..13daeee6b21a3 100644 --- a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.types +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunction.types @@ -1,6 +1,6 @@ //// [tests/cases/compiler/parenthesizedAsyncArrowFunction.ts] //// -=== parenthesizedAsyncArrowFunction.ts === +=== a.ts === // Repro from #20096 let foo = (async bar => bar); @@ -10,3 +10,1157 @@ let foo = (async bar => bar); >bar : any >bar : any +const a = true; +>a : true +>true : true + +const b = 1; +>b : 1 +>1 : 1 + +const c = [b]; +>c : number[] +>[b] : number[] +>b : 1 + +function async(...c: number[]): number { +>async : (...c: number[]) => number +>c : number[] + + return b; +>b : 1 +} + +const f1 = a ? async() : 0; +>f1 : number +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: number[]) => number +>0 : 0 + +const f2 = a ? async() : x => x; +>f2 : number | ((x: any) => any) +>a ? async() : x => x : number | ((x: any) => any) +>a : true +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f3 = a ? a ? async() : 0 : b; +>f3 : number +>a ? a ? async() : 0 : b : number +>a : true +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: number[]) => number +>0 : 0 +>b : 1 + +const f4 = a ? x => async() : x => x; +>f4 : (x: any) => any +>a ? x => async() : x => x : (x: any) => any +>a : true +>x => async() : (x: any) => number +>x : any +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f5 = a ? async (): Promise => b : () => b; +>f5 : (() => Promise) | (() => number) +>a ? async (): Promise => b : () => b : (() => Promise) | (() => number) +>a : true +>async (): Promise => b : () => Promise +>b : 1 +>() => b : () => number +>b : 1 + +const f6 = a ? async (): Promise => { return b; } : () => b; +>f6 : (() => Promise) | (() => number) +>a ? async (): Promise => { return b; } : () => b : (() => Promise) | (() => number) +>a : true +>async (): Promise => { return b; } : () => Promise +>b : 1 +>() => b : () => number +>b : 1 + +const f7 = a ? async (): Promise => a ? async() : 0 : () => b; +>f7 : (() => Promise) | (() => number) +>a ? async (): Promise => a ? async() : 0 : () => b : (() => Promise) | (() => number) +>a : true +>async (): Promise => a ? async() : 0 : () => Promise +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: number[]) => number +>0 : 0 +>() => b : () => number +>b : 1 + +const f8 = a ? (): number => b : () => b; +>f8 : () => number +>a ? (): number => b : () => b : () => number +>a : true +>(): number => b : () => number +>b : 1 +>() => b : () => number +>b : 1 + +const f9 = a ? async(...c) : 0; +>f9 : number +>a ? async(...c) : 0 : number +>a : true +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>0 : 0 + +const f10 = a ? async(...c) : x => x; +>f10 : number | ((x: any) => any) +>a ? async(...c) : x => x : number | ((x: any) => any) +>a : true +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>x => x : (x: any) => any +>x : any +>x : any + +const f11 = a ? async (...c: number[]): Promise => c.length : () => 0; +>f11 : ((...c: number[]) => Promise) | (() => number) +>a ? async (...c: number[]): Promise => c.length : () => 0 : ((...c: number[]) => Promise) | (() => number) +>a : true +>async (...c: number[]): Promise => c.length : (...c: number[]) => Promise +>c : number[] +>c.length : number +>c : number[] +>length : number +>() => 0 : () => number +>0 : 0 + +const f12 = a ? async() : x => async (...c): Promise => c.length; +>f12 : number | ((x: any) => (...c: any[]) => Promise) +>a ? async() : x => async (...c): Promise => c.length : number | ((x: any) => (...c: any[]) => Promise) +>a : true +>async() : number +>async : (...c: number[]) => number +>x => async (...c): Promise => c.length : (x: any) => (...c: any[]) => Promise +>x : any +>async (...c): Promise => c.length : (...c: any[]) => Promise +>c : any[] +>c.length : number +>c : any[] +>length : number + +type T = Promise; +>T : T + +const f13 = a ? async() : x => async (): Promise => b; +>f13 : number | ((x: any) => () => Promise) +>a ? async() : x => async (): Promise => b : number | ((x: any) => () => Promise) +>a : true +>async() : number +>async : (...c: number[]) => number +>x => async (): Promise => b : (x: any) => () => Promise +>x : any +>async (): Promise => b : () => Promise +>b : 1 + +const f14 = a ? async() : T => async (): T => 0; +>f14 : (() => T) | ((T: any) => number) +>a ? async() : T => async (): T => 0 : (() => T) | ((T: any) => number) +>a : true +>async() : T => async () : () => T +>async () : number +>async : (...c: number[]) => number +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f15 = a ? (b) : x => async (): T => 0; +>f15 : 1 | ((x: any) => () => T) +>a ? (b) : x => async (): T => 0 : 1 | ((x: any) => () => T) +>a : true +>(b) : 1 +>b : 1 +>x => async (): T => 0 : (x: any) => () => T +>x : any +>async (): T => 0 : () => T +>0 : 0 + +const f16 = a ? async(...c) : T => async (): T => 0; +>f16 : ((...c: any[]) => T) | ((T: any) => number) +>a ? async(...c) : T => async (): T => 0 : ((...c: any[]) => T) | ((T: any) => number) +>a : true +>async(...c) : T => async () : (...c: any[]) => T +>c : any[] +>async () : number +>async : (...c: number[]) => number +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f17 = a ? async() : T => (b): number => b; +>f17 : (() => T) | ((number: any) => number) +>a ? async() : T => (b): number => b : (() => T) | ((number: any) => number) +>a : true +>async() : T => (b) : () => T +>(b) : 1 +>b : 1 +>number => b : (number: any) => number +>number : any +>b : 1 + +const f18 = a ? async() : T => async (): T => 0; +>f18 : (() => T) | ((T: any) => number) +>a ? async() : T => async (): T => 0 : (() => T) | ((T: any) => number) +>a : true +>async() : T => async () : () => T +>async () : number +>async : (...c: number[]) => number +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f19 = a ? async(...c) : T => (b): number => b; +>f19 : ((...c: any[]) => T) | ((number: any) => number) +>a ? async(...c) : T => (b): number => b : ((...c: any[]) => T) | ((number: any) => number) +>a : true +>async(...c) : T => (b) : (...c: any[]) => T +>c : any[] +>(b) : 1 +>b : 1 +>number => b : (number: any) => number +>number : any +>b : 1 + +const f20 = a ? async(...c) : T => async (): T => 0; +>f20 : ((...c: any[]) => T) | ((T: any) => number) +>a ? async(...c) : T => async (): T => 0 : ((...c: any[]) => T) | ((T: any) => number) +>a : true +>async(...c) : T => async () : (...c: any[]) => T +>c : any[] +>async () : number +>async : (...c: number[]) => number +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f21 = a ? (x): number => (b): T => 0; +>f21 : (x: any) => number +>a ? (x): number => (b): T => 0 : (x: any) => number +>a : true +>(x): number => (b) : (x: any) => number +>x : any +>(b) : 1 +>b : 1 +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f22 = a ? async (): Promise => (b): T => 0; +>f22 : (() => Promise) | ((T: any) => number) +>a ? async (): Promise => (b): T => 0 : (() => Promise) | ((T: any) => number) +>a : true +>async (): Promise => (b) : () => Promise +>(b) : 1 +>b : 1 +>T => 0 : (T: any) => number +>T : any +>0 : 0 + +const f23 = a ? async () => async() : x => x; +>f23 : (x: any) => any +>a ? async () => async() : x => x : (x: any) => any +>a : true +>async () => async() : () => Promise +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f24 = a ? async (...c) => async() : x => x; +>f24 : ((...c: any[]) => Promise) | ((x: any) => any) +>a ? async (...c) => async() : x => x : ((...c: any[]) => Promise) | ((x: any) => any) +>a : true +>async (...c) => async() : (...c: any[]) => Promise +>c : any[] +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f25 = a ? () => async() : x => x; +>f25 : (x: any) => any +>a ? () => async() : x => x : (x: any) => any +>a : true +>() => async() : () => number +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f26 = a ? async (c: number): Promise => async() : x => x; +>f26 : (x: any) => any +>a ? async (c: number): Promise => async() : x => x : (x: any) => any +>a : true +>async (c: number): Promise => async() : (c: number) => Promise +>c : number +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f27 = a ? async (): Promise => async() : x => x; +>f27 : (x: any) => any +>a ? async (): Promise => async() : x => x : (x: any) => any +>a : true +>async (): Promise => async() : () => Promise +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f28 = a ? async (): Promise => async(...c) : x => x; +>f28 : (x: any) => any +>a ? async (): Promise => async(...c) : x => x : (x: any) => any +>a : true +>async (): Promise => async(...c) : () => Promise +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>x => x : (x: any) => any +>x : any +>x : any + +const f29 = a ? async (...c): Promise => async() : x => x; +>f29 : ((...c: any[]) => Promise) | ((x: any) => any) +>a ? async (...c): Promise => async() : x => x : ((...c: any[]) => Promise) | ((x: any) => any) +>a : true +>async (...c): Promise => async() : (...c: any[]) => Promise +>c : any[] +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f30 = a ? async (): Promise => async() : x => x; +>f30 : (x: any) => any +>a ? async (): Promise => async() : x => x : (x: any) => any +>a : true +>async (): Promise => async() : () => Promise +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f31 = a ? async (): (Promise) => async() : x => x; +>f31 : (x: any) => any +>a ? async (): (Promise) => async() : x => x : (x: any) => any +>a : true +>async (): (Promise) => async() : () => (Promise) +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f32 = a ? async (...c: number[]): T => async() : x => x; +>f32 : ((...c: number[]) => T) | ((x: any) => any) +>a ? async (...c: number[]): T => async() : x => x : ((...c: number[]) => T) | ((x: any) => any) +>a : true +>async (...c: number[]): T => async() : (...c: number[]) => T +>c : number[] +>async() : number +>async : (...c: number[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f33 = a ? async() : 0 +>f33 : number +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: number[]) => number +>0 : 0 + +{} +const f34 = a ? async() : {} +>f34 : {} +>a ? async() : {} : number | {} +>a : true +>async() : number +>async : (...c: number[]) => number +>{} : {} + +{} + +function* g() { +>g : () => Generator + + const f1 = a ? yield async(...c) : 0; +>f1 : any +>a ? yield async(...c) : 0 : any +>a : true +>yield async(...c) : any +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>0 : 0 + + const f2 = a ? yield async(...c) : x => x; +>f2 : any +>a ? yield async(...c) : x => x : any +>a : true +>yield async(...c) : any +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>x => x : (x: any) => any +>x : any +>x : any +} + +const d = { a: c }; +>d : { a: number[]; } +>{ a: c } : { a: number[]; } +>a : number[] +>c : number[] + +const e = () => c; +>e : () => number[] +>() => c : () => number[] +>c : number[] + +const f35 = async(...d.a); +>f35 : number +>async(...d.a) : number +>async : (...c: number[]) => number +>...d.a : number +>d.a : number[] +>d : { a: number[]; } +>a : number[] + +const f36 = async(...e()); +>f36 : number +>async(...e()) : number +>async : (...c: number[]) => number +>...e() : number +>e() : number[] +>e : () => number[] + +const f37 = async(...[b]); +>f37 : number +>async(...[b]) : number +>async : (...c: number[]) => number +>...[b] : number +>[b] : [number] +>b : 1 + +type U = number; +>U : number + +const f38 = a ? (c): U => (b) : x => x; +>f38 : (x: any) => any +>a ? (c): U => (b) : x => x : (x: any) => any +>a : true +>(c): U => (b) : (c: any) => U +>c : any +>(b) : 1 +>b : 1 +>x => x : (x: any) => any +>x : any +>x : any + +const f39 = a ? async() : function() {}; +>f39 : number | (() => void) +>a ? async() : function() {} : number | (() => void) +>a : true +>async() : number +>async : (...c: number[]) => number +>function() {} : () => void + +const f40 = a ? async() : "b" +>f40 : number | "b" +>a ? async() : "b" : number | "b" +>a : true +>async() : number +>async : (...c: number[]) => number +>"b" : "b" + +{} +const f41 = a ? async(...c) : 0 +>f41 : number +>a ? async(...c) : 0 : number +>a : true +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>0 : 0 + +{} +const f42 = a ? (c) : 0 +>f42 : 0 | number[] +>a ? (c) : 0 : 0 | number[] +>a : true +>(c) : number[] +>c : number[] +>0 : 0 + +{} + +const f43 = a ? async() : T => async (...c): T => c.length; +>f43 : (() => T) | ((T: any) => number) +>a ? async() : T => async (...c): T => c.length : (() => T) | ((T: any) => number) +>a : true +>async() : T => async (...c) : () => T +>async (...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>T => c.length : (T: any) => number +>T : any +>c.length : number +>c : number[] +>length : number + +const f44 = a ? async (): T => (b) : d => d; +>f44 : (d: any) => any +>a ? async (): T => (b) : d => d : (d: any) => any +>a : true +>async (): T => (b) : () => T +>(b) : 1 +>b : 1 +>d => d : (d: any) => any +>d : any +>d : any + +const f45 = a ? async (): T => async() : d => d; +>f45 : (d: any) => any +>a ? async (): T => async() : d => d : (d: any) => any +>a : true +>async (): T => async() : () => T +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any + +const f46 = a ? async (): T => async() : b; +>f46 : 1 | (() => T) +>a ? async (): T => async() : b : 1 | (() => T) +>a : true +>async (): T => async() : () => T +>async() : number +>async : (...c: number[]) => number +>b : 1 + +const f47 = a ? a ? async() : d => d : b; +>f47 : number | ((d: any) => any) +>a ? a ? async() : d => d : b : number | ((d: any) => any) +>a : true +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f48 = a ? a ? async(b) : d => d : b; +>f48 : number | ((d: any) => any) +>a ? a ? async(b) : d => d : b : number | ((d: any) => any) +>a : true +>a ? async(b) : d => d : number | ((d: any) => any) +>a : true +>async(b) : number +>async : (...c: number[]) => number +>b : 1 +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f49 = a ? a ? async(...c) : d => d : b; +>f49 : number | ((d: any) => any) +>a ? a ? async(...c) : d => d : b : number | ((d: any) => any) +>a : true +>a ? async(...c) : d => d : number | ((d: any) => any) +>a : true +>async(...c) : number +>async : (...c: number[]) => number +>...c : number +>c : number[] +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f50 = a ? a ? async() : T => b : async (): T => b; +>f50 : number | (() => T) | ((T: any) => number) +>a ? a ? async() : T => b : async (): T => b : number | (() => T) | ((T: any) => number) +>a : true +>a ? async() : T => b : async () : number | (() => T) +>a : true +>async() : T => b : () => T +>b : 1 +>async () : number +>async : (...c: number[]) => number +>T => b : (T: any) => number +>T : any +>b : 1 + +const f51 = a ? async (): T => async() : (d): number => d; +>f51 : (() => T) | ((d: any) => number) +>a ? async (): T => async() : (d): number => d : (() => T) | ((d: any) => number) +>a : true +>async (): T => async() : () => T +>async() : number +>async : (...c: number[]) => number +>(d): number => d : (d: any) => number +>d : any +>d : any + +const f52 = a ? a ? async (): T => async() : d => d : b; +>f52 : 1 | ((d: any) => any) +>a ? a ? async (): T => async() : d => d : b : 1 | ((d: any) => any) +>a : true +>a ? async (): T => async() : d => d : (d: any) => any +>a : true +>async (): T => async() : () => T +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f53 = a ? async (): T => a ? async() : b : d => d; +>f53 : (d: any) => any +>a ? async (): T => a ? async() : b : d => d : (d: any) => any +>a : true +>async (): T => a ? async() : b : () => T +>a ? async() : b : number +>a : true +>async() : number +>async : (...c: number[]) => number +>b : 1 +>d => d : (d: any) => any +>d : any +>d : any + +const f54 = a ? a ? async() : d => d : a ? async() : d => d; +>f54 : number | ((d: any) => any) +>a ? a ? async() : d => d : a ? async() : d => d : number | ((d: any) => any) +>a : true +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any + +const f55 = a ? a ? a ? async() : d => d : b : b; +>f55 : number | ((d: any) => any) +>a ? a ? a ? async() : d => d : b : b : number | ((d: any) => any) +>a : true +>a ? a ? async() : d => d : b : number | ((d: any) => any) +>a : true +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: number[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 +>b : 1 + +const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +>f56 : ((d: any) => number) | ((d: any) => boolean) +>a ? d => a ? (0) : a ? async(b) : async() : (d => d = a) : ((d: any) => number) | ((d: any) => boolean) +>a : true +>d => a ? (0) : a ? async(b) : async() : (d: any) => number +>d : any +>a ? (0) : a ? async(b) : async() : number +>a : true +>(0) : 0 +>0 : 0 +>a ? async(b) : async() : number +>a : true +>async(b) : number +>async : (...c: number[]) => number +>b : 1 +>async() : number +>async : (...c: number[]) => number +>(d => d = a) : (d: any) => boolean +>d => d = a : (d: any) => boolean +>d : any +>d = a : true +>d : any +>a : true + +const f57 = a ? d => d = async () => async() : (d => d = 0); +>f57 : ((d: any) => () => Promise) | ((d: any) => number) +>a ? d => d = async () => async() : (d => d = 0) : ((d: any) => () => Promise) | ((d: any) => number) +>a : true +>d => d = async () => async() : (d: any) => () => Promise +>d : any +>d = async () => async() : () => Promise +>d : any +>async () => async() : () => Promise +>async() : number +>async : (...c: number[]) => number +>(d => d = 0) : (d: any) => number +>d => d = 0 : (d: any) => number +>d : any +>d = 0 : 0 +>d : any +>0 : 0 + +=== b.ts === +const f58 = a ? async(...c: number[]): Promise => 0; +>f58 : any +>a ? async(...c: number[]): Promise => 0 : any +>a : true +>async(...c: number[]): Promise => 0 : (...c: number[]) => Promise +>c : number[] +>0 : 0 +> : any + +const f59 = a ? async (): Promise {} : d => d; +>f59 : (d: any) => any +>a ? async (): Promise {} : d => d : (d: any) => any +>a : true +>async (): Promise {} : () => Promise +>d => d : (d: any) => any +>d : any +>d : any + +const f60 = a ? (c): number {} : d => d; +>f60 : (d: any) => any +>a ? (c): number {} : d => d : (d: any) => any +>a : true +>(c): number {} : (c: any) => number +>c : any +>d => d : (d: any) => any +>d : any +>d : any + +const f61 = a ? async() : T => async(a ? b); +>f61 : any +>a ? async() : T => async(a ? b) : any +>a : true +>async() : T => async(a ? b) : () => T +>async(a ? b) : number +>async : (...c: number[]) => number +>a ? b : any +>a : true +>b : 1 +> : any +> : any + +=== c.ts === +export {}; +declare const a: any, b: any, c: any[]; +>a : any +>b : any +>c : any[] + +declare function async(...a: any[]): any; +>async : (...a: any[]) => any +>a : any[] + +type T = Promise; +>T : T + +let d: any; +>d : any + +const f62 = a ? d = (d): T => a ? 0 : async(...c) : T => b; +>f62 : any +>a ? d = (d): T => a ? 0 : async(...c) : T => b : any +>a : any +>d = (d) : any +>d : any +>(d) : any +>d : any +>T => a ? 0 : async(...c) : T => b : (T: any) => 0 | ((...c: any[]) => T) +>T : any +>a ? 0 : async(...c) : T => b : 0 | ((...c: any[]) => T) +>a : any +>0 : 0 +>async(...c) : T => b : (...c: any[]) => T +>c : any[] +>b : any + +const f63 = a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b; +>f63 : (d: any) => any +>a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b : (d: any) => any +>a : any +>async (): T => async (): T => (d): T => b : () => T +>async (): T => (d): T => b : () => T +>(d): T => b : (d: any) => T +>d : any +>b : any +>a ? d => (d): T => async(...c) : T => b : (d: any) => any +>a : any +>d => (d) : (d: any) => any +>d : any +>(d) : any +>d : any +>T => async(...c) : T => b : (T: any) => (...c: any[]) => T +>T : any +>async(...c) : T => b : (...c: any[]) => T +>c : any[] +>b : any + +const f64 = a ? async (): T => (d): T => async() : b; +>f64 : any +>a ? async (): T => (d): T => async() : b : any +>a : any +>async (): T => (d): T => async() : () => T +>(d): T => async() : (d: any) => T +>d : any +>async() : any +>async : (...a: any[]) => any +>b : any + +const f65 = (a ? async (): T => (d): T => async() : b); +>f65 : any +>(a ? async (): T => (d): T => async() : b) : any +>a ? async (): T => (d): T => async() : b : any +>a : any +>async (): T => (d): T => async() : () => T +>(d): T => async() : (d: any) => T +>d : any +>async() : any +>async : (...a: any[]) => any +>b : any + +const f66 = a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b; +>f66 : any +>a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b : any +>a : any +>d = (d) : any +>d : any +>(d) : any +>d : any +>T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b : (T: any) => 0 | ((...c: any[]) => T) +>T : any +>a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b : 0 | ((...c: any[]) => T) +>a : any +>0 : 0 +>async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b : (...c: any[]) => T +>c : any[] +>a ? d = (d): T => a ? 0 : async(...c) : T => b : any +>a : any +>d = (d) : any +>d : any +>(d) : any +>d : any +>T => a ? 0 : async(...c) : T => b : (T: any) => 0 | ((...c: any[]) => T) +>T : any +>a ? 0 : async(...c) : T => b : 0 | ((...c: any[]) => T) +>a : any +>0 : 0 +>async(...c) : T => b : (...c: any[]) => T +>c : any[] +>b : any + +const f67 = a ? async (c = a ? async() : d => d): T => async() : b; +>f67 : any +>a ? async (c = a ? async() : d => d): T => async() : b : any +>a : any +>async (c = a ? async() : d => d): T => async() : (c?: any) => T +>c : any +>a ? async() : d => d : any +>a : any +>async() : any +>async : (...a: any[]) => any +>d => d : (d: any) => any +>d : any +>d : any +>async() : any +>async : (...a: any[]) => any +>b : any + +const f68 = a ? a ? (d): T => a ? async() : b : d => d : b; +>f68 : any +>a ? a ? (d): T => a ? async() : b : d => d : b : any +>a : any +>a ? (d): T => a ? async() : b : d => d : (d: any) => any +>a : any +>(d): T => a ? async() : b : (d: any) => T +>d : any +>a ? async() : b : any +>a : any +>async() : any +>async : (...a: any[]) => any +>b : any +>d => d : (d: any) => any +>d : any +>d : any +>b : any + +const f69 = a ? async() : (d => d); +>f69 : any +>a ? async() : (d => d) : any +>a : any +>async() : any +>async : (...a: any[]) => any +>(d => d) : (d: any) => any +>d => d : (d: any) => any +>d : any +>d : any + +const f70 = a ? async() : d => (a ? async() : d => d); +>f70 : any +>a ? async() : d => (a ? async() : d => d) : any +>a : any +>async() : any +>async : (...a: any[]) => any +>d => (a ? async() : d => d) : (d: any) => any +>d : any +>(a ? async() : d => d) : any +>a ? async() : d => d : any +>a : any +>async() : any +>async : (...a: any[]) => any +>d => d : (d: any) => any +>d : any +>d : any + +type x = T; +>x : T + +declare const x: any; +>x : any + +const f71 = a ? a ? async (): T => (x): T => async() : x => x; +>f71 : (T: any) => any +>a ? a ? async (): T => (x): T => async() : x => x : (T: any) => any +>a : any +>a ? async (): T => (x): T => async() : (T: any) => any +>a : any +>async (): T => (x) : () => T +>(x) : any +>x : any +>T => async() : (T: any) => any +>T : any +>async() : any +>async : (...a: any[]) => any +>x => x : (x: any) => any +>x : any +>x : any + +const f72 = a ? a ? async (): Promise => (x): T => async() : x => x; +>f72 : (T: any) => any +>a ? a ? async (): Promise => (x): T => async() : x => x : (T: any) => any +>a : any +>a ? async (): Promise => (x): T => async() : (T: any) => any +>a : any +>async (): Promise => (x) : () => Promise +>(x) : any +>x : any +>T => async() : (T: any) => any +>T : any +>async() : any +>async : (...a: any[]) => any +>x => x : (x: any) => any +>x : any +>x : any + +const f73 = a ? async (x): T => async (): T => b; +>f73 : any +>a ? async (x): T => async (): T => b : any +>a : any +>async (x) : any +>async : (...a: any[]) => any +>x : any +>T => async (): T => b : (T: any) => () => T +>T : any +>async (): T => b : () => T +>b : any + +const f74 = a ? async (x): T => async() : x => x; +>f74 : any +>a ? async (x): T => async() : x => x : any +>a : any +>async (x) : any +>async : (...a: any[]) => any +>x : any +>T => async() : x => x : (T: any) => () => x +>T : any +>async() : x => x : () => x +>x : any + +declare function h(a: A): A; +>h : (a: A) => A +>a : A + +declare namespace number { type T = number; } +>T : number + +const f75 = a ? async(x = b < (d + 1)): T => x : 0; +>f75 : 0 | ((x?: boolean) => T) +>a ? async(x = b < (d + 1)): T => x : 0 : 0 | ((x?: boolean) => T) +>a : any +>async(x = b < (d + 1)): T => x : (x?: boolean) => T +>x : boolean +>b < (d + 1) : boolean +>b : any +>(d + 1) : any +>d + 1 : any +>d : any +>1 : 1 +>x : boolean +>0 : 0 + +const f76 = a ? async(x = b << (d + 1)): T => x : 0; +>f76 : 0 | ((x?: number) => T) +>a ? async(x = b << (d + 1)): T => x : 0 : 0 | ((x?: number) => T) +>a : any +>async(x = b << (d + 1)): T => x : (x?: number) => T +>x : number +>b << (d + 1) : number +>b : any +>(d + 1) : any +>d + 1 : any +>d : any +>1 : 1 +>x : number +>0 : 0 + +const f77 = a ? async(x = new b < (d + 1)): T => x : 0; +>f77 : 0 | ((x?: boolean) => T) +>a ? async(x = new b < (d + 1)): T => x : 0 : 0 | ((x?: boolean) => T) +>a : any +>async(x = new b < (d + 1)): T => x : (x?: boolean) => T +>x : boolean +>new b < (d + 1) : boolean +>new b : any +>b : any +>(d + 1) : any +>d + 1 : any +>d : any +>1 : 1 +>x : boolean +>0 : 0 + +const f78 = a ? async(x = h(b)): T => x : 0; +>f78 : 0 | ((x?: T) => T) +>a ? async(x = h(b)): T => x : 0 : 0 | ((x?: T) => T) +>a : any +>async(x = h(b)): T => x : (x?: T) => T +>x : T +>h(b) : T +>h : (a: A) => A +>b : any +>x : T +>0 : 0 + +const f79 = a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0; +>f79 : 0 | (() => Promise<({ a: number[]; })>) +>a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0 : 0 | (() => Promise<({ a: number[]; })>) +>a : any +>async(): Promise<({ a: number[] })> => ({ a: [] }) : () => Promise<({ a: number[]; })> +>a : number[] +>({ a: [] }) : { a: undefined[]; } +>{ a: [] } : { a: undefined[]; } +>a : undefined[] +>[] : undefined[] +>0 : 0 + +const f80 = a ? async(): Promise<([a: number])> => [b] : 0; +>f80 : 0 | (() => Promise<([a: number])>) +>a ? async(): Promise<([a: number])> => [b] : 0 : 0 | (() => Promise<([a: number])>) +>a : any +>async(): Promise<([a: number])> => [b] : () => Promise<([a: number])> +>[b] : [any] +>b : any +>0 : 0 + +const f81 = a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0; +>f81 : 0 | (() => Promise<{ readonly: number; }>) +>a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0 : 0 | (() => Promise<{ readonly: number; }>) +>a : any +>async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : () => Promise<{ readonly: number; }> +>r\u0065adonly : number +>({ readonly: 0 }) : { readonly: number; } +>{ readonly: 0 } : { readonly: number; } +>readonly : number +>0 : 0 +>0 : 0 + +const f82 = a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0; +>f82 : 0 | (() => Promise<{ get: number; }>) +>a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0 : 0 | (() => Promise<{ get: number; }>) +>a : any +>async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : () => Promise<{ get: number; }> +>g\u0065t : number +>({ get: 0 }) : { get: number; } +>{ get: 0 } : { get: number; } +>get : number +>0 : 0 +>0 : 0 + +const f83 = a ? async(): Promise => b : 0; +>f83 : 0 | (() => Promise) +>a ? async(): Promise => b : 0 : 0 | (() => Promise) +>a : any +>async(): Promise => b : () => Promise +>n\u0075mber : any +>b : any +>0 : 0 + +const f84 = a ? a ? as\u0079nc() : d => d : b; +>f84 : any +>a ? a ? as\u0079nc() : d => d : b : any +>a : any +>a ? as\u0079nc() : d => d : any +>a : any +>as\u0079nc() : any +>as\u0079nc : (...a: any[]) => any +>d => d : (d: any) => any +>d : any +>d : any +>b : any + +const f85 = a ? async(): Promise => 0 : 0; +>f85 : 0 | (() => Promise) +>a ? async(): Promise => 0 : 0 : 0 | (() => Promise) +>a : any +>async(): Promise => 0 : () => Promise +>0 : 0 +>0 : 0 + diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.js b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.js new file mode 100644 index 0000000000000..d2018d918bcc5 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.js @@ -0,0 +1,109 @@ +//// [tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts] //// + +//// [a.js] +const a = true; +const b = 1; +const c = [b]; + +function async(...c) { + return b; +} + +const f1 = a ? async(...c) : 0; +const f2 = a ? async(...c) : x => x; +const f3 = a ? async () => async() : x => x; +const f4 = a ? async (...c) => async() : x => x; +const f5 = a ? () => async() : x => x; + +const f6 = a ? async() : 0 +{} +const f7 = a ? async() : {} +{} + +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} + +const d = { a: c }; +const e = () => c; +const f8 = async(...d.a); +const f9 = async(...e()); +const f10 = async(...[b]); +const f11 = a ? async() : function() {}; +const f12 = a ? async() : "b" +{} +const f13 = a ? async(...c) : 0 +{} +const f14 = a ? (c) : 0 +{} +const f15 = a ? async() : 0; +{} + +const f16 = a ? a ? async() : d => d : b; +const f17 = a ? a ? async(b) : d => d : b; +const f18 = a ? a ? async(...c) : d => d : b; +const f19 = a ? a ? a ? async() : d => d : b : b; + +const f20 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f21 = a ? d => d = async () => async() : (d => d = 0); +const f22 = h => a ? async(h = a ? async() : d => d) : d => d; +const f23 = a ? async() : (d => d); +const f24 = a ? async() : d => (a ? async() : d => d); +const f25 = a ? a ? as\u0079nc() : d => d : b; + + +//// [a.js] +"use strict"; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +const a = true; +const b = 1; +const c = [b]; +function async(...c) { + return b; +} +const f1 = a ? async(...c) : 0; +const f2 = a ? async(...c) : x => x; +const f3 = a ? () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f4 = a ? (...c) => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : x => x; +const f5 = a ? () => async() : x => x; +const f6 = a ? async() : 0; +{ } +const f7 = a ? async() : {}; +{ } +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} +const d = { a: c }; +const e = () => c; +const f8 = async(...d.a); +const f9 = async(...e()); +const f10 = async(...[b]); +const f11 = a ? async() : function () { }; +const f12 = a ? async() : "b"; +{ } +const f13 = a ? async(...c) : 0; +{ } +const f14 = a ? (c) : 0; +{ } +const f15 = a ? async() : 0; +{ } +const f16 = a ? a ? async() : d => d : b; +const f17 = a ? a ? async(b) : d => d : b; +const f18 = a ? a ? async(...c) : d => d : b; +const f19 = a ? a ? a ? async() : d => d : b : b; +const f20 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f21 = a ? d => d = () => __awaiter(void 0, void 0, void 0, function* () { return async(); }) : (d => d = 0); +const f22 = h => a ? async(h = a ? async() : d => d) : d => d; +const f23 = a ? async() : (d => d); +const f24 = a ? async() : d => (a ? async() : d => d); +const f25 = a ? a ? as\u0079nc() : d => d : b; diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.symbols b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.symbols new file mode 100644 index 0000000000000..8457a46127de5 --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.symbols @@ -0,0 +1,246 @@ +//// [tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts] //// + +=== a.js === +const a = true; +>a : Symbol(a, Decl(a.js, 0, 5)) + +const b = 1; +>b : Symbol(b, Decl(a.js, 1, 5)) + +const c = [b]; +>c : Symbol(c, Decl(a.js, 2, 5)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +function async(...c) { +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 4, 15)) + + return b; +>b : Symbol(b, Decl(a.js, 1, 5)) +} + +const f1 = a ? async(...c) : 0; +>f1 : Symbol(f1, Decl(a.js, 8, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) + +const f2 = a ? async(...c) : x => x; +>f2 : Symbol(f2, Decl(a.js, 9, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) +>x : Symbol(x, Decl(a.js, 9, 28)) +>x : Symbol(x, Decl(a.js, 9, 28)) + +const f3 = a ? async () => async() : x => x; +>f3 : Symbol(f3, Decl(a.js, 10, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>x : Symbol(x, Decl(a.js, 10, 36)) +>x : Symbol(x, Decl(a.js, 10, 36)) + +const f4 = a ? async (...c) => async() : x => x; +>f4 : Symbol(f4, Decl(a.js, 11, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>c : Symbol(c, Decl(a.js, 11, 22)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>x : Symbol(x, Decl(a.js, 11, 40)) +>x : Symbol(x, Decl(a.js, 11, 40)) + +const f5 = a ? () => async() : x => x; +>f5 : Symbol(f5, Decl(a.js, 12, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>x : Symbol(x, Decl(a.js, 12, 30)) +>x : Symbol(x, Decl(a.js, 12, 30)) + +const f6 = a ? async() : 0 +>f6 : Symbol(f6, Decl(a.js, 14, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) + +{} +const f7 = a ? async() : {} +>f7 : Symbol(f7, Decl(a.js, 16, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) + +{} + +function* g() { +>g : Symbol(g, Decl(a.js, 17, 2)) + + const f1 = a ? yield async(...c) : 0; +>f1 : Symbol(f1, Decl(a.js, 20, 9)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) + + const f2 = a ? yield async(...c) : x => x; +>f2 : Symbol(f2, Decl(a.js, 21, 9)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) +>x : Symbol(x, Decl(a.js, 21, 38)) +>x : Symbol(x, Decl(a.js, 21, 38)) +} + +const d = { a: c }; +>d : Symbol(d, Decl(a.js, 24, 5)) +>a : Symbol(a, Decl(a.js, 24, 11)) +>c : Symbol(c, Decl(a.js, 2, 5)) + +const e = () => c; +>e : Symbol(e, Decl(a.js, 25, 5)) +>c : Symbol(c, Decl(a.js, 2, 5)) + +const f8 = async(...d.a); +>f8 : Symbol(f8, Decl(a.js, 26, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d.a : Symbol(a, Decl(a.js, 24, 11)) +>d : Symbol(d, Decl(a.js, 24, 5)) +>a : Symbol(a, Decl(a.js, 24, 11)) + +const f9 = async(...e()); +>f9 : Symbol(f9, Decl(a.js, 27, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>e : Symbol(e, Decl(a.js, 25, 5)) + +const f10 = async(...[b]); +>f10 : Symbol(f10, Decl(a.js, 28, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +const f11 = a ? async() : function() {}; +>f11 : Symbol(f11, Decl(a.js, 29, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) + +const f12 = a ? async() : "b" +>f12 : Symbol(f12, Decl(a.js, 30, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) + +{} +const f13 = a ? async(...c) : 0 +>f13 : Symbol(f13, Decl(a.js, 32, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) + +{} +const f14 = a ? (c) : 0 +>f14 : Symbol(f14, Decl(a.js, 34, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>c : Symbol(c, Decl(a.js, 2, 5)) + +{} +const f15 = a ? async() : 0; +>f15 : Symbol(f15, Decl(a.js, 36, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) + +{} + +const f16 = a ? a ? async() : d => d : b; +>f16 : Symbol(f16, Decl(a.js, 39, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 39, 29)) +>d : Symbol(d, Decl(a.js, 39, 29)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +const f17 = a ? a ? async(b) : d => d : b; +>f17 : Symbol(f17, Decl(a.js, 40, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>b : Symbol(b, Decl(a.js, 1, 5)) +>d : Symbol(d, Decl(a.js, 40, 30)) +>d : Symbol(d, Decl(a.js, 40, 30)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +const f18 = a ? a ? async(...c) : d => d : b; +>f18 : Symbol(f18, Decl(a.js, 41, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>c : Symbol(c, Decl(a.js, 2, 5)) +>d : Symbol(d, Decl(a.js, 41, 33)) +>d : Symbol(d, Decl(a.js, 41, 33)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +const f19 = a ? a ? a ? async() : d => d : b : b; +>f19 : Symbol(f19, Decl(a.js, 42, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 42, 33)) +>d : Symbol(d, Decl(a.js, 42, 33)) +>b : Symbol(b, Decl(a.js, 1, 5)) +>b : Symbol(b, Decl(a.js, 1, 5)) + +const f20 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +>f20 : Symbol(f20, Decl(a.js, 44, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>d : Symbol(d, Decl(a.js, 44, 15)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>b : Symbol(b, Decl(a.js, 1, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 44, 57)) +>d : Symbol(d, Decl(a.js, 44, 57)) +>a : Symbol(a, Decl(a.js, 0, 5)) + +const f21 = a ? d => d = async () => async() : (d => d = 0); +>f21 : Symbol(f21, Decl(a.js, 45, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>d : Symbol(d, Decl(a.js, 45, 15)) +>d : Symbol(d, Decl(a.js, 45, 15)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 45, 48)) +>d : Symbol(d, Decl(a.js, 45, 48)) + +const f22 = h => a ? async(h = a ? async() : d => d) : d => d; +>f22 : Symbol(f22, Decl(a.js, 46, 5)) +>h : Symbol(h, Decl(a.js, 46, 11)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>h : Symbol(h, Decl(a.js, 46, 11)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 46, 44)) +>d : Symbol(d, Decl(a.js, 46, 44)) +>d : Symbol(d, Decl(a.js, 46, 54)) +>d : Symbol(d, Decl(a.js, 46, 54)) + +const f23 = a ? async() : (d => d); +>f23 : Symbol(f23, Decl(a.js, 47, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 47, 27)) +>d : Symbol(d, Decl(a.js, 47, 27)) + +const f24 = a ? async() : d => (a ? async() : d => d); +>f24 : Symbol(f24, Decl(a.js, 48, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 48, 25)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>async : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 48, 45)) +>d : Symbol(d, Decl(a.js, 48, 45)) + +const f25 = a ? a ? as\u0079nc() : d => d : b; +>f25 : Symbol(f25, Decl(a.js, 49, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>a : Symbol(a, Decl(a.js, 0, 5)) +>as\u0079nc : Symbol(async, Decl(a.js, 2, 14)) +>d : Symbol(d, Decl(a.js, 49, 34)) +>d : Symbol(d, Decl(a.js, 49, 34)) +>b : Symbol(b, Decl(a.js, 1, 5)) + diff --git a/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.types b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.types new file mode 100644 index 0000000000000..a4e726e10469b --- /dev/null +++ b/tsc/testdata/baselines/reference/compiler/parenthesizedAsyncArrowFunctionJs.types @@ -0,0 +1,372 @@ +//// [tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts] //// + +=== a.js === +const a = true; +>a : true +>true : true + +const b = 1; +>b : 1 +>1 : 1 + +const c = [b]; +>c : number[] +>[b] : number[] +>b : 1 + +function async(...c) { +>async : (...c: any[]) => number +>c : any[] + + return b; +>b : 1 +} + +const f1 = a ? async(...c) : 0; +>f1 : number +>a ? async(...c) : 0 : number +>a : true +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>0 : 0 + +const f2 = a ? async(...c) : x => x; +>f2 : number | ((x: any) => any) +>a ? async(...c) : x => x : number | ((x: any) => any) +>a : true +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>x => x : (x: any) => any +>x : any +>x : any + +const f3 = a ? async () => async() : x => x; +>f3 : (x: any) => any +>a ? async () => async() : x => x : (x: any) => any +>a : true +>async () => async() : () => Promise +>async() : number +>async : (...c: any[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f4 = a ? async (...c) => async() : x => x; +>f4 : ((...c: any[]) => Promise) | ((x: any) => any) +>a ? async (...c) => async() : x => x : ((...c: any[]) => Promise) | ((x: any) => any) +>a : true +>async (...c) => async() : (...c: any[]) => Promise +>c : any[] +>async() : number +>async : (...c: any[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f5 = a ? () => async() : x => x; +>f5 : (x: any) => any +>a ? () => async() : x => x : (x: any) => any +>a : true +>() => async() : () => number +>async() : number +>async : (...c: any[]) => number +>x => x : (x: any) => any +>x : any +>x : any + +const f6 = a ? async() : 0 +>f6 : number +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: any[]) => number +>0 : 0 + +{} +const f7 = a ? async() : {} +>f7 : {} +>a ? async() : {} : number | {} +>a : true +>async() : number +>async : (...c: any[]) => number +>{} : {} + +{} + +function* g() { +>g : () => Generator + + const f1 = a ? yield async(...c) : 0; +>f1 : any +>a ? yield async(...c) : 0 : any +>a : true +>yield async(...c) : any +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>0 : 0 + + const f2 = a ? yield async(...c) : x => x; +>f2 : any +>a ? yield async(...c) : x => x : any +>a : true +>yield async(...c) : any +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>x => x : (x: any) => any +>x : any +>x : any +} + +const d = { a: c }; +>d : { a: number[]; } +>{ a: c } : { a: number[]; } +>a : number[] +>c : number[] + +const e = () => c; +>e : () => number[] +>() => c : () => number[] +>c : number[] + +const f8 = async(...d.a); +>f8 : number +>async(...d.a) : number +>async : (...c: any[]) => number +>...d.a : number +>d.a : number[] +>d : { a: number[]; } +>a : number[] + +const f9 = async(...e()); +>f9 : number +>async(...e()) : number +>async : (...c: any[]) => number +>...e() : number +>e() : number[] +>e : () => number[] + +const f10 = async(...[b]); +>f10 : number +>async(...[b]) : number +>async : (...c: any[]) => number +>...[b] : number +>[b] : [number] +>b : 1 + +const f11 = a ? async() : function() {}; +>f11 : number | (() => void) +>a ? async() : function() {} : number | (() => void) +>a : true +>async() : number +>async : (...c: any[]) => number +>function() {} : () => void + +const f12 = a ? async() : "b" +>f12 : number | "b" +>a ? async() : "b" : number | "b" +>a : true +>async() : number +>async : (...c: any[]) => number +>"b" : "b" + +{} +const f13 = a ? async(...c) : 0 +>f13 : number +>a ? async(...c) : 0 : number +>a : true +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>0 : 0 + +{} +const f14 = a ? (c) : 0 +>f14 : 0 | number[] +>a ? (c) : 0 : 0 | number[] +>a : true +>(c) : number[] +>c : number[] +>0 : 0 + +{} +const f15 = a ? async() : 0; +>f15 : number +>a ? async() : 0 : number +>a : true +>async() : number +>async : (...c: any[]) => number +>0 : 0 + +{} + +const f16 = a ? a ? async() : d => d : b; +>f16 : number | ((d: any) => any) +>a ? a ? async() : d => d : b : number | ((d: any) => any) +>a : true +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: any[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f17 = a ? a ? async(b) : d => d : b; +>f17 : number | ((d: any) => any) +>a ? a ? async(b) : d => d : b : number | ((d: any) => any) +>a : true +>a ? async(b) : d => d : number | ((d: any) => any) +>a : true +>async(b) : number +>async : (...c: any[]) => number +>b : 1 +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f18 = a ? a ? async(...c) : d => d : b; +>f18 : number | ((d: any) => any) +>a ? a ? async(...c) : d => d : b : number | ((d: any) => any) +>a : true +>a ? async(...c) : d => d : number | ((d: any) => any) +>a : true +>async(...c) : number +>async : (...c: any[]) => number +>...c : number +>c : number[] +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + +const f19 = a ? a ? a ? async() : d => d : b : b; +>f19 : number | ((d: any) => any) +>a ? a ? a ? async() : d => d : b : b : number | ((d: any) => any) +>a : true +>a ? a ? async() : d => d : b : number | ((d: any) => any) +>a : true +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: any[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 +>b : 1 + +const f20 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +>f20 : ((d: any) => number) | ((d: any) => boolean) +>a ? d => a ? (0) : a ? async(b) : async() : (d => d = a) : ((d: any) => number) | ((d: any) => boolean) +>a : true +>d => a ? (0) : a ? async(b) : async() : (d: any) => number +>d : any +>a ? (0) : a ? async(b) : async() : number +>a : true +>(0) : 0 +>0 : 0 +>a ? async(b) : async() : number +>a : true +>async(b) : number +>async : (...c: any[]) => number +>b : 1 +>async() : number +>async : (...c: any[]) => number +>(d => d = a) : (d: any) => boolean +>d => d = a : (d: any) => boolean +>d : any +>d = a : true +>d : any +>a : true + +const f21 = a ? d => d = async () => async() : (d => d = 0); +>f21 : ((d: any) => () => Promise) | ((d: any) => number) +>a ? d => d = async () => async() : (d => d = 0) : ((d: any) => () => Promise) | ((d: any) => number) +>a : true +>d => d = async () => async() : (d: any) => () => Promise +>d : any +>d = async () => async() : () => Promise +>d : any +>async () => async() : () => Promise +>async() : number +>async : (...c: any[]) => number +>(d => d = 0) : (d: any) => number +>d => d = 0 : (d: any) => number +>d : any +>d = 0 : 0 +>d : any +>0 : 0 + +const f22 = h => a ? async(h = a ? async() : d => d) : d => d; +>f22 : (h: any) => number | ((d: any) => any) +>h => a ? async(h = a ? async() : d => d) : d => d : (h: any) => number | ((d: any) => any) +>h : any +>a ? async(h = a ? async() : d => d) : d => d : number | ((d: any) => any) +>a : true +>async(h = a ? async() : d => d) : number +>async : (...c: any[]) => number +>h = a ? async() : d => d : number | ((d: any) => any) +>h : any +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: any[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>d => d : (d: any) => any +>d : any +>d : any + +const f23 = a ? async() : (d => d); +>f23 : number | ((d: any) => any) +>a ? async() : (d => d) : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: any[]) => number +>(d => d) : (d: any) => any +>d => d : (d: any) => any +>d : any +>d : any + +const f24 = a ? async() : d => (a ? async() : d => d); +>f24 : number | ((d: any) => number | ((d: any) => any)) +>a ? async() : d => (a ? async() : d => d) : number | ((d: any) => number | ((d: any) => any)) +>a : true +>async() : number +>async : (...c: any[]) => number +>d => (a ? async() : d => d) : (d: any) => number | ((d: any) => any) +>d : any +>(a ? async() : d => d) : number | ((d: any) => any) +>a ? async() : d => d : number | ((d: any) => any) +>a : true +>async() : number +>async : (...c: any[]) => number +>d => d : (d: any) => any +>d : any +>d : any + +const f25 = a ? a ? as\u0079nc() : d => d : b; +>f25 : number | ((d: any) => any) +>a ? a ? as\u0079nc() : d => d : b : number | ((d: any) => any) +>a : true +>a ? as\u0079nc() : d => d : number | ((d: any) => any) +>a : true +>as\u0079nc() : number +>as\u0079nc : (...c: any[]) => number +>d => d : (d: any) => any +>d : any +>d : any +>b : 1 + diff --git a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.errors.txt b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.errors.txt index 08dc36a626764..e322798fd3804 100644 --- a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.errors.txt +++ b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.errors.txt @@ -45,4 +45,18 @@ file.js(22,12): error TS7006: Parameter 'p' implicitly has an 'any' type. // Error (good) f(async () => { return 0 - }) \ No newline at end of file + }) + + const g = true; + + function async() { + return 1; + } + + const f1 = g ? async() : 0; + /** @type {number | ((x: number) => number)} */ + const f2 = g ? async() : x => x; + const f3 = g ? g ? async() : 0 : 1; + /** @type {(x: number) => number} */ + const f4 = g ? x => async() : x => x; + \ No newline at end of file diff --git a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.symbols b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.symbols index 40bae3eb3736c..4fc7c6c17c44c 100644 --- a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.symbols +++ b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.symbols @@ -38,3 +38,41 @@ f(async () => { return 0 }) + +const g = true; +>g : Symbol(g, Decl(file.js, 28, 5)) + +function async() { +>async : Symbol(async, Decl(file.js, 28, 15)) + + return 1; +} + +const f1 = g ? async() : 0; +>f1 : Symbol(f1, Decl(file.js, 34, 5)) +>g : Symbol(g, Decl(file.js, 28, 5)) +>async : Symbol(async, Decl(file.js, 28, 15)) + +/** @type {number | ((x: number) => number)} */ +const f2 = g ? async() : x => x; +>f2 : Symbol(f2, Decl(file.js, 36, 5)) +>g : Symbol(g, Decl(file.js, 28, 5)) +>async : Symbol(async, Decl(file.js, 28, 15)) +>x : Symbol(x, Decl(file.js, 36, 24)) +>x : Symbol(x, Decl(file.js, 36, 24)) + +const f3 = g ? g ? async() : 0 : 1; +>f3 : Symbol(f3, Decl(file.js, 37, 5)) +>g : Symbol(g, Decl(file.js, 28, 5)) +>g : Symbol(g, Decl(file.js, 28, 5)) +>async : Symbol(async, Decl(file.js, 28, 15)) + +/** @type {(x: number) => number} */ +const f4 = g ? x => async() : x => x; +>f4 : Symbol(f4, Decl(file.js, 39, 5)) +>g : Symbol(g, Decl(file.js, 28, 5)) +>x : Symbol(x, Decl(file.js, 39, 14)) +>async : Symbol(async, Decl(file.js, 28, 15)) +>x : Symbol(x, Decl(file.js, 39, 29)) +>x : Symbol(x, Decl(file.js, 39, 29)) + diff --git a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.types b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.types index d8d3316603e0e..376d8932fec68 100644 --- a/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.types +++ b/tsc/testdata/baselines/reference/conformance/asyncArrowFunction_allowJs.types @@ -51,3 +51,58 @@ f(async () => { >0 : 0 }) + +const g = true; +>g : true +>true : true + +function async() { +>async : () => number + + return 1; +>1 : 1 +} + +const f1 = g ? async() : 0; +>f1 : number +>g ? async() : 0 : number +>g : true +>async() : number +>async : () => number +>0 : 0 + +/** @type {number | ((x: number) => number)} */ +const f2 = g ? async() : x => x; +>f2 : number | ((x: number) => number) +>g ? async() : x => x : number | ((x: number) => number) +>g : true +>async() : number +>async : () => number +>x => x : (x: number) => number +>x : number +>x : number + +const f3 = g ? g ? async() : 0 : 1; +>f3 : number +>g ? g ? async() : 0 : 1 : number +>g : true +>g ? async() : 0 : number +>g : true +>async() : number +>async : () => number +>0 : 0 +>1 : 1 + +/** @type {(x: number) => number} */ +const f4 = g ? x => async() : x => x; +>f4 : (x: number) => number +>g ? x => async() : x => x : (x: number) => number +>g : true +>x => async() : (x: number) => number +>x : number +>async() : number +>async : () => number +>x => x : (x: number) => number +>x : number +>x : number + diff --git a/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts b/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts index 057eb64c82138..be2031fe98db4 100644 --- a/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts +++ b/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunction.ts @@ -1,5 +1,138 @@ // @target: es2015 // @strict: false +// @filename: a.ts // Repro from #20096 let foo = (async bar => bar); + +const a = true; +const b = 1; +const c = [b]; + +function async(...c: number[]): number { + return b; +} + +const f1 = a ? async() : 0; +const f2 = a ? async() : x => x; +const f3 = a ? a ? async() : 0 : b; +const f4 = a ? x => async() : x => x; +const f5 = a ? async (): Promise => b : () => b; +const f6 = a ? async (): Promise => { return b; } : () => b; +const f7 = a ? async (): Promise => a ? async() : 0 : () => b; +const f8 = a ? (): number => b : () => b; + +const f9 = a ? async(...c) : 0; +const f10 = a ? async(...c) : x => x; +const f11 = a ? async (...c: number[]): Promise => c.length : () => 0; +const f12 = a ? async() : x => async (...c): Promise => c.length; + +type T = Promise; +const f13 = a ? async() : x => async (): Promise => b; +const f14 = a ? async() : T => async (): T => 0; +const f15 = a ? (b) : x => async (): T => 0; +const f16 = a ? async(...c) : T => async (): T => 0; +const f17 = a ? async() : T => (b): number => b; +const f18 = a ? async() : T => async (): T => 0; +const f19 = a ? async(...c) : T => (b): number => b; +const f20 = a ? async(...c) : T => async (): T => 0; +const f21 = a ? (x): number => (b): T => 0; +const f22 = a ? async (): Promise => (b): T => 0; +const f23 = a ? async () => async() : x => x; +const f24 = a ? async (...c) => async() : x => x; +const f25 = a ? () => async() : x => x; +const f26 = a ? async (c: number): Promise => async() : x => x; +const f27 = a ? async (): Promise => async() : x => x; +const f28 = a ? async (): Promise => async(...c) : x => x; +const f29 = a ? async (...c): Promise => async() : x => x; +const f30 = a ? async (): Promise => async() : x => x; +const f31 = a ? async (): (Promise) => async() : x => x; +const f32 = a ? async (...c: number[]): T => async() : x => x; + +const f33 = a ? async() : 0 +{} +const f34 = a ? async() : {} +{} + +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} + +const d = { a: c }; +const e = () => c; +const f35 = async(...d.a); +const f36 = async(...e()); +const f37 = async(...[b]); + +type U = number; +const f38 = a ? (c): U => (b) : x => x; +const f39 = a ? async() : function() {}; +const f40 = a ? async() : "b" +{} +const f41 = a ? async(...c) : 0 +{} +const f42 = a ? (c) : 0 +{} + +const f43 = a ? async() : T => async (...c): T => c.length; + +const f44 = a ? async (): T => (b) : d => d; +const f45 = a ? async (): T => async() : d => d; +const f46 = a ? async (): T => async() : b; +const f47 = a ? a ? async() : d => d : b; +const f48 = a ? a ? async(b) : d => d : b; +const f49 = a ? a ? async(...c) : d => d : b; +const f50 = a ? a ? async() : T => b : async (): T => b; +const f51 = a ? async (): T => async() : (d): number => d; +const f52 = a ? a ? async (): T => async() : d => d : b; +const f53 = a ? async (): T => a ? async() : b : d => d; +const f54 = a ? a ? async() : d => d : a ? async() : d => d; +const f55 = a ? a ? a ? async() : d => d : b : b; + +const f56 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f57 = a ? d => d = async () => async() : (d => d = 0); + +// @filename: b.ts +const f58 = a ? async(...c: number[]): Promise => 0; +const f59 = a ? async (): Promise {} : d => d; +const f60 = a ? (c): number {} : d => d; + +const f61 = a ? async() : T => async(a ? b); + +// @filename: c.ts +export {}; +declare const a: any, b: any, c: any[]; +declare function async(...a: any[]): any; +type T = Promise; +let d: any; +const f62 = a ? d = (d): T => a ? 0 : async(...c) : T => b; +const f63 = a ? async (): T => async (): T => (d): T => b : a ? d => (d): T => async(...c) : T => b; +const f64 = a ? async (): T => (d): T => async() : b; +const f65 = (a ? async (): T => (d): T => async() : b); +const f66 = a ? d = (d): T => a ? 0 : async(...c) : T => a ? d = (d): T => a ? 0 : async(...c) : T => b; +const f67 = a ? async (c = a ? async() : d => d): T => async() : b; +const f68 = a ? a ? (d): T => a ? async() : b : d => d : b; +const f69 = a ? async() : (d => d); +const f70 = a ? async() : d => (a ? async() : d => d); + +type x = T; +declare const x: any; +const f71 = a ? a ? async (): T => (x): T => async() : x => x; +const f72 = a ? a ? async (): Promise => (x): T => async() : x => x; +const f73 = a ? async (x): T => async (): T => b; +const f74 = a ? async (x): T => async() : x => x; + +declare function h(a: A): A; +declare namespace number { type T = number; } +const f75 = a ? async(x = b < (d + 1)): T => x : 0; +const f76 = a ? async(x = b << (d + 1)): T => x : 0; +const f77 = a ? async(x = new b < (d + 1)): T => x : 0; +const f78 = a ? async(x = h(b)): T => x : 0; +const f79 = a ? async(): Promise<({ a: number[] })> => ({ a: [] }) : 0; +const f80 = a ? async(): Promise<([a: number])> => [b] : 0; +const f81 = a ? async(): Promise<{ r\u0065adonly: number }> => ({ readonly: 0 }) : 0; +const f82 = a ? async(): Promise<{ g\u0065t: number }> => ({ get: 0 }) : 0; +const f83 = a ? async(): Promise => b : 0; +const f84 = a ? a ? as\u0079nc() : d => d : b; +const f85 = a ? async(): Promise => 0 : 0; diff --git a/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts b/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts new file mode 100644 index 0000000000000..c4078243cd7ae --- /dev/null +++ b/tsc/testdata/tests/cases/compiler/parenthesizedAsyncArrowFunctionJs.ts @@ -0,0 +1,56 @@ +// @target: es2015 +// @strict: false +// @checkJs: true +// @outDir: out +// @filename: a.js + +const a = true; +const b = 1; +const c = [b]; + +function async(...c) { + return b; +} + +const f1 = a ? async(...c) : 0; +const f2 = a ? async(...c) : x => x; +const f3 = a ? async () => async() : x => x; +const f4 = a ? async (...c) => async() : x => x; +const f5 = a ? () => async() : x => x; + +const f6 = a ? async() : 0 +{} +const f7 = a ? async() : {} +{} + +function* g() { + const f1 = a ? yield async(...c) : 0; + const f2 = a ? yield async(...c) : x => x; +} + +const d = { a: c }; +const e = () => c; +const f8 = async(...d.a); +const f9 = async(...e()); +const f10 = async(...[b]); +const f11 = a ? async() : function() {}; +const f12 = a ? async() : "b" +{} +const f13 = a ? async(...c) : 0 +{} +const f14 = a ? (c) : 0 +{} +const f15 = a ? async() : 0; +{} + +const f16 = a ? a ? async() : d => d : b; +const f17 = a ? a ? async(b) : d => d : b; +const f18 = a ? a ? async(...c) : d => d : b; +const f19 = a ? a ? a ? async() : d => d : b : b; + +const f20 = a ? d => a ? (0) : a ? async(b) : async() : (d => d = a); +const f21 = a ? d => d = async () => async() : (d => d = 0); +const f22 = h => a ? async(h = a ? async() : d => d) : d => d; +const f23 = a ? async() : (d => d); +const f24 = a ? async() : d => (a ? async() : d => d); +const f25 = a ? a ? as\u0079nc() : d => d : b; diff --git a/tsc/testdata/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts b/tsc/testdata/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts index 9f1f76100434d..39759f6cb41d8 100644 --- a/tsc/testdata/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts +++ b/tsc/testdata/tests/cases/conformance/async/es2017/asyncArrowFunction/asyncArrowFunction_allowJs.ts @@ -30,4 +30,17 @@ const f = (p) => {} // Error (good) f(async () => { return 0 -}) \ No newline at end of file +}) + +const g = true; + +function async() { + return 1; +} + +const f1 = g ? async() : 0; +/** @type {number | ((x: number) => number)} */ +const f2 = g ? async() : x => x; +const f3 = g ? g ? async() : 0 : 1; +/** @type {(x: number) => number} */ +const f4 = g ? x => async() : x => x;