diff --git a/unified/extractor/ast_types.yml b/unified/extractor/ast_types.yml index 854829a17cb4..e2f3dd933a85 100644 --- a/unified/extractor/ast_types.yml +++ b/unified/extractor/ast_types.yml @@ -6,6 +6,7 @@ supertypes: - boolean_literal - string_literal - regex_literal + - string_interpolation_expr - builtin_expr - binary_expr - unary_expr @@ -39,17 +40,13 @@ supertypes: expr_or_type: - expr - type_expr - # An element of an `unresolved_operator_sequence`: either an operand (`expr`) - # or one of the infix operators separating the operands. - expr_or_operator: - - expr - - infix_operator pattern: - name_pattern - tuple_pattern - constructor_pattern - or_pattern - conditional_pattern + - type_test_pattern - ignore_pattern - expr_equality_pattern - bulk_importing_pattern @@ -130,6 +127,11 @@ named: # A regex literal regex_literal: + # A string interpolation expression. Constant parts are stored as string literals. + string_interpolation_expr: + modifier*: modifier + element*: expr + # Application of a binary operator, such as `a + b` binary_expr: left: expr @@ -151,11 +153,13 @@ named: # determine (e.g. one imported from another module), it leaves that chain # unresolved and emits it here rather than guessing a (possibly wrong) # structure. The `element`s alternate operands (`expr`) and infix operators. + # Note that these can contain assignment operators, and the LHS of an assignment operator can be a pattern unresolved_operator_sequence: - element*: expr_or_operator + # An inline union is used here to avoid generating a somewhat Swift-specific and not-that-useful union type in the public AST + element*: [expr, pattern, infix_operator] - # Plain assignment assign_expr: + # Plain assignment target: expr_or_pattern value: expr @@ -224,7 +228,7 @@ named: # A tuple expression, such as `(a, b, c)`. tuple_expr: - element*: expr + element*: argument # A parameter. # @@ -462,7 +466,7 @@ named: # In Swift: `if let y = x as? Foo` is a pattern_guard_expr containing a type_test_pattern # In Java: `x instanceof Foo y` is a type_test_pattern wrapping a name_pattern type_test_pattern: - pattern: pattern + pattern?: pattern type: type_expr # A '*' pattern that imports all members of the incoming value into the local scope diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 6396d4addd75..38fb493b558b 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -107,6 +107,40 @@ fn make_or_pattern( } } +/// Translate `node` in pattern context (`ctx.in_pattern = true`). +fn translate_pattern( + ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>, + node: yeast::Id, +) -> Result, String> { + ctx.scoped(|ctx| { + ctx.in_pattern = true; + ctx.translate(node) + }) +} + +/// Translate `node` in non-pattern context (`ctx.in_pattern = false`). +fn translate_non_pattern( + ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>, + node: yeast::Id, +) -> Result, String> { + ctx.scoped(|ctx| { + ctx.in_pattern = false; + ctx.translate(node) + }) +} + +/// Wrap an expression in an `expr_equality_pattern` if `ctx.in_pattern` is true. +fn wrap_pattern_expr( + ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>, + expr: yeast::Id, +) -> yeast::Id { + if ctx.in_pattern { + tree!((expr_equality_pattern expr: {expr})) + } else { + expr + } +} + /// Translate a multi-part identifier (for example `Foo.Bar.Baz`) into a /// `member_access_expr` chain rooted at a `name_expr` over the first /// part. Panics on an empty input because the grammar's `_+` quantifier @@ -133,6 +167,20 @@ const COMPOUND_ASSIGN_OPS: &[&str] = &[ "+=", "-=", "*=", "/=", "%=", "<<=", ">>=", "&=", "|=", "^=", "&+=", "&-=", "&*=", ]; +/// `coerce_to_pattern!(exprKind)` generates a rule to ensure that if the given node kind appears in a pattern context, +/// it is translated as an expression and wrapped in an `expr_equality_pattern`. +/// Must appear before the other rules in order to apply first. +macro_rules! coerce_to_pattern { + ($kind:ident) => { + rule!(($kind) @@expr where ctx.in_pattern => + pattern { + ctx.in_pattern = false; + tree!((expr_equality_pattern expr: {ctx.translate(expr)?})) + } + ) + }; +} + fn translation_rules() -> Vec> { vec![ // ---- Top-level ---- @@ -158,30 +206,41 @@ fn translation_rules() -> Vec> { // swift-syntax does not distinguish the lexical integer/string forms // (hex/binary/octal, single- vs multi-line, raw): each is a single // `*LiteralExpr` kind, so one rule per literal type suffices. - rule!((integerLiteralExpr) @@node => expr { - let value = tree!((int_literal #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), - rule!((floatLiteralExpr) @@node => expr { - let value = tree!((float_literal #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), - rule!((booleanLiteralExpr) @@node => expr { - let value = tree!((boolean_literal #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), - rule!((nilLiteralExpr) @@node => expr { - let value = tree!((builtin_expr #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), - rule!((stringLiteralExpr) @@node => expr { - let value = tree!((string_literal #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), - rule!((regexLiteralExpr) @@node => expr { - let value = tree!((regex_literal #{node})); - if ctx.in_pattern { tree!((expr_equality_pattern expr: {value})) } else { value } - }), + coerce_to_pattern!(integerLiteralExpr), + rule!((integerLiteralExpr) @@node => (int_literal #{node})), + coerce_to_pattern!(floatLiteralExpr), + rule!((floatLiteralExpr) @@node => (float_literal #{node})), + coerce_to_pattern!(booleanLiteralExpr), + rule!((booleanLiteralExpr) @@node => (boolean_literal #{node})), + coerce_to_pattern!(nilLiteralExpr), + rule!((nilLiteralExpr) @@node => (builtin_expr #{node})), + // Plain string literals (no interpolation) + coerce_to_pattern!(simpleStringLiteralExpr), + rule!((simpleStringLiteralExpr) @@node => (string_literal #{node})), + // String literals, possibly with interpolation. Flatten to string_literal if no interpolation. + coerce_to_pattern!(stringLiteralExpr), + rule!( + (stringLiteralExpr segments: (stringSegment) segments: _* @@rest) @@node + where rest.is_empty() + => + (string_literal #{node}) // Note: capture entire 'stringLiteralExpr' to preserve quotation marks + ), + rule!( + (stringLiteralExpr segments: _* @segs) + => + (string_interpolation_expr element: {segs}) + ), + // Map stringSegment to a string_literal for use in string_interpolation_expr + rule!((stringSegment content: @@content) => (string_literal #{content})), + // In the general case, an expressionSegment results in a call to `appendInterpolation()` which + // can take an arbitrary list of arguments. We model it as a call to a built-in called `interpolation`. + rule!( + (expressionSegment expressions: _* @exprs) + => + (call_expr callee: (builtin_expr "interpolation") argument: {exprs}) + ), + coerce_to_pattern!(regexLiteralExpr), + rule!((regexLiteralExpr) @@node => (regex_literal #{node})), // ---- Names ---- // A function reference spelled with argument labels (`f(x:y:z:)`) is a // `declReferenceExpr` carrying `argumentNames`. Mark it unsupported for @@ -196,21 +255,17 @@ fn translation_rules() -> Vec> { ), rule!((declReferenceExpr baseName: (identifier) @name) => expr { let name = tree!((name_expr identifier: (identifier #{name}))); - if ctx.in_pattern { - tree!((expr_equality_pattern expr: {name})) - } else { - name - } + wrap_pattern_expr(&mut ctx, name) }), // A bare name reference (`x`), and an operator used as a value (`+` in // `reduce(0, +)`), are both `declReferenceExpr`; its `baseName` is the // referenced identifier / operator symbol. rule!((declReferenceExpr baseName: @name) => (name_expr identifier: (identifier #{name}))), - // A discard `_` used as an expression — e.g. the target of a discarding - // assignment `_ = x`. swift-syntax models it as a `discardAssignmentExpr`; - // the target AST has no expression-level discard (only `ignore_pattern`, - // which is a pattern), so it becomes a `name_expr` over the `_` token. - rule!((discardAssignmentExpr wildcard: @@w) => (name_expr identifier: (identifier #{w}))), + // A discard `_` used as the target of an assignment becomes a `builtin_expr` because the LHS of a + // tuple-assignment such as `(foo.x, _) = ...` can't contain a mix of patterns and exprs. So we consistently + // use exprs. + rule!((discardAssignmentExpr wildcard: @@w) where ctx.in_pattern => (ignore_pattern #{w})), + rule!((discardAssignmentExpr wildcard: @@w) => (builtin_expr #{w})), // A generic specialization in expression position (`C`, // `Array`) is represented by swift-syntax as a // `genericSpecializationExpr`. When used as a call target @@ -240,6 +295,7 @@ fn translation_rules() -> Vec> { // can't match on token text, so a small Rust block reads the spelling // and routes to `compound_assign_expr` or `binary_expr`. The operator // is captured raw (`@@op`) to read its spelling. + coerce_to_pattern!(infixOperatorExpr), rule!( (infixOperatorExpr leftOperand: @l operator: (binaryOperatorExpr) @@op rightOperand: @r) => @@ -287,15 +343,32 @@ fn translation_rules() -> Vec> { // infix operators, rather than guessing a structure. rule!((sequenceExpr elements: _* @els) => (unresolved_operator_sequence element: {els})), // Prefix unary operators (`!a`, `-x`). + coerce_to_pattern!(prefixOperatorExpr), rule!((prefixOperatorExpr operator: @op expression: @operand) => (unary_expr operator: (prefix_operator #{op}) operand: {operand})), - // A `tupleExpr` is a tuple literal (`(a, b)`) or a parenthesised - // expression (`(x)`). For now it is kept as an opaque `tuple_expr` leaf - // (its source text); its elements are not descended into. - // - // TODO: a parenthesised single-element `tupleExpr` is really a grouping - // expression and should be elided (unwrapped to its inner expression) - // rather than modelled as a tuple. - rule!((tupleExpr) => (tuple_expr)), + // A tuple with a single unlabeled element is a grouping expression. + rule!( + (tupleExpr + elements: (labeledExpr + label: _? @label + expression: @inner) + elements: _* @rest) + where label.is_none() && rest.is_empty() + => + expr { inner } + ), + // Other tuple expressions in pattern context become tuple patterns. + rule!( + (tupleExpr elements: _* @elements) + where ctx.in_pattern + => + (tuple_pattern element: {elements}) + ), + // Otherwise, preserve the tuple expression. + rule!( + (tupleExpr elements: _* @elements) + => + (tuple_expr element: {elements}) + ), // A code block contains its statements directly. rule!((codeBlock statements: _* @stmts) => (block stmt: {stmts})), // ---- Properties with accessors ---- @@ -422,14 +495,14 @@ fn translation_rules() -> Vec> { // as a binding. rule!( (patternBinding - pattern: @pattern + pattern: @@pattern typeAnnotation: (typeAnnotation type: @ty)? initializer: (initializerClause value: @@val)?) => (variable_declaration modifier: {ctx.outer_modifiers.clone()} modifier: {chained_modifier(&mut ctx)} - pattern: {pattern} + pattern: {translate_pattern(&mut ctx, pattern)?} type: {ty} value: {ctx.reset(); ctx.translate(val)?}) ), @@ -542,20 +615,14 @@ fn translation_rules() -> Vec> { => (pattern_element key: (identifier #{label})? pattern: {p}) ), - // A type-casting pattern (`case is T`). Not yet supported, so it is - // mapped to `unsupported_node` — an explicit reminder that this needs - // handling in the future. (Redundant with the catch-all fallback, but - // kept as a signpost.) - rule!((isTypePattern) => (unsupported_node)), - // A wildcard *binding* pattern (`let _ = x`, `for _ in xs`). swift-syntax - // models this as a `wildcardPattern`, distinct from the `_` match form - // handled by the context-aware `discardAssignmentExpr` rule. + // A type-casting pattern (`case is T`). + rule!((isTypePattern type: @@ty) => (type_test_pattern type: { translate_non_pattern(&mut ctx, ty)? } )), + // A wildcard *binding* pattern (`let _ = x`, `for _ in xs`). rule!((wildcardPattern) => (ignore_pattern)), // An expression pattern only establishes pattern context; its child // determines the concrete pattern shape. rule!((expressionPattern expression: @@e) => expr { - ctx.in_pattern = true; - ctx.translate(e)?.into_iter().next().ok_or("expression pattern has no child")? + translate_pattern(&mut ctx, e)? }), // ---- Functions ---- // A function declaration (parameters/return type/body optional). The @@ -656,72 +723,35 @@ fn translation_rules() -> Vec> { ), rule!( (functionCallExpr calledExpression: @@rawCallee arguments: _* @args) + where ctx.in_pattern => - expr { - // Always translate the callee in non-pattern context. - let callee = ctx.scoped(|ctx| { - ctx.in_pattern = false; - ctx.translate(rawCallee) - })?; - if ctx.in_pattern { - tree!((constructor_pattern constructor: {callee} element: {args})) - } else { - tree!((call_expr callee: {callee} argument: {args})) - } + pattern { + let callee = translate_non_pattern(&mut ctx, rawCallee)?; + tree!((constructor_pattern constructor: {callee} element: {args})) } ), - // A call argument or an enum-case pattern argument. When translating an - // enum-case `constructor_pattern`'s arguments (`ctx.in_pattern`), a - // `patternExpr` argument (`let x`) becomes a bound `name_pattern`, a - // wildcard (`_`) becomes an `ignore_pattern`, and any other expression - // becomes an `expr_equality_pattern`; each is wrapped in a - // `pattern_element` carrying the optional argument label as its `key`. - // Otherwise the argument keeps its label as the `name` and its value. - // The pattern-only shapes (`patternExpr`, `discardAssignmentExpr`) are - // matched first; they never occur as ordinary call arguments. - rule!( - (labeledExpr - label: _? @@lbl - expression: (functionCallExpr - calledExpression: @constructor - arguments: _* @elements)) - => - argument { - if ctx.in_pattern { - tree!((pattern_element - key: (identifier #{lbl})? - pattern: (constructor_pattern - constructor: {constructor} - element: {elements}))) - } else { - tree!((argument - name: (identifier #{lbl})? - value: (call_expr callee: {constructor} argument: {elements}))) - } - } + rule!( + (functionCallExpr calledExpression: @callee arguments: _* @args) + => + (call_expr callee: {callee} argument: {args}) ), rule!( - (labeledExpr label: _? @@lbl expression: (patternExpr pattern: @p)) + (patternExpr pattern: @@p) => - (pattern_element key: (identifier #{lbl})? pattern: {p}) + pattern { translate_pattern(&mut ctx, p)? } ), rule!( - (labeledExpr label: _? @@lbl expression: (discardAssignmentExpr) @@wildcard) + (labeledExpr label: _? @@lbl expression: @val) + where ctx.in_pattern => - (pattern_element key: (identifier #{lbl})? pattern: (ignore_pattern #{wildcard})) + (pattern_element + key: (identifier #{lbl})? + pattern: {val}) ), rule!( (labeledExpr label: _? @@lbl expression: @val) => - argument { - if ctx.in_pattern { - tree!((pattern_element - key: (identifier #{lbl})? - pattern: {val})) - } else { - tree!((argument name: (identifier #{lbl})? value: {val})) - } - } + (argument name: (identifier #{lbl})? value: {val}) ), // Member access (`list.append`). The `declName` is itself a // `declReferenceExpr`; pull its `baseName` out as the member identifier. @@ -732,24 +762,35 @@ fn translation_rules() -> Vec> { // meaning as `Array` rather than an array literal. rule!( (memberAccessExpr - base: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @element)) + base: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @@element)) declName: (declReferenceExpr baseName: @member)) => - (member_access_expr - base: (generic_type_expr - base: (named_type_expr name: (identifier "Array")) - type_argument: {element}) - member: (identifier #{member})) + expr { + let element = translate_non_pattern(&mut ctx, element)?; + let node = tree!((member_access_expr + base: (generic_type_expr + base: (named_type_expr name: (identifier "Array")) + type_argument: {element}) + member: (identifier #{member}))); + wrap_pattern_expr(&mut ctx, node) + } ), rule!( - (memberAccessExpr base: @base declName: (declReferenceExpr baseName: @member)) + (memberAccessExpr base: @@base declName: (declReferenceExpr baseName: @member)) => - (member_access_expr base: {base} member: (identifier #{member})) + expr { + let base = translate_non_pattern(&mut ctx, base)?; + let node = tree!((member_access_expr base: {base} member: (identifier #{member}))); + wrap_pattern_expr(&mut ctx, node) + } ), rule!( (memberAccessExpr period: @dot declName: (declReferenceExpr baseName: @member)) => - (member_access_expr base: (inferred_type_expr #{dot}) member: (identifier #{member})) + expr { + let node = tree!((member_access_expr base: (inferred_type_expr #{dot}) member: (identifier #{member}))); + wrap_pattern_expr(&mut ctx, node) + } ), // Control transfer, one rule per keyword. `return` carries an optional // value; `break` / `continue` an optional target label; `throw` its @@ -833,6 +874,7 @@ fn translation_rules() -> Vec> { else: {else_stmts}) ), // Ternary (`c ? a : b`) desugars to an `if_expr`. + coerce_to_pattern!(ternaryExpr), rule!( (ternaryExpr condition: @cond thenExpression: @then_val elseExpression: @else_val) => @@ -861,15 +903,19 @@ fn translation_rules() -> Vec> { (switch_case body: (block stmt: {body})) ), // A single case item unwraps to its pattern, possibly boxed in conditional_pattern - rule!((switchCaseItem pattern: @p whereClause: (whereClause condition: @cond)) => (conditional_pattern pattern: { p } condition: {cond})), - rule!((switchCaseItem pattern: @p) => pattern { p }), + rule!( + (switchCaseItem pattern: @@p whereClause: (whereClause condition: @cond)) + => + (conditional_pattern pattern: {translate_pattern(&mut ctx, p)?} condition: {cond}) + ), + rule!((switchCaseItem pattern: @@p) => pattern { translate_pattern(&mut ctx, p)? }), // A pattern-matching condition (`if case let x = e`, `if case .foo(let x) // = e`) becomes a `pattern_guard_expr`: the matched pattern and the // scrutinee value are translated recursively. rule!( - (matchingPatternCondition pattern: @pat initializer: (initializerClause value: @val)) + (matchingPatternCondition pattern: @@pat initializer: (initializerClause value: @val)) => - (pattern_guard_expr pattern: {pat} value: {val}) + (pattern_guard_expr pattern: {translate_pattern(&mut ctx, pat)?} value: {val}) ), // Optional binding (`if let x = foo`, or shorthand `if let x`) desugars // to a `pattern_guard_expr` matching `Optional.some(x)`. The initialized @@ -905,13 +951,13 @@ fn translation_rules() -> Vec> { // A `for`-`in` loop. The optional `where` clause becomes the `guard`. rule!( (forStmt - pattern: @pat + pattern: @@pat sequence: @iter whereClause: (whereClause condition: @guard)? body: @body) => (for_each_stmt - pattern: {pat} + pattern: {translate_pattern(&mut ctx, pat)?} iterable: {iter} guard: {guard} body: {body}) @@ -941,6 +987,7 @@ fn translation_rules() -> Vec> { // ---- Collections ---- // An array literal (`[1, 2, 3]`). Each `arrayElement` unwraps to its // contained expression. + coerce_to_pattern!(arrayExpr), rule!( (arrayExpr elements: _* @els) => @@ -949,31 +996,32 @@ fn translation_rules() -> Vec> { rule!((arrayElement expression: @e) => expr { e }), // A dictionary literal (`["a": 1]`) is kept as an opaque `map_literal` // leaf (its source span). + coerce_to_pattern!(dictionaryExpr), rule!((dictionaryExpr) => (map_literal)), // A subscript access (`xs[0]`) is modelled as a call. swift-syntax does // report a distinct `subscriptCallExpr`, so giving // subscripts their own shape needs only a `subscript_expr` node in // ast_types.yml and a remap here. + coerce_to_pattern!(subscriptCallExpr), rule!( (subscriptCallExpr calledExpression: @callee arguments: _* @args) => - (call_expr callee: {callee} argument: {args}) + (unsupported_node) ), // ---- Optionals and errors ---- - // Optional chaining — unwrap the marker - rule!((optionalChainingExpr expression: @@inner) => expr { - let inner = ctx.translate(inner)?.into_iter().next().ok_or("optional chaining expression has no child")?; - if ctx.in_pattern { - tree!((constructor_pattern - constructor: (member_access_expr - base: (named_type_expr name: (identifier "Optional")) - member: (identifier "some")) - element: (pattern_element pattern: {inner}))) - } else { - inner - } - }), + // Postfix `?` in a pattern means `Optional.some`. E.g: `(x,y)?` -> `Optional.some((x,y))` + rule!((optionalChainingExpr expression: @inner) + where ctx.in_pattern => + (constructor_pattern + constructor: (member_access_expr + base: (named_type_expr name: (identifier "Optional")) + member: (identifier "some")) + element: (pattern_element pattern: {inner})) + ), + // TODO: handle suffix "?" in expr and type contexts + rule!((optionalChainingExpr expression: @inner) => expr { inner }), // try/try?/try! expr → unary_expr with operator "try", "try?" or "try!" + coerce_to_pattern!(tryExpr), rule!( (tryExpr questionOrExclamationMark: _? @@m expression: @e) => @@ -991,14 +1039,14 @@ fn translation_rules() -> Vec> { catch_clause: {catches}) ), rule!( - (catchItem pattern: @pattern whereClause: (whereClause condition: @guard)) + (catchItem pattern: @@pattern whereClause: (whereClause condition: @guard)) => - (conditional_pattern pattern: {pattern} condition: {guard}) + (conditional_pattern pattern: {translate_pattern(&mut ctx, pattern)?} condition: {guard}) ), rule!( - (catchItem pattern: @pattern) + (catchItem pattern: @@pattern) => - pattern {pattern} + pattern { translate_pattern(&mut ctx, pattern)? } ), // Catch block with one or more patterns (which have been translated by the catchItem rules) rule!( @@ -1013,16 +1061,29 @@ fn translation_rules() -> Vec> { // Catch block without error binding rule!((catchClause body: @body) => (catch_clause body: {body})), // As expression (type cast) — as?, as! - rule!((asExpr expression: @val questionOrExclamationMark: _? @@mark type: @ty) => type_cast_expr { - let op = format!("as{}", mark.map(|m| ctx.source_text(m)).unwrap_or_default()); - tree!((type_cast_expr expr: {val} operator: (infix_operator #{op}) type: {ty})) - }), + rule!( + (asExpr expression: @val type: @ty) + where ctx.in_pattern + => + (type_test_pattern pattern: {val} type: {ty}) + ), + rule!( + (asExpr expression: @val questionOrExclamationMark: _? @@mark type: @ty) + => + type_cast_expr { + let op = format!("as{}", mark.map(|m| ctx.source_text(m)).unwrap_or_default()); + tree!((type_cast_expr expr: {val} operator: (infix_operator #{op}) type: {ty})) + } + ), // Check expression (`x is T`) → type_test_expr + coerce_to_pattern!(isExpr), rule!((isExpr expression: @val type: @ty) => (type_test_expr expr: {val} operator: (infix_operator "is") type: {ty})), // Await expression → unary_expr with operator "await" + coerce_to_pattern!(awaitExpr), rule!((awaitExpr expression: @val) => (unary_expr operator: (prefix_operator "await") operand: {val})), // Force-unwrap (`x!`) → postfix unary_expr, via swift-syntax's dedicated // `forceUnwrapExpr` node. + coerce_to_pattern!(forceUnwrapExpr), rule!((forceUnwrapExpr expression: @e) => (unary_expr operator: (postfix_operator "!") operand: {e})), // ---- Imports ---- // An import declaration. The dotted path (a list of diff --git a/unified/extractor/tests/corpus/swift/collections/dictionary-subscript.output b/unified/extractor/tests/corpus/swift/collections/dictionary-subscript.output index e2f939e0683c..90cdc25313d0 100644 --- a/unified/extractor/tests/corpus/swift/collections/dictionary-subscript.output +++ b/unified/extractor/tests/corpus/swift/collections/dictionary-subscript.output @@ -50,11 +50,4 @@ top_level pattern: name_pattern identifier: identifier "v" - value: - call_expr - callee: - name_expr - identifier: identifier "d" - argument: - argument - value: string_literal "\"key\"" + value: unsupported_node "d[\"key\"]" diff --git a/unified/extractor/tests/corpus/swift/collections/subscript-access.output b/unified/extractor/tests/corpus/swift/collections/subscript-access.output index ec24f0c1f1df..465148e4f69d 100644 --- a/unified/extractor/tests/corpus/swift/collections/subscript-access.output +++ b/unified/extractor/tests/corpus/swift/collections/subscript-access.output @@ -47,11 +47,4 @@ top_level pattern: name_pattern identifier: identifier "first" - value: - call_expr - callee: - name_expr - identifier: identifier "xs" - argument: - argument - value: int_literal "0" + value: unsupported_node "xs[0]" diff --git a/unified/extractor/tests/corpus/swift/collections/tuple-literal.output b/unified/extractor/tests/corpus/swift/collections/tuple-literal.output index facbc2fcbb45..a8be2d3fb5f8 100644 --- a/unified/extractor/tests/corpus/swift/collections/tuple-literal.output +++ b/unified/extractor/tests/corpus/swift/collections/tuple-literal.output @@ -54,4 +54,12 @@ top_level pattern: name_pattern identifier: identifier "t" - value: tuple_expr "(1, \"two\", 3.0)" + value: + tuple_expr + element: + argument + value: int_literal "1" + argument + value: string_literal "\"two\"" + argument + value: float_literal "3.0" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output new file mode 100644 index 000000000000..62d80afe02bf --- /dev/null +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output @@ -0,0 +1,463 @@ +// Arbitrary expressions may appear in pattern context +switch x { +case y, y + 1, -y, y...z, "foo", 4, foo().bar, .baz, [42], ["a": 1], try y, y!, y is T, await y, "interpolate \(y)", y[4]: + print("expr") +case true ? y : z: + print("ternary is also valid") +default: + break +} + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + expressionStmt + expression: + switchExpr + leftBrace: { + rightBrace: } + cases: + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + declReferenceExpr + baseName: identifier "y" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + infixOperatorExpr + operator: + binaryOperatorExpr + operator: binaryOperator "+" + leftOperand: + declReferenceExpr + baseName: identifier "y" + rightOperand: + integerLiteralExpr + literal: integerLiteral "1" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + prefixOperatorExpr + expression: + declReferenceExpr + baseName: identifier "y" + operator: prefixOperator "-" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + infixOperatorExpr + operator: + binaryOperatorExpr + operator: binaryOperator "..." + leftOperand: + declReferenceExpr + baseName: identifier "y" + rightOperand: + declReferenceExpr + baseName: identifier "z" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + integerLiteralExpr + literal: integerLiteral "4" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "bar" + base: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "foo" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "baz" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + arrayExpr + elements: + arrayElement + expression: + integerLiteralExpr + literal: integerLiteral "42" + leftSquare: [ + rightSquare: ] + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + dictionaryExpr + leftSquare: [ + rightSquare: ] + content: + dictionaryElement + colon: : + value: + integerLiteralExpr + literal: integerLiteral "1" + key: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "a" + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + tryExpr + expression: + declReferenceExpr + baseName: identifier "y" + tryKeyword: try + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + forceUnwrapExpr + expression: + declReferenceExpr + baseName: identifier "y" + exclamationMark: ! + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + isExpr + expression: + declReferenceExpr + baseName: identifier "y" + type: + identifierType + name: identifier "T" + isKeyword: is + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + awaitExpr + expression: + declReferenceExpr + baseName: identifier "y" + awaitKeyword: await + switchCaseItem + trailingComma: , + pattern: + expressionPattern + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "interpolate " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "y" + stringSegment + content: stringSegment + switchCaseItem + pattern: + expressionPattern + expression: + subscriptCallExpr + leftSquare: [ + rightSquare: ] + arguments: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "4" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "y" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "expr" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + ternaryExpr + colon: : + condition: + booleanLiteralExpr + literal: true + questionMark: ? + elseExpression: + declReferenceExpr + baseName: identifier "z" + thenExpression: + declReferenceExpr + baseName: identifier "y" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "ternary is also valid" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchDefaultLabel + colon: : + defaultKeyword: default + statements: + codeBlockItem + item: + breakStmt + breakKeyword: break + subject: + declReferenceExpr + baseName: identifier "x" + switchKeyword: switch + +--- + +top_level + body: + block + stmt: + switch_expr + value: + name_expr + identifier: identifier "x" + case: + switch_case + pattern: + or_pattern + pattern: + expr_equality_pattern + expr: + name_expr + identifier: identifier "y" + expr_equality_pattern + expr: + binary_expr + left: + name_expr + identifier: identifier "y" + operator: infix_operator "+" + right: int_literal "1" + expr_equality_pattern + expr: + unary_expr + operand: + name_expr + identifier: identifier "y" + operator: prefix_operator "-" + expr_equality_pattern + expr: + binary_expr + left: + name_expr + identifier: identifier "y" + operator: infix_operator "..." + right: + name_expr + identifier: identifier "z" + expr_equality_pattern + expr: string_literal "\"foo\"" + expr_equality_pattern + expr: int_literal "4" + expr_equality_pattern + expr: + member_access_expr + base: + call_expr + callee: + name_expr + identifier: identifier "foo" + member: identifier "bar" + expr_equality_pattern + expr: + member_access_expr + base: inferred_type_expr "." + member: identifier "baz" + expr_equality_pattern + expr: + array_literal + element: int_literal "42" + expr_equality_pattern + expr: map_literal "[\"a\": 1]" + expr_equality_pattern + expr: + unary_expr + operand: + name_expr + identifier: identifier "y" + operator: prefix_operator "try" + expr_equality_pattern + expr: + unary_expr + operand: + name_expr + identifier: identifier "y" + operator: postfix_operator "!" + expr_equality_pattern + expr: + type_test_expr + expr: + name_expr + identifier: identifier "y" + operator: infix_operator "is" + type: + named_type_expr + name: identifier "T" + expr_equality_pattern + expr: + unary_expr + operand: + name_expr + identifier: identifier "y" + operator: prefix_operator "await" + expr_equality_pattern + expr: + string_interpolation_expr + element: + string_literal "interpolate " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "y" + string_literal + expr_equality_pattern + expr: unsupported_node "y[4]" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"expr\"" + switch_case + pattern: + expr_equality_pattern + expr: + if_expr + condition: boolean_literal "true" + then: + name_expr + identifier: identifier "y" + else: + name_expr + identifier: identifier "z" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"ternary is also valid\"" + switch_case + body: + block + stmt: break_expr "break" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.swift b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.swift new file mode 100644 index 000000000000..55d58af58131 --- /dev/null +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.swift @@ -0,0 +1,9 @@ +// Arbitrary expressions may appear in pattern context +switch x { +case y, y + 1, -y, y...z, "foo", 4, foo().bar, .baz, [42], ["a": 1], try y, y!, y is T, await y, "interpolate \(y)", y[4]: + print("expr") +case true ? y : z: + print("ternary is also valid") +default: + break +} diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.output new file mode 100644 index 000000000000..60910d2fefee --- /dev/null +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.output @@ -0,0 +1,181 @@ +switch point { +case (let x, let y): + print(x, y) +case (0, 0): + print("origin") +} + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + expressionStmt + expression: + switchExpr + leftBrace: { + rightBrace: } + cases: + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + patternExpr + pattern: + valueBindingPattern + pattern: + identifierPattern + identifier: identifier "x" + bindingSpecifier: let + trailingComma: , + labeledExpr + expression: + patternExpr + pattern: + valueBindingPattern + pattern: + identifierPattern + identifier: identifier "y" + bindingSpecifier: let + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "x" + trailingComma: , + labeledExpr + expression: + declReferenceExpr + baseName: identifier "y" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "0" + trailingComma: , + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "0" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "origin" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + subject: + declReferenceExpr + baseName: identifier "point" + switchKeyword: switch + +--- + +top_level + body: + block + stmt: + switch_expr + value: + name_expr + identifier: identifier "point" + case: + switch_case + pattern: + tuple_pattern + element: + pattern_element + pattern: + name_pattern + identifier: identifier "x" + pattern_element + pattern: + name_pattern + identifier: identifier "y" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: + name_expr + identifier: identifier "x" + argument + value: + name_expr + identifier: identifier "y" + switch_case + pattern: + tuple_pattern + element: + pattern_element + pattern: + expr_equality_pattern + expr: int_literal "0" + pattern_element + pattern: + expr_equality_pattern + expr: int_literal "0" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"origin\"" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.swift b/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.swift new file mode 100644 index 000000000000..1f3a1ab7cdbd --- /dev/null +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-tuple-pattern.swift @@ -0,0 +1,6 @@ +switch point { +case (let x, let y): + print(x, y) +case (0, 0): + print("origin") +} diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output index 90bb6b44e6e5..a72ddf32af4f 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output @@ -3,6 +3,18 @@ case .circle(let r): print(r) case .square(let s): print(s) +case .foo: + print("foo") +case T.foo: + print("foo") +// Ambiguous reference to a static property on the Array type, or an instance property on Array where S is the type of the expression T. +// The parser can't tell the difference. +case [T].foo: + print("foo") +case .foo(let x as T): + print(x) +case is T: + print("is T") } --- @@ -108,6 +120,207 @@ sourceFile calledExpression: declReferenceExpr baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "foo" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "foo" + base: + declReferenceExpr + baseName: identifier "T" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "foo" + base: + arrayExpr + elements: + arrayElement + expression: + declReferenceExpr + baseName: identifier "T" + leftSquare: [ + rightSquare: ] + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + expressionPattern + expression: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + patternExpr + pattern: + valueBindingPattern + pattern: + expressionPattern + expression: + asExpr + expression: + patternExpr + pattern: + identifierPattern + identifier: identifier "x" + asKeyword: as + type: + identifierType + name: identifier "T" + bindingSpecifier: let + additionalTrailingClosures: + calledExpression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "foo" + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "x" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + switchCase + label: + switchCaseLabel + colon: : + caseKeyword: case + caseItems: + switchCaseItem + pattern: + isTypePattern + type: + identifierType + name: identifier "T" + isKeyword: is + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "is T" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" subject: declReferenceExpr baseName: identifier "shape" @@ -172,3 +385,105 @@ top_level value: name_expr identifier: identifier "s" + switch_case + pattern: + expr_equality_pattern + expr: + member_access_expr + base: inferred_type_expr "." + member: identifier "foo" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"foo\"" + switch_case + pattern: + expr_equality_pattern + expr: + member_access_expr + base: + name_expr + identifier: identifier "T" + member: identifier "foo" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"foo\"" + switch_case + pattern: + expr_equality_pattern + expr: + member_access_expr + base: + array_literal + element: + name_expr + identifier: identifier "T" + member: identifier "foo" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"foo\"" + switch_case + pattern: + constructor_pattern + constructor: + member_access_expr + base: inferred_type_expr "." + member: identifier "foo" + element: + pattern_element + pattern: + type_test_pattern + pattern: + name_pattern + identifier: identifier "x" + type: + named_type_expr + name: identifier "T" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: + name_expr + identifier: identifier "x" + switch_case + pattern: + type_test_pattern + type: + named_type_expr + name: identifier "T" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: string_literal "\"is T\"" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.swift b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.swift index e57a4e4ad061..0dc5aa04d61e 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.swift +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.swift @@ -3,4 +3,16 @@ case .circle(let r): print(r) case .square(let s): print(s) +case .foo: + print("foo") +case T.foo: + print("foo") +// Ambiguous reference to a static property on the Array type, or an instance property on Array where S is the type of the expression T. +// The parser can't tell the difference. +case [T].foo: + print("foo") +case .foo(let x as T): + print(x) +case is T: + print("is T") } diff --git a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output index 5207085d174c..c06e04aff67c 100644 --- a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output +++ b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output @@ -1,5 +1,21 @@ +// Simple interpolation "hello \(name)" +// Multiple interpolations +"hello \(first) \(last)" + +// Interpolation with expression +"result: \(x + y)" + +// Plain string before and after interpolation +"prefix \(value) suffix" + +// Calls to custom DefaultStringInterpolation.appendInterpolation impls +"foo \(x, y)" +"foo \(x, y, z)" +"foo \(arg: x)" +"foo \(arg: x, arg2: y)" + --- sourceFile @@ -24,10 +40,309 @@ sourceFile baseName: identifier "name" stringSegment content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "hello " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "first" + stringSegment + content: stringSegment " " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "last" + stringSegment + content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "result: " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + infixOperatorExpr + operator: + binaryOperatorExpr + operator: binaryOperator "+" + leftOperand: + declReferenceExpr + baseName: identifier "x" + rightOperand: + declReferenceExpr + baseName: identifier "y" + stringSegment + content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "prefix " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "value" + stringSegment + content: stringSegment " suffix" + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "x" + trailingComma: , + labeledExpr + expression: + declReferenceExpr + baseName: identifier "y" + stringSegment + content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "x" + trailingComma: , + labeledExpr + expression: + declReferenceExpr + baseName: identifier "y" + trailingComma: , + labeledExpr + expression: + declReferenceExpr + baseName: identifier "z" + stringSegment + content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + colon: : + label: identifier "arg" + expression: + declReferenceExpr + baseName: identifier "x" + stringSegment + content: stringSegment + codeBlockItem + item: + stringLiteralExpr + closingQuote: " + openingQuote: " + segments: + stringSegment + content: stringSegment "foo " + expressionSegment + leftParen: ( + rightParen: ) + backslash: \ + expressions: + labeledExpr + colon: : + label: identifier "arg" + expression: + declReferenceExpr + baseName: identifier "x" + trailingComma: , + labeledExpr + colon: : + label: identifier "arg2" + expression: + declReferenceExpr + baseName: identifier "y" + stringSegment + content: stringSegment --- top_level body: block - stmt: string_literal "\"hello \\(name)\"" + stmt: + string_interpolation_expr + element: + string_literal "hello " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "name" + string_literal + string_interpolation_expr + element: + string_literal "hello " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "first" + string_literal " " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "last" + string_literal + string_interpolation_expr + element: + string_literal "result: " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + binary_expr + left: + name_expr + identifier: identifier "x" + operator: infix_operator "+" + right: + name_expr + identifier: identifier "y" + string_literal + string_interpolation_expr + element: + string_literal "prefix " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "value" + string_literal " suffix" + string_interpolation_expr + element: + string_literal "foo " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "x" + argument + value: + name_expr + identifier: identifier "y" + string_literal + string_interpolation_expr + element: + string_literal "foo " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + value: + name_expr + identifier: identifier "x" + argument + value: + name_expr + identifier: identifier "y" + argument + value: + name_expr + identifier: identifier "z" + string_literal + string_interpolation_expr + element: + string_literal "foo " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + name: identifier "arg" + value: + name_expr + identifier: identifier "x" + string_literal + string_interpolation_expr + element: + string_literal "foo " + call_expr + callee: builtin_expr "interpolation" + argument: + argument + name: identifier "arg" + value: + name_expr + identifier: identifier "x" + argument + name: identifier "arg2" + value: + name_expr + identifier: identifier "y" + string_literal diff --git a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.swift b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.swift index 4c58b37b89e7..b72a94faa00c 100644 --- a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.swift +++ b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.swift @@ -1 +1,17 @@ +// Simple interpolation "hello \(name)" + +// Multiple interpolations +"hello \(first) \(last)" + +// Interpolation with expression +"result: \(x + y)" + +// Plain string before and after interpolation +"prefix \(value) suffix" + +// Calls to custom DefaultStringInterpolation.appendInterpolation impls +"foo \(x, y)" +"foo \(x, y, z)" +"foo \(arg: x)" +"foo \(arg: x, arg2: y)" diff --git a/unified/extractor/tests/corpus/swift/operators/parenthesised-expression.output b/unified/extractor/tests/corpus/swift/operators/parenthesised-expression.output index 0324476ce994..da23fdf9430b 100644 --- a/unified/extractor/tests/corpus/swift/operators/parenthesised-expression.output +++ b/unified/extractor/tests/corpus/swift/operators/parenthesised-expression.output @@ -39,7 +39,15 @@ top_level block stmt: binary_expr - left: tuple_expr "(a + b)" + left: + binary_expr + left: + name_expr + identifier: identifier "a" + operator: infix_operator "+" + right: + name_expr + identifier: identifier "b" operator: infix_operator "*" right: name_expr diff --git a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output index a0563c7bc88b..fadba6e43a87 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output @@ -117,8 +117,7 @@ top_level stmt: unresolved_operator_sequence element: - name_expr - identifier: identifier "_" + builtin_expr "_" infix_operator "=" name_expr identifier: identifier "a" @@ -129,8 +128,7 @@ top_level identifier: identifier "b" unresolved_operator_sequence element: - name_expr - identifier: identifier "_" + builtin_expr "_" infix_operator "=" name_expr identifier: identifier "a" diff --git a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output index 46dc8ca6ae89..6fc46fc64167 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output @@ -90,8 +90,7 @@ top_level stmt: unresolved_operator_sequence element: - name_expr - identifier: identifier "_" + builtin_expr "_" infix_operator "=" name_expr identifier: identifier "a" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.output new file mode 100644 index 000000000000..1f7a56f03fba --- /dev/null +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.output @@ -0,0 +1,128 @@ +do { + try foo() +} catch MyError.someError(let msg) { + print(msg) +} + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + doStmt + body: + codeBlock + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + tryExpr + expression: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "foo" + tryKeyword: try + catchClauses: + catchClause + body: + codeBlock + leftBrace: { + rightBrace: } + statements: + codeBlockItem + item: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "msg" + additionalTrailingClosures: + calledExpression: + declReferenceExpr + baseName: identifier "print" + catchItems: + catchItem + pattern: + expressionPattern + expression: + functionCallExpr + leftParen: ( + rightParen: ) + arguments: + labeledExpr + expression: + patternExpr + pattern: + valueBindingPattern + pattern: + identifierPattern + identifier: identifier "msg" + bindingSpecifier: let + additionalTrailingClosures: + calledExpression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "someError" + base: + declReferenceExpr + baseName: identifier "MyError" + catchKeyword: catch + doKeyword: do + +--- + +top_level + body: + block + stmt: + try_expr + body: + block + stmt: + unary_expr + operand: + call_expr + callee: + name_expr + identifier: identifier "foo" + operator: prefix_operator "try" + catch_clause: + catch_clause + pattern: + constructor_pattern + constructor: + member_access_expr + base: + name_expr + identifier: identifier "MyError" + member: identifier "someError" + element: + pattern_element + pattern: + name_pattern + identifier: identifier "msg" + body: + block + stmt: + call_expr + callee: + name_expr + identifier: identifier "print" + argument: + argument + value: + name_expr + identifier: identifier "msg" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.swift b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.swift new file mode 100644 index 000000000000..4160a67efed9 --- /dev/null +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-pattern.swift @@ -0,0 +1,5 @@ +do { + try foo() +} catch MyError.someError(let msg) { + print(msg) +} diff --git a/unified/extractor/tests/corpus/swift/variables/tuple-assignment.output b/unified/extractor/tests/corpus/swift/variables/tuple-assignment.output new file mode 100644 index 000000000000..f46d7aa508af --- /dev/null +++ b/unified/extractor/tests/corpus/swift/variables/tuple-assignment.output @@ -0,0 +1,126 @@ +(x, _) = (1, 2) +(foo.x, _) = (1, 2) + +--- + +sourceFile + endOfFileToken: endOfFile + statements: + codeBlockItem + item: + infixOperatorExpr + operator: + assignmentExpr + equal: = + leftOperand: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + declReferenceExpr + baseName: identifier "x" + trailingComma: , + labeledExpr + expression: + discardAssignmentExpr + wildcard: _ + rightOperand: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "1" + trailingComma: , + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "2" + codeBlockItem + item: + infixOperatorExpr + operator: + assignmentExpr + equal: = + leftOperand: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + memberAccessExpr + period: . + declName: + declReferenceExpr + baseName: identifier "x" + base: + declReferenceExpr + baseName: identifier "foo" + trailingComma: , + labeledExpr + expression: + discardAssignmentExpr + wildcard: _ + rightOperand: + tupleExpr + leftParen: ( + rightParen: ) + elements: + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "1" + trailingComma: , + labeledExpr + expression: + integerLiteralExpr + literal: integerLiteral "2" + +--- + +top_level + body: + block + stmt: + assign_expr + target: + tuple_expr + element: + argument + value: + name_expr + identifier: identifier "x" + argument + value: builtin_expr "_" + value: + tuple_expr + element: + argument + value: int_literal "1" + argument + value: int_literal "2" + assign_expr + target: + tuple_expr + element: + argument + value: + member_access_expr + base: + name_expr + identifier: identifier "foo" + member: identifier "x" + argument + value: builtin_expr "_" + value: + tuple_expr + element: + argument + value: int_literal "1" + argument + value: int_literal "2" diff --git a/unified/extractor/tests/corpus/swift/variables/tuple-assignment.swift b/unified/extractor/tests/corpus/swift/variables/tuple-assignment.swift new file mode 100644 index 000000000000..dcb9e8c8c205 --- /dev/null +++ b/unified/extractor/tests/corpus/swift/variables/tuple-assignment.swift @@ -0,0 +1,2 @@ +(x, _) = (1, 2) +(foo.x, _) = (1, 2) diff --git a/unified/ql/lib/codeql/unified/internal/Ast.qll b/unified/ql/lib/codeql/unified/internal/Ast.qll index d5ffa0218523..19e6aa806cbb 100644 --- a/unified/ql/lib/codeql/unified/internal/Ast.qll +++ b/unified/ql/lib/codeql/unified/internal/Ast.qll @@ -652,7 +652,7 @@ module Unified { } } - class Expr extends @unified_expr, F::ExprOrOperator, F::ExprOrPattern, F::ExprOrType, F::Stmt { } + class Expr extends @unified_expr, F::ExprOrPattern, F::ExprOrType, F::Stmt { } /** A class representing `expr_equality_pattern` nodes. */ class ExprEqualityPattern extends @unified_expr_equality_pattern, F::Pattern { @@ -666,8 +666,6 @@ module Unified { final override F::AstNode getAFieldOrChild() { unified_expr_equality_pattern_def(this, result) } } - class ExprOrOperator extends @unified_expr_or_operator, F::AstNode { } - class ExprOrPattern extends @unified_expr_or_pattern, F::AstNode { } class ExprOrType extends @unified_expr_or_type, F::AstNode { } @@ -941,9 +939,7 @@ module Unified { } /** A class representing `infix_operator` tokens. */ - class InfixOperator extends @unified_token_infix_operator, F::ExprOrOperator, F::Operator, - F::Token - { + class InfixOperator extends @unified_token_infix_operator, F::Operator, F::Token { /** Gets the name of the primary QL class for this element. */ final override string getAPrimaryQlClass() { result = "InfixOperator" } } @@ -1272,6 +1268,32 @@ module Unified { class Stmt extends @unified_stmt, F::AstNode { } + /** A class representing `string_interpolation_expr` nodes. */ + class StringInterpolationExpr extends @unified_string_interpolation_expr, F::Expr { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "StringInterpolationExpr" } + + /** Gets the node corresponding to the field `element`. */ + final F::Expr getElement(int i) { unified_string_interpolation_expr_element(this, i, result) } + + /** Gets the node corresponding to the field `element`. */ + final F::Expr getAnElement() { result = this.getElement(_) } + + /** Gets the node corresponding to the field `modifier`. */ + final F::Modifier getModifier(int i) { + unified_string_interpolation_expr_modifier(this, i, result) + } + + /** Gets the node corresponding to the field `modifier`. */ + final F::Modifier getAModifier() { result = this.getModifier(_) } + + /** Gets a field or child node of this node. */ + final override F::AstNode getAFieldOrChild() { + unified_string_interpolation_expr_element(this, _, result) or + unified_string_interpolation_expr_modifier(this, _, result) + } + } + /** A class representing `string_literal` tokens. */ class StringLiteral extends @unified_token_string_literal, F::Expr, F::Token { /** Gets the name of the primary QL class for this element. */ @@ -1395,10 +1417,10 @@ module Unified { final override string getAPrimaryQlClass() { result = "TupleExpr" } /** Gets the node corresponding to the field `element`. */ - final F::Expr getElement(int i) { unified_tuple_expr_element(this, i, result) } + final F::Argument getElement(int i) { unified_tuple_expr_element(this, i, result) } /** Gets the node corresponding to the field `element`. */ - final F::Expr getAnElement() { result = this.getElement(_) } + final F::Argument getAnElement() { result = this.getElement(_) } /** Gets a field or child node of this node. */ final override F::AstNode getAFieldOrChild() { unified_tuple_expr_element(this, _, result) } @@ -1581,20 +1603,19 @@ module Unified { } /** A class representing `type_test_pattern` nodes. */ - class TypeTestPattern extends @unified_type_test_pattern, F::AstNode { + class TypeTestPattern extends @unified_type_test_pattern, F::Pattern { /** Gets the name of the primary QL class for this element. */ final override string getAPrimaryQlClass() { result = "TypeTestPattern" } /** Gets the node corresponding to the field `pattern`. */ - final F::Pattern getPattern() { unified_type_test_pattern_def(this, result, _) } + final F::Pattern getPattern() { unified_type_test_pattern_pattern(this, result) } /** Gets the node corresponding to the field `type`. */ - final F::TypeExpr getType() { unified_type_test_pattern_def(this, _, result) } + final F::TypeExpr getType() { unified_type_test_pattern_def(this, result) } /** Gets a field or child node of this node. */ final override F::AstNode getAFieldOrChild() { - unified_type_test_pattern_def(this, result, _) or - unified_type_test_pattern_def(this, _, result) + unified_type_test_pattern_pattern(this, result) or unified_type_test_pattern_def(this, result) } } @@ -1621,12 +1642,12 @@ module Unified { final override string getAPrimaryQlClass() { result = "UnresolvedOperatorSequence" } /** Gets the node corresponding to the field `element`. */ - final F::ExprOrOperator getElement(int i) { + final F::AstNode getElement(int i) { unified_unresolved_operator_sequence_element(this, i, result) } /** Gets the node corresponding to the field `element`. */ - final F::ExprOrOperator getAnElement() { result = this.getElement(_) } + final F::AstNode getAnElement() { result = this.getElement(_) } /** Gets a field or child node of this node. */ final override F::AstNode getAFieldOrChild() { @@ -1942,6 +1963,10 @@ module Unified { or result = node.(ReturnExpr).getValue() and i = -1 and name = "getValue" or + result = node.(StringInterpolationExpr).getElement(i) and name = "getElement" + or + result = node.(StringInterpolationExpr).getModifier(i) and name = "getModifier" + or result = node.(SwitchCase).getBody() and i = -1 and name = "getBody" or result = node.(SwitchCase).getModifier(i) and name = "getModifier" @@ -2097,8 +2122,6 @@ module UnifiedFinal { final class ExprEqualityPattern = F::ExprEqualityPattern; - final class ExprOrOperator = F::ExprOrOperator; - final class ExprOrPattern = F::ExprOrPattern; final class ExprOrType = F::ExprOrType; @@ -2177,6 +2200,8 @@ module UnifiedFinal { final class Stmt = F::Stmt; + final class StringInterpolationExpr = F::StringInterpolationExpr; + final class StringLiteral = F::StringLiteral; final class SuperExpr = F::SuperExpr; diff --git a/unified/ql/lib/unified.dbscheme b/unified/ql/lib/unified.dbscheme index c36721515d5c..4a1a45323226 100644 --- a/unified/ql/lib/unified.dbscheme +++ b/unified/ql/lib/unified.dbscheme @@ -460,15 +460,13 @@ unified_equality_type_constraint_def( int right: @unified_type_expr ref ); -@unified_expr = @unified_array_literal | @unified_assign_expr | @unified_binary_expr | @unified_block | @unified_break_expr | @unified_call_expr | @unified_compound_assign_expr | @unified_continue_expr | @unified_function_expr | @unified_if_expr | @unified_key_value_pair | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_expr | @unified_throw_expr | @unified_token_boolean_literal | @unified_token_builtin_expr | @unified_token_empty_expr | @unified_token_float_literal | @unified_token_int_literal | @unified_token_regex_literal | @unified_token_string_literal | @unified_token_super_expr | @unified_token_unsupported_node | @unified_try_expr | @unified_tuple_expr | @unified_type_cast_expr | @unified_type_test_expr | @unified_unary_expr | @unified_unresolved_operator_sequence +@unified_expr = @unified_array_literal | @unified_assign_expr | @unified_binary_expr | @unified_block | @unified_break_expr | @unified_call_expr | @unified_compound_assign_expr | @unified_continue_expr | @unified_function_expr | @unified_if_expr | @unified_key_value_pair | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_pattern_guard_expr | @unified_return_expr | @unified_string_interpolation_expr | @unified_switch_expr | @unified_throw_expr | @unified_token_boolean_literal | @unified_token_builtin_expr | @unified_token_empty_expr | @unified_token_float_literal | @unified_token_int_literal | @unified_token_regex_literal | @unified_token_string_literal | @unified_token_super_expr | @unified_token_unsupported_node | @unified_try_expr | @unified_tuple_expr | @unified_type_cast_expr | @unified_type_test_expr | @unified_unary_expr | @unified_unresolved_operator_sequence unified_expr_equality_pattern_def( unique int id: @unified_expr_equality_pattern, int expr: @unified_expr ref ); -@unified_expr_or_operator = @unified_expr | @unified_token_infix_operator - @unified_expr_or_pattern = @unified_expr | @unified_pattern @unified_expr_or_type = @unified_expr | @unified_type_expr @@ -780,7 +778,7 @@ unified_parameter_def( unique int id: @unified_parameter ); -@unified_pattern = @unified_bulk_importing_pattern | @unified_conditional_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_or_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern +@unified_pattern = @unified_bulk_importing_pattern | @unified_conditional_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_or_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern | @unified_type_test_pattern unified_pattern_element_key( unique int unified_pattern_element: @unified_pattern_element ref, @@ -816,6 +814,24 @@ unified_return_expr_def( @unified_stmt = @unified_accessor_declaration | @unified_class_like_declaration | @unified_constructor_declaration | @unified_destructor_declaration | @unified_do_while_stmt | @unified_expr | @unified_for_each_stmt | @unified_function_declaration | @unified_guard_if_stmt | @unified_import_declaration | @unified_labeled_stmt | @unified_operator_syntax_declaration | @unified_type_alias_declaration | @unified_variable_declaration | @unified_while_stmt +#keyset[unified_string_interpolation_expr, index] +unified_string_interpolation_expr_element( + int unified_string_interpolation_expr: @unified_string_interpolation_expr ref, + int index: int ref, + unique int element: @unified_expr ref +); + +#keyset[unified_string_interpolation_expr, index] +unified_string_interpolation_expr_modifier( + int unified_string_interpolation_expr: @unified_string_interpolation_expr ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_string_interpolation_expr_def( + unique int id: @unified_string_interpolation_expr +); + #keyset[unified_switch_case, index] unified_switch_case_modifier( int unified_switch_case: @unified_switch_case ref, @@ -889,7 +905,7 @@ unified_try_expr_def( unified_tuple_expr_element( int unified_tuple_expr: @unified_tuple_expr ref, int index: int ref, - unique int element: @unified_expr ref + unique int element: @unified_argument ref ); unified_tuple_expr_def( @@ -997,9 +1013,13 @@ unified_type_test_expr_def( int type__: @unified_type_expr ref ); +unified_type_test_pattern_pattern( + unique int unified_type_test_pattern: @unified_type_test_pattern ref, + unique int pattern: @unified_pattern ref +); + unified_type_test_pattern_def( unique int id: @unified_type_test_pattern, - int pattern: @unified_pattern ref, int type__: @unified_type_expr ref ); @@ -1009,11 +1029,13 @@ unified_unary_expr_def( int operator: @unified_operator ref ); +@unified_unresolved_operator_sequence_element_type = @unified_expr | @unified_pattern | @unified_token_infix_operator + #keyset[unified_unresolved_operator_sequence, index] unified_unresolved_operator_sequence_element( int unified_unresolved_operator_sequence: @unified_unresolved_operator_sequence ref, int index: int ref, - unique int element: @unified_expr_or_operator ref + unique int element: @unified_unresolved_operator_sequence_element_type ref ); unified_unresolved_operator_sequence_def( @@ -1093,7 +1115,7 @@ unified_trivia_tokeninfo( string value: string ref ); -@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_conditional_pattern | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_unresolved_operator_sequence | @unified_variable_declaration | @unified_while_stmt +@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_conditional_pattern | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_string_interpolation_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_unresolved_operator_sequence | @unified_variable_declaration | @unified_while_stmt unified_ast_node_location( unique int node: @unified_ast_node ref, diff --git a/unified/ql/test/library-tests/BasicTest/test.expected b/unified/ql/test/library-tests/BasicTest/test.expected index 301cd90ca2a5..fe7d4f50fb39 100644 --- a/unified/ql/test/library-tests/BasicTest/test.expected +++ b/unified/ql/test/library-tests/BasicTest/test.expected @@ -18,22 +18,20 @@ nameExpr | test.swift:48:15:48:19 | NameExpr | index | | test.swift:48:29:48:33 | NameExpr | index | | test.swift:48:37:48:40 | NameExpr | data | -| test.swift:49:16:49:19 | NameExpr | data | -| test.swift:49:21:49:25 | NameExpr | index | | test.swift:53:9:53:12 | NameExpr | data | | test.swift:53:21:53:24 | NameExpr | item | | test.swift:63:16:63:19 | NameExpr | self | | test.swift:65:29:65:37 | NameExpr | transform | | test.swift:65:39:65:43 | NameExpr | value | | test.swift:67:29:67:33 | NameExpr | error | -| test.swift:76:16:76:19 | NameExpr | self | -| test.swift:76:21:76:21 | NameExpr | i | -| test.swift:76:26:76:29 | NameExpr | self | -| test.swift:76:31:76:31 | NameExpr | i | +| test.swift:75:23:75:27 | NameExpr | count | | test.swift:86:12:86:17 | NameExpr | values | | test.swift:87:12:87:17 | NameExpr | values | -| test.swift:87:38:87:43 | NameExpr | values | | test.swift:87:49:87:57 | NameExpr | transform | unsupported +| test.swift:49:16:49:26 | | | +| test.swift:76:16:76:22 | | | +| test.swift:76:26:76:36 | | | +| test.swift:87:38:87:46 | | | stringValue | strings.swift:1:9:1:15 | "hello" | "hello" | diff --git a/unified/scripts/update-corpus.sh b/unified/scripts/update-corpus.sh index 2f3ebade8cb3..5c3c95cd0740 100755 --- a/unified/scripts/update-corpus.sh +++ b/unified/scripts/update-corpus.sh @@ -5,4 +5,4 @@ IFS=$'\n\t' cd "$(dirname "$0")/.." cd extractor -UNIFIED_UPDATE_CORPUS=1 cargo test +UNIFIED_UPDATE_CORPUS=1 cargo test test_corpus