From 636f31d5b39a86365a8a20e1c435cc5011706363 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 11 Sep 2026 13:20:54 +0000 Subject: [PATCH 01/10] yeast: Track child source ranges in separate contexts NB: This temporarily changes the test output for bulk imports, blocks, and things like synthesised Array and Option literals. Later commits will fix these up again. --- shared/yeast-macros/src/parse.rs | 1 + shared/yeast/doc/yeast.md | 21 +++ shared/yeast/src/build.rs | 139 +++++++++----- shared/yeast/src/lib.rs | 32 +++- shared/yeast/tests/test.rs | 170 +++++++++++++++++- unified/extractor/BUILD.bazel | 5 + .../extractor/src/languages/swift/swift.rs | 10 +- .../closures/closure-with-capture-list.output | 4 +- .../closure-with-explicit-parameters.output | 4 +- .../closure-with-shorthand-parameters.output | 4 +- .../closures/multi-statement-closure.output | 4 +- .../swift/closures/trailing-closure.output | 8 +- .../empty-array-literal-with-type.output | 4 +- ...g-modifier-does-not-leak-to-sibling.output | 8 +- .../swift/control-flow/defer-statement.output | 4 +- .../control-flow/discard-statement.output | 8 +- .../swift/control-flow/fallthrough.output | 12 +- .../swift/control-flow/guard-let.output | 14 +- .../if-let-optional-binding.output | 14 +- .../nested-enum-case-pattern.output | 16 +- .../switch-case-item-where-clauses.output | 14 +- .../switch-expression-pattern.output | 44 ++--- .../control-flow/switch-statement.output | 14 +- .../switch-with-binding-pattern.output | 8 +- ...with-labeled-case-pattern-arguments.output | 8 +- ...with-deeply-nested-path-three-parts.output | 6 +- .../import-with-dotted-path-two-parts.output | 6 +- .../simple-import-with-single-name.output | 6 +- .../expressions/array-type-constructor.output | 18 +- .../expressions/array-type-metatype.output | 6 +- .../expressions/unsafe-expression.output | 4 +- ...nction-with-default-parameter-value.output | 4 +- .../function-with-inout-parameter.output | 4 +- .../function-with-named-parameters.output | 4 +- .../function-with-no-parameters.output | 4 +- ...ion-with-parameters-and-return-type.output | 4 +- .../swift/functions/generic-function.output | 4 +- .../swift/functions/variadic-function.output | 4 +- .../literals/string-with-interpolation.output | 36 ++-- ...solved-operator-sequence-with-casts.output | 4 +- ...lved-operator-sequence-with-ternary.output | 4 +- .../unresolved-operator-sequence.output | 4 +- .../catch-where-clauses.output | 8 +- .../optionals-and-errors/do-catch.output | 4 +- .../optionals-and-errors/force-unwrap.output | 4 +- .../optional-enum-case-binding.output | 10 +- .../optional-type-annotation.output | 4 +- .../throwing-function.output | 4 +- .../try-expression-2.output | 4 +- .../try-expression.output | 4 +- ...er-does-not-leak-into-accessor-body.output | 12 +- .../corpus/swift/types/class-function.output | 4 +- .../swift/types/class-inheritance.output | 4 +- .../swift/types/class-with-initializer.output | 4 +- .../swift/types/class-with-method.output | 4 +- .../class-with-multiple-base-types.output | 6 +- .../swift/types/computed-property.output | 6 +- .../types/constructor-with-parameters.output | 4 +- .../types/enum-with-associated-values.output | 16 +- .../corpus/swift/types/enum-with-cases.output | 16 +- ...separated-cases-chained-declaration.output | 22 +-- .../tests/corpus/swift/types/extension.output | 4 +- ...tion-type-with-convention-attribute.output | 4 +- ...nction-type-with-sendable-attribute.output | 4 +- .../swift/types/noncopyable-type.output | 4 +- .../property-with-getter-and-setter.output | 4 +- .../swift/types/protocol-declaration.output | 8 +- ...nd-read-write-property-requirements.output | 4 +- .../corpus/swift/types/static-function.output | 4 +- ...fier-does-not-leak-into-initializer.output | 8 +- .../multiple-bindings-on-one-line.output | 4 +- ...y-with-willset-and-didset-observers.output | 8 +- unified/extractor/tests/location_tests.rs | 100 +++++++++++ 73 files changed, 677 insertions(+), 311 deletions(-) create mode 100644 unified/extractor/tests/location_tests.rs 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..b4ef1905b141 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -235,6 +235,27 @@ 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. After +the transform completes, the matched input node's 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. 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. + 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 diff --git a/shared/yeast/src/build.rs b/shared/yeast/src/build.rs index f4f5ae5d18f3..63b7b199311c 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,22 @@ 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. + 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 +62,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,12 +83,80 @@ 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 !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 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 + } + /// Look up a capture variable, returning its node Id. pub fn capture(&self, name: &str) -> Id { self.captures @@ -133,41 +194,33 @@ 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 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 +256,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 +289,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/lib.rs b/shared/yeast/src/lib.rs index 76bfa58124d6..cae721db6586 100644 --- a/shared/yeast/src/lib.rs +++ b/shared/yeast/src/lib.rs @@ -128,9 +128,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; } @@ -592,8 +593,7 @@ 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| { @@ -618,6 +618,24 @@ 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) => union_source_ranges(existing, source_range), + None => 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. @@ -1134,8 +1152,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, diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index e0abe51053d9..dbaee55beb22 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,174 @@ 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 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); +} + +/// 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); +} + +/// 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..3577c0482a0e 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -112,21 +112,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> { diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output index 1e28176add2b..a2b19c5503a7 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output @@ -68,13 +68,13 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="⟨body⟩⟨capture_declaration⟩" + function_expr source="{ [⟨capture_declaration⟩] in ⟨body⟩ }" capture_declaration: variable_declaration source="⟨modifier⟩ ⟨pattern⟩" modifier: modifier "weak" source="weak" pattern: identifier "self" source="self" body: - block source="{ [weak self] in ⟨stmt⟩ }" + block source="⟨stmt⟩" stmt: call_expr source="⟨callee⟩()" callee: diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output b/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output index a44783d172d1..786e7d7fb4ee 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output @@ -70,14 +70,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="⟨body⟩⟨parameter⟩⟨return_type⟩" + function_expr source="{ (⟨parameter⟩) -> ⟨return_type⟩ in ⟨body⟩ }" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" return_type: identifier "Int" source="Int" body: - block source="{ (x: Int) -> Int in ⟨stmt⟩ }" + block source="⟨stmt⟩" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "x" source="x" diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output b/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output index 6de0b9bea57c..3e30fac78c01 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output @@ -47,9 +47,9 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="⟨body⟩" + function_expr source="{ ⟨body⟩ }" body: - block source="{ ⟨stmt⟩ }" + block source="⟨stmt⟩" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "$0" source="$0" diff --git a/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output b/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output index 36649bd5ac0d..f9c054aa0b96 100644 --- a/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output +++ b/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output @@ -101,14 +101,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="⟨body⟩⟨parameter⟩⟨return_type⟩" + function_expr source="{ (⟨parameter⟩) -> ⟨return_type⟩ in\n ⟨body⟩\n}" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" return_type: identifier "Int" source="Int" body: - block source="{ (x: Int) -> Int in\n ⟨stmt⟩\n ⟨stmt⟩\n}" + block source="⟨stmt⟩\n ⟨stmt⟩" stmt: variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" diff --git a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output index ad75555b1002..c50bbde02dcc 100644 --- a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output +++ b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output @@ -43,17 +43,17 @@ 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⟩" + function_expr source="{ ⟨body⟩ }" body: - block source="{ ⟨stmt⟩ }" + block source="⟨stmt⟩" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "$0" source="$0" 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..a8bd2282ef02 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/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..ba856ea604f4 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⟩() {\n ⟨body⟩\n}" name_node: identifier "withCleanup" source="withCleanup" body: - block source="func withCleanup() {\n ⟨stmt⟩\n ⟨stmt⟩\n}" + block source="⟨stmt⟩\n ⟨stmt⟩" 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..3e3a36d98330 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⟩() {\n ⟨body⟩\n }" modifier: modifier "consuming" source="consuming" name_node: identifier "close" source="close" body: - block source="consuming func close() {\n ⟨stmt⟩\n }" + block source="⟨stmt⟩" 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..03ed5d1acc38 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⟩) {\n ⟨body⟩\n}" 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="⟨stmt⟩" 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..9312e38adefc 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="let ⟨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="⟨expr⟩" + modifier: modifier "let" source= 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..09085763f268 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="let ⟨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="⟨expr⟩" + modifier: modifier "let" source= 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..d8cea8bdf335 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,7 +162,7 @@ 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" @@ -173,9 +173,9 @@ top_level source="⟨body⟩" base: inferred_type_expr "." source="." member_name_node: identifier "received" source="received" argument: - argument source="⟨value⟩" + 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,7 +186,7 @@ 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⟩)" callee: identifier "print" source="print" @@ -195,7 +195,7 @@ top_level source="⟨body⟩" 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..a60324f47a3d 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,16 +170,16 @@ 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⟩," condition: @@ -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..a0da0f15d1e6 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⟩" @@ -342,54 +342,54 @@ top_level source="⟨body⟩" 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="try ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "try" source="try value" - unary_expr source="⟨operand⟩⟨operator⟩" + operator: prefix_operator "try" source= + unary_expr source="⟨operand⟩!" 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⟩ as ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "as" source="value as Target" + operator: infix_operator "as" source= type: identifier "Target" source="Target" - type_test_expr source="⟨expr⟩⟨operator⟩⟨type⟩" + type_test_expr source="⟨expr⟩ is ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "is" source="value is Target" + operator: infix_operator "is" source= type: identifier "Target" source="Target" - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="await ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "await" source="await value" + operator: prefix_operator "await" source= 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..889e155ae46b 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,14 +142,14 @@ 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⟩)" callee: @@ -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/desugar/import-with-deeply-nested-path-three-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output index a35890d96301..51bb4af69e5b 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output @@ -27,7 +27,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="⟨pattern⟩⟨imported_expr⟩" + import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" imported_expr: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: @@ -36,6 +36,6 @@ top_level source="⟨body⟩" member_name_node: identifier "Networking" source="Networking" member_name_node: identifier "URLSession" source="URLSession" pattern: - named_pattern source="⟨sub_pattern⟩⟨name_node⟩" + named_pattern source="⟨name_node⟩" name_node: identifier "URLSession" source="URLSession" - sub_pattern: bulk_importing_pattern "import Foundation.Networking.URLSession" source="import Foundation.Networking.URLSession" + sub_pattern: bulk_importing_pattern source= diff --git a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output index 3f069a347481..462a807f0859 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output @@ -24,12 +24,12 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="⟨pattern⟩⟨imported_expr⟩" + import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" imported_expr: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: identifier "Foundation" source="Foundation" member_name_node: identifier "Networking" source="Networking" pattern: - named_pattern source="⟨sub_pattern⟩⟨name_node⟩" + named_pattern source="⟨name_node⟩" name_node: identifier "Networking" source="Networking" - sub_pattern: bulk_importing_pattern "import Foundation.Networking" source="import Foundation.Networking" + sub_pattern: bulk_importing_pattern source= diff --git a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output index d52673da8dda..af9a65e04a90 100644 --- a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output +++ b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output @@ -21,9 +21,9 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="⟨pattern⟩⟨imported_expr⟩" + import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" imported_expr: identifier "Foundation" source="Foundation" pattern: - named_pattern source="⟨sub_pattern⟩⟨name_node⟩" + named_pattern source="⟨name_node⟩" name_node: identifier "Foundation" source="Foundation" - sub_pattern: bulk_importing_pattern "import Foundation" source="import Foundation" + sub_pattern: bulk_importing_pattern source= 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..06a7cb6fd7b5 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,16 +156,16 @@ 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⟩" + function_expr source="{ ⟨parameter⟩ ⟨parameter⟩ in\n\t⟨body⟩\n}" parameter: parameter source="⟨pattern⟩," pattern: identifier "_" source="_" parameter source="⟨pattern⟩" pattern: identifier "count" source="count" body: - block source="{ _, count in\n\t⟨stmt⟩\n}" + block source="⟨stmt⟩" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: 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..91ec160cbf4a 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..2ef5fc67213e 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⟩() {}" 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/function-with-default-parameter-value.output b/unified/extractor/tests/corpus/swift/functions/function-with-default-parameter-value.output index 65da7fc5c00f..6bb554d6521b 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⟩) {\n ⟨body⟩\n}" 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="⟨stmt⟩" 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..e44356fe9606 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⟩) {\n ⟨body⟩\n}" 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="⟨stmt⟩" 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..632da0f8efc6 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⟩) {\n ⟨body⟩\n}" 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="⟨stmt⟩" 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..b555273112d9 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⟩() {\n ⟨body⟩\n}" name_node: identifier "greet" source="greet" body: - block source="func greet() {\n ⟨stmt⟩\n}" + block source="⟨stmt⟩" 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..6d4d1c903a71 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,7 +73,7 @@ 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⟩ {\n ⟨body⟩\n}" name_node: identifier "add" source="add" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -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="⟨stmt⟩" 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..ba87c47a7b4f 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⟩ {\n ⟨body⟩\n}" 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="⟨stmt⟩" stmt: return_expr source="return ⟨value⟩" value: identifier "x" source="x" diff --git a/unified/extractor/tests/corpus/swift/functions/variadic-function.output b/unified/extractor/tests/corpus/swift/functions/variadic-function.output index 0f73aabfd8cd..da0c84c07d74 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⟩ {\n ⟨body⟩\n}" name_node: identifier "sum" source="sum" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩..." @@ -86,7 +86,7 @@ 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="⟨stmt⟩" stmt: return_expr source="return ⟨value⟩" value: 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..3531178c0f21 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,8 +274,8 @@ 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⟩," value: identifier "x" source="x" @@ -285,8 +285,8 @@ 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⟩," value: identifier "x" source="x" @@ -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,8 +308,8 @@ 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⟩," name_node: identifier "arg" source="arg" 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..f0bb8aefa70c 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,7 +93,7 @@ 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⟩) {\n ⟨body⟩\n}" name_node: identifier "casts" source="casts" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -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="⟨stmt⟩\n ⟨stmt⟩" 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..4b7d12ff3420 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,7 +99,7 @@ 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⟩ {\n ⟨body⟩\n}" name_node: identifier "choose" source="choose" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -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="⟨stmt⟩" 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..846ab17caac4 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output @@ -66,7 +66,7 @@ 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⟩) {\n ⟨body⟩\n}" name_node: identifier "combine" source="combine" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -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="⟨stmt⟩" 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..8a7c088b4c1b 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,15 +144,15 @@ top_level source="⟨body⟩" body: block source="{\n ⟨stmt⟩\n}" stmt: - unary_expr source="⟨operator⟩⟨operand⟩" + unary_expr source="try ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="try foo()" + operator: prefix_operator "try" source= 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⟩," condition: 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..cb91d71f311e 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="try ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="try foo()" + operator: prefix_operator "try" source= 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..67f5fc5ee2c9 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 @@ -36,6 +36,6 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "n" source="n" value: - unary_expr source="⟨operand⟩⟨operator⟩" + unary_expr source="⟨operand⟩!" 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..35b898deaedd 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..ef0e79bc0e7d 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..1d080dbeefa6 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⟩ {\n ⟨body⟩\n}" name_node: identifier "read" source="read" return_type: identifier "String" source="String" body: - block source="func read() throws -> String {\n ⟨stmt⟩\n}" + block source="⟨stmt⟩" 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..4d7b105688c8 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="try! ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try!" source="try! foo()" + operator: prefix_operator "try!" source= 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..fdf08e347588 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="try? ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try?" source="try? foo()" + operator: prefix_operator "try?" source= 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..17004c0c8959 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,9 +92,9 @@ sourceFile --- -top_level source="⟨body⟩" +top_level source="⟨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" @@ -107,16 +107,16 @@ 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: 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..c161b663b50a 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⟩() {}" 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..53c0a00cb10b 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⟩) {\n ⟨body⟩\n }" 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="⟨stmt⟩" 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..7d181dae78d2 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⟩() {\n ⟨body⟩\n }" name_node: identifier "bump" source="bump" body: - block source="func bump() {\n ⟨stmt⟩\n }" + block source="⟨stmt⟩" 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..5025163d5a2f 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⟩ {\n ⟨body⟩\n }" 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="⟨stmt⟩" 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..70a8e539cd6c 100644 --- a/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output +++ b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output @@ -67,7 +67,7 @@ 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⟩) {}" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," external_name_node: identifier "width" source="width" @@ -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..0d80213f4eb9 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="⟨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="⟨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..9fdf78ce054e 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..cc2c30590e27 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 @@ -48,21 +48,21 @@ top_level source="⟨body⟩" 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..d1358e2f2f17 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/function-type-with-convention-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output index e26e022261f4..299c609c8022 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output @@ -67,5 +67,5 @@ top_level source="⟨body⟩" pattern: identifier "callback" source="callback" type: unsupported_node "@convention(c) () -> Void" source="@convention(c) () -> Void" value: - function_expr source="⟨body⟩" - body: block "{}" source="{}" + function_expr source="{}" + body: block source= diff --git a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output index 3d4a80ebea18..15eb240a8f64 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output @@ -60,5 +60,5 @@ top_level source="⟨body⟩" pattern: identifier "handler" source="handler" type: unsupported_node "@Sendable () -> Void" source="@Sendable () -> Void" value: - function_expr source="⟨body⟩" - body: block "{}" source="{}" + function_expr source="{}" + body: block source= 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..f73a341020af 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 @@ -126,10 +126,10 @@ top_level source="⟨body⟩" 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="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n get { return _v }\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source="set { _v = newValue }" + modifier "chained_declaration" source= name_node: identifier "v" source="v" accessor_kind: accessor_kind "set" source="set" type: identifier "Int" source="Int" diff --git a/unified/extractor/tests/corpus/swift/types/protocol-declaration.output b/unified/extractor/tests/corpus/swift/types/protocol-declaration.output index b2bc4b1e1867..261e40a59f76 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..d8efdbcc7bd0 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 @@ -118,8 +118,8 @@ top_level source="⟨body⟩" name_node: identifier "bar" source="bar" 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" + accessor_declaration source="⟨name_node⟩: ⟨type⟩ { get ⟨accessor_kind⟩" + modifier: modifier "chained_declaration" source= name_node: identifier "bar" source="bar" accessor_kind: accessor_kind "set" source="set" type: identifier "String" source="String" diff --git a/unified/extractor/tests/corpus/swift/types/static-function.output b/unified/extractor/tests/corpus/swift/types/static-function.output index b7f87ab13d76..0c66ba1c251b 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⟩() {}" 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..7666b6d7dedb 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 @@ -44,9 +44,9 @@ top_level source="⟨body⟩" 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..7f9576a0c1b5 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,10 +110,10 @@ 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="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source="willSet { print(newValue) }" + modifier "chained_declaration" source= name_node: identifier "x" source="x" accessor_kind: accessor_kind "willSet" source="willSet" body: @@ -124,10 +124,10 @@ 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="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n willSet { print(newValue) }\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source="didSet { print(oldValue) }" + modifier "chained_declaration" source= name_node: identifier "x" source="x" accessor_kind: accessor_kind "didSet" source="didSet" body: diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs new file mode 100644 index 000000000000..0d3850b394d5 --- /dev/null +++ b/unified/extractor/tests/location_tests.rs @@ -0,0 +1,100 @@ +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; + } + Some(node.byte_range()) + }) + .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 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", + ); + assert_has_empty_span(&ast, "bulk_importing_pattern", None, 0); +} From d44191009395b912918cf1b4d63c78ae5b9a88bc Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 11 Sep 2026 14:40:00 +0000 Subject: [PATCH 02/10] yeast: Handle empty locations correctly The location 0..0 was being treated as "no useable location", which at the beginning of a file could cause problems. We now represent this as None instead, making Some(0..0) a valid empty location. --- shared/yeast/src/lib.rs | 88 +++++++---------------- shared/yeast/src/range.rs | 40 +++++++++++ shared/yeast/tests/test.rs | 30 ++++++++ unified/extractor/tests/location_tests.rs | 14 +--- 4 files changed, 99 insertions(+), 73 deletions(-) diff --git a/shared/yeast/src/lib.rs b/shared/yeast/src/lib.rs index cae721db6586..affc94c9bc88 100644 --- a/shared/yeast/src/lib.rs +++ b/shared/yeast/src/lib.rs @@ -144,10 +144,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) } } @@ -598,7 +595,7 @@ impl Ast { .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, }) }), @@ -631,7 +628,7 @@ impl Ast { panic!("extend_source_range: cannot modify a parsed node"); } node.source_range = Some(match node.source_range { - Some(existing) => union_source_ranges(existing, source_range), + Some(existing) => existing.union(source_range), None => source_range, }); } @@ -673,35 +670,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; } _ => {} } @@ -810,25 +802,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 { @@ -871,36 +844,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 { diff --git a/shared/yeast/src/range.rs b/shared/yeast/src/range.rs index e56bbcc6fb85..b9aade99ce74 100644 --- a/shared/yeast/src/range.rs +++ b/shared/yeast/src/range.rs @@ -30,3 +30,43 @@ 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 + } + } +} diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index dbaee55beb22..3d34fa69405b 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -1709,6 +1709,36 @@ fn test_nested_synthetic_node_uses_child_location() { assert_eq!(arguments.byte_range(), 0..3); } +/// 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] diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs index 0d3850b394d5..08cec5643244 100644 --- a/unified/extractor/tests/location_tests.rs +++ b/unified/extractor/tests/location_tests.rs @@ -37,7 +37,8 @@ fn ranges(ast: &Ast, kind: &str, content: Option<&str>) -> Vec, e ); } -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()"; @@ -96,5 +87,4 @@ fn import_member_chain_excludes_import_keyword() { None, "import Foundation.Networking.URLSession", ); - assert_has_empty_span(&ast, "bulk_importing_pattern", None, 0); } From d70ddb8a61387bb2ab0e0195221ae478af374c87 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 17 Sep 2026 14:46:52 +0000 Subject: [PATCH 03/10] yeast: Add explicit location macros Adds two new macros, both variants of the existing `tree!` macro. First, `tree_at!` takes an extra argument, and sets the location of the root of the constructed tree to be that of the argument in question. Secondly, `tree_spanning!` does the same construction, but accepts an iterable of nodes instead. It then makes it so that the location of the root node of the constructed tree is the smallest span that contains all of the locations given by the iterable. --- shared/yeast/doc/yeast.md | 16 +++++++++ shared/yeast/src/build.rs | 28 +++++++++++++++ shared/yeast/src/lib.rs | 46 ++++++++++++++++++++++++ shared/yeast/tests/test.rs | 71 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 161 insertions(+) diff --git a/shared/yeast/doc/yeast.md b/shared/yeast/doc/yeast.md index b4ef1905b141..16f6ddb9c937 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -256,6 +256,22 @@ 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 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 diff --git a/shared/yeast/src/build.rs b/shared/yeast/src/build.rs index 63b7b199311c..6473dcacd8bd 100644 --- a/shared/yeast/src/build.rs +++ b/shared/yeast/src/build.rs @@ -157,6 +157,16 @@ impl<'a, C> BuildCtx<'a, C> { 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. pub fn capture(&self, name: &str) -> Id { self.captures @@ -180,6 +190,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 @@ -217,6 +239,12 @@ impl<'a, C> BuildCtx<'a, C> { 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); diff --git a/shared/yeast/src/lib.rs b/shared/yeast/src/lib.rs index affc94c9bc88..a71b604411c5 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; @@ -633,6 +667,18 @@ impl Ast { }); } + /// 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. diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index 3d34fa69405b..5a6536654394 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -1799,6 +1799,77 @@ fn test_explicit_recursive_translation_keeps_nested_rule_location() { 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] From 308baff0f9530d1ae551d9d987d9e34edd24c58f Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 11 Sep 2026 14:45:12 +0000 Subject: [PATCH 04/10] yeast: Add location heuristic for synthetic nodes with no location set For such nodes, we assign them the zero-length location at the beginning of the matched input node. --- shared/yeast/doc/yeast.md | 17 ++++++----- shared/yeast/src/build.rs | 17 ++++++++++- shared/yeast/tests/test.rs | 28 ++++++++++++++++++ .../empty-array-literal-with-type.output | 2 +- .../swift/control-flow/guard-let.output | 12 ++++---- .../if-let-optional-binding.output | 12 ++++---- .../switch-expression-pattern.output | 16 +++++----- ...with-deeply-nested-path-three-parts.output | 6 ++-- .../import-with-dotted-path-two-parts.output | 6 ++-- .../simple-import-with-single-name.output | 6 ++-- .../expressions/array-type-constructor.output | 12 ++++---- .../expressions/array-type-metatype.output | 6 ++-- .../expressions/unsafe-expression.output | 2 +- .../literals/string-with-interpolation.output | 18 ++++++------ .../catch-where-clauses.output | 2 +- .../optionals-and-errors/do-catch.output | 2 +- .../optionals-and-errors/force-unwrap.output | 2 +- .../optional-enum-case-binding.output | 6 ++-- .../optional-type-annotation.output | 2 +- .../try-expression-2.output | 2 +- .../try-expression.output | 2 +- .../corpus/swift/types/class-function.output | 2 +- .../swift/types/computed-property.output | 2 +- .../types/constructor-with-parameters.output | 2 +- .../types/enum-with-associated-values.output | 16 +++++----- .../corpus/swift/types/enum-with-cases.output | 8 ++--- ...separated-cases-chained-declaration.output | 14 ++++----- ...tion-type-with-convention-attribute.output | 2 +- ...nction-type-with-sendable-attribute.output | 2 +- .../property-with-getter-and-setter.output | 2 +- .../swift/types/protocol-declaration.output | 4 +-- ...nd-read-write-property-requirements.output | 2 +- .../corpus/swift/types/static-function.output | 2 +- .../multiple-bindings-on-one-line.output | 2 +- ...y-with-willset-and-didset-observers.output | 4 +-- unified/extractor/tests/location_tests.rs | 29 +++++++++++++++++++ 36 files changed, 173 insertions(+), 98 deletions(-) diff --git a/shared/yeast/doc/yeast.md b/shared/yeast/doc/yeast.md index 16f6ddb9c937..fa917517f655 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -238,9 +238,10 @@ yeast::trees!(ctx, ### Source locations Captured nodes keep the locations assigned by their own translations. New -nodes in an output template derive their locations from their children. After -the transform completes, the matched input node's range is added only to -locally-created nodes returned as rule results: +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!( @@ -251,10 +252,12 @@ rule!( ``` Here `inner` derives its range from `child`, while the returned `outer` node -also includes the full `wrapper` range. 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. +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: diff --git a/shared/yeast/src/build.rs b/shared/yeast/src/build.rs index 6473dcacd8bd..6cbf130cb820 100644 --- a/shared/yeast/src/build.rs +++ b/shared/yeast/src/build.rs @@ -37,7 +37,8 @@ pub struct BuildCtx<'a, C: 'a = ()> { /// /// The `rule!` macro applies this range to locally-created result roots /// after the transform completes. Nested synthetic nodes derive their - /// ranges from their children. + /// 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, @@ -104,6 +105,16 @@ impl<'a, C> BuildCtx<'a, C> { 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); } @@ -129,6 +140,10 @@ impl<'a, C> BuildCtx<'a, C> { 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); diff --git a/shared/yeast/tests/test.rs b/shared/yeast/tests/test.rs index 5a6536654394..a7e24a45366f 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -1709,6 +1709,34 @@ fn test_nested_synthetic_node_uses_child_location() { 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] 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 a8bd2282ef02..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 @@ -46,6 +46,6 @@ top_level source="⟨body⟩" pattern: identifier "xs" source="xs" type: generic_type_expr source="[⟨type_argument⟩]" - base: identifier "Array" source= + base: identifier "Array" source="" type_argument: identifier "Int" source="Int" value: array_literal "[]" source="[]" 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 9312e38adefc..c0140465e35e 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="let ⟨pattern⟩ = ⟨value⟩" + pattern_guard_expr source="⟨pattern⟩ = ⟨value⟩" pattern: call_expr source="⟨argument⟩" callee: - member_access_expr source= - base: identifier "Optional" source= - member_name_node: identifier "some" source= + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: - expr_pattern source="⟨expr⟩" - modifier: modifier "let" source= + expr_pattern source="let ⟨expr⟩" + modifier: modifier "let" source="" 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 09085763f268..e582bf0debd1 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="let ⟨pattern⟩ = ⟨value⟩" + pattern_guard_expr source="⟨pattern⟩ = ⟨value⟩" pattern: call_expr source="⟨argument⟩" callee: - member_access_expr source= - base: identifier "Optional" source= - member_name_node: identifier "some" source= + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: - expr_pattern source="⟨expr⟩" - modifier: modifier "let" source= + expr_pattern source="let ⟨expr⟩" + modifier: modifier "let" source="" expr: identifier "value" source="value" value: identifier "optional" source="optional" then: 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 a0da0f15d1e6..8df5dec77cd2 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 @@ -344,29 +344,29 @@ top_level source="⟨body⟩" map_literal "[key: value]" source="[key: value]" call_expr source="⟨argument⟩?" callee: - member_access_expr source= - base: identifier "Optional" source= - member_name_node: identifier "some" source= + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: identifier "optional" source="optional" unary_expr source="try ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "try" source= + operator: prefix_operator "try" source="" unary_expr source="⟨operand⟩!" operand: identifier "value" source="value" - operator: postfix_operator "!" source= + operator: postfix_operator "!" source="" type_cast_expr source="⟨expr⟩ as ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "as" source= + operator: infix_operator "as" source="" type: identifier "Target" source="Target" type_test_expr source="⟨expr⟩ is ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "is" source= + operator: infix_operator "is" source="" type: identifier "Target" source="Target" unary_expr source="await ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "await" source= + operator: prefix_operator "await" source="" body: block source="⟨stmt⟩" stmt: diff --git a/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output index 51bb4af69e5b..2a53a68fa283 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output @@ -27,7 +27,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" + import_declaration source="⟨pattern⟩⟨imported_expr⟩" imported_expr: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: @@ -36,6 +36,6 @@ top_level source="⟨body⟩" member_name_node: identifier "Networking" source="Networking" member_name_node: identifier "URLSession" source="URLSession" pattern: - named_pattern source="⟨name_node⟩" + named_pattern source="import Foundation.Networking.⟨name_node⟩" name_node: identifier "URLSession" source="URLSession" - sub_pattern: bulk_importing_pattern source= + sub_pattern: bulk_importing_pattern source="" diff --git a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output index 462a807f0859..479cc68a7516 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output @@ -24,12 +24,12 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" + import_declaration source="⟨pattern⟩⟨imported_expr⟩" imported_expr: member_access_expr source="⟨base⟩.⟨member_name_node⟩" base: identifier "Foundation" source="Foundation" member_name_node: identifier "Networking" source="Networking" pattern: - named_pattern source="⟨name_node⟩" + named_pattern source="import Foundation.⟨name_node⟩" name_node: identifier "Networking" source="Networking" - sub_pattern: bulk_importing_pattern source= + sub_pattern: bulk_importing_pattern source="" diff --git a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output index af9a65e04a90..9f87889dca84 100644 --- a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output +++ b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output @@ -21,9 +21,9 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - import_declaration source="import ⟨imported_expr⟩⟨pattern⟩" + import_declaration source="⟨pattern⟩⟨imported_expr⟩" imported_expr: identifier "Foundation" source="Foundation" pattern: - named_pattern source="⟨name_node⟩" + named_pattern source="import ⟨name_node⟩" name_node: identifier "Foundation" source="Foundation" - sub_pattern: bulk_importing_pattern source= + sub_pattern: bulk_importing_pattern source="" 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 06a7cb6fd7b5..15f599d3749b 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="⟨type_argument⟩" - base: identifier "Array" source= + 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="[⟨callee⟩](⟨argument⟩) ⟨argument⟩" + call_expr source="⟨callee⟩](⟨argument⟩) ⟨argument⟩" callee: - generic_type_expr source="⟨type_argument⟩" - base: identifier "Array" source= + 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/array-type-metatype.output b/unified/extractor/tests/corpus/swift/expressions/array-type-metatype.output index 91ec160cbf4a..066e65ccca00 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="⟨type_argument⟩" - base: identifier "Array" source= + 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 2ef5fc67213e..71a5e020dc30 100644 --- a/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output +++ b/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output @@ -47,5 +47,5 @@ top_level source="⟨body⟩" stmt: function_declaration source="func ⟨name_node⟩() {}" name_node: identifier "doWork" source="doWork" - body: block source= + body: block source="" unsupported_node "unsafe doWork()" source="unsafe doWork()" 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 3531178c0f21..821aec63a98c 100644 --- a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output +++ b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output @@ -229,7 +229,7 @@ top_level source="⟨body⟩" element: string_literal "hello " source="hello " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "name" source="name" @@ -238,13 +238,13 @@ top_level source="⟨body⟩" element: string_literal "hello " source="hello " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "first" source="first" string_literal " " source=" " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "last" source="last" @@ -253,7 +253,7 @@ top_level source="⟨body⟩" element: string_literal "result: " source="result: " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: @@ -266,7 +266,7 @@ top_level source="⟨body⟩" element: string_literal "prefix " source="prefix " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩" value: identifier "value" source="value" @@ -275,7 +275,7 @@ top_level source="⟨body⟩" element: string_literal "foo " source="foo " call_expr source="\\(⟨argument⟩ ⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩," value: identifier "x" source="x" @@ -286,7 +286,7 @@ top_level source="⟨body⟩" element: string_literal "foo " source="foo " call_expr source="\\(⟨argument⟩ ⟨argument⟩ ⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨value⟩," value: identifier "x" source="x" @@ -299,7 +299,7 @@ top_level source="⟨body⟩" element: string_literal "foo " source="foo " call_expr source="\\(⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨name_node⟩: ⟨value⟩" name_node: identifier "arg" source="arg" @@ -309,7 +309,7 @@ top_level source="⟨body⟩" element: string_literal "foo " source="foo " call_expr source="\\(⟨argument⟩ ⟨argument⟩)" - callee: builtin_expr "interpolation" source= + callee: builtin_expr "interpolation" source="" argument: argument source="⟨name_node⟩: ⟨value⟩," name_node: identifier "arg" source="arg" 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 8a7c088b4c1b..50185d37137d 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 @@ -148,7 +148,7 @@ top_level source="⟨body⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source= + operator: prefix_operator "try" source="" catch_clause: catch_clause source="catch ⟨pattern⟩ ⟨body⟩" pattern: 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 cb91d71f311e..769c1c058939 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 @@ -69,7 +69,7 @@ top_level source="⟨body⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source= + operator: prefix_operator "try" source="" 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 67f5fc5ee2c9..55198489b5ee 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⟩!" operand: identifier "opt" source="opt" - operator: postfix_operator "!" source= + 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 35b898deaedd..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 @@ -82,9 +82,9 @@ top_level source="⟨body⟩" pattern: call_expr source="⟨argument⟩?" callee: - member_access_expr source= - base: identifier "Optional" source= - member_name_node: identifier "some" source= + member_access_expr source="" + base: identifier "Optional" source="" + member_name_node: identifier "some" source="" argument: argument source="⟨value⟩" value: 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 ef0e79bc0e7d..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 @@ -43,6 +43,6 @@ top_level source="⟨body⟩" pattern: identifier "x" source="x" type: generic_type_expr source="⟨type_argument⟩?" - base: identifier "Optional" source= + 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/try-expression-2.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/try-expression-2.output index 4d7b105688c8..206923657a07 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 @@ -47,4 +47,4 @@ top_level source="⟨body⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try!" source= + operator: prefix_operator "try!" source="" 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 fdf08e347588..ef912781b16a 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 @@ -47,4 +47,4 @@ top_level source="⟨body⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try?" source= + operator: prefix_operator "try?" source="" diff --git a/unified/extractor/tests/corpus/swift/types/class-function.output b/unified/extractor/tests/corpus/swift/types/class-function.output index c161b663b50a..ab62ab362670 100644 --- a/unified/extractor/tests/corpus/swift/types/class-function.output +++ b/unified/extractor/tests/corpus/swift/types/class-function.output @@ -54,4 +54,4 @@ top_level source="⟨body⟩" function_declaration source="⟨modifier⟩ func ⟨name_node⟩() {}" modifier: modifier "class" source="class" name_node: identifier "make" source="make" - body: block source= + body: block source="" diff --git a/unified/extractor/tests/corpus/swift/types/computed-property.output b/unified/extractor/tests/corpus/swift/types/computed-property.output index 5025163d5a2f..8c3e270e4d91 100644 --- a/unified/extractor/tests/corpus/swift/types/computed-property.output +++ b/unified/extractor/tests/corpus/swift/types/computed-property.output @@ -116,7 +116,7 @@ top_level source="⟨body⟩" accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n ⟨body⟩\n }" modifier: modifier "var" source="var" name_node: identifier "area" source="area" - accessor_kind: accessor_kind "get" source= + accessor_kind: accessor_kind "get" source="" type: identifier "Double" source="Double" body: block source="⟨stmt⟩" 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 70a8e539cd6c..feffa590a843 100644 --- a/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output +++ b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output @@ -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 source= + 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 0d80213f4eb9..18792a2b229e 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 "enum_case" source= + class_like_declaration source="⟨name_node⟩⟨member⟩)" + modifier: modifier "enum_case" source="" name_node: identifier "circle" source="circle" member: - constructor_declaration source="⟨parameter⟩" + constructor_declaration source="circle(⟨parameter⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" pattern: identifier "radius" source="radius" - body: block source= - class_like_declaration source="⟨name_node⟩(⟨member⟩)" - modifier: modifier "enum_case" source= + 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="⟨parameter⟩" + constructor_declaration source="square(⟨parameter⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" pattern: identifier "side" source="side" - body: block source= + 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 9fdf78ce054e..8b3fa7f85775 100644 --- a/unified/extractor/tests/corpus/swift/types/enum-with-cases.output +++ b/unified/extractor/tests/corpus/swift/types/enum-with-cases.output @@ -70,14 +70,14 @@ top_level source="⟨body⟩" name_node: identifier "Direction" source="Direction" member: variable_declaration source="⟨pattern⟩" - modifier: modifier "enum_case" source= + modifier: modifier "enum_case" source="" pattern: identifier "north" source="north" variable_declaration source="⟨pattern⟩" - modifier: modifier "enum_case" source= + modifier: modifier "enum_case" source="" pattern: identifier "south" source="south" variable_declaration source="⟨pattern⟩" - modifier: modifier "enum_case" source= + modifier: modifier "enum_case" source="" pattern: identifier "east" source="east" variable_declaration source="⟨pattern⟩" - modifier: modifier "enum_case" source= + 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 cc2c30590e27..19146c2fb731 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 @@ -49,20 +49,20 @@ top_level source="⟨body⟩" name_node: identifier "Suit" source="Suit" member: variable_declaration source="⟨pattern⟩," - modifier: modifier "enum_case" source= + modifier: modifier "enum_case" source="" pattern: identifier "clubs" source="clubs" variable_declaration source="⟨pattern⟩," modifier: - modifier "chained_declaration" source= - modifier "enum_case" source= + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "diamonds" source="diamonds" variable_declaration source="⟨pattern⟩," modifier: - modifier "chained_declaration" source= - modifier "enum_case" source= + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "hearts" source="hearts" variable_declaration source="⟨pattern⟩" modifier: - modifier "chained_declaration" source= - modifier "enum_case" source= + modifier "chained_declaration" source="" + modifier "enum_case" source="" pattern: identifier "spades" source="spades" diff --git a/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output index 299c609c8022..39273b1056d0 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output @@ -68,4 +68,4 @@ top_level source="⟨body⟩" type: unsupported_node "@convention(c) () -> Void" source="@convention(c) () -> Void" value: function_expr source="{}" - body: block source= + body: block source="" diff --git a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output index 15eb240a8f64..9fbaf4167fd3 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output @@ -61,4 +61,4 @@ top_level source="⟨body⟩" type: unsupported_node "@Sendable () -> Void" source="@Sendable () -> Void" value: function_expr source="{}" - body: block source= + body: block source="" 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 f73a341020af..94d514f11cdb 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 @@ -129,7 +129,7 @@ top_level source="⟨body⟩" accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: ⟨type⟩ {\n get { return _v }\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source= + modifier "chained_declaration" source="" name_node: identifier "v" source="v" accessor_kind: accessor_kind "set" source="set" type: identifier "Int" source="Int" diff --git a/unified/extractor/tests/corpus/swift/types/protocol-declaration.output b/unified/extractor/tests/corpus/swift/types/protocol-declaration.output index 261e40a59f76..5f1155e278a8 100644 --- a/unified/extractor/tests/corpus/swift/types/protocol-declaration.output +++ b/unified/extractor/tests/corpus/swift/types/protocol-declaration.output @@ -63,8 +63,8 @@ top_level source="⟨body⟩" member: function_declaration source="func ⟨name_node⟩()" name_node: identifier "draw" source="draw" - body: block source= + body: block source="" function_declaration source="⟨modifier⟩ func ⟨name_node⟩()" modifier: modifier "static" source="static" name_node: identifier "make" source="make" - body: block source= + 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 d8efdbcc7bd0..0886939c1d94 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 @@ -119,7 +119,7 @@ top_level source="⟨body⟩" accessor_kind: accessor_kind "get" source="get" type: identifier "String" source="String" accessor_declaration source="⟨name_node⟩: ⟨type⟩ { get ⟨accessor_kind⟩" - modifier: modifier "chained_declaration" source= + modifier: modifier "chained_declaration" source="" name_node: identifier "bar" source="bar" accessor_kind: accessor_kind "set" source="set" type: identifier "String" source="String" diff --git a/unified/extractor/tests/corpus/swift/types/static-function.output b/unified/extractor/tests/corpus/swift/types/static-function.output index 0c66ba1c251b..210bb2909449 100644 --- a/unified/extractor/tests/corpus/swift/types/static-function.output +++ b/unified/extractor/tests/corpus/swift/types/static-function.output @@ -54,4 +54,4 @@ top_level source="⟨body⟩" function_declaration source="⟨modifier⟩ func ⟨name_node⟩() {}" modifier: modifier "static" source="static" name_node: identifier "make" source="make" - body: block source= + body: block source="" 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 7666b6d7dedb..07797954fc8d 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 @@ -47,6 +47,6 @@ top_level source="⟨body⟩" variable_declaration source="⟨modifier⟩ x = 1, ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" - modifier "chained_declaration" source= + 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 7f9576a0c1b5..4670fd83b1d5 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 @@ -113,7 +113,7 @@ top_level source="⟨body⟩" accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source= + modifier "chained_declaration" source="" name_node: identifier "x" source="x" accessor_kind: accessor_kind "willSet" source="willSet" body: @@ -127,7 +127,7 @@ top_level source="⟨body⟩" accessor_declaration source="⟨modifier⟩ ⟨name_node⟩: Int = 0 {\n willSet { print(newValue) }\n ⟨accessor_kind⟩ ⟨body⟩" modifier: modifier "var" source="var" - modifier "chained_declaration" source= + modifier "chained_declaration" source="" name_node: identifier "x" source="x" accessor_kind: accessor_kind "didSet" source="didSet" body: diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs index 08cec5643244..9380ff7442e8 100644 --- a/unified/extractor/tests/location_tests.rs +++ b/unified/extractor/tests/location_tests.rs @@ -51,6 +51,16 @@ fn assert_has_span(ast: &Ast, source: &str, kind: &str, content: Option<&str>, e ); } +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()"; @@ -61,6 +71,25 @@ fn generic_type_children_have_local_ranges() { assert_has_span(&ast, source, "identifier", Some("Foo"), "Foo"); } +#[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"; From de995a9625b1bb8c03c325430c3a78650fc8f541 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 11 Sep 2026 14:58:55 +0000 Subject: [PATCH 05/10] Unified: Add locations for blocks Blocks are slightly awkward, since we destructure them (as codeBlock) in the query, and then reconstruct them (as `block`) in the rule body, meaning the location of the block is (by default) assigned to the wrong place by the heuristic. To get around this, I added a helper function that updates the location appropriately, including handling cases where we only optionally match a block. (Also, in some cases we can fix this by just not destructuring `codeBlock`s in the first place -- there's already a rule that maps `codeBlock` to `block`.) --- .../extractor/src/languages/swift/swift.rs | 46 ++++++++++++++----- .../closures/closure-with-capture-list.output | 4 +- .../closure-with-explicit-parameters.output | 4 +- .../closure-with-shorthand-parameters.output | 4 +- .../closures/multi-statement-closure.output | 4 +- .../swift/closures/trailing-closure.output | 4 +- .../swift/control-flow/defer-statement.output | 4 +- .../control-flow/discard-statement.output | 4 +- .../swift/control-flow/fallthrough.output | 4 +- .../expressions/array-type-constructor.output | 4 +- .../expressions/unsafe-expression.output | 4 +- ...nction-with-default-parameter-value.output | 4 +- .../function-with-inout-parameter.output | 4 +- .../function-with-named-parameters.output | 4 +- .../function-with-no-parameters.output | 4 +- ...ion-with-parameters-and-return-type.output | 4 +- .../swift/functions/generic-function.output | 4 +- .../swift/functions/variadic-function.output | 4 +- ...solved-operator-sequence-with-casts.output | 4 +- ...lved-operator-sequence-with-ternary.output | 4 +- .../unresolved-operator-sequence.output | 4 +- .../throwing-function.output | 4 +- .../corpus/swift/types/class-function.output | 4 +- .../swift/types/class-with-initializer.output | 4 +- .../swift/types/class-with-method.output | 4 +- .../swift/types/computed-property.output | 4 +- .../types/constructor-with-parameters.output | 4 +- .../tests/corpus/swift/types/extension.output | 4 +- ...tion-type-with-convention-attribute.output | 4 +- ...nction-type-with-sendable-attribute.output | 4 +- .../corpus/swift/types/static-function.output | 4 +- unified/extractor/tests/location_tests.rs | 9 ++++ 32 files changed, 103 insertions(+), 72 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 3577c0482a0e..9e6b4cde1e5b 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -1,5 +1,5 @@ use codeql_extractor::extractor::desugaring; -use yeast::{ConcreteDesugarer, DesugaringConfig, PhaseKind, Rule, rule, tree}; +use yeast::{ConcreteDesugarer, DesugaringConfig, PhaseKind, Rule, rule, tree, tree_at}; /// User context propagated from outer rules down to the inner rules that /// emit the corresponding output declarations, so that each emitted node @@ -60,6 +60,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 @@ -298,14 +309,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 @@ -561,7 +572,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} @@ -569,7 +580,7 @@ fn translation_rules() -> Vec> { type_parameter: {type_params} parameter: {params} return_type: {ret} - body: (block stmt: {body})) + body: {body}) ), rule!( (functionDecl @@ -744,14 +755,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 @@ -1271,22 +1282,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!( diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output index a2b19c5503a7..1e28176add2b 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-capture-list.output @@ -68,13 +68,13 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="{ [⟨capture_declaration⟩] in ⟨body⟩ }" + function_expr source="⟨body⟩⟨capture_declaration⟩" capture_declaration: variable_declaration source="⟨modifier⟩ ⟨pattern⟩" modifier: modifier "weak" source="weak" pattern: identifier "self" source="self" body: - block source="⟨stmt⟩" + block source="{ [weak self] in ⟨stmt⟩ }" stmt: call_expr source="⟨callee⟩()" callee: diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output b/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output index 786e7d7fb4ee..a44783d172d1 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-explicit-parameters.output @@ -70,14 +70,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="{ (⟨parameter⟩) -> ⟨return_type⟩ in ⟨body⟩ }" + function_expr source="⟨body⟩⟨parameter⟩⟨return_type⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩" + block source="{ (x: Int) -> Int in ⟨stmt⟩ }" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "x" source="x" diff --git a/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output b/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output index 3e30fac78c01..6de0b9bea57c 100644 --- a/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output +++ b/unified/extractor/tests/corpus/swift/closures/closure-with-shorthand-parameters.output @@ -47,9 +47,9 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="{ ⟨body⟩ }" + function_expr source="⟨body⟩" body: - block source="⟨stmt⟩" + block source="{ ⟨stmt⟩ }" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "$0" source="$0" diff --git a/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output b/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output index f9c054aa0b96..36649bd5ac0d 100644 --- a/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output +++ b/unified/extractor/tests/corpus/swift/closures/multi-statement-closure.output @@ -101,14 +101,14 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "f" source="f" value: - function_expr source="{ (⟨parameter⟩) -> ⟨return_type⟩ in\n ⟨body⟩\n}" + function_expr source="⟨body⟩⟨parameter⟩⟨return_type⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩\n ⟨stmt⟩" + block source="{ (x: Int) -> Int in\n ⟨stmt⟩\n ⟨stmt⟩\n}" stmt: variable_declaration source="⟨modifier⟩ ⟨pattern⟩ = ⟨value⟩" modifier: modifier "let" source="let" diff --git a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output index c50bbde02dcc..ad76f9b9abee 100644 --- a/unified/extractor/tests/corpus/swift/closures/trailing-closure.output +++ b/unified/extractor/tests/corpus/swift/closures/trailing-closure.output @@ -51,9 +51,9 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: - function_expr source="{ ⟨body⟩ }" + function_expr source="⟨body⟩" body: - block source="⟨stmt⟩" + block source="{ ⟨stmt⟩ }" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "$0" source="$0" 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 ba856ea604f4..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="func ⟨name_node⟩() {\n ⟨body⟩\n}" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "withCleanup" source="withCleanup" body: - block source="⟨stmt⟩\n ⟨stmt⟩" + 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 3e3a36d98330..df6bb28eb01b 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output +++ b/unified/extractor/tests/corpus/swift/control-flow/discard-statement.output @@ -74,9 +74,9 @@ top_level source="⟨body⟩" base_type source="⟨type⟩" type: unsupported_node "~Copyable" source="~Copyable" member: - function_declaration source="⟨modifier⟩ func ⟨name_node⟩() {\n ⟨body⟩\n }" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "consuming" source="consuming" name_node: identifier "close" source="close" body: - block source="⟨stmt⟩" + 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 03ed5d1acc38..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="func ⟨name_node⟩(⟨parameter⟩) {\n ⟨body⟩\n}" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩) ⟨body⟩" name_node: identifier "classify" source="classify" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩" @@ -94,7 +94,7 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" body: - block source="⟨stmt⟩" + block source="{\n ⟨stmt⟩\n}" stmt: switch_expr source="switch ⟨value⟩ {\n ⟨case⟩\n ⟨case⟩\n }" value: identifier "x" source="x" 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 15f599d3749b..23df62e6a6d7 100644 --- a/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output +++ b/unified/extractor/tests/corpus/swift/expressions/array-type-constructor.output @@ -158,14 +158,14 @@ top_level source="⟨body⟩" value: int_literal "1" source="1" argument source="⟨value⟩" value: - function_expr source="{ ⟨parameter⟩ ⟨parameter⟩ in\n\t⟨body⟩\n}" + function_expr source="⟨body⟩⟨parameter⟩⟨parameter⟩" parameter: parameter source="⟨pattern⟩," pattern: identifier "_" source="_" parameter source="⟨pattern⟩" pattern: identifier "count" source="count" body: - block source="⟨stmt⟩" + block source="{ _, count in\n\t⟨stmt⟩\n}" stmt: binary_expr source="⟨left⟩ ⟨operator⟩ ⟨right⟩" left: identifier "count" source="count" diff --git a/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output b/unified/extractor/tests/corpus/swift/expressions/unsafe-expression.output index 71a5e020dc30..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="func ⟨name_node⟩() {}" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "doWork" source="doWork" - body: block source="" + body: block "{}" source="{}" unsupported_node "unsafe doWork()" source="unsafe doWork()" 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 6bb554d6521b..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="func ⟨name_node⟩(⟨parameter⟩) {\n ⟨body⟩\n}" + 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="⟨stmt⟩" + 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 e44356fe9606..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="func ⟨name_node⟩(⟨parameter⟩) {\n ⟨body⟩\n}" + 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="⟨stmt⟩" + 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 632da0f8efc6..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="func ⟨name_node⟩(⟨parameter⟩) {\n ⟨body⟩\n}" + 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="⟨stmt⟩" + 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 b555273112d9..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="func ⟨name_node⟩() {\n ⟨body⟩\n}" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "greet" source="greet" body: - block source="⟨stmt⟩" + 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 6d4d1c903a71..fcac6c8c2843 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,7 +73,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) -> ⟨return_type⟩ {\n ⟨body⟩\n}" + 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⟩," @@ -86,7 +86,7 @@ top_level source="⟨body⟩" pattern: identifier "b" source="b" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩" + 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 ba87c47a7b4f..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="func ⟨name_node⟩<⟨type_parameter⟩>(⟨parameter⟩) -> ⟨return_type⟩ {\n ⟨body⟩\n}" + 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="⟨stmt⟩" + 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/variadic-function.output b/unified/extractor/tests/corpus/swift/functions/variadic-function.output index da0c84c07d74..9b48167deb9c 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="func ⟨name_node⟩(⟨parameter⟩) -> ⟨return_type⟩ {\n ⟨body⟩\n}" + 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,7 +86,7 @@ top_level source="⟨body⟩" pattern: identifier "values" source="values" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" 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 f0bb8aefa70c..92ad43c34164 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,7 +93,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) {\n ⟨body⟩\n}" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" name_node: identifier "casts" source="casts" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -105,7 +105,7 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "b" source="b" body: - block source="⟨stmt⟩\n ⟨stmt⟩" + 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 4b7d12ff3420..42f184e76b15 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,7 +99,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩ ⟨parameter⟩ ⟨parameter⟩) -> ⟨return_type⟩ {\n ⟨body⟩\n}" + 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⟩," @@ -120,7 +120,7 @@ top_level source="⟨body⟩" pattern: identifier "d" source="d" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩" + 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 846ab17caac4..28953b21acc5 100644 --- a/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output +++ b/unified/extractor/tests/corpus/swift/operators/unresolved-operator-sequence.output @@ -66,7 +66,7 @@ top_level source="⟨body⟩" body: block source="⟨stmt⟩" stmt: - function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) {\n ⟨body⟩\n}" + function_declaration source="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" name_node: identifier "combine" source="combine" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," @@ -78,7 +78,7 @@ top_level source="⟨body⟩" type: identifier "Int" source="Int" pattern: identifier "b" source="b" body: - block source="⟨stmt⟩" + 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/throwing-function.output b/unified/extractor/tests/corpus/swift/optionals-and-errors/throwing-function.output index 1d080dbeefa6..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="func ⟨name_node⟩() throws -> ⟨return_type⟩ {\n ⟨body⟩\n}" + 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="⟨stmt⟩" + block source="{\n ⟨stmt⟩\n}" stmt: return_expr source="return ⟨value⟩" value: string_literal "\"\"" source="\"\"" diff --git a/unified/extractor/tests/corpus/swift/types/class-function.output b/unified/extractor/tests/corpus/swift/types/class-function.output index ab62ab362670..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⟩ func ⟨name_node⟩() {}" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "class" source="class" name_node: identifier "make" source="make" - body: block source="" + body: block "{}" source="{}" 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 53c0a00cb10b..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="init(⟨parameter⟩) {\n ⟨body⟩\n }" + constructor_declaration source="init(⟨parameter⟩) ⟨body⟩" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Int" source="Int" pattern: identifier "x" source="x" body: - block source="⟨stmt⟩" + 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 7d181dae78d2..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="func ⟨name_node⟩() {\n ⟨body⟩\n }" + function_declaration source="func ⟨name_node⟩() ⟨body⟩" name_node: identifier "bump" source="bump" body: - block source="⟨stmt⟩" + 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/computed-property.output b/unified/extractor/tests/corpus/swift/types/computed-property.output index 8c3e270e4d91..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⟩ ⟨name_node⟩: ⟨type⟩ {\n ⟨body⟩\n }" + 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="" type: identifier "Double" source="Double" body: - block source="⟨stmt⟩" + 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 feffa590a843..9e49e134c100 100644 --- a/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output +++ b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output @@ -67,7 +67,7 @@ top_level source="⟨body⟩" modifier: modifier "struct" source="struct" name_node: identifier "Size" source="Size" member: - constructor_declaration source="init(⟨parameter⟩ ⟨parameter⟩) {}" + constructor_declaration source="init(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" parameter: parameter source="⟨external_name_node⟩ ⟨pattern⟩: ⟨type⟩," external_name_node: identifier "width" source="width" @@ -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 source="" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/types/extension.output b/unified/extractor/tests/corpus/swift/types/extension.output index d1358e2f2f17..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="func ⟨name_node⟩() -> ⟨return_type⟩ { ⟨body⟩ }" + function_declaration source="func ⟨name_node⟩() -> ⟨return_type⟩ ⟨body⟩" name_node: identifier "squared" source="squared" return_type: identifier "Int" source="Int" body: - block source="⟨stmt⟩" + block source="{ ⟨stmt⟩ }" stmt: return_expr source="return ⟨value⟩" value: diff --git a/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output index 39273b1056d0..e26e022261f4 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-convention-attribute.output @@ -67,5 +67,5 @@ top_level source="⟨body⟩" pattern: identifier "callback" source="callback" type: unsupported_node "@convention(c) () -> Void" source="@convention(c) () -> Void" value: - function_expr source="{}" - body: block source="" + function_expr source="⟨body⟩" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output index 9fbaf4167fd3..3d4a80ebea18 100644 --- a/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output +++ b/unified/extractor/tests/corpus/swift/types/function-type-with-sendable-attribute.output @@ -60,5 +60,5 @@ top_level source="⟨body⟩" pattern: identifier "handler" source="handler" type: unsupported_node "@Sendable () -> Void" source="@Sendable () -> Void" value: - function_expr source="{}" - body: block source="" + function_expr source="⟨body⟩" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/corpus/swift/types/static-function.output b/unified/extractor/tests/corpus/swift/types/static-function.output index 210bb2909449..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⟩ func ⟨name_node⟩() {}" + function_declaration source="⟨modifier⟩ func ⟨name_node⟩() ⟨body⟩" modifier: modifier "static" source="static" name_node: identifier "make" source="make" - body: block source="" + body: block "{}" source="{}" diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs index 9380ff7442e8..ffa6062a46d9 100644 --- a/unified/extractor/tests/location_tests.rs +++ b/unified/extractor/tests/location_tests.rs @@ -71,6 +71,15 @@ fn generic_type_children_have_local_ranges() { assert_has_span(&ast, source, "identifier", Some("Foo"), "Foo"); } +#[test] +fn declaration_and_operator_tokens_keep_precise_ranges() { + let source = "func f() { return x }"; + let ast = desugar(source); + + assert_has_span(&ast, source, "block", None, "{ return x }"); + assert_has_span(&ast, source, "return_expr", None, "return x"); +} + #[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 }"; From ba9279d45474fd35125fcd26ec11117103e3efa1 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 11 Sep 2026 15:30:46 +0000 Subject: [PATCH 06/10] Unified: Fix locations of various tokens Handles things like `try!` (which is represented as two separate tokens -- we explicitly union their ranges) and "let" binding modifiers (where we reuse the bindingSpecifier, getting its location and string value for free). --- .../extractor/src/languages/swift/swift.rs | 97 ++++++++++++++----- .../swift/control-flow/guard-let.output | 4 +- .../if-let-optional-binding.output | 4 +- .../nested-enum-case-pattern.output | 4 +- .../switch-expression-pattern.output | 20 ++-- ...with-deeply-nested-path-three-parts.output | 4 +- .../import-with-dotted-path-two-parts.output | 4 +- .../simple-import-with-single-name.output | 4 +- .../catch-where-clauses.output | 4 +- .../optionals-and-errors/do-catch.output | 4 +- .../optionals-and-errors/force-unwrap.output | 4 +- .../try-expression-2.output | 4 +- .../try-expression.output | 4 +- .../types/enum-with-associated-values.output | 8 +- unified/extractor/tests/location_tests.rs | 52 +++++++++- 15 files changed, 158 insertions(+), 63 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 9e6b4cde1e5b..4bed1b2ce53c 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, tree_at}; +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 @@ -97,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") } @@ -474,14 +478,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)) @@element + => + class_like_declaration { + let body = tree!((block)); + let constructor = tree_at!( + ctx, + element, + (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)) @@ -681,12 +695,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!( @@ -859,6 +878,7 @@ fn translation_rules() -> Vec> { // form is matched first. rule!( (optionalBindingCondition + bindingSpecifier: @@spec pattern: (identifierPattern identifier: @name) initializer: (initializerClause value: @val)) => @@ -867,18 +887,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 @@ -962,11 +984,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 @@ -1000,17 +1030,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` @@ -1025,14 +1067,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 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 c0140465e35e..5d12fd0a7ea4 100644 --- a/unified/extractor/tests/corpus/swift/control-flow/guard-let.output +++ b/unified/extractor/tests/corpus/swift/control-flow/guard-let.output @@ -52,8 +52,8 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: - expr_pattern source="let ⟨expr⟩" - modifier: modifier "let" source="" + 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 e582bf0debd1..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 @@ -65,8 +65,8 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: - expr_pattern source="let ⟨expr⟩" - modifier: modifier "let" source="" + 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 d8cea8bdf335..4a6c67739d9d 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 @@ -173,9 +173,9 @@ top_level source="⟨body⟩" base: inferred_type_expr "." source="." member_name_node: identifier "received" source="received" argument: - argument source="⟨value⟩)," + 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="." 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 8df5dec77cd2..6ff524b63160 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 @@ -350,23 +350,23 @@ top_level source="⟨body⟩" argument: argument source="⟨value⟩" value: identifier "optional" source="optional" - unary_expr source="try ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "try" source="" - unary_expr source="⟨operand⟩!" + operator: prefix_operator "try" source="try" + unary_expr source="⟨operand⟩⟨operator⟩" operand: identifier "value" source="value" - operator: postfix_operator "!" source="" - type_cast_expr source="⟨expr⟩ as ⟨type⟩" + operator: postfix_operator "!" source="!" + type_cast_expr source="⟨expr⟩ ⟨operator⟩ ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "as" source="" + operator: infix_operator "as" source="as" type: identifier "Target" source="Target" - type_test_expr source="⟨expr⟩ is ⟨type⟩" + type_test_expr source="⟨expr⟩ ⟨operator⟩ ⟨type⟩" expr: identifier "value" source="value" - operator: infix_operator "is" source="" + operator: infix_operator "is" source="is" type: identifier "Target" source="Target" - unary_expr source="await ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: identifier "value" source="value" - operator: prefix_operator "await" source="" + operator: prefix_operator "await" source="await" body: block source="⟨stmt⟩" stmt: diff --git a/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output index 2a53a68fa283..a35890d96301 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-deeply-nested-path-three-parts.output @@ -36,6 +36,6 @@ top_level source="⟨body⟩" member_name_node: identifier "Networking" source="Networking" member_name_node: identifier "URLSession" source="URLSession" pattern: - named_pattern source="import Foundation.Networking.⟨name_node⟩" + named_pattern source="⟨sub_pattern⟩⟨name_node⟩" name_node: identifier "URLSession" source="URLSession" - sub_pattern: bulk_importing_pattern source="" + sub_pattern: bulk_importing_pattern "import Foundation.Networking.URLSession" source="import Foundation.Networking.URLSession" diff --git a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output index 479cc68a7516..3f069a347481 100644 --- a/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output +++ b/unified/extractor/tests/corpus/swift/desugar/import-with-dotted-path-two-parts.output @@ -30,6 +30,6 @@ top_level source="⟨body⟩" base: identifier "Foundation" source="Foundation" member_name_node: identifier "Networking" source="Networking" pattern: - named_pattern source="import Foundation.⟨name_node⟩" + named_pattern source="⟨sub_pattern⟩⟨name_node⟩" name_node: identifier "Networking" source="Networking" - sub_pattern: bulk_importing_pattern source="" + sub_pattern: bulk_importing_pattern "import Foundation.Networking" source="import Foundation.Networking" diff --git a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output index 9f87889dca84..d52673da8dda 100644 --- a/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output +++ b/unified/extractor/tests/corpus/swift/desugar/simple-import-with-single-name.output @@ -24,6 +24,6 @@ top_level source="⟨body⟩" import_declaration source="⟨pattern⟩⟨imported_expr⟩" imported_expr: identifier "Foundation" source="Foundation" pattern: - named_pattern source="import ⟨name_node⟩" + named_pattern source="⟨sub_pattern⟩⟨name_node⟩" name_node: identifier "Foundation" source="Foundation" - sub_pattern: bulk_importing_pattern source="" + sub_pattern: bulk_importing_pattern "import Foundation" source="import Foundation" 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 50185d37137d..d83a29460e61 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,11 +144,11 @@ top_level source="⟨body⟩" body: block source="{\n ⟨stmt⟩\n}" stmt: - unary_expr source="try ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="" + operator: prefix_operator "try" source="try" catch_clause: catch_clause source="catch ⟨pattern⟩ ⟨body⟩" pattern: 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 769c1c058939..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="try ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try" source="" + 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 55198489b5ee..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 @@ -36,6 +36,6 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "n" source="n" value: - unary_expr source="⟨operand⟩!" + unary_expr source="⟨operand⟩⟨operator⟩" operand: identifier "opt" source="opt" - operator: postfix_operator "!" source="" + operator: postfix_operator "!" 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 206923657a07..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="try! ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try!" source="" + 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 ef912781b16a..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="try? ⟨operand⟩" + unary_expr source="⟨operator⟩ ⟨operand⟩" operand: call_expr source="⟨callee⟩()" callee: identifier "foo" source="foo" - operator: prefix_operator "try?" source="" + operator: prefix_operator "try?" source="try?" 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 18792a2b229e..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,21 +73,21 @@ top_level source="⟨body⟩" modifier: modifier "enum" source="enum" name_node: identifier "Shape" source="Shape" member: - class_like_declaration source="⟨name_node⟩⟨member⟩)" + class_like_declaration source="⟨name_node⟩⟨member⟩" modifier: modifier "enum_case" source="" name_node: identifier "circle" source="circle" member: - constructor_declaration source="circle(⟨parameter⟩" + constructor_declaration source="circle(⟨parameter⟩)" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" pattern: identifier "radius" source="radius" body: block source="" - class_like_declaration source="⟨name_node⟩⟨member⟩)" + class_like_declaration source="⟨name_node⟩⟨member⟩" modifier: modifier "enum_case" source="" name_node: identifier "square" source="square" member: - constructor_declaration source="square(⟨parameter⟩" + constructor_declaration source="square(⟨parameter⟩)" parameter: parameter source="⟨pattern⟩: ⟨type⟩" type: identifier "Double" source="Double" diff --git a/unified/extractor/tests/location_tests.rs b/unified/extractor/tests/location_tests.rs index ffa6062a46d9..30ace4016f80 100644 --- a/unified/extractor/tests/location_tests.rs +++ b/unified/extractor/tests/location_tests.rs @@ -71,13 +71,63 @@ fn generic_type_children_have_local_ranges() { 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 }"; + 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] From 4d9e29587c2e315ad9ecd22c19685e6ae3dd8f15 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 18 Sep 2026 12:56:55 +0000 Subject: [PATCH 07/10] Unified: Exclude trailing commas from locations Build arguments, tuple-pattern elements, and tuple-type elements from their meaningful child ranges so separators remain owned by their parent nodes. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- shared/yeast/doc/yeast.md | 6 ++ shared/yeast/src/lib.rs | 56 ++++++++++++-- shared/yeast/src/range.rs | 27 +++++++ shared/yeast/tests/test.rs | 24 ++++++ .../extractor/src/languages/swift/swift.rs | 75 +++++++++++++------ .../swift/collections/tuple-literal.output | 6 +- .../nested-enum-case-pattern.output | 8 +- .../switch-case-item-where-clauses.output | 4 +- .../switch-expression-pattern.output | 4 +- ...with-labeled-case-pattern-arguments.output | 4 +- .../expressions/array-type-constructor.output | 10 +-- .../expressions/array-type-metatype.output | 4 +- .../functions/call-with-inout-argument.output | 4 +- .../swift/functions/function-call.output | 4 +- ...ion-with-parameters-and-return-type.output | 4 +- .../swift/functions/generic-type-alias.output | 4 +- .../functions/nested-function-type.output | 8 +- .../swift/functions/variadic-function.output | 4 +- .../literals/string-with-interpolation.output | 14 ++-- ...solved-operator-sequence-with-casts.output | 4 +- ...lved-operator-sequence-with-ternary.output | 8 +- .../unresolved-operator-sequence.output | 4 +- .../catch-where-clauses.output | 4 +- .../types/constructor-with-parameters.output | 4 +- ...separated-cases-chained-declaration.output | 8 +- ...ic-class-parameters-and-constraints.output | 6 +- .../multiple-bindings-on-one-line.output | 2 +- .../tuple-destructuring-binding.output | 4 +- .../controlflow/basicblock-slices.expected | 4 +- 29 files changed, 227 insertions(+), 91 deletions(-) diff --git a/shared/yeast/doc/yeast.md b/shared/yeast/doc/yeast.md index fa917517f655..9916aad1bebb 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -272,6 +272,12 @@ let synthetic = tree_at!(ctx, source, (synthetic_node child: (nested value: {chi 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. diff --git a/shared/yeast/src/lib.rs b/shared/yeast/src/lib.rs index a71b604411c5..45f57fb70c94 100644 --- a/shared/yeast/src/lib.rs +++ b/shared/yeast/src/lib.rs @@ -597,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) @@ -1100,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 @@ -1114,6 +1134,7 @@ impl Rule { query, guard: None, transform, + ignored_location_fields: Vec::new(), repeated: false, } } @@ -1125,6 +1146,7 @@ impl Rule { query, guard: Some(guard), transform, + ignored_location_fields: Vec::new(), repeated: false, } } @@ -1138,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. @@ -1176,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) } } @@ -1465,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 @@ -1474,6 +1501,7 @@ impl Default for DesugaringConfig { Self { phases: Vec::new(), output_node_types_yaml: None, + ignored_location_fields: Vec::new(), } } } @@ -1490,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 b9aade99ce74..0daa631d24e0 100644 --- a/shared/yeast/src/range.rs +++ b/shared/yeast/src/range.rs @@ -69,4 +69,31 @@ impl Range { ..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 a7e24a45366f..b0c707ea8b26 100644 --- a/shared/yeast/tests/test.rs +++ b/shared/yeast/tests/test.rs @@ -1787,6 +1787,30 @@ fn test_returned_capture_keeps_its_location() { 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] diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index 4bed1b2ce53c..b4136b1ad628 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -480,13 +480,13 @@ fn translation_rules() -> Vec> { rule!( (enumCaseElement name: @name - parameterClause: (enumCaseParameterClause parameters: _* @params)) @@element + parameterClause: (enumCaseParameterClause parameters: _* @params) @@clause) => class_like_declaration { let body = tree!((block)); - let constructor = tree_at!( + let constructor = tree_spanning!( ctx, - element, + [name, clause], (constructor_declaration parameter: {params} body: {body}) ); tree!((class_like_declaration @@ -643,27 +643,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 @@ -734,14 +748,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)) @@ -863,7 +885,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 @@ -1008,7 +1036,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}) ), @@ -1170,7 +1200,9 @@ fn translation_rules() -> Vec> { } ), rule!( - (tupleTypeElement firstName: _? @@name type: @ty) + (tupleTypeElement + firstName: _? @@name + type: @ty) => argument { if ctx.in_function_type { @@ -1399,6 +1431,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/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/nested-enum-case-pattern.output b/unified/extractor/tests/corpus/swift/control-flow/nested-enum-case-pattern.output index 4a6c67739d9d..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 @@ -167,13 +167,13 @@ top_level source="⟨body⟩" 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="." member_name_node: identifier "received" source="received" argument: - argument source="⟨value⟩," + argument source="⟨value⟩" value: call_expr source="⟨callee⟩(⟨argument⟩)" callee: @@ -188,10 +188,10 @@ top_level source="⟨body⟩" body: 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" 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 a60324f47a3d..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 @@ -179,9 +179,9 @@ top_level source="⟨body⟩" value: string_literal "\"positive\"" source="\"positive\"" switch_case source="case ⟨pattern⟩:\n ⟨body⟩" pattern: - or_pattern source="⟨pattern⟩ ⟨pattern⟩" + 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" 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 6ff524b63160..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 @@ -333,9 +333,9 @@ 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" 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 889e155ae46b..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 @@ -151,13 +151,13 @@ top_level source="⟨body⟩" value: string_literal "\"yes\"" source="\"yes\"" 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⟩" 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 23df62e6a6d7..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,9 +132,9 @@ 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="[⟨type_argument⟩" + generic_type_expr source="[⟨type_argument⟩]" base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" @@ -144,9 +144,9 @@ top_level source="⟨body⟩" modifier: modifier "let" source="let" pattern: identifier "initialized" source="initialized" value: - call_expr source="⟨callee⟩](⟨argument⟩) ⟨argument⟩" + call_expr source="⟨callee⟩(⟨argument⟩) ⟨argument⟩" callee: - generic_type_expr source="[⟨type_argument⟩" + generic_type_expr source="[⟨type_argument⟩]" base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" @@ -160,7 +160,7 @@ top_level source="⟨body⟩" 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 066e65ccca00..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,9 +56,9 @@ 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="[⟨type_argument⟩" + generic_type_expr source="[⟨type_argument⟩]" base: identifier "Array" source="" type_argument: generic_type_expr source="⟨base⟩<⟨type_argument⟩>" 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-parameters-and-return-type.output b/unified/extractor/tests/corpus/swift/functions/function-with-parameters-and-return-type.output index fcac6c8c2843..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="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" + 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" 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 9b48167deb9c..9d5d1a6e5b95 100644 --- a/unified/extractor/tests/corpus/swift/functions/variadic-function.output +++ b/unified/extractor/tests/corpus/swift/functions/variadic-function.output @@ -90,13 +90,13 @@ top_level source="⟨body⟩" 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 821aec63a98c..fab3a3eb38ed 100644 --- a/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output +++ b/unified/extractor/tests/corpus/swift/literals/string-with-interpolation.output @@ -274,10 +274,10 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="\\(⟨argument⟩ ⟨argument⟩)" + 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="\\(⟨argument⟩ ⟨argument⟩ ⟨argument⟩)" + 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" @@ -308,10 +308,10 @@ top_level source="⟨body⟩" string_interpolation_expr source="\"⟨element⟩⟨element⟩\"" element: string_literal "foo " source="foo " - call_expr source="\\(⟨argument⟩ ⟨argument⟩)" + 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 92ad43c34164..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="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" + 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" 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 42f184e76b15..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="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩ ⟨parameter⟩ ⟨parameter⟩) -> ⟨return_type⟩ ⟨body⟩" + 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" 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 28953b21acc5..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="func ⟨name_node⟩(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" + 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" 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 d83a29460e61..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 @@ -152,9 +152,9 @@ top_level source="⟨body⟩" catch_clause: catch_clause source="catch ⟨pattern⟩ ⟨body⟩" pattern: - or_pattern source="⟨pattern⟩ ⟨pattern⟩" + 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/types/constructor-with-parameters.output b/unified/extractor/tests/corpus/swift/types/constructor-with-parameters.output index 9e49e134c100..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="init(⟨parameter⟩ ⟨parameter⟩) ⟨body⟩" + 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" 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 19146c2fb731..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,19 +44,19 @@ 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⟩," + variable_declaration source="⟨pattern⟩" modifier: modifier "enum_case" source="" pattern: identifier "clubs" source="clubs" - variable_declaration source="⟨pattern⟩," + variable_declaration source="⟨pattern⟩" modifier: modifier "chained_declaration" source="" modifier "enum_case" source="" pattern: identifier "diamonds" source="diamonds" - variable_declaration source="⟨pattern⟩," + variable_declaration source="⟨pattern⟩" modifier: modifier "chained_declaration" source="" modifier "enum_case" source="" 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/variables/multiple-bindings-on-one-line.output b/unified/extractor/tests/corpus/swift/variables/multiple-bindings-on-one-line.output index 07797954fc8d..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,7 +40,7 @@ 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" 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/ql/test/library-tests/controlflow/basicblock-slices.expected b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected index 97a1d1a279f0..1140c1ca1892 100644 --- a/unified/ql/test/library-tests/controlflow/basicblock-slices.expected +++ b/unified/ql/test/library-tests/controlflow/basicblock-slices.expected @@ -6,7 +6,7 @@ | 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' | +| 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' | | 15 | cfg.swift:15:1:17:1 | FunctionDeclaration | 'FunctionDeclaration' | @@ -315,7 +315,7 @@ | 380 | cfg.swift:380:1:384:1 | FunctionDeclaration | 'FunctionDeclaration' | | 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' | From f09c28616e8ae5dd00ae1e907b17888be102f708 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 18 Sep 2026 14:26:02 +0000 Subject: [PATCH 08/10] yeast: Annotate children outside parent source ranges In some cases (I'm looking at you, access_declaration) we link up things like the modifier of an accessor to a node that lives _outside_ of the declaration itself. Previously this was treated as an error (and the "fix" was to extend the source ranges), but this lead to some weird source skeletons in the output. Instead, we now allow the source of a node to be anywhere (within reason -- it has to be inside the file, and properly UTF-8 aligned), and simply add a trailing ` (external)` to the source annotation. Thus, the fields containing these values do not appear in the source skeleton for the node in question. --- shared/yeast/doc/yeast.md | 11 +++++++ shared/yeast/src/dump.rs | 63 +++++++++++++++++++++++++++++---------- 2 files changed, 59 insertions(+), 15 deletions(-) diff --git a/shared/yeast/doc/yeast.md b/shared/yeast/doc/yeast.md index 9916aad1bebb..f9f0100f2fa6 100644 --- a/shared/yeast/doc/yeast.md +++ b/shared/yeast/doc/yeast.md @@ -292,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/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}" + ); } } From 49caaa787af58edd8455f966b48138fdd15f8566 Mon Sep 17 00:00:00 2001 From: Taus Date: Fri, 18 Sep 2026 14:26:23 +0000 Subject: [PATCH 09/10] Unified: Give accessors their own source ranges Keep inherited property metadata at its original source while limiting each accessor declaration to its own keyword and optional body. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../extractor/src/languages/swift/swift.rs | 4 ++- ...er-does-not-leak-into-accessor-body.output | 10 +++---- .../property-with-getter-and-setter.output | 18 ++++++------- ...nd-read-write-property-requirements.output | 26 +++++++++---------- ...y-with-willset-and-didset-observers.output | 12 ++++----- 5 files changed, 36 insertions(+), 34 deletions(-) diff --git a/unified/extractor/src/languages/swift/swift.rs b/unified/extractor/src/languages/swift/swift.rs index b4136b1ad628..76d51c65fa55 100644 --- a/unified/extractor/src/languages/swift/swift.rs +++ b/unified/extractor/src/languages/swift/swift.rs @@ -405,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} 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 17004c0c8959..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,15 +92,15 @@ sourceFile --- -top_level source="⟨body⟩\n}" +top_level source="var p: Int {\n ⟨body⟩\n}" body: 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: 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 94d514f11cdb..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⟩ ⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" + modifier "var" source="var" (external) modifier "chained_declaration" source="" - name_node: identifier "v" source="v" + 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-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 0886939c1d94..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⟩" + type: identifier "String" source="String" (external) + accessor_declaration source="⟨accessor_kind⟩" modifier: modifier "chained_declaration" source="" - name_node: identifier "bar" source="bar" + 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/variables/property-with-willset-and-didset-observers.output b/unified/extractor/tests/corpus/swift/variables/property-with-willset-and-didset-observers.output index 4670fd83b1d5..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⟩ ⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" + modifier "var" source="var" (external) modifier "chained_declaration" source="" - name_node: identifier "x" source="x" + 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⟩ ⟨body⟩" + accessor_declaration source="⟨accessor_kind⟩ ⟨body⟩" modifier: - modifier "var" source="var" + modifier "var" source="var" (external) modifier "chained_declaration" source="" - name_node: identifier "x" source="x" + name_node: identifier "x" source="x" (external) accessor_kind: accessor_kind "didSet" source="didSet" body: block source="{ ⟨stmt⟩ }" From 0cde5040a692b055663b1c63100a9a1607ae2a76 Mon Sep 17 00:00:00 2001 From: Taus Date: Thu, 17 Sep 2026 15:30:11 +0000 Subject: [PATCH 10/10] Unified: Update location test expectations Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../library-tests/BasicTest/test.expected | 14 +- .../controlflow/basicblock-slices.expected | 168 +++++++++--------- .../library-tests/controlflow/cfg.expected | 19 +- .../test/library-tests/controlflow/cfg.swift | 18 +- .../test/library-tests/dataflow/test.expected | 24 +-- 5 files changed, 120 insertions(+), 123 deletions(-) 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 1140c1ca1892..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' | +| 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: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(...) |