diff --git a/shared/yeast-macros/src/lib.rs b/shared/yeast-macros/src/lib.rs index 1d7236b500a9..07077be51f04 100644 --- a/shared/yeast-macros/src/lib.rs +++ b/shared/yeast-macros/src/lib.rs @@ -44,8 +44,19 @@ pub fn query(input: TokenStream) -> TokenStream { /// {expr} - embed a Rust expression returning Id /// {..expr} - splice an iterable of Id (in child/field position) /// field: {..expr} - splice into a named field +/// {expr}.map(p -> tpl) - apply tpl to each element; splice result +/// {expr}.reduce_left(f -> init, acc, e -> fold) +/// - fold with per-element init; splice 0 or 1 result /// ``` /// +/// Chain syntax after `{expr}` or `{..expr}`: +/// - `.map(param -> template)` — one output node per input element. +/// - `.reduce_left(first -> init, acc, elem -> fold)` — fold left; the first +/// element is converted by `init`, subsequent elements are folded by `fold` +/// with the accumulator bound to `acc`. An empty iterable yields nothing. +/// - Chains always splice (the result is iterable). +/// - Multiple chains can be chained, e.g. `.map(...).reduce_left(...)`. +/// /// Can be called with an explicit context or using the implicit context /// from an enclosing `rule!`: /// diff --git a/shared/yeast-macros/src/parse.rs b/shared/yeast-macros/src/parse.rs index eb3b161b295a..0980d41f9567 100644 --- a/shared/yeast-macros/src/parse.rs +++ b/shared/yeast-macros/src/parse.rs @@ -141,7 +141,12 @@ fn parse_query_fields(tokens: &mut Tokens) -> Result> { // Parse the field's pattern. To support repetition like // `field: (kind)* @cap`, parse the atom first, then check for // a quantifier, and lastly handle a trailing `@capture`. - let atom = parse_query_atom(tokens)?; + // `field: @cap` is sugar for `field: _ @cap`. + let atom = if peek_is_at(tokens) { + quote! { yeast::query::QueryNode::Any { match_unnamed: true } } + } else { + parse_query_atom(tokens)? + }; if peek_is_repetition(tokens) { let rep = expect_repetition(tokens)?; let elem = quote! { @@ -259,6 +264,7 @@ fn parse_query_list(tokens: &mut Tokens) -> Result> { yeast::query::QueryListElem::SingleNode(#node) }, )?; + let elem = maybe_wrap_list_capture(tokens, elem)?; elems.push(elem); continue; } @@ -276,6 +282,7 @@ fn parse_query_list(tokens: &mut Tokens) -> Result> { yeast::query::QueryListElem::SingleNode(#node) }, )?; + let elem = maybe_wrap_list_capture(tokens, elem)?; elems.push(elem); continue; } @@ -419,23 +426,35 @@ fn parse_direct_node_inner(tokens: &mut Tokens, ctx: &Ident) -> Result into the field + // Check for field: {..expr}.chain or field: {expr}.chain — splice a Vec into the field if peek_is_group(tokens, Delimiter::Brace) { let group_clone = tokens.clone().next().unwrap(); if let TokenTree::Group(g) = &group_clone { let mut inner_check = g.stream().into_iter(); let is_splice = matches!(inner_check.next(), Some(TokenTree::Punct(p)) if p.as_char() == '.') && matches!(inner_check.next(), Some(TokenTree::Punct(p)) if p.as_char() == '.'); - if is_splice { + // Determine if a chain (.map(..)) follows the `{}` group. + let mut after = tokens.clone(); + after.next(); // skip the brace group + let has_chain = matches!(after.peek(), Some(TokenTree::Punct(p)) if p.as_char() == '.'); + + if is_splice || has_chain { let group = expect_group(tokens, Delimiter::Brace)?; - let mut inner = group.stream().into_iter().peekable(); - inner.next(); // consume first . - inner.next(); // consume second . - let expr: proc_macro2::TokenStream = inner.collect(); + let base: TokenStream = if is_splice { + let mut inner = group.stream().into_iter().peekable(); + inner.next(); // consume first . + inner.next(); // consume second . + let expr: TokenStream = inner.collect(); + quote! { + (#expr).into_iter().map(::std::convert::Into::::into) + } + } else { + let expr = group.stream(); + quote! { (#expr).into_iter() } + }; + let chained = parse_chain_suffix(tokens, ctx, base)?; stmts.push(quote! { - let #temp: Vec = (#expr).into_iter() - .map(::std::convert::Into::::into) - .collect(); + let #temp: Vec = #chained.collect(); }); // An empty splice means the field is absent — skip it // entirely rather than emitting an empty named field. @@ -472,6 +491,98 @@ fn parse_direct_node_inner(tokens: &mut Tokens, ctx: &Ident) -> Result template) -- iterator map: produces Vec +/// ``` +/// +/// The chain may be empty (returns `base` unchanged). Multiple chained calls +/// are supported, e.g. `.map(p -> ...).map(q -> ...)`. +/// +/// Each call expects the receiver to be an iterator. The `base` argument +/// should therefore already be an iterator (use `.into_iter()` on it before +/// calling this function). +fn parse_chain_suffix( + tokens: &mut Tokens, + ctx: &Ident, + base: TokenStream, +) -> Result { + let mut current = base; + while matches!(tokens.peek(), Some(TokenTree::Punct(p)) if p.as_char() == '.') { + tokens.next(); // consume . + let method = expect_ident(tokens, "expected method name after `.`")?; + let method_str = method.to_string(); + let args_group = expect_group(tokens, Delimiter::Parenthesis)?; + match method_str.as_str() { + "map" => { + let mut inner = args_group.stream().into_iter().peekable(); + let param = expect_ident(&mut inner, "expected lambda parameter name")?; + expect_punct(&mut inner, '-', "expected `->` after lambda parameter")?; + expect_punct(&mut inner, '>', "expected `->` after lambda parameter")?; + let body = parse_direct_node(&mut inner, ctx)?; + if let Some(tok) = inner.next() { + return Err(syn::Error::new_spanned( + tok, + "unexpected token after lambda body", + )); + } + current = quote! { + #current.map(|#param| #body) + }; + } + "reduce_left" => { + // Syntax: reduce_left(first -> init_tpl, acc, elem -> fold_tpl) + // - first -> init_tpl : converts the first element to the initial accumulator + // - acc, elem -> fold_tpl : fold step (acc = current accumulator, elem = next element) + // Empty iterator produces an empty iterator; non-empty produces a single-element iterator. + let mut inner = args_group.stream().into_iter().peekable(); + let init_param = expect_ident(&mut inner, "expected initial lambda parameter")?; + expect_punct(&mut inner, '-', "expected `->` after init parameter")?; + expect_punct(&mut inner, '>', "expected `->` after init parameter")?; + let init_body = parse_direct_node(&mut inner, ctx)?; + expect_punct(&mut inner, ',', "expected `,` after init template")?; + let acc_param = expect_ident(&mut inner, "expected accumulator parameter")?; + expect_punct(&mut inner, ',', "expected `,` after accumulator parameter")?; + let elem_param = expect_ident(&mut inner, "expected element parameter")?; + expect_punct(&mut inner, '-', "expected `->` after element parameter")?; + expect_punct(&mut inner, '>', "expected `->` after element parameter")?; + let fold_body = parse_direct_node(&mut inner, ctx)?; + if let Some(tok) = inner.next() { + return Err(syn::Error::new_spanned( + tok, + "unexpected token after fold template", + )); + } + current = quote! { + { + let mut __iter = #current; + let __result: Option = if let Some(#init_param) = __iter.next() { + let mut __acc: usize = #init_body; + for #elem_param in __iter { + let #acc_param: usize = __acc; + __acc = #fold_body; + } + Some(__acc) + } else { + None + }; + __result.into_iter() + } + }; + } + _ => { + return Err(syn::Error::new_spanned( + method, + format!("unknown builtin method `.{method_str}()`"), + )); + } + } + } + Ok(current) +} + /// Parse the top-level list of a `trees!` template. /// Each item is a node template or `{expr}` splice. fn parse_direct_list(tokens: &mut Tokens, ctx: &Ident) -> Result> { @@ -492,18 +603,27 @@ fn parse_direct_list(tokens: &mut Tokens, ctx: &Ident) -> Result::into) - ); + } + } else { + let expr = group.stream(); + quote! { (#expr).into_iter() } + }; + let chained = parse_chain_suffix(tokens, ctx, base)?; + items.push(quote! { + __nodes.extend(#chained); }); } else { let expr = group.stream(); @@ -604,8 +724,11 @@ fn extract_captures_inner( } last_mult = CaptureMultiplicity::Single; } - TokenTree::Punct(p) if matches!(p.as_char(), '*' | '+' | '?') => { - // Keep last_mult — the @capture follows + TokenTree::Punct(p) if p.as_char() == '*' || p.as_char() == '+' => { + last_mult = CaptureMultiplicity::Repeated; + } + TokenTree::Punct(p) if p.as_char() == '?' => { + last_mult = CaptureMultiplicity::Optional; } _ => { last_mult = CaptureMultiplicity::Single; diff --git a/shared/yeast/src/build.rs b/shared/yeast/src/build.rs index bee4c4f7d034..5b018ee8edc5 100644 --- a/shared/yeast/src/build.rs +++ b/shared/yeast/src/build.rs @@ -88,4 +88,13 @@ impl<'a> BuildCtx<'a> { self.ast .create_named_token_with_range(kind, generated, self.source_range) } + + /// Prepend a value to a field of an existing node. + pub fn prepend_field(&mut self, node_id: Id, field_name: &str, value_id: Id) { + let field_id = self + .ast + .field_id_for_name(field_name) + .unwrap_or_else(|| panic!("build: field '{field_name}' not found")); + self.ast.prepend_field_child(node_id, field_id, value_id); + } } diff --git a/shared/yeast/src/lib.rs b/shared/yeast/src/lib.rs index 0717d27e4b8b..40b90567537c 100644 --- a/shared/yeast/src/lib.rs +++ b/shared/yeast/src/lib.rs @@ -387,6 +387,12 @@ impl Ast { self.create_named_token_with_range(kind, content, None) } + /// Prepend a child id to the given field of the given node. + pub fn prepend_field_child(&mut self, node_id: Id, field_id: FieldId, value_id: Id) { + let node = self.nodes.get_mut(node_id).expect("prepend_field_child: invalid node id"); + node.fields.entry(field_id).or_default().insert(0, value_id); + } + pub fn create_named_token_with_range( &mut self, kind: &'static str, @@ -825,14 +831,6 @@ fn apply_one_shot_rules_inner( let node_kind = ast.get_node(id).map(|n| n.kind()).unwrap_or(""); - // Don't rewrite unnamed nodes (punctuation, keywords, etc.); leave them - // as-is. Rules target named nodes only. - if let Some(node) = ast.get_node(id) { - if !node.is_named() { - return Ok(vec![id]); - } - } - for rule in index.rules_for_kind(node_kind) { if let Some(mut captures) = rule.try_match(ast, id)? { // Recursively translate every captured node before invoking the diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index 7645f3776f87..3ae8e2072d9f 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -389,6 +389,29 @@ fn test_capture_unnamed_node_parenthesized() { assert!(!op_node.is_named()); } +#[test] +fn test_capture_bare_underscore_repeated() { + // `_` matches named and unnamed nodes in bare-child position. On this + // assignment shape, bare children correspond to unnamed tokens (the `=`). + let runner = Runner::new(tree_sitter_ruby::LANGUAGE.into(), &[]); + let ast = runner.run("x = 1").unwrap(); + + let query = yeast::query!((assignment _* @all)); + + let mut cursor = AstCursor::new(&ast); + cursor.goto_first_child(); + let assignment_id = cursor.node_id(); + + let mut captures = yeast::captures::Captures::new(); + let matched = query.do_match(&ast, assignment_id, &mut captures).unwrap(); + assert!(matched); + + let all = captures.get_all("all"); + assert_eq!(all.len(), 1); + assert_eq!(ast.get_node(all[0]).unwrap().kind(), "="); + assert!(!ast.get_node(all[0]).unwrap().is_named()); +} + #[test] fn test_capture_unnamed_node_bare_literal() { // `"=" @op` (without surrounding parens) is the same as `("=") @op`. diff --git a/unified/extractor/ast_types.yml b/unified/extractor/ast_types.yml index 22a5e8b19fb8..fc8350679e04 100644 --- a/unified/extractor/ast_types.yml +++ b/unified/extractor/ast_types.yml @@ -2,36 +2,102 @@ supertypes: expr: - name_expr - int_literal + - float_literal + - boolean_literal + - keyword_literal - string_literal + - regex_literal - binary_expr - unary_expr - call_expr - member_access_expr - - lambda_expr - - unsupported_node - stmt: - - empty_stmt - - block_stmt - - expr_stmt - - if_stmt - - variable_declaration_stmt - - guard_if_stmt - - unsupported_node - condition: - - expr_condition - - let_pattern_condition - - sequence_condition + - shorthand_member_access_expr + - super_expr + - function_expr + - array_literal + - map_literal + - key_value_pair + - tuple_expr + - type_cast_expr + - type_test_expr + - if_expr + - assign_expr + - compound_assign_expr + - pattern_guard_expr + - empty_expr + - block + - break_expr + - continue_expr + - return_expr + - throw_expr + - try_expr + - switch_expr - unsupported_node + expr_or_pattern: + - expr + - pattern + expr_or_type: + - expr + - type_expr pattern: - - var_pattern - - apply_pattern + - name_pattern + - constructor_pattern - tuple_pattern - ignore_pattern + - expr_equality_pattern - unsupported_node + # A statement is anything that can appear in a block. + # This type contains all of 'expr' and has partial overlap with 'member'. + # For example, type_alias_declaration can appear either as a stmt or member. + # constructor_declaration and destructor_declaration appear here because + # tree-sitter-swift's error recovery for #if/#endif in class bodies can place + # init/deinit declarations at the wrong (statement) level. + stmt: + - expr + - variable_declaration + - type_alias_declaration + - function_declaration + - import_declaration + - operator_syntax_declaration + - class_like_declaration + - accessor_declaration + - constructor_declaration + - destructor_declaration + - guard_if_stmt + - for_each_stmt + - while_stmt + - do_while_stmt + - labeled_stmt + # A member is anything that can appear in the body of a class-like declaration + member: + - constructor_declaration + - destructor_declaration + - function_declaration + - variable_declaration + - accessor_declaration + - initializer_declaration + - class_like_declaration + - type_alias_declaration + - associated_type_declaration + - unsupported_node + type_expr: + - named_type_expr + - generic_type_expr + - tuple_type_expr + - function_type_expr + - unsupported_node + type_constraint: + - equality_type_constraint + - bound_type_constraint + operator: + - infix_operator + - prefix_operator + - postfix_operator named: - # Top-level is the root node, currently containing a list of expressions + # Top-level is the root node, containing a single block of statements + # (which are themselves expressions or declarations). top_level: - body*: [expr, stmt] + body: block # An identifier used in the context of an expression name_expr: @@ -40,13 +106,28 @@ named: # An integer literal int_literal: + # A floating-point literal + float_literal: + + # A boolean literal + boolean_literal: + + # A literal backed by a keyword such as `nil`, `null`, or `nullptr`. + # + # Altough nil/null are keyword literals in many languages there should be + # no attempt to normalize "null-like" named entities, like Python's `None`. + keyword_literal: + # A string literal string_literal: + # A regex literal + regex_literal: + # Application of a binary operator, such as `a + b` binary_expr: left: expr - operator: operator + operator: infix_operator right: expr # Application of a unary operator, such as `!x` @@ -54,80 +135,261 @@ named: operand: expr operator: operator - # A function or method call, such as `f(x)` or `obj.m(x)`. Method calls - # are represented as a call whose `function` is a `member_access_expr`. + # Plain assignment + assign_expr: + target: expr_or_pattern + value: expr + + # Compound assignment + compound_assign_expr: + target: expr + operator: infix_operator + value: expr + + # A function or method call, such as `f(x)` or `obj.m(x)`. + # + # Method calls are represented as a call whose `function` is a `member_access_expr`. + # + # Constructor calls are marked by a language-specific modifier, and the target may be + # a `type_expr` if the parser can deduce that the target is a type. call_expr: - function: expr - argument*: expr + modifier*: modifier + function: expr_or_type + argument*: argument + + argument: + modifier*: modifier + name?: identifier + value?: expr # Member access, such as `obj.member`. + # + # The target may be a type expression when it is a static member access like `Array.method`. + # In ambiguous cases where the parser cannot distinguish static and instance member access, the target + # will be typically be an expression. + # + # For `super.x` the target will be an instance of `super_expr`. member_access_expr: - target: expr + target: expr_or_type member: identifier - lambda_expr: + # Member access with an omitted base expression (which must be inferred from context) + # but which is syntactically distinct from a simple identifier. + # Swift: `.member` -- that is, a dot followed by a member name. + shorthand_member_access_expr: + member: identifier + + # A `super` token, which can usually only appear as the base of member access. + super_expr: + + function_expr: + modifier*: modifier + capture_declaration*: variable_declaration parameter*: parameter - body: [expr, stmt] + return_type?: type_expr + body: block - # A parameter - parameter: - pattern: pattern + array_literal: + element*: expr - empty_stmt: + map_literal: + element*: expr - block_stmt: - body*: stmt + # A key-value pair, usually appearing as a named argument or as part of a map literal. + # + # For some languages, the key-value pair is a first class value and this type of expression + # may thus appear anywhere in the general case. + key_value_pair: + key: expr + value: expr - expr_stmt: - expr: expr + # A tuple expression, such as `(a, b, c)`. + tuple_expr: + element*: expr + + # A parameter. + # + # `type` is its declared type annotation (if any) + # + # `pattern` binds the parameter's internal name(s). For a simple parameter this is a + # `name_pattern`, but may be an arbitrary pattern for languages where patterns may appear + # in the parameter list. + # + # `external_name` is the name by which to call sites refer to the parameter, if the parameter + # can be passed as a named parameter. For example, the Swift function `func greet(person id: String)` + # would have `person` as the external name and a `name_pattern` wrapping `id` is the parameter's pattern. + parameter: + external_name?: identifier + type?: type_expr + pattern?: pattern - if_stmt: - condition: condition - then?: stmt - else?: stmt + # An expression that does nothing. Used where the grammar permits an + # empty statement (e.g. a stray `;`). + empty_expr: + + # A brace-delimited sequence of statements (`{ ... }`). Blocks are the + # only nodes that can directly contain statements; every other body-like + # field holds a single `block`. + block: + stmt*: stmt - variable_declaration_stmt: - variable_declarator+: variable_declarator + if_expr: + condition: expr + then?: expr + else?: expr - # A variable declaration, or assignment to a pattern. - # The initializer is optional (but typically only possible in combination with a simple variable pattern). - variable_declarator: + # A variable declaration or destructuring assignment that introduces new variables. + # + # Any occurrence of `var_patterns` in 'pattern' result in fresh bindings that are + # in scope for the rest of the enclosing block. + # + # The initializer is optional (but typically cannot be omitted if combined with a non-trivial pattern). + # + # Modifiers should include 'var', 'let', 'const', etc, if they are significant. + # A grouped declaration like `let x = 1, y = 2` is emitted as a sequence of + # `variable_declaration`s directly into the enclosing stmt/member slot; every + # declaration after the first in such a group is tagged with a synthetic + # `chained_declaration` modifier so the grouping can be recovered downstream. + variable_declaration: + modifier*: modifier pattern: pattern + type?: type_expr value?: expr # Evaluate 'condition', and if false, execute 'else' which must break from the enclosing block scope (return, break, etc). # Any variables bound by 'condition' will be in scope for the remainder of the enclosing block scope - # (which differs from how if_stmt works). + # (which differs from how if_expr works). guard_if_stmt: - condition: condition - else: stmt + condition: expr + else: block - # Evaluates the given condition and interprets it as a boolean (by language conventions) - expr_condition: - expr: expr + # `break` (with optional label) + break_expr: + label?: identifier - # A series of statements that are executed before evaluating the trailing condition. - # Useful for languages where a conditional clause may be preceded by side-effecting - # syntactic elements (e.g. binding clauses) that don't themselves form a condition. - sequence_condition: - stmt*: stmt - condition: condition + # `continue` (with optional label) + continue_expr: + label?: identifier + + # A labeled statement, such as `outer: for ... { ... }`. The labeled + # statement appears as the `stmt` field; `break`/`continue` may target + # the label. + labeled_stmt: + label: identifier + stmt: stmt + + # `return value` or bare `return` + return_expr: + value?: expr + + # `throw value` + throw_expr: + value?: expr + + # An import declaration. `path` is the dotted path (e.g. `Foo.Bar` becomes two identifiers). + import_declaration: + modifier*: modifier + path+: identifier + + # `typealias Name = Type` + type_alias_declaration: + modifier*: modifier + name: identifier + type_parameter*: type_parameter + type_constraint*: type_constraint + type: type_expr + + # A top-level function declaration. + function_declaration: + modifier*: modifier + name: identifier + type_parameter*: type_parameter + type_constraint*: type_constraint + parameter*: parameter + return_type?: type_expr + body?: block + + # `for pattern in iterable [where guard] { body }`. + for_each_stmt: + pattern: pattern + iterable: expr + guard?: expr + body?: block + + # `while condition { body }`. + while_stmt: + condition: expr + body?: block + + # `repeat { body } while condition`. + do_while_stmt: + body?: block + condition: expr + + # `do { body } catch pattern { ... } catch ...`. Swift uses `do`/`catch` + # for error handling; for languages with `try`/`catch`, this is the same shape. + try_expr: + body: block + catch_clause*: catch_clause + + catch_clause: + pattern?: pattern + guard?: expr + body: block + + # `switch value { case pattern: body case ...: default: body }` + switch_expr: + value: expr + case*: switch_case + + # A single `case ...:` (or `default:`) entry in a switch. + # An entry with multiple `case p1, p2:` patterns has multiple `pattern`s. + # A `default:` entry has no patterns. + # An optional `guard` corresponds to a `where`-clause on the case. + switch_case: + pattern*: pattern + guard?: expr + body: block # Evaluate 'expr' and match its result against 'pattern', and return true if it matches. - # Variables bound by the pattern will be in scope within the 'true' branch controlled by this condition. - let_pattern_condition: + # Variables bound by the pattern will be in scope within the 'true' branch controlled by this expression. + # + # In Swift, `if case let PATTERN = EXPR` maps to this node + pattern_guard_expr: pattern: pattern value: expr - # A pattern matching anything, binding its value to the given variable - var_pattern: + # A type cast expression, such as `x as T`, `x as? T`, or `x as! T`. The + # operator distinguishes between the variants. + type_cast_expr: + expr: expr + operator: infix_operator + type: type_expr + + # A type-test expression, such as `x is T`. Yields a boolean indicating + # whether `expr` is an instance of `type`. + type_test_expr: + expr: expr + operator: infix_operator + type: type_expr + + # An identifier that introduces a variable. + # + # When used as a pattern, the pattern matches anything and binds its incoming value to the variable + name_pattern: identifier: identifier + type?: type_expr # A pattern matching anything, binding no variables, usually using the syntax "_" ignore_pattern: + # A pattern that matches if the incoming value is equal to the value of the given expression. + # Used for literal patterns in switch (e.g. `case 1:`). + expr_equality_pattern: + expr: expr + # A pattern such as `Some(x)` where `Some` is the constructor and `x` is an argument - apply_pattern: + constructor_pattern: constructor: expr argument*: pattern @@ -135,10 +397,143 @@ named: tuple_pattern: element*: pattern + # A pattern that checks if the incoming value has the given type, and if so, the + # value is matched against the given nested pattern (and succeeds iff the nested match succeeds). + # + # 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 + type: type_expr + # An simple unqualified identifier token identifier: # A node that we don't yet translate unsupported_node: - operator: + infix_operator: + + prefix_operator: + + postfix_operator: + + # The fixity of a custom operator declaration (e.g. "prefix", "infix", + # "postfix"). The value is the keyword string. + fixity: + + type_parameter: + name: identifier + bound?: type_expr + + # A generic constraint of the form `T == U`, requiring two types to be + # equal. Appears in `where` clauses on generic declarations + # (e.g. Swift `func foo() where T == U`). + equality_type_constraint: + left: type_expr + right: type_expr + + # A generic constraint of the form `T: Bound`, requiring a type parameter + # to conform to (or inherit from) some other type. Appears in `where` + # clauses on generic declarations (e.g. Swift `where T: Equatable`). + bound_type_constraint: + type: type_expr + bound: type_expr + + # `infix operator +++` (and the like) — a declaration of a custom operator. + operator_syntax_declaration: + name: identifier + # The fixity specifier (`prefix`, `infix`, `postfix`), when applicable. + fixity?: fixity + # The declared precedence level, when present (e.g. Swift's + # `infix operator +++ : AdditionPrecedence`). + precedence?: expr + + # A class-like declaration: class, struct, interface (protocol), enum (or actor). + # The syntactic kind is carried as a `modifier` (e.g. "class", "struct", + # "interface", "enum", "extension"). The `"enum_case"` modifier additionally + # marks a declaration as an enum case with associated values. Extensions are + # represented as a class-like declaration with the `"extension"` modifier and + # no `name`; the extended type appears as a `base_type`. + class_like_declaration: + modifier*: modifier + name?: identifier + type_parameter*: type_parameter + type_constraint*: type_constraint + base_type*: base_type + member*: member + + # One of the base types of a class declaration. + # + # If the language has multiple kinds of base classes (e.g. extends/implements) the + # kind should be included as a modifier on this node. + base_type: + modifier*: modifier + type: type_expr + + constructor_declaration: + modifier*: modifier + name?: identifier + parameter*: parameter + body: block + + # A destructor / finalizer (Swift `deinit`, C++ `~T()`, etc.). + destructor_declaration: + modifier*: modifier + body: block + + # Declaration of a single accessor for a property (such as a getter, setter, + # or observer like Swift's `willSet`/`didSet`). + # + # Multiple accessors for the same property are emitted as a sequence of + # accessor_declaration nodes; every accessor after the first is tagged with + # a synthetic `chained_declaration` modifier so the grouping can be recovered + # downstream. Stored properties with observers are emitted as a + # variable_declaration followed by one accessor_declaration per observer + # (each observer also tagged with `chained_declaration`). + accessor_declaration: + modifier*: modifier + name: identifier + accessor_kind: accessor_kind + parameter*: parameter + type?: type_expr + return_type?: type_expr + body?: block + + # "get", "set", or a language-specific kind like "didSet" + accessor_kind: + + # Static or instance initializer block. That is, code that runs at initialization time. + initializer_declaration: + modifier*: modifier + body: block + + associated_type_declaration: + modifier*: modifier + name: identifier + bound?: type_expr + + named_type_expr: + qualifier?: type_expr + name: identifier + + generic_type_expr: + base: type_expr + type_argument*: type_expr + + # A tuple type such as `(Int, String)` or `(a: A, b: B)`. + tuple_type_expr: + element*: tuple_type_element + + # An element of a `tuple_type_expr`, optionally carrying a label. + tuple_type_element: + name?: identifier + type: type_expr + + # A function type such as `(Int, String) -> Bool` or `(x: Int) -> Bool`. + function_type_expr: + parameter*: parameter + return_type: type_expr + + # A modifier such as 'static', 'public', or 'async'. For now this is just a leaf node with a string value. + modifier: diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 595f56a0b39a..c32d748a7667 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -1,340 +1,902 @@ use codeql_extractor::extractor::simple; -use yeast::{build::BuildCtx, rule, DesugaringConfig, PhaseKind}; - -/// Names of output AST kinds that belong to the `expr` supertype. Kept in -/// sync with `ast_types.yml`. `unsupported_node` is intentionally omitted -/// because it is also a member of the `stmt` supertype. -const EXPR_KINDS: &[&str] = &[ - "name_expr", - "int_literal", - "string_literal", - "binary_expr", - "unary_expr", - "call_expr", - "member_access_expr", - "lambda_expr", -]; - -/// If `id` is an `expr`, wrap it in `expr_stmt` so it can sit in a `stmt` -/// position; otherwise return it unchanged. -fn wrap_expr_in_stmt(ctx: &mut BuildCtx, id: usize) -> usize { - let kind = ctx.ast.get_node(id).map(|n| n.kind()).unwrap_or(""); - if EXPR_KINDS.contains(&kind) { - yeast::tree!(ctx, (expr_stmt expr: {id})) - } else { - id - } -} +use yeast::{rule, DesugaringConfig, PhaseKind}; fn translation_rules() -> Vec { vec![ + // ---- Top-level ---- + // Capture all top-level statements, including unnamed tokens like `nil`. rule!( - (source_file (_)* @children) + (source_file statement: _* @children) => (top_level - body: {..children} + body: (block stmt: {..children}) ) ), - // ---- Binary expressions ---- - // Swift's parser produces a different node kind for each operator - // family, but the field shape (`lhs` / `op` / `rhs`) is uniform, so - // each maps onto `binary_expr`. + // New grammar wraps declarations in local/global wrappers. + rule!((global_declaration _ @inner) => {inner}), + rule!((local_declaration _ @inner) => {inner}), + // ---- Literals ---- + rule!((integer_literal) => (int_literal)), + rule!((hex_literal) => (int_literal)), + rule!((bin_literal) => (int_literal)), + rule!((oct_literal) => (int_literal)), + rule!((real_literal) => (float_literal)), + rule!((boolean_literal) => (boolean_literal)), + rule!("nil" => (keyword_literal)), + rule!((special_literal) => (keyword_literal)), + rule!((line_string_literal) => (string_literal)), + rule!((multi_line_string_literal) => (string_literal)), + rule!((raw_string_literal) => (string_literal)), + rule!((regex_literal) => (regex_literal)), + // ---- Names ---- + rule!((simple_identifier) @id => (name_expr identifier: (identifier #{id}))), + // A referenceable_operator (e.g. `+` used as a value, as in `reduce(0, +)`) + // is treated as a name reference to the operator symbol. + rule!((referenceable_operator) @op => (name_expr identifier: (identifier #{op}))), + // ---- Operators ---- + // All binary operators share the lhs/op/rhs shape. + rule!((additive_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((multiplicative_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((comparison_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((equality_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((conjunction_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((disjunction_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((infix_expression lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + // Range expression `a.. (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + // Open-ended ranges `a...` / `...b` + rule!((open_end_range_expression start: @l) => (unary_expr operator: (postfix_operator "...") operand: {l})), + rule!((open_start_range_expression end: @r) => (unary_expr operator: (prefix_operator "...") operand: {r})), + // Custom operator declaration: `[prefix|infix|postfix] operator OP [: PrecedenceGroup]`. + // The fixity keyword is an anonymous child of `operator_declaration`, so we + // dispatch on it with one rule per keyword. rule!( - (additive_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (operator_declaration "prefix" (referenceable_operator _ @op) (simple_identifier)? @prec) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (operator_syntax_declaration name: (identifier #{op}) fixity: (fixity "prefix") precedence: {..prec}) ), rule!( - (multiplicative_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (operator_declaration "postfix" (referenceable_operator _ @op) (simple_identifier)? @prec) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (operator_syntax_declaration name: (identifier #{op}) fixity: (fixity "postfix") precedence: {..prec}) ), rule!( - (comparison_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (operator_declaration "infix" (referenceable_operator _ @op) (simple_identifier)? @prec) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (operator_syntax_declaration + name: (identifier #{op}) + fixity: (fixity "infix") + precedence: {..prec}) ), + rule!((bitwise_operation lhs: @l op: @op rhs: @r) => (binary_expr left: {l} operator: (infix_operator #{op}) right: {r})), + rule!((nil_coalescing_expression value: @l if_nil: @r) => (binary_expr left: {l} operator: (infix_operator "??") right: {r})), + // Prefix unary operators + rule!((prefix_expression operation: @op target: @operand) => (unary_expr operator: (prefix_operator #{op}) operand: {operand})), + // Postfix unary operators + rule!((postfix_expression operation: @op target: @operand) => (unary_expr operator: (postfix_operator #{op}) operand: {operand})), + // Parenthesised single-value tuple is a grouping expression; pass through. + // Multi-value tuples become tuple_expr. + rule!((tuple_expression value: _* @v) => (tuple_expr element: {..v})), + // New grammar uses block.statement* directly. + rule!((block statement: _+ @stmts) => (block stmt: {..stmts})), + rule!((block) => (block)), + // ---- Variables ---- + // property_binding rules — these produce variable_declaration and/or accessor_declaration + // nodes for individual declarators. The outer property_declaration rule splices these out + // and attaches binding/modifiers from the parent. + + // Computed property with explicit accessors (get/set/modify) → + // a sequence of accessor_declaration nodes, each with the property name + // attached. Subsequent accessors will be tagged chained_declaration by + // the outer property_declaration rule. rule!( - (equality_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (property_binding + name: (pattern bound_identifier: @name) + computed_value: (computed_property accessor: _+ @accessors)) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + {..{ + let name_text = __yeast_ctx.ast.source_text(name.into()); + let acc_ids: Vec = accessors.iter().map(|&a| a.into()).collect(); + for &acc_id in &acc_ids { + let ident = __yeast_ctx.literal("identifier", &name_text); + __yeast_ctx.prepend_field(acc_id, "name", ident); + } + acc_ids + }} ), + // Computed property: shorthand getter (no explicit get/set, just statements) → + // a single accessor_declaration with kind "get". rule!( - (conjunction_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (property_binding + name: (pattern bound_identifier: @name) + computed_value: (computed_property statement: _* @body)) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (accessor_declaration + name: (identifier #{name}) + accessor_kind: (accessor_kind "get") + body: (block stmt: {..body})) ), + // Stored property with willSet/didSet observers (initializer optional) → + // variable_declaration followed by one accessor_declaration per observer, + // each carrying the property name. Subsequent items are tagged + // chained_declaration by the outer property_declaration rule. rule!( - (disjunction_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (property_binding + name: (pattern bound_identifier: @name) + value: _? @val + observers: (willset_didset_block willset: _? @ws didset: _? @ds)) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + {..{ + let name_text = __yeast_ctx.ast.source_text(name.into()); + let val_ids: Vec = val.iter().map(|&v| v.into()).collect(); + let mut obs_ids: Vec = Vec::new(); + obs_ids.extend(ws.iter().map(|&o| { let id: usize = o.into(); id })); + obs_ids.extend(ds.iter().map(|&o| { let id: usize = o.into(); id })); + let ident_for_var = __yeast_ctx.literal("identifier", &name_text); + let pat = __yeast_ctx.node("name_pattern", vec![("identifier", vec![ident_for_var])]); + let mut var_fields: Vec<(&str, Vec)> = vec![("pattern", vec![pat])]; + if !val_ids.is_empty() { + var_fields.push(("value", val_ids)); + } + let var_id = __yeast_ctx.node("variable_declaration", var_fields); + let mut result = vec![var_id]; + for obs_id in obs_ids { + let ident = __yeast_ctx.literal("identifier", &name_text); + __yeast_ctx.prepend_field(obs_id, "name", ident); + result.push(obs_id); + } + result + }} ), + // Plain property_binding with simple identifier name → variable_declaration rule!( - (nil_coalescing_expression - lhs: (_) @left - op: _ @operator - rhs: (_) @right) + (property_binding + name: (pattern bound_identifier: @name) + value: _? @val) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (variable_declaration + pattern: (name_pattern identifier: (identifier #{name})) + value: {..val}) ), + // Property_binding with a complex pattern (tuple destructuring etc.) rule!( - (range_expression - start: (_) @left - op: _ @operator - end: (_) @right) + (property_binding + name: @pat + value: _? @val) => - (binary_expr - left: {left} - operator: (operator #{operator}) - right: {right}) + (variable_declaration + pattern: {pat} + value: {..val}) ), - // ---- Unary expressions ---- + // property_declaration: splice declarators (each may translate to multiple nodes — + // variable_declaration and/or accessor_declaration), and attach the binding modifier + // (let/var) and any outer modifiers to each. All children after the first additionally + // get a synthetic chained_declaration modifier so the grouping can be recovered. rule!( - (prefix_expression - operation: _ @operator - target: (_) @operand) + (property_declaration + binding: (value_binding_pattern mutability: @binding_kind) + declarator: _* @decls + (modifiers)* @mods) => - (unary_expr - operand: {operand} - operator: (operator #{operator})) + {..{ + let binding_text = __yeast_ctx.ast.source_text(binding_kind.into()); + let mod_ids: Vec = mods.iter().map(|&m| m.into()).collect(); + let decl_ids: Vec = decls.iter().map(|&d| d.into()).collect(); + for (i, &decl_id) in decl_ids.iter().enumerate() { + if i > 0 { + let chained = __yeast_ctx.literal("modifier", "chained_declaration"); + __yeast_ctx.prepend_field(decl_id, "modifier", chained); + } + for &mod_id in mod_ids.iter().rev() { + __yeast_ctx.prepend_field(decl_id, "modifier", mod_id); + } + let binding_mod = __yeast_ctx.literal("modifier", &binding_text); + __yeast_ctx.prepend_field(decl_id, "modifier", binding_mod); + } + decl_ids + }} ), - // ---- Identifiers / name expressions ---- + // ---- Enums ---- + // enum_type_parameter → parameter (with optional name as pattern). rule!( - (simple_identifier) @name + (enum_type_parameter name: @name type: @ty) => - (name_expr - identifier: (identifier #{name})) + (parameter + pattern: (name_pattern identifier: (identifier #{name})) + type: {ty}) + ), + rule!( + (enum_type_parameter type: @ty) + => + (parameter type: {ty}) + ), + // enum_case_entry with associated values → class_like_declaration containing + // a constructor whose parameters are the data parameters. + rule!( + (enum_case_entry + name: @name + data_contents: (enum_type_parameters parameter: _* @params)) + => + (class_like_declaration + modifier: (modifier "enum_case") + name: (identifier #{name}) + member: (constructor_declaration parameter: {..params} body: (block))) + ), + // enum_case_entry with explicit raw value → variable_declaration with that value. + rule!( + (enum_case_entry name: @name raw_value: @val) + => + (variable_declaration + modifier: (modifier "enum_case") + pattern: (name_pattern identifier: (identifier #{name})) + value: {val}) + ), + // enum_case_entry without associated values → variable_declaration tagged enum_case. + rule!( + (enum_case_entry name: @name) + => + (variable_declaration + modifier: (modifier "enum_case") + pattern: (name_pattern identifier: (identifier #{name}))) + ), + // enum_entry: flatten case entries; attach outer modifiers to each, and + // chained_declaration on every entry after the first. + rule!( + (enum_entry case: _+ @cases (modifiers)* @mods) + => + {..{ + let mod_ids: Vec = mods.iter().map(|&m| m.into()).collect(); + let case_ids: Vec = cases.iter().map(|&c| c.into()).collect(); + for (i, &case_id) in case_ids.iter().enumerate() { + if i > 0 { + let chained = __yeast_ctx.literal("modifier", "chained_declaration"); + __yeast_ctx.prepend_field(case_id, "modifier", chained); + } + for &mod_id in mod_ids.iter().rev() { + __yeast_ctx.prepend_field(case_id, "modifier", mod_id); + } + } + case_ids + }} + ), + // Plain assignment: `x = expr` + rule!( + (assignment operator: "=" target: (directly_assignable_expression expr: @target) result: @value) + => + (assign_expr target: {target} value: {value}) + ), + // Compound assignment: `x += expr` etc. + rule!( + (assignment operator: @op target: (directly_assignable_expression expr: @target) result: @value) + => + (compound_assign_expr target: {target} operator: (infix_operator #{op}) value: {value}) + ), + // Unwrap `type` wrapper node + rule!((type name: @inner) => {inner}), + // `directly_assignable_expression` is just a wrapper; unwrap it + rule!((directly_assignable_expression expr: @inner) => {inner}), + // Pattern with bound_identifier → name_pattern + rule!((pattern bound_identifier: @name) => (name_pattern identifier: (identifier #{name}))), + // Tuple pattern (destructuring) + rule!((pattern (pattern)* @elems) => (tuple_pattern element: {..elems})), + // ---- Functions ---- + // Function declaration + // Function declaration (return type optional, body statements optional). + rule!( + (function_declaration + name: @name + parameter: _* @params + return_type: _? @ret + body: (block statement: _* @body_stmts)) + => + (function_declaration + name: (identifier #{name}) + parameter: {..params} + return_type: {..ret} + body: (block stmt: {..body_stmts})) + ), + // New grammar wraps parameters in function_parameter. + rule!((function_parameter parameter: @p) => {p}), + // Parameter with external name and type + rule!( + (parameter external_name: @ext name: @name) + => + (parameter + external_name: (identifier #{ext}) + pattern: (name_pattern identifier: (identifier #{name}))) + ), + rule!( + (parameter external_name: @ext name: @name type: @ty) + => + (parameter + external_name: (identifier #{ext}) + pattern: (name_pattern identifier: (identifier #{name})) + type: {ty}) + ), + // Parameter with just name and type (no external name) + rule!( + (parameter name: @name) + => + (parameter + pattern: (name_pattern identifier: (identifier #{name}))) ), - // ---- Literals ---- rule!( - (integer_literal) @lit + (parameter name: @name type: @ty) => - (int_literal #{lit}) + (parameter + pattern: (name_pattern identifier: (identifier #{name})) + type: {ty}) ), - // String literals: render the *raw* source text, including the - // surrounding quotes. Interpolations (e.g. `"hi \(x)"`) are not - // yet broken out into structured pieces \u2014 they show up as part - // of the literal's source text. + // Reference to a function, f(x:y:z:). This is parsed as a call with a single argument with multiple reference_specifier labels. + // We don't want downstream QL to try to handle this as a call_expr with a weird argument, so explicitly mark it as unsupported for now. rule!( - (line_string_literal) @lit + (call_expression suffix: (call_suffix arguments: (value_arguments argument: (value_argument reference_specifier: _+) @ref_arg))) => - (string_literal #{lit}) - ), // ---- Lambdas / closures ---- - // Map a `lambda_literal` whose body is a single statement to - // `lambda_expr`. Multi-statement bodies fall through to - // `unsupported_node` because `lambda_expr.body` is single-valued - // in the current `ast_types.yml`. Parameters from explicit-typed - // closures (`{ (x: Int) -> Int in ... }`) are not yet captured. + (unsupported_node) + ), + // Call expression: function(args...) + rule!( + (call_expression function: @func suffix: (call_suffix arguments: (value_arguments argument: (value_argument)* @args))) + => + (call_expr function: {func} argument: {..args}) + ), + // Value argument with label (value: _ matches both named nodes and anonymous tokens like nil) + rule!( + (value_argument name: (value_argument_label name: @label) value: @val) + => + (argument name: (identifier #{label}) value: {val}) + ), + // Value argument without label + rule!( + (value_argument value: @val) + => + (argument value: {val}) + ), + // Value argument with reference_specifier label (for getting a reference to a function, not calling it) + rule!( + (value_argument reference_specifier: (value_argument_label name: @label)) + => + (unsupported_node) + ), + // Navigation expression → member_access_expr + rule!( + (navigation_expression target: @target suffix: (navigation_suffix suffix: @member)) + => + (member_access_expr target: {target} member: (identifier #{member})) + ), + // Return / break / continue, one rule per keyword. + // The anonymous "return"/"break"/"continue" keywords are matched as + // string literals. + rule!((control_transfer_statement kind: "return" result: _? @val) => (return_expr value: {..val})), + rule!((control_transfer_statement kind: "break" result: @lbl) => (break_expr label: (identifier #{lbl}))), + rule!((control_transfer_statement kind: "break") => (break_expr)), + rule!((control_transfer_statement kind: "continue" result: @lbl) => (continue_expr label: (identifier #{lbl}))), + rule!((control_transfer_statement kind: "continue") => (continue_expr)), + rule!((control_transfer_statement kind: (throw_keyword) result: @val) => (throw_expr value: {val})), + // ---- Closures ---- + // Lambda literal with optional type header (parameters + optional return type). + // The return_type capture is optional, so this rule covers both cases. rule!( (lambda_literal - (statements (_) @body)) + attribute: _* @attrs + captures: (capture_list item: _* @captures)? + type: (lambda_function_type + params: (lambda_function_type_parameters parameter: _* @params) + return_type: _? @ret)? + statement: _* @body) + => + (function_expr + modifier: {..attrs} + capture_declaration: {..captures} + parameter: {..params} + return_type: {..ret} + body: (block stmt: {..body})) + ), + // capture_list_item with ownership modifier (e.g. [weak self], [unowned x]) + rule!( + (capture_list_item ownership: _? @ownership name: @name value: _? @val) + => + (variable_declaration + modifier: {..ownership} + pattern: (name_pattern identifier: (identifier #{name})) + value: {..val}) + ), + // Lambda parameter with type and optional external name + rule!( + (lambda_parameter external_name: @ext name: @name type: @ty) + => + (parameter + external_name: (identifier #{ext}) + pattern: (name_pattern identifier: (identifier #{name})) + type: {ty}) + ), + rule!( + (lambda_parameter name: @name type: @ty) => - (lambda_expr - body: {body}) + (parameter + pattern: (name_pattern identifier: (identifier #{name})) + type: {ty}) ), - // ---- Block / statement wrapping ---- - // A `(statements ...)` node corresponds to a brace-delimited block. - // Each child is mapped through translation; bare expression results - // get wrapped in `expr_stmt` so they fit the `body*: stmt` field. rule!( - (statements (_)* @stmts) + (lambda_parameter external_name: @ext name: @name) => - (block_stmt body: {..stmts.iter().copied().map(|n| - wrap_expr_in_stmt(&mut __yeast_ctx, n.into()) - ).collect::>()}) + (parameter + external_name: (identifier #{ext}) + pattern: (name_pattern identifier: (identifier #{name}))) ), - // ---- Calls and member access ---- - // Member access, e.g. `obj.member`. The Swift parser wraps the - // member name as `(navigation_suffix suffix: (simple_identifier))`. rule!( - (navigation_expression - target: (_) @target - suffix: (navigation_suffix - suffix: (simple_identifier) @member)) + (lambda_parameter name: @name) => - (member_access_expr - target: {target} - member: (identifier #{member})) + (parameter pattern: (name_pattern identifier: (identifier #{name}))) ), - // Function / method call. The callee is the first child of - // `call_expression`; the second is a `call_suffix` whose - // `value_arguments` (if present) hold the parenthesized args. A - // trailing closure (`call_suffix` with a `lambda_literal` child) - // is appended as a final argument. + // Call expression with trailing closure (no value_arguments) rule!( - (call_expression - (_) @callee - (call_suffix - (value_arguments - (value_argument value: (_) @args)*)? - (lambda_literal)? @trailing)) + (call_expression function: @func suffix: (call_suffix lambda: (lambda_literal) @closure)) => (call_expr - function: {callee} - argument: {..args} - argument: {..trailing} - ) + function: {func} + argument: (argument value: {closure})) ), - // ---- Guard statement ---- - // `guard let x = e else { ... }` — currently only handles the - // let-binding form. The Swift parser models the `let` keyword as a - // `value_binding_pattern` child of `condition`, followed by an - // unnamed `=` and the source expression. + // ---- Control flow ---- rule!( - (guard_statement - bound_identifier: (simple_identifier) @id - condition: (value_binding_pattern) - condition: (_) @value - (else) - (statements) @else_branch) + (if_statement condition: _* @cond body: @then_body else_branch: _? @else_stmts) + => + (if_expr + condition: {..cond}.reduce_left(first -> {first}, acc, elem -> (binary_expr operator: (infix_operator "&&") left: {acc} right: {elem})) + then: {then_body} + else: {..else_stmts}) + ), + // Guard statement + rule!( + (guard_statement condition: _* @cond body: (block statement: _* @else_stmts)) => (guard_if_stmt - condition: (let_pattern_condition - pattern: (var_pattern identifier: (identifier #{id})) - value: {value}) - else: {else_branch}) + condition: {..cond}.reduce_left(first -> {first}, acc, elem -> (binary_expr operator: (infix_operator "&&") left: {acc} right: {elem})) + else: (block stmt: {..else_stmts})) + ), + // Ternary expression → if_expr + rule!( + (ternary_expression condition: @cond if_true: @then_val if_false: @else_val) + => + (if_expr condition: {cond} then: {then_val} else: {else_val}) ), - // ---- If statement ---- - // if-let binding (with optional else branch). The Swift parser puts - // the bound name in `bound_identifier`, the `let` keyword as a - // `value_binding_pattern` child of `condition`, and the source - // expression as a separate child of `condition`. + // Switch statement rule!( - (if_statement - bound_identifier: (simple_identifier) @id - condition: (value_binding_pattern) - condition: (_) @value - (statements) @then - (else) - (_) @else_branch) + (switch_statement expr: @val entry: (switch_entry)* @cases) => - (if_stmt - condition: (let_pattern_condition - pattern: (var_pattern identifier: (identifier #{id})) - value: {value}) - then: {then} - else: {else_branch}) + (switch_expr value: {val} case: {..cases}) ), + // Switch entry with patterns and body rule!( - (if_statement - bound_identifier: (simple_identifier) @id - condition: (value_binding_pattern) - condition: (_) @value - (statements) @then) + (switch_entry pattern: (switch_pattern)* @pats statement: _* @body) => - (if_stmt - condition: (let_pattern_condition - pattern: (var_pattern identifier: (identifier #{id})) - value: {value}) - then: {then}) + (switch_case pattern: {..pats} body: (block stmt: {..body})) ), - // With explicit else branch (block or chained if). + // Switch entry: default case (no patterns) rule!( - (if_statement - condition: (_) @cond - (statements) @then - (else) - (_) @else_branch) + (switch_entry default: (default_keyword) statement: _* @body) => - (if_stmt - condition: (expr_condition expr: {cond}) - then: {then} - else: {else_branch}) + (switch_case body: (block stmt: {..body})) ), - // Without else branch. + // Switch pattern — unwrap to inner pattern + rule!((switch_pattern (pattern)* @inner) => {..inner}), + // if case let x = expr — the pattern is taken as-is (no Optional wrapping) rule!( - (if_statement - condition: (_) @cond - (statements) @then) + (if_let_binding "case" (value_binding_pattern) bound_identifier: @name _ @val) => - (if_stmt - condition: (expr_condition expr: {cond}) - then: {then}) - ), // ---- Patterns ---- - // The Swift parser uses a `pattern` node with a `bound_identifier` - // field for simple bindings such as `let x = ...`. + (pattern_guard_expr + value: {val} + pattern: (name_pattern identifier: (identifier #{name}))) + ), rule!( - (pattern bound_identifier: (simple_identifier) @id) + (if_let_binding + pattern: (pattern binding: (value_binding_pattern) bound_identifier: @name) + value: @val) => - (var_pattern - identifier: (identifier #{id})) + (pattern_guard_expr + value: {val} + pattern: (constructor_pattern + constructor: (shorthand_member_access_expr member: (identifier "some")) + argument: (name_pattern identifier: (identifier #{name})))) ), - // Inside tuple patterns, the inner `pattern` node holds a bare - // `simple_identifier` (with no `bound_identifier` field). + // Shorthand if let x (Swift 5.7+) — also semantically .some(x) rule!( - (pattern (simple_identifier) @id) + (if_let_binding + pattern: (pattern binding: (value_binding_pattern) bound_identifier: @name)) => - (var_pattern - identifier: (identifier #{id})) + (pattern_guard_expr + value: (name_expr identifier: (identifier #{name})) + pattern: (constructor_pattern + constructor: (shorthand_member_access_expr member: (identifier "some")) + argument: (name_pattern identifier: (identifier #{name})))) ), - // Tuple destructuring pattern, e.g. `let (a, b) = pair`. The parser - // emits a `pattern` node whose unnamed children are themselves - // `pattern` nodes. + // If-condition — unwrap (pass through the inner expression/pattern) + rule!((if_condition kind: @inner) => {inner}), + // ---- Loops ---- + // For-in loop with optional where-clause guard. rule!( - (pattern (pattern)+ @parts) + (for_statement + item: @pat + collection: @iter + where: (where_clause expr: @guard)? + body: (block statement: _* @body)) => - (tuple_pattern element: {..parts}) + (for_each_stmt + pattern: {pat} + iterable: {iter} + guard: {..guard} + body: (block stmt: {..body})) ), - // ---- Variable declarations ---- - // Handles single (`let x = e`), multiple (`let x = 1, y = 2`), - // and uninitialized (`var x: T`) bindings. + // While loop rule!( - (property_declaration - name: (_)* @pats - value: (_)* @vals) - => - (variable_declaration_stmt - variable_declarator: {..pats.iter().enumerate().map(|(i, &pat)| { - match vals.get(i).copied() { - Some(val) => yeast::tree!( - (variable_declarator - pattern: {pat} - value: {val})), - None => yeast::tree!( - (variable_declarator - pattern: {pat})), + (while_statement condition: _* @cond body: (block statement: _* @body)) + => + (while_stmt condition: {..cond}.reduce_left(first -> {first}, acc, elem -> (binary_expr operator: (infix_operator "&&") left: {acc} right: {elem})) body: (block stmt: {..body})) + ), + // Repeat-while loop + rule!( + (repeat_while_statement condition: _* @cond body: (block statement: _* @body)) + => + (do_while_stmt condition: {..cond}.reduce_left(first -> {first}, acc, elem -> (binary_expr operator: (infix_operator "&&") left: {acc} right: {elem})) body: (block stmt: {..body})) + ), + // Labeled statement (e.g. `outer: for ...`). Strip the trailing ':' from the label token. + rule!((labeled_statement label: (statement_label) @lbl statement: @stmt) => {..{ + let text = __yeast_ctx.ast.source_text(lbl.into()); + let name = __yeast_ctx.literal("identifier", &text[..text.len() - 1]); + vec![__yeast_ctx.node("labeled_stmt", vec![("label", vec![name]), ("stmt", vec![stmt.into()])])] + }}), + // ---- Collections ---- + // Array literal + rule!((array_literal element: _* @elems) => (array_literal element: {..elems})), + // Empty array literal + rule!((array_literal) => (array_literal)), + // Dictionary literal — zip keys and values into key_value_pairs + rule!( + (dictionary_literal key: _* @keys value: _* @vals) + => + (map_literal element: {..{ + keys.iter().zip(vals.iter()).map(|(&k, &v)| { + let k_id: usize = k.into(); + let v_id: usize = v.into(); + __yeast_ctx.node("key_value_pair", vec![ + ("key", vec![k_id]), + ("value", vec![v_id]), + ]) + }).collect::>() + }}) + ), + rule!((dictionary_literal element: _* @elems) => (map_literal element: {..elems})), + rule!((dictionary_literal_item key: @k value: @v) => (key_value_pair key: {k} value: {v})), + // ---- Optionals and errors ---- + // Optional chaining — unwrap the marker + rule!((optional_chain_marker expr: @inner) => {inner}), + // try/try?/try! expr → unary_expr with operator "try", "try?" or "try!" + rule!((try_expression (try_operator) @op expr: @inner) => (unary_expr operator: (prefix_operator #{op}) operand: {inner})), + rule!((try_expression operator: (try_operator) @op expr: @inner) => (unary_expr operator: (prefix_operator #{op}) operand: {inner})), + // Do-catch → try_expr + rule!( + (do_statement body: (block statement: _* @body) catch: (catch_block)* @catches) + => + (try_expr + body: (block stmt: {..body}) + catch_clause: {..catches}) + ), + // Catch block with bound identifier; optional where-clause guard. + rule!( + (catch_block + keyword: (catch_keyword) + error: (pattern bound_identifier: @name) + where: (where_clause expr: @guard)? + body: (block statement: _* @body)) + => + (catch_clause + pattern: (name_pattern identifier: (identifier #{name})) + guard: {..guard} + body: (block stmt: {..body})) + ), + // Catch block without error binding + rule!( + (catch_block keyword: (catch_keyword) body: (block statement: _* @body)) + => + (catch_clause body: (block stmt: {..body})) + ), + // Empty catch block: catch {} + rule!( + (catch_block (catch_keyword)) + => + (catch_clause body: (block)) + ), + // Catch block with unhandled pattern — preserve pattern; optional body. + rule!( + (catch_block keyword: (catch_keyword) error: @pat body: (block statement: _* @body)) + => + (catch_clause + pattern: {pat} + body: (block stmt: {..body})) + ), + // As expression (type cast) — as?, as! + rule!((as_expression (as_operator) @op expr: @val type: @ty) => (type_cast_expr expr: {val} operator: (infix_operator #{op}) type: {ty})), + // Check expression (`x is T`) → type_test_expr + rule!((check_expression op: @op target: @val type: @ty) => (type_test_expr expr: {val} operator: (infix_operator #{op}) type: {ty})), + // Await expression → unary_expr with operator "await" + rule!((await_expression expr: @val) => (unary_expr operator: (prefix_operator "await") operand: {val})), + // New grammar: identifier has part* and import has named fields. + rule!((identifier part: _* @parts) => {..parts}), + rule!( + (import_declaration name: (identifier part: _* @parts) modifiers: (modifiers)? @mods) + => + (import_declaration + path: {parts}.map(p -> (identifier #{p})) + modifier: {..mods}) + ), + // ---- Types and classes ---- + // Self expression → name_expr + rule!((self_expression) => (name_expr identifier: (identifier "self"))), + // Super expression → super_expr + rule!((super_expression) => (super_expr)), + // Modifiers — unwrap to individual modifier children + rule!((modifiers _* @mods) => {..mods}), + rule!((attribute) @m => (modifier #{m})), + rule!((visibility_modifier) @m => (modifier #{m})), + rule!((function_modifier) @m => (modifier #{m})), + rule!((member_modifier) @m => (modifier #{m})), + rule!((mutation_modifier) @m => (modifier #{m})), + rule!((ownership_modifier) @m => (modifier #{m})), + rule!((property_modifier) @m => (modifier #{m})), + rule!((parameter_modifier) @m => (modifier #{m})), + rule!((inheritance_modifier) @m => (modifier #{m})), + rule!((property_behavior_modifier) @m => (modifier #{m})), + // Type annotations — unwrap + rule!((type_annotation type: @inner) => {inner}), + // New grammar: user_type is split into simple_user_type parts. + // Keep a conservative textual fallback to avoid dropping type information. + rule!((user_type) @ty => (named_type_expr name: (identifier #{ty}))), + // Tuple type → tuple_type_expr + rule!((tuple_type element: _* @elems) => (tuple_type_expr element: {..elems})), + rule!((tuple_type_item name: @name type: @ty) => (tuple_type_element name: (identifier #{name}) type: {ty})), + rule!((tuple_type_item type: @ty) => (tuple_type_element type: {ty})), + // Array type `[T]` → generic_type_expr with Array base + rule!((array_type element: @e) => (generic_type_expr + base: (named_type_expr name: (identifier "Array")) + type_argument: {e})), + // Dictionary type `[K: V]` → generic_type_expr with Dictionary base + rule!((dictionary_type key: @k value: @v) => (generic_type_expr + base: (named_type_expr name: (identifier "Dictionary")) + type_argument: {k} + type_argument: {v})), + // Optional type `T?` → generic_type_expr with Optional base + rule!((optional_type wrapped: @w) => (generic_type_expr + base: (named_type_expr name: (identifier "Optional")) + type_argument: {w})), + // Function type `(Params) -> Ret` → function_type_expr. + rule!((function_type parameter: _* @ps return_type: @ret) => (function_type_expr parameter: {..ps} return_type: {ret})), + rule!((function_type_parameter name: @name type: @ty) => (parameter external_name: (identifier #{name}) type: {ty})), + rule!((function_type_parameter type: @ty) => (parameter type: {ty})), + // Selector expression: `#selector(inner)` -- not yet supported + rule!( + (selector_expression _ @inner) + => + (unsupported_node) + ), + // Key path expressions are currently unsupported. + rule!((key_path_expression) => (unsupported_node)), + // Inheritance specifier → base_type + rule!((inheritance_specifier inherits_from: @ty) => (base_type type: {ty})), + // Class declaration with body containing members + rule!( + (class_declaration + declaration_kind: @kind + name: @name + body: (class_body member: _* @members) + (inheritance_specifier)* @bases + (modifiers)* @mods) + => + (class_like_declaration + modifier: (modifier #{kind}) + modifier: {..mods} + name: (identifier #{name}) + base_type: {..bases} + member: {..members}) + ), + // Enum class declaration: same as a regular class but with an enum body. + rule!( + (class_declaration + declaration_kind: @kind + name: @name + body: (enum_class_body member: _* @members) + (inheritance_specifier)* @bases + (modifiers)* @mods) + => + (class_like_declaration + modifier: (modifier #{kind}) + modifier: {..mods} + name: (identifier #{name}) + base_type: {..bases} + member: {..members}) + ), + // Class declaration with empty body + rule!( + (class_declaration + declaration_kind: @kind + name: @name + body: _ + (inheritance_specifier)* @bases + (modifiers)* @mods) + => + (class_like_declaration + modifier: (modifier #{kind}) + modifier: {..mods} + name: (identifier #{name}) + base_type: {..bases}) + ), + // Protocol declaration + rule!( + (protocol_declaration + name: @name + body: (protocol_body member: _* @members) + (inheritance_specifier)* @bases + (modifiers)* @mods) + => + (class_like_declaration + modifier: (modifier "protocol") + modifier: {..mods} + name: (identifier #{name}) + base_type: {..bases} + member: {..members}) + ), + // Protocol function — return type and body statements both optional. + rule!( + (protocol_function_declaration + name: @name + (parameter)* @params + return_type: _? @ret + body: (block statement: _* @body_stmts)? + (modifiers)* @mods) + => + (function_declaration + modifier: {..mods} + name: (identifier #{name}) + parameter: {..params} + return_type: {..ret} + body: (block stmt: {..body_stmts})) + ), + // Init declaration → constructor_declaration. Body statements optional; + // body itself is also optional (protocol requirement). + rule!( + (init_declaration + (parameter)* @params + body: (block statement: _* @body_stmts)? + (modifiers)* @mods) + => + (constructor_declaration + modifier: {..mods} + parameter: {..params} + body: (block stmt: {..body_stmts})) + ), + // Deinit declaration → destructor_declaration. Body statements optional. + rule!( + (deinit_declaration + body: (block statement: _* @body_stmts) + (modifiers)* @mods) + => + (destructor_declaration + modifier: {..mods} + body: (block stmt: {..body_stmts})) + ), + // Typealias declaration + rule!( + (typealias_declaration name: @name value: @val (modifiers)* @mods) + => + (type_alias_declaration + modifier: {..mods} + name: (identifier #{name}) + r#type: {val}) + ), + // Subscript declaration (not yet supported -- grammar needs to distinguish plain calls from subscript calls) + rule!( + (subscript_declaration (parameter)* @params (modifiers)* @mods) + => + (unsupported_node) + ), + // Associated type declaration (with optional bound) + rule!( + (associatedtype_declaration name: @name inherits_from: _? @bound (modifiers)* @mods) + => + (associated_type_declaration + modifier: {..mods} + name: (identifier #{name}) + bound: {..bound}) + ), + // Protocol property declaration: translate each accessor requirement to an + // accessor_declaration without a body, carrying the property name and type. + // Subsequent accessors get chained_declaration (same flattening as computed properties). + rule!( + (protocol_property_declaration + name: (pattern bound_identifier: @name) + requirements: (protocol_property_requirements accessor: _+ @accessors) + type: _? @ty + (modifiers)* @mods) + => + {..{ + let name_text = __yeast_ctx.ast.source_text(name.into()); + let mod_ids: Vec = mods.iter().map(|&m| m.into()).collect(); + let ty_ids: Vec = ty.iter().map(|&t| t.into()).collect(); + let acc_ids: Vec = accessors.iter().map(|&a| a.into()).collect(); + for (i, &acc_id) in acc_ids.iter().enumerate() { + if i > 0 { + let chained = __yeast_ctx.literal("modifier", "chained_declaration"); + __yeast_ctx.prepend_field(acc_id, "modifier", chained); } - })}) + for &mod_id in mod_ids.iter().rev() { + __yeast_ctx.prepend_field(acc_id, "modifier", mod_id); + } + for &ty_id in ty_ids.iter().rev() { + __yeast_ctx.prepend_field(acc_id, "type", ty_id); + } + let ident = __yeast_ctx.literal("identifier", &name_text); + __yeast_ctx.prepend_field(acc_id, "name", ident); + } + acc_ids + }} + ), + // getter_specifier / setter_specifier → bodyless accessor_declaration + rule!((getter_specifier) => (accessor_declaration accessor_kind: (accessor_kind "get"))), + rule!((setter_specifier) => (accessor_declaration accessor_kind: (accessor_kind "set"))), + // protocol_property_requirements wrapper — should be consumed by above; fallback + rule!((protocol_property_requirements accessor: _* @accs) => {..accs}), + // Computed getter → accessor_declaration (body optional). + rule!( + (computed_getter body: (block statement: _* @body)?) + => + (accessor_declaration + accessor_kind: (accessor_kind "get") + body: (block stmt: {..body})) + ), + // Computed setter with explicit parameter name. + rule!( + (computed_setter parameter: @param body: (block statement: _* @body)) + => + (accessor_declaration + accessor_kind: (accessor_kind "set") + parameter: (parameter pattern: (name_pattern identifier: (identifier #{param}))) + body: (block stmt: {..body})) + ), + // Computed setter without explicit parameter name; body optional. + rule!( + (computed_setter body: (block statement: _* @body)?) + => + (accessor_declaration + accessor_kind: (accessor_kind "set") + body: (block stmt: {..body})) + ), + // Computed modify → accessor_declaration + rule!( + (computed_modify body: (block statement: _* @body)) + => + (accessor_declaration + accessor_kind: (accessor_kind "modify") + body: (block stmt: {..body})) + ), + // willset/didset block — spread to children + rule!((willset_didset_block _* @clauses) => {..clauses}), + // willset clause → accessor_declaration (body optional). + rule!( + (willset_clause body: (block statement: _* @body)?) + => + (accessor_declaration + accessor_kind: (accessor_kind "willSet") + body: (block stmt: {..body})) + ), + // didset clause → accessor_declaration (body optional). + rule!( + (didset_clause body: (block statement: _* @body)?) + => + (accessor_declaration + accessor_kind: (accessor_kind "didSet") + body: (block stmt: {..body})) ), + // Preprocessor conditionals — unsupported + rule!((diagnostic) => (unsupported_node)), // ---- Fallbacks ---- rule!( (_) diff --git a/unified/extractor/tests/corpus/swift/closures.txt b/unified/extractor/tests/corpus/swift/closures.txt index 0afea480a19f..37a2e50ecfdd 100644 --- a/unified/extractor/tests/corpus/swift/closures.txt +++ b/unified/extractor/tests/corpus/swift/closures.txt @@ -50,6 +50,35 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "f" + value: + function_expr + body: + block + stmt: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "x" + right: int_literal "2" + parameter: + parameter + pattern: + name_pattern + identifier: identifier "x" + type: + named_type_expr + name: identifier "Int" + return_type: + named_type_expr + name: identifier "Int" === Closure with shorthand parameters @@ -82,6 +111,26 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "f" + value: + function_expr + body: + block + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "$0" + right: + name_expr + identifier: identifier "$1" === Trailing closure @@ -114,6 +163,28 @@ source_file top_level body: + block + stmt: + call_expr + argument: + argument + value: + function_expr + body: + block + stmt: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "$0" + right: int_literal "2" + function: + member_access_expr + member: identifier "map" + target: + name_expr + identifier: identifier "xs" === Closure with capture list @@ -163,6 +234,31 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "f" + value: + function_expr + body: + block + stmt: + call_expr + function: + member_access_expr + member: identifier "doThing" + target: + name_expr + identifier: identifier "self" + capture_declaration: + variable_declaration + modifier: modifier "weak" + pattern: + name_pattern + identifier: identifier "self" === Multi-statement closure @@ -236,3 +332,46 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "f" + value: + function_expr + body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "y" + value: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "x" + right: int_literal "1" + return_expr + value: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "y" + right: int_literal "2" + parameter: + parameter + pattern: + name_pattern + identifier: identifier "x" + type: + named_type_expr + name: identifier "Int" + return_type: + named_type_expr + name: identifier "Int" diff --git a/unified/extractor/tests/corpus/swift/collections.txt b/unified/extractor/tests/corpus/swift/collections.txt index afafc1e69ef2..d311537d9753 100644 --- a/unified/extractor/tests/corpus/swift/collections.txt +++ b/unified/extractor/tests/corpus/swift/collections.txt @@ -28,6 +28,19 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "xs" + value: + array_literal + element: + int_literal "1" + int_literal "2" + int_literal "3" === Empty array literal with type @@ -68,6 +81,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "xs" + value: array_literal "[]" === Dictionary literal @@ -106,6 +127,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "d" + value: map_literal "[\"a\": 1, \"b\": 2]" === Set literal @@ -155,6 +184,19 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "s" + value: + array_literal + element: + int_literal "1" + int_literal "2" + int_literal "3" === Tuple literal @@ -191,6 +233,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "t" + value: tuple_expr "(1, \"two\", 3.0)" === Subscript access @@ -232,9 +282,21 @@ source_file top_level body: - unsupported_node "// TODO: tree-sitter-swift parses `xs[0]` as a call_expression (same shape" - unsupported_node "// as `xs(0)`), so the mapping currently produces a call_expr. Update the" - unsupported_node "// parser / add a separate subscript_expr node and remap when fixed." + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "first" + value: + call_expr + argument: + argument + value: int_literal "0" + function: + name_expr + identifier: identifier "xs" === Dictionary subscript @@ -276,8 +338,21 @@ source_file top_level body: - unsupported_node "// TODO: same parser issue as the array subscript case above —" - unsupported_node "// `d[\"key\"]` is parsed as `call_expression(d, (\"key\"))`." + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "v" + value: + call_expr + argument: + argument + value: string_literal "\"key\"" + function: + name_expr + identifier: identifier "d" === Tuple member access @@ -309,3 +384,16 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "n" + value: + member_access_expr + member: identifier "0" + target: + name_expr + identifier: identifier "t" diff --git a/unified/extractor/tests/corpus/swift/control-flow.txt b/unified/extractor/tests/corpus/swift/control-flow.txt index 600e1126cbff..3a8a2e3084ed 100644 --- a/unified/extractor/tests/corpus/swift/control-flow.txt +++ b/unified/extractor/tests/corpus/swift/control-flow.txt @@ -35,6 +35,28 @@ source_file top_level body: + block + stmt: + if_expr + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + then: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "x" + function: + name_expr + identifier: identifier "print" === If-else @@ -90,6 +112,43 @@ source_file top_level body: + block + stmt: + if_expr + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + else: + block + stmt: + call_expr + argument: + argument + value: + unary_expr + operand: + name_expr + identifier: identifier "x" + operator: prefix_operator "-" + function: + name_expr + identifier: identifier "print" + then: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "x" + function: + name_expr + identifier: identifier "print" === If-else-if chain @@ -165,6 +224,55 @@ source_file top_level body: + block + stmt: + if_expr + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + else: + if_expr + condition: + binary_expr + operator: infix_operator "<" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + else: + block + stmt: + call_expr + argument: + argument + value: int_literal "3" + function: + name_expr + identifier: identifier "print" + then: + block + stmt: + call_expr + argument: + argument + value: int_literal "2" + function: + name_expr + identifier: identifier "print" + then: + block + stmt: + call_expr + argument: + argument + value: int_literal "1" + function: + name_expr + identifier: identifier "print" === If-let optional binding @@ -207,6 +315,34 @@ source_file top_level body: + block + stmt: + if_expr + condition: + pattern_guard_expr + pattern: + constructor_pattern + argument: + name_pattern + identifier: identifier "value" + constructor: + shorthand_member_access_expr + member: identifier "some" + value: + name_expr + identifier: identifier "optional" + then: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "value" + function: + name_expr + identifier: identifier "print" === Guard let @@ -240,6 +376,25 @@ source_file top_level body: + block + stmt: + guard_if_stmt + condition: + pattern_guard_expr + pattern: + constructor_pattern + argument: + name_pattern + identifier: identifier "value" + constructor: + shorthand_member_access_expr + member: identifier "some" + value: + name_expr + identifier: identifier "optional" + else: + block + stmt: return_expr "return" === Ternary expression @@ -277,6 +432,27 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "y" + value: + if_expr + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + else: + unary_expr + operand: int_literal "1" + operator: prefix_operator "-" + then: int_literal "1" === Switch statement @@ -357,6 +533,46 @@ source_file top_level body: + block + stmt: + switch_expr + case: + switch_case + body: + block + stmt: + call_expr + argument: + argument + value: string_literal "\"one\"" + function: + name_expr + identifier: identifier "print" + switch_case + body: + block + stmt: + call_expr + argument: + argument + value: string_literal "\"two or three\"" + function: + name_expr + identifier: identifier "print" + switch_case + body: + block + stmt: + call_expr + argument: + argument + value: string_literal "\"other\"" + function: + name_expr + identifier: identifier "print" + value: + name_expr + identifier: identifier "x" === Switch with binding pattern @@ -445,3 +661,36 @@ source_file top_level body: + block + stmt: + switch_expr + case: + switch_case + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "r" + function: + name_expr + identifier: identifier "print" + switch_case + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "s" + function: + name_expr + identifier: identifier "print" + value: + name_expr + identifier: identifier "shape" diff --git a/unified/extractor/tests/corpus/swift/desugar.txt b/unified/extractor/tests/corpus/swift/desugar.txt index 9f9ffeb070a8..abf8a23e9ea0 100644 --- a/unified/extractor/tests/corpus/swift/desugar.txt +++ b/unified/extractor/tests/corpus/swift/desugar.txt @@ -17,6 +17,12 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "+" + left: int_literal "1" + right: int_literal "2" === Another additive expression is desugared @@ -37,3 +43,13 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "foo" + right: + name_expr + identifier: identifier "bar" diff --git a/unified/extractor/tests/corpus/swift/functions.txt b/unified/extractor/tests/corpus/swift/functions.txt index 0a8210a4cf76..97acbd4f4197 100644 --- a/unified/extractor/tests/corpus/swift/functions.txt +++ b/unified/extractor/tests/corpus/swift/functions.txt @@ -31,6 +31,20 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + call_expr + argument: + argument + value: string_literal "\"hello\"" + function: + name_expr + identifier: identifier "print" + name: identifier "greet" === Function with parameters and return type @@ -93,6 +107,37 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + return_expr + value: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" + name: identifier "add" + parameter: + parameter + external_name: identifier "_" + pattern: + name_pattern + identifier: identifier "a" + parameter + external_name: identifier "_" + pattern: + name_pattern + identifier: identifier "b" + return_type: + named_type_expr + name: identifier "Int" === Function with named parameters @@ -138,6 +183,28 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "name" + function: + name_expr + identifier: identifier "print" + name: identifier "greet" + parameter: + parameter + external_name: identifier "person" + pattern: + name_pattern + identifier: identifier "name" === Function with default parameter value @@ -185,6 +252,27 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "name" + function: + name_expr + identifier: identifier "print" + name: identifier "greet" + parameter: + parameter + pattern: + name_pattern + identifier: identifier "name" === Variadic function @@ -249,6 +337,38 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + return_expr + value: + call_expr + argument: + argument + value: int_literal "0" + argument + value: + name_expr + identifier: identifier "+" + function: + member_access_expr + member: identifier "reduce" + target: + name_expr + identifier: identifier "values" + name: identifier "sum" + parameter: + parameter + external_name: identifier "_" + pattern: + name_pattern + identifier: identifier "values" + return_type: + named_type_expr + name: identifier "Int" === Function call @@ -276,6 +396,17 @@ source_file top_level body: + block + stmt: + call_expr + argument: + argument + value: int_literal "1" + argument + value: int_literal "2" + function: + name_expr + identifier: identifier "foo" === Function call with labelled arguments @@ -306,6 +437,16 @@ source_file top_level body: + block + stmt: + call_expr + argument: + argument + name: identifier "person" + value: string_literal "\"Bob\"" + function: + name_expr + identifier: identifier "greet" === Method call @@ -336,6 +477,18 @@ source_file top_level body: + block + stmt: + call_expr + argument: + argument + value: int_literal "1" + function: + member_access_expr + member: identifier "append" + target: + name_expr + identifier: identifier "list" === Generic function @@ -387,3 +540,23 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + return_expr + value: + name_expr + identifier: identifier "x" + name: identifier "identity" + parameter: + parameter + external_name: identifier "_" + pattern: + name_pattern + identifier: identifier "x" + return_type: + named_type_expr + name: identifier "T" diff --git a/unified/extractor/tests/corpus/swift/literals.txt b/unified/extractor/tests/corpus/swift/literals.txt index 5044831a869b..bf14d6f99e3e 100644 --- a/unified/extractor/tests/corpus/swift/literals.txt +++ b/unified/extractor/tests/corpus/swift/literals.txt @@ -13,6 +13,8 @@ source_file top_level body: + block + stmt: int_literal "42" === Negative integer literal @@ -32,6 +34,11 @@ source_file top_level body: + block + stmt: + unary_expr + operand: int_literal "7" + operator: prefix_operator "-" === Floating-point literal @@ -48,6 +55,8 @@ source_file top_level body: + block + stmt: float_literal "3.14" === Boolean literals @@ -67,6 +76,10 @@ source_file top_level body: + block + stmt: + boolean_literal "true" + boolean_literal "false" === Nil literal @@ -83,6 +96,8 @@ source_file top_level body: + block + stmt: keyword_literal "nil" === String literal @@ -101,6 +116,8 @@ source_file top_level body: + block + stmt: string_literal "\"hello\"" === String with interpolation @@ -122,3 +139,5 @@ source_file top_level body: + block + stmt: string_literal "\"hello \\(name)\"" diff --git a/unified/extractor/tests/corpus/swift/loops.txt b/unified/extractor/tests/corpus/swift/loops.txt index 8b9f3410d35d..cb284ea94500 100644 --- a/unified/extractor/tests/corpus/swift/loops.txt +++ b/unified/extractor/tests/corpus/swift/loops.txt @@ -37,6 +37,30 @@ source_file top_level body: + block + stmt: + for_each_stmt + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "x" + function: + name_expr + identifier: identifier "print" + pattern: + name_pattern + identifier: identifier "x" + iterable: + array_literal + element: + int_literal "1" + int_literal "2" + int_literal "3" === For-in over range @@ -76,6 +100,29 @@ source_file top_level body: + block + stmt: + for_each_stmt + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "i" + function: + name_expr + identifier: identifier "print" + pattern: + name_pattern + identifier: identifier "i" + iterable: + binary_expr + operator: infix_operator "..<" + left: int_literal "0" + right: int_literal "10" === For-in with where clause @@ -119,6 +166,34 @@ source_file top_level body: + block + stmt: + for_each_stmt + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "x" + function: + name_expr + identifier: identifier "print" + pattern: + name_pattern + identifier: identifier "x" + guard: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + iterable: + name_expr + identifier: identifier "xs" === While loop @@ -154,6 +229,25 @@ source_file top_level body: + block + stmt: + while_stmt + body: + block + stmt: + compound_assign_expr + operator: infix_operator "-=" + target: + name_expr + identifier: identifier "x" + value: int_literal "1" + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" === Repeat-while loop @@ -189,6 +283,25 @@ source_file top_level body: + block + stmt: + do_while_stmt + body: + block + stmt: + compound_assign_expr + operator: infix_operator "-=" + target: + name_expr + identifier: identifier "x" + value: int_literal "1" + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" === Break and continue @@ -252,3 +365,46 @@ source_file top_level body: + block + stmt: + for_each_stmt + body: + block + stmt: + if_expr + condition: + binary_expr + operator: infix_operator "<" + left: + name_expr + identifier: identifier "x" + right: int_literal "0" + then: + block + stmt: continue_expr "continue" + if_expr + condition: + binary_expr + operator: infix_operator ">" + left: + name_expr + identifier: identifier "x" + right: int_literal "100" + then: + block + stmt: break_expr "break" + call_expr + argument: + argument + value: + name_expr + identifier: identifier "x" + function: + name_expr + identifier: identifier "print" + pattern: + name_pattern + identifier: identifier "x" + iterable: + name_expr + identifier: identifier "xs" diff --git a/unified/extractor/tests/corpus/swift/operators.txt b/unified/extractor/tests/corpus/swift/operators.txt index f1a4a5fcdb26..d912a1085dc5 100644 --- a/unified/extractor/tests/corpus/swift/operators.txt +++ b/unified/extractor/tests/corpus/swift/operators.txt @@ -17,6 +17,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Subtraction @@ -37,6 +47,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "-" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Multiplication @@ -57,6 +77,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Division @@ -77,6 +107,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "/" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Operator precedence: addition and multiplication @@ -101,6 +141,22 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "+" + left: + name_expr + identifier: identifier "a" + right: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "b" + right: + name_expr + identifier: identifier "c" === Parenthesised expression @@ -129,6 +185,14 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "*" + left: tuple_expr "(a + b)" + right: + name_expr + identifier: identifier "c" === Comparison @@ -149,6 +213,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "<" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Equality @@ -169,6 +243,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "==" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical and @@ -189,6 +273,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "&&" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical or @@ -209,6 +303,16 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "||" + left: + name_expr + identifier: identifier "a" + right: + name_expr + identifier: identifier "b" === Logical not @@ -228,6 +332,13 @@ source_file top_level body: + block + stmt: + unary_expr + operand: + name_expr + identifier: identifier "a" + operator: prefix_operator "!" === Range operator @@ -248,3 +359,9 @@ source_file top_level body: + block + stmt: + binary_expr + operator: infix_operator "..." + left: int_literal "1" + right: int_literal "10" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors.txt b/unified/extractor/tests/corpus/swift/optionals-and-errors.txt index 572e9181a681..c2f5583fa67b 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors.txt +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors.txt @@ -34,6 +34,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "x" + value: keyword_literal "nil" === Optional chaining @@ -74,6 +82,22 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "n" + value: + member_access_expr + member: identifier "bar" + target: + member_access_expr + member: identifier "foo" + target: + name_expr + identifier: identifier "obj" === Force unwrap @@ -103,6 +127,19 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "n" + value: + unary_expr + operand: + name_expr + identifier: identifier "opt" + operator: postfix_operator "!" === Nil-coalescing @@ -132,6 +169,20 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "n" + value: + binary_expr + operator: infix_operator "??" + left: + name_expr + identifier: identifier "opt" + right: int_literal "0" === Throwing function @@ -167,6 +218,18 @@ source_file top_level body: + block + stmt: + function_declaration + body: + block + stmt: + return_expr + value: string_literal "\"\"" + name: identifier "read" + return_type: + named_type_expr + name: identifier "String" === Do-catch @@ -216,6 +279,33 @@ source_file top_level body: + block + stmt: + try_expr + body: + block + stmt: + unary_expr + operand: + call_expr + function: + name_expr + identifier: identifier "foo" + operator: prefix_operator "try" + catch_clause: + catch_clause + body: + block + stmt: + call_expr + argument: + argument + value: + name_expr + identifier: identifier "error" + function: + name_expr + identifier: identifier "print" === Try? expression @@ -252,6 +342,21 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "result" + value: + unary_expr + operand: + call_expr + function: + name_expr + identifier: identifier "foo" + operator: prefix_operator "try?" === Try! expression @@ -288,3 +393,18 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "result" + value: + unary_expr + operand: + call_expr + function: + name_expr + identifier: identifier "foo" + operator: prefix_operator "try!" diff --git a/unified/extractor/tests/corpus/swift/types.txt b/unified/extractor/tests/corpus/swift/types.txt index 0bebaa1238f3..ebdc0ea15ab5 100644 --- a/unified/extractor/tests/corpus/swift/types.txt +++ b/unified/extractor/tests/corpus/swift/types.txt @@ -18,6 +18,11 @@ source_file top_level body: + block + stmt: + class_like_declaration + modifier: modifier "class" + name: identifier "Foo" === Class with stored properties @@ -79,6 +84,22 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "x" + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "y" + modifier: modifier "class" + name: identifier "Point" === Class with initializer @@ -152,6 +173,31 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "x" + constructor_declaration + body: + block + stmt: + assign_expr + target: + member_access_expr + member: identifier "x" + target: + name_expr + identifier: identifier "self" + value: + name_expr + identifier: identifier "x" + modifier: modifier "class" + name: identifier "Point" === Class with method @@ -200,6 +246,29 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "n" + value: int_literal "0" + function_declaration + body: + block + stmt: + compound_assign_expr + operator: infix_operator "+=" + target: + name_expr + identifier: identifier "n" + value: int_literal "1" + name: identifier "bump" + modifier: modifier "class" + name: identifier "Counter" === Class inheritance @@ -228,6 +297,11 @@ source_file top_level body: + block + stmt: + class_like_declaration + modifier: modifier "class" + name: identifier "Dog" === Struct @@ -289,6 +363,22 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "x" + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "y" + modifier: modifier "struct" + name: identifier "Point" === Enum with cases @@ -332,6 +422,32 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "enum_case" + pattern: + name_pattern + identifier: identifier "north" + variable_declaration + modifier: modifier "enum_case" + pattern: + name_pattern + identifier: identifier "south" + variable_declaration + modifier: modifier "enum_case" + pattern: + name_pattern + identifier: identifier "east" + variable_declaration + modifier: modifier "enum_case" + pattern: + name_pattern + identifier: identifier "west" + modifier: modifier "enum" + name: identifier "Direction" === Enum with associated values @@ -389,6 +505,40 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + class_like_declaration + member: + constructor_declaration + body: block "circle(radius: Double)" + parameter: + parameter + pattern: + name_pattern + identifier: identifier "radius" + type: + named_type_expr + name: identifier "Double" + modifier: modifier "enum_case" + name: identifier "circle" + class_like_declaration + member: + constructor_declaration + body: block "square(side: Double)" + parameter: + parameter + pattern: + name_pattern + identifier: identifier "side" + type: + named_type_expr + name: identifier "Double" + modifier: modifier "enum_case" + name: identifier "square" + modifier: modifier "enum" + name: identifier "Shape" === Protocol declaration @@ -414,6 +564,15 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + function_declaration + body: block "func draw()" + name: identifier "draw" + modifier: modifier "protocol" + name: identifier "Drawable" === Extension @@ -463,6 +622,30 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + function_declaration + body: + block + stmt: + return_expr + value: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "self" + right: + name_expr + identifier: identifier "self" + name: identifier "squared" + return_type: + named_type_expr + name: identifier "Int" + modifier: modifier "extension" + name: identifier "Int" === Computed property @@ -555,6 +738,39 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "w" + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "h" + accessor_declaration + body: + block + stmt: + return_expr + value: + binary_expr + operator: infix_operator "*" + left: + name_expr + identifier: identifier "w" + right: + name_expr + identifier: identifier "h" + modifier: modifier "var" + name: identifier "area" + accessor_kind: accessor_kind "get" + modifier: modifier "class" + name: identifier "Rect" === Property with getter and setter @@ -639,3 +855,42 @@ source_file top_level body: + block + stmt: + class_like_declaration + member: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "_v" + value: int_literal "0" + accessor_declaration + body: + block + stmt: + return_expr + value: + name_expr + identifier: identifier "_v" + modifier: modifier "var" + name: identifier "v" + accessor_kind: accessor_kind "get" + accessor_declaration + body: + block + stmt: + assign_expr + target: + name_expr + identifier: identifier "_v" + value: + name_expr + identifier: identifier "newValue" + modifier: + modifier "var" + modifier "chained_declaration" + name: identifier "v" + accessor_kind: accessor_kind "set" + modifier: modifier "class" + name: identifier "Box" diff --git a/unified/extractor/tests/corpus/swift/variables.txt b/unified/extractor/tests/corpus/swift/variables.txt index 1911ddd02b1e..5c51128a1f73 100644 --- a/unified/extractor/tests/corpus/swift/variables.txt +++ b/unified/extractor/tests/corpus/swift/variables.txt @@ -23,6 +23,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "x" + value: int_literal "1" === Var binding @@ -49,6 +57,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "x" + value: int_literal "1" === Let with type annotation @@ -84,6 +100,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "x" + value: int_literal "1" === Var without initialiser @@ -118,6 +142,13 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "var" + pattern: + name_pattern + identifier: identifier "x" === Tuple destructuring binding @@ -154,6 +185,14 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: tuple_pattern "(a, b)" + value: + name_expr + identifier: identifier "pair" === Multiple bindings on one line @@ -185,6 +224,22 @@ source_file top_level body: + block + stmt: + variable_declaration + modifier: modifier "let" + pattern: + name_pattern + identifier: identifier "x" + value: int_literal "1" + variable_declaration + modifier: + modifier "let" + modifier "chained_declaration" + pattern: + name_pattern + identifier: identifier "y" + value: int_literal "2" === Assignment @@ -207,6 +262,13 @@ source_file top_level body: + block + stmt: + assign_expr + target: + name_expr + identifier: identifier "x" + value: int_literal "1" === Compound assignment @@ -229,3 +291,11 @@ source_file top_level body: + block + stmt: + compound_assign_expr + operator: infix_operator "+=" + target: + name_expr + identifier: identifier "x" + value: int_literal "1" diff --git a/unified/ql/lib/codeql/unified/Ast.qll b/unified/ql/lib/codeql/unified/Ast.qll index d9060c26f0f2..654daa2ef73c 100644 --- a/unified/ql/lib/codeql/unified/Ast.qll +++ b/unified/ql/lib/codeql/unified/Ast.qll @@ -81,20 +81,139 @@ module Unified { ) } - /** A class representing `apply_pattern` nodes. */ - class ApplyPattern extends @unified_apply_pattern, AstNode { + /** A class representing `accessor_declaration` nodes. */ + class AccessorDeclaration extends @unified_accessor_declaration, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "ApplyPattern" } + final override string getAPrimaryQlClass() { result = "AccessorDeclaration" } - /** Gets the node corresponding to the field `argument`. */ - final Pattern getArgument(int i) { unified_apply_pattern_argument(this, i, result) } + /** Gets the node corresponding to the field `accessor_kind`. */ + final AccessorKind getAccessorKind() { unified_accessor_declaration_def(this, result, _) } - /** Gets the node corresponding to the field `constructor`. */ - final Expr getConstructor() { unified_apply_pattern_def(this, result) } + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_accessor_declaration_body(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_accessor_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_accessor_declaration_def(this, _, result) } + + /** Gets the node corresponding to the field `parameter`. */ + final Parameter getParameter(int i) { unified_accessor_declaration_parameter(this, i, result) } + + /** Gets the node corresponding to the field `return_type`. */ + final TypeExpr getReturnType() { unified_accessor_declaration_return_type(this, result) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_accessor_declaration_type(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_accessor_declaration_def(this, result, _) or + unified_accessor_declaration_body(this, result) or + unified_accessor_declaration_modifier(this, _, result) or + unified_accessor_declaration_def(this, _, result) or + unified_accessor_declaration_parameter(this, _, result) or + unified_accessor_declaration_return_type(this, result) or + unified_accessor_declaration_type(this, result) + } + } + + /** A class representing `accessor_kind` tokens. */ + class AccessorKind extends @unified_token_accessor_kind, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "AccessorKind" } + } + + /** A class representing `argument` nodes. */ + class Argument extends @unified_argument, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Argument" } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_argument_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_argument_name(this, result) } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_argument_value(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_argument_modifier(this, _, result) or + unified_argument_name(this, result) or + unified_argument_value(this, result) + } + } + + /** A class representing `array_literal` nodes. */ + class ArrayLiteral extends @unified_array_literal, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ArrayLiteral" } + + /** Gets the node corresponding to the field `element`. */ + final Expr getElement(int i) { unified_array_literal_element(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_array_literal_element(this, _, result) } + } + + /** A class representing `assign_expr` nodes. */ + class AssignExpr extends @unified_assign_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "AssignExpr" } + + /** Gets the node corresponding to the field `target`. */ + final ExprOrPattern getTarget() { unified_assign_expr_def(this, result, _) } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_assign_expr_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_apply_pattern_argument(this, _, result) or unified_apply_pattern_def(this, result) + unified_assign_expr_def(this, result, _) or unified_assign_expr_def(this, _, result) + } + } + + /** A class representing `associated_type_declaration` nodes. */ + class AssociatedTypeDeclaration extends @unified_associated_type_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "AssociatedTypeDeclaration" } + + /** Gets the node corresponding to the field `bound`. */ + final TypeExpr getBound() { unified_associated_type_declaration_bound(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { + unified_associated_type_declaration_modifier(this, i, result) + } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_associated_type_declaration_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_associated_type_declaration_bound(this, result) or + unified_associated_type_declaration_modifier(this, _, result) or + unified_associated_type_declaration_def(this, result) + } + } + + /** A class representing `base_type` nodes. */ + class BaseType extends @unified_base_type, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BaseType" } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_base_type_modifier(this, i, result) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_base_type_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_base_type_modifier(this, _, result) or unified_base_type_def(this, result) } } @@ -107,7 +226,7 @@ module Unified { final Expr getLeft() { unified_binary_expr_def(this, result, _, _) } /** Gets the node corresponding to the field `operator`. */ - final Operator getOperator() { unified_binary_expr_def(this, _, result, _) } + final InfixOperator getOperator() { unified_binary_expr_def(this, _, result, _) } /** Gets the node corresponding to the field `right`. */ final Expr getRight() { unified_binary_expr_def(this, _, _, result) } @@ -120,16 +239,52 @@ module Unified { } } - /** A class representing `block_stmt` nodes. */ - class BlockStmt extends @unified_block_stmt, AstNode { + /** A class representing `block` nodes. */ + class Block extends @unified_block, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "BlockStmt" } + final override string getAPrimaryQlClass() { result = "Block" } - /** Gets the node corresponding to the field `body`. */ - final Stmt getBody(int i) { unified_block_stmt_body(this, i, result) } + /** Gets the node corresponding to the field `stmt`. */ + final Stmt getStmt(int i) { unified_block_stmt(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_block_stmt(this, _, result) } + } + + /** A class representing `boolean_literal` tokens. */ + class BooleanLiteral extends @unified_token_boolean_literal, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BooleanLiteral" } + } + + /** A class representing `bound_type_constraint` nodes. */ + class BoundTypeConstraint extends @unified_bound_type_constraint, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BoundTypeConstraint" } + + /** Gets the node corresponding to the field `bound`. */ + final TypeExpr getBound() { unified_bound_type_constraint_def(this, result, _) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_bound_type_constraint_def(this, _, result) } /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_block_stmt_body(this, _, result) } + final override AstNode getAFieldOrChild() { + unified_bound_type_constraint_def(this, result, _) or + unified_bound_type_constraint_def(this, _, result) + } + } + + /** A class representing `break_expr` nodes. */ + class BreakExpr extends @unified_break_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "BreakExpr" } + + /** Gets the node corresponding to the field `label`. */ + final Identifier getLabel() { unified_break_expr_label(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_break_expr_label(this, result) } } /** A class representing `call_expr` nodes. */ @@ -138,49 +293,387 @@ module Unified { final override string getAPrimaryQlClass() { result = "CallExpr" } /** Gets the node corresponding to the field `argument`. */ - final Expr getArgument(int i) { unified_call_expr_argument(this, i, result) } + final Argument getArgument(int i) { unified_call_expr_argument(this, i, result) } /** Gets the node corresponding to the field `function`. */ - final Expr getFunction() { unified_call_expr_def(this, result) } + final ExprOrType getFunction() { unified_call_expr_def(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_call_expr_modifier(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_call_expr_argument(this, _, result) or + unified_call_expr_def(this, result) or + unified_call_expr_modifier(this, _, result) + } + } + + /** A class representing `catch_clause` nodes. */ + class CatchClause extends @unified_catch_clause, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "CatchClause" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_catch_clause_def(this, result) } + + /** Gets the node corresponding to the field `guard`. */ + final Expr getGuard() { unified_catch_clause_guard(this, result) } + + /** Gets the node corresponding to the field `pattern`. */ + final Pattern getPattern() { unified_catch_clause_pattern(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_catch_clause_def(this, result) or + unified_catch_clause_guard(this, result) or + unified_catch_clause_pattern(this, result) + } + } + + /** A class representing `class_like_declaration` nodes. */ + class ClassLikeDeclaration extends @unified_class_like_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ClassLikeDeclaration" } + + /** Gets the node corresponding to the field `base_type`. */ + final BaseType getBaseType(int i) { unified_class_like_declaration_base_type(this, i, result) } + + /** Gets the node corresponding to the field `member`. */ + final Member getMember(int i) { unified_class_like_declaration_member(this, i, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_class_like_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_class_like_declaration_name(this, result) } + + /** Gets the node corresponding to the field `type_constraint`. */ + final TypeConstraint getTypeConstraint(int i) { + unified_class_like_declaration_type_constraint(this, i, result) + } + + /** Gets the node corresponding to the field `type_parameter`. */ + final TypeParameter getTypeParameter(int i) { + unified_class_like_declaration_type_parameter(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_class_like_declaration_base_type(this, _, result) or + unified_class_like_declaration_member(this, _, result) or + unified_class_like_declaration_modifier(this, _, result) or + unified_class_like_declaration_name(this, result) or + unified_class_like_declaration_type_constraint(this, _, result) or + unified_class_like_declaration_type_parameter(this, _, result) + } + } + + /** A class representing `compound_assign_expr` nodes. */ + class CompoundAssignExpr extends @unified_compound_assign_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "CompoundAssignExpr" } + + /** Gets the node corresponding to the field `operator`. */ + final InfixOperator getOperator() { unified_compound_assign_expr_def(this, result, _, _) } + + /** Gets the node corresponding to the field `target`. */ + final Expr getTarget() { unified_compound_assign_expr_def(this, _, result, _) } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_compound_assign_expr_def(this, _, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_call_expr_argument(this, _, result) or unified_call_expr_def(this, result) + unified_compound_assign_expr_def(this, result, _, _) or + unified_compound_assign_expr_def(this, _, result, _) or + unified_compound_assign_expr_def(this, _, _, result) } } - class Condition extends @unified_condition, AstNode { } + /** A class representing `constructor_declaration` nodes. */ + class ConstructorDeclaration extends @unified_constructor_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ConstructorDeclaration" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_constructor_declaration_def(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_constructor_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_constructor_declaration_name(this, result) } + + /** Gets the node corresponding to the field `parameter`. */ + final Parameter getParameter(int i) { + unified_constructor_declaration_parameter(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_constructor_declaration_def(this, result) or + unified_constructor_declaration_modifier(this, _, result) or + unified_constructor_declaration_name(this, result) or + unified_constructor_declaration_parameter(this, _, result) + } + } + + /** A class representing `constructor_pattern` nodes. */ + class ConstructorPattern extends @unified_constructor_pattern, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ConstructorPattern" } + + /** Gets the node corresponding to the field `argument`. */ + final Pattern getArgument(int i) { unified_constructor_pattern_argument(this, i, result) } + + /** Gets the node corresponding to the field `constructor`. */ + final Expr getConstructor() { unified_constructor_pattern_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_constructor_pattern_argument(this, _, result) or + unified_constructor_pattern_def(this, result) + } + } + + /** A class representing `continue_expr` nodes. */ + class ContinueExpr extends @unified_continue_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ContinueExpr" } + + /** Gets the node corresponding to the field `label`. */ + final Identifier getLabel() { unified_continue_expr_label(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_continue_expr_label(this, result) } + } + + /** A class representing `destructor_declaration` nodes. */ + class DestructorDeclaration extends @unified_destructor_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "DestructorDeclaration" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_destructor_declaration_def(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_destructor_declaration_modifier(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_destructor_declaration_def(this, result) or + unified_destructor_declaration_modifier(this, _, result) + } + } - /** A class representing `empty_stmt` tokens. */ - class EmptyStmt extends @unified_token_empty_stmt, Token { + /** A class representing `do_while_stmt` nodes. */ + class DoWhileStmt extends @unified_do_while_stmt, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "EmptyStmt" } + final override string getAPrimaryQlClass() { result = "DoWhileStmt" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_do_while_stmt_body(this, result) } + + /** Gets the node corresponding to the field `condition`. */ + final Expr getCondition() { unified_do_while_stmt_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_do_while_stmt_body(this, result) or unified_do_while_stmt_def(this, result) + } + } + + /** A class representing `empty_expr` tokens. */ + class EmptyExpr extends @unified_token_empty_expr, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "EmptyExpr" } + } + + /** A class representing `equality_type_constraint` nodes. */ + class EqualityTypeConstraint extends @unified_equality_type_constraint, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "EqualityTypeConstraint" } + + /** Gets the node corresponding to the field `left`. */ + final TypeExpr getLeft() { unified_equality_type_constraint_def(this, result, _) } + + /** Gets the node corresponding to the field `right`. */ + final TypeExpr getRight() { unified_equality_type_constraint_def(this, _, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_equality_type_constraint_def(this, result, _) or + unified_equality_type_constraint_def(this, _, result) + } } class Expr extends @unified_expr, AstNode { } - /** A class representing `expr_condition` nodes. */ - class ExprCondition extends @unified_expr_condition, AstNode { + /** A class representing `expr_equality_pattern` nodes. */ + class ExprEqualityPattern extends @unified_expr_equality_pattern, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "ExprCondition" } + final override string getAPrimaryQlClass() { result = "ExprEqualityPattern" } /** Gets the node corresponding to the field `expr`. */ - final Expr getExpr() { unified_expr_condition_def(this, result) } + final Expr getExpr() { unified_expr_equality_pattern_def(this, result) } /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_expr_condition_def(this, result) } + final override AstNode getAFieldOrChild() { unified_expr_equality_pattern_def(this, result) } } - /** A class representing `expr_stmt` nodes. */ - class ExprStmt extends @unified_expr_stmt, AstNode { + class ExprOrPattern extends @unified_expr_or_pattern, AstNode { } + + class ExprOrType extends @unified_expr_or_type, AstNode { } + + /** A class representing `fixity` tokens. */ + class Fixity extends @unified_token_fixity, Token { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "ExprStmt" } + final override string getAPrimaryQlClass() { result = "Fixity" } + } - /** Gets the node corresponding to the field `expr`. */ - final Expr getExpr() { unified_expr_stmt_def(this, result) } + /** A class representing `float_literal` tokens. */ + class FloatLiteral extends @unified_token_float_literal, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "FloatLiteral" } + } + + /** A class representing `for_each_stmt` nodes. */ + class ForEachStmt extends @unified_for_each_stmt, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ForEachStmt" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_for_each_stmt_body(this, result) } + + /** Gets the node corresponding to the field `guard`. */ + final Expr getGuard() { unified_for_each_stmt_guard(this, result) } + + /** Gets the node corresponding to the field `iterable`. */ + final Expr getIterable() { unified_for_each_stmt_def(this, result, _) } + + /** Gets the node corresponding to the field `pattern`. */ + final Pattern getPattern() { unified_for_each_stmt_def(this, _, result) } /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_expr_stmt_def(this, result) } + final override AstNode getAFieldOrChild() { + unified_for_each_stmt_body(this, result) or + unified_for_each_stmt_guard(this, result) or + unified_for_each_stmt_def(this, result, _) or + unified_for_each_stmt_def(this, _, result) + } + } + + /** A class representing `function_declaration` nodes. */ + class FunctionDeclaration extends @unified_function_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "FunctionDeclaration" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_function_declaration_body(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_function_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_function_declaration_def(this, result) } + + /** Gets the node corresponding to the field `parameter`. */ + final Parameter getParameter(int i) { unified_function_declaration_parameter(this, i, result) } + + /** Gets the node corresponding to the field `return_type`. */ + final TypeExpr getReturnType() { unified_function_declaration_return_type(this, result) } + + /** Gets the node corresponding to the field `type_constraint`. */ + final TypeConstraint getTypeConstraint(int i) { + unified_function_declaration_type_constraint(this, i, result) + } + + /** Gets the node corresponding to the field `type_parameter`. */ + final TypeParameter getTypeParameter(int i) { + unified_function_declaration_type_parameter(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_function_declaration_body(this, result) or + unified_function_declaration_modifier(this, _, result) or + unified_function_declaration_def(this, result) or + unified_function_declaration_parameter(this, _, result) or + unified_function_declaration_return_type(this, result) or + unified_function_declaration_type_constraint(this, _, result) or + unified_function_declaration_type_parameter(this, _, result) + } + } + + /** A class representing `function_expr` nodes. */ + class FunctionExpr extends @unified_function_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "FunctionExpr" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_function_expr_def(this, result) } + + /** Gets the node corresponding to the field `capture_declaration`. */ + final VariableDeclaration getCaptureDeclaration(int i) { + unified_function_expr_capture_declaration(this, i, result) + } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_function_expr_modifier(this, i, result) } + + /** Gets the node corresponding to the field `parameter`. */ + final Parameter getParameter(int i) { unified_function_expr_parameter(this, i, result) } + + /** Gets the node corresponding to the field `return_type`. */ + final TypeExpr getReturnType() { unified_function_expr_return_type(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_function_expr_def(this, result) or + unified_function_expr_capture_declaration(this, _, result) or + unified_function_expr_modifier(this, _, result) or + unified_function_expr_parameter(this, _, result) or + unified_function_expr_return_type(this, result) + } + } + + /** A class representing `function_type_expr` nodes. */ + class FunctionTypeExpr extends @unified_function_type_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "FunctionTypeExpr" } + + /** Gets the node corresponding to the field `parameter`. */ + final Parameter getParameter(int i) { unified_function_type_expr_parameter(this, i, result) } + + /** Gets the node corresponding to the field `return_type`. */ + final TypeExpr getReturnType() { unified_function_type_expr_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_function_type_expr_parameter(this, _, result) or + unified_function_type_expr_def(this, result) + } + } + + /** A class representing `generic_type_expr` nodes. */ + class GenericTypeExpr extends @unified_generic_type_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "GenericTypeExpr" } + + /** Gets the node corresponding to the field `base`. */ + final TypeExpr getBase() { unified_generic_type_expr_def(this, result) } + + /** Gets the node corresponding to the field `type_argument`. */ + final TypeExpr getTypeArgument(int i) { + unified_generic_type_expr_type_argument(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_generic_type_expr_def(this, result) or + unified_generic_type_expr_type_argument(this, _, result) + } } /** A class representing `guard_if_stmt` nodes. */ @@ -189,10 +682,10 @@ module Unified { final override string getAPrimaryQlClass() { result = "GuardIfStmt" } /** Gets the node corresponding to the field `condition`. */ - final Condition getCondition() { unified_guard_if_stmt_def(this, result, _) } + final Expr getCondition() { unified_guard_if_stmt_def(this, result, _) } /** Gets the node corresponding to the field `else`. */ - final Stmt getElse() { unified_guard_if_stmt_def(this, _, result) } + final Block getElse() { unified_guard_if_stmt_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { @@ -206,25 +699,25 @@ module Unified { final override string getAPrimaryQlClass() { result = "Identifier" } } - /** A class representing `if_stmt` nodes. */ - class IfStmt extends @unified_if_stmt, AstNode { + /** A class representing `if_expr` nodes. */ + class IfExpr extends @unified_if_expr, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "IfStmt" } + final override string getAPrimaryQlClass() { result = "IfExpr" } /** Gets the node corresponding to the field `condition`. */ - final Condition getCondition() { unified_if_stmt_def(this, result) } + final Expr getCondition() { unified_if_expr_def(this, result) } /** Gets the node corresponding to the field `else`. */ - final Stmt getElse() { unified_if_stmt_else(this, result) } + final Expr getElse() { unified_if_expr_else(this, result) } /** Gets the node corresponding to the field `then`. */ - final Stmt getThen() { unified_if_stmt_then(this, result) } + final Expr getThen() { unified_if_expr_then(this, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_if_stmt_def(this, result) or - unified_if_stmt_else(this, result) or - unified_if_stmt_then(this, result) + unified_if_expr_def(this, result) or + unified_if_expr_else(this, result) or + unified_if_expr_then(this, result) } } @@ -234,47 +727,108 @@ module Unified { final override string getAPrimaryQlClass() { result = "IgnorePattern" } } + /** A class representing `import_declaration` nodes. */ + class ImportDeclaration extends @unified_import_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ImportDeclaration" } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_import_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `path`. */ + final Identifier getPath(int i) { unified_import_declaration_path(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_import_declaration_modifier(this, _, result) or + unified_import_declaration_path(this, _, result) + } + } + + /** A class representing `infix_operator` tokens. */ + class InfixOperator extends @unified_token_infix_operator, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "InfixOperator" } + } + + /** A class representing `initializer_declaration` nodes. */ + class InitializerDeclaration extends @unified_initializer_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "InitializerDeclaration" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_initializer_declaration_def(this, result) } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_initializer_declaration_modifier(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_initializer_declaration_def(this, result) or + unified_initializer_declaration_modifier(this, _, result) + } + } + /** A class representing `int_literal` tokens. */ class IntLiteral extends @unified_token_int_literal, Token { /** Gets the name of the primary QL class for this element. */ final override string getAPrimaryQlClass() { result = "IntLiteral" } } - /** A class representing `lambda_expr` nodes. */ - class LambdaExpr extends @unified_lambda_expr, AstNode { + /** A class representing `key_value_pair` nodes. */ + class KeyValuePair extends @unified_key_value_pair, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "LambdaExpr" } + final override string getAPrimaryQlClass() { result = "KeyValuePair" } - /** Gets the node corresponding to the field `body`. */ - final AstNode getBody() { unified_lambda_expr_def(this, result) } + /** Gets the node corresponding to the field `key`. */ + final Expr getKey() { unified_key_value_pair_def(this, result, _) } - /** Gets the node corresponding to the field `parameter`. */ - final Parameter getParameter(int i) { unified_lambda_expr_parameter(this, i, result) } + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_key_value_pair_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_lambda_expr_def(this, result) or unified_lambda_expr_parameter(this, _, result) + unified_key_value_pair_def(this, result, _) or unified_key_value_pair_def(this, _, result) } } - /** A class representing `let_pattern_condition` nodes. */ - class LetPatternCondition extends @unified_let_pattern_condition, AstNode { + /** A class representing `keyword_literal` tokens. */ + class KeywordLiteral extends @unified_token_keyword_literal, Token { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "LetPatternCondition" } + final override string getAPrimaryQlClass() { result = "KeywordLiteral" } + } - /** Gets the node corresponding to the field `pattern`. */ - final Pattern getPattern() { unified_let_pattern_condition_def(this, result, _) } + /** A class representing `labeled_stmt` nodes. */ + class LabeledStmt extends @unified_labeled_stmt, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "LabeledStmt" } - /** Gets the node corresponding to the field `value`. */ - final Expr getValue() { unified_let_pattern_condition_def(this, _, result) } + /** Gets the node corresponding to the field `label`. */ + final Identifier getLabel() { unified_labeled_stmt_def(this, result, _) } + + /** Gets the node corresponding to the field `stmt`. */ + final Stmt getStmt() { unified_labeled_stmt_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_let_pattern_condition_def(this, result, _) or - unified_let_pattern_condition_def(this, _, result) + unified_labeled_stmt_def(this, result, _) or unified_labeled_stmt_def(this, _, result) } } + /** A class representing `map_literal` nodes. */ + class MapLiteral extends @unified_map_literal, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "MapLiteral" } + + /** Gets the node corresponding to the field `element`. */ + final Expr getElement(int i) { unified_map_literal_element(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_map_literal_element(this, _, result) } + } + + class Member extends @unified_member, AstNode { } + /** A class representing `member_access_expr` nodes. */ class MemberAccessExpr extends @unified_member_access_expr, AstNode { /** Gets the name of the primary QL class for this element. */ @@ -284,7 +838,7 @@ module Unified { final Identifier getMember() { unified_member_access_expr_def(this, result, _) } /** Gets the node corresponding to the field `target`. */ - final Expr getTarget() { unified_member_access_expr_def(this, _, result) } + final ExprOrType getTarget() { unified_member_access_expr_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { @@ -293,6 +847,12 @@ module Unified { } } + /** A class representing `modifier` tokens. */ + class Modifier extends @unified_token_modifier, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "Modifier" } + } + /** A class representing `name_expr` nodes. */ class NameExpr extends @unified_name_expr, AstNode { /** Gets the name of the primary QL class for this element. */ @@ -305,10 +865,62 @@ module Unified { final override AstNode getAFieldOrChild() { unified_name_expr_def(this, result) } } - /** A class representing `operator` tokens. */ - class Operator extends @unified_token_operator, Token { + /** A class representing `name_pattern` nodes. */ + class NamePattern extends @unified_name_pattern, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "Operator" } + final override string getAPrimaryQlClass() { result = "NamePattern" } + + /** Gets the node corresponding to the field `identifier`. */ + final Identifier getIdentifier() { unified_name_pattern_def(this, result) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_name_pattern_type(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_name_pattern_def(this, result) or unified_name_pattern_type(this, result) + } + } + + /** A class representing `named_type_expr` nodes. */ + class NamedTypeExpr extends @unified_named_type_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "NamedTypeExpr" } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_named_type_expr_def(this, result) } + + /** Gets the node corresponding to the field `qualifier`. */ + final TypeExpr getQualifier() { unified_named_type_expr_qualifier(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_named_type_expr_def(this, result) or unified_named_type_expr_qualifier(this, result) + } + } + + class Operator extends @unified_operator, AstNode { } + + /** A class representing `operator_syntax_declaration` nodes. */ + class OperatorSyntaxDeclaration extends @unified_operator_syntax_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "OperatorSyntaxDeclaration" } + + /** Gets the node corresponding to the field `fixity`. */ + final Fixity getFixity() { unified_operator_syntax_declaration_fixity(this, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_operator_syntax_declaration_def(this, result) } + + /** Gets the node corresponding to the field `precedence`. */ + final Expr getPrecedence() { unified_operator_syntax_declaration_precedence(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_operator_syntax_declaration_fixity(this, result) or + unified_operator_syntax_declaration_def(this, result) or + unified_operator_syntax_declaration_precedence(this, result) + } } /** A class representing `parameter` nodes. */ @@ -316,30 +928,84 @@ module Unified { /** Gets the name of the primary QL class for this element. */ final override string getAPrimaryQlClass() { result = "Parameter" } + /** Gets the node corresponding to the field `external_name`. */ + final Identifier getExternalName() { unified_parameter_external_name(this, result) } + /** Gets the node corresponding to the field `pattern`. */ - final Pattern getPattern() { unified_parameter_def(this, result) } + final Pattern getPattern() { unified_parameter_pattern(this, result) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_parameter_type(this, result) } /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_parameter_def(this, result) } + final override AstNode getAFieldOrChild() { + unified_parameter_external_name(this, result) or + unified_parameter_pattern(this, result) or + unified_parameter_type(this, result) + } } class Pattern extends @unified_pattern, AstNode { } - /** A class representing `sequence_condition` nodes. */ - class SequenceCondition extends @unified_sequence_condition, AstNode { + /** A class representing `pattern_guard_expr` nodes. */ + class PatternGuardExpr extends @unified_pattern_guard_expr, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "SequenceCondition" } + final override string getAPrimaryQlClass() { result = "PatternGuardExpr" } - /** Gets the node corresponding to the field `condition`. */ - final Condition getCondition() { unified_sequence_condition_def(this, result) } + /** Gets the node corresponding to the field `pattern`. */ + final Pattern getPattern() { unified_pattern_guard_expr_def(this, result, _) } - /** Gets the node corresponding to the field `stmt`. */ - final Stmt getStmt(int i) { unified_sequence_condition_stmt(this, i, result) } + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_pattern_guard_expr_def(this, _, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_sequence_condition_def(this, result) or - unified_sequence_condition_stmt(this, _, result) + unified_pattern_guard_expr_def(this, result, _) or + unified_pattern_guard_expr_def(this, _, result) + } + } + + /** A class representing `postfix_operator` tokens. */ + class PostfixOperator extends @unified_token_postfix_operator, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "PostfixOperator" } + } + + /** A class representing `prefix_operator` tokens. */ + class PrefixOperator extends @unified_token_prefix_operator, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "PrefixOperator" } + } + + /** A class representing `regex_literal` tokens. */ + class RegexLiteral extends @unified_token_regex_literal, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "RegexLiteral" } + } + + /** A class representing `return_expr` nodes. */ + class ReturnExpr extends @unified_return_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ReturnExpr" } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_return_expr_value(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_return_expr_value(this, result) } + } + + /** A class representing `shorthand_member_access_expr` nodes. */ + class ShorthandMemberAccessExpr extends @unified_shorthand_member_access_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ShorthandMemberAccessExpr" } + + /** Gets the node corresponding to the field `member`. */ + final Identifier getMember() { unified_shorthand_member_access_expr_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_shorthand_member_access_expr_def(this, result) } } @@ -351,16 +1017,102 @@ module Unified { final override string getAPrimaryQlClass() { result = "StringLiteral" } } + /** A class representing `super_expr` tokens. */ + class SuperExpr extends @unified_token_super_expr, Token { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "SuperExpr" } + } + + /** A class representing `switch_case` nodes. */ + class SwitchCase extends @unified_switch_case, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "SwitchCase" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_switch_case_def(this, result) } + + /** Gets the node corresponding to the field `guard`. */ + final Expr getGuard() { unified_switch_case_guard(this, result) } + + /** Gets the node corresponding to the field `pattern`. */ + final Pattern getPattern(int i) { unified_switch_case_pattern(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_switch_case_def(this, result) or + unified_switch_case_guard(this, result) or + unified_switch_case_pattern(this, _, result) + } + } + + /** A class representing `switch_expr` nodes. */ + class SwitchExpr extends @unified_switch_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "SwitchExpr" } + + /** Gets the node corresponding to the field `case`. */ + final SwitchCase getCase(int i) { unified_switch_expr_case(this, i, result) } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_switch_expr_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_switch_expr_case(this, _, result) or unified_switch_expr_def(this, result) + } + } + + /** A class representing `throw_expr` nodes. */ + class ThrowExpr extends @unified_throw_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "ThrowExpr" } + + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_throw_expr_value(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_throw_expr_value(this, result) } + } + /** A class representing `top_level` nodes. */ class TopLevel extends @unified_top_level, AstNode { /** Gets the name of the primary QL class for this element. */ final override string getAPrimaryQlClass() { result = "TopLevel" } /** Gets the node corresponding to the field `body`. */ - final AstNode getBody(int i) { unified_top_level_body(this, i, result) } + final Block getBody() { unified_top_level_def(this, result) } /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_top_level_body(this, _, result) } + final override AstNode getAFieldOrChild() { unified_top_level_def(this, result) } + } + + /** A class representing `try_expr` nodes. */ + class TryExpr extends @unified_try_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TryExpr" } + + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_try_expr_def(this, result) } + + /** Gets the node corresponding to the field `catch_clause`. */ + final CatchClause getCatchClause(int i) { unified_try_expr_catch_clause(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_try_expr_def(this, result) or unified_try_expr_catch_clause(this, _, result) + } + } + + /** A class representing `tuple_expr` nodes. */ + class TupleExpr extends @unified_tuple_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TupleExpr" } + + /** Gets the node corresponding to the field `element`. */ + final Expr getElement(int i) { unified_tuple_expr_element(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_tuple_expr_element(this, _, result) } } /** A class representing `tuple_pattern` nodes. */ @@ -375,6 +1127,152 @@ module Unified { final override AstNode getAFieldOrChild() { unified_tuple_pattern_element(this, _, result) } } + /** A class representing `tuple_type_element` nodes. */ + class TupleTypeElement extends @unified_tuple_type_element, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TupleTypeElement" } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_tuple_type_element_name(this, result) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_tuple_type_element_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_tuple_type_element_name(this, result) or unified_tuple_type_element_def(this, result) + } + } + + /** A class representing `tuple_type_expr` nodes. */ + class TupleTypeExpr extends @unified_tuple_type_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TupleTypeExpr" } + + /** Gets the node corresponding to the field `element`. */ + final TupleTypeElement getElement(int i) { unified_tuple_type_expr_element(this, i, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { unified_tuple_type_expr_element(this, _, result) } + } + + /** A class representing `type_alias_declaration` nodes. */ + class TypeAliasDeclaration extends @unified_type_alias_declaration, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TypeAliasDeclaration" } + + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_type_alias_declaration_modifier(this, i, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_type_alias_declaration_def(this, result, _) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_type_alias_declaration_def(this, _, result) } + + /** Gets the node corresponding to the field `type_constraint`. */ + final TypeConstraint getTypeConstraint(int i) { + unified_type_alias_declaration_type_constraint(this, i, result) + } + + /** Gets the node corresponding to the field `type_parameter`. */ + final TypeParameter getTypeParameter(int i) { + unified_type_alias_declaration_type_parameter(this, i, result) + } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_type_alias_declaration_modifier(this, _, result) or + unified_type_alias_declaration_def(this, result, _) or + unified_type_alias_declaration_def(this, _, result) or + unified_type_alias_declaration_type_constraint(this, _, result) or + unified_type_alias_declaration_type_parameter(this, _, result) + } + } + + /** A class representing `type_cast_expr` nodes. */ + class TypeCastExpr extends @unified_type_cast_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TypeCastExpr" } + + /** Gets the node corresponding to the field `expr`. */ + final Expr getExpr() { unified_type_cast_expr_def(this, result, _, _) } + + /** Gets the node corresponding to the field `operator`. */ + final InfixOperator getOperator() { unified_type_cast_expr_def(this, _, result, _) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_type_cast_expr_def(this, _, _, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_type_cast_expr_def(this, result, _, _) or + unified_type_cast_expr_def(this, _, result, _) or + unified_type_cast_expr_def(this, _, _, result) + } + } + + class TypeConstraint extends @unified_type_constraint, AstNode { } + + class TypeExpr extends @unified_type_expr, AstNode { } + + /** A class representing `type_parameter` nodes. */ + class TypeParameter extends @unified_type_parameter, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TypeParameter" } + + /** Gets the node corresponding to the field `bound`. */ + final TypeExpr getBound() { unified_type_parameter_bound(this, result) } + + /** Gets the node corresponding to the field `name`. */ + final Identifier getName() { unified_type_parameter_def(this, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_type_parameter_bound(this, result) or unified_type_parameter_def(this, result) + } + } + + /** A class representing `type_test_expr` nodes. */ + class TypeTestExpr extends @unified_type_test_expr, AstNode { + /** Gets the name of the primary QL class for this element. */ + final override string getAPrimaryQlClass() { result = "TypeTestExpr" } + + /** Gets the node corresponding to the field `expr`. */ + final Expr getExpr() { unified_type_test_expr_def(this, result, _, _) } + + /** Gets the node corresponding to the field `operator`. */ + final InfixOperator getOperator() { unified_type_test_expr_def(this, _, result, _) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_type_test_expr_def(this, _, _, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_type_test_expr_def(this, result, _, _) or + unified_type_test_expr_def(this, _, result, _) or + unified_type_test_expr_def(this, _, _, result) + } + } + + /** A class representing `type_test_pattern` nodes. */ + class TypeTestPattern extends @unified_type_test_pattern, AstNode { + /** 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 Pattern getPattern() { unified_type_test_pattern_def(this, result, _) } + + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_type_test_pattern_def(this, _, result) } + + /** Gets a field or child node of this node. */ + final override AstNode getAFieldOrChild() { + unified_type_test_pattern_def(this, result, _) or + unified_type_test_pattern_def(this, _, result) + } + } + /** A class representing `unary_expr` nodes. */ class UnaryExpr extends @unified_unary_expr, AstNode { /** Gets the name of the primary QL class for this element. */ @@ -398,49 +1296,46 @@ module Unified { final override string getAPrimaryQlClass() { result = "UnsupportedNode" } } - /** A class representing `var_pattern` nodes. */ - class VarPattern extends @unified_var_pattern, AstNode { + /** A class representing `variable_declaration` nodes. */ + class VariableDeclaration extends @unified_variable_declaration, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "VarPattern" } + final override string getAPrimaryQlClass() { result = "VariableDeclaration" } - /** Gets the node corresponding to the field `identifier`. */ - final Identifier getIdentifier() { unified_var_pattern_def(this, result) } + /** Gets the node corresponding to the field `modifier`. */ + final Modifier getModifier(int i) { unified_variable_declaration_modifier(this, i, result) } - /** Gets a field or child node of this node. */ - final override AstNode getAFieldOrChild() { unified_var_pattern_def(this, result) } - } + /** Gets the node corresponding to the field `pattern`. */ + final Pattern getPattern() { unified_variable_declaration_def(this, result) } - /** A class representing `variable_declaration_stmt` nodes. */ - class VariableDeclarationStmt extends @unified_variable_declaration_stmt, AstNode { - /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "VariableDeclarationStmt" } + /** Gets the node corresponding to the field `type`. */ + final TypeExpr getType() { unified_variable_declaration_type(this, result) } - /** Gets the node corresponding to the field `variable_declarator`. */ - final VariableDeclarator getVariableDeclarator(int i) { - unified_variable_declaration_stmt_variable_declarator(this, i, result) - } + /** Gets the node corresponding to the field `value`. */ + final Expr getValue() { unified_variable_declaration_value(this, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_variable_declaration_stmt_variable_declarator(this, _, result) + unified_variable_declaration_modifier(this, _, result) or + unified_variable_declaration_def(this, result) or + unified_variable_declaration_type(this, result) or + unified_variable_declaration_value(this, result) } } - /** A class representing `variable_declarator` nodes. */ - class VariableDeclarator extends @unified_variable_declarator, AstNode { + /** A class representing `while_stmt` nodes. */ + class WhileStmt extends @unified_while_stmt, AstNode { /** Gets the name of the primary QL class for this element. */ - final override string getAPrimaryQlClass() { result = "VariableDeclarator" } + final override string getAPrimaryQlClass() { result = "WhileStmt" } - /** Gets the node corresponding to the field `pattern`. */ - final Pattern getPattern() { unified_variable_declarator_def(this, result) } + /** Gets the node corresponding to the field `body`. */ + final Block getBody() { unified_while_stmt_body(this, result) } - /** Gets the node corresponding to the field `value`. */ - final Expr getValue() { unified_variable_declarator_value(this, result) } + /** Gets the node corresponding to the field `condition`. */ + final Expr getCondition() { unified_while_stmt_def(this, result) } /** Gets a field or child node of this node. */ final override AstNode getAFieldOrChild() { - unified_variable_declarator_def(this, result) or - unified_variable_declarator_value(this, result) + unified_while_stmt_body(this, result) or unified_while_stmt_def(this, result) } } } diff --git a/unified/ql/lib/unified.dbscheme b/unified/ql/lib/unified.dbscheme index 28718d794236..c67568fd0d7c 100644 --- a/unified/ql/lib/unified.dbscheme +++ b/unified/ql/lib/unified.dbscheme @@ -132,107 +132,504 @@ overlayChangedFiles( ); /*- Unified dbscheme -*/ -#keyset[unified_apply_pattern, index] -unified_apply_pattern_argument( - int unified_apply_pattern: @unified_apply_pattern ref, +unified_accessor_declaration_body( + unique int unified_accessor_declaration: @unified_accessor_declaration ref, + unique int body: @unified_block ref +); + +#keyset[unified_accessor_declaration, index] +unified_accessor_declaration_modifier( + int unified_accessor_declaration: @unified_accessor_declaration ref, int index: int ref, - unique int argument: @unified_pattern ref + unique int modifier: @unified_token_modifier ref ); -unified_apply_pattern_def( - unique int id: @unified_apply_pattern, - int constructor: @unified_expr ref +#keyset[unified_accessor_declaration, index] +unified_accessor_declaration_parameter( + int unified_accessor_declaration: @unified_accessor_declaration ref, + int index: int ref, + unique int parameter: @unified_parameter ref +); + +unified_accessor_declaration_return_type( + unique int unified_accessor_declaration: @unified_accessor_declaration ref, + unique int return_type: @unified_type_expr ref +); + +unified_accessor_declaration_type( + unique int unified_accessor_declaration: @unified_accessor_declaration ref, + unique int type__: @unified_type_expr ref +); + +unified_accessor_declaration_def( + unique int id: @unified_accessor_declaration, + int accessor_kind: @unified_token_accessor_kind ref, + int name: @unified_token_identifier ref +); + +#keyset[unified_argument, index] +unified_argument_modifier( + int unified_argument: @unified_argument ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_argument_name( + unique int unified_argument: @unified_argument ref, + unique int name: @unified_token_identifier ref +); + +unified_argument_value( + unique int unified_argument: @unified_argument ref, + unique int value: @unified_expr ref +); + +unified_argument_def( + unique int id: @unified_argument +); + +#keyset[unified_array_literal, index] +unified_array_literal_element( + int unified_array_literal: @unified_array_literal ref, + int index: int ref, + unique int element: @unified_expr ref +); + +unified_array_literal_def( + unique int id: @unified_array_literal +); + +unified_assign_expr_def( + unique int id: @unified_assign_expr, + int target: @unified_expr_or_pattern ref, + int value: @unified_expr ref +); + +unified_associated_type_declaration_bound( + unique int unified_associated_type_declaration: @unified_associated_type_declaration ref, + unique int bound: @unified_type_expr ref +); + +#keyset[unified_associated_type_declaration, index] +unified_associated_type_declaration_modifier( + int unified_associated_type_declaration: @unified_associated_type_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_associated_type_declaration_def( + unique int id: @unified_associated_type_declaration, + int name: @unified_token_identifier ref +); + +#keyset[unified_base_type, index] +unified_base_type_modifier( + int unified_base_type: @unified_base_type ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_base_type_def( + unique int id: @unified_base_type, + int type__: @unified_type_expr ref ); unified_binary_expr_def( unique int id: @unified_binary_expr, int left: @unified_expr ref, - int operator: @unified_token_operator ref, + int operator: @unified_token_infix_operator ref, int right: @unified_expr ref ); -#keyset[unified_block_stmt, index] -unified_block_stmt_body( - int unified_block_stmt: @unified_block_stmt ref, +#keyset[unified_block, index] +unified_block_stmt( + int unified_block: @unified_block ref, int index: int ref, - unique int body: @unified_stmt ref + unique int stmt: @unified_stmt ref +); + +unified_block_def( + unique int id: @unified_block +); + +unified_bound_type_constraint_def( + unique int id: @unified_bound_type_constraint, + int bound: @unified_type_expr ref, + int type__: @unified_type_expr ref +); + +unified_break_expr_label( + unique int unified_break_expr: @unified_break_expr ref, + unique int label: @unified_token_identifier ref ); -unified_block_stmt_def( - unique int id: @unified_block_stmt +unified_break_expr_def( + unique int id: @unified_break_expr ); #keyset[unified_call_expr, index] unified_call_expr_argument( int unified_call_expr: @unified_call_expr ref, int index: int ref, - unique int argument: @unified_expr ref + unique int argument: @unified_argument ref +); + +#keyset[unified_call_expr, index] +unified_call_expr_modifier( + int unified_call_expr: @unified_call_expr ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref ); unified_call_expr_def( unique int id: @unified_call_expr, - int function: @unified_expr ref + int function: @unified_expr_or_type ref ); -@unified_condition = @unified_expr_condition | @unified_let_pattern_condition | @unified_sequence_condition | @unified_token_unsupported_node +unified_catch_clause_guard( + unique int unified_catch_clause: @unified_catch_clause ref, + unique int guard: @unified_expr ref +); -@unified_expr = @unified_binary_expr | @unified_call_expr | @unified_lambda_expr | @unified_member_access_expr | @unified_name_expr | @unified_token_int_literal | @unified_token_string_literal | @unified_token_unsupported_node | @unified_unary_expr +unified_catch_clause_pattern( + unique int unified_catch_clause: @unified_catch_clause ref, + unique int pattern: @unified_pattern ref +); -unified_expr_condition_def( - unique int id: @unified_expr_condition, - int expr: @unified_expr ref +unified_catch_clause_def( + unique int id: @unified_catch_clause, + int body: @unified_block ref +); + +#keyset[unified_class_like_declaration, index] +unified_class_like_declaration_base_type( + int unified_class_like_declaration: @unified_class_like_declaration ref, + int index: int ref, + unique int base_type: @unified_base_type ref +); + +#keyset[unified_class_like_declaration, index] +unified_class_like_declaration_member( + int unified_class_like_declaration: @unified_class_like_declaration ref, + int index: int ref, + unique int member: @unified_member ref +); + +#keyset[unified_class_like_declaration, index] +unified_class_like_declaration_modifier( + int unified_class_like_declaration: @unified_class_like_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_class_like_declaration_name( + unique int unified_class_like_declaration: @unified_class_like_declaration ref, + unique int name: @unified_token_identifier ref +); + +#keyset[unified_class_like_declaration, index] +unified_class_like_declaration_type_constraint( + int unified_class_like_declaration: @unified_class_like_declaration ref, + int index: int ref, + unique int type_constraint: @unified_type_constraint ref +); + +#keyset[unified_class_like_declaration, index] +unified_class_like_declaration_type_parameter( + int unified_class_like_declaration: @unified_class_like_declaration ref, + int index: int ref, + unique int type_parameter: @unified_type_parameter ref +); + +unified_class_like_declaration_def( + unique int id: @unified_class_like_declaration +); + +unified_compound_assign_expr_def( + unique int id: @unified_compound_assign_expr, + int operator: @unified_token_infix_operator ref, + int target: @unified_expr ref, + int value: @unified_expr ref +); + +#keyset[unified_constructor_declaration, index] +unified_constructor_declaration_modifier( + int unified_constructor_declaration: @unified_constructor_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_constructor_declaration_name( + unique int unified_constructor_declaration: @unified_constructor_declaration ref, + unique int name: @unified_token_identifier ref +); + +#keyset[unified_constructor_declaration, index] +unified_constructor_declaration_parameter( + int unified_constructor_declaration: @unified_constructor_declaration ref, + int index: int ref, + unique int parameter: @unified_parameter ref +); + +unified_constructor_declaration_def( + unique int id: @unified_constructor_declaration, + int body: @unified_block ref +); + +#keyset[unified_constructor_pattern, index] +unified_constructor_pattern_argument( + int unified_constructor_pattern: @unified_constructor_pattern ref, + int index: int ref, + unique int argument: @unified_pattern ref +); + +unified_constructor_pattern_def( + unique int id: @unified_constructor_pattern, + int constructor: @unified_expr ref +); + +unified_continue_expr_label( + unique int unified_continue_expr: @unified_continue_expr ref, + unique int label: @unified_token_identifier ref +); + +unified_continue_expr_def( + unique int id: @unified_continue_expr +); + +#keyset[unified_destructor_declaration, index] +unified_destructor_declaration_modifier( + int unified_destructor_declaration: @unified_destructor_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_destructor_declaration_def( + unique int id: @unified_destructor_declaration, + int body: @unified_block ref +); + +unified_do_while_stmt_body( + unique int unified_do_while_stmt: @unified_do_while_stmt ref, + unique int body: @unified_block ref +); + +unified_do_while_stmt_def( + unique int id: @unified_do_while_stmt, + int condition: @unified_expr ref ); -unified_expr_stmt_def( - unique int id: @unified_expr_stmt, +unified_equality_type_constraint_def( + unique int id: @unified_equality_type_constraint, + int left: @unified_type_expr ref, + 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_shorthand_member_access_expr | @unified_switch_expr | @unified_throw_expr | @unified_token_boolean_literal | @unified_token_empty_expr | @unified_token_float_literal | @unified_token_int_literal | @unified_token_keyword_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_expr_equality_pattern_def( + unique int id: @unified_expr_equality_pattern, int expr: @unified_expr ref ); +@unified_expr_or_pattern = @unified_expr | @unified_pattern + +@unified_expr_or_type = @unified_expr | @unified_type_expr + +unified_for_each_stmt_body( + unique int unified_for_each_stmt: @unified_for_each_stmt ref, + unique int body: @unified_block ref +); + +unified_for_each_stmt_guard( + unique int unified_for_each_stmt: @unified_for_each_stmt ref, + unique int guard: @unified_expr ref +); + +unified_for_each_stmt_def( + unique int id: @unified_for_each_stmt, + int iterable: @unified_expr ref, + int pattern: @unified_pattern ref +); + +unified_function_declaration_body( + unique int unified_function_declaration: @unified_function_declaration ref, + unique int body: @unified_block ref +); + +#keyset[unified_function_declaration, index] +unified_function_declaration_modifier( + int unified_function_declaration: @unified_function_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +#keyset[unified_function_declaration, index] +unified_function_declaration_parameter( + int unified_function_declaration: @unified_function_declaration ref, + int index: int ref, + unique int parameter: @unified_parameter ref +); + +unified_function_declaration_return_type( + unique int unified_function_declaration: @unified_function_declaration ref, + unique int return_type: @unified_type_expr ref +); + +#keyset[unified_function_declaration, index] +unified_function_declaration_type_constraint( + int unified_function_declaration: @unified_function_declaration ref, + int index: int ref, + unique int type_constraint: @unified_type_constraint ref +); + +#keyset[unified_function_declaration, index] +unified_function_declaration_type_parameter( + int unified_function_declaration: @unified_function_declaration ref, + int index: int ref, + unique int type_parameter: @unified_type_parameter ref +); + +unified_function_declaration_def( + unique int id: @unified_function_declaration, + int name: @unified_token_identifier ref +); + +#keyset[unified_function_expr, index] +unified_function_expr_capture_declaration( + int unified_function_expr: @unified_function_expr ref, + int index: int ref, + unique int capture_declaration: @unified_variable_declaration ref +); + +#keyset[unified_function_expr, index] +unified_function_expr_modifier( + int unified_function_expr: @unified_function_expr ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +#keyset[unified_function_expr, index] +unified_function_expr_parameter( + int unified_function_expr: @unified_function_expr ref, + int index: int ref, + unique int parameter: @unified_parameter ref +); + +unified_function_expr_return_type( + unique int unified_function_expr: @unified_function_expr ref, + unique int return_type: @unified_type_expr ref +); + +unified_function_expr_def( + unique int id: @unified_function_expr, + int body: @unified_block ref +); + +#keyset[unified_function_type_expr, index] +unified_function_type_expr_parameter( + int unified_function_type_expr: @unified_function_type_expr ref, + int index: int ref, + unique int parameter: @unified_parameter ref +); + +unified_function_type_expr_def( + unique int id: @unified_function_type_expr, + int return_type: @unified_type_expr ref +); + +#keyset[unified_generic_type_expr, index] +unified_generic_type_expr_type_argument( + int unified_generic_type_expr: @unified_generic_type_expr ref, + int index: int ref, + unique int type_argument: @unified_type_expr ref +); + +unified_generic_type_expr_def( + unique int id: @unified_generic_type_expr, + int base: @unified_type_expr ref +); + unified_guard_if_stmt_def( unique int id: @unified_guard_if_stmt, - int condition: @unified_condition ref, - int else: @unified_stmt ref + int condition: @unified_expr ref, + int else: @unified_block ref ); -unified_if_stmt_else( - unique int unified_if_stmt: @unified_if_stmt ref, - unique int else: @unified_stmt ref +unified_if_expr_else( + unique int unified_if_expr: @unified_if_expr ref, + unique int else: @unified_expr ref ); -unified_if_stmt_then( - unique int unified_if_stmt: @unified_if_stmt ref, - unique int then: @unified_stmt ref +unified_if_expr_then( + unique int unified_if_expr: @unified_if_expr ref, + unique int then: @unified_expr ref ); -unified_if_stmt_def( - unique int id: @unified_if_stmt, - int condition: @unified_condition ref +unified_if_expr_def( + unique int id: @unified_if_expr, + int condition: @unified_expr ref ); -@unified_lambda_expr_body_type = @unified_expr | @unified_stmt +#keyset[unified_import_declaration, index] +unified_import_declaration_modifier( + int unified_import_declaration: @unified_import_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); -#keyset[unified_lambda_expr, index] -unified_lambda_expr_parameter( - int unified_lambda_expr: @unified_lambda_expr ref, +#keyset[unified_import_declaration, index] +unified_import_declaration_path( + int unified_import_declaration: @unified_import_declaration ref, int index: int ref, - unique int parameter: @unified_parameter ref + unique int path: @unified_token_identifier ref ); -unified_lambda_expr_def( - unique int id: @unified_lambda_expr, - int body: @unified_lambda_expr_body_type ref +unified_import_declaration_def( + unique int id: @unified_import_declaration ); -unified_let_pattern_condition_def( - unique int id: @unified_let_pattern_condition, - int pattern: @unified_pattern ref, +#keyset[unified_initializer_declaration, index] +unified_initializer_declaration_modifier( + int unified_initializer_declaration: @unified_initializer_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +unified_initializer_declaration_def( + unique int id: @unified_initializer_declaration, + int body: @unified_block ref +); + +unified_key_value_pair_def( + unique int id: @unified_key_value_pair, + int key__: @unified_expr ref, int value: @unified_expr ref ); +unified_labeled_stmt_def( + unique int id: @unified_labeled_stmt, + int label: @unified_token_identifier ref, + int stmt: @unified_stmt ref +); + +#keyset[unified_map_literal, index] +unified_map_literal_element( + int unified_map_literal: @unified_map_literal ref, + int index: int ref, + unique int element: @unified_expr ref +); + +unified_map_literal_def( + unique int id: @unified_map_literal +); + +@unified_member = @unified_accessor_declaration | @unified_associated_type_declaration | @unified_class_like_declaration | @unified_constructor_declaration | @unified_destructor_declaration | @unified_function_declaration | @unified_initializer_declaration | @unified_token_unsupported_node | @unified_type_alias_declaration | @unified_variable_declaration + unified_member_access_expr_def( unique int id: @unified_member_access_expr, int member: @unified_token_identifier ref, - int target: @unified_expr ref + int target: @unified_expr_or_type ref ); unified_name_expr_def( @@ -240,38 +637,150 @@ unified_name_expr_def( int identifier: @unified_token_identifier ref ); +unified_name_pattern_type( + unique int unified_name_pattern: @unified_name_pattern ref, + unique int type__: @unified_type_expr ref +); + +unified_name_pattern_def( + unique int id: @unified_name_pattern, + int identifier: @unified_token_identifier ref +); + +unified_named_type_expr_qualifier( + unique int unified_named_type_expr: @unified_named_type_expr ref, + unique int qualifier: @unified_type_expr ref +); + +unified_named_type_expr_def( + unique int id: @unified_named_type_expr, + int name: @unified_token_identifier ref +); + +@unified_operator = @unified_token_infix_operator | @unified_token_postfix_operator | @unified_token_prefix_operator + +unified_operator_syntax_declaration_fixity( + unique int unified_operator_syntax_declaration: @unified_operator_syntax_declaration ref, + unique int fixity: @unified_token_fixity ref +); + +unified_operator_syntax_declaration_precedence( + unique int unified_operator_syntax_declaration: @unified_operator_syntax_declaration ref, + unique int precedence: @unified_expr ref +); + +unified_operator_syntax_declaration_def( + unique int id: @unified_operator_syntax_declaration, + int name: @unified_token_identifier ref +); + +unified_parameter_external_name( + unique int unified_parameter: @unified_parameter ref, + unique int external_name: @unified_token_identifier ref +); + +unified_parameter_pattern( + unique int unified_parameter: @unified_parameter ref, + unique int pattern: @unified_pattern ref +); + +unified_parameter_type( + unique int unified_parameter: @unified_parameter ref, + unique int type__: @unified_type_expr ref +); + unified_parameter_def( - unique int id: @unified_parameter, - int pattern: @unified_pattern ref + unique int id: @unified_parameter ); -@unified_pattern = @unified_apply_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern | @unified_var_pattern +@unified_pattern = @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern -#keyset[unified_sequence_condition, index] -unified_sequence_condition_stmt( - int unified_sequence_condition: @unified_sequence_condition ref, - int index: int ref, - unique int stmt: @unified_stmt ref +unified_pattern_guard_expr_def( + unique int id: @unified_pattern_guard_expr, + int pattern: @unified_pattern ref, + int value: @unified_expr ref ); -unified_sequence_condition_def( - unique int id: @unified_sequence_condition, - int condition: @unified_condition ref +unified_return_expr_value( + unique int unified_return_expr: @unified_return_expr ref, + unique int value: @unified_expr ref +); + +unified_return_expr_def( + unique int id: @unified_return_expr +); + +unified_shorthand_member_access_expr_def( + unique int id: @unified_shorthand_member_access_expr, + int member: @unified_token_identifier ref ); -@unified_stmt = @unified_block_stmt | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_token_empty_stmt | @unified_token_unsupported_node | @unified_variable_declaration_stmt +@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 + +unified_switch_case_guard( + unique int unified_switch_case: @unified_switch_case ref, + unique int guard: @unified_expr ref +); + +#keyset[unified_switch_case, index] +unified_switch_case_pattern( + int unified_switch_case: @unified_switch_case ref, + int index: int ref, + unique int pattern: @unified_pattern ref +); -@unified_top_level_body_type = @unified_expr | @unified_stmt +unified_switch_case_def( + unique int id: @unified_switch_case, + int body: @unified_block ref +); -#keyset[unified_top_level, index] -unified_top_level_body( - int unified_top_level: @unified_top_level ref, +#keyset[unified_switch_expr, index] +unified_switch_expr_case( + int unified_switch_expr: @unified_switch_expr ref, int index: int ref, - unique int body: @unified_top_level_body_type ref + unique int case__: @unified_switch_case ref +); + +unified_switch_expr_def( + unique int id: @unified_switch_expr, + int value: @unified_expr ref +); + +unified_throw_expr_value( + unique int unified_throw_expr: @unified_throw_expr ref, + unique int value: @unified_expr ref +); + +unified_throw_expr_def( + unique int id: @unified_throw_expr ); unified_top_level_def( - unique int id: @unified_top_level + unique int id: @unified_top_level, + int body: @unified_block ref +); + +#keyset[unified_try_expr, index] +unified_try_expr_catch_clause( + int unified_try_expr: @unified_try_expr ref, + int index: int ref, + unique int catch_clause: @unified_catch_clause ref +); + +unified_try_expr_def( + unique int id: @unified_try_expr, + int body: @unified_block ref +); + +#keyset[unified_tuple_expr, index] +unified_tuple_expr_element( + int unified_tuple_expr: @unified_tuple_expr ref, + int index: int ref, + unique int element: @unified_expr ref +); + +unified_tuple_expr_def( + unique int id: @unified_tuple_expr ); #keyset[unified_tuple_pattern, index] @@ -285,38 +794,126 @@ unified_tuple_pattern_def( unique int id: @unified_tuple_pattern ); +unified_tuple_type_element_name( + unique int unified_tuple_type_element: @unified_tuple_type_element ref, + unique int name: @unified_token_identifier ref +); + +unified_tuple_type_element_def( + unique int id: @unified_tuple_type_element, + int type__: @unified_type_expr ref +); + +#keyset[unified_tuple_type_expr, index] +unified_tuple_type_expr_element( + int unified_tuple_type_expr: @unified_tuple_type_expr ref, + int index: int ref, + unique int element: @unified_tuple_type_element ref +); + +unified_tuple_type_expr_def( + unique int id: @unified_tuple_type_expr +); + +#keyset[unified_type_alias_declaration, index] +unified_type_alias_declaration_modifier( + int unified_type_alias_declaration: @unified_type_alias_declaration ref, + int index: int ref, + unique int modifier: @unified_token_modifier ref +); + +#keyset[unified_type_alias_declaration, index] +unified_type_alias_declaration_type_constraint( + int unified_type_alias_declaration: @unified_type_alias_declaration ref, + int index: int ref, + unique int type_constraint: @unified_type_constraint ref +); + +#keyset[unified_type_alias_declaration, index] +unified_type_alias_declaration_type_parameter( + int unified_type_alias_declaration: @unified_type_alias_declaration ref, + int index: int ref, + unique int type_parameter: @unified_type_parameter ref +); + +unified_type_alias_declaration_def( + unique int id: @unified_type_alias_declaration, + int name: @unified_token_identifier ref, + int type__: @unified_type_expr ref +); + +unified_type_cast_expr_def( + unique int id: @unified_type_cast_expr, + int expr: @unified_expr ref, + int operator: @unified_token_infix_operator ref, + int type__: @unified_type_expr ref +); + +@unified_type_constraint = @unified_bound_type_constraint | @unified_equality_type_constraint + +@unified_type_expr = @unified_function_type_expr | @unified_generic_type_expr | @unified_named_type_expr | @unified_token_unsupported_node | @unified_tuple_type_expr + +unified_type_parameter_bound( + unique int unified_type_parameter: @unified_type_parameter ref, + unique int bound: @unified_type_expr ref +); + +unified_type_parameter_def( + unique int id: @unified_type_parameter, + int name: @unified_token_identifier ref +); + +unified_type_test_expr_def( + unique int id: @unified_type_test_expr, + int expr: @unified_expr ref, + int operator: @unified_token_infix_operator ref, + int type__: @unified_type_expr ref +); + +unified_type_test_pattern_def( + unique int id: @unified_type_test_pattern, + int pattern: @unified_pattern ref, + int type__: @unified_type_expr ref +); + unified_unary_expr_def( unique int id: @unified_unary_expr, int operand: @unified_expr ref, - int operator: @unified_token_operator ref -); - -unified_var_pattern_def( - unique int id: @unified_var_pattern, - int identifier: @unified_token_identifier ref + int operator: @unified_operator ref ); -#keyset[unified_variable_declaration_stmt, index] -unified_variable_declaration_stmt_variable_declarator( - int unified_variable_declaration_stmt: @unified_variable_declaration_stmt ref, +#keyset[unified_variable_declaration, index] +unified_variable_declaration_modifier( + int unified_variable_declaration: @unified_variable_declaration ref, int index: int ref, - unique int variable_declarator: @unified_variable_declarator ref + unique int modifier: @unified_token_modifier ref ); -unified_variable_declaration_stmt_def( - unique int id: @unified_variable_declaration_stmt +unified_variable_declaration_type( + unique int unified_variable_declaration: @unified_variable_declaration ref, + unique int type__: @unified_type_expr ref ); -unified_variable_declarator_value( - unique int unified_variable_declarator: @unified_variable_declarator ref, +unified_variable_declaration_value( + unique int unified_variable_declaration: @unified_variable_declaration ref, unique int value: @unified_expr ref ); -unified_variable_declarator_def( - unique int id: @unified_variable_declarator, +unified_variable_declaration_def( + unique int id: @unified_variable_declaration, int pattern: @unified_pattern ref ); +unified_while_stmt_body( + unique int unified_while_stmt: @unified_while_stmt ref, + unique int body: @unified_block ref +); + +unified_while_stmt_def( + unique int id: @unified_while_stmt, + int condition: @unified_expr ref +); + unified_tokeninfo( unique int id: @unified_token, int kind: int ref, @@ -324,17 +921,27 @@ unified_tokeninfo( ); case @unified_token.kind of - 1 = @unified_token_empty_stmt -| 2 = @unified_token_identifier -| 3 = @unified_token_ignore_pattern -| 4 = @unified_token_int_literal -| 5 = @unified_token_operator -| 6 = @unified_token_string_literal -| 7 = @unified_token_unsupported_node + 1 = @unified_token_accessor_kind +| 2 = @unified_token_boolean_literal +| 3 = @unified_token_empty_expr +| 4 = @unified_token_fixity +| 5 = @unified_token_float_literal +| 6 = @unified_token_identifier +| 7 = @unified_token_ignore_pattern +| 8 = @unified_token_infix_operator +| 9 = @unified_token_int_literal +| 10 = @unified_token_keyword_literal +| 11 = @unified_token_modifier +| 12 = @unified_token_postfix_operator +| 13 = @unified_token_prefix_operator +| 14 = @unified_token_regex_literal +| 15 = @unified_token_string_literal +| 16 = @unified_token_super_expr +| 17 = @unified_token_unsupported_node ; -@unified_ast_node = @unified_apply_pattern | @unified_binary_expr | @unified_block_stmt | @unified_call_expr | @unified_expr_condition | @unified_expr_stmt | @unified_guard_if_stmt | @unified_if_stmt | @unified_lambda_expr | @unified_let_pattern_condition | @unified_member_access_expr | @unified_name_expr | @unified_parameter | @unified_sequence_condition | @unified_token | @unified_top_level | @unified_tuple_pattern | @unified_unary_expr | @unified_var_pattern | @unified_variable_declaration_stmt | @unified_variable_declarator +@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_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @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_parameter | @unified_pattern_guard_expr | @unified_return_expr | @unified_shorthand_member_access_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @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_variable_declaration | @unified_while_stmt unified_ast_node_location( unique int node: @unified_ast_node ref,