Skip to content

Commit 2ef06c9

Browse files
authored
Merge pull request #22080 from asgerf/unified/commonast-followups
unified: Add or_pattern and fix 'if case let' translation
2 parents da3d0cf + 1842382 commit 2ef06c9

5 files changed

Lines changed: 152 additions & 21 deletions

File tree

unified/extractor/ast_types.yml

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ supertypes:
4242
- name_pattern
4343
- tuple_pattern
4444
- constructor_pattern
45+
- or_pattern
4546
- ignore_pattern
4647
- expr_equality_pattern
4748
- bulk_importing_pattern
@@ -359,12 +360,12 @@ named:
359360
case*: switch_case
360361

361362
# A single `case ...:` (or `default:`) entry in a switch.
362-
# An entry with multiple `case p1, p2:` patterns has multiple `pattern`s.
363-
# A `default:` entry has no patterns.
363+
# An entry with multiple `case p1, p2:` patterns uses an `or_pattern`.
364+
# A `default:` entry has no pattern.
364365
# An optional `guard` corresponds to a `where`-clause on the case.
365366
switch_case:
366367
modifier*: modifier
367-
pattern*: pattern
368+
pattern?: pattern
368369
guard?: expr
369370
body: block
370371

@@ -421,6 +422,11 @@ named:
421422
constructor: expr_or_type
422423
element*: pattern_element
423424

425+
# A disjunction pattern that matches if any of its sub-patterns match.
426+
or_pattern:
427+
modifier*: modifier
428+
pattern*: pattern
429+
424430
# A pattern with an optional associated name.
425431
pattern_element:
426432
modifier*: modifier

unified/extractor/src/languages/swift/swift.rs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -652,25 +652,34 @@ fn translation_rules() -> Vec<Rule<SwiftContext>> {
652652
=>
653653
(switch_expr value: {val} case: {..cases})
654654
),
655-
// Switch entry with patterns and body
655+
// Switch entry with multiple patterns and body
656656
rule!(
657-
(switch_entry pattern: (switch_pattern pattern: @pats)* statement: _* @body)
657+
(switch_entry
658+
pattern: (switch_pattern pattern: @first)
659+
pattern: (switch_pattern pattern: @rest)+
660+
statement: _* @body)
658661
=>
659-
(switch_case pattern: {..pats} body: (block stmt: {..body}))
662+
(switch_case pattern: (or_pattern pattern: {first} pattern: {..rest}) body: (block stmt: {..body}))
663+
),
664+
// Switch entry with exactly one pattern and body
665+
rule!(
666+
(switch_entry pattern: (switch_pattern pattern: @pat) statement: _* @body)
667+
=>
668+
(switch_case pattern: {pat} body: (block stmt: {..body}))
660669
),
661670
// Switch entry: default case (no patterns)
662671
rule!(
663672
(switch_entry default: (default_keyword) statement: _* @body)
664673
=>
665674
(switch_case body: (block stmt: {..body}))
666675
),
667-
// if case let x = expr — the pattern is taken as-is (no Optional wrapping)
676+
// if case PATTERN = expr — preserve the pattern directly (no Optional wrapping)
668677
rule!(
669-
(if_let_binding "case" (value_binding_pattern) bound_identifier: @name _ @val)
678+
(if_let_binding "case" pattern: @pat value: @val)
670679
=>
671680
(pattern_guard_expr
672681
value: {val}
673-
pattern: (name_pattern identifier: (identifier #{name})))
682+
pattern: {pat})
674683
),
675684
rule!(
676685
(if_let_binding

unified/extractor/tests/corpus/swift/control-flow.txt

Lines changed: 83 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -573,10 +573,12 @@ top_level
573573
name_expr
574574
identifier: identifier "print"
575575
pattern:
576-
expr_equality_pattern
577-
expr: int_literal "2"
578-
expr_equality_pattern
579-
expr: int_literal "3"
576+
or_pattern
577+
pattern:
578+
expr_equality_pattern
579+
expr: int_literal "2"
580+
expr_equality_pattern
581+
expr: int_literal "3"
580582
switch_case
581583
body:
582584
block
@@ -592,6 +594,83 @@ top_level
592594
name_expr
593595
identifier: identifier "x"
594596

597+
===
598+
If-case-let with shadowing in condition value
599+
===
600+
601+
if case let x = x + 10 {
602+
print(x)
603+
}
604+
605+
---
606+
607+
source_file
608+
statement:
609+
if_statement
610+
body:
611+
block
612+
statement:
613+
call_expression
614+
function: simple_identifier "print"
615+
suffix:
616+
call_suffix
617+
arguments:
618+
value_arguments
619+
argument:
620+
value_argument
621+
value: simple_identifier "x"
622+
condition:
623+
if_condition
624+
kind:
625+
if_let_binding
626+
pattern:
627+
pattern
628+
kind:
629+
binding_pattern
630+
binding:
631+
value_binding_pattern
632+
mutability: let
633+
pattern:
634+
pattern
635+
bound_identifier: simple_identifier "x"
636+
value:
637+
additive_expression
638+
lhs: simple_identifier "x"
639+
op: +
640+
rhs: integer_literal "10"
641+
642+
---
643+
644+
top_level
645+
body:
646+
block
647+
stmt:
648+
if_expr
649+
condition:
650+
pattern_guard_expr
651+
pattern:
652+
name_pattern
653+
identifier: identifier "x"
654+
value:
655+
binary_expr
656+
operator: infix_operator "+"
657+
left:
658+
name_expr
659+
identifier: identifier "x"
660+
right: int_literal "10"
661+
then:
662+
block
663+
stmt:
664+
call_expr
665+
argument:
666+
argument
667+
value:
668+
name_expr
669+
identifier: identifier "x"
670+
callee:
671+
name_expr
672+
identifier: identifier "print"
673+
595674
===
596675
Switch with binding pattern
597676
===

unified/ql/lib/codeql/unified/Ast.qll

Lines changed: 24 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -978,6 +978,23 @@ module Unified {
978978
}
979979
}
980980

981+
/** A class representing `or_pattern` nodes. */
982+
class OrPattern extends @unified_or_pattern, AstNode {
983+
/** Gets the name of the primary QL class for this element. */
984+
final override string getAPrimaryQlClass() { result = "OrPattern" }
985+
986+
/** Gets the node corresponding to the field `modifier`. */
987+
final Modifier getModifier(int i) { unified_or_pattern_modifier(this, i, result) }
988+
989+
/** Gets the node corresponding to the field `pattern`. */
990+
final Pattern getPattern(int i) { unified_or_pattern_pattern(this, i, result) }
991+
992+
/** Gets a field or child node of this node. */
993+
final override AstNode getAFieldOrChild() {
994+
unified_or_pattern_modifier(this, _, result) or unified_or_pattern_pattern(this, _, result)
995+
}
996+
}
997+
981998
/** A class representing `parameter` nodes. */
982999
class Parameter extends @unified_parameter, AstNode {
9831000
/** Gets the name of the primary QL class for this element. */
@@ -1109,14 +1126,14 @@ module Unified {
11091126
final Modifier getModifier(int i) { unified_switch_case_modifier(this, i, result) }
11101127

11111128
/** Gets the node corresponding to the field `pattern`. */
1112-
final Pattern getPattern(int i) { unified_switch_case_pattern(this, i, result) }
1129+
final Pattern getPattern() { unified_switch_case_pattern(this, result) }
11131130

11141131
/** Gets a field or child node of this node. */
11151132
final override AstNode getAFieldOrChild() {
11161133
unified_switch_case_def(this, result) or
11171134
unified_switch_case_guard(this, result) or
11181135
unified_switch_case_modifier(this, _, result) or
1119-
unified_switch_case_pattern(this, _, result)
1136+
unified_switch_case_pattern(this, result)
11201137
}
11211138
}
11221139

@@ -1654,6 +1671,10 @@ module Unified {
16541671
i = -1 and
16551672
name = "getPrecedence"
16561673
or
1674+
result = node.(OrPattern).getModifier(i) and name = "getModifier"
1675+
or
1676+
result = node.(OrPattern).getPattern(i) and name = "getPattern"
1677+
or
16571678
result = node.(Parameter).getDefault() and i = -1 and name = "getDefault"
16581679
or
16591680
result = node.(Parameter).getExternalName() and i = -1 and name = "getExternalName"
@@ -1682,7 +1703,7 @@ module Unified {
16821703
or
16831704
result = node.(SwitchCase).getModifier(i) and name = "getModifier"
16841705
or
1685-
result = node.(SwitchCase).getPattern(i) and name = "getPattern"
1706+
result = node.(SwitchCase).getPattern() and i = -1 and name = "getPattern"
16861707
or
16871708
result = node.(SwitchExpr).getCase(i) and name = "getCase"
16881709
or

unified/ql/lib/unified.dbscheme

Lines changed: 21 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -716,6 +716,24 @@ unified_operator_syntax_declaration_def(
716716
int name: @unified_token_identifier ref
717717
);
718718

719+
#keyset[unified_or_pattern, index]
720+
unified_or_pattern_modifier(
721+
int unified_or_pattern: @unified_or_pattern ref,
722+
int index: int ref,
723+
unique int modifier: @unified_token_modifier ref
724+
);
725+
726+
#keyset[unified_or_pattern, index]
727+
unified_or_pattern_pattern(
728+
int unified_or_pattern: @unified_or_pattern ref,
729+
int index: int ref,
730+
unique int pattern: @unified_pattern ref
731+
);
732+
733+
unified_or_pattern_def(
734+
unique int id: @unified_or_pattern
735+
);
736+
719737
unified_parameter_default(
720738
unique int unified_parameter: @unified_parameter ref,
721739
unique int default: @unified_expr ref
@@ -747,7 +765,7 @@ unified_parameter_def(
747765
unique int id: @unified_parameter
748766
);
749767

750-
@unified_pattern = @unified_bulk_importing_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern
768+
@unified_pattern = @unified_bulk_importing_pattern | @unified_constructor_pattern | @unified_expr_equality_pattern | @unified_name_pattern | @unified_or_pattern | @unified_token_ignore_pattern | @unified_token_unsupported_node | @unified_tuple_pattern
751769

752770
unified_pattern_element_key(
753771
unique int unified_pattern_element: @unified_pattern_element ref,
@@ -795,10 +813,8 @@ unified_switch_case_modifier(
795813
unique int modifier: @unified_token_modifier ref
796814
);
797815

798-
#keyset[unified_switch_case, index]
799816
unified_switch_case_pattern(
800-
int unified_switch_case: @unified_switch_case ref,
801-
int index: int ref,
817+
unique int unified_switch_case: @unified_switch_case ref,
802818
unique int pattern: @unified_pattern ref
803819
);
804820

@@ -1056,7 +1072,7 @@ unified_trivia_tokeninfo(
10561072
string value: string ref
10571073
);
10581074

1059-
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_variable_declaration | @unified_while_stmt
1075+
@unified_ast_node = @unified_accessor_declaration | @unified_argument | @unified_array_literal | @unified_assign_expr | @unified_associated_type_declaration | @unified_base_type | @unified_binary_expr | @unified_block | @unified_bound_type_constraint | @unified_break_expr | @unified_bulk_importing_pattern | @unified_call_expr | @unified_catch_clause | @unified_class_like_declaration | @unified_compound_assign_expr | @unified_constructor_declaration | @unified_constructor_pattern | @unified_continue_expr | @unified_destructor_declaration | @unified_do_while_stmt | @unified_equality_type_constraint | @unified_expr_equality_pattern | @unified_for_each_stmt | @unified_function_declaration | @unified_function_expr | @unified_function_type_expr | @unified_generic_type_expr | @unified_guard_if_stmt | @unified_if_expr | @unified_import_declaration | @unified_initializer_declaration | @unified_key_value_pair | @unified_labeled_stmt | @unified_map_literal | @unified_member_access_expr | @unified_name_expr | @unified_name_pattern | @unified_named_type_expr | @unified_operator_syntax_declaration | @unified_or_pattern | @unified_parameter | @unified_pattern_element | @unified_pattern_guard_expr | @unified_return_expr | @unified_switch_case | @unified_switch_expr | @unified_throw_expr | @unified_token | @unified_top_level | @unified_trivia_token | @unified_try_expr | @unified_tuple_expr | @unified_tuple_pattern | @unified_tuple_type_element | @unified_tuple_type_expr | @unified_type_alias_declaration | @unified_type_cast_expr | @unified_type_parameter | @unified_type_test_expr | @unified_type_test_pattern | @unified_unary_expr | @unified_variable_declaration | @unified_while_stmt
10601076

10611077
unified_ast_node_location(
10621078
unique int node: @unified_ast_node ref,

0 commit comments

Comments
 (0)