diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index f80d5bacdf7e..2319beb62ca1 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -671,7 +671,8 @@ fn translation_rules() -> Vec> { calledExpression: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @element)) @@array arguments: _* @args - trailingClosure: @tc) + trailingClosure: @tc + additionalTrailingClosures: _* @additional) => call_expr { let callee = tree_at!( @@ -683,7 +684,8 @@ fn translation_rules() -> Vec> { tree!((call_expr callee: {callee} argument: {args} - argument: (argument value: {tc}))) + argument: (argument value: {tc}) + argument: {additional})) } ), rule!( @@ -704,15 +706,15 @@ fn translation_rules() -> Vec> { ), // A function/method call (`foo(1, 2)`). `calledExpression` is the callee // and `arguments` is an (elided) list of `labeledExpr`, each translated - // to an `argument` below. A trailing closure (`xs.map { … }`) becomes a - // final unlabelled argument; that variant is matched first. - rule!( - (functionCallExpr calledExpression: @callee arguments: _* @args trailingClosure: @tc) - => - (call_expr callee: {callee} argument: {args} argument: (argument value: {tc})) - ), + // to an `argument` below. A trailing closure (`xs.map { … }`) becomes + // a final unlabelled argument, followed by any additional labeled + // trailing closures. rule!( - (functionCallExpr calledExpression: @@rawCallee arguments: _* @args) + (functionCallExpr + calledExpression: @@rawCallee + arguments: _* @args + trailingClosure: _? @trailing + additionalTrailingClosures: _* @additional) => expr { // Always translate the callee in non-pattern context. @@ -720,7 +722,12 @@ fn translation_rules() -> Vec> { ctx.in_pattern = false; ctx.translate(rawCallee) })?; - tree!((call_expr callee: {callee} argument: {args})) + tree!((call_expr + callee: {callee} + argument: {args} + argument: {trailing.map(|trailing| tree!((argument value: {trailing})))} + argument: {additional} + )) } ), // A call or enum-case pattern argument. @@ -1019,9 +1026,17 @@ fn translation_rules() -> Vec> { // subscripts their own shape needs only a `subscript_expr` node in // ast_types.yml and a remap here. rule!( - (subscriptCallExpr calledExpression: @callee arguments: _* @args) + (subscriptCallExpr + calledExpression: @callee + arguments: _* @args + trailingClosure: _? @trailing + additionalTrailingClosures: _* @additional) => - (call_expr callee: {callee} argument: {args}) + (call_expr + callee: {callee} + argument: {args} + argument: {trailing.map(|trailing| tree!((argument value: {trailing})))} + argument: {additional}) ), // ---- Optionals and errors ---- // Optional chaining — unwrap the marker diff --git a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output index 95d0a5585dcc..ea814c00d53b 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output +++ b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output @@ -3,6 +3,8 @@ case let .received(.some(value), timestamp): print(value, timestamp) case Type.some(let value): print(value) +case values?.map { $0 * 2 }: + break default: break } @@ -138,6 +140,53 @@ sourceFile calledExpression: declReferenceExpr baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + functionCallExpr + arguments: + additionalTrailingClosures: + calledExpression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "map" + base: + optionalChainingExpr + expression: + declReferenceExpr + baseName: identifier "values" + questionMark: ? + trailingClosure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + infixOperatorExpr + operator: + binaryOperatorExpr + operator: binaryOperator "*" + leftOperand: + declReferenceExpr + baseName: dollarIdentifier "$0" + rightOperand: + integerLiteralExpr + literal: integerLiteral "2" + statements: + codeBlockItem + item: + breakStmt + breakKeyword: break switchCase label: switchDefaultLabel @@ -159,7 +208,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" + switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" value: identifier "event" source="event" case: switch_case source="case ⟨pattern⟩:\n ⟨body⟩" @@ -216,6 +265,27 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: identifier "value" source="value" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" + pattern: + call_expr source="⟨callee⟩ ⟨argument⟩" + callee: + member_access_expr source="⟨base⟩?.⟨member_name_node⟩" + base: identifier "values" source="values" + member_name_node: identifier "map" source="map" + argument: + argument source="⟨value⟩" + value: + function_expr source="{ ⟨body⟩ }" + body: + block source="⟨stmt⟩" + stmt: + binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" + left: identifier "$0" source="$0" + operator: infix_operator "*" source="*" + right: int_literal "2" source="2" + body: + block source="⟨stmt⟩" + stmt: break_expr "break" source="break" switch_case source="default:\n ⟨body⟩" body: block source="⟨stmt⟩" diff --git a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.swift b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.swift index ed1a6b738a4b..be136fec4a6c 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.swift +++ b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.swift @@ -3,6 +3,8 @@ case let .received(.some(value), timestamp): print(value, timestamp) case Type.some(let value): print(value) +case values?.map { $0 * 2 }: + break default: break } diff --git a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output index c0970babe165..28c66609b41b 100644 --- a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output +++ b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output @@ -1,6 +1,8 @@ let values = [Result]() let initialized = [Result](unsafeUninitializedCapacity: 1) { _, count in count = 0 +} completion: { + done() } --- @@ -71,6 +73,24 @@ sourceFile integerLiteralExpr literal: integerLiteral "1" additionalTrailingClosures: + multipleTrailingClosureElement + colon: : + label: identifier "completion" + closure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "done" calledExpression: arrayExpr elements: @@ -144,7 +164,7 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "initialized" source="initialized" value: - call_expr source="⟨callee⟩(⟨argument⟩) ⟨argument⟩" + call_expr source="⟨callee⟩(⟨argument⟩) ⟨argument⟩ ⟨argument⟩" callee: generic_type_expr source="[⟨type_argument⟩]" base: identifier "Array" source="" @@ -171,3 +191,12 @@ top_level source="⟨body⟩" left: identifier "count" source="count" operator: infix_operator "=" source="=" right: int_literal "0" source="0" + argument source="⟨name_node⟩: ⟨value⟩" + name_node: identifier "completion" source="completion" + value: + function_expr source="{\n\t⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "done" source="done" diff --git a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.swift b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.swift index bd25a9cbb4ce..a4dce57c797e 100644 --- a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.swift +++ b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.swift @@ -1,4 +1,6 @@ let values = [Result]() let initialized = [Result](unsafeUninitializedCapacity: 1) { _, count in count = 0 +} completion: { + done() } diff --git a/unified/extractor/tests/corpus/swift/expressions/subscript-call.output b/unified/extractor/tests/corpus/swift/expressions/subscript-call.output new file mode 100644 index 000000000000..138caa29eb62 --- /dev/null +++ b/unified/extractor/tests/corpus/swift/expressions/subscript-call.output @@ -0,0 +1,137 @@ +handlers[0] + +handlers[0] { + first() +} completion: { + second() +} failure: { + third() +} + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + subscriptCallExpr + leftSquare: [ + rightSquare: ] + arguments: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "0" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "handlers" + codeBlockItem + item: + subscriptCallExpr + leftSquare: [ + rightSquare: ] + arguments: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "0" + additionalTrailingClosures: + multipleTrailingClosureElement + colon: : + label: identifier "completion" + closure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "second" + multipleTrailingClosureElement + colon: : + label: identifier "failure" + closure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "third" + calledExpression: + declReferenceExpr + baseName: identifier "handlers" + trailingClosure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "first" + +--- + +top_level source="⟨body⟩" + body: + block source="⟨stmt⟩\n\n⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩[⟨argument⟩]" + callee: identifier "handlers" source="handlers" + argument: + argument source="⟨value⟩" + value: int_literal "0" source="0" + call_expr source="⟨callee⟩[⟨argument⟩] ⟨argument⟩ ⟨argument⟩ ⟨argument⟩" + callee: identifier "handlers" source="handlers" + argument: + argument source="⟨value⟩" + value: int_literal "0" source="0" + argument source="⟨value⟩" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "first" source="first" + argument source="⟨name_node⟩: ⟨value⟩" + name_node: identifier "completion" source="completion" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "second" source="second" + argument source="⟨name_node⟩: ⟨value⟩" + name_node: identifier "failure" source="failure" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "third" source="third" diff --git a/unified/extractor/tests/corpus/swift/expressions/subscript-call.swift b/unified/extractor/tests/corpus/swift/expressions/subscript-call.swift new file mode 100644 index 000000000000..a0e4b51700bd --- /dev/null +++ b/unified/extractor/tests/corpus/swift/expressions/subscript-call.swift @@ -0,0 +1,9 @@ +handlers[0] + +handlers[0] { + first() +} completion: { + second() +} failure: { + third() +} diff --git a/unified/extractor/tests/corpus/swift/functions/function-call.output b/unified/extractor/tests/corpus/swift/functions/function-call.output index 19f1d7cf988f..79fc9e7f52e5 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-call.output +++ b/unified/extractor/tests/corpus/swift/functions/function-call.output @@ -1,5 +1,13 @@ foo(1, 2) +handle { + first() +} completion: { + second() +} failure: { + third() +} + --- sourceFile @@ -24,12 +32,71 @@ sourceFile calledExpression: declReferenceExpr baseName: identifier "foo" + codeBlockItem + item: + functionCallExpr + arguments: + additionalTrailingClosures: + multipleTrailingClosureElement + colon: : + label: identifier "completion" + closure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "second" + multipleTrailingClosureElement + colon: : + label: identifier "failure" + closure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "third" + calledExpression: + declReferenceExpr + baseName: identifier "handle" + trailingClosure: + closureExpr + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "first" --- top_level source="⟨body⟩" body: - block source="⟨stmt⟩" + block source="⟨stmt⟩\n\n⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: identifier "foo" source="foo" @@ -38,3 +105,32 @@ top_level source="⟨body⟩" value: int_literal "1" source="1" argument source="⟨value⟩" value: int_literal "2" source="2" + call_expr source="⟨callee⟩ ⟨argument⟩ ⟨argument⟩ ⟨argument⟩" + callee: identifier "handle" source="handle" + argument: + argument source="⟨value⟩" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "first" source="first" + argument source="⟨name_node⟩: ⟨value⟩" + name_node: identifier "completion" source="completion" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "second" source="second" + argument source="⟨name_node⟩: ⟨value⟩" + name_node: identifier "failure" source="failure" + value: + function_expr source="{\n ⟨body⟩\n}" + body: + block source="⟨stmt⟩" + stmt: + call_expr source="⟨callee⟩()" + callee: identifier "third" source="third" diff --git a/unified/extractor/tests/corpus/swift/functions/function-call.swift b/unified/extractor/tests/corpus/swift/functions/function-call.swift index 22594bf8c7da..d3fc9dd70c9c 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-call.swift +++ b/unified/extractor/tests/corpus/swift/functions/function-call.swift @@ -1 +1,9 @@ foo(1, 2) + +handle { + first() +} completion: { + second() +} failure: { + third() +}