==========================================
Ellipsis
==========================================

...

---

(parser_output
  (semgrep_ellipsis))

==========================================
Top-level statements
==========================================

foo();
...
bar();

---

(parser_output
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list)))
  (semgrep_ellipsis)
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list))))

==========================================
Top-level public constructor
==========================================

public Foo(...) { }

---

(parser_output
  (constructor_declaration
    (modifiers
      (modifier
        (public)))
    (identifier)
    (formal_parameters
      (formal_parameter
        (semgrep_ellipsis)))
    (constructor_body)))

==========================================
Top-level bare constructor
==========================================

Foo(...) { }

---

(parser_output
  (constructor_declaration
    (identifier)
    (formal_parameters
      (formal_parameter
        (semgrep_ellipsis)))
    (constructor_body)))

==========================================
Class body ellipsis
==========================================

class $X {
  ...
  f() {}
}

---

(parser_output
  (class_declaration
    (identifier
      (semgrep_metavar))
    (class_body
      (semgrep_ellipsis)
      (constructor_declaration
        (identifier)
        (formal_parameters)
        (constructor_body)))))

==========================================
Class interface body ellipsis
==========================================

interface $INTERFACE extends Remote {
  ...
  $RETURNTYPE $METHOD(Object $PARAM);
}

---

(parser_output
  (interface_declaration
    (identifier
      (semgrep_metavar))
    (extends_interfaces
      (type_list
        (type_identifier)))
    (interface_body
      (semgrep_ellipsis)
      (method_declaration
        (type_identifier
          (semgrep_metavar))
        (identifier
          (semgrep_metavar))
        (formal_parameters
          (formal_parameter
            (type_identifier)
            (identifier
              (semgrep_metavar))))))))

==========================================
Constructor body ellipsis
==========================================

public Foo(...) {
  ...
}

---

(parser_output
  (constructor_declaration
    (modifiers
      (modifier
        (public)))
    (identifier)
    (formal_parameters
      (formal_parameter
        (semgrep_ellipsis)))
    (constructor_body
      (semgrep_ellipsis))))

==========================================
Ellipsis args
==========================================

foo(..., 5)

---

(parser_output
  (method_invocation
    (identifier)
    (argument_list
      (semgrep_ellipsis)
      (int))))

==========================================
Metavariable in 'if'
==========================================

if ($COND) {
  ...
}

---

(parser_output
  (if_statement
    (parenthesized_expression
      (identifier
        (semgrep_metavar)))
    (block
      (semgrep_ellipsis))))

==========================================
Metavariable
==========================================

class $X {
  $X() { }
  void $ASDF() {
    int $QWERTY = $UIOP;
  }
}

---

(parser_output
  (class_declaration
    (identifier
      (semgrep_metavar))
    (class_body
      (constructor_declaration
        (identifier
          (semgrep_metavar))
        (formal_parameters)
        (constructor_body))
      (method_declaration
        (void_type)
        (identifier
          (semgrep_metavar))
        (formal_parameters)
        (block
          (local_variable_declaration
            (type_identifier)
            (variable_declarator
              (identifier
                (semgrep_metavar))
              (assignment_operator)
              (identifier
                (semgrep_metavar)))))))))

==========================================
Metavariable statement
==========================================

$X;

---

(parser_output
  (expression_statement
    (identifier
      (semgrep_metavar))))

==========================================
Top-level lone annotation
==========================================

@Annotation

---

(parser_output
  (annotation
    (identifier)))

==========================================
Top-level lone annotation with args
==========================================

@Annotation(param1=false, param2='hello')

---

(parser_output
  (annotation
    (identifier)
    (annotation_argument_list
      (annotation_key_value
        (identifier)
        (assignment_operator)
        (boolean))
      (annotation_key_value
        (identifier)
        (assignment_operator)
        (string_literal)))))

==========================================
Class header
==========================================

GlObAl without sharing cLaSs $A extends $SUPER implements $I1, $I2

---

(parser_output
  (modifiers
    (modifier
      (global))
    (modifier
      (without_sharing)))
  (identifier
    (semgrep_metavar))
  (superclass
    (type_identifier
      (semgrep_metavar)))
  (interfaces
    (type_list
      (type_identifier
        (semgrep_metavar))
      (type_identifier
        (semgrep_metavar)))))

==========================================
Method header
==========================================

public override void printName()

---

(parser_output
  (modifiers
    (modifier
      (public))
    (modifier
      (override)))
  (void_type)
  (identifier)
  (formal_parameters))

==========================================
'if' right-associativity
==========================================

if (true)
  if (true)
    x;
  else
    x;

---

(parser_output
  (if_statement
    (parenthesized_expression
      (boolean))
    (if_statement
      (parenthesized_expression
        (boolean))
      (expression_statement
        (identifier))
      (expression_statement
        (identifier)))))

==========================================
Partial 'if'
==========================================

iF (true)

---

(parser_output
  (partial_if
    (parenthesized_expression
      (boolean))))

==========================================
Partial 'try'
==========================================

tRy {
  insert a;
}

---

(parser_output
  (partial_try
    (block
      (expression_statement
        (dml_expression
          (dml_type
            (insert))
          (identifier))))))

==========================================
Lone 'catch'
==========================================

caTch(DmlException e) {}

---

(parser_output
  (partial_catch
    (catch_clause
      (formal_parameter
        (type_identifier)
        (identifier))
      (block))))

==========================================
Lone 'finally'
==========================================

finallY {}

---

(parser_output
  (partial_finally
    (finally_clause
      (block))))

==========================================
Ellipsis for type parameters
==========================================

class Foo<...> {}
class Foo<...,T1,...> {}

---

(parser_output
  (class_declaration
    (identifier)
    (type_parameters
      (type_parameter
        (semgrep_ellipsis)))
    (class_body))
  (class_declaration
    (identifier)
    (type_parameters
      (type_parameter
        (semgrep_ellipsis))
      (type_parameter
        (type_identifier))
      (type_parameter
        (semgrep_ellipsis)))
    (class_body)))

==========================================
'for' ellipsis
==========================================

for(...) { ... }

---

(parser_output
  (for_statement
    (semgrep_ellipsis)
    (block
      (semgrep_ellipsis))))

==========================================
'catch' ellipsis
==========================================

try {}
catch (...) {}

---

(parser_output
  (try_statement
    (block)
    (catch_clause
      (formal_parameter
        (semgrep_ellipsis))
      (block))))

==========================================
Metavariable ellipsis in parameters
==========================================

public class ClassA {
  public void func($...PARAMS) {
    obj.writeObj('object');
  }
}

---

(parser_output
  (class_declaration
    (modifiers
      (modifier
        (public)))
    (identifier)
    (class_body
      (method_declaration
        (modifiers
          (modifier
            (public)))
        (void_type)
        (identifier)
        (formal_parameters
          (formal_parameter
            (semgrep_metavar_ellipsis)))
        (block
          (expression_statement
            (method_invocation
              (identifier)
              (identifier)
              (argument_list
                (string_literal)))))))))

==========================================
Metavariable ellipsis in arguments
==========================================

obj.writeObj(foo, $...X)

---

(parser_output
  (method_invocation
    (identifier)
    (identifier)
    (argument_list
      (identifier)
      (semgrep_metavar_ellipsis))))

==========================================
Deep expressions
==========================================

if (<... $X == true ...>) {
  ...
}

foo(<... 42 ...>);

---

(parser_output
  (if_statement
    (parenthesized_expression
      (semgrep_deep_expression
        (binary_expression
          (identifier
            (semgrep_metavar))
          (boolean))))
    (block
      (semgrep_ellipsis)))
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list
        (semgrep_deep_expression
          (int))))))

==========================================
SELECT ellipsis
==========================================

[ SELECT a, ... FROM x ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier))
        (semgrep_ellipsis))
      (from_clause
        (storage_identifier
          (identifier))))))

==========================================
SELECT metavariable
==========================================

[ SELECT $A, $B FROM x ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier
            (semgrep_metavar)))
        (field_identifier
          (identifier
            (semgrep_metavar))))
      (from_clause
        (storage_identifier
          (identifier))))))

==========================================
FROM ellipsis
==========================================

[ SELECT a FROM x, ..., y ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier)))
      (from_clause
        (storage_identifier
          (identifier))
        (storage_identifier
          (semgrep_ellipsis))
        (storage_identifier
          (identifier))))))

==========================================
FROM metavariable
==========================================

[ SELECT x FROM $TBL ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier)))
      (from_clause
        (storage_identifier
          (identifier
            (semgrep_metavar)))))))

==========================================
WHERE metavariable
==========================================

[ SELECT a FROM b WHERE $COND AND $X < 42 ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier)))
      (from_clause
        (storage_identifier
          (identifier)))
      (where_clause
        (and_expression
          (semgrep_metavar)
          (comparison_expression
            (field_identifier
              (identifier
                (semgrep_metavar)))
            (value_comparison_operator)
            (int)))))))

==========================================
Metavariables for Apex expressions embedded in SOQL
==========================================

[ SELECT Id FROM Account WHERE Name = :$X ]

---

(parser_output
  (query_expression
    (soql_query_body
      (select_clause
        (field_identifier
          (identifier)))
      (from_clause
        (storage_identifier
          (identifier)))
      (where_clause
        (comparison_expression
          (field_identifier
            (identifier))
          (value_comparison_operator)
          (bound_apex_expression
            (identifier
              (semgrep_metavar))))))))

==========================================
Top-level method declaration
==========================================

$TYPE $FUNC() {
}

---

(parser_output
  (method_declaration
    (type_identifier
      (semgrep_metavar))
    (identifier
      (semgrep_metavar))
    (formal_parameters)
    (block)))

==========================================
Local variable declaration
==========================================

int x = 42;

---

(parser_output
  (local_variable_declaration
    (type_identifier)
    (variable_declarator
      (identifier)
      (assignment_operator)
      (int))))

==========================================
Enum ellipsis
==========================================

enum E { ... }

---

(parser_output
  (enum_declaration
    (identifier)
    (enum_body
      (enum_constant
        (semgrep_ellipsis)))))

==========================================
Annotation argument ellipsis
==========================================

@SomeAnnot(..., a=b)

---

(parser_output
  (annotation
    (identifier)
    (annotation_argument_list
      (annotation_key_value
        (semgrep_ellipsis))
      (annotation_key_value
        (identifier)
        (assignment_operator)
        (identifier)))))

==========================================
Switch body ellipsis
==========================================

switch on x {
  ...
  when 42 {
    ...
  }
  ...
}

---

(parser_output
  (switch_expression
    (identifier)
    (switch_block
      (switch_rule
        (semgrep_ellipsis))
      (switch_rule
        (switch_label
          (int))
        (block
          (semgrep_ellipsis)))
      (switch_rule
        (semgrep_ellipsis)))))

==========================================
Package version patterns and compositions
==========================================

Package.$MEMBER.Request;
Package.Version.$VALUE;
$PACKAGE.Version.Request;
Package.$MEMBER.$VALUE;
foo(Package.Version.$VALUE, <... Package.$MEMBER.Request ...>, $...ARGS);
Package.Version.Request;
Package.Version.1.0;
foo(Package.Version.Request, Package.Version.10.20);

---

(parser_output
  (expression_statement
    (field_access
      (field_access
        (identifier)
        (identifier
          (semgrep_metavar)))
      (identifier)))
  (expression_statement
    (field_access
      (field_access
        (identifier)
        (identifier))
      (identifier
        (semgrep_metavar))))
  (expression_statement
    (field_access
      (field_access
        (identifier
          (semgrep_metavar))
        (identifier))
      (identifier)))
  (expression_statement
    (field_access
      (field_access
        (identifier)
        (identifier
          (semgrep_metavar)))
      (identifier
        (semgrep_metavar))))
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list
        (field_access
          (field_access
            (identifier)
            (identifier))
          (identifier
            (semgrep_metavar)))
        (semgrep_deep_expression
          (field_access
            (field_access
              (identifier)
              (identifier
                (semgrep_metavar)))
            (identifier)))
        (semgrep_metavar_ellipsis))))
  (expression_statement
    (version_expression))
  (expression_statement
    (version_expression
      (version_number)))
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list
        (version_expression)
        (version_expression
          (version_number))))))

==========================================
Do statement pattern bodies
==========================================

do ... while ($COND);
do $BODY; while ($COND);
do { ... } while (<... $COND ...>);
do { foo(); } while (true);

---

(parser_output
  (do_statement
    (semgrep_ellipsis)
    (parenthesized_expression
      (identifier
        (semgrep_metavar))))
  (do_statement
    (expression_statement
      (identifier
        (semgrep_metavar)))
    (parenthesized_expression
      (identifier
        (semgrep_metavar))))
  (do_statement
    (block
      (semgrep_ellipsis))
    (parenthesized_expression
      (semgrep_deep_expression
        (identifier
          (semgrep_metavar)))))
  (do_statement
    (block
      (expression_statement
        (method_invocation
          (identifier)
          (argument_list))))
    (parenthesized_expression
      (boolean))))

==========================================
Catch and switch pattern compatibility
==========================================

try {} catch ($TYPE $EX) { ... }
try {} catch ($...PARAM) { ... }
switch on $X { when $TYPE $OBJ { ... } when $VAL, <... $OTHER ...> { ... } }

---

(parser_output
  (try_statement
    (block)
    (catch_clause
      (formal_parameter
        (type_identifier
          (semgrep_metavar))
        (identifier
          (semgrep_metavar)))
      (block
        (semgrep_ellipsis))))
  (try_statement
    (block)
    (catch_clause
      (formal_parameter
        (semgrep_metavar_ellipsis))
      (block
        (semgrep_ellipsis))))
  (switch_expression
    (identifier
      (semgrep_metavar))
    (switch_block
      (switch_rule
        (switch_label
          (when_sobject_type
            (type_identifier
              (semgrep_metavar))
            (identifier
              (semgrep_metavar))))
        (block
          (semgrep_ellipsis)))
      (switch_rule
        (switch_label
          (identifier
            (semgrep_metavar))
          (semgrep_deep_expression
            (identifier
              (semgrep_metavar))))
        (block
          (semgrep_ellipsis))))))

==========================================
Trigger event keyword boundaries
==========================================

trigger T on Account (
  before /* insert */ insert,
  before // update
  update,
  before	delete,
  after /* insert */ insert,
  after // update
  update,
  after	delete,
  after /* undelete */ undelete
) {}

---

(parser_output
  (trigger_declaration
    (identifier)
    (identifier)
    (trigger_event
      (before_insert
        (block_comment)))
    (trigger_event
      (before_update
        (line_comment)))
    (trigger_event
      (before_delete))
    (trigger_event
      (after_insert
        (block_comment)))
    (trigger_event
      (after_update
        (line_comment)))
    (trigger_event
      (after_delete))
    (trigger_event
      (after_undelete
        (block_comment)))
    (trigger_body
      (block))))

==========================================
Sharing keyword boundaries
==========================================

with /* c */ sharing class C {}
without // c
sharing class D {}
inherited	sharing class E {}

---

(parser_output
  (class_declaration
    (modifiers
      (modifier
        (with_sharing
          (block_comment))))
    (identifier)
    (class_body))
  (class_declaration
    (modifiers
      (modifier
        (without_sharing
          (line_comment))))
    (identifier)
    (class_body))
  (class_declaration
    (modifiers
      (modifier
        (inherited_sharing)))
    (identifier)
    (class_body)))

==========================================
Safe navigation boundaries and patterns
==========================================

$OBJ?.$FIELD;
$OBJ ? /* c */ . $FIELD;
$OBJ ?
. $METHOD(..., $...ARGS, <... $X ...>);

---

(parser_output
  (expression_statement
    (field_access
      (identifier
        (semgrep_metavar))
      (safe_navigation_operator)
      (identifier
        (semgrep_metavar))))
  (expression_statement
    (field_access
      (identifier
        (semgrep_metavar))
      (safe_navigation_operator
        (block_comment))
      (identifier
        (semgrep_metavar))))
  (expression_statement
    (method_invocation
      (identifier
        (semgrep_metavar))
      (safe_navigation_operator)
      (identifier
        (semgrep_metavar))
      (argument_list
        (semgrep_ellipsis)
        (semgrep_metavar_ellipsis)
        (semgrep_deep_expression
          (identifier
            (semgrep_metavar)))))))

==========================================
Embedded query keyword boundaries
==========================================

[SELECT Id FROM Account USING /* c */ SCOPE Everything WHERE Id NOT /* c */ IN :$IDS GROUP /* c */ BY Id HAVING $COND ORDER /* c */ BY Id NULLS /* c */ FIRST, Name NULLS // c
LAST ALL /* c */ ROWS];
[SELECT Id FROM Knowledge__kav WITH DATA /* c */ CATEGORY Geography__c AT usa__c];

---

(parser_output
  (expression_statement
    (query_expression
      (soql_query_body
        (select_clause
          (field_identifier
            (identifier)))
        (from_clause
          (storage_identifier
            (identifier)))
        (using_clause
          (block_comment)
          (using_scope_type))
        (where_clause
          (comparison_expression
            (field_identifier
              (identifier))
            (set_comparison_operator
              (block_comment))
            (bound_apex_expression
              (identifier
                (semgrep_metavar)))))
        (group_by_clause
          (block_comment)
          (field_identifier
            (identifier))
          (having_clause
            (semgrep_metavar)))
        (order_by_clause
          (block_comment)
          (order_expression
            (field_identifier
              (identifier))
            (order_null_direction
              (block_comment)))
          (order_expression
            (field_identifier
              (identifier))
            (order_null_direction
              (line_comment))))
        (all_rows_clause
          (block_comment)))))
  (expression_statement
    (query_expression
      (soql_query_body
        (select_clause
          (field_identifier
            (identifier)))
        (from_clause
          (storage_identifier
            (identifier)))
        (with_clause
          (with_type
            (with_data_cat_expression
              (block_comment)
              (with_data_cat_filter
                (identifier)
                (with_data_cat_filter_type)
                (identifier)))))))))

==========================================
Annotation native and pattern argument lists
==========================================

@Annotation(a=$A b=$B)

---

(parser_output
  (annotation
    (identifier)
    (annotation_argument_list
      (annotation_key_value
        (identifier)
        (assignment_operator)
        (identifier
          (semgrep_metavar)))
      (annotation_key_value
        (identifier)
        (assignment_operator)
        (identifier
          (semgrep_metavar))))))

==========================================
Empty annotation arguments
==========================================

@Annotation()

---

(parser_output
  (annotation
    (identifier)
    (annotation_argument_list)))

==========================================
Ternary versus separated safe navigation
==========================================

$COND ? $YES : $NO;

---

(parser_output
  (expression_statement
    (ternary_expression
      (identifier
        (semgrep_metavar))
      (identifier
        (semgrep_metavar))
      (identifier
        (semgrep_metavar)))))

==========================================
Package prefix field and method patterns
==========================================

Package.$X;
Package.Version;
foo(Package.$X, <... Package.Version ...>);
Package.$M(...);

---

(parser_output
  (expression_statement
    (field_access
      (identifier)
      (identifier
        (semgrep_metavar))))
  (expression_statement
    (field_access
      (identifier)
      (identifier)))
  (expression_statement
    (method_invocation
      (identifier)
      (argument_list
        (field_access
          (identifier)
          (identifier
            (semgrep_metavar)))
        (semgrep_deep_expression
          (field_access
            (identifier)
            (identifier))))))
  (expression_statement
    (method_invocation
      (identifier)
      (identifier
        (semgrep_metavar))
      (argument_list
        (semgrep_ellipsis)))))
