diff --git a/shared/yeast-macros/src/parse.rs b/shared/yeast-macros/src/parse.rs index c81febe7a649..5ab3f80fa162 100644 --- a/shared/yeast-macros/src/parse.rs +++ b/shared/yeast-macros/src/parse.rs @@ -987,6 +987,7 @@ pub fn parse_rule_top(input: TokenStream) -> Result { #(#translated_bindings)* let mut #ctx_ident = yeast::build::BuildCtx::with_translator(__ast, &__captures, __fresh, __source_range, __user_ctx, __translator); let __result: Vec = { #transform_body }; + let __result = #ctx_ident.finish_rule(__result); Ok(__result) }), ) diff --git a/shared/yeast/doc/yeast.md b/shared/yeast/doc/yeast.md index b586bed71435..f9f0100f2fa6 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -235,6 +235,52 @@ yeast::trees!(ctx, (identifier #{name}) // an identifier from a Rust variable ``` +### Source locations + +Captured nodes keep the locations assigned by their own translations. New +nodes in an output template derive their locations from their children. A +source-less nested node receives an empty location at the start of the matched +input node. After the transform completes, the full matched range is added only +to locally-created nodes returned as rule results: + +```rust +rule!( + (wrapper child: (_) @child) + => + (outer nested: (inner value: {child})) +) +``` + +Here `inner` derives its range from `child`, while the returned `outer` node +also includes the full `wrapper` range. A nested node with no located children +would instead receive an empty range at the start of `wrapper`. This lets +replacement roots include elided keywords or delimiters without assigning the +same broad range to every synthetic descendant. A transform that simply +returns a translated capture does not widen that capture to the wrapper's +range. + +When the desired range belongs to another node, `tree_at!` assigns that range +to the template's root. Nested nodes still derive their own locations normally: + +```rust +let synthetic = tree_at!(ctx, source, (synthetic_node child: (nested value: {child}))); +``` + +`tree_spanning!` similarly assigns the union of several node ranges: + +```rust +let synthetic = tree_spanning!(ctx, nodes, (synthetic_node child: {child})); +``` + +For input fields whose leading or trailing syntax should never belong to rule +results, configure them once with +`DesugaringConfig::with_ignored_location_fields(...)`. For example, ignoring +`trailingComma` retains the rest of each matched list element without requiring +every rule to capture or handle the comma. + +For literals, `ctx.literal_at_start_of(...)` creates an empty range at another +node's start. + For reviewing locations, `DumpOptions::show_abridged_source` prints each node's source range with every direct child replaced by its field name in Unicode angle brackets. This keeps delimiters and other parent-owned syntax visible @@ -246,6 +292,17 @@ return_expr source="return ⟨value⟩" call_expr source="⟨callee⟩(⟨argument⟩)" ``` +Children outside the node's source range retain their own locations and are +annotated where they are printed rather than being treated as errors: + +```text +accessor_declaration source="⟨accessor_kind⟩" + name_node: identifier "value" source="value" (external) +``` + +Node and child ranges are still validated against the source text and UTF-8 +boundaries. + ### Optional fields (`?`) A `?` on a field's value makes that field fallible. If a `#{expr}` anywhere diff --git a/shared/yeast/src/build.rs b/shared/yeast/src/build.rs index f4f5ae5d18f3..6cbf130cb820 100644 --- a/shared/yeast/src/build.rs +++ b/shared/yeast/src/build.rs @@ -1,8 +1,8 @@ -use std::collections::BTreeMap; +use std::collections::{BTreeMap, BTreeSet}; use crate::captures::Captures; use crate::tree_builder::FreshScope; -use crate::{Ast, FieldId, Id, NodeContent, Range, TranslatorHandle}; +use crate::{Ast, FieldId, Id, KindId, NodeContent, Range, TranslatorHandle}; /// Context for building new AST nodes during a transformation. /// @@ -33,13 +33,23 @@ pub struct BuildCtx<'a, C: 'a = ()> { pub ast: &'a mut Ast, pub captures: &'a Captures, pub fresh: &'a FreshScope, - /// Source range of the matched node, inherited by synthetic nodes. - pub source_range: Option, + /// Source range of the node matched by the current rule. + /// + /// The `rule!` macro applies this range to locally-created result roots + /// after the transform completes. Nested synthetic nodes derive their + /// ranges from their children, falling back to an empty range at this + /// range's start. + pub matched_source_range: Option, /// User-supplied context, accessible directly via `ctx.field` (via Deref). pub user_ctx: &'a mut C, /// Optional translator handle, populated when the context is built by /// the framework's rule driver. None when the context is built by hand. pub(crate) translator: Option>, + /// Nodes built directly through this context without an explicit source + /// range in either their content or constructor argument. Recursive + /// translations use their own context and therefore do not contribute to + /// this list. + created_nodes: BTreeSet, } impl<'a, C> BuildCtx<'a, C> { @@ -53,26 +63,10 @@ impl<'a, C> BuildCtx<'a, C> { ast, captures, fresh, - source_range: None, - user_ctx, - translator: None, - } - } - - pub fn with_source_range( - ast: &'a mut Ast, - captures: &'a Captures, - fresh: &'a FreshScope, - source_range: Option, - user_ctx: &'a mut C, - ) -> Self { - Self { - ast, - captures, - fresh, - source_range, + matched_source_range: None, user_ctx, translator: None, + created_nodes: BTreeSet::new(), } } @@ -90,10 +84,102 @@ impl<'a, C> BuildCtx<'a, C> { ast, captures, fresh, - source_range, + matched_source_range: source_range, user_ctx, translator: Some(translator), + created_nodes: BTreeSet::new(), + } + } + + /// Create a node and record it as constructed by this rule invocation. + pub fn create_node_with_range( + &mut self, + kind: KindId, + content: NodeContent, + fields: BTreeMap>, + is_named: bool, + source_range: Option, + ) -> Id { + let has_explicit_source_range = + source_range.is_some() || matches!(&content, NodeContent::Range(_)); + let id = self + .ast + .create_node_with_range(kind, content, fields, is_named, source_range); + if self + .ast + .get_node(id) + .is_some_and(|node| node.source_range().is_none()) + { + if let Some(source_range) = self.matched_source_range { + self.ast + .extend_source_range(id, source_range.empty_at_start()); + } + } + if !has_explicit_source_range { + self.created_nodes.insert(id); + } + id + } + + /// Create a node using this context's explicit default source range. + pub fn create_node( + &mut self, + kind: KindId, + content: NodeContent, + fields: BTreeMap>, + is_named: bool, + ) -> Id { + self.create_node_with_range(kind, content, fields, is_named, None) + } + + /// Create a named token and record it as constructed by this rule invocation. + pub fn create_named_token_with_range( + &mut self, + kind: &'static str, + content: String, + source_range: Option, + ) -> Id { + let has_explicit_source_range = source_range.is_some(); + let source_range = source_range.or_else(|| { + self.matched_source_range + .map(|range| range.empty_at_start()) + }); + let id = self + .ast + .create_named_token_with_range(kind, content, source_range); + if !has_explicit_source_range { + self.created_nodes.insert(id); + } + id + } + + /// Create a named token using this context's explicit default source range. + pub fn create_named_token(&mut self, kind: &'static str, content: String) -> Id { + self.create_named_token_with_range(kind, content, None) + } + + /// Finish the current rule invocation by applying the matched source range + /// to locally-created result roots. + #[doc(hidden)] + pub fn finish_rule(self, results: Vec) -> Vec { + if let Some(source_range) = self.matched_source_range { + for &id in &results { + if self.created_nodes.contains(&id) { + self.ast.extend_source_range(id, source_range); + } + } } + results + } + + /// Assign an explicit source range to a newly-built result root. + #[doc(hidden)] + pub fn set_node_source_range(&mut self, node: Id, source_range: Option) -> Id { + if let Some(source_range) = source_range { + self.ast.set_source_range(node, source_range); + self.created_nodes.remove(&node); + } + node } /// Look up a capture variable, returning its node Id. @@ -119,6 +205,18 @@ impl<'a, C> BuildCtx<'a, C> { self.ast.source_text(id) } + /// Return the source range of a parsed or synthetic node. + fn source_range_of(&self, id: Id) -> Option { + self.ast.get_node(id).and_then(|node| node.source_range()) + } + + /// Return an empty range between two non-overlapping nodes. + pub fn empty_source_range_between(&self, left: Id, right: Id) -> Option { + let left = self.source_range_of(left)?; + let right = self.source_range_of(right)?; + (left.end_byte <= right.start_byte).then(|| left.empty_at_end()) + } + /// Create a named AST node with the given kind and fields. pub fn node(&mut self, kind: &str, fields: Vec<(&str, Vec)>) -> Id { let kind_id = self @@ -133,41 +231,39 @@ impl<'a, C> BuildCtx<'a, C> { .unwrap_or_else(|| panic!("build: field '{name}' not found")); field_map.entry(field_id).or_default().extend(ids); } - self.ast.create_node_with_range( + self.create_node( kind_id, NodeContent::DynamicString(String::new()), field_map, true, - self.source_range, ) } /// Create a leaf node with a fixed string content. pub fn literal(&mut self, kind: &'static str, value: &str) -> Id { - self.ast - .create_named_token_with_range(kind, value.to_string(), self.source_range) + self.create_named_token(kind, value.to_string()) } - /// Create a leaf node with fixed content and an optional preferred source range. - /// If `source_range` is `None`, falls back to this context's inherited range. + /// Create a leaf node with fixed content and an optional source range. pub fn literal_with_source_range( &mut self, kind: &'static str, value: &str, source_range: Option, ) -> Id { - self.ast.create_named_token_with_range( - kind, - value.to_string(), - source_range.or(self.source_range), - ) + self.create_named_token_with_range(kind, value.to_string(), source_range) + } + + /// Create a literal with an empty range at another node's start. + pub fn literal_at_start_of(&mut self, kind: &'static str, value: &str, source: Id) -> Id { + let source_range = self.source_range_of(source).map(Range::empty_at_start); + self.literal_with_source_range(kind, value, source_range) } /// Create a leaf node with an auto-generated unique name. pub fn fresh(&mut self, kind: &'static str, name: &str) -> Id { let generated = self.fresh.resolve(name); - self.ast - .create_named_token_with_range(kind, generated, self.source_range) + self.create_named_token(kind, generated) } } @@ -203,8 +299,9 @@ impl BuildCtx<'_, C> { /// Run `f` with a temporary child [`BuildCtx`] whose `user_ctx` is /// a fresh clone of the current one, sharing everything else - /// (`ast`, `captures`, `fresh`, `source_range`, `translator`) by - /// re-borrow. Any mutations `f` makes to the child's `user_ctx` + /// (`ast`, `captures`, `fresh`, source ranges, `translator`) by re-borrow. + /// Nodes constructed through the child remain part of the current rule + /// invocation. Any mutations `f` makes to the child's `user_ctx` /// are discarded when it returns — no restore needed, because the /// mutations only ever happened on a local clone. /// @@ -235,11 +332,16 @@ impl BuildCtx<'_, C> { ast: &mut *self.ast, captures: self.captures, fresh: self.fresh, - source_range: self.source_range, + matched_source_range: self.matched_source_range, user_ctx: &mut child_user_ctx, translator: self.translator, + created_nodes: BTreeSet::new(), }; - f(&mut child) + let result = f(&mut child); + let created_nodes = std::mem::take(&mut child.created_nodes); + drop(child); + self.created_nodes.extend(created_nodes); + result // child_user_ctx dropped; the outer `self` is unaffected. } } diff --git a/shared/yeast/src/dump.rs b/shared/yeast/src/dump.rs index ddcf3ae12b4e..b2d89b587889 100644 --- a/shared/yeast/src/dump.rs +++ b/shared/yeast/src/dump.rs @@ -51,7 +51,7 @@ pub fn dump_ast(ast: &Ast, root: Id, source: &str) -> String { pub fn dump_ast_with_options(ast: &Ast, root: Id, source: &str, options: &DumpOptions) -> String { let mut out = String::new(); - dump_node(ast, root, source, options, 0, None, &mut out); + dump_node(ast, root, source, options, 0, None, false, &mut out); out } @@ -86,6 +86,7 @@ pub fn dump_ast_with_type_errors_and_options( expected: None, parent_field: None, }), + false, &mut out, ); out @@ -195,6 +196,7 @@ fn dump_node( options: &DumpOptions, indent: usize, type_check: Option>, + external_to_parent: bool, out: &mut String, ) { let node = match ast.get_node(id) { @@ -232,6 +234,9 @@ fn dump_node( if options.show_abridged_source { write_source_skeleton(ast, node, source, out); + if external_to_parent { + write!(out, " (external)").unwrap(); + } } if let Some(context) = type_check { @@ -300,9 +305,18 @@ fn dump_node( write!(out, "{prefix} {field_name}:").unwrap(); // Inline single child let child = ast.get_node(children[0]); + let external = child.is_some_and(|child| is_external_child(node, child)); if child.is_some_and(is_leaf) { write!(out, " ").unwrap(); - dump_node_inline(ast, children[0], source, options, child_type_check, out); + dump_node_inline( + ast, + children[0], + source, + options, + child_type_check, + external, + out, + ); } else { writeln!(out).unwrap(); dump_node( @@ -312,12 +326,16 @@ fn dump_node( options, indent + 2, child_type_check, + external, out, ); } } else { writeln!(out, "{prefix} {field_name}:").unwrap(); for &child_id in children { + let external = ast + .get_node(child_id) + .is_some_and(|child| is_external_child(node, child)); dump_node( ast, child_id, @@ -325,6 +343,7 @@ fn dump_node( options, indent + 2, child_type_check, + external, out, ); } @@ -365,6 +384,7 @@ fn dump_node( for &child_id in children { if let Some(child) = ast.get_node(child_id) { if child.is_named() { + let external = is_external_child(node, child); dump_node( ast, child_id, @@ -372,6 +392,7 @@ fn dump_node( options, indent + 1, child_type_check, + external, out, ); } @@ -387,6 +408,7 @@ fn dump_node_inline( source: &str, options: &DumpOptions, type_check: Option>, + external_to_parent: bool, out: &mut String, ) { let node = match ast.get_node(id) { @@ -419,6 +441,9 @@ fn dump_node_inline( if options.show_abridged_source { write_source_skeleton(ast, node, source, out); + if external_to_parent { + write!(out, " (external)").unwrap(); + } } if let Some(context) = type_check { @@ -457,6 +482,13 @@ fn node_source_range(node: &Node) -> Option { } } +fn is_external_child(parent: &Node, child: &Node) -> bool { + let (Some(parent), Some(child)) = (node_source_range(parent), node_source_range(child)) else { + return false; + }; + child.start_byte < parent.start_byte || child.end_byte > parent.end_byte +} + fn source_skeleton(ast: &Ast, node: &Node, source: &str) -> SourceSkeleton { let Some(parent) = node_source_range(node) else { return SourceSkeleton::Missing; @@ -494,10 +526,7 @@ fn source_skeleton(ast: &Ast, node: &Node, source: &str) -> SourceSkeleton { )); } if child.start < parent.start || child.end > parent.end { - return SourceSkeleton::Invalid(format!( - "child range {}..{} is outside node range {}..{}", - child.start, child.end, parent.start, parent.end - )); + continue; } if child.start == child.end { continue; @@ -613,12 +642,6 @@ mod tests { #[test] fn source_skeleton_validates_empty_child_ranges() { let cases = [ - ( - "abcdef", - range(0, 3), - range(4, 4), - "child range 4..4 is outside node range 0..3", - ), ( "abcdef", range(0, 6), @@ -640,6 +663,13 @@ mod tests { "unexpected dump: {dump}" ); } + + let dump = dump_with_children("abcdef", range(0, 3), &[("marker", range(4, 4))]); + assert!(dump.starts_with("parent source=\"abc\"\n")); + assert!( + dump.contains("marker: child source=\"\" (external)\n"), + "unexpected dump: {dump}" + ); } #[test] @@ -667,12 +697,15 @@ mod tests { } #[test] - fn source_skeleton_reports_children_outside_the_parent() { + fn source_skeleton_marks_children_outside_the_parent() { let source = "abcdefghi"; let dump = dump_with_children(source, range(0, 6), &[("child", range(7, 9))]); - assert!(dump - .starts_with("parent source=\n")); + assert!(dump.starts_with("parent source=\"abcdef\"\n")); + assert!( + dump.contains(" child source=\"hi\" (external)\n"), + "unexpected dump: {dump}" + ); } } diff --git a/shared/yeast/src/lib.rs b/shared/yeast/src/lib.rs index 76bfa58124d6..45f57fb70c94 100644 --- a/shared/yeast/src/lib.rs +++ b/shared/yeast/src/lib.rs @@ -18,6 +18,40 @@ mod visitor; pub use range::{Point, Range}; pub use yeast_macros::{query, rule, rules, tree, trees}; +/// Build a single AST node whose root uses another node's source range. +/// +/// Nested nodes in the template are built normally and derive their locations +/// from their own children. +#[macro_export] +macro_rules! tree_at { + ($ctx:ident, $source:expr, ($($tree:tt)*)) => {{ + let __yeast_source: $crate::Id = $source; + let __yeast_source_range = $ctx + .ast + .get_node(__yeast_source) + .and_then(|node| node.source_range()); + let __yeast_node: $crate::Id = $crate::tree!($ctx, ($($tree)*)); + $ctx.set_node_source_range(__yeast_node, __yeast_source_range) + }}; +} + +/// Build a single AST node whose root spans a collection of nodes. +/// +/// Nested nodes in the template are built normally and derive their locations +/// from their own children. +#[macro_export] +macro_rules! tree_spanning { + ($ctx:ident, $sources:expr, ($($tree:tt)*)) => {{ + let __yeast_source_range = ::std::iter::IntoIterator::into_iter($sources) + .filter_map(|source: $crate::Id| { + $ctx.ast.get_node(source).and_then(|node| node.source_range()) + }) + .reduce($crate::Range::union); + let __yeast_node: $crate::Id = $crate::tree!($ctx, ($($tree)*)); + $ctx.set_node_source_range(__yeast_node, __yeast_source_range) + }}; +} + use captures::Captures; use query::QueryNode; @@ -128,9 +162,10 @@ pub trait YeastDisplay { /// Optional source range for values used in `#{expr}` interpolations. /// -/// By default this returns `None`, so synthesized leaves inherit the matched -/// rule's source range. `Id` returns the referenced node's range, letting -/// `(kind #{capture})` carry the captured node's location. +/// By default this returns `None`, so synthesized leaves use the current +/// [`crate::build::BuildCtx`] default range, if any. `Id` returns the +/// referenced node's range, letting `(kind #{capture})` carry the captured +/// node's location. pub trait YeastSourceRange { fn yeast_source_range(&self, ast: &Ast) -> Option; } @@ -143,10 +178,7 @@ impl YeastDisplay for Id { impl YeastSourceRange for Id { fn yeast_source_range(&self, ast: &Ast) -> Option { - ast.get_node(*self).and_then(|n| match &n.content { - NodeContent::Range(r) => Some(*r), - _ => n.source_range, - }) + ast.get_node(*self).and_then(Node::source_range) } } @@ -565,6 +597,25 @@ impl Ast { self.nodes.get(id.0) } + fn source_range_ignoring_fields( + &self, + id: Id, + ignored_fields: &[&str], + ) -> Option { + let node = self.get_node(id)?; + let source_range = node.source_range()?; + let ignored_ranges = node + .fields + .iter() + .filter(|(field_id, _)| { + self.field_name_for_id(**field_id) + .is_some_and(|name| ignored_fields.contains(&name)) + }) + .flat_map(|(_, children)| children) + .filter_map(|child| self.get_node(*child).and_then(Node::source_range)); + Some(source_range.ignoring_boundary_ranges(ignored_ranges)) + } + pub fn print(&self, source: &str, root_id: Id) -> Value { let root = &self.nodes()[root_id.0]; self.print_node(root, source) @@ -592,13 +643,12 @@ impl Ast { // Parsed nodes already carry an exact source range in their content. NodeContent::Range(_) => source_range, // Synthesized nodes derive location from both their children and - // the inherited rule-match range, so tokens matched by a rule but - // elided from its output still contribute to the replacement range. + // any explicitly supplied source range. _ => self .union_source_range_of_children(&fields) .map_or(source_range, |child_range| { Some(match source_range { - Some(source_range) => union_source_ranges(child_range, source_range), + Some(source_range) => child_range.union(source_range), None => child_range, }) }), @@ -618,6 +668,36 @@ impl Ast { Id(id) } + /// Extend a synthetic node's source range to include `source_range`. + /// + /// Parsed nodes carry their exact range in [`NodeContent::Range`] and must + /// not be modified through this API. + pub fn extend_source_range(&mut self, id: Id, source_range: Range) { + let node = self + .nodes + .get_mut(id.0) + .unwrap_or_else(|| panic!("extend_source_range: invalid node id {}", id.0)); + if matches!(node.content, NodeContent::Range(_)) { + panic!("extend_source_range: cannot modify a parsed node"); + } + node.source_range = Some(match node.source_range { + Some(existing) => existing.union(source_range), + None => source_range, + }); + } + + /// Replace a synthetic node's source range. + pub(crate) fn set_source_range(&mut self, id: Id, source_range: Range) { + let node = self + .nodes + .get_mut(id.0) + .unwrap_or_else(|| panic!("set_source_range: invalid node id {}", id.0)); + if matches!(node.content, NodeContent::Range(_)) { + panic!("set_source_range: cannot modify a parsed node"); + } + node.source_range = Some(source_range); + } + /// Register a named node kind, returning its id (idempotent). Lets callers /// build an AST in a single pass, registering kinds as nodes are created /// rather than pre-populating the schema. @@ -655,35 +735,30 @@ impl Ast { let Some(child) = self.get_node(child_id) else { continue; }; - - let child_start_byte = child.start_byte(); - let child_end_byte = child.end_byte(); - - // Skip children that carry no usable location. - if child_start_byte == 0 && child_end_byte == 0 { + let Some(child_range) = child.source_range() else { continue; - } + }; match start_byte { None => { - start_byte = Some(child_start_byte); - start_point = child.start_position(); + start_byte = Some(child_range.start_byte); + start_point = child_range.start_point; } - Some(current_start) if child_start_byte < current_start => { - start_byte = Some(child_start_byte); - start_point = child.start_position(); + Some(current_start) if child_range.start_byte < current_start => { + start_byte = Some(child_range.start_byte); + start_point = child_range.start_point; } _ => {} } match end_byte { None => { - end_byte = Some(child_end_byte); - end_point = child.end_position(); + end_byte = Some(child_range.end_byte); + end_point = child_range.end_point; } - Some(current_end) if child_end_byte > current_end => { - end_byte = Some(child_end_byte); - end_point = child.end_position(); + Some(current_end) if child_range.end_byte > current_end => { + end_byte = Some(child_range.end_byte); + end_point = child_range.end_point; } _ => {} } @@ -792,25 +867,6 @@ impl Ast { } } -fn union_source_ranges(first: Range, second: Range) -> Range { - let (start_byte, start_point) = if first.start_byte <= second.start_byte { - (first.start_byte, first.start_point) - } else { - (second.start_byte, second.start_point) - }; - let (end_byte, end_point) = if first.end_byte >= second.end_byte { - (first.end_byte, first.end_point) - } else { - (second.end_byte, second.end_point) - }; - Range { - start_byte, - end_byte, - start_point, - end_point, - } -} - /// A node in our AST #[derive(PartialEq, Eq, Debug, Clone, Serialize)] pub struct Node { @@ -853,36 +909,29 @@ impl Node { Point { row: 0, column: 0 } } - pub fn start_position(&self) -> Point { + pub fn source_range(&self) -> Option { match self.content { - NodeContent::Range(range) => range.start_point, - _ => self - .source_range - .map_or_else(|| self.fake_point(), |r| r.start_point), + NodeContent::Range(range) => Some(range), + _ => self.source_range, } } + pub fn start_position(&self) -> Point { + self.source_range() + .map_or_else(|| self.fake_point(), |range| range.start_point) + } + pub fn end_position(&self) -> Point { - match self.content { - NodeContent::Range(range) => range.end_point, - _ => self - .source_range - .map_or_else(|| self.fake_point(), |r| r.end_point), - } + self.source_range() + .map_or_else(|| self.fake_point(), |range| range.end_point) } pub fn start_byte(&self) -> usize { - match self.content { - NodeContent::Range(range) => range.start_byte, - _ => self.source_range.map_or(0, |r| r.start_byte), - } + self.source_range().map_or(0, |range| range.start_byte) } pub fn end_byte(&self) -> usize { - match self.content { - NodeContent::Range(range) => range.end_byte, - _ => self.source_range.map_or(0, |r| r.end_byte), - } + self.source_range().map_or(0, |range| range.end_byte) } pub fn byte_range(&self) -> std::ops::Range { @@ -1070,6 +1119,7 @@ pub struct Rule { query: QueryNode, guard: Option>, transform: Transform, + ignored_location_fields: Vec<&'static str>, /// If true, after this rule fires on a node the engine will try to /// re-apply this same rule on the result root. Defaults to false: /// each rule fires at most once on a given node, which prevents @@ -1084,6 +1134,7 @@ impl Rule { query, guard: None, transform, + ignored_location_fields: Vec::new(), repeated: false, } } @@ -1095,6 +1146,7 @@ impl Rule { query, guard: Some(guard), transform, + ignored_location_fields: Vec::new(), repeated: false, } } @@ -1108,6 +1160,10 @@ impl Rule { self } + fn set_ignored_location_fields(&mut self, fields: &[&'static str]) { + self.ignored_location_fields = fields.to_vec(); + } + /// Attempt to match this rule's query against `node`, returning the raw /// captures on success. Does not evaluate the guard or invoke the /// transform. @@ -1134,8 +1190,8 @@ impl Rule { } } - /// Run this rule's transform with the given captures, using `node`'s - /// source range as the source range of the produced nodes. + /// Run this rule's transform with the given captures, making `node`'s + /// source range available to the transform. fn run_transform( &self, ast: &mut Ast, @@ -1146,10 +1202,8 @@ impl Rule { translator: TranslatorHandle<'_, C>, ) -> Result, String> { fresh.next_scope(); - let source_range = ast.get_node(node).and_then(|n| match n.content { - NodeContent::Range(r) => Some(r), - _ => n.source_range, - }); + let source_range = + ast.source_range_ignoring_fields(node, &self.ignored_location_fields); (self.transform)(ast, captures, fresh, source_range, user_ctx, translator) } } @@ -1435,6 +1489,9 @@ pub struct DesugaringConfig { /// node types are used (i.e. the desugared AST has the same node types /// as the tree-sitter grammar). pub output_node_types_yaml: Option<&'static str>, + /// Input field names whose boundary ranges are excluded from rule-result + /// locations. + pub ignored_location_fields: Vec<&'static str>, } // Manual `Default` impl so users with a custom `C` that doesn't implement @@ -1444,6 +1501,7 @@ impl Default for DesugaringConfig { Self { phases: Vec::new(), output_node_types_yaml: None, + ignored_location_fields: Vec::new(), } } } @@ -1460,12 +1518,30 @@ impl DesugaringConfig { mut self, name: impl Into, kind: PhaseKind, - rules: Vec>, + mut rules: Vec>, ) -> Self { + for rule in &mut rules { + rule.set_ignored_location_fields(&self.ignored_location_fields); + } self.phases.push(Phase::new(name, kind, rules)); self } + /// Ignore boundary syntax stored under any of these input field names when + /// calculating matched locations for rule results. + pub fn with_ignored_location_fields( + mut self, + fields: impl IntoIterator, + ) -> Self { + self.ignored_location_fields = fields.into_iter().collect(); + for phase in &mut self.phases { + for rule in &mut phase.rules { + rule.set_ignored_location_fields(&self.ignored_location_fields); + } + } + self + } + pub fn with_output_node_types_yaml(mut self, yaml: &'static str) -> Self { self.output_node_types_yaml = Some(yaml); self diff --git a/shared/yeast/src/range.rs b/shared/yeast/src/range.rs index e56bbcc6fb85..0daa631d24e0 100644 --- a/shared/yeast/src/range.rs +++ b/shared/yeast/src/range.rs @@ -30,3 +30,70 @@ pub struct Range { pub start_point: Point, pub end_point: Point, } + +impl Range { + /// Return the smallest range containing both ranges. + pub fn union(self, other: Self) -> Self { + let (start_byte, start_point) = if self.start_byte <= other.start_byte { + (self.start_byte, self.start_point) + } else { + (other.start_byte, other.start_point) + }; + let (end_byte, end_point) = if self.end_byte >= other.end_byte { + (self.end_byte, self.end_point) + } else { + (other.end_byte, other.end_point) + }; + Self { + start_byte, + end_byte, + start_point, + end_point, + } + } + + /// Return an empty range anchored at this range's start. + pub fn empty_at_start(self) -> Self { + Self { + end_byte: self.start_byte, + end_point: self.start_point, + ..self + } + } + + /// Return an empty range anchored at this range's end. + pub fn empty_at_end(self) -> Self { + Self { + start_byte: self.end_byte, + start_point: self.end_point, + ..self + } + } + + pub(crate) fn ignoring_boundary_ranges( + mut self, + ignored: impl IntoIterator, + ) -> Self { + let ignored: Vec<_> = ignored.into_iter().collect(); + loop { + let previous = self; + for range in &ignored { + if *range == self { + self = self.empty_at_start(); + continue; + } + if range.start_byte == self.start_byte && range.end_byte > range.start_byte { + self.start_byte = range.end_byte; + self.start_point = range.end_point; + } + if range.end_byte == self.end_byte && range.end_byte > range.start_byte { + self.end_byte = range.start_byte; + self.end_point = range.start_point; + } + } + if self == previous { + return self; + } + } + } +} diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index e0abe51053d9..b0c707ea8b26 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -1579,7 +1579,7 @@ fn test_hash_brace_renders_capture_source_text() { r#" program call - arguments: argument_list "foo.bar()" + arguments: argument_list method: identifier "bar" receiver: identifier "foo" "#, @@ -1674,6 +1674,327 @@ fn test_elided_tokens_contribute_to_replacement_location() { assert_eq!(call.end_byte(), 9); } +/// Nested nodes constructed by a rule derive their location from their own +/// children rather than inheriting the range of the rule's matched root. +#[test] +fn test_nested_synthetic_node_uses_child_location() { + let rule: Rule = rule!( + (call + method: (identifier) @name + receiver: (identifier) @recv + ) + => + (call + method: {name} + receiver: {recv} + arguments: (argument_list argument: {recv}) + ) + ); + + let ast = run_and_ast("foo.bar()", vec![rule]); + let call = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "call") + .expect("call exists"); + assert_eq!(call.byte_range(), 0..9); + + let arguments = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "argument_list") + .expect("argument list exists"); + assert_eq!(arguments.byte_range(), 0..3); +} + +/// A nested node with no explicit range or located children gets an empty +/// location at the start of the rule's matched node. +#[test] +fn test_source_less_nested_node_uses_empty_match_start() { + let rule: Rule = rule!( + (call + method: (identifier) @name + receiver: (identifier) @recv + ) + => + (call + method: {name} + receiver: {recv} + arguments: (argument_list) + ) + ); + + let ast = run_and_ast("foo.bar()", vec![rule]); + let arguments = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "argument_list") + .expect("argument list exists"); + let range = arguments.source_range().unwrap(); + assert_eq!(range.start_byte..range.end_byte, 0..0); +} + +/// An explicit empty range at byte zero is a real location, not the sentinel +/// for an absent location, and therefore contributes to parent ranges. +#[test] +fn test_empty_range_at_file_start_contributes_to_parent() { + use std::collections::BTreeMap; + + let lang: tree_sitter::Language = tree_sitter_ruby::LANGUAGE.into(); + let schema = + yeast::node_types_yaml::schema_from_yaml_with_language(OUTPUT_SCHEMA_YAML, &lang).unwrap(); + let mut ast = Ast::with_schema(schema); + let empty = Range { + start_byte: 0, + end_byte: 0, + start_point: Point::new(0, 0), + end_point: Point::new(0, 0), + }; + let child = + ast.create_named_token_with_range("identifier", "synthetic".to_owned(), Some(empty)); + let fields = BTreeMap::from([(ast.field_id_for_name("method").unwrap(), vec![child])]); + let parent = ast.create_node_with_range( + ast.id_for_node_kind("call").unwrap(), + NodeContent::DynamicString(String::new()), + fields, + true, + None, + ); + + assert_eq!(ast.get_node(parent).unwrap().source_range(), Some(empty)); +} + +/// A rule that only unwraps and returns a translated capture must not widen +/// that capture to the wrapper's source range. +#[test] +fn test_returned_capture_keeps_its_location() { + let rule: Rule = rule!( + (call method: (identifier) @name) + => + identifier { name } + ); + + let ast = run_and_ast("foo.bar()", vec![rule]); + let identifier = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "identifier") + .expect("identifier exists"); + assert_eq!(identifier.byte_range(), 4..7); +} + +#[test] +fn test_ignored_location_field_is_excluded_from_rule_result_location() { + let rule: Rule = rule!( + (assignment + left: (identifier) @left) + => + (call method: {left}) + ); + + let language: tree_sitter::Language = tree_sitter_ruby::LANGUAGE.into(); + let config = DesugaringConfig::new() + .with_ignored_location_fields(["right"]) + .add_phase("test", PhaseKind::Repeating, vec![rule]); + let runner: Runner = Runner::from_config(language, &config).unwrap(); + let ast = runner.run("x = 1").unwrap(); + let call = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "call") + .expect("call exists"); + assert_eq!(call.byte_range(), 0..4); +} + +/// Nodes allocated by an explicit recursive translation belong to that nested +/// rule invocation, even when the outer rule returns one directly. +#[test] +fn test_explicit_recursive_translation_keeps_nested_rule_location() { + let program: Rule = rule!( + (program (_)* @stmts) + => + (program stmt: {stmts}) + ); + let unwrap: Rule = rule!( + (call method: (identifier) @@name) + => + identifier { + ctx.translate(name)? + .into_iter() + .next() + .ok_or("identifier translation produced no result")? + } + ); + let translate_identifier: Rule = rule!((identifier) @@identifier => (identifier #{identifier})); + + let lang: tree_sitter::Language = tree_sitter_ruby::LANGUAGE.into(); + let schema = + yeast::node_types_yaml::schema_from_yaml_with_language(OUTPUT_SCHEMA_YAML, &lang).unwrap(); + let phases = vec![Phase::new( + "translate", + PhaseKind::OneShot, + vec![program, unwrap, translate_identifier], + )]; + let runner: Runner = Runner::with_schema(lang, &schema, &phases); + let ast = runner.run("foo.bar()").unwrap(); + let identifier = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "identifier") + .expect("identifier exists"); + assert_eq!(identifier.byte_range(), 4..7); +} + +/// `tree_at!` assigns the captured node's range only to the template root. +#[test] +fn test_tree_at_assigns_capture_range_to_root_only() { + let rule: Rule = rule!( + (call + method: (identifier) @name + receiver: (identifier) @recv + ) @@source + => + call { + let arguments = tree_at!(ctx, source, (argument_list argument: (integer "0"))); + tree!((call method: {name} receiver: {recv} arguments: {arguments})) + } + ); + + let ast = run_and_ast("foo.bar()", vec![rule]); + let arguments = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "argument_list") + .expect("argument list exists"); + assert_eq!(arguments.byte_range(), 0..9); + + let integer = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "integer") + .expect("integer exists"); + assert_eq!(integer.byte_range(), 0..0); +} + +/// `tree_spanning!` assigns the union of the captured node ranges only to the +/// template root. +#[test] +fn test_tree_spanning_assigns_union_to_root_only() { + let rule: Rule = rule!( + (call + method: (identifier) @name + receiver: (identifier) @recv + ) + => + call { + let arguments = tree_spanning!( + ctx, + [recv, name], + (argument_list argument: (integer "0")) + ); + tree!((call method: {name} receiver: {recv} arguments: {arguments})) + } + ); + + let ast = run_and_ast("foo.bar()", vec![rule]); + let arguments = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "argument_list") + .expect("argument list exists"); + assert_eq!(arguments.byte_range(), 0..7); + + let integer = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| ast.get_node(id)) + .find(|node| node.kind_name() == "integer") + .expect("integer exists"); + assert_eq!(integer.byte_range(), 0..0); +} + +/// Explicit ranges on multiple results must not be widened to the range of the +/// input node matched by the rule. +#[test] +fn test_explicitly_located_multiple_results_keep_their_ranges() { + let rule: Rule = rule!( + (assignment + left: (identifier) @@left + right: (integer) @@right) + => + identifier* { + let left_text = ctx.source_text(left); + let right_text = ctx.source_text(right); + let left_range = left.yeast_source_range(&*ctx.ast); + let right_range = right.yeast_source_range(&*ctx.ast); + vec![ + ctx.literal_with_source_range("identifier", &left_text, left_range), + ctx.literal_with_source_range("identifier", &right_text, right_range), + ] + } + ); + + let ast = run_and_ast("x = 1", vec![rule]); + let mut ranges: Vec<_> = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| { + let node = ast.get_node(id)?; + (node.kind_name() == "identifier").then(|| (ast.source_text(id), node.byte_range())) + }) + .collect(); + ranges.sort_by_key(|(_, range)| range.start); + + assert_eq!( + ranges, + vec![("x".to_string(), 0..1), ("1".to_string(), 4..5)] + ); +} + +/// A range-backed node already carries an exact parsed range and must not be +/// finalized as a synthetic result. +#[test] +fn test_range_backed_result_keeps_its_range() { + use std::collections::BTreeMap; + + let rule: Rule = rule!( + (assignment left: (identifier) @@left) + => + identifier { + let range = left.yeast_source_range(&*ctx.ast).unwrap(); + let kind = ctx.ast.id_for_node_kind("identifier").unwrap(); + ctx.create_node_with_range( + kind, + NodeContent::Range(range), + BTreeMap::new(), + true, + None, + ) + } + ); + + let ast = run_and_ast("x = 1", vec![rule]); + let identifiers: Vec<_> = ast + .reachable_node_ids() + .into_iter() + .filter_map(|id| { + let node = ast.get_node(id)?; + (node.kind_name() == "identifier").then(|| (ast.source_text(id), node.byte_range())) + }) + .collect(); + + assert_eq!(identifiers, vec![("x".to_string(), 0..1)]); +} + // ---- `rules!` macro tests (compile-time type-checking) ---- /// `rules!` should accept well-typed rules using the bare-rule-body diff --git a/unified/extractor/BUILD.bazel b/unified/extractor/BUILD.bazel index f8814c4572a1..26e815d49e8a 100644 --- a/unified/extractor/BUILD.bazel +++ b/unified/extractor/BUILD.bazel @@ -34,6 +34,11 @@ _TESTS = { "compile_data": [], "size": "medium", }, + "location_tests": { + "data": [], + "compile_data": [], + "size": "small", + }, # `include_str!`s a checked-in `parse_to_json` dump. "swift_syntax_pipeline": { "data": [], diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 8242e37a8a3f..76d51c65fa55 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -1,5 +1,7 @@ use codeql_extractor::extractor::desugaring; -use yeast::{ConcreteDesugarer, DesugaringConfig, PhaseKind, Rule, rule, tree}; +use yeast::{ + ConcreteDesugarer, DesugaringConfig, PhaseKind, Rule, rule, tree, tree_at, tree_spanning, +}; /// User context propagated from outer rules down to the inner rules that /// emit the corresponding output declarations, so that each emitted node @@ -60,6 +62,17 @@ impl SwiftContext { } } +fn block_with_anchor( + ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>, + statements: Vec, + anchor: Option, +) -> yeast::Id { + match anchor { + Some(anchor) => tree_at!(ctx, anchor, (block stmt: {statements})), + None => tree!(ctx, (block stmt: {statements})), + } +} + /// Build a freshly-created `chained_declaration` modifier node if /// `ctx.is_chained`, else `None`. Used by inner declaration rules to /// emit the chained tag for non-first children of a flattening outer @@ -86,7 +99,9 @@ fn and_chain( conds .into_iter() .reduce(|acc, elem| { - tree!((binary_expr operator: (infix_operator "&&") left: {acc} right: {elem})) + let operator_range = ctx.empty_source_range_between(acc, elem); + let operator = ctx.literal_with_source_range("infix_operator", "&&", operator_range); + tree!((binary_expr operator: {operator} left: {acc} right: {elem})) }) .expect("control-flow statement must have at least one condition") } @@ -112,21 +127,15 @@ fn member_chain( ctx: &mut yeast::build::BuildCtx<'_, SwiftContext>, parts: Vec, ) -> yeast::Id { - // `member_chain` builds the imported expression inside the larger import - // declaration rule. The imported expression should span the import path, - // not the whole declaration including the `import` keyword. - let source_range = ctx.source_range.take(); let mut iter = parts.into_iter(); let first = iter .next() .expect("identifier with `part:` must have at least one part"); let init = tree!((identifier #{first})); - let result = iter.fold( + iter.fold( init, |acc, elem| tree!((member_access_expr base: {acc} member_name_node: (identifier #{elem}))), - ); - ctx.source_range = source_range; - result + ) } fn translation_rules() -> Vec> { @@ -304,14 +313,14 @@ fn translation_rules() -> Vec> { bindings: (patternBinding pattern: (identifierPattern identifier: @@name) typeAnnotation: (typeAnnotation type: @ty) - accessorBlock: (accessorBlock accessors: (codeBlockItem)+ @body))) + accessorBlock: (accessorBlock accessors: (codeBlockItem)+ @body) @@accessor_block)) => (accessor_declaration modifier: (modifier #{spec}) name_node: (identifier #{name}) type: {ty} - accessor_kind: (accessor_kind "get") - body: (block stmt: {body})) + accessor_kind: {ctx.literal_at_start_of("accessor_kind", "get", accessor_block)} + body: {block_with_anchor(&mut ctx, body, Some(accessor_block))}) ), // A property with an explicit accessor block. swift-syntax makes both // shapes plain `accessorDecl`s, so they are told apart by the presence @@ -396,7 +405,9 @@ fn translation_rules() -> Vec> { } None => None, }; - tree!( + tree_spanning!( + ctx, + std::iter::once(spec).chain(body), (accessor_declaration modifier: {binding} modifier: {chained} @@ -469,14 +480,24 @@ fn translation_rules() -> Vec> { // `enumCaseDecl` rule below) and are tagged `enum_case`, after any // `chained_declaration` tag. rule!( - (enumCaseElement name: @name parameterClause: (enumCaseParameterClause parameters: _* @params)) - => - (class_like_declaration - modifier: {ctx.outer_modifiers.clone()} - modifier: {chained_modifier(&mut ctx)} - modifier: (modifier "enum_case") - name_node: (identifier #{name}) - member: (constructor_declaration parameter: {params} body: (block))) + (enumCaseElement + name: @name + parameterClause: (enumCaseParameterClause parameters: _* @params) @@clause) + => + class_like_declaration { + let body = tree!((block)); + let constructor = tree_spanning!( + ctx, + [name, clause], + (constructor_declaration parameter: {params} body: {body}) + ); + tree!((class_like_declaration + modifier: {ctx.outer_modifiers.clone()} + modifier: {chained_modifier(&mut ctx)} + modifier: (modifier "enum_case") + name_node: (identifier #{name}) + member: {constructor})) + } ), rule!( (enumCaseElement name: @name rawValue: (initializerClause value: @val)) @@ -567,7 +588,7 @@ fn translation_rules() -> Vec> { signature: (functionSignature parameterClause: (functionParameterClause parameters: _* @params) returnClause: (returnClause type: @ret)?) - body: (codeBlock statements: _* @body)) + body: (codeBlock) @body) => (function_declaration modifier: {mods} @@ -575,7 +596,7 @@ fn translation_rules() -> Vec> { type_parameter: {type_params} parameter: {params} return_type: {ret} - body: (block stmt: {body})) + body: {body}) ), rule!( (functionDecl @@ -624,27 +645,41 @@ fn translation_rules() -> Vec> { // `Array` generic type constructor instead. rule!( (functionCallExpr - calledExpression: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @element)) + calledExpression: (arrayExpr + elements: (arrayElement expression: (genericSpecializationExpr) @element)) @@array arguments: _* @args trailingClosure: @tc) => - (call_expr - callee: (generic_type_expr + call_expr { + let callee = tree_at!( + ctx, + array, + (generic_type_expr base: (identifier "Array") type_argument: {element}) - argument: {args} - argument: (argument value: {tc})) + ); + tree!((call_expr + callee: {callee} + argument: {args} + argument: (argument value: {tc}))) + } ), rule!( (functionCallExpr - calledExpression: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @element)) + calledExpression: (arrayExpr + elements: (arrayElement expression: (genericSpecializationExpr) @element)) @@array arguments: _* @args) => - (call_expr - callee: (generic_type_expr + call_expr { + let callee = tree_at!( + ctx, + array, + (generic_type_expr base: (identifier "Array") type_argument: {element}) - argument: {args}) + ); + tree!((call_expr callee: {callee} argument: {args})) + } ), // A function/method call (`foo(1, 2)`). `calledExpression` is the callee // and `arguments` is an (elided) list of `labeledExpr`, each translated @@ -676,12 +711,17 @@ fn translation_rules() -> Vec> { label: _? @@lbl expression: (functionCallExpr calledExpression: @constructor - arguments: _* @elements)) + arguments: _* @elements) @@call) => argument { + let value = tree_at!( + ctx, + call, + (call_expr callee: {constructor} argument: {elements}) + ); tree!((argument name_node: (identifier #{lbl})? - value: (call_expr callee: {constructor} argument: {elements}))) + value: {value})) } ), rule!( @@ -710,14 +750,22 @@ fn translation_rules() -> Vec> { // meaning as `Array` rather than an array literal. rule!( (memberAccessExpr - base: (arrayExpr elements: (arrayElement expression: (genericSpecializationExpr) @element)) + base: (arrayExpr + elements: (arrayElement expression: (genericSpecializationExpr) @element)) @@array declName: (declReferenceExpr baseName: @member)) => - (member_access_expr - base: (generic_type_expr - base: (identifier "Array") - type_argument: {element}) - member_name_node: (identifier #{member})) + member_access_expr { + let base = tree_at!( + ctx, + array, + (generic_type_expr + base: (identifier "Array") + type_argument: {element}) + ); + tree!((member_access_expr + base: {base} + member_name_node: (identifier #{member}))) + } ), rule!( (memberAccessExpr base: @base declName: (declReferenceExpr baseName: @member)) @@ -750,14 +798,14 @@ fn translation_rules() -> Vec> { capture: (closureCaptureClause items: _* @captures)? parameterClause: _* @params returnClause: (returnClause type: @ret)?)? - statements: _* @body) + statements: _* @body) @@closure => (function_expr modifier: {attrs} capture_declaration: {captures} parameter: {params} return_type: {ret} - body: (block stmt: {body})) + body: {block_with_anchor(&mut ctx, body, Some(closure))}) ), // A closure capture (`[weak self]`, `[x]`, `[y = expr]`). The optional // ownership specifier (`weak`/`unowned`) becomes a modifier; the @@ -839,7 +887,13 @@ fn translation_rules() -> Vec> { (switch_case body: (block stmt: {body})) ), // A single case item unwraps to its pattern, possibly boxed in conditional_pattern - rule!((switchCaseItem pattern: @p whereClause: (whereClause condition: @cond)) => (conditional_pattern pattern: { p } condition: {cond})), + rule!( + (switchCaseItem + pattern: @p + whereClause: (whereClause condition: @cond)) + => + (conditional_pattern pattern: {p} condition: {cond}) + ), rule!((switchCaseItem pattern: @p) => pattern { p }), // A pattern-matching condition (`if case let x = e`, `if case .foo(let x) // = e`) becomes a `pattern_guard_expr`: the matched pattern and the @@ -854,6 +908,7 @@ fn translation_rules() -> Vec> { // form is matched first. rule!( (optionalBindingCondition + bindingSpecifier: @@spec pattern: (identifierPattern identifier: @name) initializer: (initializerClause value: @val)) => @@ -862,18 +917,20 @@ fn translation_rules() -> Vec> { pattern: (call_expr callee: (member_access_expr base: (identifier "Optional") member_name_node: (identifier "some")) argument: (argument value: (expr_pattern - modifier: (modifier "let") + modifier: (modifier #{spec}) expr: (identifier #{name}))))) ), rule!( - (optionalBindingCondition pattern: (identifierPattern identifier: @name)) + (optionalBindingCondition + bindingSpecifier: @@spec + pattern: (identifierPattern identifier: @name)) => (pattern_guard_expr value: (identifier #{name}) pattern: (call_expr callee: (member_access_expr base: (identifier "Optional") member_name_node: (identifier "some")) argument: (argument value: (expr_pattern - modifier: (modifier "let") + modifier: (modifier #{spec}) expr: (identifier #{name}))))) ), // A single condition in an `if`/`while`/`guard` condition list unwraps to @@ -957,11 +1014,19 @@ fn translation_rules() -> Vec> { }), // try/try?/try! expr → unary_expr with operator "try", "try?" or "try!" rule!( - (tryExpr questionOrExclamationMark: _? @@m expression: @e) + (tryExpr + tryKeyword: @@keyword + questionOrExclamationMark: _? @@m + expression: @e) => expr { let op = format!("try{}", m.map(|m| ctx.source_text(m)).unwrap_or_default()); - tree!((unary_expr operator: (prefix_operator #{op}) operand: {e})) + let operator = tree_spanning!( + ctx, + std::iter::once(keyword).chain(m), + (prefix_operator #{op}) + ); + tree!((unary_expr operator: {operator} operand: {e})) } ), // Do-catch → try_expr @@ -973,7 +1038,9 @@ fn translation_rules() -> Vec> { catch_clause: {catches}) ), rule!( - (catchItem pattern: @pattern whereClause: (whereClause condition: @guard)) + (catchItem + pattern: @pattern + whereClause: (whereClause condition: @guard)) => (conditional_pattern pattern: {pattern} condition: {guard}) ), @@ -995,17 +1062,29 @@ fn translation_rules() -> Vec> { // Catch block without error binding rule!((catchClause body: @body) => (catch_clause body: {body})), // As expression (type cast) — as?, as! - rule!((asExpr expression: @val questionOrExclamationMark: _? @@mark type: @ty) => type_cast_expr { + rule!((asExpr expression: @val asKeyword: @@keyword questionOrExclamationMark: _? @@mark type: @ty) => type_cast_expr { let op = format!("as{}", mark.map(|m| ctx.source_text(m)).unwrap_or_default()); - tree!((type_cast_expr expr: {val} operator: (infix_operator #{op}) type: {ty})) + let operator = tree_spanning!( + ctx, + std::iter::once(keyword).chain(mark), + (infix_operator #{op}) + ); + tree!((type_cast_expr expr: {val} operator: {operator} type: {ty})) }), // Check expression (`x is T`) → type_test_expr - rule!((isExpr expression: @val type: @ty) => (type_test_expr expr: {val} operator: (infix_operator "is") type: {ty})), + rule!((isExpr expression: @val isKeyword: @@keyword type: @ty) => (type_test_expr + expr: {val} + operator: {tree_at!(ctx, keyword, (infix_operator "is"))} + type: {ty})), // Await expression → unary_expr with operator "await" - rule!((awaitExpr expression: @val) => (unary_expr operator: (prefix_operator "await") operand: {val})), + rule!((awaitExpr awaitKeyword: @@keyword expression: @val) => (unary_expr + operator: {tree_at!(ctx, keyword, (prefix_operator "await"))} + operand: {val})), // Force-unwrap (`x!`) → postfix unary_expr, via swift-syntax's dedicated // `forceUnwrapExpr` node. - rule!((forceUnwrapExpr expression: @e) => (unary_expr operator: (postfix_operator "!") operand: {e})), + rule!((forceUnwrapExpr expression: @e exclamationMark: @@mark) => (unary_expr + operator: {tree_at!(ctx, mark, (postfix_operator "!"))} + operand: {e})), // ---- Imports ---- // An import declaration. The dotted path (a list of // `importPathComponent`s) becomes a `name_node`/`member_access_expr` @@ -1020,14 +1099,17 @@ fn translation_rules() -> Vec> { attributes: _* @attrs modifiers: _* @mods importKindSpecifier: _? @@kind - path: (importPathComponent name: @@parts)*) + path: (importPathComponent name: @@parts)*) @@decl => import_declaration { let last = *parts.last().ok_or("import has no path")?; let pattern = match kind { - None => tree!((named_pattern - name_node: (identifier #{last}) - sub_pattern: (bulk_importing_pattern))), + None => { + let bulk = tree_at!(ctx, decl, (bulk_importing_pattern)); + tree!((named_pattern + name_node: (identifier #{last}) + sub_pattern: {bulk})) + } Some(_) => tree!((identifier #{last})), }; tree!((import_declaration @@ -1120,7 +1202,9 @@ fn translation_rules() -> Vec> { } ), rule!( - (tupleTypeElement firstName: _? @@name type: @ty) + (tupleTypeElement + firstName: _? @@name + type: @ty) => argument { if ctx.in_function_type { @@ -1277,22 +1361,33 @@ fn translation_rules() -> Vec> { modifiers: _* @mods signature: (functionSignature parameterClause: (functionParameterClause parameters: _* @params)) - body: (codeBlock statements: _* @body_stmts)?) + body: (codeBlock) @body) => (constructor_declaration modifier: {mods} parameter: {params} - body: (block stmt: {body_stmts})) + body: {body}) + ), + rule!( + (initializerDecl + modifiers: _* @mods + signature: (functionSignature + parameterClause: (functionParameterClause parameters: _* @params))) + => + (constructor_declaration + modifier: {mods} + parameter: {params} + body: (block)) ), // Deinit declaration → destructor_declaration. Body statements optional. rule!( (deinitializerDecl modifiers: _* @mods - body: (codeBlock statements: _* @body_stmts)) + body: (codeBlock) @body) => (destructor_declaration modifier: {mods} - body: (block stmt: {body_stmts})) + body: {body}) ), // Typealias declaration rule!( @@ -1338,6 +1433,7 @@ fn translation_rules() -> Vec> { pub fn language_spec(desugared_ast_schema: &'static str) -> desugaring::LanguageSpec { let config = DesugaringConfig::::new() + .with_ignored_location_fields(["trailingComma"]) .add_phase("translate", PhaseKind::OneShot, translation_rules()) .with_output_node_types_yaml(desugared_ast_schema); let desugarer = diff --git a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output index ad75555b1002..ad76f9b9abee 100644 --- a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output +++ b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output @@ -43,13 +43,13 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - call_expr source="⟨callee⟩⟨argument⟩" + call_expr source="⟨callee⟩ ⟨argument⟩" callee: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: identifier "xs" source="xs" member_name_node: identifier "map" source="map" argument: - argument source="xs.map ⟨value⟩" + argument source="⟨value⟩" value: function_expr source="⟨body⟩" body: diff --git a/unified/extractor/tests/corpus/swift/collections/empty-array-literal-with-type.output b/unified/extractor/tests/corpus/swift/collections/empty-array-literal-with-type.output index 28958f323827..9e05ecaab626 100644 --- a/unified/extractor/tests/corpus/swift/collections/empty-array-literal-with-type.output +++ b/unified/extractor/tests/corpus/swift/collections/empty-array-literal-with-type.output @@ -45,7 +45,7 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "xs" source="xs" type: - generic_type_expr source="⟨base⟩⟨type_argument⟩" - base: identifier "Array" source="[Int]" + generic_type_expr source="[⟨type_argument⟩]" + base: identifier "Array" source="" type_argument: identifier "Int" source="Int" value: array_literal "[]" source="[]" diff --git a/unified/extractor/tests/corpus/swift/collections/tuple-literal.output b/unified/extractor/tests/corpus/swift/collections/tuple-literal.output index 653bce662689..51088efb6750 100644 --- a/unified/extractor/tests/corpus/swift/collections/tuple-literal.output +++ b/unified/extractor/tests/corpus/swift/collections/tuple-literal.output @@ -53,11 +53,11 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "t" source="t" value: - tuple_expr source="(⟨element⟩ ⟨element⟩ ⟨element⟩)" + tuple_expr source="(⟨element⟩, ⟨element⟩, ⟨element⟩)" element: - argument source="⟨value⟩," + argument source="⟨value⟩" value: int_literal "1" source="1" - argument source="⟨value⟩," + argument source="⟨value⟩" value: string_literal "\"two\"" source="\"two\"" argument source="⟨value⟩" value: float_literal "3.0" source="3.0" diff --git a/unified/extractor/tests/corpus/swift/control-flow/binding-modifier-does-not-leak-to-sibling.output b/unified/extractor/tests/corpus/swift/control-flow/binding-modifier-does-not-leak-to-sibling.output index f960f16a50f9..73c3312ea09e 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/binding-modifier-does-not-leak-to-sibling.output +++ b/unified/extractor/tests/corpus/swift/control-flow/binding-modifier-does-not-leak-to-sibling.output @@ -95,17 +95,17 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n}" value: identifier "y" source="y" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: identifier "someConstant" source="someConstant" body: - block source="case someConstant:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"matched\"" source="\"matched\"" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: break_expr "break" source="break" diff --git a/unified/extractor/tests/corpus/swift/control-flow/defer-statement.output b/unified/extractor/tests/corpus/swift/control-flow/defer-statement.output index 78f25fbd9551..37d29a427dbe 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/defer-statement.output +++ b/unified/extractor/tests/corpus/swift/control-flow/defer-statement.output @@ -79,10 +79,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "withCleanup" source="withCleanup" body: - block source="func withCleanup() {\n ⟨stmt⟩\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n ⟨stmt⟩\n}" stmt: unsupported_node "defer { print(\"cleanup\") }" source="defer { print(\"cleanup\") }" call_expr source="⟨callee⟩(⟨argument⟩)" diff --git a/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output b/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output index b2c21eee642e..df6bb28eb01b 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output +++ b/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output @@ -67,16 +67,16 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩⟨base_type⟩⟨name_node⟩⟨member⟩" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨base_type⟩ {\n ⟨member⟩\n}" modifier: modifier "struct" source="struct" name_node: identifier "Resource" source="Resource" base_type: - base_type source="struct Resource: ⟨type⟩ {\n consuming func close() {\n discard self\n }\n}" + base_type source="⟨type⟩" type: unsupported_node "~Copyable" source="~Copyable" member: - function_declaration source="⟨modifier⟩⟨body⟩⟨name_node⟩" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "consuming" source="consuming" name_node: identifier "close" source="close" body: - block source="consuming func close() {\n ⟨stmt⟩\n }" + block source="{\n ⟨stmt⟩\n }" stmt: unsupported_node "discard self" source="discard self" diff --git a/unified/extractor/tests/corpus/swift/control-flow/fallthrough.output b/unified/extractor/tests/corpus/swift/control-flow/fallthrough.output index c5752060af62..080c3b0089d3 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/fallthrough.output +++ b/unified/extractor/tests/corpus/swift/control-flow/fallthrough.output @@ -86,7 +86,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) ⟨body⟩" name_node: identifier "classify" source="classify" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" @@ -94,17 +94,17 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" body: - block source="func classify(_ x: Int) {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: switch_expr source="switch ⟨value⟩ {\n ⟨case⟩\n ⟨case⟩\n }" value: identifier "x" source="x" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: int_literal "1" source="1" body: - block source="case 1:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: unsupported_node "fallthrough" source="fallthrough" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: break_expr "break" source="break" diff --git a/unified/extractor/tests/corpus/swift/control-flow/guard-let.output b/unified/extractor/tests/corpus/swift/control-flow/guard-let.output index aefb475a5bde..5d12fd0a7ea4 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/guard-let.output +++ b/unified/extractor/tests/corpus/swift/control-flow/guard-let.output @@ -42,18 +42,18 @@ top_level source="⟨body⟩" stmt: guard_if_stmt source="guard ⟨condition⟩ else ⟨else⟩" condition: - pattern_guard_expr source="⟨pattern⟩⟨value⟩" + pattern_guard_expr source="⟨pattern⟩ = ⟨value⟩" pattern: - call_expr source="⟨argument⟩⟨callee⟩" + call_expr source="⟨argument⟩" callee: - member_access_expr source="⟨base⟩⟨member_name_node⟩" - base: identifier "Optional" source="let value = optional" - member_name_node: identifier "some" source="let value = optional" + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: - expr_pattern source="⟨modifier⟩⟨expr⟩" - modifier: modifier "let" source="let value = optional" + expr_pattern source="⟨modifier⟩ ⟨expr⟩" + modifier: modifier "let" source="let" expr: identifier "value" source="value" value: identifier "optional" source="optional" else: diff --git a/unified/extractor/tests/corpus/swift/control-flow/if-let-optional-binding.output b/unified/extractor/tests/corpus/swift/control-flow/if-let-optional-binding.output index e878953ff7b4..097e721e5d40 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/if-let-optional-binding.output +++ b/unified/extractor/tests/corpus/swift/control-flow/if-let-optional-binding.output @@ -55,18 +55,18 @@ top_level source="⟨body⟩" stmt: if_expr source="if ⟨condition⟩ ⟨then⟩" condition: - pattern_guard_expr source="⟨pattern⟩⟨value⟩" + pattern_guard_expr source="⟨pattern⟩ = ⟨value⟩" pattern: - call_expr source="⟨argument⟩⟨callee⟩" + call_expr source="⟨argument⟩" callee: - member_access_expr source="⟨base⟩⟨member_name_node⟩" - base: identifier "Optional" source="let value = optional" - member_name_node: identifier "some" source="let value = optional" + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: - expr_pattern source="⟨modifier⟩⟨expr⟩" - modifier: modifier "let" source="let value = optional" + expr_pattern source="⟨modifier⟩ ⟨expr⟩" + modifier: modifier "let" source="let" expr: identifier "value" source="value" value: identifier "optional" source="optional" then: diff --git a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output index 0d403fd592ea..95d0a5585dcc 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output +++ b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output @@ -162,12 +162,12 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" value: identifier "event" source="event" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: expr_pattern source="⟨modifier⟩ ⟨expr⟩" modifier: modifier "let" source="let" expr: - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: member_access_expr source="⟨base⟩⟨member_name_node⟩" base: inferred_type_expr "." source="." @@ -175,7 +175,7 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: - call_expr source="⟨callee⟩(⟨argument⟩)," + call_expr source="⟨callee⟩(⟨argument⟩)" callee: member_access_expr source="⟨base⟩⟨member_name_node⟩" base: inferred_type_expr "." source="." @@ -186,16 +186,16 @@ top_level source="⟨body⟩" argument source="⟨value⟩" value: identifier "timestamp" source="timestamp" body: - block source="case let .received(.some(value), timestamp):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: identifier "print" source="print" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "value" source="value" argument source="⟨value⟩" value: identifier "timestamp" source="timestamp" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: call_expr source="⟨callee⟩(⟨argument⟩)" callee: @@ -209,14 +209,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" expr: identifier "value" source="value" body: - block source="case Type.some(let value):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: identifier "value" source="value" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: break_expr "break" source="break" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-case-item-where-clauses.output b/unified/extractor/tests/corpus/swift/control-flow/switch-case-item-where-clauses.output index a14f115a3f72..ddd959679201 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-case-item-where-clauses.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-case-item-where-clauses.output @@ -157,7 +157,7 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" value: identifier "n" source="n" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: conditional_pattern source="⟨pattern⟩ where ⟨condition⟩" condition: @@ -170,18 +170,18 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" expr: identifier "x" source="x" body: - block source="case let x where x > 0:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"positive\"" source="\"positive\"" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: - or_pattern source="case ⟨pattern⟩ ⟨pattern⟩:\n print(\"non-positive\")" + or_pattern source="⟨pattern⟩, ⟨pattern⟩" pattern: - conditional_pattern source="⟨pattern⟩ where ⟨condition⟩," + conditional_pattern source="⟨pattern⟩ where ⟨condition⟩" condition: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "y" source="y" @@ -193,16 +193,16 @@ top_level source="⟨body⟩" expr: identifier "y" source="y" int_literal "0" source="0" body: - block source="case let y where y < 0, 0:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"non-positive\"" source="\"non-positive\"" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output index e86af77df08d..0ecefc622b94 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-expression-pattern.output @@ -307,9 +307,9 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" value: identifier "subject" source="subject" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: - or_pattern source="case ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩,\n ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩,\n ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩:\n consume(value)" + or_pattern source="⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩,\n ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩,\n ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩, ⟨pattern⟩" pattern: identifier "value" source="value" binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" @@ -333,63 +333,63 @@ top_level source="⟨body⟩" member_access_expr source="⟨base⟩⟨member_name_node⟩" base: inferred_type_expr "." source="." member_name_node: identifier "inferred" source="inferred" - tuple_expr source="(⟨element⟩ ⟨element⟩)" + tuple_expr source="(⟨element⟩, ⟨element⟩)" element: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "value" source="value" argument source="⟨value⟩" value: identifier "offset" source="offset" array_literal source="[⟨element⟩]" element: identifier "value" source="value" map_literal "[key: value]" source="[key: value]" - call_expr source="⟨argument⟩⟨callee⟩" + call_expr source="⟨argument⟩?" callee: - member_access_expr source="⟨base⟩⟨member_name_node⟩" - base: identifier "Optional" source="optional?" - member_name_node: identifier "some" source="optional?" + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: - argument source="⟨value⟩?" + argument source="⟨value⟩" value: identifier "optional" source="optional" - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "try" source="try value" + operator: prefix_operator "try" source="try" unary_expr source="⟨operand⟩⟨operator⟩" operand: identifier "value" source="value" - operator: postfix_operator "!" source="value!" - type_cast_expr source="⟨expr⟩⟨operator⟩⟨type⟩" + operator: postfix_operator "!" source="!" + type_cast_expr source="⟨expr⟩ ⟨operator⟩ ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "as" source="value as Target" + operator: infix_operator "as" source="as" type: identifier "Target" source="Target" - type_test_expr source="⟨expr⟩⟨operator⟩⟨type⟩" + type_test_expr source="⟨expr⟩ ⟨operator⟩ ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "is" source="value is Target" + operator: infix_operator "is" source="is" type: identifier "Target" source="Target" - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "await" source="await value" + operator: prefix_operator "await" source="await" body: - block source="case value, value + offset, -value, lower...upper, makeValue(), makeValue().member,\n .inferred, (value, offset), [value], [key: value], optional?, try value,\n value!, value as Target, value is Target, await value:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "consume" source="consume" argument: argument source="⟨value⟩" value: identifier "value" source="value" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: if_expr source="⟨condition⟩ ? ⟨then⟩ : ⟨else⟩" condition: identifier "condition" source="condition" then: identifier "value" source="value" else: identifier "fallback" source="fallback" body: - block source="case condition ? value : fallback:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "consume" source="consume" argument: argument source="⟨value⟩" value: identifier "fallback" source="fallback" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: break_expr "break" source="break" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-statement.output b/unified/extractor/tests/corpus/swift/control-flow/switch-statement.output index 90372a736d22..7ff90754ac7a 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-statement.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-statement.output @@ -127,33 +127,33 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n⟨case⟩\n}" value: identifier "x" source="x" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: int_literal "1" source="1" body: - block source="case 1:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"one\"" source="\"one\"" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: - or_pattern source="case ⟨pattern⟩, ⟨pattern⟩:\n print(\"two or three\")" + or_pattern source="⟨pattern⟩, ⟨pattern⟩" pattern: int_literal "2" source="2" int_literal "3" source="3" body: - block source="case 2, 3:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"two or three\"" source="\"two or three\"" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output index 8d4d98ec7078..9d417531b74e 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-with-binding-pattern.output @@ -122,7 +122,7 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n}" value: identifier "shape" source="shape" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: call_expr source="⟨callee⟩(⟨argument⟩)" callee: @@ -136,14 +136,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" expr: identifier "r" source="r" body: - block source="case .circle(let r):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: identifier "r" source="r" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: call_expr source="⟨callee⟩(⟨argument⟩)" callee: @@ -157,7 +157,7 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" expr: identifier "s" source="s" body: - block source="case .square(let s):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/control-flow/switch-with-labeled-case-pattern-arguments.output b/unified/extractor/tests/corpus/swift/control-flow/switch-with-labeled-case-pattern-arguments.output index 8f7a0ae5f1f1..f700495a6c91 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/switch-with-labeled-case-pattern-arguments.output +++ b/unified/extractor/tests/corpus/swift/control-flow/switch-with-labeled-case-pattern-arguments.output @@ -130,7 +130,7 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n}" value: identifier "x" source="x" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: call_expr source="⟨callee⟩(⟨argument⟩)" callee: @@ -142,22 +142,22 @@ top_level source="⟨body⟩" name_node: identifier "isAcknowledged" source="isAcknowledged" value: boolean_literal "false" source="false" body: - block source="case .implicit(isAcknowledged: false):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" argument: argument source="⟨value⟩" value: string_literal "\"yes\"" source="\"yes\"" - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: member_access_expr source="⟨base⟩⟨member_name_node⟩" base: inferred_type_expr "." source="." member_name_node: identifier "thread" source="thread" argument: - argument source="⟨name_node⟩: ⟨value⟩," + argument source="⟨name_node⟩: ⟨value⟩" name_node: identifier "threadRowId" source="threadRowId" value: identifier "_" source="_" argument source="⟨value⟩" @@ -166,7 +166,7 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" expr: identifier "rowId" source="rowId" body: - block source="case .thread(threadRowId: _, let rowId):\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output index 2ab188e028f7..0dde851d7b0d 100644 --- a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output +++ b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output @@ -132,10 +132,10 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "values" source="values" value: - call_expr source="⟨callee⟩" + call_expr source="⟨callee⟩()" callee: - generic_type_expr source="⟨base⟩⟨type_argument⟩" - base: identifier "Array" source="[Result]()" + generic_type_expr source="[⟨type_argument⟩]" + base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" base: identifier "Result" source="Result" @@ -144,10 +144,10 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "initialized" source="initialized" value: - call_expr source="⟨argument⟩⟨callee⟩⟨argument⟩" + call_expr source="⟨callee⟩(⟨argument⟩) ⟨argument⟩" callee: - generic_type_expr source="⟨base⟩⟨type_argument⟩" - base: identifier "Array" source="[Result](unsafeUninitializedCapacity: 1) { _, count in\n\tcount = 0\n}" + generic_type_expr source="[⟨type_argument⟩]" + base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" base: identifier "Result" source="Result" @@ -156,11 +156,11 @@ top_level source="⟨body⟩" argument source="⟨name_node⟩: ⟨value⟩" name_node: identifier "unsafeUninitializedCapacity" source="unsafeUninitializedCapacity" value: int_literal "1" source="1" - argument source="[Result](unsafeUninitializedCapacity: 1) ⟨value⟩" + argument source="⟨value⟩" value: function_expr source="⟨body⟩⟨parameter⟩⟨parameter⟩" parameter: - parameter source="⟨pattern⟩," + parameter source="⟨pattern⟩" pattern: identifier "_" source="_" parameter source="⟨pattern⟩" pattern: identifier "count" source="count" diff --git a/unified/extractor/tests/corpus/swift/expressions/array-type-metatype.output b/unified/extractor/tests/corpus/swift/expressions/array-type-metatype.output index 98c721af9fab..8d0f690b12c6 100644 --- a/unified/extractor/tests/corpus/swift/expressions/array-type-metatype.output +++ b/unified/extractor/tests/corpus/swift/expressions/array-type-metatype.output @@ -56,10 +56,10 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "type" source="type" value: - member_access_expr source="⟨base⟩⟨member_name_node⟩" + member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: - generic_type_expr source="⟨base⟩⟨type_argument⟩" - base: identifier "Array" source="[Result].self" + generic_type_expr source="[⟨type_argument⟩]" + base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" base: identifier "Result" source="Result" diff --git a/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output b/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output index 06d2e76d6f55..427b4503f8ad 100644 --- a/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output +++ b/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output @@ -45,7 +45,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩\n⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "doWork" source="doWork" - body: block "func doWork() {}" source="func doWork() {}" + body: block "{}" source="{}" unsupported_node "unsafe doWork()" source="unsafe doWork()" diff --git a/unified/extractor/tests/corpus/swift/functions/call-with-inout-argument.output b/unified/extractor/tests/corpus/swift/functions/call-with-inout-argument.output index 6899013425de..588f6aafbd6b 100644 --- a/unified/extractor/tests/corpus/swift/functions/call-with-inout-argument.output +++ b/unified/extractor/tests/corpus/swift/functions/call-with-inout-argument.output @@ -81,10 +81,10 @@ top_level source="⟨body⟩" modifier: modifier "var" source="var" pattern: identifier "b" source="b" value: int_literal "2" source="2" - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: identifier "swap" source="swap" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: unsupported_node "&a" source="&a" argument source="⟨value⟩" value: unsupported_node "&b" source="&b" diff --git a/unified/extractor/tests/corpus/swift/functions/function-call.output b/unified/extractor/tests/corpus/swift/functions/function-call.output index 6f25208b0189..19f1d7cf988f 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-call.output +++ b/unified/extractor/tests/corpus/swift/functions/function-call.output @@ -31,10 +31,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: identifier "foo" source="foo" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: int_literal "1" source="1" argument source="⟨value⟩" value: int_literal "2" source="2" diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output b/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output index 65da7fc5c00f..9d283de0f316 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output @@ -65,7 +65,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) ⟨body⟩" name_node: identifier "greet" source="greet" parameter: parameter source="⟨pattern⟩: ⟨type⟩ = ⟨default⟩" @@ -73,7 +73,7 @@ top_level source="⟨body⟩" pattern: identifier "name" source="name" default: string_literal "\"world\"" source="\"world\"" body: - block source="func greet(name: String = \"world\") {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-inout-parameter.output b/unified/extractor/tests/corpus/swift/functions/function-with-inout-parameter.output index 54133b022968..2cb14ccacbb2 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-inout-parameter.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-inout-parameter.output @@ -61,7 +61,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) ⟨body⟩" name_node: identifier "increment" source="increment" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" @@ -69,7 +69,7 @@ top_level source="⟨body⟩" type: unsupported_node "inout Int" source="inout Int" pattern: identifier "x" source="x" body: - block source="func increment(_ x: inout Int) {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "x" source="x" diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-named-parameters.output b/unified/extractor/tests/corpus/swift/functions/function-with-named-parameters.output index 96d34925e8e7..878581f34212 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-named-parameters.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-named-parameters.output @@ -56,7 +56,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) ⟨body⟩" name_node: identifier "greet" source="greet" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" @@ -64,7 +64,7 @@ top_level source="⟨body⟩" type: identifier "String" source="String" pattern: identifier "name" source="name" body: - block source="func greet(person name: String) {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-no-parameters.output b/unified/extractor/tests/corpus/swift/functions/function-with-no-parameters.output index 901624c3b423..738cba0116ac 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-no-parameters.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-no-parameters.output @@ -51,10 +51,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "greet" source="greet" body: - block source="func greet() {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "print" source="print" diff --git a/unified/extractor/tests/corpus/swift/functions/function-with-parameters-and-return-type.output b/unified/extractor/tests/corpus/swift/functions/function-with-parameters-and-return-type.output index 1c200d26c675..1a5eb6bddd7c 100644 --- a/unified/extractor/tests/corpus/swift/functions/function-with-parameters-and-return-type.output +++ b/unified/extractor/tests/corpus/swift/functions/function-with-parameters-and-return-type.output @@ -73,10 +73,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩⟨parameter⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩, ⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "add" source="add" parameter: - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Int" source="Int" pattern: identifier "a" source="a" @@ -86,7 +86,7 @@ top_level source="⟨body⟩" pattern: identifier "b" source="b" return_type: identifier "Int" source="Int" body: - block source="func add(_ a: Int, _ b: Int) -> Int {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: diff --git a/unified/extractor/tests/corpus/swift/functions/generic-function.output b/unified/extractor/tests/corpus/swift/functions/generic-function.output index 280996f96f32..5c70307c6323 100644 --- a/unified/extractor/tests/corpus/swift/functions/generic-function.output +++ b/unified/extractor/tests/corpus/swift/functions/generic-function.output @@ -63,7 +63,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨type_parameter⟩⟨parameter⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩<⟨type_parameter⟩>(⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "identity" source="identity" type_parameter: type_parameter source="⟨name_node⟩" @@ -75,7 +75,7 @@ top_level source="⟨body⟩" pattern: identifier "x" source="x" return_type: identifier "T" source="T" body: - block source="func identity(_ x: T) -> T {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: identifier "x" source="x" diff --git a/unified/extractor/tests/corpus/swift/functions/generic-type-alias.output b/unified/extractor/tests/corpus/swift/functions/generic-type-alias.output index 5f06367b306b..4a7bb5d7b787 100644 --- a/unified/extractor/tests/corpus/swift/functions/generic-type-alias.output +++ b/unified/extractor/tests/corpus/swift/functions/generic-type-alias.output @@ -55,10 +55,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - type_alias_declaration source="typealias ⟨name_node⟩<⟨type_parameter⟩ ⟨type_parameter⟩> = ⟨type⟩" + type_alias_declaration source="typealias ⟨name_node⟩<⟨type_parameter⟩, ⟨type_parameter⟩> = ⟨type⟩" name_node: identifier "Box" source="Box" type_parameter: - type_parameter source="⟨name_node⟩: ⟨bound⟩," + type_parameter source="⟨name_node⟩: ⟨bound⟩" name_node: identifier "T" source="T" bound: identifier "Equatable" source="Equatable" type_parameter source="⟨name_node⟩" diff --git a/unified/extractor/tests/corpus/swift/functions/nested-function-type.output b/unified/extractor/tests/corpus/swift/functions/nested-function-type.output index d78d47dbbbb4..f4bdf2845df7 100644 --- a/unified/extractor/tests/corpus/swift/functions/nested-function-type.output +++ b/unified/extractor/tests/corpus/swift/functions/nested-function-type.output @@ -120,9 +120,9 @@ top_level source="⟨body⟩" type_alias_declaration source="typealias ⟨name_node⟩ = ⟨type⟩" name_node: identifier "MixedParametersAndTuples" source="MixedParametersAndTuples" type: - function_expr source="(⟨parameter⟩ ⟨parameter⟩) -> ⟨return_type⟩" + function_expr source="(⟨parameter⟩, ⟨parameter⟩) -> ⟨return_type⟩" parameter: - parameter source="⟨type⟩," + parameter source="⟨type⟩" type: function_expr source="(⟨parameter⟩) -> ⟨return_type⟩" parameter: @@ -132,9 +132,9 @@ top_level source="⟨body⟩" parameter source="⟨type⟩" type: identifier "String" source="String" return_type: - tuple_expr source="(⟨element⟩ ⟨element⟩)" + tuple_expr source="(⟨element⟩, ⟨element⟩)" element: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "Bool" source="Bool" argument source="⟨value⟩" value: identifier "Int" source="Int" diff --git a/unified/extractor/tests/corpus/swift/functions/variadic-function.output b/unified/extractor/tests/corpus/swift/functions/variadic-function.output index 0f73aabfd8cd..9d5d1a6e5b95 100644 --- a/unified/extractor/tests/corpus/swift/functions/variadic-function.output +++ b/unified/extractor/tests/corpus/swift/functions/variadic-function.output @@ -77,7 +77,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "sum" source="sum" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩..." @@ -86,17 +86,17 @@ top_level source="⟨body⟩" pattern: identifier "values" source="values" return_type: identifier "Int" source="Int" body: - block source="func sum(_ values: Int...) -> Int {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: - call_expr source="⟨callee⟩(⟨argument⟩ ⟨argument⟩)" + call_expr source="⟨callee⟩(⟨argument⟩, ⟨argument⟩)" callee: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: identifier "values" source="values" member_name_node: identifier "reduce" source="reduce" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: int_literal "0" source="0" argument source="⟨value⟩" value: identifier "+" source="+" diff --git a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output index 6e02c0f92968..fab3a3eb38ed 100644 --- a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output +++ b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output @@ -228,8 +228,8 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "hello " source="hello " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(name)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "name" source="name" @@ -237,14 +237,14 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩⟨element⟩⟨element⟩\"" element: string_literal "hello " source="hello " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(first)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "first" source="first" string_literal " " source=" " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(last)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "last" source="last" @@ -252,8 +252,8 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "result: " source="result: " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(x + y)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: @@ -265,8 +265,8 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩⟨element⟩\"" element: string_literal "prefix " source="prefix " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(value)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "value" source="value" @@ -274,10 +274,10 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="⟨callee⟩⟨argument⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(x, y)" + call_expr source="\\(⟨argument⟩, ⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "x" source="x" argument source="⟨value⟩" value: identifier "y" source="y" @@ -285,12 +285,12 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="⟨callee⟩⟨argument⟩⟨argument⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(x, y, z)" + call_expr source="\\(⟨argument⟩, ⟨argument⟩, ⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "x" source="x" - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "y" source="y" argument source="⟨value⟩" value: identifier "z" source="z" @@ -298,8 +298,8 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="⟨callee⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(arg: x)" + call_expr source="\\(⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: argument source="⟨name_node⟩: ⟨value⟩" name_node: identifier "arg" source="arg" @@ -308,10 +308,10 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="⟨callee⟩⟨argument⟩⟨argument⟩" - callee: builtin_expr "interpolation" source="\\(arg: x, arg2: y)" + call_expr source="\\(⟨argument⟩, ⟨argument⟩)" + callee: builtin_expr "interpolation" source="" argument: - argument source="⟨name_node⟩: ⟨value⟩," + argument source="⟨name_node⟩: ⟨value⟩" name_node: identifier "arg" source="arg" value: identifier "x" source="x" argument source="⟨name_node⟩: ⟨value⟩" diff --git a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output index 0cdfd8b9d43b..9349b1f231dc 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-casts.output @@ -93,10 +93,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩, ⟨parameter⟩) ⟨body⟩" name_node: identifier "casts" source="casts" parameter: - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Any" source="Any" pattern: identifier "a" source="a" @@ -105,7 +105,7 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "b" source="b" body: - block source="func casts(_ a: Any, _ b: Int) {\n ⟨stmt⟩\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n ⟨stmt⟩\n}" stmt: unresolved_operator_sequence source="⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩" element: diff --git a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-ternary.output b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-ternary.output index f0b2c64b9d91..c4a869673049 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-ternary.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence-with-ternary.output @@ -99,18 +99,18 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩⟨parameter⟩⟨parameter⟩⟨parameter⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩, ⟨parameter⟩, ⟨parameter⟩, ⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "choose" source="choose" parameter: - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Bool" source="Bool" pattern: identifier "c" source="c" - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Int" source="Int" pattern: identifier "a" source="a" - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Int" source="Int" pattern: identifier "b" source="b" @@ -120,7 +120,7 @@ top_level source="⟨body⟩" pattern: identifier "d" source="d" return_type: identifier "Int" source="Int" body: - block source="func choose(_ c: Bool, _ a: Int, _ b: Int, _ d: Int) -> Int {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: diff --git a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output index 2ed6779f4c89..8e0f15b58b0e 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output @@ -66,10 +66,10 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨parameter⟩⟨parameter⟩" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩, ⟨parameter⟩) ⟨body⟩" name_node: identifier "combine" source="combine" parameter: - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "_" source="_" type: identifier "Int" source="Int" pattern: identifier "a" source="a" @@ -78,7 +78,7 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "b" source="b" body: - block source="func combine(_ a: Int, _ b: Int) {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: unresolved_operator_sequence source="⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩ ⟨element⟩" element: diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-where-clauses.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-where-clauses.output index c1937aca8255..5506b163346f 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-where-clauses.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/catch-where-clauses.output @@ -144,17 +144,17 @@ top_level source="⟨body⟩" body: block source="{\n ⟨stmt⟩\n}" stmt: - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="try foo()" + operator: prefix_operator "try" source="try" catch_clause: - catch_clause source="⟨pattern⟩⟨body⟩" + catch_clause source="catch ⟨pattern⟩ ⟨body⟩" pattern: - or_pattern source="catch ⟨pattern⟩ ⟨pattern⟩ {\n print(\"retry\")\n}" + or_pattern source="⟨pattern⟩, ⟨pattern⟩" pattern: - conditional_pattern source="⟨pattern⟩ where ⟨condition⟩," + conditional_pattern source="⟨pattern⟩ where ⟨condition⟩" condition: call_expr source="⟨callee⟩(⟨argument⟩)" callee: identifier "isNetworkError" source="isNetworkError" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/do-catch.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/do-catch.output index 0c5009e02fc3..b97772cd71a4 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/do-catch.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/do-catch.output @@ -65,11 +65,11 @@ top_level source="⟨body⟩" body: block source="{\n ⟨stmt⟩\n}" stmt: - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="try foo()" + operator: prefix_operator "try" source="try" catch_clause: catch_clause source="catch ⟨body⟩" body: diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/force-unwrap.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/force-unwrap.output index 4d8b84743253..8ed940058d75 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/force-unwrap.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/force-unwrap.output @@ -38,4 +38,4 @@ top_level source="⟨body⟩" value: unary_expr source="⟨operand⟩⟨operator⟩" operand: identifier "opt" source="opt" - operator: postfix_operator "!" source="opt!" + operator: postfix_operator "!" source="!" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-enum-case-binding.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-enum-case-binding.output index 739fcb48ec29..6e2b26b9678f 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-enum-case-binding.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-enum-case-binding.output @@ -80,13 +80,13 @@ top_level source="⟨body⟩" condition: pattern_guard_expr source="case ⟨pattern⟩ = ⟨value⟩" pattern: - call_expr source="⟨argument⟩⟨callee⟩" + call_expr source="⟨argument⟩?" callee: - member_access_expr source="⟨base⟩⟨member_name_node⟩" - base: identifier "Optional" source=".some(let value)?" - member_name_node: identifier "some" source=".some(let value)?" + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: - argument source="⟨value⟩?" + argument source="⟨value⟩" value: call_expr source="⟨callee⟩(⟨argument⟩)" callee: diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-type-annotation.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-type-annotation.output index 6860e38d7a3a..ceb65bc91c9c 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-type-annotation.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/optional-type-annotation.output @@ -42,7 +42,7 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "x" source="x" type: - generic_type_expr source="⟨type_argument⟩⟨base⟩" - base: identifier "Optional" source="Int?" + generic_type_expr source="⟨type_argument⟩?" + base: identifier "Optional" source="" type_argument: identifier "Int" source="Int" value: builtin_expr "nil" source="nil" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/throwing-function.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/throwing-function.output index 5be898e21651..6e6cc3b99e18 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/throwing-function.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/throwing-function.output @@ -55,11 +55,11 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="⟨body⟩⟨name_node⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩() throws -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "read" source="read" return_type: identifier "String" source="String" body: - block source="func read() throws -> String {\n ⟨stmt⟩\n}" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: string_literal "\"\"" source="\"\"" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression-2.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression-2.output index 4faa3545ea5c..0949c7553141 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression-2.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression-2.output @@ -43,8 +43,8 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "result" source="result" value: - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try!" source="try! foo()" + operator: prefix_operator "try!" source="try!" diff --git a/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression.output index 57464ed82141..a5169c10141c 100644 --- a/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression.output +++ b/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression.output @@ -43,8 +43,8 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "result" source="result" value: - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try?" source="try? foo()" + operator: prefix_operator "try?" source="try?" diff --git a/unified/extractor/tests/corpus/swift/types/binding-modifier-does-not-leak-into-accessor-body.output b/unified/extractor/tests/corpus/swift/types/binding-modifier-does-not-leak-into-accessor-body.output index 6a02642ced38..88674d76efbd 100644 --- a/unified/extractor/tests/corpus/swift/types/binding-modifier-does-not-leak-into-accessor-body.output +++ b/unified/extractor/tests/corpus/swift/types/binding-modifier-does-not-leak-into-accessor-body.output @@ -92,31 +92,31 @@ sourceFile --- -top_level source="⟨body⟩" +top_level source="var p: Int {\n ⟨body⟩\n}" body: - block source="⟨stmt⟩\n}" + block source="⟨stmt⟩" stmt: - accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n ⟨accessor_kind⟩ ⟨body⟩" - modifier: modifier "var" source="var" - name_node: identifier "p" source="p" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" + modifier: modifier "var" source="var" (external) + name_node: identifier "p" source="p" (external) accessor_kind: accessor_kind "get" source="get" - type: identifier "Int" source="Int" + type: identifier "Int" source="Int" (external) body: block source="{\n ⟨stmt⟩\n }" stmt: switch_expr source="switch ⟨value⟩ {\n ⟨case⟩\n ⟨case⟩\n }" value: identifier "y" source="y" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: identifier "someConstant" source="someConstant" body: - block source="case someConstant:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: return_expr source="return ⟨value⟩" value: int_literal "1" source="1" - switch_case source="⟨body⟩" + switch_case source="default:\n ⟨body⟩" body: - block source="default:\n ⟨stmt⟩" + block source="⟨stmt⟩" stmt: return_expr source="return ⟨value⟩" value: int_literal "2" source="2" diff --git a/unified/extractor/tests/corpus/swift/types/class-function.output b/unified/extractor/tests/corpus/swift/types/class-function.output index a3084367cea1..9b3770561a37 100644 --- a/unified/extractor/tests/corpus/swift/types/class-function.output +++ b/unified/extractor/tests/corpus/swift/types/class-function.output @@ -51,7 +51,7 @@ top_level source="⟨body⟩" modifier: modifier "class" source="class" name_node: identifier "Factory" source="Factory" member: - function_declaration source="⟨modifier⟩⟨body⟩⟨name_node⟩" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "class" source="class" name_node: identifier "make" source="make" - body: block "class func make() {}" source="class func make() {}" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/types/class-inheritance.output b/unified/extractor/tests/corpus/swift/types/class-inheritance.output index 28a35c0906ff..7ab4d280ebc6 100644 --- a/unified/extractor/tests/corpus/swift/types/class-inheritance.output +++ b/unified/extractor/tests/corpus/swift/types/class-inheritance.output @@ -32,9 +32,9 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩⟨base_type⟩⟨name_node⟩" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨base_type⟩ {}" modifier: modifier "class" source="class" name_node: identifier "Dog" source="Dog" base_type: - base_type source="class Dog: ⟨type⟩ {}" + base_type source="⟨type⟩" type: identifier "Animal" source="Animal" diff --git a/unified/extractor/tests/corpus/swift/types/class-with-initializer.output b/unified/extractor/tests/corpus/swift/types/class-with-initializer.output index f5e85a979d67..702b4da82448 100644 --- a/unified/extractor/tests/corpus/swift/types/class-with-initializer.output +++ b/unified/extractor/tests/corpus/swift/types/class-with-initializer.output @@ -98,13 +98,13 @@ top_level source="⟨body⟩" modifier: modifier "var" source="var" pattern: identifier "x" source="x" type: identifier "Int" source="Int" - constructor_declaration source="⟨body⟩⟨parameter⟩" + constructor_declaration source="init(⟨parameter⟩) ⟨body⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" body: - block source="init(x: Int) {\n ⟨stmt⟩\n }" + block source="{\n ⟨stmt⟩\n }" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: diff --git a/unified/extractor/tests/corpus/swift/types/class-with-method.output b/unified/extractor/tests/corpus/swift/types/class-with-method.output index 64981979359d..8752f5c37a50 100644 --- a/unified/extractor/tests/corpus/swift/types/class-with-method.output +++ b/unified/extractor/tests/corpus/swift/types/class-with-method.output @@ -85,10 +85,10 @@ top_level source="⟨body⟩" modifier: modifier "var" source="var" pattern: identifier "n" source="n" value: int_literal "0" source="0" - function_declaration source="⟨body⟩⟨name_node⟩" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "bump" source="bump" body: - block source="func bump() {\n ⟨stmt⟩\n }" + block source="{\n ⟨stmt⟩\n }" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "n" source="n" diff --git a/unified/extractor/tests/corpus/swift/types/class-with-multiple-base-types.output b/unified/extractor/tests/corpus/swift/types/class-with-multiple-base-types.output index f2a839add74c..700a0e6eccc2 100644 --- a/unified/extractor/tests/corpus/swift/types/class-with-multiple-base-types.output +++ b/unified/extractor/tests/corpus/swift/types/class-with-multiple-base-types.output @@ -37,11 +37,11 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩⟨base_type⟩⟨base_type⟩⟨name_node⟩" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨base_type⟩, ⟨base_type⟩ {}" modifier: modifier "class" source="class" name_node: identifier "Button" source="Button" base_type: - base_type source="class Button: ⟨type⟩, Drawable {}" + base_type source="⟨type⟩" type: identifier "Control" source="Control" - base_type source="class Button: Control, ⟨type⟩ {}" + base_type source="⟨type⟩" type: identifier "Drawable" source="Drawable" diff --git a/unified/extractor/tests/corpus/swift/types/computed-property.output b/unified/extractor/tests/corpus/swift/types/computed-property.output index b4021e9dfdbb..a88f7a20956d 100644 --- a/unified/extractor/tests/corpus/swift/types/computed-property.output +++ b/unified/extractor/tests/corpus/swift/types/computed-property.output @@ -113,13 +113,13 @@ top_level source="⟨body⟩" modifier: modifier "var" source="var" pattern: identifier "h" source="h" type: identifier "Double" source="Double" - accessor_declaration source="⟨modifier⟩⟨accessor_kind⟩⟨body⟩⟨name_node⟩⟨type⟩" + accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ ⟨body⟩" modifier: modifier "var" source="var" name_node: identifier "area" source="area" - accessor_kind: accessor_kind "get" source="var area: Double {\n return w * h\n }" + accessor_kind: accessor_kind "get" source="" type: identifier "Double" source="Double" body: - block source="var area: Double {\n ⟨stmt⟩\n }" + block source="{\n ⟨stmt⟩\n }" stmt: return_expr source="return ⟨value⟩" value: diff --git a/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output index 72d8952ea356..9aca7926d719 100644 --- a/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output +++ b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output @@ -67,9 +67,9 @@ top_level source="⟨body⟩" modifier: modifier "struct" source="struct" name_node: identifier "Size" source="Size" member: - constructor_declaration source="⟨body⟩⟨parameter⟩⟨parameter⟩" + constructor_declaration source="init(⟨parameter⟩, ⟨parameter⟩) ⟨body⟩" parameter: - parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," + parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" external_name_node: identifier "width" source="width" type: identifier "Int" source="Int" pattern: identifier "w" source="w" @@ -77,4 +77,4 @@ top_level source="⟨body⟩" external_name_node: identifier "height" source="height" type: identifier "Int" source="Int" pattern: identifier "h" source="h" - body: block "init(width w: Int, height h: Int) {}" source="init(width w: Int, height h: Int) {}" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/types/enum-with-associated-values.output b/unified/extractor/tests/corpus/swift/types/enum-with-associated-values.output index ef7a079eabf9..2d0432557fe5 100644 --- a/unified/extractor/tests/corpus/swift/types/enum-with-associated-values.output +++ b/unified/extractor/tests/corpus/swift/types/enum-with-associated-values.output @@ -73,23 +73,23 @@ top_level source="⟨body⟩" modifier: modifier "enum" source="enum" name_node: identifier "Shape" source="Shape" member: - class_like_declaration source="⟨name_node⟩⟨member⟩⟨modifier⟩" - modifier: modifier "enum_case" source="circle(radius: Double)" + class_like_declaration source="⟨name_node⟩⟨member⟩" + modifier: modifier "enum_case" source="" name_node: identifier "circle" source="circle" member: - constructor_declaration source="⟨body⟩⟨parameter⟩" + constructor_declaration source="circle(⟨parameter⟩)" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" pattern: identifier "radius" source="radius" - body: block "circle(radius: Double)" source="circle(radius: Double)" - class_like_declaration source="⟨name_node⟩⟨member⟩⟨modifier⟩" - modifier: modifier "enum_case" source="square(side: Double)" + body: block source="" + class_like_declaration source="⟨name_node⟩⟨member⟩" + modifier: modifier "enum_case" source="" name_node: identifier "square" source="square" member: - constructor_declaration source="⟨body⟩⟨parameter⟩" + constructor_declaration source="square(⟨parameter⟩)" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" pattern: identifier "side" source="side" - body: block "square(side: Double)" source="square(side: Double)" + body: block source="" diff --git a/unified/extractor/tests/corpus/swift/types/enum-with-cases.output b/unified/extractor/tests/corpus/swift/types/enum-with-cases.output index a66dc1f2d7c0..8b3fa7f85775 100644 --- a/unified/extractor/tests/corpus/swift/types/enum-with-cases.output +++ b/unified/extractor/tests/corpus/swift/types/enum-with-cases.output @@ -69,15 +69,15 @@ top_level source="⟨body⟩" modifier: modifier "enum" source="enum" name_node: identifier "Direction" source="Direction" member: - variable_declaration source="⟨modifier⟩⟨pattern⟩" - modifier: modifier "enum_case" source="north" + variable_declaration source="⟨pattern⟩" + modifier: modifier "enum_case" source="" pattern: identifier "north" source="north" - variable_declaration source="⟨modifier⟩⟨pattern⟩" - modifier: modifier "enum_case" source="south" + variable_declaration source="⟨pattern⟩" + modifier: modifier "enum_case" source="" pattern: identifier "south" source="south" - variable_declaration source="⟨modifier⟩⟨pattern⟩" - modifier: modifier "enum_case" source="east" + variable_declaration source="⟨pattern⟩" + modifier: modifier "enum_case" source="" pattern: identifier "east" source="east" - variable_declaration source="⟨modifier⟩⟨pattern⟩" - modifier: modifier "enum_case" source="west" + variable_declaration source="⟨pattern⟩" + modifier: modifier "enum_case" source="" pattern: identifier "west" source="west" diff --git a/unified/extractor/tests/corpus/swift/types/enum-with-comma-separated-cases-chained-declaration.output b/unified/extractor/tests/corpus/swift/types/enum-with-comma-separated-cases-chained-declaration.output index 97945a6cc910..8325b84b5bef 100644 --- a/unified/extractor/tests/corpus/swift/types/enum-with-comma-separated-cases-chained-declaration.output +++ b/unified/extractor/tests/corpus/swift/types/enum-with-comma-separated-cases-chained-declaration.output @@ -44,25 +44,25 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n case ⟨member⟩ ⟨member⟩ ⟨member⟩ ⟨member⟩\n}" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n case ⟨member⟩, ⟨member⟩, ⟨member⟩, ⟨member⟩\n}" modifier: modifier "enum" source="enum" name_node: identifier "Suit" source="Suit" member: - variable_declaration source="⟨pattern⟩⟨modifier⟩" - modifier: modifier "enum_case" source="clubs," + variable_declaration source="⟨pattern⟩" + modifier: modifier "enum_case" source="" pattern: identifier "clubs" source="clubs" - variable_declaration source="⟨pattern⟩⟨modifier⟩⟨modifier⟩" + variable_declaration source="⟨pattern⟩" modifier: - modifier "chained_declaration" source="diamonds," - modifier "enum_case" source="diamonds," + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "diamonds" source="diamonds" - variable_declaration source="⟨pattern⟩⟨modifier⟩⟨modifier⟩" + variable_declaration source="⟨pattern⟩" modifier: - modifier "chained_declaration" source="hearts," - modifier "enum_case" source="hearts," + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "hearts" source="hearts" - variable_declaration source="⟨modifier⟩⟨modifier⟩⟨pattern⟩" + variable_declaration source="⟨pattern⟩" modifier: - modifier "chained_declaration" source="spades" - modifier "enum_case" source="spades" + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "spades" source="spades" diff --git a/unified/extractor/tests/corpus/swift/types/extension.output b/unified/extractor/tests/corpus/swift/types/extension.output index 0ab670eb5cfd..2830565acf9a 100644 --- a/unified/extractor/tests/corpus/swift/types/extension.output +++ b/unified/extractor/tests/corpus/swift/types/extension.output @@ -72,11 +72,11 @@ top_level source="⟨body⟩" modifier: modifier "extension" source="extension" extension_target: identifier "Int" source="Int" member: - function_declaration source="⟨body⟩⟨name_node⟩⟨return_type⟩" + function_declaration source="func ⟨name_node⟩() -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "squared" source="squared" return_type: identifier "Int" source="Int" body: - block source="func squared() -> Int { ⟨stmt⟩ }" + block source="{ ⟨stmt⟩ }" stmt: return_expr source="return ⟨value⟩" value: diff --git a/unified/extractor/tests/corpus/swift/types/generic-class-parameters-and-constraints.output b/unified/extractor/tests/corpus/swift/types/generic-class-parameters-and-constraints.output index 8e057dfae084..dd8eebf431b1 100644 --- a/unified/extractor/tests/corpus/swift/types/generic-class-parameters-and-constraints.output +++ b/unified/extractor/tests/corpus/swift/types/generic-class-parameters-and-constraints.output @@ -66,17 +66,17 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩ ⟨name_node⟩<⟨type_parameter⟩ ⟨type_parameter⟩> where ⟨type_constraint⟩ ⟨type_constraint⟩ {\n}" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩<⟨type_parameter⟩, ⟨type_parameter⟩> where ⟨type_constraint⟩, ⟨type_constraint⟩ {\n}" modifier: modifier "class" source="class" name_node: identifier "Box" source="Box" type_parameter: - type_parameter source="⟨name_node⟩: ⟨bound⟩," + type_parameter source="⟨name_node⟩: ⟨bound⟩" name_node: identifier "T" source="T" bound: identifier "Equatable" source="Equatable" type_parameter source="⟨name_node⟩" name_node: identifier "U" source="U" type_constraint: - bound_type_constraint source="⟨type⟩: ⟨bound⟩," + bound_type_constraint source="⟨type⟩: ⟨bound⟩" type: identifier "U" source="U" bound: identifier "Equatable" source="Equatable" equality_type_constraint source="⟨left⟩ == ⟨right⟩" diff --git a/unified/extractor/tests/corpus/swift/types/noncopyable-type.output b/unified/extractor/tests/corpus/swift/types/noncopyable-type.output index 0a22d1ca0b07..4e3238bf4e62 100644 --- a/unified/extractor/tests/corpus/swift/types/noncopyable-type.output +++ b/unified/extractor/tests/corpus/swift/types/noncopyable-type.output @@ -54,11 +54,11 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩⟨base_type⟩⟨name_node⟩⟨member⟩" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨base_type⟩ {\n ⟨member⟩\n}" modifier: modifier "struct" source="struct" name_node: identifier "FileHandle" source="FileHandle" base_type: - base_type source="struct FileHandle: ⟨type⟩ {\n let descriptor: Int\n}" + base_type source="⟨type⟩" type: unsupported_node "~Copyable" source="~Copyable" member: variable_declaration source="⟨modifier⟩ ⟨pattern⟩: ⟨type⟩" diff --git a/unified/extractor/tests/corpus/swift/types/property-with-getter-and-setter.output b/unified/extractor/tests/corpus/swift/types/property-with-getter-and-setter.output index f84cf98e24c4..00e111bf77ad 100644 --- a/unified/extractor/tests/corpus/swift/types/property-with-getter-and-setter.output +++ b/unified/extractor/tests/corpus/swift/types/property-with-getter-and-setter.output @@ -106,7 +106,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n ⟨member⟩\n ⟨member⟩⟨member⟩\n }\n}" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n ⟨member⟩\n var v: Int {\n ⟨member⟩\n ⟨member⟩\n }\n}" modifier: modifier "class" source="class" name_node: identifier "Box" source="Box" member: @@ -116,23 +116,23 @@ top_level source="⟨body⟩" modifier "private" source="private" pattern: identifier "_v" source="_v" value: int_literal "0" source="0" - accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n ⟨accessor_kind⟩ ⟨body⟩" - modifier: modifier "var" source="var" - name_node: identifier "v" source="v" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" + modifier: modifier "var" source="var" (external) + name_node: identifier "v" source="v" (external) accessor_kind: accessor_kind "get" source="get" - type: identifier "Int" source="Int" + type: identifier "Int" source="Int" (external) body: block source="{ ⟨stmt⟩ }" stmt: return_expr source="return ⟨value⟩" value: identifier "_v" source="_v" - accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n get { return _v }\n ⟨accessor_kind⟩⟨modifier⟩⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" - modifier "chained_declaration" source="set { _v = newValue }" - name_node: identifier "v" source="v" + modifier "var" source="var" (external) + modifier "chained_declaration" source="" + name_node: identifier "v" source="v" (external) accessor_kind: accessor_kind "set" source="set" - type: identifier "Int" source="Int" + type: identifier "Int" source="Int" (external) body: block source="{ ⟨stmt⟩ }" stmt: diff --git a/unified/extractor/tests/corpus/swift/types/protocol-declaration.output b/unified/extractor/tests/corpus/swift/types/protocol-declaration.output index b2bc4b1e1867..5f1155e278a8 100644 --- a/unified/extractor/tests/corpus/swift/types/protocol-declaration.output +++ b/unified/extractor/tests/corpus/swift/types/protocol-declaration.output @@ -61,10 +61,10 @@ top_level source="⟨body⟩" modifier: modifier "protocol" source="protocol" name_node: identifier "Drawable" source="Drawable" member: - function_declaration source="⟨body⟩⟨name_node⟩" + function_declaration source="func ⟨name_node⟩()" name_node: identifier "draw" source="draw" - body: block "func draw()" source="func draw()" - function_declaration source="⟨modifier⟩⟨body⟩⟨name_node⟩" + body: block source="" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩()" modifier: modifier "static" source="static" name_node: identifier "make" source="make" - body: block "static func make()" source="static func make()" + body: block source="" diff --git a/unified/extractor/tests/corpus/swift/types/protocol-with-read-only-and-read-write-property-requirements.output b/unified/extractor/tests/corpus/swift/types/protocol-with-read-only-and-read-write-property-requirements.output index 0a3277df185c..8a43a3c70588 100644 --- a/unified/extractor/tests/corpus/swift/types/protocol-with-read-only-and-read-write-property-requirements.output +++ b/unified/extractor/tests/corpus/swift/types/protocol-with-read-only-and-read-write-property-requirements.output @@ -106,24 +106,24 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n var ⟨member⟩ }\n var ⟨member⟩⟨member⟩ }\n var ⟨member⟩ }\n}" + class_like_declaration source="⟨modifier⟩ ⟨name_node⟩ {\n var foo: Int { ⟨member⟩ }\n var bar: String { ⟨member⟩ ⟨member⟩ }\n var count: Int { ⟨member⟩ }\n}" modifier: modifier "protocol" source="protocol" name_node: identifier "P" source="P" member: - accessor_declaration source="⟨name_node⟩: ⟨type⟩ { ⟨accessor_kind⟩" - name_node: identifier "foo" source="foo" + accessor_declaration source="⟨accessor_kind⟩" + name_node: identifier "foo" source="foo" (external) accessor_kind: accessor_kind "get" source="get" - type: identifier "Int" source="Int" - accessor_declaration source="⟨name_node⟩: ⟨type⟩ { ⟨accessor_kind⟩" - name_node: identifier "bar" source="bar" + type: identifier "Int" source="Int" (external) + accessor_declaration source="⟨accessor_kind⟩" + name_node: identifier "bar" source="bar" (external) accessor_kind: accessor_kind "get" source="get" - type: identifier "String" source="String" - accessor_declaration source="⟨name_node⟩: ⟨type⟩ { get ⟨accessor_kind⟩⟨modifier⟩" - modifier: modifier "chained_declaration" source="set" - name_node: identifier "bar" source="bar" + type: identifier "String" source="String" (external) + accessor_declaration source="⟨accessor_kind⟩" + modifier: modifier "chained_declaration" source="" + name_node: identifier "bar" source="bar" (external) accessor_kind: accessor_kind "set" source="set" - type: identifier "String" source="String" - accessor_declaration source="⟨name_node⟩: ⟨type⟩ { ⟨accessor_kind⟩" - name_node: identifier "count" source="count" + type: identifier "String" source="String" (external) + accessor_declaration source="⟨accessor_kind⟩" + name_node: identifier "count" source="count" (external) accessor_kind: accessor_kind "get" source="get" - type: identifier "Int" source="Int" + type: identifier "Int" source="Int" (external) diff --git a/unified/extractor/tests/corpus/swift/types/static-function.output b/unified/extractor/tests/corpus/swift/types/static-function.output index b7f87ab13d76..0f27333bac05 100644 --- a/unified/extractor/tests/corpus/swift/types/static-function.output +++ b/unified/extractor/tests/corpus/swift/types/static-function.output @@ -51,7 +51,7 @@ top_level source="⟨body⟩" modifier: modifier "class" source="class" name_node: identifier "Factory" source="Factory" member: - function_declaration source="⟨modifier⟩⟨body⟩⟨name_node⟩" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "static" source="static" name_node: identifier "make" source="make" - body: block "static func make() {}" source="static func make() {}" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/variables/binding-modifier-does-not-leak-into-initializer.output b/unified/extractor/tests/corpus/swift/variables/binding-modifier-does-not-leak-into-initializer.output index 90e58be069ad..d42155011399 100644 --- a/unified/extractor/tests/corpus/swift/variables/binding-modifier-does-not-leak-into-initializer.output +++ b/unified/extractor/tests/corpus/swift/variables/binding-modifier-does-not-leak-into-initializer.output @@ -72,12 +72,12 @@ top_level source="⟨body⟩" switch_expr source="switch ⟨value⟩ {\n⟨case⟩\n⟨case⟩\n}" value: identifier "y" source="y" case: - switch_case source="⟨body⟩⟨pattern⟩" + switch_case source="case ⟨pattern⟩: ⟨body⟩" pattern: identifier "someConstant" source="someConstant" body: - block source="case someConstant: ⟨stmt⟩" + block source="⟨stmt⟩" stmt: int_literal "1" source="1" - switch_case source="⟨body⟩" + switch_case source="default: ⟨body⟩" body: - block source="default: ⟨stmt⟩" + block source="⟨stmt⟩" stmt: int_literal "2" source="2" diff --git a/unified/extractor/tests/corpus/swift/variables/multiple-bindings-on-one-line.output b/unified/extractor/tests/corpus/swift/variables/multiple-bindings-on-one-line.output index fd6057bfb1f8..5a4907fed714 100644 --- a/unified/extractor/tests/corpus/swift/variables/multiple-bindings-on-one-line.output +++ b/unified/extractor/tests/corpus/swift/variables/multiple-bindings-on-one-line.output @@ -40,13 +40,13 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩⟨stmt⟩" stmt: - variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩," + variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" pattern: identifier "x" source="x" value: int_literal "1" source="1" - variable_declaration source="⟨modifier⟩ x = 1, ⟨pattern⟩⟨modifier⟩⟨value⟩" + variable_declaration source="⟨modifier⟩ x = 1, ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" - modifier "chained_declaration" source="y = 2" + modifier "chained_declaration" source="" pattern: identifier "y" source="y" value: int_literal "2" source="2" diff --git a/unified/extractor/tests/corpus/swift/variables/property-with-willset-and-didset-observers.output b/unified/extractor/tests/corpus/swift/variables/property-with-willset-and-didset-observers.output index 13397f03e6fd..1f2ff4a67244 100644 --- a/unified/extractor/tests/corpus/swift/variables/property-with-willset-and-didset-observers.output +++ b/unified/extractor/tests/corpus/swift/variables/property-with-willset-and-didset-observers.output @@ -110,11 +110,11 @@ top_level source="⟨body⟩" pattern: identifier "x" source="x" type: identifier "Int" source="Int" value: int_literal "0" source="0" - accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n ⟨accessor_kind⟩⟨modifier⟩⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" - modifier "chained_declaration" source="willSet { print(newValue) }" - name_node: identifier "x" source="x" + modifier "var" source="var" (external) + modifier "chained_declaration" source="" + name_node: identifier "x" source="x" (external) accessor_kind: accessor_kind "willSet" source="willSet" body: block source="{ ⟨stmt⟩ }" @@ -124,11 +124,11 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: identifier "newValue" source="newValue" - accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n willSet { print(newValue) }\n ⟨accessor_kind⟩⟨modifier⟩⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" - modifier "chained_declaration" source="didSet { print(oldValue) }" - name_node: identifier "x" source="x" + modifier "var" source="var" (external) + modifier "chained_declaration" source="" + name_node: identifier "x" source="x" (external) accessor_kind: accessor_kind "didSet" source="didSet" body: block source="{ ⟨stmt⟩ }" diff --git a/unified/extractor/tests/corpus/swift/variables/tuple-destructuring-binding.output b/unified/extractor/tests/corpus/swift/variables/tuple-destructuring-binding.output index 794c3e5054ec..54f978c8c25b 100644 --- a/unified/extractor/tests/corpus/swift/variables/tuple-destructuring-binding.output +++ b/unified/extractor/tests/corpus/swift/variables/tuple-destructuring-binding.output @@ -43,9 +43,9 @@ top_level source="⟨body⟩" variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" pattern: - tuple_expr source="(⟨element⟩ ⟨element⟩)" + tuple_expr source="(⟨element⟩, ⟨element⟩)" element: - argument source="⟨value⟩," + argument source="⟨value⟩" value: identifier "a" source="a" argument source="⟨value⟩" value: identifier "b" source="b" diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs new file mode 100644 index 000000000000..30ace4016f80 --- /dev/null +++ b/unified/extractor/tests/location_tests.rs @@ -0,0 +1,178 @@ +use yeast::Ast; + +#[path = "../src/languages/mod.rs"] +mod languages; + +fn desugar(source: &str) -> Ast { + let lang = languages::all_language_specs() + .into_iter() + .find(|language| { + language + .file_globs + .iter() + .any(|glob| glob.contains("swift")) + }) + .expect("Swift language spec"); + let parsed = (lang.parser)(source.as_bytes()).expect("Swift should parse"); + lang.desugarer + .run_from_ast(parsed.ast) + .expect("Swift should desugar") +} + +fn spans(ast: &Ast, source: &str, kind: &str, content: Option<&str>) -> Vec { + ranges(ast, kind, content) + .into_iter() + .filter_map(|range| source.get(range).map(str::to_owned)) + .collect() +} + +fn ranges(ast: &Ast, kind: &str, content: Option<&str>) -> Vec> { + ast.reachable_node_ids() + .into_iter() + .filter_map(|id| { + let node = ast.get_node(id)?; + if node.kind_name() != kind + || content + .is_some_and(|content| node.opt_string_content().as_deref() != Some(content)) + { + return None; + } + node.source_range() + .map(|range| range.start_byte..range.end_byte) + }) + .collect() +} + +fn assert_has_span(ast: &Ast, source: &str, kind: &str, content: Option<&str>, expected: &str) { + let spans = spans(ast, source, kind, content); + assert!( + spans.iter().any(|span| span == expected), + "expected {kind} {content:?} to span {expected:?}, got {spans:?}" + ); +} + +fn assert_has_empty_span(ast: &Ast, kind: &str, content: Option<&str>, expected_offset: usize) { + let ranges = ranges(ast, kind, content); + assert!( + ranges + .iter() + .any(|range| range.start == expected_offset && range.end == expected_offset), + "expected {kind} {content:?} to have an empty span at {expected_offset}, got {ranges:?}" + ); +} + +#[test] +fn generic_type_children_have_local_ranges() { + let source = "let x = C()"; + let ast = desugar(source); + + assert_has_span(&ast, source, "generic_type_expr", None, "C"); + assert_has_span(&ast, source, "identifier", Some("C"), "C"); + assert_has_span(&ast, source, "identifier", Some("Foo"), "Foo"); +} + +#[test] +fn nested_calls_include_their_delimiters() { + let source = r#"sink(source("first"), source("second"))"#; + let ast = desugar(source); + + assert_has_span(&ast, source, "call_expr", None, r#"source("first")"#); + assert_has_span(&ast, source, "call_expr", None, r#"source("second")"#); +} + +#[test] +fn enum_case_constructors_include_their_parameter_clause() { + let source = "enum Result { case success(T) }"; + let ast = desugar(source); + + assert_has_span(&ast, source, "constructor_declaration", None, "success(T)"); +} + +#[test] +fn synthesized_condition_and_switch_nodes_use_child_ranges() { + let source = "if a, b { c }\nswitch x { case a, b: c }"; + let ast = desugar(source); + + assert_has_span(&ast, source, "binary_expr", None, "a, b"); + assert_has_empty_span( + &ast, + "infix_operator", + Some("&&"), + source.find(',').unwrap(), + ); + assert_has_span(&ast, source, "or_pattern", None, "a, b"); + assert_has_span(&ast, source, "block", None, "c"); +} + +#[test] +fn declaration_and_operator_tokens_keep_precise_ranges() { + let source = "func f() { return x }\nlet y = try? await value! as? T\nlet z = value is T"; + let ast = desugar(source); + + assert_has_span(&ast, source, "block", None, "{ return x }"); + assert_has_span(&ast, source, "return_expr", None, "return x"); + assert_has_span(&ast, source, "prefix_operator", Some("try?"), "try?"); + assert_has_span(&ast, source, "prefix_operator", Some("await"), "await"); + assert_has_span(&ast, source, "postfix_operator", Some("!"), "!"); + assert_has_span(&ast, source, "infix_operator", Some("as?"), "as?"); + assert_has_span(&ast, source, "infix_operator", Some("is"), "is"); +} + +#[test] +fn synthetic_optional_binding_nodes_anchor_to_binding_keyword() { + let source = "if let value = optional {}"; + let ast = desugar(source); + let binding_start = source.find("let").unwrap(); + + assert_has_empty_span(&ast, "member_access_expr", None, binding_start); + assert_has_empty_span(&ast, "identifier", Some("Optional"), binding_start); + assert_has_empty_span(&ast, "identifier", Some("some"), binding_start); + assert_has_span(&ast, source, "modifier", Some("let"), "let"); +} + +#[test] +fn synthetic_type_and_modifier_nodes_use_empty_scope_start_ranges() { + let source = "let array: [T]\nlet optional: T?\nenum E { case a, b }"; + let ast = desugar(source); + + assert_has_empty_span(&ast, "identifier", Some("Array"), source.find('[').unwrap()); + assert_has_empty_span( + &ast, + "identifier", + Some("Optional"), + source.find("T?").unwrap(), + ); + let case_a = source.find("a, b").unwrap(); + let case_b = case_a + "a, ".len(); + assert_has_empty_span(&ast, "modifier", Some("enum_case"), case_a); + assert_has_empty_span(&ast, "modifier", Some("enum_case"), case_b); + assert_has_empty_span(&ast, "modifier", Some("chained_declaration"), case_b); +} + +#[test] +fn import_member_chain_excludes_import_keyword() { + let source = "import Foundation.Networking.URLSession"; + let ast = desugar(source); + + assert_has_span( + &ast, + source, + "member_access_expr", + None, + "Foundation.Networking", + ); + assert_has_span( + &ast, + source, + "member_access_expr", + None, + "Foundation.Networking.URLSession", + ); + assert_has_span( + &ast, + source, + "import_declaration", + None, + "import Foundation.Networking.URLSession", + ); +} diff --git a/unified/ql/test/library-tests/BasicTest/test.expected b/unified/ql/test/library-tests/BasicTest/test.expected index 5f8e2a323ad2..5d865bf4e8df 100644 --- a/unified/ql/test/library-tests/BasicTest/test.expected +++ b/unified/ql/test/library-tests/BasicTest/test.expected @@ -12,7 +12,7 @@ identifier | test.swift:4:18:4:18 | T | T | | test.swift:4:21:4:29 | Equatable | Equatable | | test.swift:5:9:5:13 | items | items | -| test.swift:5:16:5:18 | Array | Array | +| test.swift:5:16:5:15 | Array | Array | | test.swift:5:17:5:17 | T | T | | test.swift:7:19:7:21 | add | add | | test.swift:7:23:7:23 | _ | _ | @@ -37,8 +37,8 @@ identifier | test.swift:20:15:20:16 | at | at | | test.swift:20:18:20:22 | index | index | | test.swift:20:25:20:27 | Int | Int | +| test.swift:20:33:20:32 | Optional | Optional | | test.swift:20:33:20:39 | Element | Element | -| test.swift:20:33:20:40 | Optional | Optional | | test.swift:24:6:24:10 | merge | merge | | test.swift:24:12:24:12 | T | T | | test.swift:24:15:24:24 | Collection | Collection | @@ -48,7 +48,7 @@ identifier | test.swift:24:39:24:39 | _ | _ | | test.swift:24:41:24:46 | second | second | | test.swift:24:49:24:49 | T | T | -| test.swift:24:55:24:65 | Array | Array | +| test.swift:24:55:24:54 | Array | Array | | test.swift:24:56:24:56 | T | T | | test.swift:24:58:24:64 | Element | Element | | test.swift:25:9:25:14 | result | result | @@ -69,7 +69,7 @@ identifier | test.swift:36:15:36:21 | Element | Element | | test.swift:36:25:36:25 | T | T | | test.swift:37:17:37:20 | data | data | -| test.swift:37:23:37:25 | Array | Array | +| test.swift:37:23:37:22 | Array | Array | | test.swift:37:24:37:24 | T | T | | test.swift:39:9:39:13 | count | count | | test.swift:39:16:39:18 | Int | Int | @@ -83,8 +83,8 @@ identifier | test.swift:47:15:47:16 | at | at | | test.swift:47:18:47:22 | index | index | | test.swift:47:25:47:27 | Int | Int | +| test.swift:47:33:47:32 | Optional | Optional | | test.swift:47:33:47:33 | T | T | -| test.swift:47:33:47:34 | Optional | Optional | | test.swift:48:15:48:19 | index | index | | test.swift:48:29:48:33 | index | index | | test.swift:48:37:48:40 | data | data | @@ -138,14 +138,14 @@ identifier | test.swift:85:14:85:14 | T | T | | test.swift:85:17:85:17 | _ | _ | | test.swift:85:19:85:24 | values | values | -| test.swift:85:27:85:29 | Array | Array | +| test.swift:85:27:85:26 | Array | Array | | test.swift:85:28:85:28 | T | T | | test.swift:85:32:85:40 | transform | transform | | test.swift:85:44:85:44 | T | T | | test.swift:85:47:85:47 | T | T | | test.swift:85:53:85:53 | T | T | +| test.swift:85:59:85:58 | Optional | Optional | | test.swift:85:59:85:59 | T | T | -| test.swift:85:59:85:60 | Optional | Optional | | test.swift:86:12:86:17 | values | values | | test.swift:86:19:86:25 | isEmpty | isEmpty | | test.swift:87:12:87:17 | values | values | diff --git a/unified/ql/test/library-tests/controlflow/basicblock-slices.expected b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected index 97a1d1a279f0..9402484e36f5 100644 --- a/unified/ql/test/library-tests/controlflow/basicblock-slices.expected +++ b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected @@ -1,19 +1,19 @@ -| 1 | cfg.swift:1:1:604:2 | Block | 'Block -V VariableDeclaration -V topLevelDecl -> Int -> 0' | +| 1 | cfg.swift:1:1:604:1 | Block | 'Block -V VariableDeclaration -V topLevelDecl -> Int -> 0' | | 2 | cfg.swift:2:1:2:1 | 0 | '0' | | 3 | cfg.swift:3:1:3:12 | topLevelDecl | 'topLevelDecl -> 1 -^ ... + ...' | -| 5 | cfg.swift:5:1:5:37 | Block | 'Block -V 0 -^ ReturnExpr' | | 5 | cfg.swift:5:1:5:37 | FunctionDeclaration | 'FunctionDeclaration' | +| 5 | cfg.swift:5:26:5:37 | Block | 'Block -V 0 -^ ReturnExpr' | | 7 | cfg.swift:7:1:7:10 | returnZero | 'returnZero -^ returnZero(...)' | | 8 | cfg.swift:8:1:8:6 | Double | 'Double -> Argument -V topLevelDecl -^ Double(...)' | -| 10 | cfg.swift:10:1:13:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyError -^ BaseType -V Error' | -| 11 | cfg.swift:11:10:11:16 | VariableDeclaration | 'VariableDeclaration -V error1 -> VariableDeclaration -V error2' | +| 10 | cfg.swift:10:1:13:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyError -> BaseType -V Error' | +| 11 | cfg.swift:11:10:11:15 | VariableDeclaration | 'VariableDeclaration -V error1 -> VariableDeclaration -V error2' | | 12 | cfg.swift:12:10:12:31 | ClassLikeDeclaration | 'ClassLikeDeclaration -V error3 -^ ConstructorDeclaration' | -| 12 | cfg.swift:12:17:12:25 | withParam | 'withParam -^ Block' | +| 12 | cfg.swift:12:17:12:25 | withParam | 'withParam -? Block' | | 15 | cfg.swift:15:1:17:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 15 | cfg.swift:15:13:15:13 | x | 'x -^ Block' | +| 15 | cfg.swift:15:13:15:13 | x | 'x -> Block' | | 16 | cfg.swift:16:10:16:10 | x | 'x -> 0 -^ ... == ... -^ ReturnExpr' | | 19 | cfg.swift:19:1:26:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 19 | cfg.swift:19:17:19:17 | x | 'x -^ Block' | +| 19 | cfg.swift:19:17:19:17 | x | 'x -> Block' | | 20 | cfg.swift:20:3:22:3 | GuardIfStmt | 'GuardIfStmt -V x -> 0 -^ ... >= ...' | | 20 | cfg.swift:20:21:22:3 | Block | 'Block' | | 21 | cfg.swift:21:11:21:17 | MyError | 'MyError -^ ... .error1 -^ ThrowExpr' | @@ -21,7 +21,7 @@ | 23 | cfg.swift:23:21:25:3 | Block | 'Block' | | 24 | cfg.swift:24:11:24:17 | MyError | 'MyError -^ ... .error3 -> Argument -V x -> 1 -^ ... + ... -^ ... .error3(...) -^ ThrowExpr' | | 28 | cfg.swift:28:1:45:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 28 | cfg.swift:28:15:28:15 | x | 'x -^ Block' | +| 28 | cfg.swift:28:15:28:15 | x | 'x -> Block' | | 29 | cfg.swift:29:3:43:3 | TryExpr | 'TryExpr -V Block' | | 30 | cfg.swift:30:5:30:24 | try ... | 'try ...' | | 30 | cfg.swift:30:9:30:18 | mightThrow | 'mightThrow -> Argument -V 0 -^ mightThrow(...)' | @@ -38,62 +38,62 @@ | 39 | cfg.swift:39:22:41:3 | Block | 'Block' | | 40 | cfg.swift:40:5:40:9 | print | 'print -> Argument -V "MyError" -^ print(...)' | | 41 | cfg.swift:41:5:43:3 | CatchClause | 'CatchClause -V Block' | -| 42 | cfg.swift:42:5:42:9 | print | 'print -> Argument -V Unknown error -> interpolation -V Argument -V error -^ interpolation(...) -> -^ StringInterpolationExpr -^ print(...)' | +| 42 | cfg.swift:42:5:42:9 | print | 'print -> Argument -V Unknown error -> interpolation -> Argument -V error -^ interpolation(...) -> -^ StringInterpolationExpr -^ print(...)' | | 44 | cfg.swift:44:10:44:10 | 0 | '0 -^ ReturnExpr' | | 47 | cfg.swift:47:1:51:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 47 | cfg.swift:47:21:47:21 | s | 's -^ Block' | +| 47 | cfg.swift:47:21:47:21 | s | 's -> Block' | | 48 | cfg.swift:48:10:50:3 | Block | 'Block' | | 48 | cfg.swift:48:10:50:3 | FunctionExpr | 'FunctionExpr -^ ReturnExpr' | | 49 | cfg.swift:49:12:49:12 | s | 's -> "" -^ ... + ... -^ ReturnExpr' | | 53 | cfg.swift:53:1:58:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 53 | cfg.swift:53:21:53:21 | x | 'x -^ Block' | +| 53 | cfg.swift:53:21:53:21 | x | 'x -> Block' | | 54 | cfg.swift:54:3:56:3 | FunctionDeclaration | 'FunctionDeclaration' | -| 54 | cfg.swift:54:10:54:10 | y | 'y -^ Block' | +| 54 | cfg.swift:54:10:54:10 | y | 'y -> Block' | | 55 | cfg.swift:55:12:55:12 | x | 'x -> y -^ ... + ... -^ ReturnExpr' | | 57 | cfg.swift:57:10:57:10 | f | 'f -^ ReturnExpr' | | 60 | cfg.swift:60:1:64:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 60 | cfg.swift:60:21:60:21 | x | 'x -^ Block' | +| 60 | cfg.swift:60:21:60:21 | x | 'x -> Block' | | 61 | cfg.swift:61:10:63:3 | Block | 'Block' | | 61 | cfg.swift:61:10:63:3 | FunctionExpr | 'FunctionExpr -^ ReturnExpr' | | 62 | cfg.swift:62:6:62:6 | y | 'y' | | 62 | cfg.swift:62:19:62:19 | x | 'x -> y -^ ... + ...' | -| 66 | cfg.swift:66:1:70:1 | Block | 'Block' | | 66 | cfg.swift:66:1:70:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 66 | cfg.swift:66:21:70:1 | Block | 'Block' | | 67 | cfg.swift:67:3:67:34 | VariableDeclaration | 'VariableDeclaration -V x1 -> createClosure1 -> Argument -V "" -^ createClosure1(...) -^ ...(...)' | | 68 | cfg.swift:68:3:68:35 | VariableDeclaration | 'VariableDeclaration -V x2 -> createClosure2 -> Argument -V 0 -^ createClosure2(...) -> Argument -V 10 -^ ...(...)' | | 69 | cfg.swift:69:3:69:35 | VariableDeclaration | 'VariableDeclaration -V x3 -> createClosure3 -> Argument -V 0 -^ createClosure3(...) -> Argument -V 10 -^ ...(...)' | | 72 | cfg.swift:72:1:75:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 72 | cfg.swift:72:20:72:20 | s | 's -^ Block' | -| 73 | cfg.swift:73:3:73:23 | VariableDeclaration | 'VariableDeclaration -V n -> Optional -V Int -^ GenericTypeExpr -> Int -> Argument -V s -^ Int(...)' | +| 72 | cfg.swift:72:20:72:20 | s | 's -> Block' | +| 73 | cfg.swift:73:3:73:23 | VariableDeclaration | 'VariableDeclaration -V n -> Optional -> Int -^ GenericTypeExpr -> Int -> Argument -V s -^ Int(...)' | | 74 | cfg.swift:74:10:74:10 | n | 'n -^ ReturnExpr' | -| 77 | cfg.swift:77:1:81:1 | Block | 'Block' | | 77 | cfg.swift:77:1:81:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 77 | cfg.swift:77:39:81:1 | Block | 'Block' | | 78 | cfg.swift:78:3:78:36 | VariableDeclaration | 'VariableDeclaration -V nBang -> maybeParseInt -> Argument -V "42" -^ maybeParseInt(...) -^ ... !' | | 79 | cfg.swift:79:3:79:31 | VariableDeclaration | 'VariableDeclaration -V n -> maybeParseInt -> Argument -V "42" -^ maybeParseInt(...)' | | 80 | cfg.swift:80:10:80:14 | nBang | 'nBang -> n -^ ... ! -^ ... + ... -^ ReturnExpr' | -| 83 | cfg.swift:83:1:98:1 | Block | 'Block' | | 83 | cfg.swift:83:1:98:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 83 | cfg.swift:83:25:98:1 | Block | 'Block' | | 84 | cfg.swift:84:3:84:15 | VariableDeclaration | 'VariableDeclaration -V temp -> 10' | | 86 | cfg.swift:86:3:88:3 | FunctionDeclaration | 'FunctionDeclaration' | -| 86 | cfg.swift:86:12:86:12 | a | 'a -^ Block' | +| 86 | cfg.swift:86:12:86:12 | a | 'a -> Block' | | 87 | cfg.swift:87:5:87:5 | a | 'a -> a -> 1 -^ ... + ... -^ ... = ...' | | 90 | cfg.swift:90:3:92:3 | FunctionDeclaration | 'FunctionDeclaration' | -| 90 | cfg.swift:90:20:90:20 | a | 'a -^ Block' | +| 90 | cfg.swift:90:20:90:20 | a | 'a -> Block' | | 91 | cfg.swift:91:5:91:5 | a | 'a -> nil -^ ... = ...' | | 94 | cfg.swift:94:3:94:5 | add | 'add -> Argument -V -^ add(...)' | -| 95 | cfg.swift:95:3:95:30 | VariableDeclaration | 'VariableDeclaration -V tempOptional -> Optional -V Int -^ GenericTypeExpr -> 10' | +| 95 | cfg.swift:95:3:95:30 | VariableDeclaration | 'VariableDeclaration -V tempOptional -> Optional -> Int -^ GenericTypeExpr -> 10' | | 96 | cfg.swift:96:3:96:13 | addOptional | 'addOptional -> Argument -V -^ addOptional(...)' | | 97 | cfg.swift:97:10:97:13 | temp | 'temp -> tempOptional -^ ... ! -^ ... + ... -^ ReturnExpr' | | 100 | cfg.swift:100:1:109:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V C' | | 101 | cfg.swift:101:3:101:16 | VariableDeclaration | 'VariableDeclaration -V myInt -> Int' | | 102 | cfg.swift:102:3:104:3 | ConstructorDeclaration | 'ConstructorDeclaration' | -| 102 | cfg.swift:102:8:102:8 | n | 'n -^ Block' | +| 102 | cfg.swift:102:8:102:8 | n | 'n -> Block' | | 103 | cfg.swift:103:5:103:9 | myInt | 'myInt -> n -^ ... = ...' | -| 106 | cfg.swift:106:3:108:3 | Block | 'Block' | | 106 | cfg.swift:106:3:108:3 | FunctionDeclaration | 'FunctionDeclaration' | +| 106 | cfg.swift:106:26:108:3 | Block | 'Block' | | 107 | cfg.swift:107:12:107:16 | myInt | 'myInt -^ ReturnExpr' | | 111 | cfg.swift:111:1:137:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 111 | cfg.swift:111:20:111:24 | param | 'param -> inoutParam -> opt -^ Block' | +| 111 | cfg.swift:111:20:111:24 | param | 'param -> inoutParam -> opt -> Block' | | 112 | cfg.swift:112:3:112:18 | VariableDeclaration | 'VariableDeclaration -V c -> C -> Argument -V 42 -^ C(...)' | | 113 | cfg.swift:113:3:113:18 | VariableDeclaration | 'VariableDeclaration -V n1 -> c -^ ... .myInt' | | 114 | cfg.swift:114:3:114:23 | VariableDeclaration | 'VariableDeclaration -V n2 -> c -^ ... .self -^ ... .myInt' | @@ -116,29 +116,27 @@ | 135 | cfg.swift:135:3:135:27 | VariableDeclaration | 'VariableDeclaration -V n19 -> opt -^ ... .getMyInt -^ ... .getMyInt(...)' | | 136 | cfg.swift:136:3:136:32 | VariableDeclaration | 'VariableDeclaration -V n20 -> opt -^ ... .self -^ ... .getMyInt -^ ... .getMyInt(...)' | | 139 | cfg.swift:139:1:166:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 139 | cfg.swift:139:15:139:15 | x | 'x -^ Block' | +| 139 | cfg.swift:139:15:139:15 | x | 'x -> Block' | | 140 | cfg.swift:140:3:141:12 | ForEachStmt | 'ForEachStmt -V 0 -> 10 -^ ... ... ...' | | 140 | cfg.swift:140:7:140:7 | _ | '_' | | 141 | cfg.swift:141:9:141:12 | Block | 'Block' | | 143 | cfg.swift:143:3:153:3 | SwitchExpr | 'SwitchExpr -V x' | -| 144 | cfg.swift:144:5:146:17 | Block | 'Block' | | 144 | cfg.swift:144:5:146:17 | SwitchCase | 'SwitchCase -V 0 -> 1 -^ OrPattern' | -| 145 | cfg.swift:145:14:145:17 | true | 'true -^ ReturnExpr' | -| 147 | cfg.swift:147:5:150:17 | Block | 'Block' | +| 145 | cfg.swift:145:7:146:17 | Block | 'Block -V true -^ ReturnExpr' | | 147 | cfg.swift:147:5:150:17 | SwitchCase | 'SwitchCase' | | 147 | cfg.swift:147:10:147:10 | x | 'x -^ ConditionalPattern' | | 148 | cfg.swift:148:9:149:17 | ... && ... | '... && ... -V x -> 2 -^ ... >= ...' | | 149 | cfg.swift:149:13:149:13 | x | 'x -> 5 -^ ... < ...' | -| 150 | cfg.swift:150:14:150:17 | true | 'true -^ ReturnExpr' | -| 151 | cfg.swift:151:5:152:18 | SwitchCase | 'SwitchCase -V Block' | -| 152 | cfg.swift:152:14:152:18 | false | 'false -^ ReturnExpr' | +| 150 | cfg.swift:150:7:150:17 | Block | 'Block -V true -^ ReturnExpr' | +| 151 | cfg.swift:151:5:152:18 | SwitchCase | 'SwitchCase' | +| 152 | cfg.swift:152:7:152:18 | Block | 'Block -V false -^ ReturnExpr' | | 168 | cfg.swift:168:1:184:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 168 | cfg.swift:168:16:168:16 | x | 'x -^ Block' | +| 168 | cfg.swift:168:16:168:16 | x | 'x -> Block' | | 170 | cfg.swift:170:3:172:3 | | '' | | 174 | cfg.swift:174:3:176:3 | | '' | | 178 | cfg.swift:178:3:183:3 | | '' | | 186 | cfg.swift:186:1:198:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 186 | cfg.swift:186:9:186:9 | x | 'x -^ Block' | +| 186 | cfg.swift:186:9:186:9 | x | 'x -> Block' | | 187 | cfg.swift:187:3:197:3 | IfExpr | 'IfExpr -V x -> 2 -^ ... > ...' | | 187 | cfg.swift:187:12:189:3 | Block | 'Block' | | 188 | cfg.swift:188:5:188:9 | print | 'print -> Argument -V "x is greater than 2" -^ print(...)' | @@ -150,13 +148,13 @@ | 195 | cfg.swift:195:8:197:3 | Block | 'Block' | | 196 | cfg.swift:196:5:196:9 | print | 'print -> Argument -V "I can't guess the number" -^ print(...)' | | 200 | cfg.swift:200:1:205:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 200 | cfg.swift:200:9:200:9 | b | 'b -^ Block' | +| 200 | cfg.swift:200:9:200:9 | b | 'b -> Block' | | 201 | cfg.swift:201:3:203:3 | IfExpr | 'IfExpr -V b' | | 201 | cfg.swift:201:8:203:3 | Block | 'Block' | | 202 | cfg.swift:202:12:202:12 | 0 | '0 -^ ReturnExpr' | | 204 | cfg.swift:204:10:204:10 | 1 | '1 -^ ReturnExpr' | | 207 | cfg.swift:207:1:215:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 207 | cfg.swift:207:9:207:9 | x | 'x -^ Block' | +| 207 | cfg.swift:207:9:207:9 | x | 'x -> Block' | | 208 | cfg.swift:208:3:213:3 | IfExpr | 'IfExpr -V x -> 0 -^ ... < ...' | | 208 | cfg.swift:208:12:213:3 | Block | 'Block' | | 209 | cfg.swift:209:5:209:5 | x | 'x -> x -^ - ... -^ ... = ...' | @@ -165,7 +163,7 @@ | 211 | cfg.swift:211:7:211:7 | x | 'x -> x -> 1 -^ ... - ... -^ ... = ...' | | 214 | cfg.swift:214:10:214:10 | x | 'x -^ ReturnExpr' | | 217 | cfg.swift:217:1:223:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 217 | cfg.swift:217:10:217:11 | b1 | 'b1 -> b2 -> b3 -^ Block' | +| 217 | cfg.swift:217:10:217:11 | b1 | 'b1 -> b2 -> b3 -> Block' | | 218 | cfg.swift:218:3:222:20 | ReturnExpr | 'ReturnExpr' | | 218 | cfg.swift:218:10:222:20 | IfExpr | 'IfExpr -V IfExpr -V b1' | | 219 | cfg.swift:219:13:219:14 | b2 | 'b2' | @@ -173,7 +171,7 @@ | 221 | cfg.swift:221:9:221:18 | "b2 \|\| b3" | '"b2 \|\| b3"' | | 222 | cfg.swift:222:9:222:20 | "!b2 \|\| !b3" | '"!b2 \|\| !b3"' | | 225 | cfg.swift:225:1:234:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 225 | cfg.swift:225:31:225:31 | b | 'b -^ Block' | +| 225 | cfg.swift:225:31:225:31 | b | 'b -> Block' | | 226 | cfg.swift:226:3:233:3 | IfExpr | 'IfExpr -V IfExpr -V b' | | 227 | cfg.swift:227:8:227:11 | true | 'true' | | 228 | cfg.swift:228:7:228:10 | Bool | 'Bool -> Argument -V false -^ Bool(...)' | @@ -181,24 +179,24 @@ | 229 | cfg.swift:229:12:229:14 | "b" | '"b" -^ ReturnExpr' | | 231 | cfg.swift:231:8:233:3 | Block | 'Block' | | 232 | cfg.swift:232:12:232:15 | "!b" | '"!b" -^ ReturnExpr' | -| 236 | cfg.swift:236:1:240:1 | Block | 'Block' | | 236 | cfg.swift:236:1:240:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 236 | cfg.swift:236:27:240:1 | Block | 'Block' | | 237 | cfg.swift:237:3:239:3 | IfExpr | 'IfExpr -V ! ... -V true' | | 242 | cfg.swift:242:1:248:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 242 | cfg.swift:242:17:242:17 | b | 'b -^ Block' | +| 242 | cfg.swift:242:17:242:17 | b | 'b -> Block' | | 243 | cfg.swift:243:3:246:9 | IfExpr | 'IfExpr -V b' | | 243 | cfg.swift:243:8:245:3 | Block | 'Block' | | 244 | cfg.swift:244:5:244:9 | print | 'print -> Argument -V "true" -^ print(...)' | | 246 | cfg.swift:246:8:246:9 | Block | 'Block' | | 247 | cfg.swift:247:3:247:7 | print | 'print -> Argument -V "done" -^ print(...)' | | 250 | cfg.swift:250:1:254:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 250 | cfg.swift:250:16:250:17 | b1 | 'b1 -> b2 -^ Block' | +| 250 | cfg.swift:250:16:250:17 | b1 | 'b1 -> b2 -> Block' | | 251 | cfg.swift:251:3:253:3 | IfExpr | 'IfExpr -V ... \|\| ... -V b1' | | 251 | cfg.swift:251:13:251:14 | b2 | 'b2' | | 251 | cfg.swift:251:17:253:3 | Block | 'Block' | | 252 | cfg.swift:252:5:252:9 | print | 'print -> Argument -V "b1 or b2" -^ print(...)' | | 256 | cfg.swift:256:1:273:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 256 | cfg.swift:256:18:256:18 | a | 'a -> b -^ Block' | +| 256 | cfg.swift:256:18:256:18 | a | 'a -> b -> Block' | | 257 | cfg.swift:257:3:257:15 | VariableDeclaration | 'VariableDeclaration -V c -> a -> b -^ ... + ...' | | 258 | cfg.swift:258:3:258:15 | VariableDeclaration | 'VariableDeclaration -V d -> a -> b -^ ... - ...' | | 259 | cfg.swift:259:3:259:15 | VariableDeclaration | 'VariableDeclaration -V e -> a -> b -^ ... * ...' | @@ -216,10 +214,10 @@ | 271 | cfg.swift:271:3:271:15 | VariableDeclaration | 'VariableDeclaration -V s -> a -> b -^ ... > ...' | | 272 | cfg.swift:272:3:272:16 | VariableDeclaration | 'VariableDeclaration -V t -> a -> b -^ ... >= ...' | | 275 | cfg.swift:275:1:277:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 275 | cfg.swift:275:25:275:25 | x | 'x -> y -^ Block' | -| 276 | cfg.swift:276:11:276:10 | | ' -> interpolation -V Argument -V x -^ interpolation(...) -> + -> interpolation -V Argument -V y -^ interpolation(...) -> is equal to -> interpolation -V Argument -V x -> y -^ ... + ... -^ interpolation(...) -> and here is a zero: -> interpolation -V Argument -V returnZero -^ returnZero(...) -^ interpolation(...) -> -^ StringInterpolationExpr -^ ReturnExpr' | -| 279 | cfg.swift:279:1:310:1 | Block | 'Block' | +| 275 | cfg.swift:275:25:275:25 | x | 'x -> y -> Block' | +| 276 | cfg.swift:276:11:276:10 | | ' -> interpolation -> Argument -V x -^ interpolation(...) -> + -> interpolation -> Argument -V y -^ interpolation(...) -> is equal to -> interpolation -> Argument -V x -> y -^ ... + ... -^ interpolation(...) -> and here is a zero: -> interpolation -> Argument -V returnZero -^ returnZero(...) -^ interpolation(...) -> -^ StringInterpolationExpr -^ ReturnExpr' | | 279 | cfg.swift:279:1:310:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 279 | cfg.swift:279:55:310:1 | Block | 'Block' | | 280 | cfg.swift:280:3:280:44 | VariableDeclaration | 'VariableDeclaration -V a -> 0 -> 1 -> 2 -> 3 -> 4 -> 5 -> 6 -> 7 -> 8 -> 9 -> 10 -^ ArrayLiteral' | | 281 | cfg.swift:281:3:281:3 | a | 'a -> Argument -V 0 -^ a(...) -> 0 -^ ... = ...' | | 282 | cfg.swift:282:3:282:3 | a | 'a -> Argument -V 1 -^ a(...) -> 1 -^ ... += ...' | @@ -246,16 +244,16 @@ | 305 | cfg.swift:305:3:305:3 | b | 'b -> Argument -V 9 -^ b(...) -> b -> Argument -V 8 -^ b(...) -> 1 -^ ... << ... -^ ... = ...' | | 306 | cfg.swift:306:3:306:3 | b | 'b -> Argument -V 10 -^ b(...) -> b -> Argument -V 9 -^ b(...) -> 1 -^ ... >> ... -^ ... = ...' | | 308 | cfg.swift:308:3:308:39 | VariableDeclaration | 'VariableDeclaration -V Argument -V a1 -> Argument -V a2 -> Argument -V a3 -> Argument -V a4 -> Argument -V a5 -^ TupleExpr -> tupleWithA' | -| 309 | cfg.swift:309:11:309:20 | Argument | 'Argument -V a1 -> b -> Argument -V 0 -^ b(...) -^ ... + ... -> Argument -V a2 -> b -> Argument -V 1 -^ b(...) -^ ... + ... -> Argument -V a3 -> b -> Argument -V 2 -^ b(...) -^ ... + ... -> Argument -V a4 -> b -> Argument -V 3 -^ b(...) -^ ... + ... -> Argument -V a5 -> b -> Argument -V 4 -^ b(...) -^ ... + ... -^ TupleExpr -^ ReturnExpr' | +| 309 | cfg.swift:309:11:309:19 | Argument | 'Argument -V a1 -> b -> Argument -V 0 -^ b(...) -^ ... + ... -> Argument -V a2 -> b -> Argument -V 1 -^ b(...) -^ ... + ... -> Argument -V a3 -> b -> Argument -V 2 -^ b(...) -^ ... + ... -> Argument -V a4 -> b -> Argument -V 3 -^ b(...) -^ ... + ... -> Argument -V a5 -> b -> Argument -V 4 -^ b(...) -^ ... + ... -^ TupleExpr -^ ReturnExpr' | | 312 | cfg.swift:312:1:317:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 312 | cfg.swift:312:12:312:12 | x | 'x -^ Block' | +| 312 | cfg.swift:312:12:312:12 | x | 'x -> Block' | | 313 | cfg.swift:313:3:316:3 | WhileStmt | 'WhileStmt' | | 313 | cfg.swift:313:9:313:9 | x | 'x -> 0 -^ ... >= ...' | | 313 | cfg.swift:313:16:316:3 | Block | 'Block' | | 314 | cfg.swift:314:5:314:9 | print | 'print -> Argument -V x -^ print(...)' | | 315 | cfg.swift:315:5:315:5 | x | 'x -> 1 -^ ... -= ...' | | 319 | cfg.swift:319:1:332:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 319 | cfg.swift:319:12:319:12 | x | 'x -^ Block' | +| 319 | cfg.swift:319:12:319:12 | x | 'x -> Block' | | 320 | cfg.swift:320:3:330:3 | WhileStmt | 'WhileStmt' | | 320 | cfg.swift:320:9:320:9 | x | 'x -> 0 -^ ... >= ...' | | 320 | cfg.swift:320:16:330:3 | Block | 'Block' | @@ -270,7 +268,7 @@ | 329 | cfg.swift:329:5:329:9 | print | 'print -> Argument -V "Iter" -^ print(...)' | | 331 | cfg.swift:331:3:331:7 | print | 'print -> Argument -V "Done" -^ print(...)' | | 334 | cfg.swift:334:1:349:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 334 | cfg.swift:334:18:334:18 | x | 'x -^ Block' | +| 334 | cfg.swift:334:18:334:18 | x | 'x -> Block' | | 335 | cfg.swift:335:3:348:3 | LabeledStmt | 'LabeledStmt -V WhileStmt' | | 335 | cfg.swift:335:16:335:16 | x | 'x -> 0 -^ ... >= ...' | | 335 | cfg.swift:335:23:348:3 | Block | 'Block' | @@ -288,44 +286,44 @@ | 345 | cfg.swift:345:7:345:11 | print | 'print -> Argument -V "Iter" -^ print(...)' | | 347 | cfg.swift:347:5:347:9 | print | 'print -> Argument -V "Done" -^ print(...)' | | 351 | cfg.swift:351:1:356:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 351 | cfg.swift:351:17:351:17 | x | 'x -^ Block' | +| 351 | cfg.swift:351:17:351:17 | x | 'x -> Block' | | 352 | cfg.swift:352:3:355:16 | DoWhileStmt | 'DoWhileStmt' | | 352 | cfg.swift:352:10:355:3 | Block | 'Block' | | 353 | cfg.swift:353:5:353:9 | print | 'print -> Argument -V x -^ print(...)' | | 354 | cfg.swift:354:5:354:5 | x | 'x -> 1 -^ ... -= ...' | | 355 | cfg.swift:355:11:355:11 | x | 'x -> 0 -^ ... >= ...' | -| 358 | cfg.swift:358:1:363:1 | Block | 'Block' | | 358 | cfg.swift:358:1:363:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 358 | cfg.swift:358:32:363:1 | Block | 'Block' | | 359 | cfg.swift:359:3:359:11 | VariableDeclaration | 'VariableDeclaration -V x -> 0' | | 360 | cfg.swift:360:3:362:3 | WhileStmt | 'WhileStmt' | | 360 | cfg.swift:360:9:360:9 | x | 'x -> 10 -^ ... < ...' | | 360 | cfg.swift:360:17:362:3 | Block | 'Block' | | 361 | cfg.swift:361:5:361:5 | x | 'x -> 1 -^ ... += ...' | | 365 | cfg.swift:365:1:374:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V OptionalC' | -| 366 | cfg.swift:366:3:366:11 | VariableDeclaration | 'VariableDeclaration -V c -> Optional -V C -^ GenericTypeExpr' | +| 366 | cfg.swift:366:3:366:11 | VariableDeclaration | 'VariableDeclaration -V c -> Optional -> C -^ GenericTypeExpr' | | 367 | cfg.swift:367:3:369:3 | ConstructorDeclaration | 'ConstructorDeclaration' | -| 367 | cfg.swift:367:8:367:10 | arg | 'arg -^ Block' | +| 367 | cfg.swift:367:8:367:10 | arg | 'arg -> Block' | | 368 | cfg.swift:368:5:368:5 | c | 'c -> arg -^ ... = ...' | -| 371 | cfg.swift:371:3:373:3 | Block | 'Block' | | 371 | cfg.swift:371:3:373:3 | FunctionDeclaration | 'FunctionDeclaration' | +| 371 | cfg.swift:371:28:373:3 | Block | 'Block' | | 372 | cfg.swift:372:12:372:12 | c | 'c -^ ReturnExpr' | | 376 | cfg.swift:376:1:378:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 376 | cfg.swift:376:19:376:19 | c | 'c -^ Block' | +| 376 | cfg.swift:376:19:376:19 | c | 'c -> Block' | | 377 | cfg.swift:377:10:377:10 | c | 'c -^ ... .getOptional -^ ... .getOptional(...) -^ ... .getMyInt -^ ... .getMyInt(...) -^ ReturnExpr' | | 380 | cfg.swift:380:1:384:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 380 | cfg.swift:380:18:380:18 | x | 'x -> y -^ Block' | +| 380 | cfg.swift:380:18:380:18 | x | 'x -> y -> Block' | | 381 | cfg.swift:381:10:383:3 | Block | 'Block' | -| 381 | cfg.swift:381:13:381:22 | VariableDeclaration | 'VariableDeclaration -V z -> x -> y -^ ... + ... -> VariableDeclaration -V t -> "literal" -^ FunctionExpr -^ ReturnExpr' | +| 381 | cfg.swift:381:13:381:21 | VariableDeclaration | 'VariableDeclaration -V z -> x -> y -^ ... + ... -> VariableDeclaration -V t -> "literal" -^ FunctionExpr -^ ReturnExpr' | | 382 | cfg.swift:382:12:382:12 | z | 'z -^ ReturnExpr' | | 386 | cfg.swift:386:1:388:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 386 | cfg.swift:386:23:386:23 | t | 't -^ Block' | +| 386 | cfg.swift:386:23:386:23 | t | 't -> Block' | | 387 | cfg.swift:387:10:387:10 | t | 't -^ ... .a -> t -^ ... .1 -^ ... + ... -> t -^ ... .c -^ ... + ... -> Argument -V 1 -> Argument -V 2 -> Argument -V 3 -^ TupleExpr -^ ... .0 -^ ... + ... -^ ReturnExpr' | -| 390 | cfg.swift:390:1:394:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V Derived -^ BaseType -V C' | -| 391 | cfg.swift:391:3:393:3 | Block | 'Block' | +| 390 | cfg.swift:390:1:394:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V Derived -> BaseType -V C' | | 391 | cfg.swift:391:3:393:3 | ConstructorDeclaration | 'ConstructorDeclaration' | +| 391 | cfg.swift:391:10:393:3 | Block | 'Block' | | 392 | cfg.swift:392:5:392:9 | | ' -^ ... .init -> Argument -V 0 -^ ... .init(...)' | | 396 | cfg.swift:396:1:404:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 396 | cfg.swift:396:21:396:21 | x | 'x -^ Block' | +| 396 | cfg.swift:396:21:396:21 | x | 'x -> Block' | | 397 | cfg.swift:397:3:402:3 | TryExpr | 'TryExpr -V Block' | | 398 | cfg.swift:398:5:398:24 | try ... | 'try ...' | | 398 | cfg.swift:398:9:398:18 | mightThrow | 'mightThrow -> Argument -V 0 -^ mightThrow(...)' | @@ -335,26 +333,26 @@ | 403 | cfg.swift:403:10:403:10 | 0 | '0 -^ ReturnExpr' | | 406 | cfg.swift:406:1:415:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V Structors' | | 407 | cfg.swift:407:3:407:16 | VariableDeclaration | 'VariableDeclaration -V field -> Int' | -| 408 | cfg.swift:408:3:410:3 | Block | 'Block' | | 408 | cfg.swift:408:3:410:3 | ConstructorDeclaration | 'ConstructorDeclaration' | +| 408 | cfg.swift:408:10:410:3 | Block | 'Block' | | 409 | cfg.swift:409:5:409:9 | field | 'field -> 10 -^ ... = ...' | -| 412 | cfg.swift:412:3:414:3 | Block | 'Block' | | 412 | cfg.swift:412:3:414:3 | DestructorDeclaration | 'DestructorDeclaration' | +| 412 | cfg.swift:412:10:414:3 | Block | 'Block' | | 413 | cfg.swift:413:5:413:9 | field | 'field -> 0 -^ ... = ...' | | 417 | cfg.swift:417:1:419:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 417 | cfg.swift:417:24:417:24 | x | 'x -> y -^ Block' | +| 417 | cfg.swift:417:24:417:24 | x | 'x -> y -> Block' | | 418 | cfg.swift:418:10:418:25 | MapLiteral | 'MapLiteral -^ ReturnExpr' | -| 421 | cfg.swift:421:1:444:1 | Block | 'Block' | | 421 | cfg.swift:421:1:444:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 421 | cfg.swift:421:33:444:1 | Block | 'Block' | | 422 | cfg.swift:422:3:427:3 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyLocalClass' | | 423 | cfg.swift:423:5:423:14 | VariableDeclaration | 'VariableDeclaration -V x -> Int' | -| 424 | cfg.swift:424:5:426:5 | Block | 'Block' | | 424 | cfg.swift:424:5:426:5 | ConstructorDeclaration | 'ConstructorDeclaration' | +| 424 | cfg.swift:424:12:426:5 | Block | 'Block' | | 425 | cfg.swift:425:7:425:7 | x | 'x -> 10 -^ ... = ...' | | 429 | cfg.swift:429:3:434:3 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyLocalStruct' | | 430 | cfg.swift:430:5:430:14 | VariableDeclaration | 'VariableDeclaration -V x -> Int' | -| 431 | cfg.swift:431:5:433:5 | Block | 'Block' | | 431 | cfg.swift:431:5:433:5 | ConstructorDeclaration | 'ConstructorDeclaration' | +| 431 | cfg.swift:431:12:433:5 | Block | 'Block' | | 432 | cfg.swift:432:7:432:7 | x | 'x -> 10 -^ ... = ...' | | 436 | cfg.swift:436:3:439:3 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyLocalEnum' | | 437 | cfg.swift:437:10:437:10 | VariableDeclaration | 'VariableDeclaration -V A' | @@ -365,10 +363,10 @@ | 447 | cfg.swift:447:3:447:13 | VariableDeclaration | 'VariableDeclaration -V x -> Int' | | 450 | cfg.swift:450:1:454:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V A' | | 451 | cfg.swift:451:3:451:11 | VariableDeclaration | 'VariableDeclaration -V b -> B' | -| 452 | cfg.swift:452:3:452:14 | VariableDeclaration | 'VariableDeclaration -V bs -> Array -V B -^ GenericTypeExpr' | -| 453 | cfg.swift:453:3:453:15 | VariableDeclaration | 'VariableDeclaration -V mayB -> Optional -V B -^ GenericTypeExpr' | +| 452 | cfg.swift:452:3:452:14 | VariableDeclaration | 'VariableDeclaration -V bs -> Array -> B -^ GenericTypeExpr' | +| 453 | cfg.swift:453:3:453:15 | VariableDeclaration | 'VariableDeclaration -V mayB -> Optional -> B -^ GenericTypeExpr' | | 456 | cfg.swift:456:1:466:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 456 | cfg.swift:456:11:456:11 | a | 'a -^ Block' | +| 456 | cfg.swift:456:11:456:11 | a | 'a -> Block' | | 457 | cfg.swift:457:3:457:24 | VariableDeclaration | 'VariableDeclaration -V kpGet_b_x -> ' | | 458 | cfg.swift:458:3:458:31 | VariableDeclaration | 'VariableDeclaration -V kpGet_bs_0_x -> ' | | 459 | cfg.swift:459:3:459:37 | VariableDeclaration | 'VariableDeclaration -V kpGet_mayB_force_x -> ' | @@ -377,16 +375,16 @@ | 463 | cfg.swift:463:3:463:51 | VariableDeclaration | 'VariableDeclaration -V apply_kpGet_bs_0_x -> a -> Argument -V kpGet_bs_0_x -^ a(...)' | | 464 | cfg.swift:464:3:464:63 | VariableDeclaration | 'VariableDeclaration -V apply_kpGet_mayB_force_x -> a -> Argument -V kpGet_mayB_force_x -^ a(...)' | | 465 | cfg.swift:465:3:465:51 | VariableDeclaration | 'VariableDeclaration -V apply_kpGet_mayB_x -> a -> Argument -V kpGet_mayB_x -^ a(...)' | -| 468 | cfg.swift:468:1:495:1 | Block | 'Block' | | 468 | cfg.swift:468:1:495:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 468 | cfg.swift:468:21:495:1 | Block | 'Block' | | 469 | cfg.swift:469:1:475:6 | | '' | | 477 | cfg.swift:477:3:477:3 | 5 | '5' | | 479 | cfg.swift:479:1:482:6 | | '' | | 484 | cfg.swift:484:3:484:3 | 8 | '8' | | 486 | cfg.swift:486:1:492:6 | | '' | | 494 | cfg.swift:494:3:494:4 | 13 | '13' | -| 497 | cfg.swift:497:1:522:1 | Block | 'Block' | | 497 | cfg.swift:497:1:522:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 497 | cfg.swift:497:29:522:1 | Block | 'Block' | | 498 | cfg.swift:498:3:498:11 | VariableDeclaration | 'VariableDeclaration -V x -> 0' | | 500 | cfg.swift:500:3:502:3 | IfExpr | 'IfExpr -V ' | | 500 | cfg.swift:500:30:502:3 | Block | 'Block' | @@ -405,12 +403,12 @@ | 517 | cfg.swift:517:29:519:3 | Block | 'Block' | | 518 | cfg.swift:518:5:518:5 | x | 'x -> 1 -^ ... += ...' | | 521 | cfg.swift:521:10:521:10 | x | 'x -^ ReturnExpr' | -| 524 | cfg.swift:524:1:538:1 | Block | 'Block' | | 524 | cfg.swift:524:1:538:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 524 | cfg.swift:524:28:538:1 | Block | 'Block' | | 525 | cfg.swift:525:5:533:6 | VariableDeclaration | 'VariableDeclaration -V stream -> AsyncStream -> Argument -V Int -^ ... .self -> Argument -V . -^ ... .bufferingNewest -> Argument -V 5 -^ ... .bufferingNewest(...) -> Argument -V FunctionExpr -^ AsyncStream(...)' | | 525 | cfg.swift:525:78:533:5 | Block | 'Block' | | 526 | cfg.swift:526:9:526:20 | continuation | 'continuation' | -| 527 | cfg.swift:527:13:527:16 | Task | 'Task -^ ... .detached -^ Argument -V FunctionExpr -^ ... .detached(...)' | +| 527 | cfg.swift:527:13:527:16 | Task | 'Task -^ ... .detached -> Argument -V FunctionExpr -^ ... .detached(...)' | | 527 | cfg.swift:527:27:532:13 | Block | 'Block' | | 528 | cfg.swift:528:17:530:17 | ForEachStmt | 'ForEachStmt -V 1 -> 100 -^ ... ... ...' | | 528 | cfg.swift:528:21:528:21 | i | 'i -> Block' | @@ -420,12 +418,12 @@ | 535 | cfg.swift:535:19:535:19 | i | 'i -> Block' | | 536 | cfg.swift:536:9:536:13 | print | 'print -> Argument -V i -^ print(...)' | | 540 | cfg.swift:540:1:544:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 540 | cfg.swift:540:24:540:24 | x | 'x -^ Block' | +| 540 | cfg.swift:540:24:540:24 | x | 'x -> Block' | | 541 | cfg.swift:541:3:543:9 | ReturnExpr | 'ReturnExpr' | | 542 | cfg.swift:542:5:543:9 | ... ?? ... | '... ?? ... -V x' | | 543 | cfg.swift:543:9:543:9 | 0 | '0' | | 546 | cfg.swift:546:1:553:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 546 | cfg.swift:546:25:546:25 | x | 'x -^ Block' | +| 546 | cfg.swift:546:25:546:25 | x | 'x -> Block' | | 547 | cfg.swift:547:3:552:3 | IfExpr | 'IfExpr -V ... ?? ... -V x' | | 548 | cfg.swift:548:7:548:11 | false | 'false' | | 548 | cfg.swift:548:13:550:3 | Block | 'Block' | @@ -433,34 +431,34 @@ | 550 | cfg.swift:550:10:552:3 | Block | 'Block' | | 551 | cfg.swift:551:12:551:12 | 0 | '0 -^ ReturnExpr' | | 555 | cfg.swift:555:1:557:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 555 | cfg.swift:555:24:555:27 | expr | 'expr -^ Block' | +| 555 | cfg.swift:555:24:555:27 | expr | 'expr -> Block' | | 556 | cfg.swift:556:10:556:13 | expr | 'expr -^ expr(...) -^ ReturnExpr' | -| 559 | cfg.swift:559:1:561:1 | Block | 'Block' | | 559 | cfg.swift:559:1:561:1 | FunctionDeclaration | 'FunctionDeclaration' | +| 559 | cfg.swift:559:24:561:1 | Block | 'Block' | | 560 | cfg.swift:560:3:560:17 | usesAutoclosure | 'usesAutoclosure -> Argument -V 1 -^ usesAutoclosure(...)' | | 565 | cfg.swift:565:1:567:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyProtocol' | -| 566 | cfg.swift:566:2:566:21 | Block | 'Block' | +| 566 | cfg.swift:566:2:566:1 | Block | 'Block' | | 566 | cfg.swift:566:2:566:21 | FunctionDeclaration | 'FunctionDeclaration' | -| 569 | cfg.swift:569:1:571:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyProcotolImpl -^ BaseType -V MyProtocol' | -| 570 | cfg.swift:570:2:570:34 | Block | 'Block -V 0 -^ ReturnExpr' | +| 569 | cfg.swift:569:1:571:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyProcotolImpl -> BaseType -V MyProtocol' | | 570 | cfg.swift:570:2:570:34 | FunctionDeclaration | 'FunctionDeclaration' | -| 573 | cfg.swift:573:1:573:62 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | +| 570 | cfg.swift:570:23:570:34 | Block | 'Block -V 0 -^ ReturnExpr' | | 573 | cfg.swift:573:1:573:62 | FunctionDeclaration | 'FunctionDeclaration' | -| 574 | cfg.swift:574:1:574:70 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | +| 573 | cfg.swift:573:36:573:62 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | | 574 | cfg.swift:574:1:574:70 | FunctionDeclaration | 'FunctionDeclaration' | +| 574 | cfg.swift:574:44:574:70 | Block | 'Block -V MyProcotolImpl -^ MyProcotolImpl(...) -^ ReturnExpr' | | 576 | cfg.swift:576:1:576:23 | FunctionDeclaration | 'FunctionDeclaration' | -| 576 | cfg.swift:576:11:576:13 | arg | 'arg -^ Block' | +| 576 | cfg.swift:576:11:576:13 | arg | 'arg -> Block' | | 578 | cfg.swift:578:1:583:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 578 | cfg.swift:578:30:578:30 | x | 'x -> y -^ Block' | +| 578 | cfg.swift:578:30:578:30 | x | 'x -> y -> Block' | | 579 | cfg.swift:579:2:579:5 | sink | 'sink -> Argument -V x -^ ... .source -^ ... .source(...) -^ sink(...)' | | 580 | cfg.swift:580:2:580:5 | sink | 'sink -> Argument -V y -^ ... .source -^ ... .source(...) -^ sink(...)' | | 581 | cfg.swift:581:2:581:5 | sink | 'sink -> Argument -V getMyProtocol -^ getMyProtocol(...) -^ ... .source -^ ... .source(...) -^ sink(...)' | | 582 | cfg.swift:582:2:582:5 | sink | 'sink -> Argument -V getMyProtocolImpl -^ getMyProtocolImpl(...) -^ ... .source -^ ... .source(...) -^ sink(...)' | | 585 | cfg.swift:585:1:593:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 585 | cfg.swift:585:23:585:23 | x | 'x -^ Block' | +| 585 | cfg.swift:585:23:585:23 | x | 'x -> Block' | | 586 | cfg.swift:586:3:589:3 | VariableDeclaration | 'VariableDeclaration -V a -> SwitchExpr -V x' | -| 587 | cfg.swift:587:5:587:17 | Block | 'Block -V 1' | | 587 | cfg.swift:587:5:587:17 | SwitchCase | 'SwitchCase -V 0 -> 5 -^ ... ..< ...' | +| 587 | cfg.swift:587:17:587:17 | Block | 'Block -V 1' | | 588 | cfg.swift:588:5:588:14 | SwitchCase | 'SwitchCase -V Block -V 2' | | 590 | cfg.swift:590:3:592:18 | VariableDeclaration | 'VariableDeclaration -V b' | | 591 | cfg.swift:591:9:592:18 | IfExpr | 'IfExpr -V x -> 42 -^ ... < ...' | @@ -469,7 +467,7 @@ | 596 | cfg.swift:596:1:598:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V ValueGenericsStruct -> TypeParameter -V N -> Int' | | 597 | cfg.swift:597:5:597:13 | VariableDeclaration | 'VariableDeclaration -V x -> N' | | 600 | cfg.swift:600:1:604:1 | FunctionDeclaration | 'FunctionDeclaration' | -| 600 | cfg.swift:600:36:600:40 | value | 'value -^ Block' | +| 600 | cfg.swift:600:36:600:40 | value | 'value -> Block' | | 601 | cfg.swift:601:5:601:13 | VariableDeclaration | 'VariableDeclaration -V x -> N' | | 602 | cfg.swift:602:5:602:9 | print | 'print -> Argument -V x -^ print(...)' | | 603 | cfg.swift:603:5:603:5 | _ | '_ -> value -^ ... = ...' | diff --git a/unified/ql/test/library-tests/controlflow/cfg.expected b/unified/ql/test/library-tests/controlflow/cfg.expected index fc1f15c91c5f..01f47f8be713 100644 --- a/unified/ql/test/library-tests/controlflow/cfg.expected +++ b/unified/ql/test/library-tests/controlflow/cfg.expected @@ -1,6 +1,5 @@ bbContinues | cfg.swift:62:6:62:6 | y | 'y goto Block(-1)' | -| cfg.swift:147:5:147:5 | Block | 'Block goto true(+3)' | | cfg.swift:525:78:525:78 | Block | 'Block goto Task(+2)' | | cfg.swift:526:9:526:20 | continuation | 'continuation goto Block(-1)' | bbStep @@ -10,8 +9,8 @@ bbStep | cfg.swift:30:9:30:24 | mightThrow(...) | 'mightThrow(...) : exception -> CatchClause(+5)' | | cfg.swift:30:9:30:24 | mightThrow(...) | 'mightThrow(...) : successor -> try ...(+0)' | | cfg.swift:33:5:33:33 | print(...) | 'print(...) : successor -> 0(+11)' | -| cfg.swift:35:5:35:5 | OrPattern | 'OrPattern : match -> Block(+0)' | -| cfg.swift:35:5:35:5 | OrPattern | 'OrPattern : no-match -> CatchClause(+2)' | +| cfg.swift:35:11:35:60 | OrPattern | 'OrPattern : match -> Block(+0)' | +| cfg.swift:35:11:35:60 | OrPattern | 'OrPattern : no-match -> CatchClause(+2)' | | cfg.swift:37:11:37:39 | ... .error3(...) | '... .error3(...) : match -> Block(+0)' | | cfg.swift:37:11:37:39 | ... .error3(...) | '... .error3(...) : no-match -> CatchClause(+2)' | | cfg.swift:39:11:39:20 | | ' : match -> Block(+0)' | @@ -22,9 +21,9 @@ bbStep | cfg.swift:140:12:140:17 | ... ... ... | '... ... ... : non-empty -> _(+0)' | | cfg.swift:141:9:141:12 | Block | 'Block : successor -> SwitchExpr(+2)' | | cfg.swift:141:9:141:12 | Block | 'Block : successor -> _(-1)' | -| cfg.swift:144:5:144:5 | OrPattern | 'OrPattern : match -> Block(+0)' | -| cfg.swift:144:5:144:5 | OrPattern | 'OrPattern : no-match -> SwitchCase(+3)' | -| cfg.swift:147:10:147:10 | ConditionalPattern | 'ConditionalPattern : match -> Block(+0)' | +| cfg.swift:144:10:144:13 | OrPattern | 'OrPattern : match -> Block(+1)' | +| cfg.swift:144:10:144:13 | OrPattern | 'OrPattern : no-match -> SwitchCase(+3)' | +| cfg.swift:147:10:147:10 | ConditionalPattern | 'ConditionalPattern : match -> Block(+3)' | | cfg.swift:147:10:147:10 | ConditionalPattern | 'ConditionalPattern : no-match -> SwitchCase(+4)' | | cfg.swift:148:10:148:15 | ... >= ... | '... >= ... : false -> x(-1)' | | cfg.swift:148:10:148:15 | ... >= ... | '... >= ... : true -> x(+1)' | @@ -159,8 +158,8 @@ noCfg | cfg.swift:524:6:524:17 | testAsyncFor | | cfg.swift:559:6:559:20 | autoclosureTest | nonSimple -| cfg.swift:10:1:10:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyError -^ BaseType -V Error' | +| cfg.swift:12:17:12:25 | withParam | 'withParam -? Block' | | cfg.swift:35:5:35:5 | CatchClause | 'CatchClause -V MyError -^ ... .error1 -> isZero -> Argument -V x -^ isZero(...) -? MyError -^ ... .error2 -^ ConditionalPattern -^ OrPattern' | -| cfg.swift:390:1:390:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V Derived -^ BaseType -V C' | -| cfg.swift:527:13:527:16 | Task | 'Task -^ ... .detached -^ Argument -V FunctionExpr -^ ... .detached(...)' | -| cfg.swift:569:1:569:1 | ClassLikeDeclaration | 'ClassLikeDeclaration -V MyProcotolImpl -^ BaseType -V MyProtocol' | +testFailures +| cfg.swift:32:27:32:103 | // $ nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' | Missing result: nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' | +| cfg.swift:400:27:400:103 | // $ nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' | Missing result: nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' | diff --git a/unified/ql/test/library-tests/controlflow/cfg.swift b/unified/ql/test/library-tests/controlflow/cfg.swift index 2061d46cd78a..6882f9043cf3 100644 --- a/unified/ql/test/library-tests/controlflow/cfg.swift +++ b/unified/ql/test/library-tests/controlflow/cfg.swift @@ -7,9 +7,9 @@ func returnZero() -> Int { return 0 } returnZero() Double(topLevelDecl) -enum MyError: Error { // $ nonSimple='ClassLikeDeclaration -V MyError -^ BaseType -V Error' +enum MyError: Error { case error1, error2 - case error3(withParam: Int) + case error3(withParam: Int) // $ nonSimple='withParam -? Block' } func isZero(x : Int) -> Bool { @@ -29,7 +29,7 @@ func tryCatch(x : Int) -> Int { do { try mightThrow(x: 0) // $ bbStep='mightThrow(...) : exception -> CatchClause(+5)' bbStep='mightThrow(...) : successor -> try ...(+0)' print("Did not throw.") - try! mightThrow(x: 0) + try! mightThrow(x: 0) // $ nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' print("Still did not throw.") // $ bbStep='print(...) : successor -> 0(+11)' } catch MyError.error1 , MyError.error2 where isZero(x: x) { // $ bbStep='OrPattern : match -> Block(+0)' bbStep='OrPattern : no-match -> CatchClause(+2)' nonSimple='CatchClause -V MyError -^ ... .error1 -> isZero -> Argument -V x -^ isZero(...) -? MyError -^ ... .error2 -^ ConditionalPattern -^ OrPattern' @@ -141,10 +141,10 @@ func patterns(x : Int) -> Bool { { } // $ bbStep='Block : successor -> _(-1)' bbStep='Block : successor -> SwitchExpr(+2)' switch x { - case 0, 1: // $ bbStep='OrPattern : match -> Block(+0)' bbStep='OrPattern : no-match -> SwitchCase(+3)' + case 0, 1: // $ bbStep='OrPattern : match -> Block(+1)' bbStep='OrPattern : no-match -> SwitchCase(+3)' return true return true // $ noCfg - case x where // $ bbContinues='Block goto true(+3)' bbStep='ConditionalPattern : match -> Block(+0)' bbStep='ConditionalPattern : no-match -> SwitchCase(+4)' + case x where // $ bbStep='ConditionalPattern : match -> Block(+3)' bbStep='ConditionalPattern : no-match -> SwitchCase(+4)' (x >= 2) && // $ bbStep='... >= ... : false -> x(-1)' bbStep='... >= ... : true -> x(+1)' x < 5: // $ bbStep='... < ... : successor -> x(-2)' return true @@ -387,7 +387,7 @@ func testTupleElement(t : (a: Int, Int, c: Int)) -> Int { return t.a + t.1 + t.c + (1, 2, 3).0 } -class Derived : C { // $ nonSimple='ClassLikeDeclaration -V Derived -^ BaseType -V C' +class Derived : C { init() { super.init(n: 0) } @@ -397,7 +397,7 @@ func doWithoutCatch(x : Int) throws -> Int { do { try mightThrow(x: 0) // $ bbStep='mightThrow(...) : successor -> try ...(+0)' print("Did not throw.") - try! mightThrow(x: 0) + try! mightThrow(x: 0) // $ nonSimple='mightThrow -> Argument -V 0 -^ CallExpr -? try! -^ UnaryExpr' print("Still did not throw.") } return 0 @@ -524,7 +524,7 @@ func testAvailable() -> Int { // $ noCfg func testAsyncFor () async { // $ noCfg var stream = AsyncStream(Int.self, bufferingPolicy: .bufferingNewest(5), { // $ bbContinues='Block goto Task(+2)' continuation in // $ bbContinues='continuation goto Block(-1)' - Task.detached { // $ nonSimple='Task -^ ... .detached -^ Argument -V FunctionExpr -^ ... .detached(...)' + Task.detached { for i in 1...100 { // $ bbStep='... ... ... : empty -> continuation(+3)' bbStep='... ... ... : non-empty -> i(+0)' continuation.yield(i) // $ bbStep='... .yield(...) : successor -> continuation(+2)' bbStep='... .yield(...) : successor -> i(-1)' } @@ -566,7 +566,7 @@ protocol MyProtocol { func source() -> Int } -class MyProcotolImpl : MyProtocol { // $ nonSimple='ClassLikeDeclaration -V MyProcotolImpl -^ BaseType -V MyProtocol' +class MyProcotolImpl : MyProtocol { func source() -> Int { return 0 } } diff --git a/unified/ql/test/library-tests/dataflow/test.expected b/unified/ql/test/library-tests/dataflow/test.expected index fb4090d3e62f..fb050d0a5aba 100644 --- a/unified/ql/test/library-tests/dataflow/test.expected +++ b/unified/ql/test/library-tests/dataflow/test.expected @@ -56,7 +56,7 @@ edges | test.swift:10:18:10:31 | source(...) | test.swift:10:10:10:33 | StringInterpolationExpr | provenance | | | test.swift:11:18:11:31 | source(...) | test.swift:11:10:11:38 | StringInterpolationExpr | provenance | | | test.swift:16:10:16:33 | TupleExpr [0] | test.swift:16:10:16:35 | ... .0 | provenance | | -| test.swift:16:11:16:25 | source(...) | test.swift:16:10:16:33 | TupleExpr [0] | provenance | | +| test.swift:16:11:16:24 | source(...) | test.swift:16:10:16:33 | TupleExpr [0] | provenance | | | test.swift:19:10:19:33 | TupleExpr [1] | test.swift:19:10:19:35 | ... .1 | provenance | | | test.swift:19:19:19:32 | source(...) | test.swift:19:10:19:33 | TupleExpr [1] | provenance | | | test.swift:23:9:23:9 | a | test.swift:24:10:24:10 | a | provenance | | @@ -64,7 +64,7 @@ edges | test.swift:28:9:28:14 | TupleExpr [0] | test.swift:28:10:28:10 | a | provenance | | | test.swift:28:10:28:10 | a | test.swift:29:10:29:10 | a | provenance | | | test.swift:28:18:28:41 | TupleExpr [0] | test.swift:28:9:28:14 | TupleExpr [0] | provenance | | -| test.swift:28:19:28:33 | source(...) | test.swift:28:18:28:41 | TupleExpr [0] | provenance | | +| test.swift:28:19:28:32 | source(...) | test.swift:28:18:28:41 | TupleExpr [0] | provenance | | | test.swift:32:9:32:14 | TupleExpr [1] | test.swift:32:13:32:13 | d | provenance | | | test.swift:32:13:32:13 | d | test.swift:34:10:34:10 | d | provenance | | | test.swift:32:18:32:41 | TupleExpr [1] | test.swift:32:9:32:14 | TupleExpr [1] | provenance | | @@ -85,7 +85,7 @@ edges | test.swift:64:6:64:10 | [post] tuple [1] | test.swift:66:10:66:14 | tuple [1] | provenance | | | test.swift:64:6:64:12 | ... .1 | test.swift:64:6:64:10 | [post] tuple [1] | provenance | | | test.swift:64:20:64:51 | TupleExpr [0] | test.swift:64:5:64:16 | TupleExpr [0] | provenance | | -| test.swift:64:21:64:35 | source(...) | test.swift:64:20:64:51 | TupleExpr [0] | provenance | | +| test.swift:64:21:64:34 | source(...) | test.swift:64:20:64:51 | TupleExpr [0] | provenance | | | test.swift:66:10:66:14 | tuple [1] | test.swift:66:10:66:16 | ... .1 | provenance | | | test.swift:74:5:74:9 | [post] tuple [0] | test.swift:75:10:75:14 | tuple [0] | provenance | | | test.swift:74:5:74:11 | ... .0 | test.swift:74:5:74:9 | [post] tuple [0] | provenance | | @@ -105,7 +105,7 @@ edges | test.swift:117:9:117:13 | tuple [1] | test.swift:120:17:120:21 | tuple [1] | provenance | | | test.swift:117:17:117:50 | TupleExpr [0] | test.swift:117:9:117:13 | tuple [0] | provenance | | | test.swift:117:17:117:50 | TupleExpr [1] | test.swift:117:9:117:13 | tuple [1] | provenance | | -| test.swift:117:18:117:33 | source(...) | test.swift:117:17:117:50 | TupleExpr [0] | provenance | | +| test.swift:117:18:117:32 | source(...) | test.swift:117:17:117:50 | TupleExpr [0] | provenance | | | test.swift:117:35:117:49 | source(...) | test.swift:117:17:117:50 | TupleExpr [1] | provenance | | | test.swift:120:9:120:13 | TupleExpr [0] | test.swift:120:10:120:10 | a | provenance | | | test.swift:120:9:120:13 | TupleExpr [1] | test.swift:120:12:120:12 | b | provenance | | @@ -216,7 +216,7 @@ nodes | test.swift:11:18:11:31 | source(...) | semmle.label | source(...) | | test.swift:16:10:16:33 | TupleExpr [0] | semmle.label | TupleExpr [0] | | test.swift:16:10:16:35 | ... .0 | semmle.label | ... .0 | -| test.swift:16:11:16:25 | source(...) | semmle.label | source(...) | +| test.swift:16:11:16:24 | source(...) | semmle.label | source(...) | | test.swift:19:10:19:33 | TupleExpr [1] | semmle.label | TupleExpr [1] | | test.swift:19:10:19:35 | ... .1 | semmle.label | ... .1 | | test.swift:19:19:19:32 | source(...) | semmle.label | source(...) | @@ -226,7 +226,7 @@ nodes | test.swift:28:9:28:14 | TupleExpr [0] | semmle.label | TupleExpr [0] | | test.swift:28:10:28:10 | a | semmle.label | a | | test.swift:28:18:28:41 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:28:19:28:33 | source(...) | semmle.label | source(...) | +| test.swift:28:19:28:32 | source(...) | semmle.label | source(...) | | test.swift:29:10:29:10 | a | semmle.label | a | | test.swift:32:9:32:14 | TupleExpr [1] | semmle.label | TupleExpr [1] | | test.swift:32:13:32:13 | d | semmle.label | d | @@ -252,7 +252,7 @@ nodes | test.swift:64:6:64:10 | [post] tuple [1] | semmle.label | [post] tuple [1] | | test.swift:64:6:64:12 | ... .1 | semmle.label | ... .1 | | test.swift:64:20:64:51 | TupleExpr [0] | semmle.label | TupleExpr [0] | -| test.swift:64:21:64:35 | source(...) | semmle.label | source(...) | +| test.swift:64:21:64:34 | source(...) | semmle.label | source(...) | | test.swift:66:10:66:14 | tuple [1] | semmle.label | tuple [1] | | test.swift:66:10:66:16 | ... .1 | semmle.label | ... .1 | | test.swift:74:5:74:9 | [post] tuple [0] | semmle.label | [post] tuple [0] | @@ -277,7 +277,7 @@ nodes | test.swift:117:9:117:13 | tuple [1] | semmle.label | tuple [1] | | test.swift:117:17:117:50 | TupleExpr [0] | semmle.label | TupleExpr [0] | | test.swift:117:17:117:50 | TupleExpr [1] | semmle.label | TupleExpr [1] | -| test.swift:117:18:117:33 | source(...) | semmle.label | source(...) | +| test.swift:117:18:117:32 | source(...) | semmle.label | source(...) | | test.swift:117:35:117:49 | source(...) | semmle.label | source(...) | | test.swift:120:9:120:13 | TupleExpr [0] | semmle.label | TupleExpr [0] | | test.swift:120:9:120:13 | TupleExpr [1] | semmle.label | TupleExpr [1] | @@ -346,22 +346,22 @@ testFailures | test.swift:9:10:9:33 | StringInterpolationExpr | test.swift:9:13:9:26 | source(...) | test.swift:9:10:9:33 | StringInterpolationExpr | $@ | test.swift:9:13:9:26 | source(...) | source(...) | | test.swift:10:10:10:33 | StringInterpolationExpr | test.swift:10:18:10:31 | source(...) | test.swift:10:10:10:33 | StringInterpolationExpr | $@ | test.swift:10:18:10:31 | source(...) | source(...) | | test.swift:11:10:11:38 | StringInterpolationExpr | test.swift:11:18:11:31 | source(...) | test.swift:11:10:11:38 | StringInterpolationExpr | $@ | test.swift:11:18:11:31 | source(...) | source(...) | -| test.swift:16:10:16:35 | ... .0 | test.swift:16:11:16:25 | source(...) | test.swift:16:10:16:35 | ... .0 | $@ | test.swift:16:11:16:25 | source(...) | source(...) | +| test.swift:16:10:16:35 | ... .0 | test.swift:16:11:16:24 | source(...) | test.swift:16:10:16:35 | ... .0 | $@ | test.swift:16:11:16:24 | source(...) | source(...) | | test.swift:19:10:19:35 | ... .1 | test.swift:19:19:19:32 | source(...) | test.swift:19:10:19:35 | ... .1 | $@ | test.swift:19:19:19:32 | source(...) | source(...) | | test.swift:24:10:24:10 | a | test.swift:23:13:23:26 | source(...) | test.swift:24:10:24:10 | a | $@ | test.swift:23:13:23:26 | source(...) | source(...) | -| test.swift:29:10:29:10 | a | test.swift:28:19:28:33 | source(...) | test.swift:29:10:29:10 | a | $@ | test.swift:28:19:28:33 | source(...) | source(...) | +| test.swift:29:10:29:10 | a | test.swift:28:19:28:32 | source(...) | test.swift:29:10:29:10 | a | $@ | test.swift:28:19:28:32 | source(...) | source(...) | | test.swift:34:10:34:10 | d | test.swift:32:27:32:40 | source(...) | test.swift:34:10:34:10 | d | $@ | test.swift:32:27:32:40 | source(...) | source(...) | | test.swift:39:10:39:10 | a | test.swift:38:13:38:26 | source(...) | test.swift:39:10:39:10 | a | $@ | test.swift:38:13:38:26 | source(...) | source(...) | | test.swift:47:10:47:16 | ... .0 | test.swift:46:15:46:28 | source(...) | test.swift:47:10:47:16 | ... .0 | $@ | test.swift:46:15:46:28 | source(...) | source(...) | | test.swift:58:10:58:23 | ... .0 | test.swift:53:22:53:35 | source(...) | test.swift:58:10:58:23 | ... .0 | $@ | test.swift:53:22:53:35 | source(...) | source(...) | -| test.swift:66:10:66:16 | ... .1 | test.swift:64:21:64:35 | source(...) | test.swift:66:10:66:16 | ... .1 | $@ | test.swift:64:21:64:35 | source(...) | source(...) | +| test.swift:66:10:66:16 | ... .1 | test.swift:64:21:64:34 | source(...) | test.swift:66:10:66:16 | ... .1 | $@ | test.swift:64:21:64:34 | source(...) | source(...) | | test.swift:75:10:75:16 | ... .0 | test.swift:74:15:74:29 | source(...) | test.swift:75:10:75:16 | ... .0 | $@ | test.swift:74:15:74:29 | source(...) | source(...) | | test.swift:90:10:90:10 | x | test.swift:86:13:86:27 | source(...) | test.swift:90:10:90:10 | x | $@ | test.swift:86:13:86:27 | source(...) | source(...) | | test.swift:96:10:96:10 | y | test.swift:94:13:94:27 | source(...) | test.swift:96:10:96:10 | y | $@ | test.swift:94:13:94:27 | source(...) | source(...) | | test.swift:99:14:99:14 | x | test.swift:86:13:86:27 | source(...) | test.swift:99:14:99:14 | x | $@ | test.swift:86:13:86:27 | source(...) | source(...) | | test.swift:100:14:100:14 | y | test.swift:94:13:94:27 | source(...) | test.swift:100:14:100:14 | y | $@ | test.swift:94:13:94:27 | source(...) | source(...) | | test.swift:112:10:112:16 | ... .0 | test.swift:107:19:107:33 | source(...) | test.swift:112:10:112:16 | ... .0 | $@ | test.swift:107:19:107:33 | source(...) | source(...) | -| test.swift:125:10:125:10 | a | test.swift:117:18:117:33 | source(...) | test.swift:125:10:125:10 | a | $@ | test.swift:117:18:117:33 | source(...) | source(...) | +| test.swift:125:10:125:10 | a | test.swift:117:18:117:32 | source(...) | test.swift:125:10:125:10 | a | $@ | test.swift:117:18:117:32 | source(...) | source(...) | | test.swift:126:10:126:10 | b | test.swift:117:35:117:49 | source(...) | test.swift:126:10:126:10 | b | $@ | test.swift:117:35:117:49 | source(...) | source(...) | | test.swift:132:10:132:10 | a | test.swift:131:19:131:33 | source(...) | test.swift:132:10:132:10 | a | $@ | test.swift:131:19:131:33 | source(...) | source(...) | | test.swift:138:10:138:10 | a | test.swift:137:10:137:24 | source(...) | test.swift:138:10:138:10 | a | $@ | test.swift:137:10:137:24 | source(...) | source(...) |