================================================================================
Basic record declaration
================================================================================

record F {
  int Age { get; init; }
}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    body: (declaration_list
      (property_declaration
        type: (predefined_type)
        name: (identifier)
        accessors: (accessor_list
          (accessor_declaration)
          (accessor_declaration))))))

================================================================================
Basic record struct declaration
================================================================================

record struct F {
  int Age { get; init; }
}

--------------------------------------------------------------------------------

(compilation_unit
  (record_struct_declaration
    name: (identifier)
    body: (declaration_list
      (property_declaration
        type: (predefined_type)
        name: (identifier)
        accessors: (accessor_list
          (accessor_declaration)
          (accessor_declaration))))))

================================================================================
Record class with optional `class` specification
================================================================================

record class F {
  int Age { get; init; }
}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    body: (declaration_list
      (property_declaration
        type: (predefined_type)
        name: (identifier)
        accessors: (accessor_list
          (accessor_declaration)
          (accessor_declaration))))))

================================================================================
Record with a type parameter struct constraint
================================================================================

public record F<T> where T:struct {}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (modifier)
    name: (identifier)
    type_parameters: (type_parameter_list
      (type_parameter
        name: (identifier)))
    (type_parameter_constraints_clause
      target: (identifier)
      constraints: (type_parameter_constraint))
    body: (declaration_list)))

================================================================================
Record with a type parameter class constraint
================================================================================

public record F<T> where T:class {}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (modifier)
    name: (identifier)
    type_parameters: (type_parameter_list
      (type_parameter
        name: (identifier)))
    (type_parameter_constraints_clause
      target: (identifier)
      constraints: (type_parameter_constraint))
    body: (declaration_list)))

================================================================================
Record with type parameter new constraint
================================================================================

public record F<T> where T: new() {}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (modifier)
    name: (identifier)
    type_parameters: (type_parameter_list
      (type_parameter
        name: (identifier)))
    (type_parameter_constraints_clause
      target: (identifier)
      constraints: (type_parameter_constraint
        (constructor_constraint)))
    body: (declaration_list)))

================================================================================
Record with interface
================================================================================

public record A : ISomething { }

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (modifier)
    name: (identifier)
    bases: (base_list
      (identifier))
    body: (declaration_list)))

================================================================================
Record with multiple type parameter constraints
================================================================================

[Nice]
private record F<T1,T2> where T1 : I1, I2, new() where T2 : I2 { }

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (attribute_list
      (attribute
        name: (identifier)))
    (modifier)
    name: (identifier)
    type_parameters: (type_parameter_list
      (type_parameter
        name: (identifier))
      (type_parameter
        name: (identifier)))
    (type_parameter_constraints_clause
      target: (identifier)
      constraints: (type_parameter_constraint
        (type_constraint
          type: (identifier)))
      constraints: (type_parameter_constraint
        (type_constraint
          type: (identifier)))
      constraints: (type_parameter_constraint
        (constructor_constraint)))
    (type_parameter_constraints_clause
      target: (identifier)
      constraints: (type_parameter_constraint
        (type_constraint
          type: (identifier))))
    body: (declaration_list)))

================================================================================
Record with constructor
================================================================================

record Person(string FirstName, string LastName);

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    parameters: (parameter_list
      (parameter
        type: (predefined_type)
        name: (identifier))
      (parameter
        type: (predefined_type)
        name: (identifier)))))

================================================================================
Record inheritance with constructor overload
================================================================================

record Teacher(string FirstName, string LastName, string Subject) : Person(FirstName, LastName);

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    parameters: (parameter_list
      (parameter
        type: (predefined_type)
        name: (identifier))
      (parameter
        type: (predefined_type)
        name: (identifier))
      (parameter
        type: (predefined_type)
        name: (identifier)))
    bases: (base_list
      (primary_constructor_base_type
        type: (identifier)
        (argument_list
          (argument
            (identifier))
          (argument
            (identifier)))))))

================================================================================
Record inheritance with constructor overload and interfaces
================================================================================

record Teacher(string FirstName, string LastName, string Subject) : Person(FirstName, LastName), Ns.I1, I2;

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    parameters: (parameter_list
      (parameter
        type: (predefined_type)
        name: (identifier))
      (parameter
        type: (predefined_type)
        name: (identifier))
      (parameter
        type: (predefined_type)
        name: (identifier)))
    bases: (base_list
      (primary_constructor_base_type
        type: (identifier)
        (argument_list
          (argument
            (identifier))
          (argument
            (identifier))))
      (qualified_name
        qualifier: (identifier)
        name: (identifier))
      (identifier))))

================================================================================
Record inheritance with generic base
================================================================================

record Teacher() : Entity<Person>(), I1;

record A : System.IEquatable<A>;

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    parameters: (parameter_list)
    bases: (base_list
      (primary_constructor_base_type
        type: (generic_name
          name: (identifier)
          type_arguments: (type_argument_list
            (identifier)))
        (argument_list))
      (identifier)))
  (record_declaration
    name: (identifier)
    bases: (base_list
      (qualified_name
        qualifier: (identifier)
        name: (generic_name
          name: (identifier)
          type_arguments: (type_argument_list
            (identifier)))))))

================================================================================
Record types can end with a semicolon
================================================================================

public record Person { };

public record struct Person2 { };

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    (modifier)
    name: (identifier)
    body: (declaration_list))
  (record_struct_declaration
    (modifier)
    name: (identifier)
    body: (declaration_list)))

================================================================================
Record types can seal ToString()
================================================================================

record A {
  public sealed override string ToString(){
      return "";
  }
}

--------------------------------------------------------------------------------

(compilation_unit
  (record_declaration
    name: (identifier)
    body: (declaration_list
      (method_declaration
        (modifier)
        (modifier)
        (modifier)
        type: (predefined_type)
        name: (identifier)
        parameters: (parameter_list)
        body: (block
          (return_statement
            (string_literal)))))))

================================================================================
With expression typical basic form
================================================================================

void A() {
  var newFriend = friend with { LastName = "Edwards" };
}

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_function_statement
      type: (predefined_type)
      name: (identifier)
      parameters: (parameter_list)
      body: (block
        (local_declaration_statement
          (variable_declaration
            type: (implicit_type)
            (variable_declarator
              name: (identifier)
              (equals_value_clause
                (with_expression
                  (identifier)
                  (with_initializer_expression
                    (simple_assignment_expression
                      (identifier)
                      (string_literal
                        (string_literal_fragment)))))))))))))

================================================================================
With expression using expressions
================================================================================

void A() {
  var friend = GetAFriend() with {
      ForeName = RandomFirstName(),
      LastName = RandomLastName()
  };
}

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_function_statement
      type: (predefined_type)
      name: (identifier)
      parameters: (parameter_list)
      body: (block
        (local_declaration_statement
          (variable_declaration
            type: (implicit_type)
            (variable_declarator
              name: (identifier)
              (equals_value_clause
                (with_expression
                  (invocation_expression
                    function: (identifier)
                    arguments: (argument_list))
                  (with_initializer_expression
                    (simple_assignment_expression
                      (identifier)
                      (invocation_expression
                        function: (identifier)
                        arguments: (argument_list)))
                    (simple_assignment_expression
                      (identifier)
                      (invocation_expression
                        function: (identifier)
                        arguments: (argument_list)))))))))))))

================================================================================
Precedence between with and cast
================================================================================

var x = (Point) p1 with {X = 3};

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_declaration_statement
      (variable_declaration
        type: (implicit_type)
        (variable_declarator
          name: (identifier)
          (equals_value_clause
            (with_expression
              (cast_expression
                type: (identifier)
                value: (identifier))
              (with_initializer_expression
                (simple_assignment_expression
                  (identifier)
                  (integer_literal))))))))))

================================================================================
Precedence between with and switch
================================================================================

var x = p1 with {X = 3} switch { _ => 3 };

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_declaration_statement
      (variable_declaration
        type: (implicit_type)
        (variable_declarator
          name: (identifier)
          (equals_value_clause
            (switch_expression
              (with_expression
                (identifier)
                (with_initializer_expression
                  (simple_assignment_expression
                    (identifier)
                    (integer_literal))))
              (switch_expression_arm
                (discard)
                (integer_literal)))))))))

================================================================================
Precedence between with and equals
================================================================================

var x = p1 with {X = 3} == p1 with {X = 4};

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_declaration_statement
      (variable_declaration
        type: (implicit_type)
        (variable_declarator
          name: (identifier)
          (equals_value_clause
            (binary_expression
              left: (with_expression
                (identifier)
                (with_initializer_expression
                  (simple_assignment_expression
                    (identifier)
                    (integer_literal))))
              right: (with_expression
                (identifier)
                (with_initializer_expression
                  (simple_assignment_expression
                    (identifier)
                    (integer_literal)))))))))))

================================================================================
Associativity of with expression
================================================================================

var x = p1 with {X = 3} with {X = 4} with {X = 5};

--------------------------------------------------------------------------------

(compilation_unit
  (global_statement
    (local_declaration_statement
      (variable_declaration
        type: (implicit_type)
        (variable_declarator
          name: (identifier)
          (equals_value_clause
            (with_expression
              (with_expression
                (with_expression
                  (identifier)
                  (with_initializer_expression
                    (simple_assignment_expression
                      (identifier)
                      (integer_literal))))
                (with_initializer_expression
                  (simple_assignment_expression
                    (identifier)
                    (integer_literal))))
              (with_initializer_expression
                (simple_assignment_expression
                  (identifier)
                  (integer_literal))))))))))
