=====================================
Global empty class
=====================================

public class F {}

---

(compilation_unit
  (class_declaration
    (modifier)
    name: (identifier)
    body: (declaration_list)))

=====================================
Class base is dynamic
=====================================

public class F : dynamic { }

---

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

=====================================
Class base is object with interfaces
=====================================

public class F : object, IAlpha, IOmega { }

---

(compilation_unit
  (class_declaration
    (modifier)
    name: (identifier)
    bases: (base_list
      (predefined_type)
      (identifier)
      (identifier))
    body: (declaration_list)))

=====================================
Partial class
=====================================

public partial class F {}

---

(compilation_unit
 (class_declaration
   (modifier) (modifier)
   (identifier)
   (declaration_list)))

=====================================
Class with a single type parameter
=====================================

class F<T> {}

---

(compilation_unit
  (class_declaration
    (identifier)
     (type_parameter_list (type_parameter (identifier)))
     (declaration_list)))

=====================================
Class with multiple type parameters
=====================================

internal class F<T1, T2> {}

---

(compilation_unit
 (class_declaration
   (modifier)
   (identifier)
    (type_parameter_list
      (type_parameter (identifier))
      (type_parameter (identifier)))
    (declaration_list)))

=====================================
Class with co-variant and contra-variant type parameters
=====================================

internal class F<in T1, out T2> {}

---

(compilation_unit
 (class_declaration
   (modifier)
   (identifier)
    (type_parameter_list
      (type_parameter (identifier))
      (type_parameter (identifier)))
    (declaration_list)))

=====================================
Class with a type parameter struct constraint
=====================================

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

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier) (type_parameter_constraint))
    (declaration_list)))

=====================================
Class with a type parameter unmanaged constraint
=====================================

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

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier) (type_parameter_constraint))
    (declaration_list)))

=====================================
Class with a type parameter class constraint
=====================================

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

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier) (type_parameter_constraint))
    (declaration_list)))

=====================================
Class with a type parameter and nullable constraints
=====================================

public class F<T> where T:class?, notnull, Mine? {}

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause (identifier)
      (type_parameter_constraint)
      (type_parameter_constraint)
      (type_parameter_constraint (type_constraint (nullable_type (identifier)))))
    (declaration_list)))

=====================================
Class with type parameter new constraint
=====================================

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

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier)
      (type_parameter_constraint (constructor_constraint)))
    (declaration_list)))

=====================================
Class with type parameter identifier constraint
=====================================

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

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier)
      (type_parameter_constraint (type_constraint (identifier))))
    (declaration_list)))

=====================================
Class with type parameter identifier and new constraints
=====================================

public class F<T> where T: I, new() {}

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier)
      (type_parameter_constraint
        (type_constraint (identifier)))
      (type_parameter_constraint (constructor_constraint)))
    (declaration_list)))

=====================================
Class with multiple type parameter constraints
=====================================

private class F<T1,T2> where T1 : I1, I2, new() where T2 : I2 { }

---

(compilation_unit
  (class_declaration
    (modifier)
    (identifier)
    (type_parameter_list
      (type_parameter (identifier))
      (type_parameter (identifier)))
    (type_parameter_constraints_clause
      (identifier)
      (type_parameter_constraint (type_constraint (identifier)))
      (type_parameter_constraint (type_constraint (identifier)))
      (type_parameter_constraint (constructor_constraint)))
    (type_parameter_constraints_clause
      (identifier)
      (type_parameter_constraint (type_constraint (identifier))))
    (declaration_list)))

=====================================
Class with public constructor
=====================================

class Foo {
  public Foo() {}
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (constructor_declaration
        (modifier)
        (identifier)
        (parameter_list)
        (block)))))

=====================================
Class with expression bodied constructor
=====================================

class Foo {
  public Foo(string name) => Name = name;
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (constructor_declaration
        (modifier)
        (identifier)
        (parameter_list (parameter (predefined_type) (identifier)))
        (arrow_expression_clause
          (assignment_expression (identifier) (assignment_operator) (identifier)))))))

=====================================
Class with static constructor
=====================================

class Foo {
  static Foo() {}
  static extern Foo() {}
  extern static Foo() {}
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (constructor_declaration
        (modifier)
        (identifier)
        (parameter_list)
        (block))
      (constructor_declaration
        (modifier) (modifier)
        (identifier)
        (parameter_list)
        (block))
      (constructor_declaration
        (modifier) (modifier)
        (identifier)
        (parameter_list)
        (block)))))

=====================================
Class with extern destructor
=====================================

class Foo {
  extern ~Foo() {}
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (destructor_declaration
        (identifier)
        (parameter_list)
        (block)))))

=====================================
Class with expression bodied destructor
=====================================

class Foo {
  ~Foo() => DoSomething();
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (destructor_declaration
        (identifier)
        (parameter_list)
        (arrow_expression_clause
          (invocation_expression
            (identifier)
            (argument_list)))))))

=====================================
Class with constants
=====================================

class Foo {
  private const int a = 1;
  const string b = $"hello";
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (field_declaration
        (modifier) (modifier)
        (variable_declaration
          (predefined_type)
          (variable_declarator
            (identifier)
            (equals_value_clause
              (integer_literal)))))
      (field_declaration
        (modifier)
        (variable_declaration
          (predefined_type)
          (variable_declarator
            (identifier)
            (equals_value_clause
              (interpolated_string_expression
                (interpolated_string_text)))))))))

=====================================
Class with indexer
=====================================

class Foo {
  public bool this[int index] {
    get { return a; }
    set { a = value; }
  }
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (indexer_declaration
        (modifier)
        (predefined_type)
        (bracketed_parameter_list (parameter (predefined_type) (identifier)))
        (accessor_list
          (accessor_declaration
            (block (return_statement (identifier))))
          (accessor_declaration
            (block (expression_statement (assignment_expression (identifier) (assignment_operator) (identifier))))))))))

=====================================
Class with expression bodied indexer
=====================================

class Foo {
  public bool this[int index] => a[index];
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (indexer_declaration
        (modifier)
        (predefined_type)
        (bracketed_parameter_list (parameter (predefined_type) (identifier)))
        (arrow_expression_clause
          (element_access_expression (identifier)
            (bracketed_argument_list (argument (identifier)))))))))

=====================================
Class with expression bodied indexer accessors
=====================================

class Foo {
    public string this[int index]
    {
        get => a[index];
        set => a[index] = value;
    }
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (indexer_declaration
        (modifier)
        (predefined_type)
        (bracketed_parameter_list (parameter (predefined_type) (identifier)))
        (accessor_list
          (accessor_declaration
            (arrow_expression_clause
              (element_access_expression (identifier)
                (bracketed_argument_list (argument (identifier))))))
          (accessor_declaration
            (arrow_expression_clause
              (assignment_expression
                (element_access_expression (identifier)
                  (bracketed_argument_list (argument (identifier))))
                  (assignment_operator) (identifier)))))))))


=====================================
Class with varargs indexer
=====================================

class A {
    public int this[params string[] arguments] {
        get { return 1; }
    }
}

---

(compilation_unit
  (class_declaration
    (identifier)
    (declaration_list
      (indexer_declaration
        (modifier)
        (predefined_type)
          (bracketed_parameter_list
            (array_type (predefined_type) (array_rank_specifier)) (identifier))
            (accessor_list
              (accessor_declaration
                (block
                  (return_statement (integer_literal)))))))))

=================================
Method with qualified return type
=================================

class A {
  B.C d() {
    return null;
  }
}

---

(compilation_unit
  (class_declaration
    name: (identifier)
    body: (declaration_list
      (method_declaration
        type: (qualified_name (identifier) (identifier))
        name: (identifier)
        parameters: (parameter_list)
        body: (block
          (return_statement (null_literal)))))))

=================================
Class and methods with Unicode identifiers
=================================

class Ωµ {
  B.C d() {
    return null;
  }
}

---

(compilation_unit
  (class_declaration
    name: (identifier)
    body: (declaration_list
      (method_declaration
        type: (qualified_name (identifier) (identifier))
        name: (identifier)
        parameters: (parameter_list)
        body: (block
          (return_statement (null_literal)))))))
